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