xref: /freebsd/sys/dev/oce/oce_mbox.c (revision c6ec7d31830ab1c80edae95ad5e4b9dba10c47ac)
1 /*-
2  * Copyright (C) 2012 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 /* $FreeBSD$ */
41 
42 #include "oce_if.h"
43 
44 
45 /**
46  * @brief Reset (firmware) common function
47  * @param sc		software handle to the device
48  * @returns		0 on success, ETIMEDOUT on failure
49  */
50 int
51 oce_reset_fun(POCE_SOFTC sc)
52 {
53 	struct oce_mbx *mbx;
54 	struct oce_bmbx *mb;
55 	struct ioctl_common_function_reset *fwcmd;
56 	int rc = 0;
57 
58 	if (sc->flags & OCE_FLAGS_FUNCRESET_RQD) {
59 		mb = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
60 		mbx = &mb->mbx;
61 		bzero(mbx, sizeof(struct oce_mbx));
62 
63 		fwcmd = (struct ioctl_common_function_reset *)&mbx->payload;
64 		mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
65 					MBX_SUBSYSTEM_COMMON,
66 					OPCODE_COMMON_FUNCTION_RESET,
67 					10,	/* MBX_TIMEOUT_SEC */
68 					sizeof(struct
69 					    ioctl_common_function_reset),
70 					OCE_MBX_VER_V0);
71 
72 		mbx->u0.s.embedded = 1;
73 		mbx->payload_length =
74 		    sizeof(struct ioctl_common_function_reset);
75 
76 		rc = oce_mbox_dispatch(sc, 2);
77 	}
78 
79 	return rc;
80 }
81 
82 
83 /**
84  * @brief  		This funtions tells firmware we are
85  *			done with commands.
86  * @param sc            software handle to the device
87  * @returns             0 on success, ETIMEDOUT on failure
88  */
89 int
90 oce_fw_clean(POCE_SOFTC sc)
91 {
92 	struct oce_bmbx *mbx;
93 	uint8_t *ptr;
94 	int ret = 0;
95 
96 	mbx = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
97 	ptr = (uint8_t *) &mbx->mbx;
98 
99 	/* Endian Signature */
100 	*ptr++ = 0xff;
101 	*ptr++ = 0xaa;
102 	*ptr++ = 0xbb;
103 	*ptr++ = 0xff;
104 	*ptr++ = 0xff;
105 	*ptr++ = 0xcc;
106 	*ptr++ = 0xdd;
107 	*ptr = 0xff;
108 
109 	ret = oce_mbox_dispatch(sc, 2);
110 
111 	return ret;
112 }
113 
114 
115 /**
116  * @brief Mailbox wait
117  * @param sc		software handle to the device
118  * @param tmo_sec	timeout in seconds
119  */
120 static int
121 oce_mbox_wait(POCE_SOFTC sc, uint32_t tmo_sec)
122 {
123 	tmo_sec *= 10000;
124 	pd_mpu_mbox_db_t mbox_db;
125 
126 	for (;;) {
127 		if (tmo_sec != 0) {
128 			if (--tmo_sec == 0)
129 				break;
130 		}
131 
132 		mbox_db.dw0 = OCE_READ_REG32(sc, db, PD_MPU_MBOX_DB);
133 
134 		if (mbox_db.bits.ready)
135 			return 0;
136 
137 		DELAY(100);
138 	}
139 
140 	device_printf(sc->dev, "Mailbox timed out\n");
141 
142 	return ETIMEDOUT;
143 }
144 
145 
146 /**
147  * @brief Mailbox dispatch
148  * @param sc		software handle to the device
149  * @param tmo_sec	timeout in seconds
150  */
151 int
152 oce_mbox_dispatch(POCE_SOFTC sc, uint32_t tmo_sec)
153 {
154 	pd_mpu_mbox_db_t mbox_db;
155 	uint32_t pa;
156 	int rc;
157 
158 	oce_dma_sync(&sc->bsmbx, BUS_DMASYNC_PREWRITE);
159 	pa = (uint32_t) ((uint64_t) sc->bsmbx.paddr >> 34);
160 	bzero(&mbox_db, sizeof(pd_mpu_mbox_db_t));
161 	mbox_db.bits.ready = 0;
162 	mbox_db.bits.hi = 1;
163 	mbox_db.bits.address = pa;
164 
165 	rc = oce_mbox_wait(sc, tmo_sec);
166 	if (rc == 0) {
167 		OCE_WRITE_REG32(sc, db, PD_MPU_MBOX_DB, mbox_db.dw0);
168 
169 		pa = (uint32_t) ((uint64_t) sc->bsmbx.paddr >> 4) & 0x3fffffff;
170 		mbox_db.bits.ready = 0;
171 		mbox_db.bits.hi = 0;
172 		mbox_db.bits.address = pa;
173 
174 		rc = oce_mbox_wait(sc, tmo_sec);
175 
176 		if (rc == 0) {
177 			OCE_WRITE_REG32(sc, db, PD_MPU_MBOX_DB, mbox_db.dw0);
178 
179 			rc = oce_mbox_wait(sc, tmo_sec);
180 
181 			oce_dma_sync(&sc->bsmbx, BUS_DMASYNC_POSTWRITE);
182 		}
183 	}
184 
185 	return rc;
186 }
187 
188 
189 
190 /**
191  * @brief 		Mailbox common request header initialization
192  * @param hdr		mailbox header
193  * @param dom		domain
194  * @param port		port
195  * @param subsys	subsystem
196  * @param opcode	opcode
197  * @param timeout	timeout
198  * @param pyld_len	payload length
199  */
200 void
201 mbx_common_req_hdr_init(struct mbx_hdr *hdr,
202 			uint8_t dom, uint8_t port,
203 			uint8_t subsys, uint8_t opcode,
204 			uint32_t timeout, uint32_t pyld_len,
205 			uint8_t version)
206 {
207 	hdr->u0.req.opcode = opcode;
208 	hdr->u0.req.subsystem = subsys;
209 	hdr->u0.req.port_number = port;
210 	hdr->u0.req.domain = dom;
211 
212 	hdr->u0.req.timeout = timeout;
213 	hdr->u0.req.request_length = pyld_len - sizeof(struct mbx_hdr);
214 	hdr->u0.req.version = version;
215 }
216 
217 
218 
219 /**
220  * @brief Function to initialize the hw with host endian information
221  * @param sc		software handle to the device
222  * @returns		0 on success, ETIMEDOUT on failure
223  */
224 int
225 oce_mbox_init(POCE_SOFTC sc)
226 {
227 	struct oce_bmbx *mbx;
228 	uint8_t *ptr;
229 	int ret = 0;
230 
231 	if (sc->flags & OCE_FLAGS_MBOX_ENDIAN_RQD) {
232 		mbx = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
233 		ptr = (uint8_t *) &mbx->mbx;
234 
235 		/* Endian Signature */
236 		*ptr++ = 0xff;
237 		*ptr++ = 0x12;
238 		*ptr++ = 0x34;
239 		*ptr++ = 0xff;
240 		*ptr++ = 0xff;
241 		*ptr++ = 0x56;
242 		*ptr++ = 0x78;
243 		*ptr = 0xff;
244 
245 		ret = oce_mbox_dispatch(sc, 0);
246 	}
247 
248 	return ret;
249 }
250 
251 
252 /**
253  * @brief 		Function to get the firmware version
254  * @param sc		software handle to the device
255  * @returns		0 on success, EIO on failure
256  */
257 int
258 oce_get_fw_version(POCE_SOFTC sc)
259 {
260 	struct oce_mbx mbx;
261 	struct mbx_get_common_fw_version *fwcmd;
262 	int ret = 0;
263 
264 	bzero(&mbx, sizeof(struct oce_mbx));
265 
266 	fwcmd = (struct mbx_get_common_fw_version *)&mbx.payload;
267 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
268 				MBX_SUBSYSTEM_COMMON,
269 				OPCODE_COMMON_GET_FW_VERSION,
270 				MBX_TIMEOUT_SEC,
271 				sizeof(struct mbx_get_common_fw_version),
272 				OCE_MBX_VER_V0);
273 
274 	mbx.u0.s.embedded = 1;
275 	mbx.payload_length = sizeof(struct mbx_get_common_fw_version);
276 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
277 
278 	ret = oce_mbox_post(sc, &mbx, NULL);
279 	if (ret)
280 		return ret;
281 
282 	bcopy(fwcmd->params.rsp.fw_ver_str, sc->fw_version, 32);
283 
284 	return 0;
285 }
286 
287 
288 /**
289  * @brief	Firmware will send gracious notifications during
290  *		attach only after sending first mcc commnad. We
291  *		use MCC queue only for getting async and mailbox
292  *		for sending cmds. So to get gracious notifications
293  *		atleast send one dummy command on mcc.
294  */
295 int
296 oce_first_mcc_cmd(POCE_SOFTC sc)
297 {
298 	struct oce_mbx *mbx;
299 	struct oce_mq *mq = sc->mq;
300 	struct mbx_get_common_fw_version *fwcmd;
301 	uint32_t reg_value;
302 
303 	mbx = RING_GET_PRODUCER_ITEM_VA(mq->ring, struct oce_mbx);
304 	bzero(mbx, sizeof(struct oce_mbx));
305 
306 	fwcmd = (struct mbx_get_common_fw_version *)&mbx->payload;
307 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
308 				MBX_SUBSYSTEM_COMMON,
309 				OPCODE_COMMON_GET_FW_VERSION,
310 				MBX_TIMEOUT_SEC,
311 				sizeof(struct mbx_get_common_fw_version),
312 				OCE_MBX_VER_V0);
313 	mbx->u0.s.embedded = 1;
314 	mbx->payload_length = sizeof(struct mbx_get_common_fw_version);
315 	bus_dmamap_sync(mq->ring->dma.tag, mq->ring->dma.map,
316 				BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
317 	RING_PUT(mq->ring, 1);
318 	reg_value = (1 << 16) | mq->mq_id;
319 	OCE_WRITE_REG32(sc, db, PD_MQ_DB, reg_value);
320 
321 	return 0;
322 }
323 
324 /**
325  * @brief		Function to post a MBX to the mbox
326  * @param sc		software handle to the device
327  * @param mbx 		pointer to the MBX to send
328  * @param mbxctx	pointer to the mbx context structure
329  * @returns		0 on success, error on failure
330  */
331 int
332 oce_mbox_post(POCE_SOFTC sc, struct oce_mbx *mbx, struct oce_mbx_ctx *mbxctx)
333 {
334 	struct oce_mbx *mb_mbx = NULL;
335 	struct oce_mq_cqe *mb_cqe = NULL;
336 	struct oce_bmbx *mb = NULL;
337 	int rc = 0;
338 	uint32_t tmo = 0;
339 	uint32_t cstatus = 0;
340 	uint32_t xstatus = 0;
341 
342 	LOCK(&sc->bmbx_lock);
343 
344 	mb = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
345 	mb_mbx = &mb->mbx;
346 
347 	/* get the tmo */
348 	tmo = mbx->tag[0];
349 	mbx->tag[0] = 0;
350 
351 	/* copy mbx into mbox */
352 	bcopy(mbx, mb_mbx, sizeof(struct oce_mbx));
353 
354 	/* now dispatch */
355 	rc = oce_mbox_dispatch(sc, tmo);
356 	if (rc == 0) {
357 		/*
358 		 * the command completed successfully. Now get the
359 		 * completion queue entry
360 		 */
361 		mb_cqe = &mb->cqe;
362 		DW_SWAP(u32ptr(&mb_cqe->u0.dw[0]), sizeof(struct oce_mq_cqe));
363 
364 		/* copy mbox mbx back */
365 		bcopy(mb_mbx, mbx, sizeof(struct oce_mbx));
366 
367 		/* pick up the mailbox status */
368 		cstatus = mb_cqe->u0.s.completion_status;
369 		xstatus = mb_cqe->u0.s.extended_status;
370 
371 		/*
372 		 * store the mbx context in the cqe tag section so that
373 		 * the upper layer handling the cqe can associate the mbx
374 		 * with the response
375 		 */
376 		if (cstatus == 0 && mbxctx) {
377 			/* save context */
378 			mbxctx->mbx = mb_mbx;
379 			bcopy(&mbxctx, mb_cqe->u0.s.mq_tag,
380 				sizeof(struct oce_mbx_ctx *));
381 		}
382 	}
383 
384 	UNLOCK(&sc->bmbx_lock);
385 
386 	return rc;
387 }
388 
389 /**
390  * @brief Function to read the mac address associated with an interface
391  * @param sc		software handle to the device
392  * @param if_id 	interface id to read the address from
393  * @param perm 		set to 1 if reading the factory mac address.
394  *			In this case if_id is ignored
395  * @param type 		type of the mac address, whether network or storage
396  * @param[out] mac 	[OUTPUT] pointer to a buffer containing the
397  *			mac address when the command succeeds.
398  * @returns		0 on success, EIO on failure
399  */
400 int
401 oce_read_mac_addr(POCE_SOFTC sc, uint32_t if_id,
402 		uint8_t perm, uint8_t type, struct mac_address_format *mac)
403 {
404 	struct oce_mbx mbx;
405 	struct mbx_query_common_iface_mac *fwcmd;
406 	int ret = 0;
407 
408 	bzero(&mbx, sizeof(struct oce_mbx));
409 
410 	fwcmd = (struct mbx_query_common_iface_mac *)&mbx.payload;
411 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
412 				MBX_SUBSYSTEM_COMMON,
413 				OPCODE_COMMON_QUERY_IFACE_MAC,
414 				MBX_TIMEOUT_SEC,
415 				sizeof(struct mbx_query_common_iface_mac),
416 				OCE_MBX_VER_V0);
417 
418 	fwcmd->params.req.permanent = perm;
419 	if (!perm)
420 		fwcmd->params.req.if_id = (uint16_t) if_id;
421 	else
422 		fwcmd->params.req.if_id = 0;
423 
424 	fwcmd->params.req.type = type;
425 
426 	mbx.u0.s.embedded = 1;
427 	mbx.payload_length = sizeof(struct mbx_query_common_iface_mac);
428 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
429 
430 	ret = oce_mbox_post(sc, &mbx, NULL);
431 	if (ret)
432 		return ret;
433 
434 	/* copy the mac addres in the output parameter */
435 	mac->size_of_struct = fwcmd->params.rsp.mac.size_of_struct;
436 	bcopy(&fwcmd->params.rsp.mac.mac_addr[0], &mac->mac_addr[0],
437 		mac->size_of_struct);
438 
439 	return 0;
440 }
441 
442 /**
443  * @brief Function to query the fw attributes from the hw
444  * @param sc		software handle to the device
445  * @returns		0 on success, EIO on failure
446  */
447 int
448 oce_get_fw_config(POCE_SOFTC sc)
449 {
450 	struct oce_mbx mbx;
451 	struct mbx_common_query_fw_config *fwcmd;
452 	int ret = 0;
453 
454 	bzero(&mbx, sizeof(struct oce_mbx));
455 
456 	fwcmd = (struct mbx_common_query_fw_config *)&mbx.payload;
457 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
458 				MBX_SUBSYSTEM_COMMON,
459 				OPCODE_COMMON_QUERY_FIRMWARE_CONFIG,
460 				MBX_TIMEOUT_SEC,
461 				sizeof(struct mbx_common_query_fw_config),
462 				OCE_MBX_VER_V0);
463 
464 	mbx.u0.s.embedded = 1;
465 	mbx.payload_length = sizeof(struct mbx_common_query_fw_config);
466 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
467 
468 	ret = oce_mbox_post(sc, &mbx, NULL);
469 	if (ret)
470 		return ret;
471 
472 	DW_SWAP(u32ptr(fwcmd), sizeof(struct mbx_common_query_fw_config));
473 
474 	sc->config_number = fwcmd->params.rsp.config_number;
475 	sc->asic_revision = fwcmd->params.rsp.asic_revision;
476 	sc->port_id	  = fwcmd->params.rsp.port_id;
477 	sc->function_mode = fwcmd->params.rsp.function_mode;
478 	sc->function_caps = fwcmd->params.rsp.function_caps;
479 
480 	if (fwcmd->params.rsp.ulp[0].ulp_mode & ULP_NIC_MODE) {
481 		sc->max_tx_rings = fwcmd->params.rsp.ulp[0].nic_wq_tot;
482 		sc->max_rx_rings = fwcmd->params.rsp.ulp[0].lro_rqid_tot;
483 	} else {
484 		sc->max_tx_rings = fwcmd->params.rsp.ulp[1].nic_wq_tot;
485 		sc->max_rx_rings = fwcmd->params.rsp.ulp[1].lro_rqid_tot;
486 	}
487 
488 	return 0;
489 
490 }
491 
492 /**
493  *
494  * @brief function to create a device interface
495  * @param sc		software handle to the device
496  * @param cap_flags	capability flags
497  * @param en_flags	enable capability flags
498  * @param vlan_tag	optional vlan tag to associate with the if
499  * @param mac_addr	pointer to a buffer containing the mac address
500  * @param[out] if_id	[OUTPUT] pointer to an integer to hold the ID of the
501  interface created
502  * @returns		0 on success, EIO on failure
503  */
504 int
505 oce_if_create(POCE_SOFTC sc,
506 		uint32_t cap_flags,
507 		uint32_t en_flags,
508 		uint16_t vlan_tag,
509 		uint8_t *mac_addr,
510 		uint32_t *if_id)
511 {
512 	struct oce_mbx mbx;
513 	struct mbx_create_common_iface *fwcmd;
514 	int rc = 0;
515 
516 	bzero(&mbx, sizeof(struct oce_mbx));
517 
518 	fwcmd = (struct mbx_create_common_iface *)&mbx.payload;
519 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
520 				MBX_SUBSYSTEM_COMMON,
521 				OPCODE_COMMON_CREATE_IFACE,
522 				MBX_TIMEOUT_SEC,
523 				sizeof(struct mbx_create_common_iface),
524 				OCE_MBX_VER_V0);
525 	DW_SWAP(u32ptr(&fwcmd->hdr), sizeof(struct mbx_hdr));
526 
527 	fwcmd->params.req.version = 0;
528 	fwcmd->params.req.cap_flags = LE_32(cap_flags);
529 	fwcmd->params.req.enable_flags = LE_32(en_flags);
530 	if (mac_addr != NULL) {
531 		bcopy(mac_addr, &fwcmd->params.req.mac_addr[0], 6);
532 		fwcmd->params.req.vlan_tag.u0.normal.vtag = LE_16(vlan_tag);
533 		fwcmd->params.req.mac_invalid = 0;
534 	} else {
535 		fwcmd->params.req.mac_invalid = 1;
536 	}
537 
538 	mbx.u0.s.embedded = 1;
539 	mbx.payload_length = sizeof(struct mbx_create_common_iface);
540 	DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ);
541 
542 	rc = oce_mbox_post(sc, &mbx, NULL);
543 	if (rc)
544 		return rc;
545 
546 	*if_id = LE_32(fwcmd->params.rsp.if_id);
547 
548 	if (mac_addr != NULL)
549 		sc->pmac_id = LE_32(fwcmd->params.rsp.pmac_id);
550 
551 	return 0;
552 }
553 
554 /**
555  * @brief		Function to delete an interface
556  * @param sc 		software handle to the device
557  * @param if_id		ID of the interface to delete
558  * @returns		0 on success, EIO on failure
559  */
560 int
561 oce_if_del(POCE_SOFTC sc, uint32_t if_id)
562 {
563 	struct oce_mbx mbx;
564 	struct mbx_destroy_common_iface *fwcmd;
565 	int rc = 0;
566 
567 	bzero(&mbx, sizeof(struct oce_mbx));
568 
569 	fwcmd = (struct mbx_destroy_common_iface *)&mbx.payload;
570 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
571 				MBX_SUBSYSTEM_COMMON,
572 				OPCODE_COMMON_DESTROY_IFACE,
573 				MBX_TIMEOUT_SEC,
574 				sizeof(struct mbx_destroy_common_iface),
575 				OCE_MBX_VER_V0);
576 
577 	fwcmd->params.req.if_id = if_id;
578 
579 	mbx.u0.s.embedded = 1;
580 	mbx.payload_length = sizeof(struct mbx_destroy_common_iface);
581 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
582 
583 	rc = oce_mbox_post(sc, &mbx, NULL);
584 	return rc;
585 }
586 
587 /**
588  * @brief Function to send the mbx command to configure vlan
589  * @param sc 		software handle to the device
590  * @param if_id 	interface identifier index
591  * @param vtag_arr	array of vlan tags
592  * @param vtag_cnt	number of elements in array
593  * @param untagged	boolean TRUE/FLASE
594  * @param enable_promisc flag to enable/disable VLAN promiscuous mode
595  * @returns		0 on success, EIO on failure
596  */
597 int
598 oce_config_vlan(POCE_SOFTC sc,
599 		uint32_t if_id,
600 		struct normal_vlan *vtag_arr,
601 		uint8_t vtag_cnt, uint32_t untagged, uint32_t enable_promisc)
602 {
603 	struct oce_mbx mbx;
604 	struct mbx_common_config_vlan *fwcmd;
605 	int rc;
606 
607 	bzero(&mbx, sizeof(struct oce_mbx));
608 	fwcmd = (struct mbx_common_config_vlan *)&mbx.payload;
609 
610 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
611 				MBX_SUBSYSTEM_COMMON,
612 				OPCODE_COMMON_CONFIG_IFACE_VLAN,
613 				MBX_TIMEOUT_SEC,
614 				sizeof(struct mbx_common_config_vlan),
615 				OCE_MBX_VER_V0);
616 
617 	fwcmd->params.req.if_id = (uint8_t) if_id;
618 	fwcmd->params.req.promisc = (uint8_t) enable_promisc;
619 	fwcmd->params.req.untagged = (uint8_t) untagged;
620 	fwcmd->params.req.num_vlans = vtag_cnt;
621 
622 	if (!enable_promisc) {
623 		bcopy(vtag_arr, fwcmd->params.req.tags.normal_vlans,
624 			vtag_cnt * sizeof(struct normal_vlan));
625 	}
626 	mbx.u0.s.embedded = 1;
627 	mbx.payload_length = sizeof(struct mbx_common_config_vlan);
628 	DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + mbx.payload_length));
629 
630 	rc = oce_mbox_post(sc, &mbx, NULL);
631 
632 	return rc;
633 
634 }
635 
636 /**
637  * @brief Function to set flow control capability in the hardware
638  * @param sc 		software handle to the device
639  * @param flow_control	flow control flags to set
640  * @returns		0 on success, EIO on failure
641  */
642 int
643 oce_set_flow_control(POCE_SOFTC sc, uint32_t flow_control)
644 {
645 	struct oce_mbx mbx;
646 	struct mbx_common_get_set_flow_control *fwcmd =
647 		(struct mbx_common_get_set_flow_control *)&mbx.payload;
648 	int rc;
649 
650 	bzero(&mbx, sizeof(struct oce_mbx));
651 
652 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
653 				MBX_SUBSYSTEM_COMMON,
654 				OPCODE_COMMON_SET_FLOW_CONTROL,
655 				MBX_TIMEOUT_SEC,
656 				sizeof(struct mbx_common_get_set_flow_control),
657 				OCE_MBX_VER_V0);
658 
659 	if (flow_control & OCE_FC_TX)
660 		fwcmd->tx_flow_control = 1;
661 
662 	if (flow_control & OCE_FC_RX)
663 		fwcmd->rx_flow_control = 1;
664 
665 	mbx.u0.s.embedded = 1;
666 	mbx.payload_length = sizeof(struct mbx_common_get_set_flow_control);
667 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
668 
669 	rc = oce_mbox_post(sc, &mbx, NULL);
670 
671 	return rc;
672 }
673 
674 /**
675  * @brief Initialize the RSS CPU indirection table
676  *
677  * The table is used to choose the queue to place the incomming packets.
678  * Incomming packets are hashed.  The lowest bits in the hash result
679  * are used as the index into the CPU indirection table.
680  * Each entry in the table contains the RSS CPU-ID returned by the NIC
681  * create.  Based on the CPU ID, the receive completion is routed to
682  * the corresponding RSS CQs.  (Non-RSS packets are always completed
683  * on the default (0) CQ).
684  *
685  * @param sc 		software handle to the device
686  * @param *fwcmd	pointer to the rss mbox command
687  * @returns		none
688  */
689 static int
690 oce_rss_itbl_init(POCE_SOFTC sc, struct mbx_config_nic_rss *fwcmd)
691 {
692 	int i = 0, j = 0, rc = 0;
693 	uint8_t *tbl = fwcmd->params.req.cputable;
694 
695 
696 	for (j = 0; j < sc->nrqs; j++) {
697 		if (sc->rq[j]->cfg.is_rss_queue) {
698 			tbl[i] = sc->rq[j]->rss_cpuid;
699 			i = i + 1;
700 		}
701 	}
702 	if (i == 0) {
703 		device_printf(sc->dev, "error: Invalid number of RSS RQ's\n");
704 		rc = ENXIO;
705 
706 	}
707 
708 	/* fill log2 value indicating the size of the CPU table */
709 	if (rc == 0)
710 		fwcmd->params.req.cpu_tbl_sz_log2 = LE_16(OCE_LOG2(i));
711 
712 	return rc;
713 }
714 
715 /**
716  * @brief Function to set flow control capability in the hardware
717  * @param sc 		software handle to the device
718  * @param if_id 	interface id to read the address from
719  * @param enable_rss	0=disable, RSS_ENABLE_xxx flags otherwise
720  * @returns		0 on success, EIO on failure
721  */
722 int
723 oce_config_nic_rss(POCE_SOFTC sc, uint32_t if_id, uint16_t enable_rss)
724 {
725 	int rc;
726 	struct oce_mbx mbx;
727 	struct mbx_config_nic_rss *fwcmd =
728 				(struct mbx_config_nic_rss *)&mbx.payload;
729 
730 	bzero(&mbx, sizeof(struct oce_mbx));
731 
732 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
733 				MBX_SUBSYSTEM_NIC,
734 				NIC_CONFIG_RSS,
735 				MBX_TIMEOUT_SEC,
736 				sizeof(struct mbx_config_nic_rss),
737 				OCE_MBX_VER_V0);
738 	if (enable_rss)
739 		fwcmd->params.req.enable_rss = (RSS_ENABLE_IPV4 |
740 						RSS_ENABLE_TCP_IPV4 |
741 						RSS_ENABLE_IPV6 |
742 						RSS_ENABLE_TCP_IPV6);
743 	fwcmd->params.req.flush = OCE_FLUSH;
744 	fwcmd->params.req.if_id = LE_32(if_id);
745 
746 	srandom(arc4random());	/* random entropy seed */
747 	read_random(fwcmd->params.req.hash, sizeof(fwcmd->params.req.hash));
748 
749 	rc = oce_rss_itbl_init(sc, fwcmd);
750 	if (rc == 0) {
751 		mbx.u0.s.embedded = 1;
752 		mbx.payload_length = sizeof(struct mbx_config_nic_rss);
753 		DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
754 
755 		rc = oce_mbox_post(sc, &mbx, NULL);
756 
757 	}
758 
759 	return rc;
760 }
761 
762 /**
763  * @brief 		RXF function to enable/disable device promiscuous mode
764  * @param sc		software handle to the device
765  * @param enable	enable/disable flag
766  * @returns		0 on success, EIO on failure
767  * @note
768  *	The NIC_CONFIG_PROMISCUOUS command deprecated for Lancer.
769  *	This function uses the COMMON_SET_IFACE_RX_FILTER command instead.
770  */
771 int
772 oce_rxf_set_promiscuous(POCE_SOFTC sc, uint32_t enable)
773 {
774 	struct mbx_set_common_iface_rx_filter *fwcmd;
775 	int sz = sizeof(struct mbx_set_common_iface_rx_filter);
776 	iface_rx_filter_ctx_t *req;
777 	OCE_DMA_MEM sgl;
778 	int rc;
779 
780 	/* allocate mbx payload's dma scatter/gather memory */
781 	rc = oce_dma_alloc(sc, sz, &sgl, 0);
782 	if (rc)
783 		return rc;
784 
785 	fwcmd = OCE_DMAPTR(&sgl, struct mbx_set_common_iface_rx_filter);
786 
787 	req =  &fwcmd->params.req;
788 	req->iface_flags_mask = MBX_RX_IFACE_FLAGS_PROMISCUOUS |
789 				MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS;
790 	if (enable) {
791 		req->iface_flags = MBX_RX_IFACE_FLAGS_PROMISCUOUS |
792 				   MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS;
793 	}
794 	req->if_id = sc->if_id;
795 
796 	rc = oce_set_common_iface_rx_filter(sc, &sgl);
797 	oce_dma_free(sc, &sgl);
798 
799 	return rc;
800 }
801 
802 
803 /**
804  * @brief 			Function modify and select rx filter options
805  * @param sc			software handle to the device
806  * @param sgl			scatter/gather request/response
807  * @returns			0 on success, error code on failure
808  */
809 int
810 oce_set_common_iface_rx_filter(POCE_SOFTC sc, POCE_DMA_MEM sgl)
811 {
812 	struct oce_mbx mbx;
813 	int mbx_sz = sizeof(struct mbx_set_common_iface_rx_filter);
814 	struct mbx_set_common_iface_rx_filter *fwcmd;
815 	int rc;
816 
817 	bzero(&mbx, sizeof(struct oce_mbx));
818 	fwcmd = OCE_DMAPTR(sgl, struct mbx_set_common_iface_rx_filter);
819 
820 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
821 				MBX_SUBSYSTEM_COMMON,
822 				OPCODE_COMMON_SET_IFACE_RX_FILTER,
823 				MBX_TIMEOUT_SEC,
824 				mbx_sz,
825 				OCE_MBX_VER_V0);
826 
827 	oce_dma_sync(sgl, BUS_DMASYNC_PREWRITE);
828 	mbx.u0.s.embedded = 0;
829 	mbx.u0.s.sge_count = 1;
830 	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(sgl->paddr);
831 	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(sgl->paddr);
832 	mbx.payload.u0.u1.sgl[0].length = mbx_sz;
833 	mbx.payload_length = mbx_sz;
834 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
835 
836 	rc = oce_mbox_post(sc, &mbx, NULL);
837 	return rc;
838 }
839 
840 /**
841  * @brief Function to query the link status from the hardware
842  * @param sc 		software handle to the device
843  * @param[out] link	pointer to the structure returning link attributes
844  * @returns		0 on success, EIO on failure
845  */
846 int
847 oce_get_link_status(POCE_SOFTC sc, struct link_status *link)
848 {
849 	struct oce_mbx mbx;
850 	struct mbx_query_common_link_config *fwcmd;
851 	int rc = 0;
852 
853 	bzero(&mbx, sizeof(struct oce_mbx));
854 
855 	fwcmd = (struct mbx_query_common_link_config *)&mbx.payload;
856 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
857 				MBX_SUBSYSTEM_COMMON,
858 				OPCODE_COMMON_QUERY_LINK_CONFIG,
859 				MBX_TIMEOUT_SEC,
860 				sizeof(struct mbx_query_common_link_config),
861 				OCE_MBX_VER_V0);
862 
863 	mbx.u0.s.embedded = 1;
864 	mbx.payload_length = sizeof(struct mbx_query_common_link_config);
865 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
866 
867 	rc = oce_mbox_post(sc, &mbx, NULL);
868 
869 	if (rc) {
870 		device_printf(sc->dev, "Could not get link speed: %d\n", rc);
871 	} else {
872 		/* interpret response */
873 		bcopy(&fwcmd->params.rsp, link, sizeof(struct link_status));
874 		link->logical_link_status = LE_32(link->logical_link_status);
875 		link->qos_link_speed = LE_16(link->qos_link_speed);
876 	}
877 
878 	return rc;
879 }
880 
881 
882 
883 int
884 oce_mbox_get_nic_stats_v0(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem)
885 {
886 	struct oce_mbx mbx;
887 	struct mbx_get_nic_stats_v0 *fwcmd;
888 	int rc = 0;
889 
890 	bzero(&mbx, sizeof(struct oce_mbx));
891 
892 	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_nic_stats_v0);
893 	bzero(fwcmd, sizeof(struct mbx_get_nic_stats_v0));
894 
895 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
896 				MBX_SUBSYSTEM_NIC,
897 				NIC_GET_STATS,
898 				MBX_TIMEOUT_SEC,
899 				sizeof(struct mbx_get_nic_stats_v0),
900 				OCE_MBX_VER_V0);
901 
902 	mbx.u0.s.embedded = 0;
903 	mbx.u0.s.sge_count = 1;
904 
905 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
906 
907 	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
908 	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
909 	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_nic_stats_v0);
910 
911 	mbx.payload_length = sizeof(struct mbx_get_nic_stats_v0);
912 
913 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
914 
915 	rc = oce_mbox_post(sc, &mbx, NULL);
916 
917 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
918 
919 	if (rc) {
920 		device_printf(sc->dev,
921 			"Could not get nic statistics: %d\n", rc);
922 	}
923 
924 	return rc;
925 }
926 
927 
928 
929 /**
930  * @brief Function to get NIC statistics
931  * @param sc 		software handle to the device
932  * @param *stats	pointer to where to store statistics
933  * @param reset_stats	resets statistics of set
934  * @returns		0 on success, EIO on failure
935  * @note		command depricated in Lancer
936  */
937 int
938 oce_mbox_get_nic_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem)
939 {
940 	struct oce_mbx mbx;
941 	struct mbx_get_nic_stats *fwcmd;
942 	int rc = 0;
943 
944 	bzero(&mbx, sizeof(struct oce_mbx));
945 	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_nic_stats);
946 	bzero(fwcmd, sizeof(struct mbx_get_nic_stats));
947 
948 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
949 				MBX_SUBSYSTEM_NIC,
950 				NIC_GET_STATS,
951 				MBX_TIMEOUT_SEC,
952 				sizeof(struct mbx_get_nic_stats),
953 				OCE_MBX_VER_V1);
954 
955 
956 	mbx.u0.s.embedded = 0;  /* stats too large for embedded mbx rsp */
957 	mbx.u0.s.sge_count = 1; /* using scatter gather instead */
958 
959 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
960 	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
961 	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
962 	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_nic_stats);
963 
964 	mbx.payload_length = sizeof(struct mbx_get_nic_stats);
965 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
966 
967 	rc = oce_mbox_post(sc, &mbx, NULL);
968 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
969 	if (rc) {
970 		device_printf(sc->dev,
971 			"Could not get nic statistics: %d\n", rc);
972 	}
973 	return rc;
974 }
975 
976 
977 /**
978  * @brief Function to get pport (physical port) statistics
979  * @param sc 		software handle to the device
980  * @param *stats	pointer to where to store statistics
981  * @param reset_stats	resets statistics of set
982  * @returns		0 on success, EIO on failure
983  */
984 int
985 oce_mbox_get_pport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem,
986 				uint32_t reset_stats)
987 {
988 	struct oce_mbx mbx;
989 	struct mbx_get_pport_stats *fwcmd;
990 	int rc = 0;
991 
992 	bzero(&mbx, sizeof(struct oce_mbx));
993 	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_pport_stats);
994 	bzero(fwcmd, sizeof(struct mbx_get_pport_stats));
995 
996 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
997 				MBX_SUBSYSTEM_NIC,
998 				NIC_GET_PPORT_STATS,
999 				MBX_TIMEOUT_SEC,
1000 				sizeof(struct mbx_get_pport_stats),
1001 				OCE_MBX_VER_V0);
1002 
1003 	fwcmd->params.req.reset_stats = reset_stats;
1004 	fwcmd->params.req.port_number = sc->if_id;
1005 
1006 	mbx.u0.s.embedded = 0;	/* stats too large for embedded mbx rsp */
1007 	mbx.u0.s.sge_count = 1; /* using scatter gather instead */
1008 
1009 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
1010 	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
1011 	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
1012 	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_pport_stats);
1013 
1014 	mbx.payload_length = sizeof(struct mbx_get_pport_stats);
1015 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1016 
1017 	rc = oce_mbox_post(sc, &mbx, NULL);
1018 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
1019 
1020 	if (rc != 0) {
1021 		device_printf(sc->dev,
1022 			  "Could not get physical port statistics: %d\n", rc);
1023 	}
1024 
1025 	return rc;
1026 }
1027 
1028 
1029 /**
1030  * @brief Function to get vport (virtual port) statistics
1031  * @param sc 		software handle to the device
1032  * @param *stats	pointer to where to store statistics
1033  * @param reset_stats	resets statistics of set
1034  * @returns		0 on success, EIO on failure
1035  */
1036 int
1037 oce_mbox_get_vport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem,
1038 				uint32_t req_size, uint32_t reset_stats)
1039 {
1040 	struct oce_mbx mbx;
1041 	struct mbx_get_vport_stats *fwcmd;
1042 	int rc = 0;
1043 
1044 	bzero(&mbx, sizeof(struct oce_mbx));
1045 
1046 	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_vport_stats);
1047 	bzero(fwcmd, sizeof(struct mbx_get_vport_stats));
1048 
1049 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1050 				MBX_SUBSYSTEM_NIC,
1051 				NIC_GET_VPORT_STATS,
1052 				MBX_TIMEOUT_SEC,
1053 				sizeof(struct mbx_get_vport_stats),
1054 				OCE_MBX_VER_V0);
1055 
1056 	fwcmd->params.req.reset_stats = reset_stats;
1057 	fwcmd->params.req.vport_number = sc->if_id;
1058 
1059 	mbx.u0.s.embedded = 0;	/* stats too large for embedded mbx rsp */
1060 	mbx.u0.s.sge_count = 1; /* using scatter gather instead */
1061 
1062 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
1063 	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
1064 	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
1065 	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_vport_stats);
1066 
1067 	mbx.payload_length = sizeof(struct mbx_get_vport_stats);
1068 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1069 
1070 	rc = oce_mbox_post(sc, &mbx, NULL);
1071 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
1072 
1073 	if (rc != 0) {
1074 		device_printf(sc->dev,
1075 			  "Could not get physical port statistics: %d\n", rc);
1076 	}
1077 
1078 	return rc;
1079 }
1080 
1081 
1082 /**
1083  * @brief               Function to update the muticast filter with
1084  *                      values in dma_mem
1085  * @param sc            software handle to the device
1086  * @param dma_mem       pointer to dma memory region
1087  * @returns             0 on success, EIO on failure
1088  */
1089 int
1090 oce_update_multicast(POCE_SOFTC sc, POCE_DMA_MEM pdma_mem)
1091 {
1092 	struct oce_mbx mbx;
1093 	struct oce_mq_sge *sgl;
1094 	struct mbx_set_common_iface_multicast *req = NULL;
1095 	int rc = 0;
1096 
1097 	req = OCE_DMAPTR(pdma_mem, struct mbx_set_common_iface_multicast);
1098 	mbx_common_req_hdr_init(&req->hdr, 0, 0,
1099 				MBX_SUBSYSTEM_COMMON,
1100 				OPCODE_COMMON_SET_IFACE_MULTICAST,
1101 				MBX_TIMEOUT_SEC,
1102 				sizeof(struct mbx_set_common_iface_multicast),
1103 				OCE_MBX_VER_V0);
1104 
1105 	bzero(&mbx, sizeof(struct oce_mbx));
1106 
1107 	mbx.u0.s.embedded = 0; /*Non embeded*/
1108 	mbx.payload_length = sizeof(struct mbx_set_common_iface_multicast);
1109 	mbx.u0.s.sge_count = 1;
1110 	sgl = &mbx.payload.u0.u1.sgl[0];
1111 	sgl->pa_hi = htole32(upper_32_bits(pdma_mem->paddr));
1112 	sgl->pa_lo = htole32((pdma_mem->paddr) & 0xFFFFFFFF);
1113 	sgl->length = htole32(mbx.payload_length);
1114 
1115 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1116 
1117 	rc = oce_mbox_post(sc, &mbx, NULL);
1118 
1119 	return rc;
1120 }
1121 
1122 
1123 /**
1124  * @brief               Function to send passthrough Ioctls
1125  * @param sc            software handle to the device
1126  * @param dma_mem       pointer to dma memory region
1127  * @param req_size      size of dma_mem
1128  * @returns             0 on success, EIO on failure
1129  */
1130 int
1131 oce_pass_through_mbox(POCE_SOFTC sc, POCE_DMA_MEM dma_mem, uint32_t req_size)
1132 {
1133 	struct oce_mbx mbx;
1134 	struct oce_mq_sge *sgl;
1135 	int rc = 0;
1136 
1137 	bzero(&mbx, sizeof(struct oce_mbx));
1138 
1139 	mbx.u0.s.embedded  = 0; /*Non embeded*/
1140 	mbx.payload_length = req_size;
1141 	mbx.u0.s.sge_count = 1;
1142 	sgl = &mbx.payload.u0.u1.sgl[0];
1143 	sgl->pa_hi = htole32(upper_32_bits(dma_mem->paddr));
1144 	sgl->pa_lo = htole32((dma_mem->paddr) & 0xFFFFFFFF);
1145 	sgl->length = htole32(req_size);
1146 
1147 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1148 
1149 	rc = oce_mbox_post(sc, &mbx, NULL);
1150 	return rc;
1151 }
1152 
1153 
1154 int
1155 oce_mbox_macaddr_add(POCE_SOFTC sc, uint8_t *mac_addr,
1156 		 uint32_t if_id, uint32_t *pmac_id)
1157 {
1158 	struct oce_mbx mbx;
1159 	struct mbx_add_common_iface_mac *fwcmd;
1160 	int rc = 0;
1161 
1162 	bzero(&mbx, sizeof(struct oce_mbx));
1163 
1164 	fwcmd = (struct mbx_add_common_iface_mac *)&mbx.payload;
1165 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1166 				MBX_SUBSYSTEM_COMMON,
1167 				OPCODE_COMMON_ADD_IFACE_MAC,
1168 				MBX_TIMEOUT_SEC,
1169 				sizeof(struct mbx_add_common_iface_mac),
1170 				OCE_MBX_VER_V0);
1171 
1172 	fwcmd->params.req.if_id = (uint16_t) if_id;
1173 	bcopy(mac_addr, fwcmd->params.req.mac_address, 6);
1174 
1175 	mbx.u0.s.embedded = 1;
1176 	mbx.payload_length = sizeof(struct  mbx_add_common_iface_mac);
1177 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1178 	rc = oce_mbox_post(sc, &mbx, NULL);
1179 	if (rc)
1180 		return rc;
1181 
1182 	*pmac_id = fwcmd->params.rsp.pmac_id;
1183 
1184 	return rc;
1185 }
1186 
1187 
1188 int
1189 oce_mbox_macaddr_del(POCE_SOFTC sc, uint32_t if_id, uint32_t pmac_id)
1190 {
1191 	struct oce_mbx mbx;
1192 	struct mbx_del_common_iface_mac *fwcmd;
1193 	int rc = 0;
1194 
1195 	bzero(&mbx, sizeof(struct oce_mbx));
1196 
1197 	fwcmd = (struct mbx_del_common_iface_mac *)&mbx.payload;
1198 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1199 				MBX_SUBSYSTEM_COMMON,
1200 				OPCODE_COMMON_DEL_IFACE_MAC,
1201 				MBX_TIMEOUT_SEC,
1202 				sizeof(struct mbx_del_common_iface_mac),
1203 				OCE_MBX_VER_V0);
1204 
1205 	fwcmd->params.req.if_id = (uint16_t)if_id;
1206 	fwcmd->params.req.pmac_id = pmac_id;
1207 
1208 	mbx.u0.s.embedded = 1;
1209 	mbx.payload_length = sizeof(struct  mbx_del_common_iface_mac);
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 
1218 int
1219 oce_mbox_check_native_mode(POCE_SOFTC sc)
1220 {
1221 	struct oce_mbx mbx;
1222 	struct mbx_common_set_function_cap *fwcmd;
1223 	int rc = 0;
1224 
1225 	bzero(&mbx, sizeof(struct oce_mbx));
1226 
1227 	fwcmd = (struct mbx_common_set_function_cap *)&mbx.payload;
1228 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1229 				MBX_SUBSYSTEM_COMMON,
1230 				OPCODE_COMMON_SET_FUNCTIONAL_CAPS,
1231 				MBX_TIMEOUT_SEC,
1232 				sizeof(struct mbx_common_set_function_cap),
1233 				OCE_MBX_VER_V0);
1234 
1235 	fwcmd->params.req.valid_capability_flags = CAP_SW_TIMESTAMPS |
1236 							CAP_BE3_NATIVE_ERX_API;
1237 
1238 	fwcmd->params.req.capability_flags = CAP_BE3_NATIVE_ERX_API;
1239 
1240 	mbx.u0.s.embedded = 1;
1241 	mbx.payload_length = sizeof(struct mbx_common_set_function_cap);
1242 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1243 
1244 	rc = oce_mbox_post(sc, &mbx, NULL);
1245 	//if (rc != 0)		This can fail in legacy mode. So skip
1246 	//	FN_LEAVE(rc);
1247 
1248 	sc->be3_native = fwcmd->params.rsp.capability_flags
1249 			& CAP_BE3_NATIVE_ERX_API;
1250 
1251 	return 0;
1252 }
1253 
1254 
1255 
1256 int
1257 oce_mbox_cmd_set_loopback(POCE_SOFTC sc, uint8_t port_num,
1258 		uint8_t loopback_type, uint8_t enable)
1259 {
1260 	struct oce_mbx mbx;
1261 	struct mbx_lowlevel_set_loopback_mode *fwcmd;
1262 	int rc = 0;
1263 
1264 
1265 	bzero(&mbx, sizeof(struct oce_mbx));
1266 
1267 	fwcmd = (struct mbx_lowlevel_set_loopback_mode *)&mbx.payload;
1268 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1269 				MBX_SUBSYSTEM_LOWLEVEL,
1270 				OPCODE_LOWLEVEL_SET_LOOPBACK_MODE,
1271 				MBX_TIMEOUT_SEC,
1272 				sizeof(struct mbx_lowlevel_set_loopback_mode),
1273 				OCE_MBX_VER_V0);
1274 
1275 	fwcmd->params.req.src_port = port_num;
1276 	fwcmd->params.req.dest_port = port_num;
1277 	fwcmd->params.req.loopback_type = loopback_type;
1278 	fwcmd->params.req.loopback_state = enable;
1279 
1280 	mbx.u0.s.embedded = 1;
1281 	mbx.payload_length = sizeof(struct  mbx_lowlevel_set_loopback_mode);
1282 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1283 
1284 	rc = oce_mbox_post(sc, &mbx, NULL);
1285 
1286 	return rc;
1287 
1288 }
1289 
1290 int
1291 oce_mbox_cmd_test_loopback(POCE_SOFTC sc, uint32_t port_num,
1292 	uint32_t loopback_type, uint32_t pkt_size, uint32_t num_pkts,
1293 	uint64_t pattern)
1294 {
1295 
1296 	struct oce_mbx mbx;
1297 	struct mbx_lowlevel_test_loopback_mode *fwcmd;
1298 	int rc = 0;
1299 
1300 
1301 	bzero(&mbx, sizeof(struct oce_mbx));
1302 
1303 	fwcmd = (struct mbx_lowlevel_test_loopback_mode *)&mbx.payload;
1304 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1305 				MBX_SUBSYSTEM_LOWLEVEL,
1306 				OPCODE_LOWLEVEL_TEST_LOOPBACK,
1307 				MBX_TIMEOUT_SEC,
1308 				sizeof(struct mbx_lowlevel_test_loopback_mode),
1309 				OCE_MBX_VER_V0);
1310 
1311 	fwcmd->params.req.pattern = pattern;
1312 	fwcmd->params.req.src_port = port_num;
1313 	fwcmd->params.req.dest_port = port_num;
1314 	fwcmd->params.req.pkt_size = pkt_size;
1315 	fwcmd->params.req.num_pkts = num_pkts;
1316 	fwcmd->params.req.loopback_type = loopback_type;
1317 
1318 	mbx.u0.s.embedded = 1;
1319 	mbx.payload_length = sizeof(struct  mbx_lowlevel_test_loopback_mode);
1320 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1321 
1322 	rc = oce_mbox_post(sc, &mbx, NULL);
1323 	if (rc)
1324 		return rc;
1325 
1326 	return(fwcmd->params.rsp.status);
1327 }
1328 
1329 int
1330 oce_mbox_write_flashrom(POCE_SOFTC sc, uint32_t optype,uint32_t opcode,
1331 				POCE_DMA_MEM pdma_mem, uint32_t num_bytes)
1332 {
1333 
1334 	struct oce_mbx mbx;
1335 	struct oce_mq_sge *sgl = NULL;
1336 	struct mbx_common_read_write_flashrom *fwcmd = NULL;
1337 	int rc = 0, payload_len = 0;
1338 
1339 	bzero(&mbx, sizeof(struct oce_mbx));
1340 	fwcmd = OCE_DMAPTR(pdma_mem, struct mbx_common_read_write_flashrom);
1341 	payload_len = sizeof(struct mbx_common_read_write_flashrom) + 32*1024;
1342 
1343 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1344 				MBX_SUBSYSTEM_COMMON,
1345 				OPCODE_COMMON_WRITE_FLASHROM,
1346 				LONG_TIMEOUT,
1347 				payload_len,
1348 				OCE_MBX_VER_V0);
1349 
1350 	fwcmd->flash_op_type = optype;
1351 	fwcmd->flash_op_code = opcode;
1352 	fwcmd->data_buffer_size = num_bytes;
1353 
1354 	mbx.u0.s.embedded  = 0; /*Non embeded*/
1355 	mbx.payload_length = payload_len;
1356 	mbx.u0.s.sge_count = 1;
1357 
1358 	sgl = &mbx.payload.u0.u1.sgl[0];
1359 	sgl->pa_hi = upper_32_bits(pdma_mem->paddr);
1360 	sgl->pa_lo = pdma_mem->paddr & 0xFFFFFFFF;
1361 	sgl->length = payload_len;
1362 
1363 	/* post the command */
1364 	rc = oce_mbox_post(sc, &mbx, NULL);
1365 	if (rc) {
1366 		device_printf(sc->dev, "Write FlashROM mbox post failed\n");
1367 	} else {
1368 		rc = fwcmd->hdr.u0.rsp.status;
1369 	}
1370 
1371 	return rc;
1372 
1373 }
1374 
1375 int
1376 oce_mbox_get_flashrom_crc(POCE_SOFTC sc, uint8_t *flash_crc,
1377 				uint32_t offset, uint32_t optype)
1378 {
1379 
1380 	int rc = 0, payload_len = 0;
1381 	struct oce_mbx mbx;
1382 	struct mbx_common_read_write_flashrom *fwcmd;
1383 
1384 	bzero(&mbx, sizeof(struct oce_mbx));
1385 
1386 	fwcmd = (struct mbx_common_read_write_flashrom *)&mbx.payload;
1387 
1388 	/* Firmware requires extra 4 bytes with this ioctl. Since there
1389 	   is enough room in the mbx payload it should be good enough
1390 	   Reference: Bug 14853
1391 	*/
1392 	payload_len = sizeof(struct mbx_common_read_write_flashrom) + 4;
1393 
1394 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1395 				MBX_SUBSYSTEM_COMMON,
1396 				OPCODE_COMMON_READ_FLASHROM,
1397 				MBX_TIMEOUT_SEC,
1398 				payload_len,
1399 				OCE_MBX_VER_V0);
1400 
1401 	fwcmd->flash_op_type = optype;
1402 	fwcmd->flash_op_code = FLASHROM_OPER_REPORT;
1403 	fwcmd->data_offset = offset;
1404 	fwcmd->data_buffer_size = 0x4;
1405 
1406 	mbx.u0.s.embedded  = 1;
1407 	mbx.payload_length = payload_len;
1408 
1409 	/* post the command */
1410 	rc = oce_mbox_post(sc, &mbx, NULL);
1411 	if (rc) {
1412 		device_printf(sc->dev, "Read FlashROM CRC mbox post failed\n");
1413 	} else {
1414 		bcopy(fwcmd->data_buffer, flash_crc, 4);
1415 		rc = fwcmd->hdr.u0.rsp.status;
1416 	}
1417 	return rc;
1418 }
1419 
1420 int
1421 oce_mbox_get_phy_info(POCE_SOFTC sc, struct oce_phy_info *phy_info)
1422 {
1423 
1424 	struct oce_mbx mbx;
1425 	struct mbx_common_phy_info *fwcmd;
1426 	int rc = 0;
1427 
1428 	bzero(&mbx, sizeof(struct oce_mbx));
1429 
1430 	fwcmd = (struct mbx_common_phy_info *)&mbx.payload;
1431 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1432 				MBX_SUBSYSTEM_COMMON,
1433 				OPCODE_COMMON_GET_PHY_CONFIG,
1434 				MBX_TIMEOUT_SEC,
1435 				sizeof(struct mbx_common_phy_info),
1436 				OCE_MBX_VER_V0);
1437 
1438 	mbx.u0.s.embedded = 1;
1439 	mbx.payload_length = sizeof(struct  mbx_common_phy_info);
1440 
1441 	/* now post the command */
1442 	rc = oce_mbox_post(sc, &mbx, NULL);
1443 	if (rc) {
1444 		device_printf(sc->dev, "Read PHY info  mbox post failed\n");
1445 	} else {
1446 		rc = fwcmd->hdr.u0.rsp.status;
1447 		phy_info->phy_type = fwcmd->params.rsp.phy_info.phy_type;
1448 		phy_info->interface_type =
1449 				fwcmd->params.rsp.phy_info.interface_type;
1450 		phy_info->auto_speeds_supported =
1451 			fwcmd->params.rsp.phy_info.auto_speeds_supported;
1452 		phy_info->fixed_speeds_supported =
1453 			fwcmd->params.rsp.phy_info.fixed_speeds_supported;
1454 		phy_info->misc_params =fwcmd->params.rsp.phy_info.misc_params;
1455 
1456 	}
1457 	return rc;
1458 
1459 }
1460 
1461 
1462 int
1463 oce_mbox_lancer_write_flashrom(POCE_SOFTC sc, uint32_t data_size,
1464 			uint32_t data_offset, POCE_DMA_MEM pdma_mem,
1465 			uint32_t *written_data, uint32_t *additional_status)
1466 {
1467 
1468 	struct oce_mbx mbx;
1469 	struct mbx_lancer_common_write_object *fwcmd = NULL;
1470 	int rc = 0, payload_len = 0;
1471 
1472 	bzero(&mbx, sizeof(struct oce_mbx));
1473 	payload_len = sizeof(struct mbx_lancer_common_write_object);
1474 
1475 	mbx.u0.s.embedded  = 1;/* Embedded */
1476 	mbx.payload_length = payload_len;
1477 	fwcmd = (struct mbx_lancer_common_write_object *)&mbx.payload;
1478 
1479 	/* initialize the ioctl header */
1480 	mbx_common_req_hdr_init(&fwcmd->params.req.hdr, 0, 0,
1481 				MBX_SUBSYSTEM_COMMON,
1482 				OPCODE_COMMON_WRITE_OBJECT,
1483 				LONG_TIMEOUT,
1484 				payload_len,
1485 				OCE_MBX_VER_V0);
1486 
1487 	fwcmd->params.req.write_length = data_size;
1488 	if (data_size == 0)
1489 		fwcmd->params.req.eof = 1;
1490 	else
1491 		fwcmd->params.req.eof = 0;
1492 
1493 	strcpy(fwcmd->params.req.object_name, "/prg");
1494 	fwcmd->params.req.descriptor_count = 1;
1495 	fwcmd->params.req.write_offset = data_offset;
1496 	fwcmd->params.req.buffer_length = data_size;
1497 	fwcmd->params.req.address_lower = pdma_mem->paddr & 0xFFFFFFFF;
1498 	fwcmd->params.req.address_upper = upper_32_bits(pdma_mem->paddr);
1499 
1500 	/* post the command */
1501 	rc = oce_mbox_post(sc, &mbx, NULL);
1502 	if (rc) {
1503 		device_printf(sc->dev,
1504 			"Write Lancer FlashROM mbox post failed\n");
1505 	} else {
1506 		*written_data = fwcmd->params.rsp.actual_write_length;
1507 		*additional_status = fwcmd->params.rsp.additional_status;
1508 		rc = fwcmd->params.rsp.status;
1509 	}
1510 	return rc;
1511 
1512 }
1513 
1514 
1515 
1516 int
1517 oce_mbox_create_rq(struct oce_rq *rq)
1518 {
1519 
1520 	struct oce_mbx mbx;
1521 	struct mbx_create_nic_rq *fwcmd;
1522 	POCE_SOFTC sc = rq->parent;
1523 	int rc, num_pages = 0;
1524 
1525 	if (rq->qstate == QCREATED)
1526 		return 0;
1527 
1528 	bzero(&mbx, sizeof(struct oce_mbx));
1529 
1530 	fwcmd = (struct mbx_create_nic_rq *)&mbx.payload;
1531 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1532 				MBX_SUBSYSTEM_NIC,
1533 				NIC_CREATE_RQ, MBX_TIMEOUT_SEC,
1534 				sizeof(struct mbx_create_nic_rq),
1535 				OCE_MBX_VER_V0);
1536 
1537 	/* oce_page_list will also prepare pages */
1538 	num_pages = oce_page_list(rq->ring, &fwcmd->params.req.pages[0]);
1539 
1540 	if (IS_XE201(sc)) {
1541 		fwcmd->params.req.frag_size = rq->cfg.frag_size/2048;
1542 		fwcmd->params.req.page_size = 1;
1543 		fwcmd->hdr.u0.req.version = OCE_MBX_VER_V1;
1544 	} else
1545 		fwcmd->params.req.frag_size = OCE_LOG2(rq->cfg.frag_size);
1546 	fwcmd->params.req.num_pages = num_pages;
1547 	fwcmd->params.req.cq_id = rq->cq->cq_id;
1548 	fwcmd->params.req.if_id = sc->if_id;
1549 	fwcmd->params.req.max_frame_size = rq->cfg.mtu;
1550 	fwcmd->params.req.is_rss_queue = rq->cfg.is_rss_queue;
1551 
1552 	mbx.u0.s.embedded = 1;
1553 	mbx.payload_length = sizeof(struct mbx_create_nic_rq);
1554 
1555 	rc = oce_mbox_post(sc, &mbx, NULL);
1556 	if (rc)
1557 		goto error;
1558 
1559 	rq->rq_id = fwcmd->params.rsp.rq_id;
1560 	rq->rss_cpuid = fwcmd->params.rsp.rss_cpuid;
1561 
1562 	return 0;
1563 error:
1564 	device_printf(sc->dev, "Mbox Create RQ failed\n");
1565 	return rc;
1566 
1567 }
1568 
1569 
1570 
1571 int
1572 oce_mbox_create_wq(struct oce_wq *wq)
1573 {
1574 	struct oce_mbx mbx;
1575 	struct mbx_create_nic_wq *fwcmd;
1576 	POCE_SOFTC sc = wq->parent;
1577 	int rc = 0, version, num_pages;
1578 
1579 	bzero(&mbx, sizeof(struct oce_mbx));
1580 
1581 	fwcmd = (struct mbx_create_nic_wq *)&mbx.payload;
1582 	if (IS_XE201(sc)) {
1583 		version = OCE_MBX_VER_V1;
1584 		fwcmd->params.req.if_id = sc->if_id;
1585 	} else
1586 		version = OCE_MBX_VER_V0;
1587 
1588 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1589 				MBX_SUBSYSTEM_NIC,
1590 				NIC_CREATE_WQ, MBX_TIMEOUT_SEC,
1591 				sizeof(struct mbx_create_nic_wq),
1592 				version);
1593 
1594 	num_pages = oce_page_list(wq->ring, &fwcmd->params.req.pages[0]);
1595 
1596 	fwcmd->params.req.nic_wq_type = wq->cfg.wq_type;
1597 	fwcmd->params.req.num_pages = num_pages;
1598 	fwcmd->params.req.wq_size = OCE_LOG2(wq->cfg.q_len) + 1;
1599 	fwcmd->params.req.cq_id = wq->cq->cq_id;
1600 	fwcmd->params.req.ulp_num = 1;
1601 
1602 	mbx.u0.s.embedded = 1;
1603 	mbx.payload_length = sizeof(struct mbx_create_nic_wq);
1604 
1605 	rc = oce_mbox_post(sc, &mbx, NULL);
1606 	if (rc)
1607 		goto error;
1608 
1609 	wq->wq_id = LE_16(fwcmd->params.rsp.wq_id);
1610 
1611 	return 0;
1612 error:
1613 	device_printf(sc->dev, "Mbox Create WQ failed\n");
1614 	return rc;
1615 
1616 }
1617 
1618 
1619 
1620 int
1621 oce_mbox_create_eq(struct oce_eq *eq)
1622 {
1623 	struct oce_mbx mbx;
1624 	struct mbx_create_common_eq *fwcmd;
1625 	POCE_SOFTC sc = eq->parent;
1626 	int rc = 0;
1627 	uint32_t num_pages;
1628 
1629 	bzero(&mbx, sizeof(struct oce_mbx));
1630 
1631 	fwcmd = (struct mbx_create_common_eq *)&mbx.payload;
1632 
1633 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1634 				MBX_SUBSYSTEM_COMMON,
1635 				OPCODE_COMMON_CREATE_EQ, MBX_TIMEOUT_SEC,
1636 				sizeof(struct mbx_create_common_eq),
1637 				OCE_MBX_VER_V0);
1638 
1639 	num_pages = oce_page_list(eq->ring, &fwcmd->params.req.pages[0]);
1640 	fwcmd->params.req.ctx.num_pages = num_pages;
1641 	fwcmd->params.req.ctx.valid = 1;
1642 	fwcmd->params.req.ctx.size = (eq->eq_cfg.item_size == 4) ? 0 : 1;
1643 	fwcmd->params.req.ctx.count = OCE_LOG2(eq->eq_cfg.q_len / 256);
1644 	fwcmd->params.req.ctx.armed = 0;
1645 	fwcmd->params.req.ctx.delay_mult = eq->eq_cfg.cur_eqd;
1646 
1647 
1648 	mbx.u0.s.embedded = 1;
1649 	mbx.payload_length = sizeof(struct mbx_create_common_eq);
1650 
1651 	rc = oce_mbox_post(sc, &mbx, NULL);
1652 	if (rc)
1653 		goto error;
1654 
1655 	eq->eq_id = LE_16(fwcmd->params.rsp.eq_id);
1656 
1657 	return 0;
1658 error:
1659 	device_printf(sc->dev, "Mbox Create EQ failed\n");
1660 	return rc;
1661 }
1662 
1663 
1664 
1665 int
1666 oce_mbox_cq_create(struct oce_cq *cq, uint32_t ncoalesce, uint32_t is_eventable)
1667 {
1668 	struct oce_mbx mbx;
1669 	struct mbx_create_common_cq *fwcmd;
1670 	POCE_SOFTC sc = cq->parent;
1671 	uint8_t version;
1672 	oce_cq_ctx_t *ctx;
1673 	uint32_t num_pages, page_size;
1674 	int rc = 0;
1675 
1676 
1677 	bzero(&mbx, sizeof(struct oce_mbx));
1678 
1679 	fwcmd = (struct mbx_create_common_cq *)&mbx.payload;
1680 
1681 	if (IS_XE201(sc))
1682 		version = OCE_MBX_VER_V2;
1683 	else
1684 		version = OCE_MBX_VER_V0;
1685 
1686 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1687 				MBX_SUBSYSTEM_COMMON,
1688 				OPCODE_COMMON_CREATE_CQ,
1689 				MBX_TIMEOUT_SEC,
1690 				sizeof(struct mbx_create_common_cq),
1691 				version);
1692 
1693 	ctx = &fwcmd->params.req.cq_ctx;
1694 
1695 	num_pages = oce_page_list(cq->ring, &fwcmd->params.req.pages[0]);
1696 	page_size =  1;  /* 1 for 4K */
1697 
1698 	if (version == OCE_MBX_VER_V2) {
1699 		ctx->v2.num_pages = LE_16(num_pages);
1700 		ctx->v2.page_size = page_size;
1701 		ctx->v2.eventable = is_eventable;
1702 		ctx->v2.valid = 1;
1703 		ctx->v2.count = OCE_LOG2(cq->cq_cfg.q_len / 256);
1704 		ctx->v2.nodelay = cq->cq_cfg.nodelay;
1705 		ctx->v2.coalesce_wm = ncoalesce;
1706 		ctx->v2.armed = 0;
1707 		ctx->v2.eq_id = cq->eq->eq_id;
1708 		if (ctx->v2.count == 3) {
1709 			if (cq->cq_cfg.q_len > (4*1024)-1)
1710 				ctx->v2.cqe_count = (4*1024)-1;
1711 			else
1712 				ctx->v2.cqe_count = cq->cq_cfg.q_len;
1713 		}
1714 	} else {
1715 		ctx->v0.num_pages = LE_16(num_pages);
1716 		ctx->v0.eventable = is_eventable;
1717 		ctx->v0.valid = 1;
1718 		ctx->v0.count = OCE_LOG2(cq->cq_cfg.q_len / 256);
1719 		ctx->v0.nodelay = cq->cq_cfg.nodelay;
1720 		ctx->v0.coalesce_wm = ncoalesce;
1721 		ctx->v0.armed = 0;
1722 		ctx->v0.eq_id = cq->eq->eq_id;
1723 	}
1724 
1725 	mbx.u0.s.embedded = 1;
1726 	mbx.payload_length = sizeof(struct mbx_create_common_cq);
1727 
1728 	rc = oce_mbox_post(sc, &mbx, NULL);
1729 	if (rc)
1730 		goto error;
1731 
1732 	cq->cq_id = LE_16(fwcmd->params.rsp.cq_id);
1733 
1734 	return 0;
1735 error:
1736 	device_printf(sc->dev, "Mbox Create CQ failed\n");
1737 	return rc;
1738 
1739 }
1740