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