oce_mbox.c revision 252869
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
40247880Sdelphij
41231437Sluigi/* $FreeBSD: head/sys/dev/oce/oce_mbox.c 252869 2013-07-06 08:30:45Z delphij $ */
42231437Sluigi
43247880Sdelphij
44231437Sluigi#include "oce_if.h"
45247880Sdelphijextern uint32_t sfp_vpd_dump_buffer[TRANSCEIVER_DATA_NUM_ELE];
46231437Sluigi
47231437Sluigi/**
48231437Sluigi * @brief Reset (firmware) common function
49231437Sluigi * @param sc		software handle to the device
50231437Sluigi * @returns		0 on success, ETIMEDOUT on failure
51231437Sluigi */
52231437Sluigiint
53231437Sluigioce_reset_fun(POCE_SOFTC sc)
54231437Sluigi{
55231437Sluigi	struct oce_mbx *mbx;
56231437Sluigi	struct oce_bmbx *mb;
57231437Sluigi	struct ioctl_common_function_reset *fwcmd;
58231437Sluigi	int rc = 0;
59231437Sluigi
60231437Sluigi	if (sc->flags & OCE_FLAGS_FUNCRESET_RQD) {
61231437Sluigi		mb = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
62231437Sluigi		mbx = &mb->mbx;
63231437Sluigi		bzero(mbx, sizeof(struct oce_mbx));
64231437Sluigi
65231437Sluigi		fwcmd = (struct ioctl_common_function_reset *)&mbx->payload;
66231437Sluigi		mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
67231437Sluigi					MBX_SUBSYSTEM_COMMON,
68231437Sluigi					OPCODE_COMMON_FUNCTION_RESET,
69231437Sluigi					10,	/* MBX_TIMEOUT_SEC */
70231437Sluigi					sizeof(struct
71231437Sluigi					    ioctl_common_function_reset),
72231437Sluigi					OCE_MBX_VER_V0);
73231437Sluigi
74231437Sluigi		mbx->u0.s.embedded = 1;
75231437Sluigi		mbx->payload_length =
76231437Sluigi		    sizeof(struct ioctl_common_function_reset);
77231437Sluigi
78231437Sluigi		rc = oce_mbox_dispatch(sc, 2);
79231437Sluigi	}
80231437Sluigi
81231437Sluigi	return rc;
82231437Sluigi}
83231437Sluigi
84231437Sluigi
85231437Sluigi/**
86231437Sluigi * @brief  		This funtions tells firmware we are
87231437Sluigi *			done with commands.
88231437Sluigi * @param sc            software handle to the device
89231437Sluigi * @returns             0 on success, ETIMEDOUT on failure
90231437Sluigi */
91231437Sluigiint
92231437Sluigioce_fw_clean(POCE_SOFTC sc)
93231437Sluigi{
94231437Sluigi	struct oce_bmbx *mbx;
95231437Sluigi	uint8_t *ptr;
96231437Sluigi	int ret = 0;
97231437Sluigi
98231437Sluigi	mbx = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
99231437Sluigi	ptr = (uint8_t *) &mbx->mbx;
100231437Sluigi
101231437Sluigi	/* Endian Signature */
102231437Sluigi	*ptr++ = 0xff;
103231437Sluigi	*ptr++ = 0xaa;
104231437Sluigi	*ptr++ = 0xbb;
105231437Sluigi	*ptr++ = 0xff;
106231437Sluigi	*ptr++ = 0xff;
107231437Sluigi	*ptr++ = 0xcc;
108231437Sluigi	*ptr++ = 0xdd;
109231437Sluigi	*ptr = 0xff;
110231437Sluigi
111231437Sluigi	ret = oce_mbox_dispatch(sc, 2);
112231437Sluigi
113231437Sluigi	return ret;
114231437Sluigi}
115231437Sluigi
116231437Sluigi
117231437Sluigi/**
118231437Sluigi * @brief Mailbox wait
119231437Sluigi * @param sc		software handle to the device
120231437Sluigi * @param tmo_sec	timeout in seconds
121231437Sluigi */
122231437Sluigistatic int
123231437Sluigioce_mbox_wait(POCE_SOFTC sc, uint32_t tmo_sec)
124231437Sluigi{
125231437Sluigi	tmo_sec *= 10000;
126231437Sluigi	pd_mpu_mbox_db_t mbox_db;
127231437Sluigi
128231437Sluigi	for (;;) {
129231437Sluigi		if (tmo_sec != 0) {
130231437Sluigi			if (--tmo_sec == 0)
131231437Sluigi				break;
132231437Sluigi		}
133231437Sluigi
134231437Sluigi		mbox_db.dw0 = OCE_READ_REG32(sc, db, PD_MPU_MBOX_DB);
135231437Sluigi
136231437Sluigi		if (mbox_db.bits.ready)
137231437Sluigi			return 0;
138231437Sluigi
139231437Sluigi		DELAY(100);
140231437Sluigi	}
141231437Sluigi
142231437Sluigi	device_printf(sc->dev, "Mailbox timed out\n");
143231437Sluigi
144231437Sluigi	return ETIMEDOUT;
145231437Sluigi}
146231437Sluigi
147231437Sluigi
148231437Sluigi/**
149231437Sluigi * @brief Mailbox dispatch
150231437Sluigi * @param sc		software handle to the device
151231437Sluigi * @param tmo_sec	timeout in seconds
152231437Sluigi */
153231437Sluigiint
154231437Sluigioce_mbox_dispatch(POCE_SOFTC sc, uint32_t tmo_sec)
155231437Sluigi{
156231437Sluigi	pd_mpu_mbox_db_t mbox_db;
157231437Sluigi	uint32_t pa;
158231437Sluigi	int rc;
159231437Sluigi
160231437Sluigi	oce_dma_sync(&sc->bsmbx, BUS_DMASYNC_PREWRITE);
161231437Sluigi	pa = (uint32_t) ((uint64_t) sc->bsmbx.paddr >> 34);
162231437Sluigi	bzero(&mbox_db, sizeof(pd_mpu_mbox_db_t));
163231437Sluigi	mbox_db.bits.ready = 0;
164231437Sluigi	mbox_db.bits.hi = 1;
165231437Sluigi	mbox_db.bits.address = pa;
166231437Sluigi
167231437Sluigi	rc = oce_mbox_wait(sc, tmo_sec);
168231437Sluigi	if (rc == 0) {
169231437Sluigi		OCE_WRITE_REG32(sc, db, PD_MPU_MBOX_DB, mbox_db.dw0);
170231437Sluigi
171231437Sluigi		pa = (uint32_t) ((uint64_t) sc->bsmbx.paddr >> 4) & 0x3fffffff;
172231437Sluigi		mbox_db.bits.ready = 0;
173231437Sluigi		mbox_db.bits.hi = 0;
174231437Sluigi		mbox_db.bits.address = pa;
175231437Sluigi
176231437Sluigi		rc = oce_mbox_wait(sc, tmo_sec);
177231437Sluigi
178231437Sluigi		if (rc == 0) {
179231437Sluigi			OCE_WRITE_REG32(sc, db, PD_MPU_MBOX_DB, mbox_db.dw0);
180231437Sluigi
181231437Sluigi			rc = oce_mbox_wait(sc, tmo_sec);
182231437Sluigi
183231437Sluigi			oce_dma_sync(&sc->bsmbx, BUS_DMASYNC_POSTWRITE);
184231437Sluigi		}
185231437Sluigi	}
186231437Sluigi
187231437Sluigi	return rc;
188231437Sluigi}
189231437Sluigi
190231437Sluigi
191231437Sluigi
192231437Sluigi/**
193231437Sluigi * @brief 		Mailbox common request header initialization
194231437Sluigi * @param hdr		mailbox header
195231437Sluigi * @param dom		domain
196231437Sluigi * @param port		port
197231437Sluigi * @param subsys	subsystem
198231437Sluigi * @param opcode	opcode
199231437Sluigi * @param timeout	timeout
200231437Sluigi * @param pyld_len	payload length
201231437Sluigi */
202231437Sluigivoid
203231437Sluigimbx_common_req_hdr_init(struct mbx_hdr *hdr,
204231437Sluigi			uint8_t dom, uint8_t port,
205231437Sluigi			uint8_t subsys, uint8_t opcode,
206231437Sluigi			uint32_t timeout, uint32_t pyld_len,
207231437Sluigi			uint8_t version)
208231437Sluigi{
209231437Sluigi	hdr->u0.req.opcode = opcode;
210231437Sluigi	hdr->u0.req.subsystem = subsys;
211231437Sluigi	hdr->u0.req.port_number = port;
212231437Sluigi	hdr->u0.req.domain = dom;
213231437Sluigi
214231437Sluigi	hdr->u0.req.timeout = timeout;
215231437Sluigi	hdr->u0.req.request_length = pyld_len - sizeof(struct mbx_hdr);
216231437Sluigi	hdr->u0.req.version = version;
217231437Sluigi}
218231437Sluigi
219231437Sluigi
220231437Sluigi
221231437Sluigi/**
222231437Sluigi * @brief Function to initialize the hw with host endian information
223231437Sluigi * @param sc		software handle to the device
224231437Sluigi * @returns		0 on success, ETIMEDOUT on failure
225231437Sluigi */
226231437Sluigiint
227231437Sluigioce_mbox_init(POCE_SOFTC sc)
228231437Sluigi{
229231437Sluigi	struct oce_bmbx *mbx;
230231437Sluigi	uint8_t *ptr;
231231437Sluigi	int ret = 0;
232231437Sluigi
233231437Sluigi	if (sc->flags & OCE_FLAGS_MBOX_ENDIAN_RQD) {
234231437Sluigi		mbx = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
235231437Sluigi		ptr = (uint8_t *) &mbx->mbx;
236231437Sluigi
237231437Sluigi		/* Endian Signature */
238231437Sluigi		*ptr++ = 0xff;
239231437Sluigi		*ptr++ = 0x12;
240231437Sluigi		*ptr++ = 0x34;
241231437Sluigi		*ptr++ = 0xff;
242231437Sluigi		*ptr++ = 0xff;
243231437Sluigi		*ptr++ = 0x56;
244231437Sluigi		*ptr++ = 0x78;
245231437Sluigi		*ptr = 0xff;
246231437Sluigi
247231437Sluigi		ret = oce_mbox_dispatch(sc, 0);
248231437Sluigi	}
249231437Sluigi
250231437Sluigi	return ret;
251231437Sluigi}
252231437Sluigi
253231437Sluigi
254231437Sluigi/**
255231437Sluigi * @brief 		Function to get the firmware version
256231437Sluigi * @param sc		software handle to the device
257231437Sluigi * @returns		0 on success, EIO on failure
258231437Sluigi */
259231437Sluigiint
260231437Sluigioce_get_fw_version(POCE_SOFTC sc)
261231437Sluigi{
262231437Sluigi	struct oce_mbx mbx;
263231437Sluigi	struct mbx_get_common_fw_version *fwcmd;
264231437Sluigi	int ret = 0;
265231437Sluigi
266231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
267231437Sluigi
268231437Sluigi	fwcmd = (struct mbx_get_common_fw_version *)&mbx.payload;
269231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
270231437Sluigi				MBX_SUBSYSTEM_COMMON,
271231437Sluigi				OPCODE_COMMON_GET_FW_VERSION,
272231437Sluigi				MBX_TIMEOUT_SEC,
273231437Sluigi				sizeof(struct mbx_get_common_fw_version),
274231437Sluigi				OCE_MBX_VER_V0);
275231437Sluigi
276231437Sluigi	mbx.u0.s.embedded = 1;
277231437Sluigi	mbx.payload_length = sizeof(struct mbx_get_common_fw_version);
278231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
279231437Sluigi
280231437Sluigi	ret = oce_mbox_post(sc, &mbx, NULL);
281247880Sdelphij	if (!ret)
282247880Sdelphij                ret = fwcmd->hdr.u0.rsp.status;
283247880Sdelphij	if (ret) {
284247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
285247880Sdelphij			      __FUNCTION__, ret);
286247880Sdelphij		goto error;
287247880Sdelphij	}
288231437Sluigi
289231437Sluigi	bcopy(fwcmd->params.rsp.fw_ver_str, sc->fw_version, 32);
290247880Sdelphijerror:
291247880Sdelphij	return ret;
292231437Sluigi}
293231437Sluigi
294231437Sluigi
295231437Sluigi/**
296231879Sluigi * @brief	Firmware will send gracious notifications during
297231879Sluigi *		attach only after sending first mcc commnad. We
298231879Sluigi *		use MCC queue only for getting async and mailbox
299231879Sluigi *		for sending cmds. So to get gracious notifications
300231879Sluigi *		atleast send one dummy command on mcc.
301231879Sluigi */
302231879Sluigiint
303231879Sluigioce_first_mcc_cmd(POCE_SOFTC sc)
304231879Sluigi{
305231879Sluigi	struct oce_mbx *mbx;
306231879Sluigi	struct oce_mq *mq = sc->mq;
307231879Sluigi	struct mbx_get_common_fw_version *fwcmd;
308231879Sluigi	uint32_t reg_value;
309231879Sluigi
310231879Sluigi	mbx = RING_GET_PRODUCER_ITEM_VA(mq->ring, struct oce_mbx);
311231879Sluigi	bzero(mbx, sizeof(struct oce_mbx));
312231879Sluigi
313231879Sluigi	fwcmd = (struct mbx_get_common_fw_version *)&mbx->payload;
314231879Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
315231879Sluigi				MBX_SUBSYSTEM_COMMON,
316231879Sluigi				OPCODE_COMMON_GET_FW_VERSION,
317231879Sluigi				MBX_TIMEOUT_SEC,
318231879Sluigi				sizeof(struct mbx_get_common_fw_version),
319231879Sluigi				OCE_MBX_VER_V0);
320231879Sluigi	mbx->u0.s.embedded = 1;
321231879Sluigi	mbx->payload_length = sizeof(struct mbx_get_common_fw_version);
322231879Sluigi	bus_dmamap_sync(mq->ring->dma.tag, mq->ring->dma.map,
323231879Sluigi				BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
324231879Sluigi	RING_PUT(mq->ring, 1);
325231879Sluigi	reg_value = (1 << 16) | mq->mq_id;
326231879Sluigi	OCE_WRITE_REG32(sc, db, PD_MQ_DB, reg_value);
327231879Sluigi
328231879Sluigi	return 0;
329231879Sluigi}
330231879Sluigi
331231879Sluigi/**
332231437Sluigi * @brief		Function to post a MBX to the mbox
333231437Sluigi * @param sc		software handle to the device
334231437Sluigi * @param mbx 		pointer to the MBX to send
335231437Sluigi * @param mbxctx	pointer to the mbx context structure
336231437Sluigi * @returns		0 on success, error on failure
337231437Sluigi */
338231437Sluigiint
339231437Sluigioce_mbox_post(POCE_SOFTC sc, struct oce_mbx *mbx, struct oce_mbx_ctx *mbxctx)
340231437Sluigi{
341231437Sluigi	struct oce_mbx *mb_mbx = NULL;
342231437Sluigi	struct oce_mq_cqe *mb_cqe = NULL;
343231437Sluigi	struct oce_bmbx *mb = NULL;
344231437Sluigi	int rc = 0;
345231437Sluigi	uint32_t tmo = 0;
346231437Sluigi	uint32_t cstatus = 0;
347231437Sluigi	uint32_t xstatus = 0;
348231437Sluigi
349231437Sluigi	LOCK(&sc->bmbx_lock);
350231437Sluigi
351231437Sluigi	mb = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
352231437Sluigi	mb_mbx = &mb->mbx;
353231437Sluigi
354231437Sluigi	/* get the tmo */
355231437Sluigi	tmo = mbx->tag[0];
356231437Sluigi	mbx->tag[0] = 0;
357231437Sluigi
358231437Sluigi	/* copy mbx into mbox */
359231437Sluigi	bcopy(mbx, mb_mbx, sizeof(struct oce_mbx));
360231437Sluigi
361231437Sluigi	/* now dispatch */
362231437Sluigi	rc = oce_mbox_dispatch(sc, tmo);
363231437Sluigi	if (rc == 0) {
364231437Sluigi		/*
365231437Sluigi		 * the command completed successfully. Now get the
366231437Sluigi		 * completion queue entry
367231437Sluigi		 */
368231437Sluigi		mb_cqe = &mb->cqe;
369231437Sluigi		DW_SWAP(u32ptr(&mb_cqe->u0.dw[0]), sizeof(struct oce_mq_cqe));
370231437Sluigi
371231437Sluigi		/* copy mbox mbx back */
372231437Sluigi		bcopy(mb_mbx, mbx, sizeof(struct oce_mbx));
373231437Sluigi
374231437Sluigi		/* pick up the mailbox status */
375231437Sluigi		cstatus = mb_cqe->u0.s.completion_status;
376231437Sluigi		xstatus = mb_cqe->u0.s.extended_status;
377231437Sluigi
378231437Sluigi		/*
379231437Sluigi		 * store the mbx context in the cqe tag section so that
380231437Sluigi		 * the upper layer handling the cqe can associate the mbx
381231437Sluigi		 * with the response
382231437Sluigi		 */
383231437Sluigi		if (cstatus == 0 && mbxctx) {
384231437Sluigi			/* save context */
385231437Sluigi			mbxctx->mbx = mb_mbx;
386231437Sluigi			bcopy(&mbxctx, mb_cqe->u0.s.mq_tag,
387231437Sluigi				sizeof(struct oce_mbx_ctx *));
388231437Sluigi		}
389231437Sluigi	}
390231437Sluigi
391231437Sluigi	UNLOCK(&sc->bmbx_lock);
392231437Sluigi
393231437Sluigi	return rc;
394231437Sluigi}
395231437Sluigi
396231437Sluigi/**
397231437Sluigi * @brief Function to read the mac address associated with an interface
398231437Sluigi * @param sc		software handle to the device
399231437Sluigi * @param if_id 	interface id to read the address from
400231437Sluigi * @param perm 		set to 1 if reading the factory mac address.
401231437Sluigi *			In this case if_id is ignored
402231437Sluigi * @param type 		type of the mac address, whether network or storage
403231437Sluigi * @param[out] mac 	[OUTPUT] pointer to a buffer containing the
404231437Sluigi *			mac address when the command succeeds.
405231437Sluigi * @returns		0 on success, EIO on failure
406231437Sluigi */
407231437Sluigiint
408231437Sluigioce_read_mac_addr(POCE_SOFTC sc, uint32_t if_id,
409231437Sluigi		uint8_t perm, uint8_t type, struct mac_address_format *mac)
410231437Sluigi{
411231437Sluigi	struct oce_mbx mbx;
412231437Sluigi	struct mbx_query_common_iface_mac *fwcmd;
413231437Sluigi	int ret = 0;
414231437Sluigi
415231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
416231437Sluigi
417231437Sluigi	fwcmd = (struct mbx_query_common_iface_mac *)&mbx.payload;
418231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
419231437Sluigi				MBX_SUBSYSTEM_COMMON,
420231437Sluigi				OPCODE_COMMON_QUERY_IFACE_MAC,
421231437Sluigi				MBX_TIMEOUT_SEC,
422231437Sluigi				sizeof(struct mbx_query_common_iface_mac),
423231437Sluigi				OCE_MBX_VER_V0);
424231437Sluigi
425231437Sluigi	fwcmd->params.req.permanent = perm;
426231437Sluigi	if (!perm)
427231437Sluigi		fwcmd->params.req.if_id = (uint16_t) if_id;
428231437Sluigi	else
429231437Sluigi		fwcmd->params.req.if_id = 0;
430231437Sluigi
431231437Sluigi	fwcmd->params.req.type = type;
432231437Sluigi
433231437Sluigi	mbx.u0.s.embedded = 1;
434231437Sluigi	mbx.payload_length = sizeof(struct mbx_query_common_iface_mac);
435231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
436231437Sluigi
437231437Sluigi	ret = oce_mbox_post(sc, &mbx, NULL);
438247880Sdelphij	if (!ret)
439247880Sdelphij                ret = fwcmd->hdr.u0.rsp.status;
440247880Sdelphij	if (ret) {
441247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
442247880Sdelphij			      __FUNCTION__, ret);
443247880Sdelphij		goto error;
444247880Sdelphij	}
445231437Sluigi
446231437Sluigi	/* copy the mac addres in the output parameter */
447231437Sluigi	mac->size_of_struct = fwcmd->params.rsp.mac.size_of_struct;
448231437Sluigi	bcopy(&fwcmd->params.rsp.mac.mac_addr[0], &mac->mac_addr[0],
449231437Sluigi		mac->size_of_struct);
450247880Sdelphijerror:
451247880Sdelphij	return ret;
452231437Sluigi}
453231437Sluigi
454231437Sluigi/**
455231437Sluigi * @brief Function to query the fw attributes from the hw
456231437Sluigi * @param sc		software handle to the device
457231437Sluigi * @returns		0 on success, EIO on failure
458231437Sluigi */
459231437Sluigiint
460231437Sluigioce_get_fw_config(POCE_SOFTC sc)
461231437Sluigi{
462231437Sluigi	struct oce_mbx mbx;
463231437Sluigi	struct mbx_common_query_fw_config *fwcmd;
464231437Sluigi	int ret = 0;
465231437Sluigi
466231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
467231437Sluigi
468231437Sluigi	fwcmd = (struct mbx_common_query_fw_config *)&mbx.payload;
469231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
470231437Sluigi				MBX_SUBSYSTEM_COMMON,
471231437Sluigi				OPCODE_COMMON_QUERY_FIRMWARE_CONFIG,
472231437Sluigi				MBX_TIMEOUT_SEC,
473231437Sluigi				sizeof(struct mbx_common_query_fw_config),
474231437Sluigi				OCE_MBX_VER_V0);
475231437Sluigi
476231437Sluigi	mbx.u0.s.embedded = 1;
477231437Sluigi	mbx.payload_length = sizeof(struct mbx_common_query_fw_config);
478231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
479231437Sluigi
480231437Sluigi	ret = oce_mbox_post(sc, &mbx, NULL);
481247880Sdelphij	if (!ret)
482247880Sdelphij                ret = fwcmd->hdr.u0.rsp.status;
483247880Sdelphij	if (ret) {
484247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
485247880Sdelphij			      __FUNCTION__, ret);
486247880Sdelphij		goto error;
487247880Sdelphij	}
488231437Sluigi
489231437Sluigi	DW_SWAP(u32ptr(fwcmd), sizeof(struct mbx_common_query_fw_config));
490231437Sluigi
491231437Sluigi	sc->config_number = fwcmd->params.rsp.config_number;
492231437Sluigi	sc->asic_revision = fwcmd->params.rsp.asic_revision;
493231437Sluigi	sc->port_id	  = fwcmd->params.rsp.port_id;
494231437Sluigi	sc->function_mode = fwcmd->params.rsp.function_mode;
495231437Sluigi	sc->function_caps = fwcmd->params.rsp.function_caps;
496231437Sluigi
497231437Sluigi	if (fwcmd->params.rsp.ulp[0].ulp_mode & ULP_NIC_MODE) {
498231437Sluigi		sc->max_tx_rings = fwcmd->params.rsp.ulp[0].nic_wq_tot;
499231437Sluigi		sc->max_rx_rings = fwcmd->params.rsp.ulp[0].lro_rqid_tot;
500231437Sluigi	} else {
501231437Sluigi		sc->max_tx_rings = fwcmd->params.rsp.ulp[1].nic_wq_tot;
502231437Sluigi		sc->max_rx_rings = fwcmd->params.rsp.ulp[1].lro_rqid_tot;
503231437Sluigi	}
504231437Sluigi
505247880Sdelphijerror:
506247880Sdelphij	return ret;
507231437Sluigi
508231437Sluigi}
509231437Sluigi
510231437Sluigi/**
511231437Sluigi *
512231437Sluigi * @brief function to create a device interface
513231437Sluigi * @param sc		software handle to the device
514231437Sluigi * @param cap_flags	capability flags
515231437Sluigi * @param en_flags	enable capability flags
516231437Sluigi * @param vlan_tag	optional vlan tag to associate with the if
517231437Sluigi * @param mac_addr	pointer to a buffer containing the mac address
518231437Sluigi * @param[out] if_id	[OUTPUT] pointer to an integer to hold the ID of the
519231437Sluigi interface created
520231437Sluigi * @returns		0 on success, EIO on failure
521231437Sluigi */
522231437Sluigiint
523231437Sluigioce_if_create(POCE_SOFTC sc,
524231437Sluigi		uint32_t cap_flags,
525231437Sluigi		uint32_t en_flags,
526231437Sluigi		uint16_t vlan_tag,
527231437Sluigi		uint8_t *mac_addr,
528231437Sluigi		uint32_t *if_id)
529231437Sluigi{
530231437Sluigi	struct oce_mbx mbx;
531231437Sluigi	struct mbx_create_common_iface *fwcmd;
532231437Sluigi	int rc = 0;
533231437Sluigi
534231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
535231437Sluigi
536231437Sluigi	fwcmd = (struct mbx_create_common_iface *)&mbx.payload;
537231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
538231437Sluigi				MBX_SUBSYSTEM_COMMON,
539231437Sluigi				OPCODE_COMMON_CREATE_IFACE,
540231437Sluigi				MBX_TIMEOUT_SEC,
541231437Sluigi				sizeof(struct mbx_create_common_iface),
542231437Sluigi				OCE_MBX_VER_V0);
543231437Sluigi	DW_SWAP(u32ptr(&fwcmd->hdr), sizeof(struct mbx_hdr));
544231437Sluigi
545231437Sluigi	fwcmd->params.req.version = 0;
546231437Sluigi	fwcmd->params.req.cap_flags = LE_32(cap_flags);
547231437Sluigi	fwcmd->params.req.enable_flags = LE_32(en_flags);
548231437Sluigi	if (mac_addr != NULL) {
549231437Sluigi		bcopy(mac_addr, &fwcmd->params.req.mac_addr[0], 6);
550231437Sluigi		fwcmd->params.req.vlan_tag.u0.normal.vtag = LE_16(vlan_tag);
551231437Sluigi		fwcmd->params.req.mac_invalid = 0;
552231437Sluigi	} else {
553231437Sluigi		fwcmd->params.req.mac_invalid = 1;
554231437Sluigi	}
555231437Sluigi
556231437Sluigi	mbx.u0.s.embedded = 1;
557231437Sluigi	mbx.payload_length = sizeof(struct mbx_create_common_iface);
558231437Sluigi	DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ);
559231437Sluigi
560231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
561247880Sdelphij	if (!rc)
562247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
563247880Sdelphij	if (rc) {
564247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
565247880Sdelphij			      __FUNCTION__, rc);
566247880Sdelphij		goto error;
567247880Sdelphij	}
568231437Sluigi
569231437Sluigi	*if_id = LE_32(fwcmd->params.rsp.if_id);
570231437Sluigi
571231437Sluigi	if (mac_addr != NULL)
572231437Sluigi		sc->pmac_id = LE_32(fwcmd->params.rsp.pmac_id);
573247880Sdelphijerror:
574247880Sdelphij	return rc;
575231437Sluigi}
576231437Sluigi
577231437Sluigi/**
578231437Sluigi * @brief		Function to delete an interface
579231437Sluigi * @param sc 		software handle to the device
580231437Sluigi * @param if_id		ID of the interface to delete
581231437Sluigi * @returns		0 on success, EIO on failure
582231437Sluigi */
583231437Sluigiint
584231437Sluigioce_if_del(POCE_SOFTC sc, uint32_t if_id)
585231437Sluigi{
586231437Sluigi	struct oce_mbx mbx;
587231437Sluigi	struct mbx_destroy_common_iface *fwcmd;
588231437Sluigi	int rc = 0;
589231437Sluigi
590231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
591231437Sluigi
592231437Sluigi	fwcmd = (struct mbx_destroy_common_iface *)&mbx.payload;
593231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
594231437Sluigi				MBX_SUBSYSTEM_COMMON,
595231437Sluigi				OPCODE_COMMON_DESTROY_IFACE,
596231437Sluigi				MBX_TIMEOUT_SEC,
597231437Sluigi				sizeof(struct mbx_destroy_common_iface),
598231437Sluigi				OCE_MBX_VER_V0);
599231437Sluigi
600231437Sluigi	fwcmd->params.req.if_id = if_id;
601231437Sluigi
602231437Sluigi	mbx.u0.s.embedded = 1;
603231437Sluigi	mbx.payload_length = sizeof(struct mbx_destroy_common_iface);
604231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
605231437Sluigi
606231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
607247880Sdelphij	if (!rc)
608247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
609247880Sdelphij	if (rc)
610247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
611247880Sdelphij			      __FUNCTION__, rc);
612231437Sluigi	return rc;
613231437Sluigi}
614231437Sluigi
615231437Sluigi/**
616231437Sluigi * @brief Function to send the mbx command to configure vlan
617231437Sluigi * @param sc 		software handle to the device
618231437Sluigi * @param if_id 	interface identifier index
619231437Sluigi * @param vtag_arr	array of vlan tags
620231437Sluigi * @param vtag_cnt	number of elements in array
621231437Sluigi * @param untagged	boolean TRUE/FLASE
622231437Sluigi * @param enable_promisc flag to enable/disable VLAN promiscuous mode
623231437Sluigi * @returns		0 on success, EIO on failure
624231437Sluigi */
625231437Sluigiint
626231437Sluigioce_config_vlan(POCE_SOFTC sc,
627231437Sluigi		uint32_t if_id,
628231437Sluigi		struct normal_vlan *vtag_arr,
629231437Sluigi		uint8_t vtag_cnt, uint32_t untagged, uint32_t enable_promisc)
630231437Sluigi{
631231437Sluigi	struct oce_mbx mbx;
632231437Sluigi	struct mbx_common_config_vlan *fwcmd;
633231437Sluigi	int rc;
634231437Sluigi
635231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
636231437Sluigi	fwcmd = (struct mbx_common_config_vlan *)&mbx.payload;
637231437Sluigi
638231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
639231437Sluigi				MBX_SUBSYSTEM_COMMON,
640231437Sluigi				OPCODE_COMMON_CONFIG_IFACE_VLAN,
641231437Sluigi				MBX_TIMEOUT_SEC,
642231437Sluigi				sizeof(struct mbx_common_config_vlan),
643231437Sluigi				OCE_MBX_VER_V0);
644231437Sluigi
645231437Sluigi	fwcmd->params.req.if_id = (uint8_t) if_id;
646231437Sluigi	fwcmd->params.req.promisc = (uint8_t) enable_promisc;
647231437Sluigi	fwcmd->params.req.untagged = (uint8_t) untagged;
648231437Sluigi	fwcmd->params.req.num_vlans = vtag_cnt;
649231437Sluigi
650231437Sluigi	if (!enable_promisc) {
651231437Sluigi		bcopy(vtag_arr, fwcmd->params.req.tags.normal_vlans,
652231437Sluigi			vtag_cnt * sizeof(struct normal_vlan));
653231437Sluigi	}
654231437Sluigi	mbx.u0.s.embedded = 1;
655231437Sluigi	mbx.payload_length = sizeof(struct mbx_common_config_vlan);
656231437Sluigi	DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + mbx.payload_length));
657231437Sluigi
658231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
659247880Sdelphij	if (!rc)
660247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
661247880Sdelphij	if (rc)
662247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
663247880Sdelphij			      __FUNCTION__, rc);
664247880Sdelphij	return 0;
665231437Sluigi
666231437Sluigi}
667231437Sluigi
668231437Sluigi/**
669231437Sluigi * @brief Function to set flow control capability in the hardware
670231437Sluigi * @param sc 		software handle to the device
671231437Sluigi * @param flow_control	flow control flags to set
672231437Sluigi * @returns		0 on success, EIO on failure
673231437Sluigi */
674231437Sluigiint
675231437Sluigioce_set_flow_control(POCE_SOFTC sc, uint32_t flow_control)
676231437Sluigi{
677231437Sluigi	struct oce_mbx mbx;
678231437Sluigi	struct mbx_common_get_set_flow_control *fwcmd =
679231437Sluigi		(struct mbx_common_get_set_flow_control *)&mbx.payload;
680231437Sluigi	int rc;
681231437Sluigi
682231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
683231437Sluigi
684231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
685231437Sluigi				MBX_SUBSYSTEM_COMMON,
686231437Sluigi				OPCODE_COMMON_SET_FLOW_CONTROL,
687231437Sluigi				MBX_TIMEOUT_SEC,
688231437Sluigi				sizeof(struct mbx_common_get_set_flow_control),
689231437Sluigi				OCE_MBX_VER_V0);
690231437Sluigi
691231437Sluigi	if (flow_control & OCE_FC_TX)
692231437Sluigi		fwcmd->tx_flow_control = 1;
693231437Sluigi
694231437Sluigi	if (flow_control & OCE_FC_RX)
695231437Sluigi		fwcmd->rx_flow_control = 1;
696231437Sluigi
697231437Sluigi	mbx.u0.s.embedded = 1;
698231437Sluigi	mbx.payload_length = sizeof(struct mbx_common_get_set_flow_control);
699231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
700231437Sluigi
701231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
702247880Sdelphij	if (!rc)
703247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
704247880Sdelphij	if (rc)
705247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
706247880Sdelphij			      __FUNCTION__, rc);
707231437Sluigi	return rc;
708231437Sluigi}
709231437Sluigi
710231437Sluigi/**
711231437Sluigi * @brief Initialize the RSS CPU indirection table
712231437Sluigi *
713231437Sluigi * The table is used to choose the queue to place the incomming packets.
714231437Sluigi * Incomming packets are hashed.  The lowest bits in the hash result
715231437Sluigi * are used as the index into the CPU indirection table.
716231437Sluigi * Each entry in the table contains the RSS CPU-ID returned by the NIC
717231437Sluigi * create.  Based on the CPU ID, the receive completion is routed to
718231437Sluigi * the corresponding RSS CQs.  (Non-RSS packets are always completed
719231437Sluigi * on the default (0) CQ).
720231437Sluigi *
721231437Sluigi * @param sc 		software handle to the device
722231437Sluigi * @param *fwcmd	pointer to the rss mbox command
723231437Sluigi * @returns		none
724231437Sluigi */
725231437Sluigistatic int
726231437Sluigioce_rss_itbl_init(POCE_SOFTC sc, struct mbx_config_nic_rss *fwcmd)
727231437Sluigi{
728231437Sluigi	int i = 0, j = 0, rc = 0;
729231437Sluigi	uint8_t *tbl = fwcmd->params.req.cputable;
730252869Sdelphij	struct oce_rq *rq = NULL;
731231437Sluigi
732231437Sluigi
733252869Sdelphij	for (j = 0; j < INDIRECTION_TABLE_ENTRIES ; j += (sc->nrqs - 1)) {
734252869Sdelphij		for_all_rss_queues(sc, rq, i) {
735252869Sdelphij			if ((j + i) >= INDIRECTION_TABLE_ENTRIES)
736252869Sdelphij				break;
737252869Sdelphij			tbl[j + i] = rq->rss_cpuid;
738231437Sluigi		}
739231437Sluigi	}
740231437Sluigi	if (i == 0) {
741231437Sluigi		device_printf(sc->dev, "error: Invalid number of RSS RQ's\n");
742231437Sluigi		rc = ENXIO;
743231437Sluigi
744231437Sluigi	}
745231437Sluigi
746231437Sluigi	/* fill log2 value indicating the size of the CPU table */
747231437Sluigi	if (rc == 0)
748231437Sluigi		fwcmd->params.req.cpu_tbl_sz_log2 = LE_16(OCE_LOG2(i));
749231437Sluigi
750231437Sluigi	return rc;
751231437Sluigi}
752231437Sluigi
753231437Sluigi/**
754231437Sluigi * @brief Function to set flow control capability in the hardware
755231437Sluigi * @param sc 		software handle to the device
756231437Sluigi * @param if_id 	interface id to read the address from
757231437Sluigi * @param enable_rss	0=disable, RSS_ENABLE_xxx flags otherwise
758231437Sluigi * @returns		0 on success, EIO on failure
759231437Sluigi */
760231437Sluigiint
761231437Sluigioce_config_nic_rss(POCE_SOFTC sc, uint32_t if_id, uint16_t enable_rss)
762231437Sluigi{
763231437Sluigi	int rc;
764231437Sluigi	struct oce_mbx mbx;
765231437Sluigi	struct mbx_config_nic_rss *fwcmd =
766231437Sluigi				(struct mbx_config_nic_rss *)&mbx.payload;
767247880Sdelphij	int version;
768231437Sluigi
769231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
770231437Sluigi
771252869Sdelphij	if (IS_XE201(sc) || IS_SH(sc)) {
772247880Sdelphij		version = OCE_MBX_VER_V1;
773247880Sdelphij		fwcmd->params.req.enable_rss = RSS_ENABLE_UDP_IPV4 |
774247880Sdelphij					       RSS_ENABLE_UDP_IPV6;
775247880Sdelphij	} else
776247880Sdelphij		version = OCE_MBX_VER_V0;
777247880Sdelphij
778231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
779231437Sluigi				MBX_SUBSYSTEM_NIC,
780231437Sluigi				NIC_CONFIG_RSS,
781231437Sluigi				MBX_TIMEOUT_SEC,
782231437Sluigi				sizeof(struct mbx_config_nic_rss),
783247880Sdelphij				version);
784231437Sluigi	if (enable_rss)
785247880Sdelphij		fwcmd->params.req.enable_rss |= (RSS_ENABLE_IPV4 |
786247880Sdelphij					         RSS_ENABLE_TCP_IPV4 |
787247880Sdelphij						 RSS_ENABLE_IPV6 |
788247880Sdelphij						 RSS_ENABLE_TCP_IPV6);
789231437Sluigi	fwcmd->params.req.flush = OCE_FLUSH;
790231437Sluigi	fwcmd->params.req.if_id = LE_32(if_id);
791231437Sluigi
792231437Sluigi	srandom(arc4random());	/* random entropy seed */
793231437Sluigi	read_random(fwcmd->params.req.hash, sizeof(fwcmd->params.req.hash));
794231437Sluigi
795231437Sluigi	rc = oce_rss_itbl_init(sc, fwcmd);
796231437Sluigi	if (rc == 0) {
797231437Sluigi		mbx.u0.s.embedded = 1;
798231437Sluigi		mbx.payload_length = sizeof(struct mbx_config_nic_rss);
799231437Sluigi		DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
800231437Sluigi
801231437Sluigi		rc = oce_mbox_post(sc, &mbx, NULL);
802247880Sdelphij		if (!rc)
803247880Sdelphij                	rc = fwcmd->hdr.u0.rsp.status;
804247880Sdelphij		if (rc)
805247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
806247880Sdelphij			      __FUNCTION__, rc);
807231437Sluigi	}
808231437Sluigi	return rc;
809231437Sluigi}
810231437Sluigi
811231437Sluigi/**
812231437Sluigi * @brief 		RXF function to enable/disable device promiscuous mode
813231437Sluigi * @param sc		software handle to the device
814231437Sluigi * @param enable	enable/disable flag
815231437Sluigi * @returns		0 on success, EIO on failure
816231437Sluigi * @note
817231437Sluigi *	The NIC_CONFIG_PROMISCUOUS command deprecated for Lancer.
818231437Sluigi *	This function uses the COMMON_SET_IFACE_RX_FILTER command instead.
819231437Sluigi */
820231437Sluigiint
821231437Sluigioce_rxf_set_promiscuous(POCE_SOFTC sc, uint32_t enable)
822231437Sluigi{
823231437Sluigi	struct mbx_set_common_iface_rx_filter *fwcmd;
824231437Sluigi	int sz = sizeof(struct mbx_set_common_iface_rx_filter);
825231437Sluigi	iface_rx_filter_ctx_t *req;
826231437Sluigi	OCE_DMA_MEM sgl;
827231437Sluigi	int rc;
828231437Sluigi
829231437Sluigi	/* allocate mbx payload's dma scatter/gather memory */
830231437Sluigi	rc = oce_dma_alloc(sc, sz, &sgl, 0);
831231437Sluigi	if (rc)
832231437Sluigi		return rc;
833231437Sluigi
834231437Sluigi	fwcmd = OCE_DMAPTR(&sgl, struct mbx_set_common_iface_rx_filter);
835231437Sluigi
836231437Sluigi	req =  &fwcmd->params.req;
837231437Sluigi	req->iface_flags_mask = MBX_RX_IFACE_FLAGS_PROMISCUOUS |
838231437Sluigi				MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS;
839231437Sluigi	if (enable) {
840231437Sluigi		req->iface_flags = MBX_RX_IFACE_FLAGS_PROMISCUOUS |
841231437Sluigi				   MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS;
842231437Sluigi	}
843231437Sluigi	req->if_id = sc->if_id;
844231437Sluigi
845231437Sluigi	rc = oce_set_common_iface_rx_filter(sc, &sgl);
846231437Sluigi	oce_dma_free(sc, &sgl);
847231437Sluigi
848231437Sluigi	return rc;
849231437Sluigi}
850231437Sluigi
851231437Sluigi
852231437Sluigi/**
853231437Sluigi * @brief 			Function modify and select rx filter options
854231437Sluigi * @param sc			software handle to the device
855231437Sluigi * @param sgl			scatter/gather request/response
856231437Sluigi * @returns			0 on success, error code on failure
857231437Sluigi */
858231437Sluigiint
859231437Sluigioce_set_common_iface_rx_filter(POCE_SOFTC sc, POCE_DMA_MEM sgl)
860231437Sluigi{
861231437Sluigi	struct oce_mbx mbx;
862231437Sluigi	int mbx_sz = sizeof(struct mbx_set_common_iface_rx_filter);
863231437Sluigi	struct mbx_set_common_iface_rx_filter *fwcmd;
864231437Sluigi	int rc;
865231437Sluigi
866231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
867231437Sluigi	fwcmd = OCE_DMAPTR(sgl, struct mbx_set_common_iface_rx_filter);
868231437Sluigi
869231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
870231437Sluigi				MBX_SUBSYSTEM_COMMON,
871231437Sluigi				OPCODE_COMMON_SET_IFACE_RX_FILTER,
872231437Sluigi				MBX_TIMEOUT_SEC,
873231437Sluigi				mbx_sz,
874231437Sluigi				OCE_MBX_VER_V0);
875231437Sluigi
876231437Sluigi	oce_dma_sync(sgl, BUS_DMASYNC_PREWRITE);
877231437Sluigi	mbx.u0.s.embedded = 0;
878231437Sluigi	mbx.u0.s.sge_count = 1;
879231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(sgl->paddr);
880231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(sgl->paddr);
881231437Sluigi	mbx.payload.u0.u1.sgl[0].length = mbx_sz;
882231437Sluigi	mbx.payload_length = mbx_sz;
883231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
884231437Sluigi
885231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
886247880Sdelphij	if (!rc)
887247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
888247880Sdelphij	if (rc)
889247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
890247880Sdelphij			      __FUNCTION__, rc);
891247880Sdelphij	return 0;
892231437Sluigi}
893231437Sluigi
894231437Sluigi/**
895231437Sluigi * @brief Function to query the link status from the hardware
896231437Sluigi * @param sc 		software handle to the device
897231437Sluigi * @param[out] link	pointer to the structure returning link attributes
898231437Sluigi * @returns		0 on success, EIO on failure
899231437Sluigi */
900231437Sluigiint
901231437Sluigioce_get_link_status(POCE_SOFTC sc, struct link_status *link)
902231437Sluigi{
903231437Sluigi	struct oce_mbx mbx;
904231437Sluigi	struct mbx_query_common_link_config *fwcmd;
905247880Sdelphij	int rc = 0, version;
906231437Sluigi
907231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
908231437Sluigi
909247880Sdelphij	IS_XE201(sc) ? (version = OCE_MBX_VER_V1) : (version = OCE_MBX_VER_V0);
910247880Sdelphij
911231437Sluigi	fwcmd = (struct mbx_query_common_link_config *)&mbx.payload;
912231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
913231437Sluigi				MBX_SUBSYSTEM_COMMON,
914231437Sluigi				OPCODE_COMMON_QUERY_LINK_CONFIG,
915231437Sluigi				MBX_TIMEOUT_SEC,
916231437Sluigi				sizeof(struct mbx_query_common_link_config),
917247880Sdelphij				version);
918231437Sluigi
919231437Sluigi	mbx.u0.s.embedded = 1;
920231437Sluigi	mbx.payload_length = sizeof(struct mbx_query_common_link_config);
921231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
922231437Sluigi
923231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
924231437Sluigi
925247880Sdelphij	if (!rc)
926247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
927231437Sluigi	if (rc) {
928247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
929247880Sdelphij			      __FUNCTION__, rc);
930247880Sdelphij		goto error;
931231437Sluigi	}
932247880Sdelphij	/* interpret response */
933247880Sdelphij	bcopy(&fwcmd->params.rsp, link, sizeof(struct link_status));
934247880Sdelphij	link->logical_link_status = LE_32(link->logical_link_status);
935247880Sdelphij	link->qos_link_speed = LE_16(link->qos_link_speed);
936247880Sdelphijerror:
937231437Sluigi	return rc;
938231437Sluigi}
939231437Sluigi
940231437Sluigi
941231437Sluigi
942231437Sluigiint
943231437Sluigioce_mbox_get_nic_stats_v0(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem)
944231437Sluigi{
945231437Sluigi	struct oce_mbx mbx;
946231437Sluigi	struct mbx_get_nic_stats_v0 *fwcmd;
947231437Sluigi	int rc = 0;
948231437Sluigi
949231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
950231437Sluigi
951231437Sluigi	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_nic_stats_v0);
952231437Sluigi	bzero(fwcmd, sizeof(struct mbx_get_nic_stats_v0));
953231437Sluigi
954231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
955231437Sluigi				MBX_SUBSYSTEM_NIC,
956231437Sluigi				NIC_GET_STATS,
957231437Sluigi				MBX_TIMEOUT_SEC,
958231437Sluigi				sizeof(struct mbx_get_nic_stats_v0),
959231437Sluigi				OCE_MBX_VER_V0);
960231437Sluigi
961231437Sluigi	mbx.u0.s.embedded = 0;
962231437Sluigi	mbx.u0.s.sge_count = 1;
963231437Sluigi
964231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
965231437Sluigi
966231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
967231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
968231437Sluigi	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_nic_stats_v0);
969231437Sluigi
970231437Sluigi	mbx.payload_length = sizeof(struct mbx_get_nic_stats_v0);
971231437Sluigi
972231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
973231437Sluigi
974231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
975231437Sluigi
976231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
977231437Sluigi
978247880Sdelphij	if (!rc)
979247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
980247880Sdelphij	if (rc)
981247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
982247880Sdelphij			      __FUNCTION__, rc);
983231437Sluigi	return rc;
984231437Sluigi}
985231437Sluigi
986231437Sluigi
987231437Sluigi
988231437Sluigi/**
989231437Sluigi * @brief Function to get NIC statistics
990231437Sluigi * @param sc 		software handle to the device
991231437Sluigi * @param *stats	pointer to where to store statistics
992231437Sluigi * @param reset_stats	resets statistics of set
993231437Sluigi * @returns		0 on success, EIO on failure
994231437Sluigi * @note		command depricated in Lancer
995231437Sluigi */
996231437Sluigiint
997231437Sluigioce_mbox_get_nic_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem)
998231437Sluigi{
999231437Sluigi	struct oce_mbx mbx;
1000231437Sluigi	struct mbx_get_nic_stats *fwcmd;
1001231437Sluigi	int rc = 0;
1002231437Sluigi
1003231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1004231437Sluigi	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_nic_stats);
1005231437Sluigi	bzero(fwcmd, sizeof(struct mbx_get_nic_stats));
1006231437Sluigi
1007231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1008231437Sluigi				MBX_SUBSYSTEM_NIC,
1009231437Sluigi				NIC_GET_STATS,
1010231437Sluigi				MBX_TIMEOUT_SEC,
1011231437Sluigi				sizeof(struct mbx_get_nic_stats),
1012231437Sluigi				OCE_MBX_VER_V1);
1013231437Sluigi
1014231437Sluigi
1015231437Sluigi	mbx.u0.s.embedded = 0;  /* stats too large for embedded mbx rsp */
1016231437Sluigi	mbx.u0.s.sge_count = 1; /* using scatter gather instead */
1017231437Sluigi
1018231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
1019231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
1020231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
1021231437Sluigi	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_nic_stats);
1022231437Sluigi
1023231437Sluigi	mbx.payload_length = sizeof(struct mbx_get_nic_stats);
1024231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1025231437Sluigi
1026231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1027231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
1028247880Sdelphij	if (!rc)
1029247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1030247880Sdelphij	if (rc)
1031247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1032247880Sdelphij			      __FUNCTION__, rc);
1033231437Sluigi	return rc;
1034231437Sluigi}
1035231437Sluigi
1036231437Sluigi
1037231437Sluigi/**
1038231437Sluigi * @brief Function to get pport (physical port) statistics
1039231437Sluigi * @param sc 		software handle to the device
1040231437Sluigi * @param *stats	pointer to where to store statistics
1041231437Sluigi * @param reset_stats	resets statistics of set
1042231437Sluigi * @returns		0 on success, EIO on failure
1043231437Sluigi */
1044231437Sluigiint
1045231437Sluigioce_mbox_get_pport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem,
1046231437Sluigi				uint32_t reset_stats)
1047231437Sluigi{
1048231437Sluigi	struct oce_mbx mbx;
1049231437Sluigi	struct mbx_get_pport_stats *fwcmd;
1050231437Sluigi	int rc = 0;
1051231437Sluigi
1052231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1053231437Sluigi	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_pport_stats);
1054231437Sluigi	bzero(fwcmd, sizeof(struct mbx_get_pport_stats));
1055231437Sluigi
1056231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1057231437Sluigi				MBX_SUBSYSTEM_NIC,
1058231437Sluigi				NIC_GET_PPORT_STATS,
1059231437Sluigi				MBX_TIMEOUT_SEC,
1060231437Sluigi				sizeof(struct mbx_get_pport_stats),
1061231437Sluigi				OCE_MBX_VER_V0);
1062231437Sluigi
1063231437Sluigi	fwcmd->params.req.reset_stats = reset_stats;
1064247880Sdelphij	fwcmd->params.req.port_number = sc->port_id;
1065231437Sluigi
1066231437Sluigi	mbx.u0.s.embedded = 0;	/* stats too large for embedded mbx rsp */
1067231437Sluigi	mbx.u0.s.sge_count = 1; /* using scatter gather instead */
1068231437Sluigi
1069231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
1070231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
1071231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
1072231437Sluigi	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_pport_stats);
1073231437Sluigi
1074231437Sluigi	mbx.payload_length = sizeof(struct mbx_get_pport_stats);
1075231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1076231437Sluigi
1077231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1078231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
1079231437Sluigi
1080247880Sdelphij	if (!rc)
1081247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1082247880Sdelphij	if (rc)
1083247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1084247880Sdelphij			      __FUNCTION__, rc);
1085231437Sluigi	return rc;
1086231437Sluigi}
1087231437Sluigi
1088231437Sluigi
1089231437Sluigi/**
1090231437Sluigi * @brief Function to get vport (virtual port) statistics
1091231437Sluigi * @param sc 		software handle to the device
1092231437Sluigi * @param *stats	pointer to where to store statistics
1093231437Sluigi * @param reset_stats	resets statistics of set
1094231437Sluigi * @returns		0 on success, EIO on failure
1095231437Sluigi */
1096231437Sluigiint
1097231437Sluigioce_mbox_get_vport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem,
1098231437Sluigi				uint32_t req_size, uint32_t reset_stats)
1099231437Sluigi{
1100231437Sluigi	struct oce_mbx mbx;
1101231437Sluigi	struct mbx_get_vport_stats *fwcmd;
1102231437Sluigi	int rc = 0;
1103231437Sluigi
1104231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1105231437Sluigi
1106231437Sluigi	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_vport_stats);
1107231437Sluigi	bzero(fwcmd, sizeof(struct mbx_get_vport_stats));
1108231437Sluigi
1109231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1110231437Sluigi				MBX_SUBSYSTEM_NIC,
1111231437Sluigi				NIC_GET_VPORT_STATS,
1112231437Sluigi				MBX_TIMEOUT_SEC,
1113231437Sluigi				sizeof(struct mbx_get_vport_stats),
1114231437Sluigi				OCE_MBX_VER_V0);
1115231437Sluigi
1116231437Sluigi	fwcmd->params.req.reset_stats = reset_stats;
1117231437Sluigi	fwcmd->params.req.vport_number = sc->if_id;
1118231437Sluigi
1119231437Sluigi	mbx.u0.s.embedded = 0;	/* stats too large for embedded mbx rsp */
1120231437Sluigi	mbx.u0.s.sge_count = 1; /* using scatter gather instead */
1121231437Sluigi
1122231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
1123231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
1124231437Sluigi	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
1125231437Sluigi	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_vport_stats);
1126231437Sluigi
1127231437Sluigi	mbx.payload_length = sizeof(struct mbx_get_vport_stats);
1128231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1129231437Sluigi
1130231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1131231437Sluigi	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
1132231437Sluigi
1133247880Sdelphij	if (!rc)
1134247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1135247880Sdelphij	if (rc)
1136247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1137247880Sdelphij			      __FUNCTION__, rc);
1138231437Sluigi	return rc;
1139231437Sluigi}
1140231437Sluigi
1141231437Sluigi
1142231437Sluigi/**
1143231437Sluigi * @brief               Function to update the muticast filter with
1144231437Sluigi *                      values in dma_mem
1145231437Sluigi * @param sc            software handle to the device
1146231437Sluigi * @param dma_mem       pointer to dma memory region
1147231437Sluigi * @returns             0 on success, EIO on failure
1148231437Sluigi */
1149231437Sluigiint
1150231437Sluigioce_update_multicast(POCE_SOFTC sc, POCE_DMA_MEM pdma_mem)
1151231437Sluigi{
1152231437Sluigi	struct oce_mbx mbx;
1153231437Sluigi	struct oce_mq_sge *sgl;
1154231437Sluigi	struct mbx_set_common_iface_multicast *req = NULL;
1155231437Sluigi	int rc = 0;
1156231437Sluigi
1157231437Sluigi	req = OCE_DMAPTR(pdma_mem, struct mbx_set_common_iface_multicast);
1158231437Sluigi	mbx_common_req_hdr_init(&req->hdr, 0, 0,
1159231437Sluigi				MBX_SUBSYSTEM_COMMON,
1160231437Sluigi				OPCODE_COMMON_SET_IFACE_MULTICAST,
1161231437Sluigi				MBX_TIMEOUT_SEC,
1162231437Sluigi				sizeof(struct mbx_set_common_iface_multicast),
1163231437Sluigi				OCE_MBX_VER_V0);
1164231437Sluigi
1165231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1166231437Sluigi
1167231437Sluigi	mbx.u0.s.embedded = 0; /*Non embeded*/
1168231437Sluigi	mbx.payload_length = sizeof(struct mbx_set_common_iface_multicast);
1169231437Sluigi	mbx.u0.s.sge_count = 1;
1170231437Sluigi	sgl = &mbx.payload.u0.u1.sgl[0];
1171231437Sluigi	sgl->pa_hi = htole32(upper_32_bits(pdma_mem->paddr));
1172231437Sluigi	sgl->pa_lo = htole32((pdma_mem->paddr) & 0xFFFFFFFF);
1173231437Sluigi	sgl->length = htole32(mbx.payload_length);
1174231437Sluigi
1175231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1176231437Sluigi
1177231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1178247880Sdelphij	if (!rc)
1179247880Sdelphij                rc = req->hdr.u0.rsp.status;
1180247880Sdelphij	if (rc)
1181247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1182247880Sdelphij			      __FUNCTION__, rc);
1183231437Sluigi	return rc;
1184231437Sluigi}
1185231437Sluigi
1186231437Sluigi
1187231437Sluigi/**
1188231437Sluigi * @brief               Function to send passthrough Ioctls
1189231437Sluigi * @param sc            software handle to the device
1190231437Sluigi * @param dma_mem       pointer to dma memory region
1191231437Sluigi * @param req_size      size of dma_mem
1192231437Sluigi * @returns             0 on success, EIO on failure
1193231437Sluigi */
1194231437Sluigiint
1195231437Sluigioce_pass_through_mbox(POCE_SOFTC sc, POCE_DMA_MEM dma_mem, uint32_t req_size)
1196231437Sluigi{
1197231437Sluigi	struct oce_mbx mbx;
1198231437Sluigi	struct oce_mq_sge *sgl;
1199231437Sluigi	int rc = 0;
1200231437Sluigi
1201231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1202231437Sluigi
1203231437Sluigi	mbx.u0.s.embedded  = 0; /*Non embeded*/
1204231437Sluigi	mbx.payload_length = req_size;
1205231437Sluigi	mbx.u0.s.sge_count = 1;
1206231437Sluigi	sgl = &mbx.payload.u0.u1.sgl[0];
1207231437Sluigi	sgl->pa_hi = htole32(upper_32_bits(dma_mem->paddr));
1208231437Sluigi	sgl->pa_lo = htole32((dma_mem->paddr) & 0xFFFFFFFF);
1209231437Sluigi	sgl->length = htole32(req_size);
1210231437Sluigi
1211231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1212231437Sluigi
1213231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1214231437Sluigi	return rc;
1215231437Sluigi}
1216231437Sluigi
1217231437Sluigi
1218231437Sluigiint
1219231437Sluigioce_mbox_macaddr_add(POCE_SOFTC sc, uint8_t *mac_addr,
1220231437Sluigi		 uint32_t if_id, uint32_t *pmac_id)
1221231437Sluigi{
1222231437Sluigi	struct oce_mbx mbx;
1223231437Sluigi	struct mbx_add_common_iface_mac *fwcmd;
1224231437Sluigi	int rc = 0;
1225231437Sluigi
1226231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1227231437Sluigi
1228231437Sluigi	fwcmd = (struct mbx_add_common_iface_mac *)&mbx.payload;
1229231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1230231437Sluigi				MBX_SUBSYSTEM_COMMON,
1231231437Sluigi				OPCODE_COMMON_ADD_IFACE_MAC,
1232231437Sluigi				MBX_TIMEOUT_SEC,
1233231437Sluigi				sizeof(struct mbx_add_common_iface_mac),
1234231437Sluigi				OCE_MBX_VER_V0);
1235231437Sluigi
1236231437Sluigi	fwcmd->params.req.if_id = (uint16_t) if_id;
1237231437Sluigi	bcopy(mac_addr, fwcmd->params.req.mac_address, 6);
1238231437Sluigi
1239231437Sluigi	mbx.u0.s.embedded = 1;
1240231437Sluigi	mbx.payload_length = sizeof(struct  mbx_add_common_iface_mac);
1241231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1242231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1243247880Sdelphij	if (!rc)
1244247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1245247880Sdelphij	if (rc) {
1246247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1247247880Sdelphij			      __FUNCTION__, rc);
1248247880Sdelphij		goto error;
1249247880Sdelphij	}
1250231437Sluigi	*pmac_id = fwcmd->params.rsp.pmac_id;
1251247880Sdelphijerror:
1252231437Sluigi	return rc;
1253231437Sluigi}
1254231437Sluigi
1255231437Sluigi
1256231437Sluigiint
1257231437Sluigioce_mbox_macaddr_del(POCE_SOFTC sc, uint32_t if_id, uint32_t pmac_id)
1258231437Sluigi{
1259231437Sluigi	struct oce_mbx mbx;
1260231437Sluigi	struct mbx_del_common_iface_mac *fwcmd;
1261231437Sluigi	int rc = 0;
1262231437Sluigi
1263231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1264231437Sluigi
1265231437Sluigi	fwcmd = (struct mbx_del_common_iface_mac *)&mbx.payload;
1266231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1267231437Sluigi				MBX_SUBSYSTEM_COMMON,
1268231437Sluigi				OPCODE_COMMON_DEL_IFACE_MAC,
1269231437Sluigi				MBX_TIMEOUT_SEC,
1270231437Sluigi				sizeof(struct mbx_del_common_iface_mac),
1271231437Sluigi				OCE_MBX_VER_V0);
1272231437Sluigi
1273231437Sluigi	fwcmd->params.req.if_id = (uint16_t)if_id;
1274231437Sluigi	fwcmd->params.req.pmac_id = pmac_id;
1275231437Sluigi
1276231437Sluigi	mbx.u0.s.embedded = 1;
1277231437Sluigi	mbx.payload_length = sizeof(struct  mbx_del_common_iface_mac);
1278231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1279231437Sluigi
1280231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1281247880Sdelphij	if (!rc)
1282247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1283247880Sdelphij	if (rc)
1284247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1285247880Sdelphij			      __FUNCTION__, rc);
1286231437Sluigi	return rc;
1287231437Sluigi}
1288231437Sluigi
1289231437Sluigi
1290231437Sluigi
1291231437Sluigiint
1292231437Sluigioce_mbox_check_native_mode(POCE_SOFTC sc)
1293231437Sluigi{
1294231437Sluigi	struct oce_mbx mbx;
1295231437Sluigi	struct mbx_common_set_function_cap *fwcmd;
1296231437Sluigi	int rc = 0;
1297231437Sluigi
1298231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1299231437Sluigi
1300231437Sluigi	fwcmd = (struct mbx_common_set_function_cap *)&mbx.payload;
1301231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1302231437Sluigi				MBX_SUBSYSTEM_COMMON,
1303231437Sluigi				OPCODE_COMMON_SET_FUNCTIONAL_CAPS,
1304231437Sluigi				MBX_TIMEOUT_SEC,
1305231437Sluigi				sizeof(struct mbx_common_set_function_cap),
1306231437Sluigi				OCE_MBX_VER_V0);
1307231437Sluigi
1308231437Sluigi	fwcmd->params.req.valid_capability_flags = CAP_SW_TIMESTAMPS |
1309231437Sluigi							CAP_BE3_NATIVE_ERX_API;
1310231437Sluigi
1311231437Sluigi	fwcmd->params.req.capability_flags = CAP_BE3_NATIVE_ERX_API;
1312231437Sluigi
1313231437Sluigi	mbx.u0.s.embedded = 1;
1314231437Sluigi	mbx.payload_length = sizeof(struct mbx_common_set_function_cap);
1315231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1316231437Sluigi
1317231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1318247880Sdelphij	if (!rc)
1319247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1320247880Sdelphij	if (rc) {
1321247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1322247880Sdelphij			      __FUNCTION__, rc);
1323247880Sdelphij		goto error;
1324247880Sdelphij	}
1325231437Sluigi	sc->be3_native = fwcmd->params.rsp.capability_flags
1326231437Sluigi			& CAP_BE3_NATIVE_ERX_API;
1327231437Sluigi
1328247880Sdelphijerror:
1329231437Sluigi	return 0;
1330231437Sluigi}
1331231437Sluigi
1332231437Sluigi
1333231437Sluigi
1334231437Sluigiint
1335231437Sluigioce_mbox_cmd_set_loopback(POCE_SOFTC sc, uint8_t port_num,
1336231437Sluigi		uint8_t loopback_type, uint8_t enable)
1337231437Sluigi{
1338231437Sluigi	struct oce_mbx mbx;
1339231437Sluigi	struct mbx_lowlevel_set_loopback_mode *fwcmd;
1340231437Sluigi	int rc = 0;
1341231437Sluigi
1342231437Sluigi
1343231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1344231437Sluigi
1345231437Sluigi	fwcmd = (struct mbx_lowlevel_set_loopback_mode *)&mbx.payload;
1346231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1347231437Sluigi				MBX_SUBSYSTEM_LOWLEVEL,
1348231437Sluigi				OPCODE_LOWLEVEL_SET_LOOPBACK_MODE,
1349231437Sluigi				MBX_TIMEOUT_SEC,
1350231437Sluigi				sizeof(struct mbx_lowlevel_set_loopback_mode),
1351231437Sluigi				OCE_MBX_VER_V0);
1352231437Sluigi
1353231437Sluigi	fwcmd->params.req.src_port = port_num;
1354231437Sluigi	fwcmd->params.req.dest_port = port_num;
1355231437Sluigi	fwcmd->params.req.loopback_type = loopback_type;
1356231437Sluigi	fwcmd->params.req.loopback_state = enable;
1357231437Sluigi
1358231437Sluigi	mbx.u0.s.embedded = 1;
1359231437Sluigi	mbx.payload_length = sizeof(struct  mbx_lowlevel_set_loopback_mode);
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)
1366247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1367247880Sdelphij			      __FUNCTION__, rc);
1368231437Sluigi
1369231437Sluigi	return rc;
1370231437Sluigi
1371231437Sluigi}
1372231437Sluigi
1373231437Sluigiint
1374231437Sluigioce_mbox_cmd_test_loopback(POCE_SOFTC sc, uint32_t port_num,
1375231437Sluigi	uint32_t loopback_type, uint32_t pkt_size, uint32_t num_pkts,
1376231437Sluigi	uint64_t pattern)
1377231437Sluigi{
1378231437Sluigi
1379231437Sluigi	struct oce_mbx mbx;
1380231437Sluigi	struct mbx_lowlevel_test_loopback_mode *fwcmd;
1381231437Sluigi	int rc = 0;
1382231437Sluigi
1383231437Sluigi
1384231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1385231437Sluigi
1386231437Sluigi	fwcmd = (struct mbx_lowlevel_test_loopback_mode *)&mbx.payload;
1387231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1388231437Sluigi				MBX_SUBSYSTEM_LOWLEVEL,
1389231437Sluigi				OPCODE_LOWLEVEL_TEST_LOOPBACK,
1390231437Sluigi				MBX_TIMEOUT_SEC,
1391231437Sluigi				sizeof(struct mbx_lowlevel_test_loopback_mode),
1392231437Sluigi				OCE_MBX_VER_V0);
1393231437Sluigi
1394231437Sluigi	fwcmd->params.req.pattern = pattern;
1395231437Sluigi	fwcmd->params.req.src_port = port_num;
1396231437Sluigi	fwcmd->params.req.dest_port = port_num;
1397231437Sluigi	fwcmd->params.req.pkt_size = pkt_size;
1398231437Sluigi	fwcmd->params.req.num_pkts = num_pkts;
1399231437Sluigi	fwcmd->params.req.loopback_type = loopback_type;
1400231437Sluigi
1401231437Sluigi	mbx.u0.s.embedded = 1;
1402231437Sluigi	mbx.payload_length = sizeof(struct  mbx_lowlevel_test_loopback_mode);
1403231437Sluigi	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1404231437Sluigi
1405231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1406247880Sdelphij	if (!rc)
1407247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1408231437Sluigi	if (rc)
1409247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1410247880Sdelphij			      __FUNCTION__, rc);
1411231437Sluigi
1412247880Sdelphij	return rc;
1413231437Sluigi}
1414231437Sluigi
1415231437Sluigiint
1416231437Sluigioce_mbox_write_flashrom(POCE_SOFTC sc, uint32_t optype,uint32_t opcode,
1417231437Sluigi				POCE_DMA_MEM pdma_mem, uint32_t num_bytes)
1418231437Sluigi{
1419231437Sluigi
1420231437Sluigi	struct oce_mbx mbx;
1421231437Sluigi	struct oce_mq_sge *sgl = NULL;
1422231437Sluigi	struct mbx_common_read_write_flashrom *fwcmd = NULL;
1423231437Sluigi	int rc = 0, payload_len = 0;
1424231437Sluigi
1425231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1426231437Sluigi	fwcmd = OCE_DMAPTR(pdma_mem, struct mbx_common_read_write_flashrom);
1427231437Sluigi	payload_len = sizeof(struct mbx_common_read_write_flashrom) + 32*1024;
1428231437Sluigi
1429231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1430231437Sluigi				MBX_SUBSYSTEM_COMMON,
1431231437Sluigi				OPCODE_COMMON_WRITE_FLASHROM,
1432231437Sluigi				LONG_TIMEOUT,
1433231437Sluigi				payload_len,
1434231437Sluigi				OCE_MBX_VER_V0);
1435231437Sluigi
1436231437Sluigi	fwcmd->flash_op_type = optype;
1437231437Sluigi	fwcmd->flash_op_code = opcode;
1438231437Sluigi	fwcmd->data_buffer_size = num_bytes;
1439231437Sluigi
1440231437Sluigi	mbx.u0.s.embedded  = 0; /*Non embeded*/
1441231437Sluigi	mbx.payload_length = payload_len;
1442231437Sluigi	mbx.u0.s.sge_count = 1;
1443231437Sluigi
1444231437Sluigi	sgl = &mbx.payload.u0.u1.sgl[0];
1445231437Sluigi	sgl->pa_hi = upper_32_bits(pdma_mem->paddr);
1446231437Sluigi	sgl->pa_lo = pdma_mem->paddr & 0xFFFFFFFF;
1447231437Sluigi	sgl->length = payload_len;
1448231437Sluigi
1449231437Sluigi	/* post the command */
1450231879Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1451247880Sdelphij	if (!rc)
1452247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1453247880Sdelphij	if (rc)
1454247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1455247880Sdelphij			      __FUNCTION__, rc);
1456231437Sluigi
1457231437Sluigi	return rc;
1458231437Sluigi
1459231437Sluigi}
1460231437Sluigi
1461231437Sluigiint
1462231437Sluigioce_mbox_get_flashrom_crc(POCE_SOFTC sc, uint8_t *flash_crc,
1463231437Sluigi				uint32_t offset, uint32_t optype)
1464231437Sluigi{
1465231437Sluigi
1466231437Sluigi	int rc = 0, payload_len = 0;
1467231437Sluigi	struct oce_mbx mbx;
1468231437Sluigi	struct mbx_common_read_write_flashrom *fwcmd;
1469231437Sluigi
1470231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1471231437Sluigi
1472231437Sluigi	fwcmd = (struct mbx_common_read_write_flashrom *)&mbx.payload;
1473231437Sluigi
1474231437Sluigi	/* Firmware requires extra 4 bytes with this ioctl. Since there
1475231437Sluigi	   is enough room in the mbx payload it should be good enough
1476231437Sluigi	   Reference: Bug 14853
1477231437Sluigi	*/
1478231437Sluigi	payload_len = sizeof(struct mbx_common_read_write_flashrom) + 4;
1479231437Sluigi
1480231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1481231437Sluigi				MBX_SUBSYSTEM_COMMON,
1482231437Sluigi				OPCODE_COMMON_READ_FLASHROM,
1483231437Sluigi				MBX_TIMEOUT_SEC,
1484231437Sluigi				payload_len,
1485231437Sluigi				OCE_MBX_VER_V0);
1486231437Sluigi
1487231437Sluigi	fwcmd->flash_op_type = optype;
1488231437Sluigi	fwcmd->flash_op_code = FLASHROM_OPER_REPORT;
1489231437Sluigi	fwcmd->data_offset = offset;
1490231437Sluigi	fwcmd->data_buffer_size = 0x4;
1491231437Sluigi
1492231437Sluigi	mbx.u0.s.embedded  = 1;
1493231437Sluigi	mbx.payload_length = payload_len;
1494231437Sluigi
1495231437Sluigi	/* post the command */
1496231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1497247880Sdelphij	if (!rc)
1498247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1499231437Sluigi	if (rc) {
1500247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1501247880Sdelphij			      __FUNCTION__, rc);
1502247880Sdelphij		goto error;
1503231437Sluigi	}
1504247880Sdelphij	bcopy(fwcmd->data_buffer, flash_crc, 4);
1505247880Sdelphijerror:
1506231437Sluigi	return rc;
1507231437Sluigi}
1508231437Sluigi
1509231437Sluigiint
1510231437Sluigioce_mbox_get_phy_info(POCE_SOFTC sc, struct oce_phy_info *phy_info)
1511231437Sluigi{
1512231437Sluigi
1513231437Sluigi	struct oce_mbx mbx;
1514231437Sluigi	struct mbx_common_phy_info *fwcmd;
1515231437Sluigi	int rc = 0;
1516231437Sluigi
1517231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1518231437Sluigi
1519231437Sluigi	fwcmd = (struct mbx_common_phy_info *)&mbx.payload;
1520231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1521231437Sluigi				MBX_SUBSYSTEM_COMMON,
1522231437Sluigi				OPCODE_COMMON_GET_PHY_CONFIG,
1523231437Sluigi				MBX_TIMEOUT_SEC,
1524231437Sluigi				sizeof(struct mbx_common_phy_info),
1525231437Sluigi				OCE_MBX_VER_V0);
1526231437Sluigi
1527231437Sluigi	mbx.u0.s.embedded = 1;
1528231437Sluigi	mbx.payload_length = sizeof(struct  mbx_common_phy_info);
1529231437Sluigi
1530231437Sluigi	/* now post the command */
1531231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1532247880Sdelphij	if (!rc)
1533247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1534231437Sluigi	if (rc) {
1535247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1536247880Sdelphij			      __FUNCTION__, rc);
1537247880Sdelphij		goto error;
1538231437Sluigi	}
1539247880Sdelphij	phy_info->phy_type = fwcmd->params.rsp.phy_info.phy_type;
1540247880Sdelphij	phy_info->interface_type =
1541247880Sdelphij			fwcmd->params.rsp.phy_info.interface_type;
1542247880Sdelphij	phy_info->auto_speeds_supported =
1543247880Sdelphij		fwcmd->params.rsp.phy_info.auto_speeds_supported;
1544247880Sdelphij	phy_info->fixed_speeds_supported =
1545247880Sdelphij		fwcmd->params.rsp.phy_info.fixed_speeds_supported;
1546247880Sdelphij	phy_info->misc_params =fwcmd->params.rsp.phy_info.misc_params;
1547247880Sdelphijerror:
1548231437Sluigi	return rc;
1549231437Sluigi
1550231437Sluigi}
1551231437Sluigi
1552231437Sluigi
1553231437Sluigiint
1554231437Sluigioce_mbox_lancer_write_flashrom(POCE_SOFTC sc, uint32_t data_size,
1555231437Sluigi			uint32_t data_offset, POCE_DMA_MEM pdma_mem,
1556231437Sluigi			uint32_t *written_data, uint32_t *additional_status)
1557231437Sluigi{
1558231437Sluigi
1559231437Sluigi	struct oce_mbx mbx;
1560231437Sluigi	struct mbx_lancer_common_write_object *fwcmd = NULL;
1561231437Sluigi	int rc = 0, payload_len = 0;
1562231437Sluigi
1563231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1564231437Sluigi	payload_len = sizeof(struct mbx_lancer_common_write_object);
1565231437Sluigi
1566231437Sluigi	mbx.u0.s.embedded  = 1;/* Embedded */
1567231437Sluigi	mbx.payload_length = payload_len;
1568231437Sluigi	fwcmd = (struct mbx_lancer_common_write_object *)&mbx.payload;
1569231437Sluigi
1570231437Sluigi	/* initialize the ioctl header */
1571231437Sluigi	mbx_common_req_hdr_init(&fwcmd->params.req.hdr, 0, 0,
1572231437Sluigi				MBX_SUBSYSTEM_COMMON,
1573231437Sluigi				OPCODE_COMMON_WRITE_OBJECT,
1574231437Sluigi				LONG_TIMEOUT,
1575231437Sluigi				payload_len,
1576231437Sluigi				OCE_MBX_VER_V0);
1577231437Sluigi
1578231437Sluigi	fwcmd->params.req.write_length = data_size;
1579231437Sluigi	if (data_size == 0)
1580231437Sluigi		fwcmd->params.req.eof = 1;
1581231437Sluigi	else
1582231437Sluigi		fwcmd->params.req.eof = 0;
1583231437Sluigi
1584231437Sluigi	strcpy(fwcmd->params.req.object_name, "/prg");
1585231437Sluigi	fwcmd->params.req.descriptor_count = 1;
1586231437Sluigi	fwcmd->params.req.write_offset = data_offset;
1587231437Sluigi	fwcmd->params.req.buffer_length = data_size;
1588231437Sluigi	fwcmd->params.req.address_lower = pdma_mem->paddr & 0xFFFFFFFF;
1589231437Sluigi	fwcmd->params.req.address_upper = upper_32_bits(pdma_mem->paddr);
1590231437Sluigi
1591231437Sluigi	/* post the command */
1592231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1593247880Sdelphij	if (!rc)
1594247880Sdelphij                rc = fwcmd->params.rsp.status;
1595231437Sluigi	if (rc) {
1596247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1597247880Sdelphij			      __FUNCTION__, rc);
1598247880Sdelphij		goto error;
1599231437Sluigi	}
1600247880Sdelphij	*written_data = fwcmd->params.rsp.actual_write_length;
1601247880Sdelphij	*additional_status = fwcmd->params.rsp.additional_status;
1602247880Sdelphijerror:
1603231437Sluigi	return rc;
1604231437Sluigi
1605231437Sluigi}
1606231437Sluigi
1607231437Sluigi
1608231437Sluigi
1609231437Sluigiint
1610231437Sluigioce_mbox_create_rq(struct oce_rq *rq)
1611231437Sluigi{
1612231437Sluigi
1613231437Sluigi	struct oce_mbx mbx;
1614231437Sluigi	struct mbx_create_nic_rq *fwcmd;
1615231437Sluigi	POCE_SOFTC sc = rq->parent;
1616231437Sluigi	int rc, num_pages = 0;
1617231437Sluigi
1618231437Sluigi	if (rq->qstate == QCREATED)
1619231437Sluigi		return 0;
1620231437Sluigi
1621231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1622231437Sluigi
1623231437Sluigi	fwcmd = (struct mbx_create_nic_rq *)&mbx.payload;
1624231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1625231437Sluigi				MBX_SUBSYSTEM_NIC,
1626231437Sluigi				NIC_CREATE_RQ, MBX_TIMEOUT_SEC,
1627231437Sluigi				sizeof(struct mbx_create_nic_rq),
1628231437Sluigi				OCE_MBX_VER_V0);
1629231437Sluigi
1630231437Sluigi	/* oce_page_list will also prepare pages */
1631231437Sluigi	num_pages = oce_page_list(rq->ring, &fwcmd->params.req.pages[0]);
1632231437Sluigi
1633231437Sluigi	if (IS_XE201(sc)) {
1634231437Sluigi		fwcmd->params.req.frag_size = rq->cfg.frag_size/2048;
1635231437Sluigi		fwcmd->params.req.page_size = 1;
1636231437Sluigi		fwcmd->hdr.u0.req.version = OCE_MBX_VER_V1;
1637231437Sluigi	} else
1638231437Sluigi		fwcmd->params.req.frag_size = OCE_LOG2(rq->cfg.frag_size);
1639231437Sluigi	fwcmd->params.req.num_pages = num_pages;
1640231437Sluigi	fwcmd->params.req.cq_id = rq->cq->cq_id;
1641231437Sluigi	fwcmd->params.req.if_id = sc->if_id;
1642231437Sluigi	fwcmd->params.req.max_frame_size = rq->cfg.mtu;
1643231437Sluigi	fwcmd->params.req.is_rss_queue = rq->cfg.is_rss_queue;
1644231437Sluigi
1645231437Sluigi	mbx.u0.s.embedded = 1;
1646231437Sluigi	mbx.payload_length = sizeof(struct mbx_create_nic_rq);
1647231437Sluigi
1648231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1649247880Sdelphij	if (!rc)
1650247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1651247880Sdelphij	if (rc) {
1652247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1653247880Sdelphij			      __FUNCTION__, rc);
1654231437Sluigi		goto error;
1655247880Sdelphij	}
1656231437Sluigi	rq->rq_id = fwcmd->params.rsp.rq_id;
1657231437Sluigi	rq->rss_cpuid = fwcmd->params.rsp.rss_cpuid;
1658231437Sluigierror:
1659231437Sluigi	return rc;
1660231437Sluigi
1661231437Sluigi}
1662231437Sluigi
1663231437Sluigi
1664231437Sluigi
1665231437Sluigiint
1666231437Sluigioce_mbox_create_wq(struct oce_wq *wq)
1667231437Sluigi{
1668231437Sluigi	struct oce_mbx mbx;
1669231437Sluigi	struct mbx_create_nic_wq *fwcmd;
1670231437Sluigi	POCE_SOFTC sc = wq->parent;
1671231437Sluigi	int rc = 0, version, num_pages;
1672231437Sluigi
1673231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1674231437Sluigi
1675231437Sluigi	fwcmd = (struct mbx_create_nic_wq *)&mbx.payload;
1676231437Sluigi	if (IS_XE201(sc)) {
1677231437Sluigi		version = OCE_MBX_VER_V1;
1678231437Sluigi		fwcmd->params.req.if_id = sc->if_id;
1679252869Sdelphij	} else if(IS_BE(sc))
1680252869Sdelphij		IS_PROFILE_SUPER_NIC(sc) ? (version = OCE_MBX_VER_V2)
1681252869Sdelphij					 : (version = OCE_MBX_VER_V0);
1682252869Sdelphij	else
1683252869Sdelphij		version = OCE_MBX_VER_V2;
1684231437Sluigi
1685231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1686231437Sluigi				MBX_SUBSYSTEM_NIC,
1687231437Sluigi				NIC_CREATE_WQ, MBX_TIMEOUT_SEC,
1688231437Sluigi				sizeof(struct mbx_create_nic_wq),
1689231437Sluigi				version);
1690231437Sluigi
1691231437Sluigi	num_pages = oce_page_list(wq->ring, &fwcmd->params.req.pages[0]);
1692231437Sluigi
1693231437Sluigi	fwcmd->params.req.nic_wq_type = wq->cfg.wq_type;
1694231437Sluigi	fwcmd->params.req.num_pages = num_pages;
1695231437Sluigi	fwcmd->params.req.wq_size = OCE_LOG2(wq->cfg.q_len) + 1;
1696231437Sluigi	fwcmd->params.req.cq_id = wq->cq->cq_id;
1697231437Sluigi	fwcmd->params.req.ulp_num = 1;
1698231437Sluigi
1699231437Sluigi	mbx.u0.s.embedded = 1;
1700231437Sluigi	mbx.payload_length = sizeof(struct mbx_create_nic_wq);
1701231437Sluigi
1702231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1703247880Sdelphij	if (!rc)
1704247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1705247880Sdelphij	if (rc) {
1706247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1707247880Sdelphij			      __FUNCTION__, rc);
1708231437Sluigi		goto error;
1709247880Sdelphij	}
1710231437Sluigi	wq->wq_id = LE_16(fwcmd->params.rsp.wq_id);
1711252869Sdelphij	if (version == OCE_MBX_VER_V2)
1712252869Sdelphij		wq->db_offset = LE_32(fwcmd->params.rsp.db_offset);
1713252869Sdelphij	else
1714252869Sdelphij		wq->db_offset = PD_TXULP_DB;
1715231437Sluigierror:
1716231437Sluigi	return rc;
1717231437Sluigi
1718231437Sluigi}
1719231437Sluigi
1720231437Sluigi
1721231437Sluigi
1722231437Sluigiint
1723231437Sluigioce_mbox_create_eq(struct oce_eq *eq)
1724231437Sluigi{
1725231437Sluigi	struct oce_mbx mbx;
1726231437Sluigi	struct mbx_create_common_eq *fwcmd;
1727231437Sluigi	POCE_SOFTC sc = eq->parent;
1728231437Sluigi	int rc = 0;
1729231437Sluigi	uint32_t num_pages;
1730231437Sluigi
1731231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1732231437Sluigi
1733231437Sluigi	fwcmd = (struct mbx_create_common_eq *)&mbx.payload;
1734231437Sluigi
1735231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1736231437Sluigi				MBX_SUBSYSTEM_COMMON,
1737231437Sluigi				OPCODE_COMMON_CREATE_EQ, MBX_TIMEOUT_SEC,
1738231437Sluigi				sizeof(struct mbx_create_common_eq),
1739231437Sluigi				OCE_MBX_VER_V0);
1740231437Sluigi
1741231437Sluigi	num_pages = oce_page_list(eq->ring, &fwcmd->params.req.pages[0]);
1742231437Sluigi	fwcmd->params.req.ctx.num_pages = num_pages;
1743231437Sluigi	fwcmd->params.req.ctx.valid = 1;
1744231437Sluigi	fwcmd->params.req.ctx.size = (eq->eq_cfg.item_size == 4) ? 0 : 1;
1745231437Sluigi	fwcmd->params.req.ctx.count = OCE_LOG2(eq->eq_cfg.q_len / 256);
1746231437Sluigi	fwcmd->params.req.ctx.armed = 0;
1747231437Sluigi	fwcmd->params.req.ctx.delay_mult = eq->eq_cfg.cur_eqd;
1748231437Sluigi
1749231437Sluigi
1750231437Sluigi	mbx.u0.s.embedded = 1;
1751231437Sluigi	mbx.payload_length = sizeof(struct mbx_create_common_eq);
1752231437Sluigi
1753231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1754247880Sdelphij	if (!rc)
1755247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1756247880Sdelphij	if (rc) {
1757247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1758247880Sdelphij			      __FUNCTION__, rc);
1759231437Sluigi		goto error;
1760247880Sdelphij	}
1761231437Sluigi	eq->eq_id = LE_16(fwcmd->params.rsp.eq_id);
1762231437Sluigierror:
1763231437Sluigi	return rc;
1764231437Sluigi}
1765231437Sluigi
1766231437Sluigi
1767231437Sluigi
1768231437Sluigiint
1769231437Sluigioce_mbox_cq_create(struct oce_cq *cq, uint32_t ncoalesce, uint32_t is_eventable)
1770231437Sluigi{
1771231437Sluigi	struct oce_mbx mbx;
1772231437Sluigi	struct mbx_create_common_cq *fwcmd;
1773231437Sluigi	POCE_SOFTC sc = cq->parent;
1774231437Sluigi	uint8_t version;
1775231437Sluigi	oce_cq_ctx_t *ctx;
1776231437Sluigi	uint32_t num_pages, page_size;
1777231437Sluigi	int rc = 0;
1778231437Sluigi
1779231437Sluigi
1780231437Sluigi	bzero(&mbx, sizeof(struct oce_mbx));
1781231437Sluigi
1782231437Sluigi	fwcmd = (struct mbx_create_common_cq *)&mbx.payload;
1783231437Sluigi
1784231437Sluigi	if (IS_XE201(sc))
1785231437Sluigi		version = OCE_MBX_VER_V2;
1786231437Sluigi	else
1787231437Sluigi		version = OCE_MBX_VER_V0;
1788231437Sluigi
1789231437Sluigi	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1790231437Sluigi				MBX_SUBSYSTEM_COMMON,
1791231437Sluigi				OPCODE_COMMON_CREATE_CQ,
1792231437Sluigi				MBX_TIMEOUT_SEC,
1793231437Sluigi				sizeof(struct mbx_create_common_cq),
1794231437Sluigi				version);
1795231437Sluigi
1796231437Sluigi	ctx = &fwcmd->params.req.cq_ctx;
1797231437Sluigi
1798231437Sluigi	num_pages = oce_page_list(cq->ring, &fwcmd->params.req.pages[0]);
1799231437Sluigi	page_size =  1;  /* 1 for 4K */
1800231437Sluigi
1801231437Sluigi	if (version == OCE_MBX_VER_V2) {
1802231437Sluigi		ctx->v2.num_pages = LE_16(num_pages);
1803231437Sluigi		ctx->v2.page_size = page_size;
1804231437Sluigi		ctx->v2.eventable = is_eventable;
1805231437Sluigi		ctx->v2.valid = 1;
1806231437Sluigi		ctx->v2.count = OCE_LOG2(cq->cq_cfg.q_len / 256);
1807231437Sluigi		ctx->v2.nodelay = cq->cq_cfg.nodelay;
1808231437Sluigi		ctx->v2.coalesce_wm = ncoalesce;
1809231437Sluigi		ctx->v2.armed = 0;
1810231437Sluigi		ctx->v2.eq_id = cq->eq->eq_id;
1811231437Sluigi		if (ctx->v2.count == 3) {
1812231437Sluigi			if (cq->cq_cfg.q_len > (4*1024)-1)
1813231437Sluigi				ctx->v2.cqe_count = (4*1024)-1;
1814231437Sluigi			else
1815231437Sluigi				ctx->v2.cqe_count = cq->cq_cfg.q_len;
1816231437Sluigi		}
1817231437Sluigi	} else {
1818231437Sluigi		ctx->v0.num_pages = LE_16(num_pages);
1819231437Sluigi		ctx->v0.eventable = is_eventable;
1820231437Sluigi		ctx->v0.valid = 1;
1821231437Sluigi		ctx->v0.count = OCE_LOG2(cq->cq_cfg.q_len / 256);
1822231437Sluigi		ctx->v0.nodelay = cq->cq_cfg.nodelay;
1823231437Sluigi		ctx->v0.coalesce_wm = ncoalesce;
1824231437Sluigi		ctx->v0.armed = 0;
1825231437Sluigi		ctx->v0.eq_id = cq->eq->eq_id;
1826231437Sluigi	}
1827231437Sluigi
1828231437Sluigi	mbx.u0.s.embedded = 1;
1829231437Sluigi	mbx.payload_length = sizeof(struct mbx_create_common_cq);
1830231437Sluigi
1831231437Sluigi	rc = oce_mbox_post(sc, &mbx, NULL);
1832247880Sdelphij	if (!rc)
1833247880Sdelphij                rc = fwcmd->hdr.u0.rsp.status;
1834247880Sdelphij	if (rc) {
1835247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1836247880Sdelphij			      __FUNCTION__, rc);
1837231437Sluigi		goto error;
1838247880Sdelphij	}
1839231437Sluigi	cq->cq_id = LE_16(fwcmd->params.rsp.cq_id);
1840247880Sdelphijerror:
1841247880Sdelphij	return rc;
1842231437Sluigi
1843247880Sdelphij}
1844247880Sdelphij
1845247880Sdelphijint
1846247880Sdelphijoce_mbox_read_transrecv_data(POCE_SOFTC sc, uint32_t page_num)
1847247880Sdelphij{
1848247880Sdelphij	int rc = 0;
1849247880Sdelphij	struct oce_mbx mbx;
1850247880Sdelphij	struct mbx_read_common_transrecv_data *fwcmd;
1851247880Sdelphij	struct oce_mq_sge *sgl;
1852247880Sdelphij	OCE_DMA_MEM dma;
1853247880Sdelphij
1854247880Sdelphij	/* Allocate DMA mem*/
1855247880Sdelphij	if (oce_dma_alloc(sc, sizeof(struct mbx_read_common_transrecv_data),
1856247880Sdelphij				&dma, 0))
1857247880Sdelphij		return ENOMEM;
1858247880Sdelphij
1859247880Sdelphij	fwcmd = OCE_DMAPTR(&dma, struct mbx_read_common_transrecv_data);
1860247880Sdelphij	bzero(fwcmd, sizeof(struct mbx_read_common_transrecv_data));
1861247880Sdelphij
1862247880Sdelphij	bzero(&mbx, sizeof(struct oce_mbx));
1863247880Sdelphij	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1864247880Sdelphij			MBX_SUBSYSTEM_COMMON,
1865247880Sdelphij			OPCODE_COMMON_READ_TRANSRECEIVER_DATA,
1866247880Sdelphij			MBX_TIMEOUT_SEC,
1867247880Sdelphij			sizeof(struct mbx_read_common_transrecv_data),
1868247880Sdelphij			OCE_MBX_VER_V0);
1869247880Sdelphij
1870247880Sdelphij	/* fill rest of mbx */
1871247880Sdelphij	mbx.u0.s.embedded = 0;
1872247880Sdelphij	mbx.payload_length = sizeof(struct mbx_read_common_transrecv_data);
1873247880Sdelphij	mbx.u0.s.sge_count = 1;
1874247880Sdelphij	sgl = &mbx.payload.u0.u1.sgl[0];
1875247880Sdelphij	sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
1876247880Sdelphij	sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
1877247880Sdelphij	sgl->length = htole32(mbx.payload_length);
1878247880Sdelphij	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1879247880Sdelphij
1880247880Sdelphij	fwcmd->params.req.port = LE_32(sc->port_id);
1881247880Sdelphij	fwcmd->params.req.page_num = LE_32(page_num);
1882247880Sdelphij
1883247880Sdelphij	/* command post */
1884247880Sdelphij	rc = oce_mbox_post(sc, &mbx, NULL);
1885247880Sdelphij	if (!rc)
1886252869Sdelphij		rc = fwcmd->hdr.u0.rsp.status;
1887247880Sdelphij	if (rc) {
1888247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1889247880Sdelphij			      __FUNCTION__, rc);
1890247880Sdelphij		goto error;
1891247880Sdelphij	}
1892247880Sdelphij	if(fwcmd->params.rsp.page_num == PAGE_NUM_A0)
1893247880Sdelphij	{
1894247880Sdelphij		bcopy((char *)fwcmd->params.rsp.page_data,
1895247880Sdelphij				(char *)&sfp_vpd_dump_buffer[0],
1896247880Sdelphij				TRANSCEIVER_A0_SIZE);
1897247880Sdelphij	}
1898247880Sdelphij
1899247880Sdelphij	if(fwcmd->params.rsp.page_num == PAGE_NUM_A2)
1900247880Sdelphij	{
1901247880Sdelphij		bcopy((char *)fwcmd->params.rsp.page_data,
1902247880Sdelphij				(char *)&sfp_vpd_dump_buffer[32],
1903247880Sdelphij				TRANSCEIVER_A2_SIZE);
1904247880Sdelphij	}
1905231437Sluigierror:
1906252869Sdelphij	oce_dma_free(sc, &dma);
1907231437Sluigi	return rc;
1908247880Sdelphij}
1909231437Sluigi
1910247880Sdelphijvoid
1911247880Sdelphijoce_mbox_eqd_modify_periodic(POCE_SOFTC sc, struct oce_set_eqd *set_eqd,
1912247880Sdelphij				int num)
1913247880Sdelphij{
1914247880Sdelphij	struct oce_mbx mbx;
1915247880Sdelphij	struct mbx_modify_common_eq_delay *fwcmd;
1916247880Sdelphij	int rc = 0;
1917247880Sdelphij	int i = 0;
1918247880Sdelphij
1919247880Sdelphij	bzero(&mbx, sizeof(struct oce_mbx));
1920247880Sdelphij
1921247880Sdelphij	/* Initialize MODIFY_EQ_DELAY ioctl header */
1922247880Sdelphij	fwcmd = (struct mbx_modify_common_eq_delay *)&mbx.payload;
1923247880Sdelphij	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1924247880Sdelphij				MBX_SUBSYSTEM_COMMON,
1925247880Sdelphij				OPCODE_COMMON_MODIFY_EQ_DELAY,
1926247880Sdelphij				MBX_TIMEOUT_SEC,
1927247880Sdelphij				sizeof(struct mbx_modify_common_eq_delay),
1928247880Sdelphij				OCE_MBX_VER_V0);
1929247880Sdelphij	/* fill rest of mbx */
1930247880Sdelphij	mbx.u0.s.embedded = 1;
1931247880Sdelphij	mbx.payload_length = sizeof(struct mbx_modify_common_eq_delay);
1932247880Sdelphij	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1933247880Sdelphij
1934247880Sdelphij	fwcmd->params.req.num_eq = num;
1935247880Sdelphij	for (i = 0; i < num; i++) {
1936247880Sdelphij		fwcmd->params.req.delay[i].eq_id =
1937247880Sdelphij					htole32(set_eqd[i].eq_id);
1938247880Sdelphij		fwcmd->params.req.delay[i].phase = 0;
1939247880Sdelphij		fwcmd->params.req.delay[i].dm =
1940247880Sdelphij		htole32(set_eqd[i].delay_multiplier);
1941247880Sdelphij	}
1942247880Sdelphij
1943247880Sdelphij
1944247880Sdelphij	/* command post */
1945247880Sdelphij	rc = oce_mbox_post(sc, &mbx, NULL);
1946247880Sdelphij
1947247880Sdelphij	if (!rc)
1948252869Sdelphij		rc = fwcmd->hdr.u0.rsp.status;
1949247880Sdelphij	if (rc)
1950247880Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1951247880Sdelphij			      __FUNCTION__, rc);
1952231437Sluigi}
1953247880Sdelphij
1954252869Sdelphijint
1955252869Sdelphijoce_get_profile_config(POCE_SOFTC sc)
1956252869Sdelphij{
1957252869Sdelphij	struct oce_mbx mbx;
1958252869Sdelphij	struct mbx_common_get_profile_config *fwcmd;
1959252869Sdelphij	int rc = 0;
1960252869Sdelphij	int version = 0;
1961252869Sdelphij	struct oce_mq_sge *sgl;
1962252869Sdelphij	OCE_DMA_MEM dma;
1963252869Sdelphij	uint32_t desc_count = 0;
1964252869Sdelphij	struct oce_nic_resc_desc *nic_desc = NULL;
1965252869Sdelphij	int i;
1966252869Sdelphij	boolean_t nic_desc_valid = FALSE;
1967247880Sdelphij
1968252869Sdelphij	if (IS_BE2(sc))
1969252869Sdelphij		return -1;
1970252869Sdelphij
1971252869Sdelphij	/* Allocate DMA mem*/
1972252869Sdelphij	if (oce_dma_alloc(sc, sizeof(struct mbx_common_get_profile_config),
1973252869Sdelphij			  &dma, 0))
1974252869Sdelphij		return ENOMEM;
1975252869Sdelphij
1976252869Sdelphij	/* Initialize MODIFY_EQ_DELAY ioctl header */
1977252869Sdelphij	fwcmd = OCE_DMAPTR(&dma, struct mbx_common_get_profile_config);
1978252869Sdelphij	bzero(fwcmd, sizeof(struct mbx_common_get_profile_config));
1979252869Sdelphij
1980252869Sdelphij	if (IS_BE3(sc))
1981252869Sdelphij		version = OCE_MBX_VER_V1;
1982252869Sdelphij	else
1983252869Sdelphij		version = OCE_MBX_VER_V0;
1984252869Sdelphij
1985252869Sdelphij	bzero(&mbx, sizeof(struct oce_mbx));
1986252869Sdelphij	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1987252869Sdelphij				MBX_SUBSYSTEM_COMMON,
1988252869Sdelphij				OPCODE_COMMON_GET_PROFILE_CONFIG,
1989252869Sdelphij				MBX_TIMEOUT_SEC,
1990252869Sdelphij				sizeof(struct mbx_common_get_profile_config),
1991252869Sdelphij				version);
1992252869Sdelphij	/* fill rest of mbx */
1993252869Sdelphij	mbx.u0.s.embedded = 0;
1994252869Sdelphij	mbx.payload_length = sizeof(struct mbx_common_get_profile_config);
1995252869Sdelphij	mbx.u0.s.sge_count = 1;
1996252869Sdelphij	sgl = &mbx.payload.u0.u1.sgl[0];
1997252869Sdelphij	sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
1998252869Sdelphij	sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
1999252869Sdelphij	sgl->length = htole32(mbx.payload_length);
2000252869Sdelphij	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
2001252869Sdelphij
2002252869Sdelphij	fwcmd->params.req.type = ACTIVE_PROFILE;
2003252869Sdelphij
2004252869Sdelphij	/* command post */
2005252869Sdelphij	rc = oce_mbox_post(sc, &mbx, NULL);
2006252869Sdelphij	if (!rc)
2007252869Sdelphij		rc = fwcmd->hdr.u0.rsp.status;
2008252869Sdelphij	if (rc) {
2009252869Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
2010252869Sdelphij			      __FUNCTION__, rc);
2011252869Sdelphij		goto error;
2012252869Sdelphij	}
2013252869Sdelphij
2014252869Sdelphij	nic_desc = (struct oce_nic_resc_desc *) fwcmd->params.rsp.resources;
2015252869Sdelphij	desc_count = HOST_32(fwcmd->params.rsp.desc_count);
2016252869Sdelphij	for (i = 0; i < desc_count; i++) {
2017252869Sdelphij		if ((nic_desc->desc_type == NIC_RESC_DESC_TYPE_V0) ||
2018252869Sdelphij		    (nic_desc->desc_type == NIC_RESC_DESC_TYPE_V1)) {
2019252869Sdelphij			nic_desc_valid = TRUE;
2020252869Sdelphij			break;
2021252869Sdelphij		}
2022252869Sdelphij		nic_desc = (struct oce_nic_resc_desc *) \
2023252869Sdelphij				((char *)nic_desc + nic_desc->desc_len);
2024252869Sdelphij	}
2025252869Sdelphij	if (!nic_desc_valid) {
2026252869Sdelphij		rc = -1;
2027252869Sdelphij		goto error;
2028252869Sdelphij	}
2029252869Sdelphij	else {
2030252869Sdelphij		sc->nwqs = HOST_32(nic_desc->txq_count);
2031252869Sdelphij		if (sc->nwqs)
2032252869Sdelphij			sc->nwqs = MIN(sc->nwqs, OCE_MAX_WQ);
2033252869Sdelphij		else
2034252869Sdelphij			sc->nwqs = OCE_MAX_WQ;
2035252869Sdelphij
2036252869Sdelphij	}
2037252869Sdelphijerror:
2038252869Sdelphij	oce_dma_free(sc, &dma);
2039252869Sdelphij	return rc;
2040252869Sdelphij
2041252869Sdelphij}
2042252869Sdelphij
2043252869Sdelphijint
2044252869Sdelphijoce_get_func_config(POCE_SOFTC sc)
2045252869Sdelphij{
2046252869Sdelphij	struct oce_mbx mbx;
2047252869Sdelphij	struct mbx_common_get_func_config *fwcmd;
2048252869Sdelphij	int rc = 0;
2049252869Sdelphij	int version = 0;
2050252869Sdelphij	struct oce_mq_sge *sgl;
2051252869Sdelphij	OCE_DMA_MEM dma;
2052252869Sdelphij	uint32_t desc_count = 0;
2053252869Sdelphij	struct oce_nic_resc_desc *nic_desc = NULL;
2054252869Sdelphij	int i;
2055252869Sdelphij	boolean_t nic_desc_valid = FALSE;
2056252869Sdelphij	uint32_t max_rss = 0;
2057252869Sdelphij
2058252869Sdelphij	if ((IS_BE(sc) || IS_SH(sc)) && (!sc->be3_native))
2059252869Sdelphij		max_rss = OCE_LEGACY_MODE_RSS;
2060252869Sdelphij	else
2061252869Sdelphij		max_rss = OCE_MAX_RSS;
2062252869Sdelphij
2063252869Sdelphij	/* Allocate DMA mem*/
2064252869Sdelphij	if (oce_dma_alloc(sc, sizeof(struct mbx_common_get_func_config),
2065252869Sdelphij			  &dma, 0))
2066252869Sdelphij		return ENOMEM;
2067252869Sdelphij
2068252869Sdelphij	/* Initialize MODIFY_EQ_DELAY ioctl header */
2069252869Sdelphij	fwcmd = OCE_DMAPTR(&dma, struct mbx_common_get_func_config);
2070252869Sdelphij	bzero(fwcmd, sizeof(struct mbx_common_get_func_config));
2071252869Sdelphij
2072252869Sdelphij	if (IS_SH(sc))
2073252869Sdelphij		version = OCE_MBX_VER_V1;
2074252869Sdelphij	else
2075252869Sdelphij		version = OCE_MBX_VER_V0;
2076252869Sdelphij
2077252869Sdelphij	bzero(&mbx, sizeof(struct oce_mbx));
2078252869Sdelphij	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
2079252869Sdelphij				MBX_SUBSYSTEM_COMMON,
2080252869Sdelphij				OPCODE_COMMON_GET_FUNCTION_CONFIG,
2081252869Sdelphij				MBX_TIMEOUT_SEC,
2082252869Sdelphij				sizeof(struct mbx_common_get_func_config),
2083252869Sdelphij				version);
2084252869Sdelphij	/* fill rest of mbx */
2085252869Sdelphij	mbx.u0.s.embedded = 0;
2086252869Sdelphij	mbx.payload_length = sizeof(struct mbx_common_get_func_config);
2087252869Sdelphij	mbx.u0.s.sge_count = 1;
2088252869Sdelphij	sgl = &mbx.payload.u0.u1.sgl[0];
2089252869Sdelphij	sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
2090252869Sdelphij	sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
2091252869Sdelphij	sgl->length = htole32(mbx.payload_length);
2092252869Sdelphij	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
2093252869Sdelphij
2094252869Sdelphij	/* command post */
2095252869Sdelphij	rc = oce_mbox_post(sc, &mbx, NULL);
2096252869Sdelphij	if (!rc)
2097252869Sdelphij		rc = fwcmd->hdr.u0.rsp.status;
2098252869Sdelphij	if (rc) {
2099252869Sdelphij		device_printf(sc->dev,"%s failed - cmd status: %d\n",
2100252869Sdelphij			      __FUNCTION__, rc);
2101252869Sdelphij		goto error;
2102252869Sdelphij	}
2103252869Sdelphij
2104252869Sdelphij	nic_desc = (struct oce_nic_resc_desc *) fwcmd->params.rsp.resources;
2105252869Sdelphij	desc_count = HOST_32(fwcmd->params.rsp.desc_count);
2106252869Sdelphij	for (i = 0; i < desc_count; i++) {
2107252869Sdelphij		if ((nic_desc->desc_type == NIC_RESC_DESC_TYPE_V0) ||
2108252869Sdelphij		    (nic_desc->desc_type == NIC_RESC_DESC_TYPE_V1)) {
2109252869Sdelphij			nic_desc_valid = TRUE;
2110252869Sdelphij			break;
2111252869Sdelphij		}
2112252869Sdelphij		nic_desc = (struct oce_nic_resc_desc *) \
2113252869Sdelphij				((char *)nic_desc + nic_desc->desc_len);
2114252869Sdelphij	}
2115252869Sdelphij	if (!nic_desc_valid) {
2116252869Sdelphij		rc = -1;
2117252869Sdelphij		goto error;
2118252869Sdelphij	}
2119252869Sdelphij	else {
2120252869Sdelphij		sc->nwqs = HOST_32(nic_desc->txq_count);
2121252869Sdelphij                if (sc->nwqs)
2122252869Sdelphij                        sc->nwqs = MIN(sc->nwqs, OCE_MAX_WQ);
2123252869Sdelphij                else
2124252869Sdelphij                        sc->nwqs = OCE_MAX_WQ;
2125252869Sdelphij
2126252869Sdelphij		sc->nrssqs = HOST_32(nic_desc->rssq_count);
2127252869Sdelphij		if (sc->nrssqs)
2128252869Sdelphij			sc->nrssqs = MIN(sc->nrssqs, max_rss);
2129252869Sdelphij		else
2130252869Sdelphij			sc->nrssqs = max_rss;
2131252869Sdelphij		sc->nrqs =  sc->nrssqs + 1; /* 1 for def RX */;
2132252869Sdelphij	}
2133252869Sdelphijerror:
2134252869Sdelphij	oce_dma_free(sc, &dma);
2135252869Sdelphij	return rc;
2136252869Sdelphij
2137252869Sdelphij}
2138