oce_mbox.c revision 258941
1231437Sluigi/*-
2252869Sdelphij * Copyright (C) 2013 Emulex
3231437Sluigi * All rights reserved.
4231437Sluigi *
5231437Sluigi * Redistribution and use in source and binary forms, with or without
6231437Sluigi * modification, are permitted provided that the following conditions are met:
7231437Sluigi *
8231437Sluigi * 1. Redistributions of source code must retain the above copyright notice,
9231437Sluigi *    this list of conditions and the following disclaimer.
10231437Sluigi *
11231437Sluigi * 2. Redistributions in binary form must reproduce the above copyright
12231437Sluigi *    notice, this list of conditions and the following disclaimer in the
13231437Sluigi *    documentation and/or other materials provided with the distribution.
14231437Sluigi *
15231437Sluigi * 3. Neither the name of the Emulex Corporation nor the names of its
16231437Sluigi *    contributors may be used to endorse or promote products derived from
17231437Sluigi *    this software without specific prior written permission.
18231437Sluigi *
19231437Sluigi * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20231437Sluigi * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21231437Sluigi * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22231437Sluigi * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23231437Sluigi * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24231437Sluigi * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25231437Sluigi * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26231437Sluigi * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27231437Sluigi * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28231437Sluigi * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29231437Sluigi * POSSIBILITY OF SUCH DAMAGE.
30231437Sluigi *
31231437Sluigi * Contact Information:
32231437Sluigi * freebsd-drivers@emulex.com
33231437Sluigi *
34231437Sluigi * Emulex
35231437Sluigi * 3333 Susan Street
36231437Sluigi * Costa Mesa, CA 92626
37231437Sluigi */
38231437Sluigi
39231437Sluigi/* $FreeBSD: head/sys/dev/oce/oce_mbox.c 258941 2013-12-04 20:24:18Z delphij $ */
40231437Sluigi
41231437Sluigi#include "oce_if.h"
42247880Sdelphijextern uint32_t sfp_vpd_dump_buffer[TRANSCEIVER_DATA_NUM_ELE];
43231437Sluigi
44231437Sluigi/**
45231437Sluigi * @brief Reset (firmware) common function
46231437Sluigi * @param sc		software handle to the device
47231437Sluigi * @returns		0 on success, ETIMEDOUT on failure
48231437Sluigi */
49231437Sluigiint
50231437Sluigioce_reset_fun(POCE_SOFTC sc)
51231437Sluigi{
52231437Sluigi	struct oce_mbx *mbx;
53231437Sluigi	struct oce_bmbx *mb;
54231437Sluigi	struct ioctl_common_function_reset *fwcmd;
55231437Sluigi	int rc = 0;
56231437Sluigi
57231437Sluigi	if (sc->flags & OCE_FLAGS_FUNCRESET_RQD) {
58231437Sluigi		mb = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
59231437Sluigi		mbx = &mb->mbx;
60231437Sluigi		bzero(mbx, sizeof(struct oce_mbx));
61231437Sluigi
62231437Sluigi		fwcmd = (struct ioctl_common_function_reset *)&mbx->payload;
63231437Sluigi		mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
64231437Sluigi					MBX_SUBSYSTEM_COMMON,
65231437Sluigi					OPCODE_COMMON_FUNCTION_RESET,
66231437Sluigi					10,	/* MBX_TIMEOUT_SEC */
67231437Sluigi					sizeof(struct
68231437Sluigi					    ioctl_common_function_reset),
69231437Sluigi					OCE_MBX_VER_V0);
70231437Sluigi
71231437Sluigi		mbx->u0.s.embedded = 1;
72231437Sluigi		mbx->payload_length =
73231437Sluigi		    sizeof(struct ioctl_common_function_reset);
74231437Sluigi
75231437Sluigi		rc = oce_mbox_dispatch(sc, 2);
76231437Sluigi	}
77231437Sluigi
78231437Sluigi	return rc;
79231437Sluigi}
80231437Sluigi
81231437Sluigi
82231437Sluigi/**
83231437Sluigi * @brief  		This funtions tells firmware we are
84231437Sluigi *			done with commands.
85231437Sluigi * @param sc            software handle to the device
86231437Sluigi * @returns             0 on success, ETIMEDOUT on failure
87231437Sluigi */
88231437Sluigiint
89231437Sluigioce_fw_clean(POCE_SOFTC sc)
90231437Sluigi{
91231437Sluigi	struct oce_bmbx *mbx;
92231437Sluigi	uint8_t *ptr;
93231437Sluigi	int ret = 0;
94231437Sluigi
95231437Sluigi	mbx = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
96231437Sluigi	ptr = (uint8_t *) &mbx->mbx;
97231437Sluigi
98231437Sluigi	/* Endian Signature */
99231437Sluigi	*ptr++ = 0xff;
100231437Sluigi	*ptr++ = 0xaa;
101231437Sluigi	*ptr++ = 0xbb;
102231437Sluigi	*ptr++ = 0xff;
103231437Sluigi	*ptr++ = 0xff;
104231437Sluigi	*ptr++ = 0xcc;
105231437Sluigi	*ptr++ = 0xdd;
106231437Sluigi	*ptr = 0xff;
107231437Sluigi
108231437Sluigi	ret = oce_mbox_dispatch(sc, 2);
109231437Sluigi
110231437Sluigi	return ret;
111231437Sluigi}
112231437Sluigi
113231437Sluigi
114231437Sluigi/**
115231437Sluigi * @brief Mailbox wait
116231437Sluigi * @param sc		software handle to the device
117231437Sluigi * @param tmo_sec	timeout in seconds
118231437Sluigi */
119231437Sluigistatic int
120231437Sluigioce_mbox_wait(POCE_SOFTC sc, uint32_t tmo_sec)
121231437Sluigi{
122231437Sluigi	tmo_sec *= 10000;
123231437Sluigi	pd_mpu_mbox_db_t mbox_db;
124231437Sluigi
125231437Sluigi	for (;;) {
126231437Sluigi		if (tmo_sec != 0) {
127231437Sluigi			if (--tmo_sec == 0)
128231437Sluigi				break;
129231437Sluigi		}
130231437Sluigi
131231437Sluigi		mbox_db.dw0 = OCE_READ_REG32(sc, db, PD_MPU_MBOX_DB);
132231437Sluigi
133231437Sluigi		if (mbox_db.bits.ready)
134231437Sluigi			return 0;
135231437Sluigi
136231437Sluigi		DELAY(100);
137231437Sluigi	}
138231437Sluigi
139231437Sluigi	device_printf(sc->dev, "Mailbox timed out\n");
140231437Sluigi
141231437Sluigi	return ETIMEDOUT;
142231437Sluigi}
143231437Sluigi
144231437Sluigi
145231437Sluigi/**
146231437Sluigi * @brief Mailbox dispatch
147231437Sluigi * @param sc		software handle to the device
148231437Sluigi * @param tmo_sec	timeout in seconds
149231437Sluigi */
150231437Sluigiint
151231437Sluigioce_mbox_dispatch(POCE_SOFTC sc, uint32_t tmo_sec)
152231437Sluigi{
153231437Sluigi	pd_mpu_mbox_db_t mbox_db;
154231437Sluigi	uint32_t pa;
155231437Sluigi	int rc;
156231437Sluigi
157231437Sluigi	oce_dma_sync(&sc->bsmbx, BUS_DMASYNC_PREWRITE);
158231437Sluigi	pa = (uint32_t) ((uint64_t) sc->bsmbx.paddr >> 34);
159231437Sluigi	bzero(&mbox_db, sizeof(pd_mpu_mbox_db_t));
160231437Sluigi	mbox_db.bits.ready = 0;
161231437Sluigi	mbox_db.bits.hi = 1;
162231437Sluigi	mbox_db.bits.address = pa;
163231437Sluigi
164231437Sluigi	rc = oce_mbox_wait(sc, tmo_sec);
165231437Sluigi	if (rc == 0) {
166231437Sluigi		OCE_WRITE_REG32(sc, db, PD_MPU_MBOX_DB, mbox_db.dw0);
167231437Sluigi
168231437Sluigi		pa = (uint32_t) ((uint64_t) sc->bsmbx.paddr >> 4) & 0x3fffffff;
169231437Sluigi		mbox_db.bits.ready = 0;
170231437Sluigi		mbox_db.bits.hi = 0;
171231437Sluigi		mbox_db.bits.address = pa;
172231437Sluigi
173231437Sluigi		rc = oce_mbox_wait(sc, tmo_sec);
174231437Sluigi
175231437Sluigi		if (rc == 0) {
176231437Sluigi			OCE_WRITE_REG32(sc, db, PD_MPU_MBOX_DB, mbox_db.dw0);
177231437Sluigi
178231437Sluigi			rc = oce_mbox_wait(sc, tmo_sec);
179231437Sluigi
180231437Sluigi			oce_dma_sync(&sc->bsmbx, BUS_DMASYNC_POSTWRITE);
181231437Sluigi		}
182231437Sluigi	}
183231437Sluigi
184231437Sluigi	return rc;
185231437Sluigi}
186231437Sluigi
187231437Sluigi
188231437Sluigi
189231437Sluigi/**
190231437Sluigi * @brief 		Mailbox common request header initialization
191231437Sluigi * @param hdr		mailbox header
192231437Sluigi * @param dom		domain
193231437Sluigi * @param port		port
194231437Sluigi * @param subsys	subsystem
195231437Sluigi * @param opcode	opcode
196231437Sluigi * @param timeout	timeout
197231437Sluigi * @param pyld_len	payload length
198231437Sluigi */
199231437Sluigivoid
200231437Sluigimbx_common_req_hdr_init(struct mbx_hdr *hdr,
201231437Sluigi			uint8_t dom, uint8_t port,
202231437Sluigi			uint8_t subsys, uint8_t opcode,
203231437Sluigi			uint32_t timeout, uint32_t pyld_len,
204231437Sluigi			uint8_t version)
205231437Sluigi{
206231437Sluigi	hdr->u0.req.opcode = opcode;
207231437Sluigi	hdr->u0.req.subsystem = subsys;
208231437Sluigi	hdr->u0.req.port_number = port;
209231437Sluigi	hdr->u0.req.domain = dom;
210231437Sluigi
211231437Sluigi	hdr->u0.req.timeout = timeout;
212231437Sluigi	hdr->u0.req.request_length = pyld_len - sizeof(struct mbx_hdr);
213231437Sluigi	hdr->u0.req.version = version;
214231437Sluigi}
215231437Sluigi
216231437Sluigi
217231437Sluigi
218231437Sluigi/**
219231437Sluigi * @brief Function to initialize the hw with host endian information
220231437Sluigi * @param sc		software handle to the device
221231437Sluigi * @returns		0 on success, ETIMEDOUT on failure
222231437Sluigi */
223231437Sluigiint
224231437Sluigioce_mbox_init(POCE_SOFTC sc)
225231437Sluigi{
226231437Sluigi	struct oce_bmbx *mbx;
227231437Sluigi	uint8_t *ptr;
228231437Sluigi	int ret = 0;
229231437Sluigi
230231437Sluigi	if (sc->flags & OCE_FLAGS_MBOX_ENDIAN_RQD) {
231231437Sluigi		mbx = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
232231437Sluigi		ptr = (uint8_t *) &mbx->mbx;
233231437Sluigi
234231437Sluigi		/* Endian Signature */
235231437Sluigi		*ptr++ = 0xff;
236231437Sluigi		*ptr++ = 0x12;
237231437Sluigi		*ptr++ = 0x34;
238231437Sluigi		*ptr++ = 0xff;
239231437Sluigi		*ptr++ = 0xff;
240231437Sluigi		*ptr++ = 0x56;
241231437Sluigi		*ptr++ = 0x78;
242231437Sluigi		*ptr = 0xff;
243231437Sluigi
244231437Sluigi		ret = oce_mbox_dispatch(sc, 0);
245231437Sluigi	}
246231437Sluigi
247231437Sluigi	return ret;
248231437Sluigi}
249231437Sluigi
250231437Sluigi
251231437Sluigi/**
252231437Sluigi * @brief 		Function to get the firmware version
253231437Sluigi * @param sc		software handle to the device
254231437Sluigi * @returns		0 on success, EIO on failure
255231437Sluigi */
256231437Sluigiint
257231437Sluigioce_get_fw_version(POCE_SOFTC sc)
258231437Sluigi{
259231437Sluigi	struct oce_mbx mbx;
260231437Sluigi	struct mbx_get_common_fw_version *fwcmd;
261231437Sluigi	int ret = 0;
262231437Sluigi
263231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
264231437Sluigi
265231437Sluigi	fwcmd = (struct mbx_get_common_fw_version *)&mbx.payload;
266231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
267231437Sluigi				MBX_SUBSYSTEM_COMMON,
268231437Sluigi				OPCODE_COMMON_GET_FW_VERSION,
269231437Sluigi				MBX_TIMEOUT_SEC,
270231437Sluigi				sizeof(struct mbx_get_common_fw_version),
271231437Sluigi				OCE_MBX_VER_V0);
272231437Sluigi
273231437Sluigi	mbx.u0.s.embedded = 1;
274231437Sluigi	mbx.payload_length = sizeof(struct mbx_get_common_fw_version);
275231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
276231437Sluigi
277231437Sluigi	ret = oce_mbox_post(sc, &mbx, NULL);
278247880Sdelphij	if (!ret)
279247880Sdelphij                ret = fwcmd->hdr.u0.rsp.status;
280247880Sdelphij	if (ret) {
281257007Sdelphij		device_printf(sc->dev,
282257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
283257007Sdelphij			      __FUNCTION__, ret,
284257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
285247880Sdelphij		goto error;
286247880Sdelphij	}
287231437Sluigi
288231437Sluigi	bcopy(fwcmd->params.rsp.fw_ver_str, sc->fw_version, 32);
289247880Sdelphijerror:
290247880Sdelphij	return ret;
291231437Sluigi}
292231437Sluigi
293231437Sluigi
294231437Sluigi/**
295231879Sluigi * @brief	Firmware will send gracious notifications during
296231879Sluigi *		attach only after sending first mcc commnad. We
297231879Sluigi *		use MCC queue only for getting async and mailbox
298231879Sluigi *		for sending cmds. So to get gracious notifications
299231879Sluigi *		atleast send one dummy command on mcc.
300231879Sluigi */
301231879Sluigiint
302231879Sluigioce_first_mcc_cmd(POCE_SOFTC sc)
303231879Sluigi{
304231879Sluigi	struct oce_mbx *mbx;
305231879Sluigi	struct oce_mq *mq = sc->mq;
306231879Sluigi	struct mbx_get_common_fw_version *fwcmd;
307231879Sluigi	uint32_t reg_value;
308231879Sluigi
309231879Sluigi	mbx = RING_GET_PRODUCER_ITEM_VA(mq->ring, struct oce_mbx);
310231879Sluigi	bzero(mbx, sizeof(struct oce_mbx));
311231879Sluigi
312231879Sluigi	fwcmd = (struct mbx_get_common_fw_version *)&mbx->payload;
313231879Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
314231879Sluigi				MBX_SUBSYSTEM_COMMON,
315231879Sluigi				OPCODE_COMMON_GET_FW_VERSION,
316231879Sluigi				MBX_TIMEOUT_SEC,
317231879Sluigi				sizeof(struct mbx_get_common_fw_version),
318231879Sluigi				OCE_MBX_VER_V0);
319231879Sluigi	mbx->u0.s.embedded = 1;
320231879Sluigi	mbx->payload_length = sizeof(struct mbx_get_common_fw_version);
321231879Sluigi	bus_dmamap_sync(mq->ring->dma.tag, mq->ring->dma.map,
322231879Sluigi				BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
323231879Sluigi	RING_PUT(mq->ring, 1);
324231879Sluigi	reg_value = (1 << 16) | mq->mq_id;
325231879Sluigi	OCE_WRITE_REG32(sc, db, PD_MQ_DB, reg_value);
326231879Sluigi
327231879Sluigi	return 0;
328231879Sluigi}
329231879Sluigi
330231879Sluigi/**
331231437Sluigi * @brief		Function to post a MBX to the mbox
332231437Sluigi * @param sc		software handle to the device
333231437Sluigi * @param mbx 		pointer to the MBX to send
334231437Sluigi * @param mbxctx	pointer to the mbx context structure
335231437Sluigi * @returns		0 on success, error on failure
336231437Sluigi */
337231437Sluigiint
338231437Sluigioce_mbox_post(POCE_SOFTC sc, struct oce_mbx *mbx, struct oce_mbx_ctx *mbxctx)
339231437Sluigi{
340231437Sluigi	struct oce_mbx *mb_mbx = NULL;
341231437Sluigi	struct oce_mq_cqe *mb_cqe = NULL;
342231437Sluigi	struct oce_bmbx *mb = NULL;
343231437Sluigi	int rc = 0;
344231437Sluigi	uint32_t tmo = 0;
345231437Sluigi	uint32_t cstatus = 0;
346231437Sluigi	uint32_t xstatus = 0;
347231437Sluigi
348231437Sluigi	LOCK(&sc->bmbx_lock);
349231437Sluigi
350231437Sluigi	mb = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
351231437Sluigi	mb_mbx = &mb->mbx;
352231437Sluigi
353231437Sluigi	/* get the tmo */
354231437Sluigi	tmo = mbx->tag[0];
355231437Sluigi	mbx->tag[0] = 0;
356231437Sluigi
357231437Sluigi	/* copy mbx into mbox */
358231437Sluigi	bcopy(mbx, mb_mbx, sizeof(struct oce_mbx));
359231437Sluigi
360231437Sluigi	/* now dispatch */
361231437Sluigi	rc = oce_mbox_dispatch(sc, tmo);
362231437Sluigi	if (rc == 0) {
363231437Sluigi		/*
364231437Sluigi		 * the command completed successfully. Now get the
365231437Sluigi		 * completion queue entry
366231437Sluigi		 */
367231437Sluigi		mb_cqe = &mb->cqe;
368231437Sluigi		DW_SWAP(u32ptr(&mb_cqe->u0.dw[0]), sizeof(struct oce_mq_cqe));
369231437Sluigi
370231437Sluigi		/* copy mbox mbx back */
371231437Sluigi		bcopy(mb_mbx, mbx, sizeof(struct oce_mbx));
372231437Sluigi
373231437Sluigi		/* pick up the mailbox status */
374231437Sluigi		cstatus = mb_cqe->u0.s.completion_status;
375231437Sluigi		xstatus = mb_cqe->u0.s.extended_status;
376231437Sluigi
377231437Sluigi		/*
378231437Sluigi		 * store the mbx context in the cqe tag section so that
379231437Sluigi		 * the upper layer handling the cqe can associate the mbx
380231437Sluigi		 * with the response
381231437Sluigi		 */
382231437Sluigi		if (cstatus == 0 && mbxctx) {
383231437Sluigi			/* save context */
384231437Sluigi			mbxctx->mbx = mb_mbx;
385231437Sluigi			bcopy(&mbxctx, mb_cqe->u0.s.mq_tag,
386231437Sluigi				sizeof(struct oce_mbx_ctx *));
387231437Sluigi		}
388231437Sluigi	}
389231437Sluigi
390231437Sluigi	UNLOCK(&sc->bmbx_lock);
391231437Sluigi
392231437Sluigi	return rc;
393231437Sluigi}
394231437Sluigi
395231437Sluigi/**
396231437Sluigi * @brief Function to read the mac address associated with an interface
397231437Sluigi * @param sc		software handle to the device
398231437Sluigi * @param if_id 	interface id to read the address from
399231437Sluigi * @param perm 		set to 1 if reading the factory mac address.
400231437Sluigi *			In this case if_id is ignored
401231437Sluigi * @param type 		type of the mac address, whether network or storage
402231437Sluigi * @param[out] mac 	[OUTPUT] pointer to a buffer containing the
403231437Sluigi *			mac address when the command succeeds.
404231437Sluigi * @returns		0 on success, EIO on failure
405231437Sluigi */
406231437Sluigiint
407231437Sluigioce_read_mac_addr(POCE_SOFTC sc, uint32_t if_id,
408231437Sluigi		uint8_t perm, uint8_t type, struct mac_address_format *mac)
409231437Sluigi{
410231437Sluigi	struct oce_mbx mbx;
411231437Sluigi	struct mbx_query_common_iface_mac *fwcmd;
412231437Sluigi	int ret = 0;
413231437Sluigi
414231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
415231437Sluigi
416231437Sluigi	fwcmd = (struct mbx_query_common_iface_mac *)&mbx.payload;
417231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
418231437Sluigi				MBX_SUBSYSTEM_COMMON,
419231437Sluigi				OPCODE_COMMON_QUERY_IFACE_MAC,
420231437Sluigi				MBX_TIMEOUT_SEC,
421231437Sluigi				sizeof(struct mbx_query_common_iface_mac),
422231437Sluigi				OCE_MBX_VER_V0);
423231437Sluigi
424231437Sluigi	fwcmd->params.req.permanent = perm;
425231437Sluigi	if (!perm)
426231437Sluigi		fwcmd->params.req.if_id = (uint16_t) if_id;
427231437Sluigi	else
428231437Sluigi		fwcmd->params.req.if_id = 0;
429231437Sluigi
430231437Sluigi	fwcmd->params.req.type = type;
431231437Sluigi
432231437Sluigi	mbx.u0.s.embedded = 1;
433231437Sluigi	mbx.payload_length = sizeof(struct mbx_query_common_iface_mac);
434231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
435231437Sluigi
436231437Sluigi	ret = oce_mbox_post(sc, &mbx, NULL);
437247880Sdelphij	if (!ret)
438247880Sdelphij                ret = fwcmd->hdr.u0.rsp.status;
439247880Sdelphij	if (ret) {
440257007Sdelphij		device_printf(sc->dev,
441257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
442257007Sdelphij			      __FUNCTION__, ret,
443257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
444247880Sdelphij		goto error;
445247880Sdelphij	}
446231437Sluigi
447231437Sluigi	/* copy the mac addres in the output parameter */
448231437Sluigi	mac->size_of_struct = fwcmd->params.rsp.mac.size_of_struct;
449231437Sluigi	bcopy(&fwcmd->params.rsp.mac.mac_addr[0], &mac->mac_addr[0],
450231437Sluigi		mac->size_of_struct);
451247880Sdelphijerror:
452247880Sdelphij	return ret;
453231437Sluigi}
454231437Sluigi
455231437Sluigi/**
456231437Sluigi * @brief Function to query the fw attributes from the hw
457231437Sluigi * @param sc		software handle to the device
458231437Sluigi * @returns		0 on success, EIO on failure
459231437Sluigi */
460231437Sluigiint
461231437Sluigioce_get_fw_config(POCE_SOFTC sc)
462231437Sluigi{
463231437Sluigi	struct oce_mbx mbx;
464231437Sluigi	struct mbx_common_query_fw_config *fwcmd;
465231437Sluigi	int ret = 0;
466231437Sluigi
467231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
468231437Sluigi
469231437Sluigi	fwcmd = (struct mbx_common_query_fw_config *)&mbx.payload;
470231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
471231437Sluigi				MBX_SUBSYSTEM_COMMON,
472231437Sluigi				OPCODE_COMMON_QUERY_FIRMWARE_CONFIG,
473231437Sluigi				MBX_TIMEOUT_SEC,
474231437Sluigi				sizeof(struct mbx_common_query_fw_config),
475231437Sluigi				OCE_MBX_VER_V0);
476231437Sluigi
477231437Sluigi	mbx.u0.s.embedded = 1;
478231437Sluigi	mbx.payload_length = sizeof(struct mbx_common_query_fw_config);
479231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
480231437Sluigi
481231437Sluigi	ret = oce_mbox_post(sc, &mbx, NULL);
482247880Sdelphij	if (!ret)
483247880Sdelphij                ret = fwcmd->hdr.u0.rsp.status;
484247880Sdelphij	if (ret) {
485257007Sdelphij		device_printf(sc->dev,
486257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
487257007Sdelphij			      __FUNCTION__, ret,
488257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
489247880Sdelphij		goto error;
490247880Sdelphij	}
491231437Sluigi
492231437Sluigi	DW_SWAP(u32ptr(fwcmd), sizeof(struct mbx_common_query_fw_config));
493231437Sluigi
494257007Sdelphij	sc->config_number = HOST_32(fwcmd->params.rsp.config_number);
495257007Sdelphij	sc->asic_revision = HOST_32(fwcmd->params.rsp.asic_revision);
496257007Sdelphij	sc->port_id	  = HOST_32(fwcmd->params.rsp.port_id);
497257007Sdelphij	sc->function_mode = HOST_32(fwcmd->params.rsp.function_mode);
498257007Sdelphij	sc->function_caps = HOST_32(fwcmd->params.rsp.function_caps);
499231437Sluigi
500231437Sluigi	if (fwcmd->params.rsp.ulp[0].ulp_mode & ULP_NIC_MODE) {
501257007Sdelphij		sc->max_tx_rings = HOST_32(fwcmd->params.rsp.ulp[0].nic_wq_tot);
502257007Sdelphij		sc->max_rx_rings = HOST_32(fwcmd->params.rsp.ulp[0].lro_rqid_tot);
503231437Sluigi	} else {
504257007Sdelphij		sc->max_tx_rings = HOST_32(fwcmd->params.rsp.ulp[1].nic_wq_tot);
505257007Sdelphij		sc->max_rx_rings = HOST_32(fwcmd->params.rsp.ulp[1].lro_rqid_tot);
506231437Sluigi	}
507231437Sluigi
508247880Sdelphijerror:
509247880Sdelphij	return ret;
510231437Sluigi
511231437Sluigi}
512231437Sluigi
513231437Sluigi/**
514231437Sluigi *
515231437Sluigi * @brief function to create a device interface
516231437Sluigi * @param sc		software handle to the device
517231437Sluigi * @param cap_flags	capability flags
518231437Sluigi * @param en_flags	enable capability flags
519231437Sluigi * @param vlan_tag	optional vlan tag to associate with the if
520231437Sluigi * @param mac_addr	pointer to a buffer containing the mac address
521231437Sluigi * @param[out] if_id	[OUTPUT] pointer to an integer to hold the ID of the
522231437Sluigi interface created
523231437Sluigi * @returns		0 on success, EIO on failure
524231437Sluigi */
525231437Sluigiint
526231437Sluigioce_if_create(POCE_SOFTC sc,
527231437Sluigi		uint32_t cap_flags,
528231437Sluigi		uint32_t en_flags,
529231437Sluigi		uint16_t vlan_tag,
530231437Sluigi		uint8_t *mac_addr,
531231437Sluigi		uint32_t *if_id)
532231437Sluigi{
533231437Sluigi	struct oce_mbx mbx;
534231437Sluigi	struct mbx_create_common_iface *fwcmd;
535231437Sluigi	int rc = 0;
536231437Sluigi
537231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
538231437Sluigi
539231437Sluigi	fwcmd = (struct mbx_create_common_iface *)&mbx.payload;
540231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
541231437Sluigi				MBX_SUBSYSTEM_COMMON,
542231437Sluigi				OPCODE_COMMON_CREATE_IFACE,
543231437Sluigi				MBX_TIMEOUT_SEC,
544231437Sluigi				sizeof(struct mbx_create_common_iface),
545231437Sluigi				OCE_MBX_VER_V0);
546231437Sluigi	DW_SWAP(u32ptr(&fwcmd->hdr), sizeof(struct mbx_hdr));
547231437Sluigi
548231437Sluigi	fwcmd->params.req.version = 0;
549231437Sluigi	fwcmd->params.req.cap_flags = LE_32(cap_flags);
550231437Sluigi	fwcmd->params.req.enable_flags = LE_32(en_flags);
551231437Sluigi	if (mac_addr != NULL) {
552231437Sluigi		bcopy(mac_addr, &fwcmd->params.req.mac_addr[0], 6);
553231437Sluigi		fwcmd->params.req.vlan_tag.u0.normal.vtag = LE_16(vlan_tag);
554231437Sluigi		fwcmd->params.req.mac_invalid = 0;
555231437Sluigi	} else {
556231437Sluigi		fwcmd->params.req.mac_invalid = 1;
557231437Sluigi	}
558231437Sluigi
559231437Sluigi	mbx.u0.s.embedded = 1;
560231437Sluigi	mbx.payload_length = sizeof(struct mbx_create_common_iface);
561231437Sluigi	DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ);
562231437Sluigi
563231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
564247880Sdelphij	if (!rc)
565247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
566247880Sdelphij	if (rc) {
567257007Sdelphij		device_printf(sc->dev,
568257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
569257007Sdelphij			      __FUNCTION__, rc,
570257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
571247880Sdelphij		goto error;
572247880Sdelphij	}
573231437Sluigi
574257007Sdelphij	*if_id = HOST_32(fwcmd->params.rsp.if_id);
575231437Sluigi
576231437Sluigi	if (mac_addr != NULL)
577257007Sdelphij		sc->pmac_id = HOST_32(fwcmd->params.rsp.pmac_id);
578247880Sdelphijerror:
579247880Sdelphij	return rc;
580231437Sluigi}
581231437Sluigi
582231437Sluigi/**
583231437Sluigi * @brief		Function to delete an interface
584231437Sluigi * @param sc 		software handle to the device
585231437Sluigi * @param if_id		ID of the interface to delete
586231437Sluigi * @returns		0 on success, EIO on failure
587231437Sluigi */
588231437Sluigiint
589231437Sluigioce_if_del(POCE_SOFTC sc, uint32_t if_id)
590231437Sluigi{
591231437Sluigi	struct oce_mbx mbx;
592231437Sluigi	struct mbx_destroy_common_iface *fwcmd;
593231437Sluigi	int rc = 0;
594231437Sluigi
595231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
596231437Sluigi
597231437Sluigi	fwcmd = (struct mbx_destroy_common_iface *)&mbx.payload;
598231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
599231437Sluigi				MBX_SUBSYSTEM_COMMON,
600231437Sluigi				OPCODE_COMMON_DESTROY_IFACE,
601231437Sluigi				MBX_TIMEOUT_SEC,
602231437Sluigi				sizeof(struct mbx_destroy_common_iface),
603231437Sluigi				OCE_MBX_VER_V0);
604231437Sluigi
605231437Sluigi	fwcmd->params.req.if_id = if_id;
606231437Sluigi
607231437Sluigi	mbx.u0.s.embedded = 1;
608231437Sluigi	mbx.payload_length = sizeof(struct mbx_destroy_common_iface);
609231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
610231437Sluigi
611231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
612247880Sdelphij	if (!rc)
613247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
614247880Sdelphij	if (rc)
615257007Sdelphij		device_printf(sc->dev,
616257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
617257007Sdelphij			      __FUNCTION__, rc,
618257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
619231437Sluigi	return rc;
620231437Sluigi}
621231437Sluigi
622231437Sluigi/**
623231437Sluigi * @brief Function to send the mbx command to configure vlan
624231437Sluigi * @param sc 		software handle to the device
625231437Sluigi * @param if_id 	interface identifier index
626231437Sluigi * @param vtag_arr	array of vlan tags
627231437Sluigi * @param vtag_cnt	number of elements in array
628231437Sluigi * @param untagged	boolean TRUE/FLASE
629231437Sluigi * @param enable_promisc flag to enable/disable VLAN promiscuous mode
630231437Sluigi * @returns		0 on success, EIO on failure
631231437Sluigi */
632231437Sluigiint
633231437Sluigioce_config_vlan(POCE_SOFTC sc,
634231437Sluigi		uint32_t if_id,
635231437Sluigi		struct normal_vlan *vtag_arr,
636231437Sluigi		uint8_t vtag_cnt, uint32_t untagged, uint32_t enable_promisc)
637231437Sluigi{
638231437Sluigi	struct oce_mbx mbx;
639231437Sluigi	struct mbx_common_config_vlan *fwcmd;
640257007Sdelphij	int rc = 0;
641231437Sluigi
642257007Sdelphij	if (sc->vlans_added > sc->max_vlans)
643257007Sdelphij		goto vlan_promisc;
644257007Sdelphij
645231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
646231437Sluigi	fwcmd = (struct mbx_common_config_vlan *)&mbx.payload;
647231437Sluigi
648231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
649231437Sluigi				MBX_SUBSYSTEM_COMMON,
650231437Sluigi				OPCODE_COMMON_CONFIG_IFACE_VLAN,
651231437Sluigi				MBX_TIMEOUT_SEC,
652231437Sluigi				sizeof(struct mbx_common_config_vlan),
653231437Sluigi				OCE_MBX_VER_V0);
654231437Sluigi
655231437Sluigi	fwcmd->params.req.if_id = (uint8_t) if_id;
656231437Sluigi	fwcmd->params.req.promisc = (uint8_t) enable_promisc;
657231437Sluigi	fwcmd->params.req.untagged = (uint8_t) untagged;
658231437Sluigi	fwcmd->params.req.num_vlans = vtag_cnt;
659231437Sluigi
660231437Sluigi	if (!enable_promisc) {
661231437Sluigi		bcopy(vtag_arr, fwcmd->params.req.tags.normal_vlans,
662231437Sluigi			vtag_cnt * sizeof(struct normal_vlan));
663231437Sluigi	}
664231437Sluigi	mbx.u0.s.embedded = 1;
665231437Sluigi	mbx.payload_length = sizeof(struct mbx_common_config_vlan);
666231437Sluigi	DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + mbx.payload_length));
667231437Sluigi
668231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
669247880Sdelphij	if (!rc)
670247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
671247880Sdelphij	if (rc)
672257007Sdelphij		device_printf(sc->dev,
673257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
674257007Sdelphij			      __FUNCTION__, rc,
675257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
676231437Sluigi
677257007Sdelphij	goto done;
678257007Sdelphij
679257007Sdelphijvlan_promisc:
680257007Sdelphij	/* Enable Vlan Promis */
681257007Sdelphij	oce_rxf_set_promiscuous(sc, (1 << 1));
682257007Sdelphij	device_printf(sc->dev,"Enabling Vlan Promisc Mode\n");
683257007Sdelphijdone:
684257007Sdelphij	return rc;
685257007Sdelphij
686231437Sluigi}
687231437Sluigi
688231437Sluigi/**
689231437Sluigi * @brief Function to set flow control capability in the hardware
690231437Sluigi * @param sc 		software handle to the device
691231437Sluigi * @param flow_control	flow control flags to set
692231437Sluigi * @returns		0 on success, EIO on failure
693231437Sluigi */
694231437Sluigiint
695231437Sluigioce_set_flow_control(POCE_SOFTC sc, uint32_t flow_control)
696231437Sluigi{
697231437Sluigi	struct oce_mbx mbx;
698231437Sluigi	struct mbx_common_get_set_flow_control *fwcmd =
699231437Sluigi		(struct mbx_common_get_set_flow_control *)&mbx.payload;
700231437Sluigi	int rc;
701231437Sluigi
702231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
703231437Sluigi
704231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
705231437Sluigi				MBX_SUBSYSTEM_COMMON,
706231437Sluigi				OPCODE_COMMON_SET_FLOW_CONTROL,
707231437Sluigi				MBX_TIMEOUT_SEC,
708231437Sluigi				sizeof(struct mbx_common_get_set_flow_control),
709231437Sluigi				OCE_MBX_VER_V0);
710231437Sluigi
711231437Sluigi	if (flow_control & OCE_FC_TX)
712231437Sluigi		fwcmd->tx_flow_control = 1;
713231437Sluigi
714231437Sluigi	if (flow_control & OCE_FC_RX)
715231437Sluigi		fwcmd->rx_flow_control = 1;
716231437Sluigi
717231437Sluigi	mbx.u0.s.embedded = 1;
718231437Sluigi	mbx.payload_length = sizeof(struct mbx_common_get_set_flow_control);
719231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
720231437Sluigi
721231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
722247880Sdelphij	if (!rc)
723247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
724247880Sdelphij	if (rc)
725257007Sdelphij		device_printf(sc->dev,
726257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
727257007Sdelphij			      __FUNCTION__, rc,
728257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
729231437Sluigi	return rc;
730231437Sluigi}
731231437Sluigi
732231437Sluigi/**
733231437Sluigi * @brief Initialize the RSS CPU indirection table
734231437Sluigi *
735231437Sluigi * The table is used to choose the queue to place the incomming packets.
736231437Sluigi * Incomming packets are hashed.  The lowest bits in the hash result
737231437Sluigi * are used as the index into the CPU indirection table.
738231437Sluigi * Each entry in the table contains the RSS CPU-ID returned by the NIC
739231437Sluigi * create.  Based on the CPU ID, the receive completion is routed to
740231437Sluigi * the corresponding RSS CQs.  (Non-RSS packets are always completed
741231437Sluigi * on the default (0) CQ).
742231437Sluigi *
743231437Sluigi * @param sc 		software handle to the device
744231437Sluigi * @param *fwcmd	pointer to the rss mbox command
745231437Sluigi * @returns		none
746231437Sluigi */
747231437Sluigistatic int
748231437Sluigioce_rss_itbl_init(POCE_SOFTC sc, struct mbx_config_nic_rss *fwcmd)
749231437Sluigi{
750231437Sluigi	int i = 0, j = 0, rc = 0;
751231437Sluigi	uint8_t *tbl = fwcmd->params.req.cputable;
752252869Sdelphij	struct oce_rq *rq = NULL;
753231437Sluigi
754231437Sluigi
755252869Sdelphij	for (j = 0; j < INDIRECTION_TABLE_ENTRIES ; j += (sc->nrqs - 1)) {
756252869Sdelphij		for_all_rss_queues(sc, rq, i) {
757252869Sdelphij			if ((j + i) >= INDIRECTION_TABLE_ENTRIES)
758252869Sdelphij				break;
759252869Sdelphij			tbl[j + i] = rq->rss_cpuid;
760231437Sluigi		}
761231437Sluigi	}
762231437Sluigi	if (i == 0) {
763231437Sluigi		device_printf(sc->dev, "error: Invalid number of RSS RQ's\n");
764231437Sluigi		rc = ENXIO;
765231437Sluigi
766231437Sluigi	}
767231437Sluigi
768231437Sluigi	/* fill log2 value indicating the size of the CPU table */
769231437Sluigi	if (rc == 0)
770231437Sluigi		fwcmd->params.req.cpu_tbl_sz_log2 = LE_16(OCE_LOG2(i));
771231437Sluigi
772231437Sluigi	return rc;
773231437Sluigi}
774231437Sluigi
775231437Sluigi/**
776231437Sluigi * @brief Function to set flow control capability in the hardware
777231437Sluigi * @param sc 		software handle to the device
778231437Sluigi * @param if_id 	interface id to read the address from
779231437Sluigi * @param enable_rss	0=disable, RSS_ENABLE_xxx flags otherwise
780231437Sluigi * @returns		0 on success, EIO on failure
781231437Sluigi */
782231437Sluigiint
783231437Sluigioce_config_nic_rss(POCE_SOFTC sc, uint32_t if_id, uint16_t enable_rss)
784231437Sluigi{
785231437Sluigi	int rc;
786231437Sluigi	struct oce_mbx mbx;
787231437Sluigi	struct mbx_config_nic_rss *fwcmd =
788231437Sluigi				(struct mbx_config_nic_rss *)&mbx.payload;
789247880Sdelphij	int version;
790231437Sluigi
791231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
792231437Sluigi
793252869Sdelphij	if (IS_XE201(sc) || IS_SH(sc)) {
794247880Sdelphij		version = OCE_MBX_VER_V1;
795247880Sdelphij		fwcmd->params.req.enable_rss = RSS_ENABLE_UDP_IPV4 |
796247880Sdelphij					       RSS_ENABLE_UDP_IPV6;
797247880Sdelphij	} else
798247880Sdelphij		version = OCE_MBX_VER_V0;
799247880Sdelphij
800231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
801231437Sluigi				MBX_SUBSYSTEM_NIC,
802231437Sluigi				NIC_CONFIG_RSS,
803231437Sluigi				MBX_TIMEOUT_SEC,
804231437Sluigi				sizeof(struct mbx_config_nic_rss),
805247880Sdelphij				version);
806231437Sluigi	if (enable_rss)
807247880Sdelphij		fwcmd->params.req.enable_rss |= (RSS_ENABLE_IPV4 |
808247880Sdelphij					         RSS_ENABLE_TCP_IPV4 |
809247880Sdelphij						 RSS_ENABLE_IPV6 |
810247880Sdelphij						 RSS_ENABLE_TCP_IPV6);
811231437Sluigi	fwcmd->params.req.flush = OCE_FLUSH;
812231437Sluigi	fwcmd->params.req.if_id = LE_32(if_id);
813231437Sluigi
814231437Sluigi	srandom(arc4random());	/* random entropy seed */
815231437Sluigi	read_random(fwcmd->params.req.hash, sizeof(fwcmd->params.req.hash));
816231437Sluigi
817231437Sluigi	rc = oce_rss_itbl_init(sc, fwcmd);
818231437Sluigi	if (rc == 0) {
819231437Sluigi		mbx.u0.s.embedded = 1;
820231437Sluigi		mbx.payload_length = sizeof(struct mbx_config_nic_rss);
821231437Sluigi		DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
822231437Sluigi
823231437Sluigi		rc = oce_mbox_post(sc, &mbx, NULL);
824247880Sdelphij		if (!rc)
825247880Sdelphij                	rc = fwcmd->hdr.u0.rsp.status;
826247880Sdelphij		if (rc)
827257007Sdelphij		device_printf(sc->dev,
828257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
829257007Sdelphij			      __FUNCTION__, rc,
830257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
831231437Sluigi	}
832231437Sluigi	return rc;
833231437Sluigi}
834231437Sluigi
835231437Sluigi/**
836231437Sluigi * @brief 		RXF function to enable/disable device promiscuous mode
837231437Sluigi * @param sc		software handle to the device
838231437Sluigi * @param enable	enable/disable flag
839231437Sluigi * @returns		0 on success, EIO on failure
840231437Sluigi * @note
841231437Sluigi *	The NIC_CONFIG_PROMISCUOUS command deprecated for Lancer.
842231437Sluigi *	This function uses the COMMON_SET_IFACE_RX_FILTER command instead.
843231437Sluigi */
844231437Sluigiint
845257007Sdelphijoce_rxf_set_promiscuous(POCE_SOFTC sc, uint8_t enable)
846231437Sluigi{
847231437Sluigi	struct mbx_set_common_iface_rx_filter *fwcmd;
848231437Sluigi	int sz = sizeof(struct mbx_set_common_iface_rx_filter);
849231437Sluigi	iface_rx_filter_ctx_t *req;
850231437Sluigi	OCE_DMA_MEM sgl;
851231437Sluigi	int rc;
852231437Sluigi
853231437Sluigi	/* allocate mbx payload's dma scatter/gather memory */
854231437Sluigi	rc = oce_dma_alloc(sc, sz, &sgl, 0);
855231437Sluigi	if (rc)
856231437Sluigi		return rc;
857231437Sluigi
858231437Sluigi	fwcmd = OCE_DMAPTR(&sgl, struct mbx_set_common_iface_rx_filter);
859231437Sluigi
860231437Sluigi	req =  &fwcmd->params.req;
861231437Sluigi	req->iface_flags_mask = MBX_RX_IFACE_FLAGS_PROMISCUOUS |
862231437Sluigi				MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS;
863257007Sdelphij	/* Bit 0 Mac promisc, Bit 1 Vlan promisc */
864257007Sdelphij	if (enable & 0x01)
865257007Sdelphij		req->iface_flags = MBX_RX_IFACE_FLAGS_PROMISCUOUS;
866257007Sdelphij
867257007Sdelphij	if (enable & 0x02)
868257007Sdelphij		req->iface_flags = MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS;
869257007Sdelphij
870231437Sluigi	req->if_id = sc->if_id;
871231437Sluigi
872231437Sluigi	rc = oce_set_common_iface_rx_filter(sc, &sgl);
873231437Sluigi	oce_dma_free(sc, &sgl);
874231437Sluigi
875231437Sluigi	return rc;
876231437Sluigi}
877231437Sluigi
878231437Sluigi
879231437Sluigi/**
880231437Sluigi * @brief 			Function modify and select rx filter options
881231437Sluigi * @param sc			software handle to the device
882231437Sluigi * @param sgl			scatter/gather request/response
883231437Sluigi * @returns			0 on success, error code on failure
884231437Sluigi */
885231437Sluigiint
886231437Sluigioce_set_common_iface_rx_filter(POCE_SOFTC sc, POCE_DMA_MEM sgl)
887231437Sluigi{
888231437Sluigi	struct oce_mbx mbx;
889231437Sluigi	int mbx_sz = sizeof(struct mbx_set_common_iface_rx_filter);
890231437Sluigi	struct mbx_set_common_iface_rx_filter *fwcmd;
891231437Sluigi	int rc;
892231437Sluigi
893231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
894231437Sluigi	fwcmd = OCE_DMAPTR(sgl, struct mbx_set_common_iface_rx_filter);
895231437Sluigi
896231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
897231437Sluigi				MBX_SUBSYSTEM_COMMON,
898231437Sluigi				OPCODE_COMMON_SET_IFACE_RX_FILTER,
899231437Sluigi				MBX_TIMEOUT_SEC,
900231437Sluigi				mbx_sz,
901231437Sluigi				OCE_MBX_VER_V0);
902231437Sluigi
903231437Sluigi	oce_dma_sync(sgl, BUS_DMASYNC_PREWRITE);
904231437Sluigi	mbx.u0.s.embedded = 0;
905231437Sluigi	mbx.u0.s.sge_count = 1;
906231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(sgl->paddr);
907231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(sgl->paddr);
908231437Sluigi	mbx.payload.u0.u1.sgl[0].length = mbx_sz;
909231437Sluigi	mbx.payload_length = mbx_sz;
910231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
911231437Sluigi
912231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
913247880Sdelphij	if (!rc)
914247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
915247880Sdelphij	if (rc)
916257007Sdelphij		device_printf(sc->dev,
917257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
918257007Sdelphij			      __FUNCTION__, rc,
919257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
920257007Sdelphij	return rc;
921231437Sluigi}
922231437Sluigi
923231437Sluigi/**
924231437Sluigi * @brief Function to query the link status from the hardware
925231437Sluigi * @param sc 		software handle to the device
926231437Sluigi * @param[out] link	pointer to the structure returning link attributes
927231437Sluigi * @returns		0 on success, EIO on failure
928231437Sluigi */
929231437Sluigiint
930231437Sluigioce_get_link_status(POCE_SOFTC sc, struct link_status *link)
931231437Sluigi{
932231437Sluigi	struct oce_mbx mbx;
933231437Sluigi	struct mbx_query_common_link_config *fwcmd;
934247880Sdelphij	int rc = 0, version;
935231437Sluigi
936231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
937231437Sluigi
938258941Sdelphij	IS_BE2(sc) ? (version = OCE_MBX_VER_V0) : (version = OCE_MBX_VER_V1);
939247880Sdelphij
940231437Sluigi	fwcmd = (struct mbx_query_common_link_config *)&mbx.payload;
941231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
942231437Sluigi				MBX_SUBSYSTEM_COMMON,
943231437Sluigi				OPCODE_COMMON_QUERY_LINK_CONFIG,
944231437Sluigi				MBX_TIMEOUT_SEC,
945231437Sluigi				sizeof(struct mbx_query_common_link_config),
946247880Sdelphij				version);
947231437Sluigi
948231437Sluigi	mbx.u0.s.embedded = 1;
949231437Sluigi	mbx.payload_length = sizeof(struct mbx_query_common_link_config);
950231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
951231437Sluigi
952231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
953231437Sluigi
954247880Sdelphij	if (!rc)
955247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
956231437Sluigi	if (rc) {
957257007Sdelphij		device_printf(sc->dev,
958257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
959257007Sdelphij			      __FUNCTION__, rc,
960257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
961247880Sdelphij		goto error;
962231437Sluigi	}
963247880Sdelphij	/* interpret response */
964247880Sdelphij	bcopy(&fwcmd->params.rsp, link, sizeof(struct link_status));
965257007Sdelphij	link->logical_link_status = HOST_32(link->logical_link_status);
966257007Sdelphij	link->qos_link_speed = HOST_16(link->qos_link_speed);
967247880Sdelphijerror:
968231437Sluigi	return rc;
969231437Sluigi}
970231437Sluigi
971231437Sluigi
972231437Sluigi
973231437Sluigiint
974231437Sluigioce_mbox_get_nic_stats_v0(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem)
975231437Sluigi{
976231437Sluigi	struct oce_mbx mbx;
977231437Sluigi	struct mbx_get_nic_stats_v0 *fwcmd;
978231437Sluigi	int rc = 0;
979231437Sluigi
980231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
981231437Sluigi
982231437Sluigi	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_nic_stats_v0);
983231437Sluigi	bzero(fwcmd, sizeof(struct mbx_get_nic_stats_v0));
984231437Sluigi
985231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
986231437Sluigi				MBX_SUBSYSTEM_NIC,
987231437Sluigi				NIC_GET_STATS,
988231437Sluigi				MBX_TIMEOUT_SEC,
989231437Sluigi				sizeof(struct mbx_get_nic_stats_v0),
990231437Sluigi				OCE_MBX_VER_V0);
991231437Sluigi
992231437Sluigi	mbx.u0.s.embedded = 0;
993231437Sluigi	mbx.u0.s.sge_count = 1;
994231437Sluigi
995231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
996231437Sluigi
997231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
998231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
999231437Sluigi	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_nic_stats_v0);
1000231437Sluigi
1001231437Sluigi	mbx.payload_length = sizeof(struct mbx_get_nic_stats_v0);
1002231437Sluigi
1003231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1004231437Sluigi
1005231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1006231437Sluigi
1007231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
1008231437Sluigi
1009247880Sdelphij	if (!rc)
1010247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1011247880Sdelphij	if (rc)
1012257007Sdelphij		device_printf(sc->dev,
1013257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1014257007Sdelphij			      __FUNCTION__, rc,
1015257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1016231437Sluigi	return rc;
1017231437Sluigi}
1018231437Sluigi
1019231437Sluigi
1020231437Sluigi
1021231437Sluigi/**
1022231437Sluigi * @brief Function to get NIC statistics
1023231437Sluigi * @param sc 		software handle to the device
1024231437Sluigi * @param *stats	pointer to where to store statistics
1025231437Sluigi * @param reset_stats	resets statistics of set
1026231437Sluigi * @returns		0 on success, EIO on failure
1027231437Sluigi * @note		command depricated in Lancer
1028231437Sluigi */
1029231437Sluigiint
1030231437Sluigioce_mbox_get_nic_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem)
1031231437Sluigi{
1032231437Sluigi	struct oce_mbx mbx;
1033231437Sluigi	struct mbx_get_nic_stats *fwcmd;
1034231437Sluigi	int rc = 0;
1035231437Sluigi
1036231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1037231437Sluigi	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_nic_stats);
1038231437Sluigi	bzero(fwcmd, sizeof(struct mbx_get_nic_stats));
1039231437Sluigi
1040231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1041231437Sluigi				MBX_SUBSYSTEM_NIC,
1042231437Sluigi				NIC_GET_STATS,
1043231437Sluigi				MBX_TIMEOUT_SEC,
1044231437Sluigi				sizeof(struct mbx_get_nic_stats),
1045231437Sluigi				OCE_MBX_VER_V1);
1046231437Sluigi
1047231437Sluigi
1048231437Sluigi	mbx.u0.s.embedded = 0;  /* stats too large for embedded mbx rsp */
1049231437Sluigi	mbx.u0.s.sge_count = 1; /* using scatter gather instead */
1050231437Sluigi
1051231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
1052231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
1053231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
1054231437Sluigi	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_nic_stats);
1055231437Sluigi
1056231437Sluigi	mbx.payload_length = sizeof(struct mbx_get_nic_stats);
1057231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1058231437Sluigi
1059231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1060231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
1061247880Sdelphij	if (!rc)
1062247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1063247880Sdelphij	if (rc)
1064257007Sdelphij		device_printf(sc->dev,
1065257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1066257007Sdelphij			      __FUNCTION__, rc,
1067257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1068231437Sluigi	return rc;
1069231437Sluigi}
1070231437Sluigi
1071231437Sluigi
1072231437Sluigi/**
1073231437Sluigi * @brief Function to get pport (physical port) statistics
1074231437Sluigi * @param sc 		software handle to the device
1075231437Sluigi * @param *stats	pointer to where to store statistics
1076231437Sluigi * @param reset_stats	resets statistics of set
1077231437Sluigi * @returns		0 on success, EIO on failure
1078231437Sluigi */
1079231437Sluigiint
1080231437Sluigioce_mbox_get_pport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem,
1081231437Sluigi				uint32_t reset_stats)
1082231437Sluigi{
1083231437Sluigi	struct oce_mbx mbx;
1084231437Sluigi	struct mbx_get_pport_stats *fwcmd;
1085231437Sluigi	int rc = 0;
1086231437Sluigi
1087231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1088231437Sluigi	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_pport_stats);
1089231437Sluigi	bzero(fwcmd, sizeof(struct mbx_get_pport_stats));
1090231437Sluigi
1091231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1092231437Sluigi				MBX_SUBSYSTEM_NIC,
1093231437Sluigi				NIC_GET_PPORT_STATS,
1094231437Sluigi				MBX_TIMEOUT_SEC,
1095231437Sluigi				sizeof(struct mbx_get_pport_stats),
1096231437Sluigi				OCE_MBX_VER_V0);
1097231437Sluigi
1098231437Sluigi	fwcmd->params.req.reset_stats = reset_stats;
1099247880Sdelphij	fwcmd->params.req.port_number = sc->port_id;
1100231437Sluigi
1101231437Sluigi	mbx.u0.s.embedded = 0;	/* stats too large for embedded mbx rsp */
1102231437Sluigi	mbx.u0.s.sge_count = 1; /* using scatter gather instead */
1103231437Sluigi
1104231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
1105231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
1106231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
1107231437Sluigi	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_pport_stats);
1108231437Sluigi
1109231437Sluigi	mbx.payload_length = sizeof(struct mbx_get_pport_stats);
1110231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1111231437Sluigi
1112231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1113231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
1114231437Sluigi
1115247880Sdelphij	if (!rc)
1116247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1117247880Sdelphij	if (rc)
1118257007Sdelphij		device_printf(sc->dev,
1119257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1120257007Sdelphij			      __FUNCTION__, rc,
1121257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1122231437Sluigi	return rc;
1123231437Sluigi}
1124231437Sluigi
1125231437Sluigi
1126231437Sluigi/**
1127231437Sluigi * @brief Function to get vport (virtual port) statistics
1128231437Sluigi * @param sc 		software handle to the device
1129231437Sluigi * @param *stats	pointer to where to store statistics
1130231437Sluigi * @param reset_stats	resets statistics of set
1131231437Sluigi * @returns		0 on success, EIO on failure
1132231437Sluigi */
1133231437Sluigiint
1134231437Sluigioce_mbox_get_vport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem,
1135231437Sluigi				uint32_t req_size, uint32_t reset_stats)
1136231437Sluigi{
1137231437Sluigi	struct oce_mbx mbx;
1138231437Sluigi	struct mbx_get_vport_stats *fwcmd;
1139231437Sluigi	int rc = 0;
1140231437Sluigi
1141231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1142231437Sluigi
1143231437Sluigi	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_vport_stats);
1144231437Sluigi	bzero(fwcmd, sizeof(struct mbx_get_vport_stats));
1145231437Sluigi
1146231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1147231437Sluigi				MBX_SUBSYSTEM_NIC,
1148231437Sluigi				NIC_GET_VPORT_STATS,
1149231437Sluigi				MBX_TIMEOUT_SEC,
1150231437Sluigi				sizeof(struct mbx_get_vport_stats),
1151231437Sluigi				OCE_MBX_VER_V0);
1152231437Sluigi
1153231437Sluigi	fwcmd->params.req.reset_stats = reset_stats;
1154231437Sluigi	fwcmd->params.req.vport_number = sc->if_id;
1155231437Sluigi
1156231437Sluigi	mbx.u0.s.embedded = 0;	/* stats too large for embedded mbx rsp */
1157231437Sluigi	mbx.u0.s.sge_count = 1; /* using scatter gather instead */
1158231437Sluigi
1159231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
1160231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
1161231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
1162231437Sluigi	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_vport_stats);
1163231437Sluigi
1164231437Sluigi	mbx.payload_length = sizeof(struct mbx_get_vport_stats);
1165231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1166231437Sluigi
1167231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1168231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
1169231437Sluigi
1170247880Sdelphij	if (!rc)
1171247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1172247880Sdelphij	if (rc)
1173257007Sdelphij		device_printf(sc->dev,
1174257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1175257007Sdelphij			      __FUNCTION__, rc,
1176257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1177231437Sluigi	return rc;
1178231437Sluigi}
1179231437Sluigi
1180231437Sluigi
1181231437Sluigi/**
1182231437Sluigi * @brief               Function to update the muticast filter with
1183231437Sluigi *                      values in dma_mem
1184231437Sluigi * @param sc            software handle to the device
1185231437Sluigi * @param dma_mem       pointer to dma memory region
1186231437Sluigi * @returns             0 on success, EIO on failure
1187231437Sluigi */
1188231437Sluigiint
1189231437Sluigioce_update_multicast(POCE_SOFTC sc, POCE_DMA_MEM pdma_mem)
1190231437Sluigi{
1191231437Sluigi	struct oce_mbx mbx;
1192231437Sluigi	struct oce_mq_sge *sgl;
1193231437Sluigi	struct mbx_set_common_iface_multicast *req = NULL;
1194231437Sluigi	int rc = 0;
1195231437Sluigi
1196231437Sluigi	req = OCE_DMAPTR(pdma_mem, struct mbx_set_common_iface_multicast);
1197231437Sluigi	mbx_common_req_hdr_init(&req->hdr, 0, 0,
1198231437Sluigi				MBX_SUBSYSTEM_COMMON,
1199231437Sluigi				OPCODE_COMMON_SET_IFACE_MULTICAST,
1200231437Sluigi				MBX_TIMEOUT_SEC,
1201231437Sluigi				sizeof(struct mbx_set_common_iface_multicast),
1202231437Sluigi				OCE_MBX_VER_V0);
1203231437Sluigi
1204231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1205231437Sluigi
1206231437Sluigi	mbx.u0.s.embedded = 0; /*Non embeded*/
1207231437Sluigi	mbx.payload_length = sizeof(struct mbx_set_common_iface_multicast);
1208231437Sluigi	mbx.u0.s.sge_count = 1;
1209231437Sluigi	sgl = &mbx.payload.u0.u1.sgl[0];
1210231437Sluigi	sgl->pa_hi = htole32(upper_32_bits(pdma_mem->paddr));
1211231437Sluigi	sgl->pa_lo = htole32((pdma_mem->paddr) & 0xFFFFFFFF);
1212231437Sluigi	sgl->length = htole32(mbx.payload_length);
1213231437Sluigi
1214231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1215231437Sluigi
1216231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1217247880Sdelphij	if (!rc)
1218247880Sdelphij                rc = req->hdr.u0.rsp.status;
1219247880Sdelphij	if (rc)
1220257007Sdelphij		device_printf(sc->dev,
1221257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1222257007Sdelphij			      __FUNCTION__, rc,
1223257007Sdelphij			      req->hdr.u0.rsp.additional_status);
1224231437Sluigi	return rc;
1225231437Sluigi}
1226231437Sluigi
1227231437Sluigi
1228231437Sluigi/**
1229231437Sluigi * @brief               Function to send passthrough Ioctls
1230231437Sluigi * @param sc            software handle to the device
1231231437Sluigi * @param dma_mem       pointer to dma memory region
1232231437Sluigi * @param req_size      size of dma_mem
1233231437Sluigi * @returns             0 on success, EIO on failure
1234231437Sluigi */
1235231437Sluigiint
1236231437Sluigioce_pass_through_mbox(POCE_SOFTC sc, POCE_DMA_MEM dma_mem, uint32_t req_size)
1237231437Sluigi{
1238231437Sluigi	struct oce_mbx mbx;
1239231437Sluigi	struct oce_mq_sge *sgl;
1240231437Sluigi	int rc = 0;
1241231437Sluigi
1242231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1243231437Sluigi
1244231437Sluigi	mbx.u0.s.embedded  = 0; /*Non embeded*/
1245231437Sluigi	mbx.payload_length = req_size;
1246231437Sluigi	mbx.u0.s.sge_count = 1;
1247231437Sluigi	sgl = &mbx.payload.u0.u1.sgl[0];
1248231437Sluigi	sgl->pa_hi = htole32(upper_32_bits(dma_mem->paddr));
1249231437Sluigi	sgl->pa_lo = htole32((dma_mem->paddr) & 0xFFFFFFFF);
1250231437Sluigi	sgl->length = htole32(req_size);
1251231437Sluigi
1252231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1253231437Sluigi
1254231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1255231437Sluigi	return rc;
1256231437Sluigi}
1257231437Sluigi
1258231437Sluigi
1259231437Sluigiint
1260231437Sluigioce_mbox_macaddr_add(POCE_SOFTC sc, uint8_t *mac_addr,
1261231437Sluigi		 uint32_t if_id, uint32_t *pmac_id)
1262231437Sluigi{
1263231437Sluigi	struct oce_mbx mbx;
1264231437Sluigi	struct mbx_add_common_iface_mac *fwcmd;
1265231437Sluigi	int rc = 0;
1266231437Sluigi
1267231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1268231437Sluigi
1269231437Sluigi	fwcmd = (struct mbx_add_common_iface_mac *)&mbx.payload;
1270231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1271231437Sluigi				MBX_SUBSYSTEM_COMMON,
1272231437Sluigi				OPCODE_COMMON_ADD_IFACE_MAC,
1273231437Sluigi				MBX_TIMEOUT_SEC,
1274231437Sluigi				sizeof(struct mbx_add_common_iface_mac),
1275231437Sluigi				OCE_MBX_VER_V0);
1276231437Sluigi
1277231437Sluigi	fwcmd->params.req.if_id = (uint16_t) if_id;
1278231437Sluigi	bcopy(mac_addr, fwcmd->params.req.mac_address, 6);
1279231437Sluigi
1280231437Sluigi	mbx.u0.s.embedded = 1;
1281231437Sluigi	mbx.payload_length = sizeof(struct  mbx_add_common_iface_mac);
1282231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1283231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1284247880Sdelphij	if (!rc)
1285247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1286247880Sdelphij	if (rc) {
1287257007Sdelphij		device_printf(sc->dev,
1288257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1289257007Sdelphij			      __FUNCTION__, rc,
1290257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1291247880Sdelphij		goto error;
1292247880Sdelphij	}
1293231437Sluigi	*pmac_id = fwcmd->params.rsp.pmac_id;
1294247880Sdelphijerror:
1295231437Sluigi	return rc;
1296231437Sluigi}
1297231437Sluigi
1298231437Sluigi
1299231437Sluigiint
1300231437Sluigioce_mbox_macaddr_del(POCE_SOFTC sc, uint32_t if_id, uint32_t pmac_id)
1301231437Sluigi{
1302231437Sluigi	struct oce_mbx mbx;
1303231437Sluigi	struct mbx_del_common_iface_mac *fwcmd;
1304231437Sluigi	int rc = 0;
1305231437Sluigi
1306231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1307231437Sluigi
1308231437Sluigi	fwcmd = (struct mbx_del_common_iface_mac *)&mbx.payload;
1309231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1310231437Sluigi				MBX_SUBSYSTEM_COMMON,
1311231437Sluigi				OPCODE_COMMON_DEL_IFACE_MAC,
1312231437Sluigi				MBX_TIMEOUT_SEC,
1313231437Sluigi				sizeof(struct mbx_del_common_iface_mac),
1314231437Sluigi				OCE_MBX_VER_V0);
1315231437Sluigi
1316231437Sluigi	fwcmd->params.req.if_id = (uint16_t)if_id;
1317231437Sluigi	fwcmd->params.req.pmac_id = pmac_id;
1318231437Sluigi
1319231437Sluigi	mbx.u0.s.embedded = 1;
1320231437Sluigi	mbx.payload_length = sizeof(struct  mbx_del_common_iface_mac);
1321231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1322231437Sluigi
1323231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1324247880Sdelphij	if (!rc)
1325247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1326247880Sdelphij	if (rc)
1327257007Sdelphij		device_printf(sc->dev,
1328257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1329257007Sdelphij			      __FUNCTION__, rc,
1330257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1331231437Sluigi	return rc;
1332231437Sluigi}
1333231437Sluigi
1334231437Sluigi
1335231437Sluigi
1336231437Sluigiint
1337231437Sluigioce_mbox_check_native_mode(POCE_SOFTC sc)
1338231437Sluigi{
1339231437Sluigi	struct oce_mbx mbx;
1340231437Sluigi	struct mbx_common_set_function_cap *fwcmd;
1341231437Sluigi	int rc = 0;
1342231437Sluigi
1343231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1344231437Sluigi
1345231437Sluigi	fwcmd = (struct mbx_common_set_function_cap *)&mbx.payload;
1346231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1347231437Sluigi				MBX_SUBSYSTEM_COMMON,
1348231437Sluigi				OPCODE_COMMON_SET_FUNCTIONAL_CAPS,
1349231437Sluigi				MBX_TIMEOUT_SEC,
1350231437Sluigi				sizeof(struct mbx_common_set_function_cap),
1351231437Sluigi				OCE_MBX_VER_V0);
1352231437Sluigi
1353231437Sluigi	fwcmd->params.req.valid_capability_flags = CAP_SW_TIMESTAMPS |
1354231437Sluigi							CAP_BE3_NATIVE_ERX_API;
1355231437Sluigi
1356231437Sluigi	fwcmd->params.req.capability_flags = CAP_BE3_NATIVE_ERX_API;
1357231437Sluigi
1358231437Sluigi	mbx.u0.s.embedded = 1;
1359231437Sluigi	mbx.payload_length = sizeof(struct mbx_common_set_function_cap);
1360231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1361231437Sluigi
1362231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1363247880Sdelphij	if (!rc)
1364247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1365247880Sdelphij	if (rc) {
1366257007Sdelphij		device_printf(sc->dev,
1367257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1368257007Sdelphij			      __FUNCTION__, rc,
1369257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1370247880Sdelphij		goto error;
1371247880Sdelphij	}
1372257007Sdelphij	sc->be3_native = HOST_32(fwcmd->params.rsp.capability_flags)
1373231437Sluigi			& CAP_BE3_NATIVE_ERX_API;
1374231437Sluigi
1375247880Sdelphijerror:
1376231437Sluigi	return 0;
1377231437Sluigi}
1378231437Sluigi
1379231437Sluigi
1380231437Sluigi
1381231437Sluigiint
1382231437Sluigioce_mbox_cmd_set_loopback(POCE_SOFTC sc, uint8_t port_num,
1383231437Sluigi		uint8_t loopback_type, uint8_t enable)
1384231437Sluigi{
1385231437Sluigi	struct oce_mbx mbx;
1386231437Sluigi	struct mbx_lowlevel_set_loopback_mode *fwcmd;
1387231437Sluigi	int rc = 0;
1388231437Sluigi
1389231437Sluigi
1390231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1391231437Sluigi
1392231437Sluigi	fwcmd = (struct mbx_lowlevel_set_loopback_mode *)&mbx.payload;
1393231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1394231437Sluigi				MBX_SUBSYSTEM_LOWLEVEL,
1395231437Sluigi				OPCODE_LOWLEVEL_SET_LOOPBACK_MODE,
1396231437Sluigi				MBX_TIMEOUT_SEC,
1397231437Sluigi				sizeof(struct mbx_lowlevel_set_loopback_mode),
1398231437Sluigi				OCE_MBX_VER_V0);
1399231437Sluigi
1400231437Sluigi	fwcmd->params.req.src_port = port_num;
1401231437Sluigi	fwcmd->params.req.dest_port = port_num;
1402231437Sluigi	fwcmd->params.req.loopback_type = loopback_type;
1403231437Sluigi	fwcmd->params.req.loopback_state = enable;
1404231437Sluigi
1405231437Sluigi	mbx.u0.s.embedded = 1;
1406231437Sluigi	mbx.payload_length = sizeof(struct  mbx_lowlevel_set_loopback_mode);
1407231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1408231437Sluigi
1409231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1410247880Sdelphij	if (!rc)
1411247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1412247880Sdelphij	if (rc)
1413257007Sdelphij		device_printf(sc->dev,
1414257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1415257007Sdelphij			      __FUNCTION__, rc,
1416257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1417231437Sluigi
1418231437Sluigi	return rc;
1419231437Sluigi
1420231437Sluigi}
1421231437Sluigi
1422231437Sluigiint
1423231437Sluigioce_mbox_cmd_test_loopback(POCE_SOFTC sc, uint32_t port_num,
1424231437Sluigi	uint32_t loopback_type, uint32_t pkt_size, uint32_t num_pkts,
1425231437Sluigi	uint64_t pattern)
1426231437Sluigi{
1427231437Sluigi
1428231437Sluigi	struct oce_mbx mbx;
1429231437Sluigi	struct mbx_lowlevel_test_loopback_mode *fwcmd;
1430231437Sluigi	int rc = 0;
1431231437Sluigi
1432231437Sluigi
1433231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1434231437Sluigi
1435231437Sluigi	fwcmd = (struct mbx_lowlevel_test_loopback_mode *)&mbx.payload;
1436231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1437231437Sluigi				MBX_SUBSYSTEM_LOWLEVEL,
1438231437Sluigi				OPCODE_LOWLEVEL_TEST_LOOPBACK,
1439231437Sluigi				MBX_TIMEOUT_SEC,
1440231437Sluigi				sizeof(struct mbx_lowlevel_test_loopback_mode),
1441231437Sluigi				OCE_MBX_VER_V0);
1442231437Sluigi
1443231437Sluigi	fwcmd->params.req.pattern = pattern;
1444231437Sluigi	fwcmd->params.req.src_port = port_num;
1445231437Sluigi	fwcmd->params.req.dest_port = port_num;
1446231437Sluigi	fwcmd->params.req.pkt_size = pkt_size;
1447231437Sluigi	fwcmd->params.req.num_pkts = num_pkts;
1448231437Sluigi	fwcmd->params.req.loopback_type = loopback_type;
1449231437Sluigi
1450231437Sluigi	mbx.u0.s.embedded = 1;
1451231437Sluigi	mbx.payload_length = sizeof(struct  mbx_lowlevel_test_loopback_mode);
1452231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1453231437Sluigi
1454231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1455247880Sdelphij	if (!rc)
1456247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1457231437Sluigi	if (rc)
1458257007Sdelphij		device_printf(sc->dev,
1459257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1460257007Sdelphij			      __FUNCTION__, rc,
1461257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1462231437Sluigi
1463247880Sdelphij	return rc;
1464231437Sluigi}
1465231437Sluigi
1466231437Sluigiint
1467231437Sluigioce_mbox_write_flashrom(POCE_SOFTC sc, uint32_t optype,uint32_t opcode,
1468231437Sluigi				POCE_DMA_MEM pdma_mem, uint32_t num_bytes)
1469231437Sluigi{
1470231437Sluigi
1471231437Sluigi	struct oce_mbx mbx;
1472231437Sluigi	struct oce_mq_sge *sgl = NULL;
1473231437Sluigi	struct mbx_common_read_write_flashrom *fwcmd = NULL;
1474231437Sluigi	int rc = 0, payload_len = 0;
1475231437Sluigi
1476231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1477231437Sluigi	fwcmd = OCE_DMAPTR(pdma_mem, struct mbx_common_read_write_flashrom);
1478231437Sluigi	payload_len = sizeof(struct mbx_common_read_write_flashrom) + 32*1024;
1479231437Sluigi
1480231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1481231437Sluigi				MBX_SUBSYSTEM_COMMON,
1482231437Sluigi				OPCODE_COMMON_WRITE_FLASHROM,
1483231437Sluigi				LONG_TIMEOUT,
1484231437Sluigi				payload_len,
1485231437Sluigi				OCE_MBX_VER_V0);
1486231437Sluigi
1487257007Sdelphij	fwcmd->flash_op_type = LE_32(optype);
1488257007Sdelphij	fwcmd->flash_op_code = LE_32(opcode);
1489257007Sdelphij	fwcmd->data_buffer_size = LE_32(num_bytes);
1490231437Sluigi
1491231437Sluigi	mbx.u0.s.embedded  = 0; /*Non embeded*/
1492231437Sluigi	mbx.payload_length = payload_len;
1493231437Sluigi	mbx.u0.s.sge_count = 1;
1494231437Sluigi
1495231437Sluigi	sgl = &mbx.payload.u0.u1.sgl[0];
1496231437Sluigi	sgl->pa_hi = upper_32_bits(pdma_mem->paddr);
1497231437Sluigi	sgl->pa_lo = pdma_mem->paddr & 0xFFFFFFFF;
1498231437Sluigi	sgl->length = payload_len;
1499231437Sluigi
1500231437Sluigi	/* post the command */
1501231879Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1502247880Sdelphij	if (!rc)
1503247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1504247880Sdelphij	if (rc)
1505257007Sdelphij		device_printf(sc->dev,
1506257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1507257007Sdelphij			      __FUNCTION__, rc,
1508257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1509231437Sluigi
1510231437Sluigi	return rc;
1511231437Sluigi
1512231437Sluigi}
1513231437Sluigi
1514231437Sluigiint
1515231437Sluigioce_mbox_get_flashrom_crc(POCE_SOFTC sc, uint8_t *flash_crc,
1516231437Sluigi				uint32_t offset, uint32_t optype)
1517231437Sluigi{
1518231437Sluigi
1519231437Sluigi	int rc = 0, payload_len = 0;
1520231437Sluigi	struct oce_mbx mbx;
1521231437Sluigi	struct mbx_common_read_write_flashrom *fwcmd;
1522231437Sluigi
1523231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1524231437Sluigi
1525231437Sluigi	fwcmd = (struct mbx_common_read_write_flashrom *)&mbx.payload;
1526231437Sluigi
1527231437Sluigi	/* Firmware requires extra 4 bytes with this ioctl. Since there
1528231437Sluigi	   is enough room in the mbx payload it should be good enough
1529231437Sluigi	   Reference: Bug 14853
1530231437Sluigi	*/
1531231437Sluigi	payload_len = sizeof(struct mbx_common_read_write_flashrom) + 4;
1532231437Sluigi
1533231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1534231437Sluigi				MBX_SUBSYSTEM_COMMON,
1535231437Sluigi				OPCODE_COMMON_READ_FLASHROM,
1536231437Sluigi				MBX_TIMEOUT_SEC,
1537231437Sluigi				payload_len,
1538231437Sluigi				OCE_MBX_VER_V0);
1539231437Sluigi
1540231437Sluigi	fwcmd->flash_op_type = optype;
1541231437Sluigi	fwcmd->flash_op_code = FLASHROM_OPER_REPORT;
1542231437Sluigi	fwcmd->data_offset = offset;
1543231437Sluigi	fwcmd->data_buffer_size = 0x4;
1544231437Sluigi
1545231437Sluigi	mbx.u0.s.embedded  = 1;
1546231437Sluigi	mbx.payload_length = payload_len;
1547231437Sluigi
1548231437Sluigi	/* post the command */
1549231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1550247880Sdelphij	if (!rc)
1551247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1552231437Sluigi	if (rc) {
1553257007Sdelphij		device_printf(sc->dev,
1554257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1555257007Sdelphij			      __FUNCTION__, rc,
1556257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1557247880Sdelphij		goto error;
1558231437Sluigi	}
1559247880Sdelphij	bcopy(fwcmd->data_buffer, flash_crc, 4);
1560247880Sdelphijerror:
1561231437Sluigi	return rc;
1562231437Sluigi}
1563231437Sluigi
1564231437Sluigiint
1565231437Sluigioce_mbox_get_phy_info(POCE_SOFTC sc, struct oce_phy_info *phy_info)
1566231437Sluigi{
1567231437Sluigi
1568231437Sluigi	struct oce_mbx mbx;
1569231437Sluigi	struct mbx_common_phy_info *fwcmd;
1570231437Sluigi	int rc = 0;
1571231437Sluigi
1572231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1573231437Sluigi
1574231437Sluigi	fwcmd = (struct mbx_common_phy_info *)&mbx.payload;
1575231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1576231437Sluigi				MBX_SUBSYSTEM_COMMON,
1577231437Sluigi				OPCODE_COMMON_GET_PHY_CONFIG,
1578231437Sluigi				MBX_TIMEOUT_SEC,
1579231437Sluigi				sizeof(struct mbx_common_phy_info),
1580231437Sluigi				OCE_MBX_VER_V0);
1581231437Sluigi
1582231437Sluigi	mbx.u0.s.embedded = 1;
1583231437Sluigi	mbx.payload_length = sizeof(struct  mbx_common_phy_info);
1584231437Sluigi
1585231437Sluigi	/* now post the command */
1586231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1587247880Sdelphij	if (!rc)
1588247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1589231437Sluigi	if (rc) {
1590257007Sdelphij		device_printf(sc->dev,
1591257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1592257007Sdelphij			      __FUNCTION__, rc,
1593257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1594247880Sdelphij		goto error;
1595231437Sluigi	}
1596257007Sdelphij	phy_info->phy_type = HOST_16(fwcmd->params.rsp.phy_info.phy_type);
1597247880Sdelphij	phy_info->interface_type =
1598257007Sdelphij			HOST_16(fwcmd->params.rsp.phy_info.interface_type);
1599247880Sdelphij	phy_info->auto_speeds_supported =
1600257007Sdelphij		HOST_16(fwcmd->params.rsp.phy_info.auto_speeds_supported);
1601247880Sdelphij	phy_info->fixed_speeds_supported =
1602257007Sdelphij		HOST_16(fwcmd->params.rsp.phy_info.fixed_speeds_supported);
1603257007Sdelphij	phy_info->misc_params = HOST_32(fwcmd->params.rsp.phy_info.misc_params);
1604247880Sdelphijerror:
1605231437Sluigi	return rc;
1606231437Sluigi
1607231437Sluigi}
1608231437Sluigi
1609231437Sluigi
1610231437Sluigiint
1611231437Sluigioce_mbox_lancer_write_flashrom(POCE_SOFTC sc, uint32_t data_size,
1612231437Sluigi			uint32_t data_offset, POCE_DMA_MEM pdma_mem,
1613231437Sluigi			uint32_t *written_data, uint32_t *additional_status)
1614231437Sluigi{
1615231437Sluigi
1616231437Sluigi	struct oce_mbx mbx;
1617231437Sluigi	struct mbx_lancer_common_write_object *fwcmd = NULL;
1618231437Sluigi	int rc = 0, payload_len = 0;
1619231437Sluigi
1620231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1621231437Sluigi	payload_len = sizeof(struct mbx_lancer_common_write_object);
1622231437Sluigi
1623231437Sluigi	mbx.u0.s.embedded  = 1;/* Embedded */
1624231437Sluigi	mbx.payload_length = payload_len;
1625231437Sluigi	fwcmd = (struct mbx_lancer_common_write_object *)&mbx.payload;
1626231437Sluigi
1627231437Sluigi	/* initialize the ioctl header */
1628231437Sluigi	mbx_common_req_hdr_init(&fwcmd->params.req.hdr, 0, 0,
1629231437Sluigi				MBX_SUBSYSTEM_COMMON,
1630231437Sluigi				OPCODE_COMMON_WRITE_OBJECT,
1631231437Sluigi				LONG_TIMEOUT,
1632231437Sluigi				payload_len,
1633231437Sluigi				OCE_MBX_VER_V0);
1634231437Sluigi
1635231437Sluigi	fwcmd->params.req.write_length = data_size;
1636231437Sluigi	if (data_size == 0)
1637231437Sluigi		fwcmd->params.req.eof = 1;
1638231437Sluigi	else
1639231437Sluigi		fwcmd->params.req.eof = 0;
1640231437Sluigi
1641231437Sluigi	strcpy(fwcmd->params.req.object_name, "/prg");
1642231437Sluigi	fwcmd->params.req.descriptor_count = 1;
1643231437Sluigi	fwcmd->params.req.write_offset = data_offset;
1644231437Sluigi	fwcmd->params.req.buffer_length = data_size;
1645231437Sluigi	fwcmd->params.req.address_lower = pdma_mem->paddr & 0xFFFFFFFF;
1646231437Sluigi	fwcmd->params.req.address_upper = upper_32_bits(pdma_mem->paddr);
1647231437Sluigi
1648231437Sluigi	/* post the command */
1649231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1650247880Sdelphij	if (!rc)
1651247880Sdelphij                rc = fwcmd->params.rsp.status;
1652231437Sluigi	if (rc) {
1653257007Sdelphij		device_printf(sc->dev,
1654257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1655257007Sdelphij			      __FUNCTION__, rc,
1656257007Sdelphij			      fwcmd->params.rsp.additional_status);
1657247880Sdelphij		goto error;
1658231437Sluigi	}
1659257007Sdelphij	*written_data = HOST_32(fwcmd->params.rsp.actual_write_length);
1660247880Sdelphij	*additional_status = fwcmd->params.rsp.additional_status;
1661247880Sdelphijerror:
1662231437Sluigi	return rc;
1663231437Sluigi
1664231437Sluigi}
1665231437Sluigi
1666231437Sluigi
1667231437Sluigi
1668231437Sluigiint
1669231437Sluigioce_mbox_create_rq(struct oce_rq *rq)
1670231437Sluigi{
1671231437Sluigi
1672231437Sluigi	struct oce_mbx mbx;
1673231437Sluigi	struct mbx_create_nic_rq *fwcmd;
1674231437Sluigi	POCE_SOFTC sc = rq->parent;
1675231437Sluigi	int rc, num_pages = 0;
1676231437Sluigi
1677231437Sluigi	if (rq->qstate == QCREATED)
1678231437Sluigi		return 0;
1679231437Sluigi
1680231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1681231437Sluigi
1682231437Sluigi	fwcmd = (struct mbx_create_nic_rq *)&mbx.payload;
1683231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1684231437Sluigi				MBX_SUBSYSTEM_NIC,
1685231437Sluigi				NIC_CREATE_RQ, MBX_TIMEOUT_SEC,
1686231437Sluigi				sizeof(struct mbx_create_nic_rq),
1687231437Sluigi				OCE_MBX_VER_V0);
1688231437Sluigi
1689231437Sluigi	/* oce_page_list will also prepare pages */
1690231437Sluigi	num_pages = oce_page_list(rq->ring, &fwcmd->params.req.pages[0]);
1691231437Sluigi
1692231437Sluigi	if (IS_XE201(sc)) {
1693231437Sluigi		fwcmd->params.req.frag_size = rq->cfg.frag_size/2048;
1694231437Sluigi		fwcmd->params.req.page_size = 1;
1695231437Sluigi		fwcmd->hdr.u0.req.version = OCE_MBX_VER_V1;
1696231437Sluigi	} else
1697231437Sluigi		fwcmd->params.req.frag_size = OCE_LOG2(rq->cfg.frag_size);
1698231437Sluigi	fwcmd->params.req.num_pages = num_pages;
1699231437Sluigi	fwcmd->params.req.cq_id = rq->cq->cq_id;
1700231437Sluigi	fwcmd->params.req.if_id = sc->if_id;
1701231437Sluigi	fwcmd->params.req.max_frame_size = rq->cfg.mtu;
1702231437Sluigi	fwcmd->params.req.is_rss_queue = rq->cfg.is_rss_queue;
1703231437Sluigi
1704231437Sluigi	mbx.u0.s.embedded = 1;
1705231437Sluigi	mbx.payload_length = sizeof(struct mbx_create_nic_rq);
1706231437Sluigi
1707231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1708247880Sdelphij	if (!rc)
1709247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1710247880Sdelphij	if (rc) {
1711257007Sdelphij		device_printf(sc->dev,
1712257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1713257007Sdelphij			      __FUNCTION__, rc,
1714257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1715231437Sluigi		goto error;
1716247880Sdelphij	}
1717257007Sdelphij	rq->rq_id = HOST_16(fwcmd->params.rsp.rq_id);
1718231437Sluigi	rq->rss_cpuid = fwcmd->params.rsp.rss_cpuid;
1719231437Sluigierror:
1720231437Sluigi	return rc;
1721231437Sluigi
1722231437Sluigi}
1723231437Sluigi
1724231437Sluigi
1725231437Sluigi
1726231437Sluigiint
1727231437Sluigioce_mbox_create_wq(struct oce_wq *wq)
1728231437Sluigi{
1729231437Sluigi	struct oce_mbx mbx;
1730231437Sluigi	struct mbx_create_nic_wq *fwcmd;
1731231437Sluigi	POCE_SOFTC sc = wq->parent;
1732231437Sluigi	int rc = 0, version, num_pages;
1733231437Sluigi
1734231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1735231437Sluigi
1736231437Sluigi	fwcmd = (struct mbx_create_nic_wq *)&mbx.payload;
1737257007Sdelphij	if (IS_XE201(sc))
1738231437Sluigi		version = OCE_MBX_VER_V1;
1739257007Sdelphij	else if(IS_BE(sc))
1740252869Sdelphij		IS_PROFILE_SUPER_NIC(sc) ? (version = OCE_MBX_VER_V2)
1741252869Sdelphij					 : (version = OCE_MBX_VER_V0);
1742252869Sdelphij	else
1743252869Sdelphij		version = OCE_MBX_VER_V2;
1744231437Sluigi
1745257007Sdelphij	if (version > OCE_MBX_VER_V0)
1746257007Sdelphij		fwcmd->params.req.if_id = sc->if_id;
1747257007Sdelphij
1748231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1749231437Sluigi				MBX_SUBSYSTEM_NIC,
1750231437Sluigi				NIC_CREATE_WQ, MBX_TIMEOUT_SEC,
1751231437Sluigi				sizeof(struct mbx_create_nic_wq),
1752231437Sluigi				version);
1753231437Sluigi
1754231437Sluigi	num_pages = oce_page_list(wq->ring, &fwcmd->params.req.pages[0]);
1755231437Sluigi
1756231437Sluigi	fwcmd->params.req.nic_wq_type = wq->cfg.wq_type;
1757231437Sluigi	fwcmd->params.req.num_pages = num_pages;
1758231437Sluigi	fwcmd->params.req.wq_size = OCE_LOG2(wq->cfg.q_len) + 1;
1759231437Sluigi	fwcmd->params.req.cq_id = wq->cq->cq_id;
1760231437Sluigi	fwcmd->params.req.ulp_num = 1;
1761231437Sluigi
1762231437Sluigi	mbx.u0.s.embedded = 1;
1763231437Sluigi	mbx.payload_length = sizeof(struct mbx_create_nic_wq);
1764231437Sluigi
1765231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1766247880Sdelphij	if (!rc)
1767247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1768247880Sdelphij	if (rc) {
1769257007Sdelphij		device_printf(sc->dev,
1770257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1771257007Sdelphij			      __FUNCTION__, rc,
1772257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1773231437Sluigi		goto error;
1774247880Sdelphij	}
1775257007Sdelphij	wq->wq_id = HOST_16(fwcmd->params.rsp.wq_id);
1776252869Sdelphij	if (version == OCE_MBX_VER_V2)
1777257007Sdelphij		wq->db_offset = HOST_32(fwcmd->params.rsp.db_offset);
1778252869Sdelphij	else
1779252869Sdelphij		wq->db_offset = PD_TXULP_DB;
1780231437Sluigierror:
1781231437Sluigi	return rc;
1782231437Sluigi
1783231437Sluigi}
1784231437Sluigi
1785231437Sluigi
1786231437Sluigi
1787231437Sluigiint
1788231437Sluigioce_mbox_create_eq(struct oce_eq *eq)
1789231437Sluigi{
1790231437Sluigi	struct oce_mbx mbx;
1791231437Sluigi	struct mbx_create_common_eq *fwcmd;
1792231437Sluigi	POCE_SOFTC sc = eq->parent;
1793231437Sluigi	int rc = 0;
1794231437Sluigi	uint32_t num_pages;
1795231437Sluigi
1796231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1797231437Sluigi
1798231437Sluigi	fwcmd = (struct mbx_create_common_eq *)&mbx.payload;
1799231437Sluigi
1800231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1801231437Sluigi				MBX_SUBSYSTEM_COMMON,
1802231437Sluigi				OPCODE_COMMON_CREATE_EQ, MBX_TIMEOUT_SEC,
1803231437Sluigi				sizeof(struct mbx_create_common_eq),
1804231437Sluigi				OCE_MBX_VER_V0);
1805231437Sluigi
1806231437Sluigi	num_pages = oce_page_list(eq->ring, &fwcmd->params.req.pages[0]);
1807231437Sluigi	fwcmd->params.req.ctx.num_pages = num_pages;
1808231437Sluigi	fwcmd->params.req.ctx.valid = 1;
1809231437Sluigi	fwcmd->params.req.ctx.size = (eq->eq_cfg.item_size == 4) ? 0 : 1;
1810231437Sluigi	fwcmd->params.req.ctx.count = OCE_LOG2(eq->eq_cfg.q_len / 256);
1811231437Sluigi	fwcmd->params.req.ctx.armed = 0;
1812231437Sluigi	fwcmd->params.req.ctx.delay_mult = eq->eq_cfg.cur_eqd;
1813231437Sluigi
1814231437Sluigi
1815231437Sluigi	mbx.u0.s.embedded = 1;
1816231437Sluigi	mbx.payload_length = sizeof(struct mbx_create_common_eq);
1817231437Sluigi
1818231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1819247880Sdelphij	if (!rc)
1820247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1821247880Sdelphij	if (rc) {
1822257007Sdelphij		device_printf(sc->dev,
1823257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1824257007Sdelphij			      __FUNCTION__, rc,
1825257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1826231437Sluigi		goto error;
1827247880Sdelphij	}
1828257007Sdelphij	eq->eq_id = HOST_16(fwcmd->params.rsp.eq_id);
1829231437Sluigierror:
1830231437Sluigi	return rc;
1831231437Sluigi}
1832231437Sluigi
1833231437Sluigi
1834231437Sluigi
1835231437Sluigiint
1836231437Sluigioce_mbox_cq_create(struct oce_cq *cq, uint32_t ncoalesce, uint32_t is_eventable)
1837231437Sluigi{
1838231437Sluigi	struct oce_mbx mbx;
1839231437Sluigi	struct mbx_create_common_cq *fwcmd;
1840231437Sluigi	POCE_SOFTC sc = cq->parent;
1841231437Sluigi	uint8_t version;
1842231437Sluigi	oce_cq_ctx_t *ctx;
1843231437Sluigi	uint32_t num_pages, page_size;
1844231437Sluigi	int rc = 0;
1845231437Sluigi
1846231437Sluigi
1847231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1848231437Sluigi
1849231437Sluigi	fwcmd = (struct mbx_create_common_cq *)&mbx.payload;
1850231437Sluigi
1851231437Sluigi	if (IS_XE201(sc))
1852231437Sluigi		version = OCE_MBX_VER_V2;
1853231437Sluigi	else
1854231437Sluigi		version = OCE_MBX_VER_V0;
1855231437Sluigi
1856231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1857231437Sluigi				MBX_SUBSYSTEM_COMMON,
1858231437Sluigi				OPCODE_COMMON_CREATE_CQ,
1859231437Sluigi				MBX_TIMEOUT_SEC,
1860231437Sluigi				sizeof(struct mbx_create_common_cq),
1861231437Sluigi				version);
1862231437Sluigi
1863231437Sluigi	ctx = &fwcmd->params.req.cq_ctx;
1864231437Sluigi
1865231437Sluigi	num_pages = oce_page_list(cq->ring, &fwcmd->params.req.pages[0]);
1866231437Sluigi	page_size =  1;  /* 1 for 4K */
1867231437Sluigi
1868231437Sluigi	if (version == OCE_MBX_VER_V2) {
1869231437Sluigi		ctx->v2.num_pages = LE_16(num_pages);
1870231437Sluigi		ctx->v2.page_size = page_size;
1871231437Sluigi		ctx->v2.eventable = is_eventable;
1872231437Sluigi		ctx->v2.valid = 1;
1873231437Sluigi		ctx->v2.count = OCE_LOG2(cq->cq_cfg.q_len / 256);
1874231437Sluigi		ctx->v2.nodelay = cq->cq_cfg.nodelay;
1875231437Sluigi		ctx->v2.coalesce_wm = ncoalesce;
1876231437Sluigi		ctx->v2.armed = 0;
1877231437Sluigi		ctx->v2.eq_id = cq->eq->eq_id;
1878231437Sluigi		if (ctx->v2.count == 3) {
1879231437Sluigi			if (cq->cq_cfg.q_len > (4*1024)-1)
1880231437Sluigi				ctx->v2.cqe_count = (4*1024)-1;
1881231437Sluigi			else
1882231437Sluigi				ctx->v2.cqe_count = cq->cq_cfg.q_len;
1883231437Sluigi		}
1884231437Sluigi	} else {
1885231437Sluigi		ctx->v0.num_pages = LE_16(num_pages);
1886231437Sluigi		ctx->v0.eventable = is_eventable;
1887231437Sluigi		ctx->v0.valid = 1;
1888231437Sluigi		ctx->v0.count = OCE_LOG2(cq->cq_cfg.q_len / 256);
1889231437Sluigi		ctx->v0.nodelay = cq->cq_cfg.nodelay;
1890231437Sluigi		ctx->v0.coalesce_wm = ncoalesce;
1891231437Sluigi		ctx->v0.armed = 0;
1892231437Sluigi		ctx->v0.eq_id = cq->eq->eq_id;
1893231437Sluigi	}
1894231437Sluigi
1895231437Sluigi	mbx.u0.s.embedded = 1;
1896231437Sluigi	mbx.payload_length = sizeof(struct mbx_create_common_cq);
1897231437Sluigi
1898231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1899247880Sdelphij	if (!rc)
1900247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1901247880Sdelphij	if (rc) {
1902257007Sdelphij		device_printf(sc->dev,
1903257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1904257007Sdelphij			      __FUNCTION__, rc,
1905257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1906231437Sluigi		goto error;
1907247880Sdelphij	}
1908257007Sdelphij	cq->cq_id = HOST_16(fwcmd->params.rsp.cq_id);
1909247880Sdelphijerror:
1910247880Sdelphij	return rc;
1911231437Sluigi
1912247880Sdelphij}
1913247880Sdelphij
1914247880Sdelphijint
1915247880Sdelphijoce_mbox_read_transrecv_data(POCE_SOFTC sc, uint32_t page_num)
1916247880Sdelphij{
1917247880Sdelphij	int rc = 0;
1918247880Sdelphij	struct oce_mbx mbx;
1919247880Sdelphij	struct mbx_read_common_transrecv_data *fwcmd;
1920247880Sdelphij	struct oce_mq_sge *sgl;
1921247880Sdelphij	OCE_DMA_MEM dma;
1922247880Sdelphij
1923247880Sdelphij	/* Allocate DMA mem*/
1924247880Sdelphij	if (oce_dma_alloc(sc, sizeof(struct mbx_read_common_transrecv_data),
1925247880Sdelphij				&dma, 0))
1926247880Sdelphij		return ENOMEM;
1927247880Sdelphij
1928247880Sdelphij	fwcmd = OCE_DMAPTR(&dma, struct mbx_read_common_transrecv_data);
1929247880Sdelphij	bzero(fwcmd, sizeof(struct mbx_read_common_transrecv_data));
1930247880Sdelphij
1931247880Sdelphij	bzero(&mbx, sizeof(struct oce_mbx));
1932247880Sdelphij	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1933247880Sdelphij			MBX_SUBSYSTEM_COMMON,
1934247880Sdelphij			OPCODE_COMMON_READ_TRANSRECEIVER_DATA,
1935247880Sdelphij			MBX_TIMEOUT_SEC,
1936247880Sdelphij			sizeof(struct mbx_read_common_transrecv_data),
1937247880Sdelphij			OCE_MBX_VER_V0);
1938247880Sdelphij
1939247880Sdelphij	/* fill rest of mbx */
1940247880Sdelphij	mbx.u0.s.embedded = 0;
1941247880Sdelphij	mbx.payload_length = sizeof(struct mbx_read_common_transrecv_data);
1942247880Sdelphij	mbx.u0.s.sge_count = 1;
1943247880Sdelphij	sgl = &mbx.payload.u0.u1.sgl[0];
1944247880Sdelphij	sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
1945247880Sdelphij	sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
1946247880Sdelphij	sgl->length = htole32(mbx.payload_length);
1947247880Sdelphij	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1948247880Sdelphij
1949247880Sdelphij	fwcmd->params.req.port = LE_32(sc->port_id);
1950247880Sdelphij	fwcmd->params.req.page_num = LE_32(page_num);
1951247880Sdelphij
1952247880Sdelphij	/* command post */
1953247880Sdelphij	rc = oce_mbox_post(sc, &mbx, NULL);
1954247880Sdelphij	if (!rc)
1955252869Sdelphij		rc = fwcmd->hdr.u0.rsp.status;
1956247880Sdelphij	if (rc) {
1957257007Sdelphij		device_printf(sc->dev,
1958257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
1959257007Sdelphij			      __FUNCTION__, rc,
1960257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
1961247880Sdelphij		goto error;
1962247880Sdelphij	}
1963247880Sdelphij	if(fwcmd->params.rsp.page_num == PAGE_NUM_A0)
1964247880Sdelphij	{
1965247880Sdelphij		bcopy((char *)fwcmd->params.rsp.page_data,
1966247880Sdelphij				(char *)&sfp_vpd_dump_buffer[0],
1967247880Sdelphij				TRANSCEIVER_A0_SIZE);
1968247880Sdelphij	}
1969247880Sdelphij
1970247880Sdelphij	if(fwcmd->params.rsp.page_num == PAGE_NUM_A2)
1971247880Sdelphij	{
1972247880Sdelphij		bcopy((char *)fwcmd->params.rsp.page_data,
1973247880Sdelphij				(char *)&sfp_vpd_dump_buffer[32],
1974247880Sdelphij				TRANSCEIVER_A2_SIZE);
1975247880Sdelphij	}
1976231437Sluigierror:
1977252869Sdelphij	oce_dma_free(sc, &dma);
1978231437Sluigi	return rc;
1979247880Sdelphij}
1980231437Sluigi
1981247880Sdelphijvoid
1982247880Sdelphijoce_mbox_eqd_modify_periodic(POCE_SOFTC sc, struct oce_set_eqd *set_eqd,
1983247880Sdelphij				int num)
1984247880Sdelphij{
1985247880Sdelphij	struct oce_mbx mbx;
1986247880Sdelphij	struct mbx_modify_common_eq_delay *fwcmd;
1987247880Sdelphij	int rc = 0;
1988247880Sdelphij	int i = 0;
1989247880Sdelphij
1990247880Sdelphij	bzero(&mbx, sizeof(struct oce_mbx));
1991247880Sdelphij
1992247880Sdelphij	/* Initialize MODIFY_EQ_DELAY ioctl header */
1993247880Sdelphij	fwcmd = (struct mbx_modify_common_eq_delay *)&mbx.payload;
1994247880Sdelphij	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1995247880Sdelphij				MBX_SUBSYSTEM_COMMON,
1996247880Sdelphij				OPCODE_COMMON_MODIFY_EQ_DELAY,
1997247880Sdelphij				MBX_TIMEOUT_SEC,
1998247880Sdelphij				sizeof(struct mbx_modify_common_eq_delay),
1999247880Sdelphij				OCE_MBX_VER_V0);
2000247880Sdelphij	/* fill rest of mbx */
2001247880Sdelphij	mbx.u0.s.embedded = 1;
2002247880Sdelphij	mbx.payload_length = sizeof(struct mbx_modify_common_eq_delay);
2003247880Sdelphij	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
2004247880Sdelphij
2005247880Sdelphij	fwcmd->params.req.num_eq = num;
2006247880Sdelphij	for (i = 0; i < num; i++) {
2007247880Sdelphij		fwcmd->params.req.delay[i].eq_id =
2008247880Sdelphij					htole32(set_eqd[i].eq_id);
2009247880Sdelphij		fwcmd->params.req.delay[i].phase = 0;
2010247880Sdelphij		fwcmd->params.req.delay[i].dm =
2011247880Sdelphij		htole32(set_eqd[i].delay_multiplier);
2012247880Sdelphij	}
2013247880Sdelphij
2014247880Sdelphij
2015247880Sdelphij	/* command post */
2016247880Sdelphij	rc = oce_mbox_post(sc, &mbx, NULL);
2017247880Sdelphij
2018247880Sdelphij	if (!rc)
2019252869Sdelphij		rc = fwcmd->hdr.u0.rsp.status;
2020247880Sdelphij	if (rc)
2021257007Sdelphij		device_printf(sc->dev,
2022257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
2023257007Sdelphij			      __FUNCTION__, rc,
2024257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
2025231437Sluigi}
2026247880Sdelphij
2027252869Sdelphijint
2028258941Sdelphijoce_get_profile_config(POCE_SOFTC sc, uint32_t max_rss)
2029252869Sdelphij{
2030252869Sdelphij	struct oce_mbx mbx;
2031252869Sdelphij	struct mbx_common_get_profile_config *fwcmd;
2032252869Sdelphij	int rc = 0;
2033252869Sdelphij	int version = 0;
2034252869Sdelphij	struct oce_mq_sge *sgl;
2035252869Sdelphij	OCE_DMA_MEM dma;
2036252869Sdelphij	uint32_t desc_count = 0;
2037252869Sdelphij	struct oce_nic_resc_desc *nic_desc = NULL;
2038252869Sdelphij	int i;
2039252869Sdelphij	boolean_t nic_desc_valid = FALSE;
2040247880Sdelphij
2041252869Sdelphij	if (IS_BE2(sc))
2042252869Sdelphij		return -1;
2043252869Sdelphij
2044252869Sdelphij	/* Allocate DMA mem*/
2045252869Sdelphij	if (oce_dma_alloc(sc, sizeof(struct mbx_common_get_profile_config),
2046252869Sdelphij			  &dma, 0))
2047252869Sdelphij		return ENOMEM;
2048252869Sdelphij
2049252869Sdelphij	/* Initialize MODIFY_EQ_DELAY ioctl header */
2050252869Sdelphij	fwcmd = OCE_DMAPTR(&dma, struct mbx_common_get_profile_config);
2051252869Sdelphij	bzero(fwcmd, sizeof(struct mbx_common_get_profile_config));
2052252869Sdelphij
2053258941Sdelphij	if (!IS_XE201(sc))
2054252869Sdelphij		version = OCE_MBX_VER_V1;
2055252869Sdelphij	else
2056252869Sdelphij		version = OCE_MBX_VER_V0;
2057252869Sdelphij
2058252869Sdelphij	bzero(&mbx, sizeof(struct oce_mbx));
2059252869Sdelphij	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
2060252869Sdelphij				MBX_SUBSYSTEM_COMMON,
2061252869Sdelphij				OPCODE_COMMON_GET_PROFILE_CONFIG,
2062252869Sdelphij				MBX_TIMEOUT_SEC,
2063252869Sdelphij				sizeof(struct mbx_common_get_profile_config),
2064252869Sdelphij				version);
2065252869Sdelphij	/* fill rest of mbx */
2066252869Sdelphij	mbx.u0.s.embedded = 0;
2067252869Sdelphij	mbx.payload_length = sizeof(struct mbx_common_get_profile_config);
2068252869Sdelphij	mbx.u0.s.sge_count = 1;
2069252869Sdelphij	sgl = &mbx.payload.u0.u1.sgl[0];
2070252869Sdelphij	sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
2071252869Sdelphij	sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
2072252869Sdelphij	sgl->length = htole32(mbx.payload_length);
2073252869Sdelphij	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
2074252869Sdelphij
2075252869Sdelphij	fwcmd->params.req.type = ACTIVE_PROFILE;
2076252869Sdelphij
2077252869Sdelphij	/* command post */
2078252869Sdelphij	rc = oce_mbox_post(sc, &mbx, NULL);
2079252869Sdelphij	if (!rc)
2080252869Sdelphij		rc = fwcmd->hdr.u0.rsp.status;
2081252869Sdelphij	if (rc) {
2082257007Sdelphij		device_printf(sc->dev,
2083257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
2084257007Sdelphij			      __FUNCTION__, rc,
2085257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
2086252869Sdelphij		goto error;
2087252869Sdelphij	}
2088252869Sdelphij
2089252869Sdelphij	nic_desc = (struct oce_nic_resc_desc *) fwcmd->params.rsp.resources;
2090252869Sdelphij	desc_count = HOST_32(fwcmd->params.rsp.desc_count);
2091252869Sdelphij	for (i = 0; i < desc_count; i++) {
2092252869Sdelphij		if ((nic_desc->desc_type == NIC_RESC_DESC_TYPE_V0) ||
2093252869Sdelphij		    (nic_desc->desc_type == NIC_RESC_DESC_TYPE_V1)) {
2094252869Sdelphij			nic_desc_valid = TRUE;
2095252869Sdelphij			break;
2096252869Sdelphij		}
2097252869Sdelphij		nic_desc = (struct oce_nic_resc_desc *) \
2098252869Sdelphij				((char *)nic_desc + nic_desc->desc_len);
2099252869Sdelphij	}
2100252869Sdelphij	if (!nic_desc_valid) {
2101252869Sdelphij		rc = -1;
2102252869Sdelphij		goto error;
2103252869Sdelphij	}
2104252869Sdelphij	else {
2105258941Sdelphij		sc->max_vlans = HOST_16(nic_desc->vlan_count);
2106258941Sdelphij		sc->nwqs = HOST_16(nic_desc->txq_count);
2107252869Sdelphij		if (sc->nwqs)
2108252869Sdelphij			sc->nwqs = MIN(sc->nwqs, OCE_MAX_WQ);
2109252869Sdelphij		else
2110252869Sdelphij			sc->nwqs = OCE_MAX_WQ;
2111252869Sdelphij
2112258941Sdelphij		sc->nrssqs = HOST_16(nic_desc->rssq_count);
2113258941Sdelphij		if (sc->nrssqs)
2114258941Sdelphij			sc->nrssqs = MIN(sc->nrssqs, max_rss);
2115258941Sdelphij		else
2116258941Sdelphij			sc->nrssqs = max_rss;
2117258941Sdelphij		sc->nrqs =  sc->nrssqs + 1; /* 1 for def RX */;
2118258941Sdelphij
2119252869Sdelphij	}
2120252869Sdelphijerror:
2121252869Sdelphij	oce_dma_free(sc, &dma);
2122252869Sdelphij	return rc;
2123252869Sdelphij
2124252869Sdelphij}
2125252869Sdelphij
2126252869Sdelphijint
2127252869Sdelphijoce_get_func_config(POCE_SOFTC sc)
2128252869Sdelphij{
2129252869Sdelphij	struct oce_mbx mbx;
2130252869Sdelphij	struct mbx_common_get_func_config *fwcmd;
2131252869Sdelphij	int rc = 0;
2132252869Sdelphij	int version = 0;
2133252869Sdelphij	struct oce_mq_sge *sgl;
2134252869Sdelphij	OCE_DMA_MEM dma;
2135252869Sdelphij	uint32_t desc_count = 0;
2136252869Sdelphij	struct oce_nic_resc_desc *nic_desc = NULL;
2137252869Sdelphij	int i;
2138252869Sdelphij	boolean_t nic_desc_valid = FALSE;
2139252869Sdelphij	uint32_t max_rss = 0;
2140252869Sdelphij
2141252869Sdelphij	if ((IS_BE(sc) || IS_SH(sc)) && (!sc->be3_native))
2142252869Sdelphij		max_rss = OCE_LEGACY_MODE_RSS;
2143252869Sdelphij	else
2144252869Sdelphij		max_rss = OCE_MAX_RSS;
2145252869Sdelphij
2146252869Sdelphij	/* Allocate DMA mem*/
2147252869Sdelphij	if (oce_dma_alloc(sc, sizeof(struct mbx_common_get_func_config),
2148252869Sdelphij			  &dma, 0))
2149252869Sdelphij		return ENOMEM;
2150252869Sdelphij
2151252869Sdelphij	/* Initialize MODIFY_EQ_DELAY ioctl header */
2152252869Sdelphij	fwcmd = OCE_DMAPTR(&dma, struct mbx_common_get_func_config);
2153252869Sdelphij	bzero(fwcmd, sizeof(struct mbx_common_get_func_config));
2154252869Sdelphij
2155252869Sdelphij	if (IS_SH(sc))
2156252869Sdelphij		version = OCE_MBX_VER_V1;
2157252869Sdelphij	else
2158252869Sdelphij		version = OCE_MBX_VER_V0;
2159252869Sdelphij
2160252869Sdelphij	bzero(&mbx, sizeof(struct oce_mbx));
2161252869Sdelphij	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
2162252869Sdelphij				MBX_SUBSYSTEM_COMMON,
2163252869Sdelphij				OPCODE_COMMON_GET_FUNCTION_CONFIG,
2164252869Sdelphij				MBX_TIMEOUT_SEC,
2165252869Sdelphij				sizeof(struct mbx_common_get_func_config),
2166252869Sdelphij				version);
2167252869Sdelphij	/* fill rest of mbx */
2168252869Sdelphij	mbx.u0.s.embedded = 0;
2169252869Sdelphij	mbx.payload_length = sizeof(struct mbx_common_get_func_config);
2170252869Sdelphij	mbx.u0.s.sge_count = 1;
2171252869Sdelphij	sgl = &mbx.payload.u0.u1.sgl[0];
2172252869Sdelphij	sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
2173252869Sdelphij	sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
2174252869Sdelphij	sgl->length = htole32(mbx.payload_length);
2175252869Sdelphij	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
2176252869Sdelphij
2177252869Sdelphij	/* command post */
2178252869Sdelphij	rc = oce_mbox_post(sc, &mbx, NULL);
2179252869Sdelphij	if (!rc)
2180252869Sdelphij		rc = fwcmd->hdr.u0.rsp.status;
2181252869Sdelphij	if (rc) {
2182257007Sdelphij		device_printf(sc->dev,
2183257007Sdelphij			      "%s failed - cmd status: %d addi status: %d\n",
2184257007Sdelphij			      __FUNCTION__, rc,
2185257007Sdelphij			      fwcmd->hdr.u0.rsp.additional_status);
2186252869Sdelphij		goto error;
2187252869Sdelphij	}
2188252869Sdelphij
2189252869Sdelphij	nic_desc = (struct oce_nic_resc_desc *) fwcmd->params.rsp.resources;
2190252869Sdelphij	desc_count = HOST_32(fwcmd->params.rsp.desc_count);
2191252869Sdelphij	for (i = 0; i < desc_count; i++) {
2192252869Sdelphij		if ((nic_desc->desc_type == NIC_RESC_DESC_TYPE_V0) ||
2193252869Sdelphij		    (nic_desc->desc_type == NIC_RESC_DESC_TYPE_V1)) {
2194252869Sdelphij			nic_desc_valid = TRUE;
2195252869Sdelphij			break;
2196252869Sdelphij		}
2197252869Sdelphij		nic_desc = (struct oce_nic_resc_desc *) \
2198252869Sdelphij				((char *)nic_desc + nic_desc->desc_len);
2199252869Sdelphij	}
2200252869Sdelphij	if (!nic_desc_valid) {
2201252869Sdelphij		rc = -1;
2202252869Sdelphij		goto error;
2203252869Sdelphij	}
2204252869Sdelphij	else {
2205257007Sdelphij		sc->max_vlans = nic_desc->vlan_count;
2206252869Sdelphij		sc->nwqs = HOST_32(nic_desc->txq_count);
2207252869Sdelphij                if (sc->nwqs)
2208252869Sdelphij                        sc->nwqs = MIN(sc->nwqs, OCE_MAX_WQ);
2209252869Sdelphij                else
2210252869Sdelphij                        sc->nwqs = OCE_MAX_WQ;
2211252869Sdelphij
2212252869Sdelphij		sc->nrssqs = HOST_32(nic_desc->rssq_count);
2213252869Sdelphij		if (sc->nrssqs)
2214252869Sdelphij			sc->nrssqs = MIN(sc->nrssqs, max_rss);
2215252869Sdelphij		else
2216252869Sdelphij			sc->nrssqs = max_rss;
2217252869Sdelphij		sc->nrqs =  sc->nrssqs + 1; /* 1 for def RX */;
2218252869Sdelphij	}
2219252869Sdelphijerror:
2220252869Sdelphij	oce_dma_free(sc, &dma);
2221252869Sdelphij	return rc;
2222252869Sdelphij
2223252869Sdelphij}
2224