xref: /freebsd/sys/dev/oce/oce_mbox.c (revision 47dd1d1b619cc035b82b49a91a25544309ff95ae)
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (C) 2013 Emulex
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice,
11  *    this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the Emulex Corporation nor the names of its
18  *    contributors may be used to endorse or promote products derived from
19  *    this software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  *
33  * Contact Information:
34  * freebsd-drivers@emulex.com
35  *
36  * Emulex
37  * 3333 Susan Street
38  * Costa Mesa, CA 92626
39  */
40 
41 /* $FreeBSD$ */
42 
43 #include "oce_if.h"
44 extern uint32_t sfp_vpd_dump_buffer[TRANSCEIVER_DATA_NUM_ELE];
45 
46 int
47 oce_wait_ready(POCE_SOFTC sc)
48 {
49 #define SLIPORT_READY_TIMEOUT 30000
50 	uint32_t sliport_status, i;
51 
52 	if (!IS_XE201(sc))
53 		return (-1);
54 
55 	for (i = 0; i < SLIPORT_READY_TIMEOUT; i++) {
56 		sliport_status = OCE_READ_REG32(sc, db, SLIPORT_STATUS_OFFSET);
57 		if (sliport_status & SLIPORT_STATUS_RDY_MASK)
58 			return 0;
59 
60 		if (sliport_status & SLIPORT_STATUS_ERR_MASK &&
61 			!(sliport_status & SLIPORT_STATUS_RN_MASK)) {
62 			device_printf(sc->dev, "Error detected in the card\n");
63 			return EIO;
64 		}
65 
66 		DELAY(1000);
67 	}
68 
69 	device_printf(sc->dev, "Firmware wait timed out\n");
70 
71 	return (-1);
72 }
73 
74 /**
75  * @brief Reset (firmware) common function
76  * @param sc		software handle to the device
77  * @returns		0 on success, ETIMEDOUT on failure
78  */
79 int
80 oce_reset_fun(POCE_SOFTC sc)
81 {
82 	struct oce_mbx *mbx;
83 	struct oce_bmbx *mb;
84 	struct ioctl_common_function_reset *fwcmd;
85 	int rc = 0;
86 
87 	if (IS_XE201(sc)) {
88 		OCE_WRITE_REG32(sc, db, SLIPORT_CONTROL_OFFSET,
89 					SLI_PORT_CONTROL_IP_MASK);
90 
91 		rc = oce_wait_ready(sc);
92 		if (rc) {
93 			device_printf(sc->dev, "Firmware reset Failed\n");
94 		}
95 
96 		return rc;
97 	}
98 
99 	mb = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
100 	mbx = &mb->mbx;
101 	bzero(mbx, sizeof(struct oce_mbx));
102 
103 	fwcmd = (struct ioctl_common_function_reset *)&mbx->payload;
104 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
105 			MBX_SUBSYSTEM_COMMON,
106 			OPCODE_COMMON_FUNCTION_RESET,
107 			10,	/* MBX_TIMEOUT_SEC */
108 			sizeof(struct
109 				ioctl_common_function_reset),
110 			OCE_MBX_VER_V0);
111 
112 	mbx->u0.s.embedded = 1;
113 	mbx->payload_length =
114 		sizeof(struct ioctl_common_function_reset);
115 
116 	rc = oce_mbox_dispatch(sc, 2);
117 
118 	return rc;
119 }
120 
121 
122 /**
123  * @brief  		This funtions tells firmware we are
124  *			done with commands.
125  * @param sc            software handle to the device
126  * @returns             0 on success, ETIMEDOUT on failure
127  */
128 int
129 oce_fw_clean(POCE_SOFTC sc)
130 {
131 	struct oce_bmbx *mbx;
132 	uint8_t *ptr;
133 	int ret = 0;
134 
135 	mbx = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
136 	ptr = (uint8_t *) &mbx->mbx;
137 
138 	/* Endian Signature */
139 	*ptr++ = 0xff;
140 	*ptr++ = 0xaa;
141 	*ptr++ = 0xbb;
142 	*ptr++ = 0xff;
143 	*ptr++ = 0xff;
144 	*ptr++ = 0xcc;
145 	*ptr++ = 0xdd;
146 	*ptr = 0xff;
147 
148 	ret = oce_mbox_dispatch(sc, 2);
149 
150 	return ret;
151 }
152 
153 
154 /**
155  * @brief Mailbox wait
156  * @param sc		software handle to the device
157  * @param tmo_sec	timeout in seconds
158  */
159 static int
160 oce_mbox_wait(POCE_SOFTC sc, uint32_t tmo_sec)
161 {
162 	tmo_sec *= 10000;
163 	pd_mpu_mbox_db_t mbox_db;
164 
165 	for (;;) {
166 		if (tmo_sec != 0) {
167 			if (--tmo_sec == 0)
168 				break;
169 		}
170 
171 		mbox_db.dw0 = OCE_READ_REG32(sc, db, PD_MPU_MBOX_DB);
172 
173 		if (mbox_db.bits.ready)
174 			return 0;
175 
176 		DELAY(100);
177 	}
178 
179 	device_printf(sc->dev, "Mailbox timed out\n");
180 
181 	return ETIMEDOUT;
182 }
183 
184 
185 /**
186  * @brief Mailbox dispatch
187  * @param sc		software handle to the device
188  * @param tmo_sec	timeout in seconds
189  */
190 int
191 oce_mbox_dispatch(POCE_SOFTC sc, uint32_t tmo_sec)
192 {
193 	pd_mpu_mbox_db_t mbox_db;
194 	uint32_t pa;
195 	int rc;
196 
197 	oce_dma_sync(&sc->bsmbx, BUS_DMASYNC_PREWRITE);
198 	pa = (uint32_t) ((uint64_t) sc->bsmbx.paddr >> 34);
199 	bzero(&mbox_db, sizeof(pd_mpu_mbox_db_t));
200 	mbox_db.bits.ready = 0;
201 	mbox_db.bits.hi = 1;
202 	mbox_db.bits.address = pa;
203 
204 	rc = oce_mbox_wait(sc, tmo_sec);
205 	if (rc == 0) {
206 		OCE_WRITE_REG32(sc, db, PD_MPU_MBOX_DB, mbox_db.dw0);
207 
208 		pa = (uint32_t) ((uint64_t) sc->bsmbx.paddr >> 4) & 0x3fffffff;
209 		mbox_db.bits.ready = 0;
210 		mbox_db.bits.hi = 0;
211 		mbox_db.bits.address = pa;
212 
213 		rc = oce_mbox_wait(sc, tmo_sec);
214 
215 		if (rc == 0) {
216 			OCE_WRITE_REG32(sc, db, PD_MPU_MBOX_DB, mbox_db.dw0);
217 
218 			rc = oce_mbox_wait(sc, tmo_sec);
219 
220 			oce_dma_sync(&sc->bsmbx, BUS_DMASYNC_POSTWRITE);
221 		}
222 	}
223 
224 	return rc;
225 }
226 
227 
228 
229 /**
230  * @brief 		Mailbox common request header initialization
231  * @param hdr		mailbox header
232  * @param dom		domain
233  * @param port		port
234  * @param subsys	subsystem
235  * @param opcode	opcode
236  * @param timeout	timeout
237  * @param pyld_len	payload length
238  */
239 void
240 mbx_common_req_hdr_init(struct mbx_hdr *hdr,
241 			uint8_t dom, uint8_t port,
242 			uint8_t subsys, uint8_t opcode,
243 			uint32_t timeout, uint32_t pyld_len,
244 			uint8_t version)
245 {
246 	hdr->u0.req.opcode = opcode;
247 	hdr->u0.req.subsystem = subsys;
248 	hdr->u0.req.port_number = port;
249 	hdr->u0.req.domain = dom;
250 
251 	hdr->u0.req.timeout = timeout;
252 	hdr->u0.req.request_length = pyld_len - sizeof(struct mbx_hdr);
253 	hdr->u0.req.version = version;
254 }
255 
256 
257 
258 /**
259  * @brief Function to initialize the hw with host endian information
260  * @param sc		software handle to the device
261  * @returns		0 on success, ETIMEDOUT on failure
262  */
263 int
264 oce_mbox_init(POCE_SOFTC sc)
265 {
266 	struct oce_bmbx *mbx;
267 	uint8_t *ptr;
268 	int ret = 0;
269 
270 	if (sc->flags & OCE_FLAGS_MBOX_ENDIAN_RQD) {
271 		mbx = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
272 		ptr = (uint8_t *) &mbx->mbx;
273 
274 		/* Endian Signature */
275 		*ptr++ = 0xff;
276 		*ptr++ = 0x12;
277 		*ptr++ = 0x34;
278 		*ptr++ = 0xff;
279 		*ptr++ = 0xff;
280 		*ptr++ = 0x56;
281 		*ptr++ = 0x78;
282 		*ptr = 0xff;
283 
284 		ret = oce_mbox_dispatch(sc, 0);
285 	}
286 
287 	return ret;
288 }
289 
290 
291 /**
292  * @brief 		Function to get the firmware version
293  * @param sc		software handle to the device
294  * @returns		0 on success, EIO on failure
295  */
296 int
297 oce_get_fw_version(POCE_SOFTC sc)
298 {
299 	struct oce_mbx mbx;
300 	struct mbx_get_common_fw_version *fwcmd;
301 	int ret = 0;
302 
303 	bzero(&mbx, sizeof(struct oce_mbx));
304 
305 	fwcmd = (struct mbx_get_common_fw_version *)&mbx.payload;
306 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
307 				MBX_SUBSYSTEM_COMMON,
308 				OPCODE_COMMON_GET_FW_VERSION,
309 				MBX_TIMEOUT_SEC,
310 				sizeof(struct mbx_get_common_fw_version),
311 				OCE_MBX_VER_V0);
312 
313 	mbx.u0.s.embedded = 1;
314 	mbx.payload_length = sizeof(struct mbx_get_common_fw_version);
315 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
316 
317 	ret = oce_mbox_post(sc, &mbx, NULL);
318 	if (!ret)
319                 ret = fwcmd->hdr.u0.rsp.status;
320 	if (ret) {
321 		device_printf(sc->dev,
322 			      "%s failed - cmd status: %d addi status: %d\n",
323 			      __FUNCTION__, ret,
324 			      fwcmd->hdr.u0.rsp.additional_status);
325 		goto error;
326 	}
327 
328 	bcopy(fwcmd->params.rsp.fw_ver_str, sc->fw_version, 32);
329 error:
330 	return ret;
331 }
332 
333 
334 /**
335  * @brief	Firmware will send gracious notifications during
336  *		attach only after sending first mcc commnad. We
337  *		use MCC queue only for getting async and mailbox
338  *		for sending cmds. So to get gracious notifications
339  *		atleast send one dummy command on mcc.
340  */
341 int
342 oce_first_mcc_cmd(POCE_SOFTC sc)
343 {
344 	struct oce_mbx *mbx;
345 	struct oce_mq *mq = sc->mq;
346 	struct mbx_get_common_fw_version *fwcmd;
347 	uint32_t reg_value;
348 
349 	mbx = RING_GET_PRODUCER_ITEM_VA(mq->ring, struct oce_mbx);
350 	bzero(mbx, sizeof(struct oce_mbx));
351 
352 	fwcmd = (struct mbx_get_common_fw_version *)&mbx->payload;
353 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
354 				MBX_SUBSYSTEM_COMMON,
355 				OPCODE_COMMON_GET_FW_VERSION,
356 				MBX_TIMEOUT_SEC,
357 				sizeof(struct mbx_get_common_fw_version),
358 				OCE_MBX_VER_V0);
359 	mbx->u0.s.embedded = 1;
360 	mbx->payload_length = sizeof(struct mbx_get_common_fw_version);
361 	bus_dmamap_sync(mq->ring->dma.tag, mq->ring->dma.map,
362 				BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
363 	RING_PUT(mq->ring, 1);
364 	reg_value = (1 << 16) | mq->mq_id;
365 	OCE_WRITE_REG32(sc, db, PD_MQ_DB, reg_value);
366 
367 	return 0;
368 }
369 
370 /**
371  * @brief		Function to post a MBX to the mbox
372  * @param sc		software handle to the device
373  * @param mbx 		pointer to the MBX to send
374  * @param mbxctx	pointer to the mbx context structure
375  * @returns		0 on success, error on failure
376  */
377 int
378 oce_mbox_post(POCE_SOFTC sc, struct oce_mbx *mbx, struct oce_mbx_ctx *mbxctx)
379 {
380 	struct oce_mbx *mb_mbx = NULL;
381 	struct oce_mq_cqe *mb_cqe = NULL;
382 	struct oce_bmbx *mb = NULL;
383 	int rc = 0;
384 	uint32_t tmo = 0;
385 	uint32_t cstatus = 0;
386 	uint32_t xstatus = 0;
387 
388 	LOCK(&sc->bmbx_lock);
389 
390 	mb = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
391 	mb_mbx = &mb->mbx;
392 
393 	/* get the tmo */
394 	tmo = mbx->tag[0];
395 	mbx->tag[0] = 0;
396 
397 	/* copy mbx into mbox */
398 	bcopy(mbx, mb_mbx, sizeof(struct oce_mbx));
399 
400 	/* now dispatch */
401 	rc = oce_mbox_dispatch(sc, tmo);
402 	if (rc == 0) {
403 		/*
404 		 * the command completed successfully. Now get the
405 		 * completion queue entry
406 		 */
407 		mb_cqe = &mb->cqe;
408 		DW_SWAP(u32ptr(&mb_cqe->u0.dw[0]), sizeof(struct oce_mq_cqe));
409 
410 		/* copy mbox mbx back */
411 		bcopy(mb_mbx, mbx, sizeof(struct oce_mbx));
412 
413 		/* pick up the mailbox status */
414 		cstatus = mb_cqe->u0.s.completion_status;
415 		xstatus = mb_cqe->u0.s.extended_status;
416 
417 		/*
418 		 * store the mbx context in the cqe tag section so that
419 		 * the upper layer handling the cqe can associate the mbx
420 		 * with the response
421 		 */
422 		if (cstatus == 0 && mbxctx) {
423 			/* save context */
424 			mbxctx->mbx = mb_mbx;
425 			bcopy(&mbxctx, mb_cqe->u0.s.mq_tag,
426 				sizeof(struct oce_mbx_ctx *));
427 		}
428 	}
429 
430 	UNLOCK(&sc->bmbx_lock);
431 
432 	return rc;
433 }
434 
435 /**
436  * @brief Function to read the mac address associated with an interface
437  * @param sc		software handle to the device
438  * @param if_id 	interface id to read the address from
439  * @param perm 		set to 1 if reading the factory mac address.
440  *			In this case if_id is ignored
441  * @param type 		type of the mac address, whether network or storage
442  * @param[out] mac 	[OUTPUT] pointer to a buffer containing the
443  *			mac address when the command succeeds.
444  * @returns		0 on success, EIO on failure
445  */
446 int
447 oce_read_mac_addr(POCE_SOFTC sc, uint32_t if_id,
448 		uint8_t perm, uint8_t type, struct mac_address_format *mac)
449 {
450 	struct oce_mbx mbx;
451 	struct mbx_query_common_iface_mac *fwcmd;
452 	int ret = 0;
453 
454 	bzero(&mbx, sizeof(struct oce_mbx));
455 
456 	fwcmd = (struct mbx_query_common_iface_mac *)&mbx.payload;
457 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
458 				MBX_SUBSYSTEM_COMMON,
459 				OPCODE_COMMON_QUERY_IFACE_MAC,
460 				MBX_TIMEOUT_SEC,
461 				sizeof(struct mbx_query_common_iface_mac),
462 				OCE_MBX_VER_V0);
463 
464 	fwcmd->params.req.permanent = perm;
465 	if (!perm)
466 		fwcmd->params.req.if_id = (uint16_t) if_id;
467 	else
468 		fwcmd->params.req.if_id = 0;
469 
470 	fwcmd->params.req.type = type;
471 
472 	mbx.u0.s.embedded = 1;
473 	mbx.payload_length = sizeof(struct mbx_query_common_iface_mac);
474 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
475 
476 	ret = oce_mbox_post(sc, &mbx, NULL);
477 	if (!ret)
478                 ret = fwcmd->hdr.u0.rsp.status;
479 	if (ret) {
480 		device_printf(sc->dev,
481 			      "%s failed - cmd status: %d addi status: %d\n",
482 			      __FUNCTION__, ret,
483 			      fwcmd->hdr.u0.rsp.additional_status);
484 		goto error;
485 	}
486 
487 	/* copy the mac addres in the output parameter */
488 	mac->size_of_struct = fwcmd->params.rsp.mac.size_of_struct;
489 	bcopy(&fwcmd->params.rsp.mac.mac_addr[0], &mac->mac_addr[0],
490 		mac->size_of_struct);
491 error:
492 	return ret;
493 }
494 
495 /**
496  * @brief Function to query the fw attributes from the hw
497  * @param sc		software handle to the device
498  * @returns		0 on success, EIO on failure
499  */
500 int
501 oce_get_fw_config(POCE_SOFTC sc)
502 {
503 	struct oce_mbx mbx;
504 	struct mbx_common_query_fw_config *fwcmd;
505 	int ret = 0;
506 
507 	bzero(&mbx, sizeof(struct oce_mbx));
508 
509 	fwcmd = (struct mbx_common_query_fw_config *)&mbx.payload;
510 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
511 				MBX_SUBSYSTEM_COMMON,
512 				OPCODE_COMMON_QUERY_FIRMWARE_CONFIG,
513 				MBX_TIMEOUT_SEC,
514 				sizeof(struct mbx_common_query_fw_config),
515 				OCE_MBX_VER_V0);
516 
517 	mbx.u0.s.embedded = 1;
518 	mbx.payload_length = sizeof(struct mbx_common_query_fw_config);
519 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
520 
521 	ret = oce_mbox_post(sc, &mbx, NULL);
522 	if (!ret)
523                 ret = fwcmd->hdr.u0.rsp.status;
524 	if (ret) {
525 		device_printf(sc->dev,
526 			      "%s failed - cmd status: %d addi status: %d\n",
527 			      __FUNCTION__, ret,
528 			      fwcmd->hdr.u0.rsp.additional_status);
529 		goto error;
530 	}
531 
532 	DW_SWAP(u32ptr(fwcmd), sizeof(struct mbx_common_query_fw_config));
533 
534 	sc->config_number = HOST_32(fwcmd->params.rsp.config_number);
535 	sc->asic_revision = HOST_32(fwcmd->params.rsp.asic_revision);
536 	sc->port_id	  = HOST_32(fwcmd->params.rsp.port_id);
537 	sc->function_mode = HOST_32(fwcmd->params.rsp.function_mode);
538 	if ((sc->function_mode & (ULP_NIC_MODE | ULP_RDMA_MODE)) ==
539 	    (ULP_NIC_MODE | ULP_RDMA_MODE)) {
540 	  sc->rdma_flags = OCE_RDMA_FLAG_SUPPORTED;
541 	}
542 	sc->function_caps = HOST_32(fwcmd->params.rsp.function_caps);
543 
544 	if (fwcmd->params.rsp.ulp[0].ulp_mode & ULP_NIC_MODE) {
545 		sc->max_tx_rings = HOST_32(fwcmd->params.rsp.ulp[0].nic_wq_tot);
546 		sc->max_rx_rings = HOST_32(fwcmd->params.rsp.ulp[0].lro_rqid_tot);
547 	} else {
548 		sc->max_tx_rings = HOST_32(fwcmd->params.rsp.ulp[1].nic_wq_tot);
549 		sc->max_rx_rings = HOST_32(fwcmd->params.rsp.ulp[1].lro_rqid_tot);
550 	}
551 
552 error:
553 	return ret;
554 
555 }
556 
557 /**
558  *
559  * @brief function to create a device interface
560  * @param sc		software handle to the device
561  * @param cap_flags	capability flags
562  * @param en_flags	enable capability flags
563  * @param vlan_tag	optional vlan tag to associate with the if
564  * @param mac_addr	pointer to a buffer containing the mac address
565  * @param[out] if_id	[OUTPUT] pointer to an integer to hold the ID of the
566  interface created
567  * @returns		0 on success, EIO on failure
568  */
569 int
570 oce_if_create(POCE_SOFTC sc,
571 		uint32_t cap_flags,
572 		uint32_t en_flags,
573 		uint16_t vlan_tag,
574 		uint8_t *mac_addr,
575 		uint32_t *if_id)
576 {
577 	struct oce_mbx mbx;
578 	struct mbx_create_common_iface *fwcmd;
579 	int rc = 0;
580 
581 	bzero(&mbx, sizeof(struct oce_mbx));
582 
583 	fwcmd = (struct mbx_create_common_iface *)&mbx.payload;
584 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
585 				MBX_SUBSYSTEM_COMMON,
586 				OPCODE_COMMON_CREATE_IFACE,
587 				MBX_TIMEOUT_SEC,
588 				sizeof(struct mbx_create_common_iface),
589 				OCE_MBX_VER_V0);
590 	DW_SWAP(u32ptr(&fwcmd->hdr), sizeof(struct mbx_hdr));
591 
592 	fwcmd->params.req.version = 0;
593 	fwcmd->params.req.cap_flags = LE_32(cap_flags);
594 	fwcmd->params.req.enable_flags = LE_32(en_flags);
595 	if (mac_addr != NULL) {
596 		bcopy(mac_addr, &fwcmd->params.req.mac_addr[0], 6);
597 		fwcmd->params.req.vlan_tag.u0.normal.vtag = LE_16(vlan_tag);
598 		fwcmd->params.req.mac_invalid = 0;
599 	} else {
600 		fwcmd->params.req.mac_invalid = 1;
601 	}
602 
603 	mbx.u0.s.embedded = 1;
604 	mbx.payload_length = sizeof(struct mbx_create_common_iface);
605 	DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ);
606 
607 	rc = oce_mbox_post(sc, &mbx, NULL);
608 	if (!rc)
609                 rc = fwcmd->hdr.u0.rsp.status;
610 	if (rc) {
611 		device_printf(sc->dev,
612 			      "%s failed - cmd status: %d addi status: %d\n",
613 			      __FUNCTION__, rc,
614 			      fwcmd->hdr.u0.rsp.additional_status);
615 		goto error;
616 	}
617 
618 	*if_id = HOST_32(fwcmd->params.rsp.if_id);
619 
620 	if (mac_addr != NULL)
621 		sc->pmac_id = HOST_32(fwcmd->params.rsp.pmac_id);
622 error:
623 	return rc;
624 }
625 
626 /**
627  * @brief		Function to delete an interface
628  * @param sc 		software handle to the device
629  * @param if_id		ID of the interface to delete
630  * @returns		0 on success, EIO on failure
631  */
632 int
633 oce_if_del(POCE_SOFTC sc, uint32_t if_id)
634 {
635 	struct oce_mbx mbx;
636 	struct mbx_destroy_common_iface *fwcmd;
637 	int rc = 0;
638 
639 	bzero(&mbx, sizeof(struct oce_mbx));
640 
641 	fwcmd = (struct mbx_destroy_common_iface *)&mbx.payload;
642 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
643 				MBX_SUBSYSTEM_COMMON,
644 				OPCODE_COMMON_DESTROY_IFACE,
645 				MBX_TIMEOUT_SEC,
646 				sizeof(struct mbx_destroy_common_iface),
647 				OCE_MBX_VER_V0);
648 
649 	fwcmd->params.req.if_id = if_id;
650 
651 	mbx.u0.s.embedded = 1;
652 	mbx.payload_length = sizeof(struct mbx_destroy_common_iface);
653 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
654 
655 	rc = oce_mbox_post(sc, &mbx, NULL);
656 	if (!rc)
657                 rc = fwcmd->hdr.u0.rsp.status;
658 	if (rc)
659 		device_printf(sc->dev,
660 			      "%s failed - cmd status: %d addi status: %d\n",
661 			      __FUNCTION__, rc,
662 			      fwcmd->hdr.u0.rsp.additional_status);
663 	return rc;
664 }
665 
666 /**
667  * @brief Function to send the mbx command to configure vlan
668  * @param sc 		software handle to the device
669  * @param if_id 	interface identifier index
670  * @param vtag_arr	array of vlan tags
671  * @param vtag_cnt	number of elements in array
672  * @param untagged	boolean TRUE/FLASE
673  * @param enable_promisc flag to enable/disable VLAN promiscuous mode
674  * @returns		0 on success, EIO on failure
675  */
676 int
677 oce_config_vlan(POCE_SOFTC sc,
678 		uint32_t if_id,
679 		struct normal_vlan *vtag_arr,
680 		uint8_t vtag_cnt, uint32_t untagged, uint32_t enable_promisc)
681 {
682 	struct oce_mbx mbx;
683 	struct mbx_common_config_vlan *fwcmd;
684 	int rc = 0;
685 
686 	if (sc->vlans_added > sc->max_vlans)
687 		goto vlan_promisc;
688 
689 	bzero(&mbx, sizeof(struct oce_mbx));
690 	fwcmd = (struct mbx_common_config_vlan *)&mbx.payload;
691 
692 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
693 				MBX_SUBSYSTEM_COMMON,
694 				OPCODE_COMMON_CONFIG_IFACE_VLAN,
695 				MBX_TIMEOUT_SEC,
696 				sizeof(struct mbx_common_config_vlan),
697 				OCE_MBX_VER_V0);
698 
699 	fwcmd->params.req.if_id = (uint8_t) if_id;
700 	fwcmd->params.req.promisc = (uint8_t) enable_promisc;
701 	fwcmd->params.req.untagged = (uint8_t) untagged;
702 	fwcmd->params.req.num_vlans = vtag_cnt;
703 
704 	if (!enable_promisc) {
705 		bcopy(vtag_arr, fwcmd->params.req.tags.normal_vlans,
706 			vtag_cnt * sizeof(struct normal_vlan));
707 	}
708 	mbx.u0.s.embedded = 1;
709 	mbx.payload_length = sizeof(struct mbx_common_config_vlan);
710 	DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + mbx.payload_length));
711 
712 	rc = oce_mbox_post(sc, &mbx, NULL);
713 	if (!rc)
714                 rc = fwcmd->hdr.u0.rsp.status;
715 	if (rc)
716 		device_printf(sc->dev,
717 			      "%s failed - cmd status: %d addi status: %d\n",
718 			      __FUNCTION__, rc,
719 			      fwcmd->hdr.u0.rsp.additional_status);
720 
721 	goto done;
722 
723 vlan_promisc:
724 	/* Enable Vlan Promis */
725 	oce_rxf_set_promiscuous(sc, (1 << 1));
726 	device_printf(sc->dev,"Enabling Vlan Promisc Mode\n");
727 done:
728 	return rc;
729 
730 }
731 
732 /**
733  * @brief Function to set flow control capability in the hardware
734  * @param sc 		software handle to the device
735  * @param flow_control	flow control flags to set
736  * @returns		0 on success, EIO on failure
737  */
738 int
739 oce_set_flow_control(POCE_SOFTC sc, uint32_t flow_control)
740 {
741 	struct oce_mbx mbx;
742 	struct mbx_common_get_set_flow_control *fwcmd =
743 		(struct mbx_common_get_set_flow_control *)&mbx.payload;
744 	int rc;
745 
746 	bzero(&mbx, sizeof(struct oce_mbx));
747 
748 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
749 				MBX_SUBSYSTEM_COMMON,
750 				OPCODE_COMMON_SET_FLOW_CONTROL,
751 				MBX_TIMEOUT_SEC,
752 				sizeof(struct mbx_common_get_set_flow_control),
753 				OCE_MBX_VER_V0);
754 
755 	if (flow_control & OCE_FC_TX)
756 		fwcmd->tx_flow_control = 1;
757 
758 	if (flow_control & OCE_FC_RX)
759 		fwcmd->rx_flow_control = 1;
760 
761 	mbx.u0.s.embedded = 1;
762 	mbx.payload_length = sizeof(struct mbx_common_get_set_flow_control);
763 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
764 
765 	rc = oce_mbox_post(sc, &mbx, NULL);
766 	if (!rc)
767                 rc = fwcmd->hdr.u0.rsp.status;
768 	if (rc)
769 		device_printf(sc->dev,
770 			      "%s failed - cmd status: %d addi status: %d\n",
771 			      __FUNCTION__, rc,
772 			      fwcmd->hdr.u0.rsp.additional_status);
773 	return rc;
774 }
775 
776 /**
777  * @brief Initialize the RSS CPU indirection table
778  *
779  * The table is used to choose the queue to place the incomming packets.
780  * Incomming packets are hashed.  The lowest bits in the hash result
781  * are used as the index into the CPU indirection table.
782  * Each entry in the table contains the RSS CPU-ID returned by the NIC
783  * create.  Based on the CPU ID, the receive completion is routed to
784  * the corresponding RSS CQs.  (Non-RSS packets are always completed
785  * on the default (0) CQ).
786  *
787  * @param sc 		software handle to the device
788  * @param *fwcmd	pointer to the rss mbox command
789  * @returns		none
790  */
791 static int
792 oce_rss_itbl_init(POCE_SOFTC sc, struct mbx_config_nic_rss *fwcmd)
793 {
794 	int i = 0, j = 0, rc = 0;
795 	uint8_t *tbl = fwcmd->params.req.cputable;
796 	struct oce_rq *rq = NULL;
797 
798 
799 	for (j = 0; j < INDIRECTION_TABLE_ENTRIES ; j += (sc->nrqs - 1)) {
800 		for_all_rss_queues(sc, rq, i) {
801 			if ((j + i) >= INDIRECTION_TABLE_ENTRIES)
802 				break;
803 			tbl[j + i] = rq->rss_cpuid;
804 		}
805 	}
806 	if (i == 0) {
807 		device_printf(sc->dev, "error: Invalid number of RSS RQ's\n");
808 		rc = ENXIO;
809 
810 	}
811 
812 	/* fill log2 value indicating the size of the CPU table */
813 	if (rc == 0)
814 		fwcmd->params.req.cpu_tbl_sz_log2 = LE_16(OCE_LOG2(INDIRECTION_TABLE_ENTRIES));
815 
816 	return rc;
817 }
818 
819 /**
820  * @brief Function to set flow control capability in the hardware
821  * @param sc 		software handle to the device
822  * @param if_id 	interface id to read the address from
823  * @param enable_rss	0=disable, RSS_ENABLE_xxx flags otherwise
824  * @returns		0 on success, EIO on failure
825  */
826 int
827 oce_config_nic_rss(POCE_SOFTC sc, uint32_t if_id, uint16_t enable_rss)
828 {
829 	int rc;
830 	struct oce_mbx mbx;
831 	struct mbx_config_nic_rss *fwcmd =
832 				(struct mbx_config_nic_rss *)&mbx.payload;
833 	int version;
834 
835 	bzero(&mbx, sizeof(struct oce_mbx));
836 
837 	if (IS_XE201(sc) || IS_SH(sc)) {
838 		version = OCE_MBX_VER_V1;
839 		fwcmd->params.req.enable_rss = RSS_ENABLE_UDP_IPV4 |
840 					       RSS_ENABLE_UDP_IPV6;
841 	} else
842 		version = OCE_MBX_VER_V0;
843 
844 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
845 				MBX_SUBSYSTEM_NIC,
846 				NIC_CONFIG_RSS,
847 				MBX_TIMEOUT_SEC,
848 				sizeof(struct mbx_config_nic_rss),
849 				version);
850 	if (enable_rss)
851 		fwcmd->params.req.enable_rss |= (RSS_ENABLE_IPV4 |
852 					         RSS_ENABLE_TCP_IPV4 |
853 						 RSS_ENABLE_IPV6 |
854 						 RSS_ENABLE_TCP_IPV6);
855 
856 	if(!sc->enable_hwlro)
857 		fwcmd->params.req.flush = OCE_FLUSH;
858 	else
859 		fwcmd->params.req.flush = 0;
860 
861 	fwcmd->params.req.if_id = LE_32(if_id);
862 
863 	srandom(arc4random());	/* random entropy seed */
864 	read_random(fwcmd->params.req.hash, sizeof(fwcmd->params.req.hash));
865 
866 	rc = oce_rss_itbl_init(sc, fwcmd);
867 	if (rc == 0) {
868 		mbx.u0.s.embedded = 1;
869 		mbx.payload_length = sizeof(struct mbx_config_nic_rss);
870 		DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
871 
872 		rc = oce_mbox_post(sc, &mbx, NULL);
873 		if (!rc)
874                 	rc = fwcmd->hdr.u0.rsp.status;
875 		if (rc)
876 		device_printf(sc->dev,
877 			      "%s failed - cmd status: %d addi status: %d\n",
878 			      __FUNCTION__, rc,
879 			      fwcmd->hdr.u0.rsp.additional_status);
880 	}
881 	return rc;
882 }
883 
884 /**
885  * @brief 		RXF function to enable/disable device promiscuous mode
886  * @param sc		software handle to the device
887  * @param enable	enable/disable flag
888  * @returns		0 on success, EIO on failure
889  * @note
890  *	The NIC_CONFIG_PROMISCUOUS command deprecated for Lancer.
891  *	This function uses the COMMON_SET_IFACE_RX_FILTER command instead.
892  */
893 int
894 oce_rxf_set_promiscuous(POCE_SOFTC sc, uint8_t enable)
895 {
896 	struct mbx_set_common_iface_rx_filter *fwcmd;
897 	int sz = sizeof(struct mbx_set_common_iface_rx_filter);
898 	iface_rx_filter_ctx_t *req;
899 	OCE_DMA_MEM sgl;
900 	int rc;
901 
902 	/* allocate mbx payload's dma scatter/gather memory */
903 	rc = oce_dma_alloc(sc, sz, &sgl, 0);
904 	if (rc)
905 		return rc;
906 
907 	fwcmd = OCE_DMAPTR(&sgl, struct mbx_set_common_iface_rx_filter);
908 
909 	req =  &fwcmd->params.req;
910 	req->iface_flags_mask = MBX_RX_IFACE_FLAGS_PROMISCUOUS |
911 				MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS;
912 	/* Bit 0 Mac promisc, Bit 1 Vlan promisc */
913 	if (enable & 0x01)
914 		req->iface_flags = MBX_RX_IFACE_FLAGS_PROMISCUOUS;
915 
916 	if (enable & 0x02)
917 		req->iface_flags |= MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS;
918 
919 	req->if_id = sc->if_id;
920 
921 	rc = oce_set_common_iface_rx_filter(sc, &sgl);
922 	oce_dma_free(sc, &sgl);
923 
924 	return rc;
925 }
926 
927 
928 /**
929  * @brief 			Function modify and select rx filter options
930  * @param sc			software handle to the device
931  * @param sgl			scatter/gather request/response
932  * @returns			0 on success, error code on failure
933  */
934 int
935 oce_set_common_iface_rx_filter(POCE_SOFTC sc, POCE_DMA_MEM sgl)
936 {
937 	struct oce_mbx mbx;
938 	int mbx_sz = sizeof(struct mbx_set_common_iface_rx_filter);
939 	struct mbx_set_common_iface_rx_filter *fwcmd;
940 	int rc;
941 
942 	bzero(&mbx, sizeof(struct oce_mbx));
943 	fwcmd = OCE_DMAPTR(sgl, struct mbx_set_common_iface_rx_filter);
944 
945 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
946 				MBX_SUBSYSTEM_COMMON,
947 				OPCODE_COMMON_SET_IFACE_RX_FILTER,
948 				MBX_TIMEOUT_SEC,
949 				mbx_sz,
950 				OCE_MBX_VER_V0);
951 
952 	oce_dma_sync(sgl, BUS_DMASYNC_PREWRITE);
953 	mbx.u0.s.embedded = 0;
954 	mbx.u0.s.sge_count = 1;
955 	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(sgl->paddr);
956 	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(sgl->paddr);
957 	mbx.payload.u0.u1.sgl[0].length = mbx_sz;
958 	mbx.payload_length = mbx_sz;
959 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
960 
961 	rc = oce_mbox_post(sc, &mbx, NULL);
962 	if (!rc)
963                 rc = fwcmd->hdr.u0.rsp.status;
964 	if (rc)
965 		device_printf(sc->dev,
966 			      "%s failed - cmd status: %d addi status: %d\n",
967 			      __FUNCTION__, rc,
968 			      fwcmd->hdr.u0.rsp.additional_status);
969 	return rc;
970 }
971 
972 /**
973  * @brief Function to query the link status from the hardware
974  * @param sc 		software handle to the device
975  * @param[out] link	pointer to the structure returning link attributes
976  * @returns		0 on success, EIO on failure
977  */
978 int
979 oce_get_link_status(POCE_SOFTC sc, struct link_status *link)
980 {
981 	struct oce_mbx mbx;
982 	struct mbx_query_common_link_config *fwcmd;
983 	int rc = 0, version;
984 
985 	bzero(&mbx, sizeof(struct oce_mbx));
986 
987 	IS_BE2(sc) ? (version = OCE_MBX_VER_V0) : (version = OCE_MBX_VER_V1);
988 
989 	fwcmd = (struct mbx_query_common_link_config *)&mbx.payload;
990 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
991 				MBX_SUBSYSTEM_COMMON,
992 				OPCODE_COMMON_QUERY_LINK_CONFIG,
993 				MBX_TIMEOUT_SEC,
994 				sizeof(struct mbx_query_common_link_config),
995 				version);
996 
997 	mbx.u0.s.embedded = 1;
998 	mbx.payload_length = sizeof(struct mbx_query_common_link_config);
999 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1000 
1001 	rc = oce_mbox_post(sc, &mbx, NULL);
1002 
1003 	if (!rc)
1004                 rc = fwcmd->hdr.u0.rsp.status;
1005 	if (rc) {
1006 		device_printf(sc->dev,
1007 			      "%s failed - cmd status: %d addi status: %d\n",
1008 			      __FUNCTION__, rc,
1009 			      fwcmd->hdr.u0.rsp.additional_status);
1010 		goto error;
1011 	}
1012 	/* interpret response */
1013 	link->qos_link_speed = HOST_16(fwcmd->params.rsp.qos_link_speed);
1014 	link->phys_port_speed = fwcmd->params.rsp.physical_port_speed;
1015 	link->logical_link_status = fwcmd->params.rsp.logical_link_status;
1016 error:
1017 	return rc;
1018 }
1019 
1020 
1021 /**
1022  * @brief Function to get NIC statistics
1023  * @param sc            software handle to the device
1024  * @param *stats        pointer to where to store statistics
1025  * @param reset_stats   resets statistics of set
1026  * @returns             0 on success, EIO on failure
1027  * @note                command depricated in Lancer
1028  */
1029 #define OCE_MBOX_GET_NIC_STATS(sc, pstats_dma_mem, version) 				\
1030 int 											\
1031 oce_mbox_get_nic_stats_v##version(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem) 		\
1032 { 											\
1033         struct oce_mbx mbx; 								\
1034         struct mbx_get_nic_stats_v##version *fwcmd; 					\
1035         int rc = 0; 									\
1036 											\
1037         bzero(&mbx, sizeof(struct oce_mbx)); 						\
1038         fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_nic_stats_v##version); 	\
1039         bzero(fwcmd, sizeof(*fwcmd)); 							\
1040 											\
1041         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 					\
1042                                 MBX_SUBSYSTEM_NIC, 					\
1043                                 NIC_GET_STATS, 						\
1044                                 MBX_TIMEOUT_SEC, 					\
1045                                 sizeof(*fwcmd), 					\
1046                                 OCE_MBX_VER_V##version); 				\
1047 											\
1048         mbx.u0.s.embedded = 0;  /* stats too large for embedded mbx rsp */ 		\
1049         mbx.u0.s.sge_count = 1; /* using scatter gather instead */ 			\
1050 											\
1051         oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE); 				\
1052         mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);		\
1053         mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr); 		\
1054         mbx.payload.u0.u1.sgl[0].length = sizeof(*fwcmd); 				\
1055         mbx.payload_length = sizeof(*fwcmd); 						\
1056         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 			\
1057 											\
1058         rc = oce_mbox_post(sc, &mbx, NULL); 						\
1059         oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE); 				\
1060         if (!rc) 									\
1061                 rc = fwcmd->hdr.u0.rsp.status; 						\
1062         if (rc) 									\
1063                 device_printf(sc->dev, 							\
1064                               "%s failed - cmd status: %d addi status: %d\n", 		\
1065                               __FUNCTION__, rc, 					\
1066                               fwcmd->hdr.u0.rsp.additional_status); 			\
1067         return rc; 									\
1068 }
1069 
1070 OCE_MBOX_GET_NIC_STATS(sc, pstats_dma_mem, 0);
1071 OCE_MBOX_GET_NIC_STATS(sc, pstats_dma_mem, 1);
1072 OCE_MBOX_GET_NIC_STATS(sc, pstats_dma_mem, 2);
1073 
1074 
1075 /**
1076  * @brief Function to get pport (physical port) statistics
1077  * @param sc 		software handle to the device
1078  * @param *stats	pointer to where to store statistics
1079  * @param reset_stats	resets statistics of set
1080  * @returns		0 on success, EIO on failure
1081  */
1082 int
1083 oce_mbox_get_pport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem,
1084 				uint32_t reset_stats)
1085 {
1086 	struct oce_mbx mbx;
1087 	struct mbx_get_pport_stats *fwcmd;
1088 	int rc = 0;
1089 
1090 	bzero(&mbx, sizeof(struct oce_mbx));
1091 	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_pport_stats);
1092 	bzero(fwcmd, sizeof(struct mbx_get_pport_stats));
1093 
1094 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1095 				MBX_SUBSYSTEM_NIC,
1096 				NIC_GET_PPORT_STATS,
1097 				MBX_TIMEOUT_SEC,
1098 				sizeof(struct mbx_get_pport_stats),
1099 				OCE_MBX_VER_V0);
1100 
1101 	fwcmd->params.req.reset_stats = reset_stats;
1102 	fwcmd->params.req.port_number = sc->port_id;
1103 
1104 	mbx.u0.s.embedded = 0;	/* stats too large for embedded mbx rsp */
1105 	mbx.u0.s.sge_count = 1; /* using scatter gather instead */
1106 
1107 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
1108 	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
1109 	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
1110 	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_pport_stats);
1111 
1112 	mbx.payload_length = sizeof(struct mbx_get_pport_stats);
1113 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1114 
1115 	rc = oce_mbox_post(sc, &mbx, NULL);
1116 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
1117 
1118 	if (!rc)
1119                 rc = fwcmd->hdr.u0.rsp.status;
1120 	if (rc)
1121 		device_printf(sc->dev,
1122 			      "%s failed - cmd status: %d addi status: %d\n",
1123 			      __FUNCTION__, rc,
1124 			      fwcmd->hdr.u0.rsp.additional_status);
1125 	return rc;
1126 }
1127 
1128 
1129 /**
1130  * @brief Function to get vport (virtual port) statistics
1131  * @param sc 		software handle to the device
1132  * @param *stats	pointer to where to store statistics
1133  * @param reset_stats	resets statistics of set
1134  * @returns		0 on success, EIO on failure
1135  */
1136 int
1137 oce_mbox_get_vport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem,
1138 				uint32_t req_size, uint32_t reset_stats)
1139 {
1140 	struct oce_mbx mbx;
1141 	struct mbx_get_vport_stats *fwcmd;
1142 	int rc = 0;
1143 
1144 	bzero(&mbx, sizeof(struct oce_mbx));
1145 
1146 	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_vport_stats);
1147 	bzero(fwcmd, sizeof(struct mbx_get_vport_stats));
1148 
1149 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1150 				MBX_SUBSYSTEM_NIC,
1151 				NIC_GET_VPORT_STATS,
1152 				MBX_TIMEOUT_SEC,
1153 				sizeof(struct mbx_get_vport_stats),
1154 				OCE_MBX_VER_V0);
1155 
1156 	fwcmd->params.req.reset_stats = reset_stats;
1157 	fwcmd->params.req.vport_number = sc->if_id;
1158 
1159 	mbx.u0.s.embedded = 0;	/* stats too large for embedded mbx rsp */
1160 	mbx.u0.s.sge_count = 1; /* using scatter gather instead */
1161 
1162 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
1163 	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
1164 	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
1165 	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_vport_stats);
1166 
1167 	mbx.payload_length = sizeof(struct mbx_get_vport_stats);
1168 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1169 
1170 	rc = oce_mbox_post(sc, &mbx, NULL);
1171 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
1172 
1173 	if (!rc)
1174                 rc = fwcmd->hdr.u0.rsp.status;
1175 	if (rc)
1176 		device_printf(sc->dev,
1177 			      "%s failed - cmd status: %d addi status: %d\n",
1178 			      __FUNCTION__, rc,
1179 			      fwcmd->hdr.u0.rsp.additional_status);
1180 	return rc;
1181 }
1182 
1183 
1184 /**
1185  * @brief               Function to update the muticast filter with
1186  *                      values in dma_mem
1187  * @param sc            software handle to the device
1188  * @param dma_mem       pointer to dma memory region
1189  * @returns             0 on success, EIO on failure
1190  */
1191 int
1192 oce_update_multicast(POCE_SOFTC sc, POCE_DMA_MEM pdma_mem)
1193 {
1194 	struct oce_mbx mbx;
1195 	struct oce_mq_sge *sgl;
1196 	struct mbx_set_common_iface_multicast *req = NULL;
1197 	int rc = 0;
1198 
1199 	req = OCE_DMAPTR(pdma_mem, struct mbx_set_common_iface_multicast);
1200 	mbx_common_req_hdr_init(&req->hdr, 0, 0,
1201 				MBX_SUBSYSTEM_COMMON,
1202 				OPCODE_COMMON_SET_IFACE_MULTICAST,
1203 				MBX_TIMEOUT_SEC,
1204 				sizeof(struct mbx_set_common_iface_multicast),
1205 				OCE_MBX_VER_V0);
1206 
1207 	bzero(&mbx, sizeof(struct oce_mbx));
1208 
1209 	mbx.u0.s.embedded = 0; /*Non embeded*/
1210 	mbx.payload_length = sizeof(struct mbx_set_common_iface_multicast);
1211 	mbx.u0.s.sge_count = 1;
1212 	sgl = &mbx.payload.u0.u1.sgl[0];
1213 	sgl->pa_hi = htole32(upper_32_bits(pdma_mem->paddr));
1214 	sgl->pa_lo = htole32((pdma_mem->paddr) & 0xFFFFFFFF);
1215 	sgl->length = htole32(mbx.payload_length);
1216 
1217 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1218 
1219 	rc = oce_mbox_post(sc, &mbx, NULL);
1220 	if (!rc)
1221                 rc = req->hdr.u0.rsp.status;
1222 	if (rc)
1223 		device_printf(sc->dev,
1224 			      "%s failed - cmd status: %d addi status: %d\n",
1225 			      __FUNCTION__, rc,
1226 			      req->hdr.u0.rsp.additional_status);
1227 	return rc;
1228 }
1229 
1230 
1231 /**
1232  * @brief               Function to send passthrough Ioctls
1233  * @param sc            software handle to the device
1234  * @param dma_mem       pointer to dma memory region
1235  * @param req_size      size of dma_mem
1236  * @returns             0 on success, EIO on failure
1237  */
1238 int
1239 oce_pass_through_mbox(POCE_SOFTC sc, POCE_DMA_MEM dma_mem, uint32_t req_size)
1240 {
1241 	struct oce_mbx mbx;
1242 	struct oce_mq_sge *sgl;
1243 	int rc = 0;
1244 
1245 	bzero(&mbx, sizeof(struct oce_mbx));
1246 
1247 	mbx.u0.s.embedded  = 0; /*Non embeded*/
1248 	mbx.payload_length = req_size;
1249 	mbx.u0.s.sge_count = 1;
1250 	sgl = &mbx.payload.u0.u1.sgl[0];
1251 	sgl->pa_hi = htole32(upper_32_bits(dma_mem->paddr));
1252 	sgl->pa_lo = htole32((dma_mem->paddr) & 0xFFFFFFFF);
1253 	sgl->length = htole32(req_size);
1254 
1255 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1256 
1257 	rc = oce_mbox_post(sc, &mbx, NULL);
1258 	return rc;
1259 }
1260 
1261 
1262 int
1263 oce_mbox_macaddr_add(POCE_SOFTC sc, uint8_t *mac_addr,
1264 		 uint32_t if_id, uint32_t *pmac_id)
1265 {
1266 	struct oce_mbx mbx;
1267 	struct mbx_add_common_iface_mac *fwcmd;
1268 	int rc = 0;
1269 
1270 	bzero(&mbx, sizeof(struct oce_mbx));
1271 
1272 	fwcmd = (struct mbx_add_common_iface_mac *)&mbx.payload;
1273 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1274 				MBX_SUBSYSTEM_COMMON,
1275 				OPCODE_COMMON_ADD_IFACE_MAC,
1276 				MBX_TIMEOUT_SEC,
1277 				sizeof(struct mbx_add_common_iface_mac),
1278 				OCE_MBX_VER_V0);
1279 
1280 	fwcmd->params.req.if_id = (uint16_t) if_id;
1281 	bcopy(mac_addr, fwcmd->params.req.mac_address, 6);
1282 
1283 	mbx.u0.s.embedded = 1;
1284 	mbx.payload_length = sizeof(struct  mbx_add_common_iface_mac);
1285 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1286 	rc = oce_mbox_post(sc, &mbx, NULL);
1287 	if (!rc)
1288                 rc = fwcmd->hdr.u0.rsp.status;
1289 	if (rc) {
1290 		device_printf(sc->dev,
1291 			      "%s failed - cmd status: %d addi status: %d\n",
1292 			      __FUNCTION__, rc,
1293 			      fwcmd->hdr.u0.rsp.additional_status);
1294 		goto error;
1295 	}
1296 	*pmac_id = fwcmd->params.rsp.pmac_id;
1297 error:
1298 	return rc;
1299 }
1300 
1301 
1302 int
1303 oce_mbox_macaddr_del(POCE_SOFTC sc, uint32_t if_id, uint32_t pmac_id)
1304 {
1305 	struct oce_mbx mbx;
1306 	struct mbx_del_common_iface_mac *fwcmd;
1307 	int rc = 0;
1308 
1309 	bzero(&mbx, sizeof(struct oce_mbx));
1310 
1311 	fwcmd = (struct mbx_del_common_iface_mac *)&mbx.payload;
1312 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1313 				MBX_SUBSYSTEM_COMMON,
1314 				OPCODE_COMMON_DEL_IFACE_MAC,
1315 				MBX_TIMEOUT_SEC,
1316 				sizeof(struct mbx_del_common_iface_mac),
1317 				OCE_MBX_VER_V0);
1318 
1319 	fwcmd->params.req.if_id = (uint16_t)if_id;
1320 	fwcmd->params.req.pmac_id = pmac_id;
1321 
1322 	mbx.u0.s.embedded = 1;
1323 	mbx.payload_length = sizeof(struct  mbx_del_common_iface_mac);
1324 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1325 
1326 	rc = oce_mbox_post(sc, &mbx, NULL);
1327 	if (!rc)
1328                 rc = fwcmd->hdr.u0.rsp.status;
1329 	if (rc)
1330 		device_printf(sc->dev,
1331 			      "%s failed - cmd status: %d addi status: %d\n",
1332 			      __FUNCTION__, rc,
1333 			      fwcmd->hdr.u0.rsp.additional_status);
1334 	return rc;
1335 }
1336 
1337 
1338 
1339 int
1340 oce_mbox_check_native_mode(POCE_SOFTC sc)
1341 {
1342 	struct oce_mbx mbx;
1343 	struct mbx_common_set_function_cap *fwcmd;
1344 	int rc = 0;
1345 
1346 	bzero(&mbx, sizeof(struct oce_mbx));
1347 
1348 	fwcmd = (struct mbx_common_set_function_cap *)&mbx.payload;
1349 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1350 				MBX_SUBSYSTEM_COMMON,
1351 				OPCODE_COMMON_SET_FUNCTIONAL_CAPS,
1352 				MBX_TIMEOUT_SEC,
1353 				sizeof(struct mbx_common_set_function_cap),
1354 				OCE_MBX_VER_V0);
1355 
1356 	fwcmd->params.req.valid_capability_flags = CAP_SW_TIMESTAMPS |
1357 							CAP_BE3_NATIVE_ERX_API;
1358 
1359 	fwcmd->params.req.capability_flags = CAP_BE3_NATIVE_ERX_API;
1360 
1361 	mbx.u0.s.embedded = 1;
1362 	mbx.payload_length = sizeof(struct mbx_common_set_function_cap);
1363 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1364 
1365 	rc = oce_mbox_post(sc, &mbx, NULL);
1366 	if (!rc)
1367                 rc = fwcmd->hdr.u0.rsp.status;
1368 	if (rc) {
1369 		device_printf(sc->dev,
1370 			      "%s failed - cmd status: %d addi status: %d\n",
1371 			      __FUNCTION__, rc,
1372 			      fwcmd->hdr.u0.rsp.additional_status);
1373 		goto error;
1374 	}
1375 	sc->be3_native = HOST_32(fwcmd->params.rsp.capability_flags)
1376 			& CAP_BE3_NATIVE_ERX_API;
1377 
1378 error:
1379 	return 0;
1380 }
1381 
1382 
1383 
1384 int
1385 oce_mbox_cmd_set_loopback(POCE_SOFTC sc, uint8_t port_num,
1386 		uint8_t loopback_type, uint8_t enable)
1387 {
1388 	struct oce_mbx mbx;
1389 	struct mbx_lowlevel_set_loopback_mode *fwcmd;
1390 	int rc = 0;
1391 
1392 
1393 	bzero(&mbx, sizeof(struct oce_mbx));
1394 
1395 	fwcmd = (struct mbx_lowlevel_set_loopback_mode *)&mbx.payload;
1396 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1397 				MBX_SUBSYSTEM_LOWLEVEL,
1398 				OPCODE_LOWLEVEL_SET_LOOPBACK_MODE,
1399 				MBX_TIMEOUT_SEC,
1400 				sizeof(struct mbx_lowlevel_set_loopback_mode),
1401 				OCE_MBX_VER_V0);
1402 
1403 	fwcmd->params.req.src_port = port_num;
1404 	fwcmd->params.req.dest_port = port_num;
1405 	fwcmd->params.req.loopback_type = loopback_type;
1406 	fwcmd->params.req.loopback_state = enable;
1407 
1408 	mbx.u0.s.embedded = 1;
1409 	mbx.payload_length = sizeof(struct  mbx_lowlevel_set_loopback_mode);
1410 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1411 
1412 	rc = oce_mbox_post(sc, &mbx, NULL);
1413 	if (!rc)
1414                 rc = fwcmd->hdr.u0.rsp.status;
1415 	if (rc)
1416 		device_printf(sc->dev,
1417 			      "%s failed - cmd status: %d addi status: %d\n",
1418 			      __FUNCTION__, rc,
1419 			      fwcmd->hdr.u0.rsp.additional_status);
1420 
1421 	return rc;
1422 
1423 }
1424 
1425 int
1426 oce_mbox_cmd_test_loopback(POCE_SOFTC sc, uint32_t port_num,
1427 	uint32_t loopback_type, uint32_t pkt_size, uint32_t num_pkts,
1428 	uint64_t pattern)
1429 {
1430 
1431 	struct oce_mbx mbx;
1432 	struct mbx_lowlevel_test_loopback_mode *fwcmd;
1433 	int rc = 0;
1434 
1435 
1436 	bzero(&mbx, sizeof(struct oce_mbx));
1437 
1438 	fwcmd = (struct mbx_lowlevel_test_loopback_mode *)&mbx.payload;
1439 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1440 				MBX_SUBSYSTEM_LOWLEVEL,
1441 				OPCODE_LOWLEVEL_TEST_LOOPBACK,
1442 				MBX_TIMEOUT_SEC,
1443 				sizeof(struct mbx_lowlevel_test_loopback_mode),
1444 				OCE_MBX_VER_V0);
1445 
1446 	fwcmd->params.req.pattern = pattern;
1447 	fwcmd->params.req.src_port = port_num;
1448 	fwcmd->params.req.dest_port = port_num;
1449 	fwcmd->params.req.pkt_size = pkt_size;
1450 	fwcmd->params.req.num_pkts = num_pkts;
1451 	fwcmd->params.req.loopback_type = loopback_type;
1452 
1453 	mbx.u0.s.embedded = 1;
1454 	mbx.payload_length = sizeof(struct  mbx_lowlevel_test_loopback_mode);
1455 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1456 
1457 	rc = oce_mbox_post(sc, &mbx, NULL);
1458 	if (!rc)
1459                 rc = fwcmd->hdr.u0.rsp.status;
1460 	if (rc)
1461 		device_printf(sc->dev,
1462 			      "%s failed - cmd status: %d addi status: %d\n",
1463 			      __FUNCTION__, rc,
1464 			      fwcmd->hdr.u0.rsp.additional_status);
1465 
1466 	return rc;
1467 }
1468 
1469 int
1470 oce_mbox_write_flashrom(POCE_SOFTC sc, uint32_t optype,uint32_t opcode,
1471 				POCE_DMA_MEM pdma_mem, uint32_t num_bytes)
1472 {
1473 
1474 	struct oce_mbx mbx;
1475 	struct oce_mq_sge *sgl = NULL;
1476 	struct mbx_common_read_write_flashrom *fwcmd = NULL;
1477 	int rc = 0, payload_len = 0;
1478 
1479 	bzero(&mbx, sizeof(struct oce_mbx));
1480 	fwcmd = OCE_DMAPTR(pdma_mem, struct mbx_common_read_write_flashrom);
1481 	payload_len = sizeof(struct mbx_common_read_write_flashrom) + 32*1024;
1482 
1483 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1484 				MBX_SUBSYSTEM_COMMON,
1485 				OPCODE_COMMON_WRITE_FLASHROM,
1486 				LONG_TIMEOUT,
1487 				payload_len,
1488 				OCE_MBX_VER_V0);
1489 
1490 	fwcmd->flash_op_type = LE_32(optype);
1491 	fwcmd->flash_op_code = LE_32(opcode);
1492 	fwcmd->data_buffer_size = LE_32(num_bytes);
1493 
1494 	mbx.u0.s.embedded  = 0; /*Non embeded*/
1495 	mbx.payload_length = payload_len;
1496 	mbx.u0.s.sge_count = 1;
1497 
1498 	sgl = &mbx.payload.u0.u1.sgl[0];
1499 	sgl->pa_hi = upper_32_bits(pdma_mem->paddr);
1500 	sgl->pa_lo = pdma_mem->paddr & 0xFFFFFFFF;
1501 	sgl->length = payload_len;
1502 
1503 	/* post the command */
1504 	rc = oce_mbox_post(sc, &mbx, NULL);
1505 	if (!rc)
1506                 rc = fwcmd->hdr.u0.rsp.status;
1507 	if (rc)
1508 		device_printf(sc->dev,
1509 			      "%s failed - cmd status: %d addi status: %d\n",
1510 			      __FUNCTION__, rc,
1511 			      fwcmd->hdr.u0.rsp.additional_status);
1512 
1513 	return rc;
1514 
1515 }
1516 
1517 int
1518 oce_mbox_get_flashrom_crc(POCE_SOFTC sc, uint8_t *flash_crc,
1519 				uint32_t offset, uint32_t optype)
1520 {
1521 
1522 	int rc = 0, payload_len = 0;
1523 	struct oce_mbx mbx;
1524 	struct mbx_common_read_write_flashrom *fwcmd;
1525 
1526 	bzero(&mbx, sizeof(struct oce_mbx));
1527 
1528 	fwcmd = (struct mbx_common_read_write_flashrom *)&mbx.payload;
1529 
1530 	/* Firmware requires extra 4 bytes with this ioctl. Since there
1531 	   is enough room in the mbx payload it should be good enough
1532 	   Reference: Bug 14853
1533 	*/
1534 	payload_len = sizeof(struct mbx_common_read_write_flashrom) + 4;
1535 
1536 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1537 				MBX_SUBSYSTEM_COMMON,
1538 				OPCODE_COMMON_READ_FLASHROM,
1539 				MBX_TIMEOUT_SEC,
1540 				payload_len,
1541 				OCE_MBX_VER_V0);
1542 
1543 	fwcmd->flash_op_type = optype;
1544 	fwcmd->flash_op_code = FLASHROM_OPER_REPORT;
1545 	fwcmd->data_offset = offset;
1546 	fwcmd->data_buffer_size = 0x4;
1547 
1548 	mbx.u0.s.embedded  = 1;
1549 	mbx.payload_length = payload_len;
1550 
1551 	/* post the command */
1552 	rc = oce_mbox_post(sc, &mbx, NULL);
1553 	if (!rc)
1554                 rc = fwcmd->hdr.u0.rsp.status;
1555 	if (rc) {
1556 		device_printf(sc->dev,
1557 			      "%s failed - cmd status: %d addi status: %d\n",
1558 			      __FUNCTION__, rc,
1559 			      fwcmd->hdr.u0.rsp.additional_status);
1560 		goto error;
1561 	}
1562 	bcopy(fwcmd->data_buffer, flash_crc, 4);
1563 error:
1564 	return rc;
1565 }
1566 
1567 int
1568 oce_mbox_get_phy_info(POCE_SOFTC sc, struct oce_phy_info *phy_info)
1569 {
1570 
1571 	struct oce_mbx mbx;
1572 	struct mbx_common_phy_info *fwcmd;
1573 	int rc = 0;
1574 
1575 	bzero(&mbx, sizeof(struct oce_mbx));
1576 
1577 	fwcmd = (struct mbx_common_phy_info *)&mbx.payload;
1578 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1579 				MBX_SUBSYSTEM_COMMON,
1580 				OPCODE_COMMON_GET_PHY_CONFIG,
1581 				MBX_TIMEOUT_SEC,
1582 				sizeof(struct mbx_common_phy_info),
1583 				OCE_MBX_VER_V0);
1584 
1585 	mbx.u0.s.embedded = 1;
1586 	mbx.payload_length = sizeof(struct  mbx_common_phy_info);
1587 
1588 	/* now post the command */
1589 	rc = oce_mbox_post(sc, &mbx, NULL);
1590 	if (!rc)
1591                 rc = fwcmd->hdr.u0.rsp.status;
1592 	if (rc) {
1593 		device_printf(sc->dev,
1594 			      "%s failed - cmd status: %d addi status: %d\n",
1595 			      __FUNCTION__, rc,
1596 			      fwcmd->hdr.u0.rsp.additional_status);
1597 		goto error;
1598 	}
1599 	phy_info->phy_type = HOST_16(fwcmd->params.rsp.phy_info.phy_type);
1600 	phy_info->interface_type =
1601 			HOST_16(fwcmd->params.rsp.phy_info.interface_type);
1602 	phy_info->auto_speeds_supported =
1603 		HOST_16(fwcmd->params.rsp.phy_info.auto_speeds_supported);
1604 	phy_info->fixed_speeds_supported =
1605 		HOST_16(fwcmd->params.rsp.phy_info.fixed_speeds_supported);
1606 	phy_info->misc_params = HOST_32(fwcmd->params.rsp.phy_info.misc_params);
1607 error:
1608 	return rc;
1609 
1610 }
1611 
1612 
1613 int
1614 oce_mbox_lancer_write_flashrom(POCE_SOFTC sc, uint32_t data_size,
1615 			uint32_t data_offset, POCE_DMA_MEM pdma_mem,
1616 			uint32_t *written_data, uint32_t *additional_status)
1617 {
1618 
1619 	struct oce_mbx mbx;
1620 	struct mbx_lancer_common_write_object *fwcmd = NULL;
1621 	int rc = 0, payload_len = 0;
1622 
1623 	bzero(&mbx, sizeof(struct oce_mbx));
1624 	payload_len = sizeof(struct mbx_lancer_common_write_object);
1625 
1626 	mbx.u0.s.embedded  = 1;/* Embedded */
1627 	mbx.payload_length = payload_len;
1628 	fwcmd = (struct mbx_lancer_common_write_object *)&mbx.payload;
1629 
1630 	/* initialize the ioctl header */
1631 	mbx_common_req_hdr_init(&fwcmd->params.req.hdr, 0, 0,
1632 				MBX_SUBSYSTEM_COMMON,
1633 				OPCODE_COMMON_WRITE_OBJECT,
1634 				LONG_TIMEOUT,
1635 				payload_len,
1636 				OCE_MBX_VER_V0);
1637 
1638 	fwcmd->params.req.write_length = data_size;
1639 	if (data_size == 0)
1640 		fwcmd->params.req.eof = 1;
1641 	else
1642 		fwcmd->params.req.eof = 0;
1643 
1644 	strcpy(fwcmd->params.req.object_name, "/prg");
1645 	fwcmd->params.req.descriptor_count = 1;
1646 	fwcmd->params.req.write_offset = data_offset;
1647 	fwcmd->params.req.buffer_length = data_size;
1648 	fwcmd->params.req.address_lower = pdma_mem->paddr & 0xFFFFFFFF;
1649 	fwcmd->params.req.address_upper = upper_32_bits(pdma_mem->paddr);
1650 
1651 	/* post the command */
1652 	rc = oce_mbox_post(sc, &mbx, NULL);
1653 	if (!rc)
1654                 rc = fwcmd->params.rsp.status;
1655 	if (rc) {
1656 		device_printf(sc->dev,
1657 			      "%s failed - cmd status: %d addi status: %d\n",
1658 			      __FUNCTION__, rc,
1659 			      fwcmd->params.rsp.additional_status);
1660 		goto error;
1661 	}
1662 	*written_data = HOST_32(fwcmd->params.rsp.actual_write_length);
1663 	*additional_status = fwcmd->params.rsp.additional_status;
1664 error:
1665 	return rc;
1666 
1667 }
1668 
1669 
1670 
1671 int
1672 oce_mbox_create_rq(struct oce_rq *rq)
1673 {
1674 
1675 	struct oce_mbx mbx;
1676 	struct mbx_create_nic_rq *fwcmd;
1677 	POCE_SOFTC sc = rq->parent;
1678 	int rc, num_pages = 0;
1679 
1680 	if (rq->qstate == QCREATED)
1681 		return 0;
1682 
1683 	bzero(&mbx, sizeof(struct oce_mbx));
1684 
1685 	fwcmd = (struct mbx_create_nic_rq *)&mbx.payload;
1686 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1687 				MBX_SUBSYSTEM_NIC,
1688 				NIC_CREATE_RQ, MBX_TIMEOUT_SEC,
1689 				sizeof(struct mbx_create_nic_rq),
1690 				OCE_MBX_VER_V0);
1691 
1692 	/* oce_page_list will also prepare pages */
1693 	num_pages = oce_page_list(rq->ring, &fwcmd->params.req.pages[0]);
1694 
1695 	if (IS_XE201(sc)) {
1696 		fwcmd->params.req.frag_size = rq->cfg.frag_size/2048;
1697 		fwcmd->params.req.page_size = 1;
1698 		fwcmd->hdr.u0.req.version = OCE_MBX_VER_V1;
1699 	} else
1700 		fwcmd->params.req.frag_size = OCE_LOG2(rq->cfg.frag_size);
1701 	fwcmd->params.req.num_pages = num_pages;
1702 	fwcmd->params.req.cq_id = rq->cq->cq_id;
1703 	fwcmd->params.req.if_id = sc->if_id;
1704 	fwcmd->params.req.max_frame_size = rq->cfg.mtu;
1705 	fwcmd->params.req.is_rss_queue = rq->cfg.is_rss_queue;
1706 
1707 	mbx.u0.s.embedded = 1;
1708 	mbx.payload_length = sizeof(struct mbx_create_nic_rq);
1709 
1710 	rc = oce_mbox_post(sc, &mbx, NULL);
1711 	if (!rc)
1712                 rc = fwcmd->hdr.u0.rsp.status;
1713 	if (rc) {
1714 		device_printf(sc->dev,
1715 			      "%s failed - cmd status: %d addi status: %d\n",
1716 			      __FUNCTION__, rc,
1717 			      fwcmd->hdr.u0.rsp.additional_status);
1718 		goto error;
1719 	}
1720 	rq->rq_id = HOST_16(fwcmd->params.rsp.rq_id);
1721 	rq->rss_cpuid = fwcmd->params.rsp.rss_cpuid;
1722 error:
1723 	return rc;
1724 
1725 }
1726 
1727 
1728 
1729 int
1730 oce_mbox_create_wq(struct oce_wq *wq)
1731 {
1732 	struct oce_mbx mbx;
1733 	struct mbx_create_nic_wq *fwcmd;
1734 	POCE_SOFTC sc = wq->parent;
1735 	int rc = 0, version, num_pages;
1736 
1737 	bzero(&mbx, sizeof(struct oce_mbx));
1738 
1739 	fwcmd = (struct mbx_create_nic_wq *)&mbx.payload;
1740 	if (IS_XE201(sc))
1741 		version = OCE_MBX_VER_V1;
1742 	else if(IS_BE(sc))
1743 		IS_PROFILE_SUPER_NIC(sc) ? (version = OCE_MBX_VER_V2)
1744 					 : (version = OCE_MBX_VER_V0);
1745 	else
1746 		version = OCE_MBX_VER_V2;
1747 
1748 	if (version > OCE_MBX_VER_V0)
1749 		fwcmd->params.req.if_id = sc->if_id;
1750 
1751 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1752 				MBX_SUBSYSTEM_NIC,
1753 				NIC_CREATE_WQ, MBX_TIMEOUT_SEC,
1754 				sizeof(struct mbx_create_nic_wq),
1755 				version);
1756 
1757 	num_pages = oce_page_list(wq->ring, &fwcmd->params.req.pages[0]);
1758 
1759 	fwcmd->params.req.nic_wq_type = wq->cfg.wq_type;
1760 	fwcmd->params.req.num_pages = num_pages;
1761 	fwcmd->params.req.wq_size = OCE_LOG2(wq->cfg.q_len) + 1;
1762 	fwcmd->params.req.cq_id = wq->cq->cq_id;
1763 	fwcmd->params.req.ulp_num = 1;
1764 
1765 	mbx.u0.s.embedded = 1;
1766 	mbx.payload_length = sizeof(struct mbx_create_nic_wq);
1767 
1768 	rc = oce_mbox_post(sc, &mbx, NULL);
1769 	if (!rc)
1770                 rc = fwcmd->hdr.u0.rsp.status;
1771 	if (rc) {
1772 		device_printf(sc->dev,
1773 			      "%s failed - cmd status: %d addi status: %d\n",
1774 			      __FUNCTION__, rc,
1775 			      fwcmd->hdr.u0.rsp.additional_status);
1776 		goto error;
1777 	}
1778 	wq->wq_id = HOST_16(fwcmd->params.rsp.wq_id);
1779 	if (version == OCE_MBX_VER_V2)
1780 		wq->db_offset = HOST_32(fwcmd->params.rsp.db_offset);
1781 	else
1782 		wq->db_offset = PD_TXULP_DB;
1783 error:
1784 	return rc;
1785 
1786 }
1787 
1788 
1789 
1790 int
1791 oce_mbox_create_eq(struct oce_eq *eq)
1792 {
1793 	struct oce_mbx mbx;
1794 	struct mbx_create_common_eq *fwcmd;
1795 	POCE_SOFTC sc = eq->parent;
1796 	int rc = 0;
1797 	uint32_t num_pages;
1798 
1799 	bzero(&mbx, sizeof(struct oce_mbx));
1800 
1801 	fwcmd = (struct mbx_create_common_eq *)&mbx.payload;
1802 
1803 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1804 				MBX_SUBSYSTEM_COMMON,
1805 				OPCODE_COMMON_CREATE_EQ, MBX_TIMEOUT_SEC,
1806 				sizeof(struct mbx_create_common_eq),
1807 				OCE_MBX_VER_V0);
1808 
1809 	num_pages = oce_page_list(eq->ring, &fwcmd->params.req.pages[0]);
1810 	fwcmd->params.req.ctx.num_pages = num_pages;
1811 	fwcmd->params.req.ctx.valid = 1;
1812 	fwcmd->params.req.ctx.size = (eq->eq_cfg.item_size == 4) ? 0 : 1;
1813 	fwcmd->params.req.ctx.count = OCE_LOG2(eq->eq_cfg.q_len / 256);
1814 	fwcmd->params.req.ctx.armed = 0;
1815 	fwcmd->params.req.ctx.delay_mult = eq->eq_cfg.cur_eqd;
1816 
1817 
1818 	mbx.u0.s.embedded = 1;
1819 	mbx.payload_length = sizeof(struct mbx_create_common_eq);
1820 
1821 	rc = oce_mbox_post(sc, &mbx, NULL);
1822 	if (!rc)
1823                 rc = fwcmd->hdr.u0.rsp.status;
1824 	if (rc) {
1825 		device_printf(sc->dev,
1826 			      "%s failed - cmd status: %d addi status: %d\n",
1827 			      __FUNCTION__, rc,
1828 			      fwcmd->hdr.u0.rsp.additional_status);
1829 		goto error;
1830 	}
1831 	eq->eq_id = HOST_16(fwcmd->params.rsp.eq_id);
1832 error:
1833 	return rc;
1834 }
1835 
1836 
1837 
1838 int
1839 oce_mbox_cq_create(struct oce_cq *cq, uint32_t ncoalesce, uint32_t is_eventable)
1840 {
1841 	struct oce_mbx mbx;
1842 	struct mbx_create_common_cq *fwcmd;
1843 	POCE_SOFTC sc = cq->parent;
1844 	uint8_t version;
1845 	oce_cq_ctx_t *ctx;
1846 	uint32_t num_pages, page_size;
1847 	int rc = 0;
1848 
1849 
1850 	bzero(&mbx, sizeof(struct oce_mbx));
1851 
1852 	fwcmd = (struct mbx_create_common_cq *)&mbx.payload;
1853 
1854 	if (IS_XE201(sc))
1855 		version = OCE_MBX_VER_V2;
1856 	else
1857 		version = OCE_MBX_VER_V0;
1858 
1859 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1860 				MBX_SUBSYSTEM_COMMON,
1861 				OPCODE_COMMON_CREATE_CQ,
1862 				MBX_TIMEOUT_SEC,
1863 				sizeof(struct mbx_create_common_cq),
1864 				version);
1865 
1866 	ctx = &fwcmd->params.req.cq_ctx;
1867 
1868 	num_pages = oce_page_list(cq->ring, &fwcmd->params.req.pages[0]);
1869 	page_size =  1;  /* 1 for 4K */
1870 
1871 	if (version == OCE_MBX_VER_V2) {
1872 		ctx->v2.num_pages = LE_16(num_pages);
1873 		ctx->v2.page_size = page_size;
1874 		ctx->v2.eventable = is_eventable;
1875 		ctx->v2.valid = 1;
1876 		ctx->v2.count = OCE_LOG2(cq->cq_cfg.q_len / 256);
1877 		ctx->v2.nodelay = cq->cq_cfg.nodelay;
1878 		ctx->v2.coalesce_wm = ncoalesce;
1879 		ctx->v2.armed = 0;
1880 		ctx->v2.eq_id = cq->eq->eq_id;
1881 		if (ctx->v2.count == 3) {
1882 			if ((u_int)cq->cq_cfg.q_len > (4*1024)-1)
1883 				ctx->v2.cqe_count = (4*1024)-1;
1884 			else
1885 				ctx->v2.cqe_count = cq->cq_cfg.q_len;
1886 		}
1887 	} else {
1888 		ctx->v0.num_pages = LE_16(num_pages);
1889 		ctx->v0.eventable = is_eventable;
1890 		ctx->v0.valid = 1;
1891 		ctx->v0.count = OCE_LOG2(cq->cq_cfg.q_len / 256);
1892 		ctx->v0.nodelay = cq->cq_cfg.nodelay;
1893 		ctx->v0.coalesce_wm = ncoalesce;
1894 		ctx->v0.armed = 0;
1895 		ctx->v0.eq_id = cq->eq->eq_id;
1896 	}
1897 
1898 	mbx.u0.s.embedded = 1;
1899 	mbx.payload_length = sizeof(struct mbx_create_common_cq);
1900 
1901 	rc = oce_mbox_post(sc, &mbx, NULL);
1902 	if (!rc)
1903                 rc = fwcmd->hdr.u0.rsp.status;
1904 	if (rc) {
1905 		device_printf(sc->dev,
1906 			      "%s failed - cmd status: %d addi status: %d\n",
1907 			      __FUNCTION__, rc,
1908 			      fwcmd->hdr.u0.rsp.additional_status);
1909 		goto error;
1910 	}
1911 	cq->cq_id = HOST_16(fwcmd->params.rsp.cq_id);
1912 error:
1913 	return rc;
1914 
1915 }
1916 
1917 int
1918 oce_mbox_read_transrecv_data(POCE_SOFTC sc, uint32_t page_num)
1919 {
1920 	int rc = 0;
1921 	struct oce_mbx mbx;
1922 	struct mbx_read_common_transrecv_data *fwcmd;
1923 	struct oce_mq_sge *sgl;
1924 	OCE_DMA_MEM dma;
1925 
1926 	/* Allocate DMA mem*/
1927 	if (oce_dma_alloc(sc, sizeof(struct mbx_read_common_transrecv_data),
1928 				&dma, 0))
1929 		return ENOMEM;
1930 
1931 	fwcmd = OCE_DMAPTR(&dma, struct mbx_read_common_transrecv_data);
1932 	bzero(fwcmd, sizeof(struct mbx_read_common_transrecv_data));
1933 
1934 	bzero(&mbx, sizeof(struct oce_mbx));
1935 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1936 			MBX_SUBSYSTEM_COMMON,
1937 			OPCODE_COMMON_READ_TRANSRECEIVER_DATA,
1938 			MBX_TIMEOUT_SEC,
1939 			sizeof(struct mbx_read_common_transrecv_data),
1940 			OCE_MBX_VER_V0);
1941 
1942 	/* fill rest of mbx */
1943 	mbx.u0.s.embedded = 0;
1944 	mbx.payload_length = sizeof(struct mbx_read_common_transrecv_data);
1945 	mbx.u0.s.sge_count = 1;
1946 	sgl = &mbx.payload.u0.u1.sgl[0];
1947 	sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
1948 	sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
1949 	sgl->length = htole32(mbx.payload_length);
1950 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1951 
1952 	fwcmd->params.req.port = LE_32(sc->port_id);
1953 	fwcmd->params.req.page_num = LE_32(page_num);
1954 
1955 	/* command post */
1956 	rc = oce_mbox_post(sc, &mbx, NULL);
1957 	if (!rc)
1958 		rc = fwcmd->hdr.u0.rsp.status;
1959 	if (rc) {
1960 		device_printf(sc->dev,
1961 			      "%s failed - cmd status: %d addi status: %d\n",
1962 			      __FUNCTION__, rc,
1963 			      fwcmd->hdr.u0.rsp.additional_status);
1964 		goto error;
1965 	}
1966 	if(fwcmd->params.rsp.page_num == PAGE_NUM_A0)
1967 	{
1968 		bcopy((char *)fwcmd->params.rsp.page_data,
1969 				(char *)&sfp_vpd_dump_buffer[0],
1970 				TRANSCEIVER_A0_SIZE);
1971 	}
1972 
1973 	if(fwcmd->params.rsp.page_num == PAGE_NUM_A2)
1974 	{
1975 		bcopy((char *)fwcmd->params.rsp.page_data,
1976 				(char *)&sfp_vpd_dump_buffer[32],
1977 				TRANSCEIVER_A2_SIZE);
1978 	}
1979 error:
1980 	oce_dma_free(sc, &dma);
1981 	return rc;
1982 }
1983 
1984 void
1985 oce_mbox_eqd_modify_periodic(POCE_SOFTC sc, struct oce_set_eqd *set_eqd,
1986 				int num)
1987 {
1988 	struct oce_mbx mbx;
1989 	struct mbx_modify_common_eq_delay *fwcmd;
1990 	int rc = 0;
1991 	int i = 0;
1992 
1993 	bzero(&mbx, sizeof(struct oce_mbx));
1994 
1995 	/* Initialize MODIFY_EQ_DELAY ioctl header */
1996 	fwcmd = (struct mbx_modify_common_eq_delay *)&mbx.payload;
1997 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1998 				MBX_SUBSYSTEM_COMMON,
1999 				OPCODE_COMMON_MODIFY_EQ_DELAY,
2000 				MBX_TIMEOUT_SEC,
2001 				sizeof(struct mbx_modify_common_eq_delay),
2002 				OCE_MBX_VER_V0);
2003 	/* fill rest of mbx */
2004 	mbx.u0.s.embedded = 1;
2005 	mbx.payload_length = sizeof(struct mbx_modify_common_eq_delay);
2006 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
2007 
2008 	fwcmd->params.req.num_eq = num;
2009 	for (i = 0; i < num; i++) {
2010 		fwcmd->params.req.delay[i].eq_id =
2011 					htole32(set_eqd[i].eq_id);
2012 		fwcmd->params.req.delay[i].phase = 0;
2013 		fwcmd->params.req.delay[i].dm =
2014 		htole32(set_eqd[i].delay_multiplier);
2015 	}
2016 
2017 
2018 	/* command post */
2019 	rc = oce_mbox_post(sc, &mbx, NULL);
2020 
2021 	if (!rc)
2022 		rc = fwcmd->hdr.u0.rsp.status;
2023 	if (rc)
2024 		device_printf(sc->dev,
2025 			      "%s failed - cmd status: %d addi status: %d\n",
2026 			      __FUNCTION__, rc,
2027 			      fwcmd->hdr.u0.rsp.additional_status);
2028 }
2029 
2030 int
2031 oce_get_profile_config(POCE_SOFTC sc, uint32_t max_rss)
2032 {
2033 	struct oce_mbx mbx;
2034 	struct mbx_common_get_profile_config *fwcmd;
2035 	int rc = 0;
2036 	int version = 0;
2037 	struct oce_mq_sge *sgl;
2038 	OCE_DMA_MEM dma;
2039 	uint32_t desc_count = 0;
2040 	struct oce_nic_resc_desc *nic_desc = NULL;
2041 	int i;
2042 	boolean_t nic_desc_valid = FALSE;
2043 
2044 	if (IS_BE2(sc))
2045 		return -1;
2046 
2047 	/* Allocate DMA mem*/
2048 	if (oce_dma_alloc(sc, sizeof(struct mbx_common_get_profile_config),
2049 			  &dma, 0))
2050 		return ENOMEM;
2051 
2052 	/* Initialize MODIFY_EQ_DELAY ioctl header */
2053 	fwcmd = OCE_DMAPTR(&dma, struct mbx_common_get_profile_config);
2054 	bzero(fwcmd, sizeof(struct mbx_common_get_profile_config));
2055 
2056 	if (!IS_XE201(sc))
2057 		version = OCE_MBX_VER_V1;
2058 	else
2059 		version = OCE_MBX_VER_V0;
2060 
2061 	bzero(&mbx, sizeof(struct oce_mbx));
2062 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
2063 				MBX_SUBSYSTEM_COMMON,
2064 				OPCODE_COMMON_GET_PROFILE_CONFIG,
2065 				MBX_TIMEOUT_SEC,
2066 				sizeof(struct mbx_common_get_profile_config),
2067 				version);
2068 	/* fill rest of mbx */
2069 	mbx.u0.s.embedded = 0;
2070 	mbx.payload_length = sizeof(struct mbx_common_get_profile_config);
2071 	mbx.u0.s.sge_count = 1;
2072 	sgl = &mbx.payload.u0.u1.sgl[0];
2073 	sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
2074 	sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
2075 	sgl->length = htole32(mbx.payload_length);
2076 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
2077 
2078 	fwcmd->params.req.type = ACTIVE_PROFILE;
2079 
2080 	/* command post */
2081 	rc = oce_mbox_post(sc, &mbx, NULL);
2082 	if (!rc)
2083 		rc = fwcmd->hdr.u0.rsp.status;
2084 	if (rc) {
2085 		device_printf(sc->dev,
2086 			      "%s failed - cmd status: %d addi status: %d\n",
2087 			      __FUNCTION__, rc,
2088 			      fwcmd->hdr.u0.rsp.additional_status);
2089 		goto error;
2090 	}
2091 
2092 	nic_desc = (struct oce_nic_resc_desc *) fwcmd->params.rsp.resources;
2093 	desc_count = HOST_32(fwcmd->params.rsp.desc_count);
2094 	for (i = 0; i < desc_count; i++) {
2095 		if ((nic_desc->desc_type == NIC_RESC_DESC_TYPE_V0) ||
2096 		    (nic_desc->desc_type == NIC_RESC_DESC_TYPE_V1)) {
2097 			nic_desc_valid = TRUE;
2098 			break;
2099 		}
2100 		nic_desc = (struct oce_nic_resc_desc *) \
2101 				((char *)nic_desc + nic_desc->desc_len);
2102 	}
2103 	if (!nic_desc_valid) {
2104 		rc = -1;
2105 		goto error;
2106 	}
2107 	else {
2108 		sc->max_vlans = HOST_16(nic_desc->vlan_count);
2109 		sc->nwqs = HOST_16(nic_desc->txq_count);
2110 		if (sc->nwqs)
2111 			sc->nwqs = MIN(sc->nwqs, OCE_MAX_WQ);
2112 		else
2113 			sc->nwqs = OCE_MAX_WQ;
2114 
2115 		sc->nrssqs = HOST_16(nic_desc->rssq_count);
2116 		if (sc->nrssqs)
2117 			sc->nrssqs = MIN(sc->nrssqs, max_rss);
2118 		else
2119 			sc->nrssqs = max_rss;
2120 		sc->nrqs =  sc->nrssqs + 1; /* 1 for def RX */
2121 
2122 	}
2123 error:
2124 	oce_dma_free(sc, &dma);
2125 	return rc;
2126 
2127 }
2128 
2129 int
2130 oce_get_func_config(POCE_SOFTC sc)
2131 {
2132 	struct oce_mbx mbx;
2133 	struct mbx_common_get_func_config *fwcmd;
2134 	int rc = 0;
2135 	int version = 0;
2136 	struct oce_mq_sge *sgl;
2137 	OCE_DMA_MEM dma;
2138 	uint32_t desc_count = 0;
2139 	struct oce_nic_resc_desc *nic_desc = NULL;
2140 	int i;
2141 	boolean_t nic_desc_valid = FALSE;
2142 	uint32_t max_rss = 0;
2143 
2144 	if ((IS_BE(sc) || IS_SH(sc)) && (!sc->be3_native))
2145 		max_rss = OCE_LEGACY_MODE_RSS;
2146 	else
2147 		max_rss = OCE_MAX_RSS;
2148 
2149 	/* Allocate DMA mem*/
2150 	if (oce_dma_alloc(sc, sizeof(struct mbx_common_get_func_config),
2151 			  &dma, 0))
2152 		return ENOMEM;
2153 
2154 	/* Initialize MODIFY_EQ_DELAY ioctl header */
2155 	fwcmd = OCE_DMAPTR(&dma, struct mbx_common_get_func_config);
2156 	bzero(fwcmd, sizeof(struct mbx_common_get_func_config));
2157 
2158 	if (IS_SH(sc))
2159 		version = OCE_MBX_VER_V1;
2160 	else
2161 		version = OCE_MBX_VER_V0;
2162 
2163 	bzero(&mbx, sizeof(struct oce_mbx));
2164 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
2165 				MBX_SUBSYSTEM_COMMON,
2166 				OPCODE_COMMON_GET_FUNCTION_CONFIG,
2167 				MBX_TIMEOUT_SEC,
2168 				sizeof(struct mbx_common_get_func_config),
2169 				version);
2170 	/* fill rest of mbx */
2171 	mbx.u0.s.embedded = 0;
2172 	mbx.payload_length = sizeof(struct mbx_common_get_func_config);
2173 	mbx.u0.s.sge_count = 1;
2174 	sgl = &mbx.payload.u0.u1.sgl[0];
2175 	sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
2176 	sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
2177 	sgl->length = htole32(mbx.payload_length);
2178 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
2179 
2180 	/* command post */
2181 	rc = oce_mbox_post(sc, &mbx, NULL);
2182 	if (!rc)
2183 		rc = fwcmd->hdr.u0.rsp.status;
2184 	if (rc) {
2185 		device_printf(sc->dev,
2186 			      "%s failed - cmd status: %d addi status: %d\n",
2187 			      __FUNCTION__, rc,
2188 			      fwcmd->hdr.u0.rsp.additional_status);
2189 		goto error;
2190 	}
2191 
2192 	nic_desc = (struct oce_nic_resc_desc *) fwcmd->params.rsp.resources;
2193 	desc_count = HOST_32(fwcmd->params.rsp.desc_count);
2194 	for (i = 0; i < desc_count; i++) {
2195 		if ((nic_desc->desc_type == NIC_RESC_DESC_TYPE_V0) ||
2196 		    (nic_desc->desc_type == NIC_RESC_DESC_TYPE_V1)) {
2197 			nic_desc_valid = TRUE;
2198 			break;
2199 		}
2200 		nic_desc = (struct oce_nic_resc_desc *) \
2201 				((char *)nic_desc + nic_desc->desc_len);
2202 	}
2203 	if (!nic_desc_valid) {
2204 		rc = -1;
2205 		goto error;
2206 	}
2207 	else {
2208 		sc->max_vlans = nic_desc->vlan_count;
2209 		sc->nwqs = HOST_32(nic_desc->txq_count);
2210                 if (sc->nwqs)
2211                         sc->nwqs = MIN(sc->nwqs, OCE_MAX_WQ);
2212                 else
2213                         sc->nwqs = OCE_MAX_WQ;
2214 
2215 		sc->nrssqs = HOST_32(nic_desc->rssq_count);
2216 		if (sc->nrssqs)
2217 			sc->nrssqs = MIN(sc->nrssqs, max_rss);
2218 		else
2219 			sc->nrssqs = max_rss;
2220 		sc->nrqs =  sc->nrssqs + 1; /* 1 for def RX */
2221 	}
2222 error:
2223 	oce_dma_free(sc, &dma);
2224 	return rc;
2225 
2226 }
2227 
2228 /* hw lro functions */
2229 
2230 int
2231 oce_mbox_nic_query_lro_capabilities(POCE_SOFTC sc, uint32_t *lro_rq_cnt, uint32_t *lro_flags)
2232 {
2233         struct oce_mbx mbx;
2234         struct mbx_nic_query_lro_capabilities *fwcmd;
2235         int rc = 0;
2236 
2237         bzero(&mbx, sizeof(struct oce_mbx));
2238 
2239         fwcmd = (struct mbx_nic_query_lro_capabilities *)&mbx.payload;
2240         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
2241                                 MBX_SUBSYSTEM_NIC,
2242                                 0x20,MBX_TIMEOUT_SEC,
2243                                 sizeof(struct mbx_nic_query_lro_capabilities),
2244                                 OCE_MBX_VER_V0);
2245 
2246         mbx.u0.s.embedded = 1;
2247         mbx.payload_length = sizeof(struct mbx_nic_query_lro_capabilities);
2248 
2249         rc = oce_mbox_post(sc, &mbx, NULL);
2250         if (!rc)
2251                 rc = fwcmd->hdr.u0.rsp.status;
2252         if (rc) {
2253                 device_printf(sc->dev,
2254                               "%s failed - cmd status: %d addi status: %d\n",
2255                               __FUNCTION__, rc,
2256                               fwcmd->hdr.u0.rsp.additional_status);
2257 
2258                 return rc;
2259         }
2260         if(lro_flags)
2261                 *lro_flags = HOST_32(fwcmd->params.rsp.lro_flags);
2262 
2263         if(lro_rq_cnt)
2264                 *lro_rq_cnt = HOST_16(fwcmd->params.rsp.lro_rq_cnt);
2265 
2266         return rc;
2267 }
2268 
2269 int
2270 oce_mbox_nic_set_iface_lro_config(POCE_SOFTC sc, int enable)
2271 {
2272         struct oce_mbx mbx;
2273         struct mbx_nic_set_iface_lro_config *fwcmd;
2274         int rc = 0;
2275 
2276         bzero(&mbx, sizeof(struct oce_mbx));
2277 
2278         fwcmd = (struct mbx_nic_set_iface_lro_config *)&mbx.payload;
2279         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
2280                                 MBX_SUBSYSTEM_NIC,
2281                                 0x26,MBX_TIMEOUT_SEC,
2282                                 sizeof(struct mbx_nic_set_iface_lro_config),
2283                                 OCE_MBX_VER_V0);
2284 
2285         mbx.u0.s.embedded = 1;
2286         mbx.payload_length = sizeof(struct mbx_nic_set_iface_lro_config);
2287 
2288         fwcmd->params.req.iface_id = sc->if_id;
2289         fwcmd->params.req.lro_flags = 0;
2290 
2291         if(enable) {
2292                 fwcmd->params.req.lro_flags = LRO_FLAGS_HASH_MODE | LRO_FLAGS_RSS_MODE;
2293                 fwcmd->params.req.lro_flags |= LRO_FLAGS_CLSC_IPV4 | LRO_FLAGS_CLSC_IPV6;
2294 
2295                 fwcmd->params.req.max_clsc_byte_cnt = 64*1024; /* min = 2974, max = 0xfa59 */
2296                 fwcmd->params.req.max_clsc_seg_cnt = 43; /* min = 2, max = 64 */
2297                 fwcmd->params.req.max_clsc_usec_delay = 18; /* min = 1, max = 256 */
2298                 fwcmd->params.req.min_clsc_frame_byte_cnt = 0; /* min = 1, max = 9014 */
2299         }
2300 
2301         rc = oce_mbox_post(sc, &mbx, NULL);
2302         if (!rc)
2303                 rc = fwcmd->hdr.u0.rsp.status;
2304         if (rc) {
2305                 device_printf(sc->dev,
2306                               "%s failed - cmd status: %d addi status: %d\n",
2307                               __FUNCTION__, rc,
2308                               fwcmd->hdr.u0.rsp.additional_status);
2309 
2310                 return rc;
2311         }
2312         return rc;
2313 }
2314 
2315 int
2316 oce_mbox_create_rq_v2(struct oce_rq *rq)
2317 {
2318         struct oce_mbx mbx;
2319         struct mbx_create_nic_rq_v2 *fwcmd;
2320         POCE_SOFTC sc = rq->parent;
2321         int rc = 0, num_pages = 0;
2322 
2323         if (rq->qstate == QCREATED)
2324                 return 0;
2325 
2326         bzero(&mbx, sizeof(struct oce_mbx));
2327 
2328         fwcmd = (struct mbx_create_nic_rq_v2 *)&mbx.payload;
2329         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
2330                                 MBX_SUBSYSTEM_NIC,
2331                                 0x08, MBX_TIMEOUT_SEC,
2332                                 sizeof(struct mbx_create_nic_rq_v2),
2333                                 OCE_MBX_VER_V2);
2334 
2335         /* oce_page_list will also prepare pages */
2336         num_pages = oce_page_list(rq->ring, &fwcmd->params.req.pages[0]);
2337 
2338         fwcmd->params.req.cq_id = rq->cq->cq_id;
2339         fwcmd->params.req.frag_size = rq->cfg.frag_size/2048;
2340         fwcmd->params.req.num_pages = num_pages;
2341 
2342         fwcmd->params.req.if_id = sc->if_id;
2343 
2344         fwcmd->params.req.max_frame_size = rq->cfg.mtu;
2345         fwcmd->params.req.page_size = 1;
2346         if(rq->cfg.is_rss_queue) {
2347                 fwcmd->params.req.rq_flags = (NIC_RQ_FLAGS_RSS | NIC_RQ_FLAGS_LRO);
2348         }else {
2349                 device_printf(sc->dev,
2350                         "non rss lro queue should not be created \n");
2351                 goto error;
2352         }
2353         mbx.u0.s.embedded = 1;
2354         mbx.payload_length = sizeof(struct mbx_create_nic_rq_v2);
2355 
2356         rc = oce_mbox_post(sc, &mbx, NULL);
2357         if (!rc)
2358                 rc = fwcmd->hdr.u0.rsp.status;
2359         if (rc) {
2360                 device_printf(sc->dev,
2361                               "%s failed - cmd status: %d addi status: %d\n",
2362                               __FUNCTION__, rc,
2363                               fwcmd->hdr.u0.rsp.additional_status);
2364                 goto error;
2365         }
2366         rq->rq_id = HOST_16(fwcmd->params.rsp.rq_id);
2367         rq->rss_cpuid = fwcmd->params.rsp.rss_cpuid;
2368 
2369 error:
2370         return rc;
2371 }
2372 
2373