xref: /freebsd/sys/dev/oce/oce_mbox.c (revision 595e514d0df2bac5b813d35f83e32875dbf16a83)
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 
41 /* $FreeBSD$ */
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 
731 
732 	for (j = 0; j < sc->nrqs; j++) {
733 		if (sc->rq[j]->cfg.is_rss_queue) {
734 			tbl[i] = sc->rq[j]->rss_cpuid;
735 			i = i + 1;
736 		}
737 	}
738 	if (i == 0) {
739 		device_printf(sc->dev, "error: Invalid number of RSS RQ's\n");
740 		rc = ENXIO;
741 
742 	}
743 
744 	/* fill log2 value indicating the size of the CPU table */
745 	if (rc == 0)
746 		fwcmd->params.req.cpu_tbl_sz_log2 = LE_16(OCE_LOG2(i));
747 
748 	return rc;
749 }
750 
751 /**
752  * @brief Function to set flow control capability in the hardware
753  * @param sc 		software handle to the device
754  * @param if_id 	interface id to read the address from
755  * @param enable_rss	0=disable, RSS_ENABLE_xxx flags otherwise
756  * @returns		0 on success, EIO on failure
757  */
758 int
759 oce_config_nic_rss(POCE_SOFTC sc, uint32_t if_id, uint16_t enable_rss)
760 {
761 	int rc;
762 	struct oce_mbx mbx;
763 	struct mbx_config_nic_rss *fwcmd =
764 				(struct mbx_config_nic_rss *)&mbx.payload;
765 	int version;
766 
767 	bzero(&mbx, sizeof(struct oce_mbx));
768 
769 	if (IS_XE201(sc)) {
770 		version = OCE_MBX_VER_V1;
771 		fwcmd->params.req.enable_rss = RSS_ENABLE_UDP_IPV4 |
772 					       RSS_ENABLE_UDP_IPV6;
773 	} else
774 		version = OCE_MBX_VER_V0;
775 
776 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
777 				MBX_SUBSYSTEM_NIC,
778 				NIC_CONFIG_RSS,
779 				MBX_TIMEOUT_SEC,
780 				sizeof(struct mbx_config_nic_rss),
781 				version);
782 	if (enable_rss)
783 		fwcmd->params.req.enable_rss |= (RSS_ENABLE_IPV4 |
784 					         RSS_ENABLE_TCP_IPV4 |
785 						 RSS_ENABLE_IPV6 |
786 						 RSS_ENABLE_TCP_IPV6);
787 	fwcmd->params.req.flush = OCE_FLUSH;
788 	fwcmd->params.req.if_id = LE_32(if_id);
789 
790 	srandom(arc4random());	/* random entropy seed */
791 	read_random(fwcmd->params.req.hash, sizeof(fwcmd->params.req.hash));
792 
793 	rc = oce_rss_itbl_init(sc, fwcmd);
794 	if (rc == 0) {
795 		mbx.u0.s.embedded = 1;
796 		mbx.payload_length = sizeof(struct mbx_config_nic_rss);
797 		DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
798 
799 		rc = oce_mbox_post(sc, &mbx, NULL);
800 		if (!rc)
801                 	rc = fwcmd->hdr.u0.rsp.status;
802 		if (rc)
803 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
804 			      __FUNCTION__, rc);
805 	}
806 	return rc;
807 }
808 
809 /**
810  * @brief 		RXF function to enable/disable device promiscuous mode
811  * @param sc		software handle to the device
812  * @param enable	enable/disable flag
813  * @returns		0 on success, EIO on failure
814  * @note
815  *	The NIC_CONFIG_PROMISCUOUS command deprecated for Lancer.
816  *	This function uses the COMMON_SET_IFACE_RX_FILTER command instead.
817  */
818 int
819 oce_rxf_set_promiscuous(POCE_SOFTC sc, uint32_t enable)
820 {
821 	struct mbx_set_common_iface_rx_filter *fwcmd;
822 	int sz = sizeof(struct mbx_set_common_iface_rx_filter);
823 	iface_rx_filter_ctx_t *req;
824 	OCE_DMA_MEM sgl;
825 	int rc;
826 
827 	/* allocate mbx payload's dma scatter/gather memory */
828 	rc = oce_dma_alloc(sc, sz, &sgl, 0);
829 	if (rc)
830 		return rc;
831 
832 	fwcmd = OCE_DMAPTR(&sgl, struct mbx_set_common_iface_rx_filter);
833 
834 	req =  &fwcmd->params.req;
835 	req->iface_flags_mask = MBX_RX_IFACE_FLAGS_PROMISCUOUS |
836 				MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS;
837 	if (enable) {
838 		req->iface_flags = MBX_RX_IFACE_FLAGS_PROMISCUOUS |
839 				   MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS;
840 	}
841 	req->if_id = sc->if_id;
842 
843 	rc = oce_set_common_iface_rx_filter(sc, &sgl);
844 	oce_dma_free(sc, &sgl);
845 
846 	return rc;
847 }
848 
849 
850 /**
851  * @brief 			Function modify and select rx filter options
852  * @param sc			software handle to the device
853  * @param sgl			scatter/gather request/response
854  * @returns			0 on success, error code on failure
855  */
856 int
857 oce_set_common_iface_rx_filter(POCE_SOFTC sc, POCE_DMA_MEM sgl)
858 {
859 	struct oce_mbx mbx;
860 	int mbx_sz = sizeof(struct mbx_set_common_iface_rx_filter);
861 	struct mbx_set_common_iface_rx_filter *fwcmd;
862 	int rc;
863 
864 	bzero(&mbx, sizeof(struct oce_mbx));
865 	fwcmd = OCE_DMAPTR(sgl, struct mbx_set_common_iface_rx_filter);
866 
867 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
868 				MBX_SUBSYSTEM_COMMON,
869 				OPCODE_COMMON_SET_IFACE_RX_FILTER,
870 				MBX_TIMEOUT_SEC,
871 				mbx_sz,
872 				OCE_MBX_VER_V0);
873 
874 	oce_dma_sync(sgl, BUS_DMASYNC_PREWRITE);
875 	mbx.u0.s.embedded = 0;
876 	mbx.u0.s.sge_count = 1;
877 	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(sgl->paddr);
878 	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(sgl->paddr);
879 	mbx.payload.u0.u1.sgl[0].length = mbx_sz;
880 	mbx.payload_length = mbx_sz;
881 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
882 
883 	rc = oce_mbox_post(sc, &mbx, NULL);
884 	if (!rc)
885                 rc = fwcmd->hdr.u0.rsp.status;
886 	if (rc)
887 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
888 			      __FUNCTION__, rc);
889 	return 0;
890 }
891 
892 /**
893  * @brief Function to query the link status from the hardware
894  * @param sc 		software handle to the device
895  * @param[out] link	pointer to the structure returning link attributes
896  * @returns		0 on success, EIO on failure
897  */
898 int
899 oce_get_link_status(POCE_SOFTC sc, struct link_status *link)
900 {
901 	struct oce_mbx mbx;
902 	struct mbx_query_common_link_config *fwcmd;
903 	int rc = 0, version;
904 
905 	bzero(&mbx, sizeof(struct oce_mbx));
906 
907 	IS_XE201(sc) ? (version = OCE_MBX_VER_V1) : (version = OCE_MBX_VER_V0);
908 
909 	fwcmd = (struct mbx_query_common_link_config *)&mbx.payload;
910 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
911 				MBX_SUBSYSTEM_COMMON,
912 				OPCODE_COMMON_QUERY_LINK_CONFIG,
913 				MBX_TIMEOUT_SEC,
914 				sizeof(struct mbx_query_common_link_config),
915 				version);
916 
917 	mbx.u0.s.embedded = 1;
918 	mbx.payload_length = sizeof(struct mbx_query_common_link_config);
919 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
920 
921 	rc = oce_mbox_post(sc, &mbx, NULL);
922 
923 	if (!rc)
924                 rc = fwcmd->hdr.u0.rsp.status;
925 	if (rc) {
926 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
927 			      __FUNCTION__, rc);
928 		goto error;
929 	}
930 	/* interpret response */
931 	bcopy(&fwcmd->params.rsp, link, sizeof(struct link_status));
932 	link->logical_link_status = LE_32(link->logical_link_status);
933 	link->qos_link_speed = LE_16(link->qos_link_speed);
934 error:
935 	return rc;
936 }
937 
938 
939 
940 int
941 oce_mbox_get_nic_stats_v0(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem)
942 {
943 	struct oce_mbx mbx;
944 	struct mbx_get_nic_stats_v0 *fwcmd;
945 	int rc = 0;
946 
947 	bzero(&mbx, sizeof(struct oce_mbx));
948 
949 	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_nic_stats_v0);
950 	bzero(fwcmd, sizeof(struct mbx_get_nic_stats_v0));
951 
952 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
953 				MBX_SUBSYSTEM_NIC,
954 				NIC_GET_STATS,
955 				MBX_TIMEOUT_SEC,
956 				sizeof(struct mbx_get_nic_stats_v0),
957 				OCE_MBX_VER_V0);
958 
959 	mbx.u0.s.embedded = 0;
960 	mbx.u0.s.sge_count = 1;
961 
962 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
963 
964 	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
965 	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
966 	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_nic_stats_v0);
967 
968 	mbx.payload_length = sizeof(struct mbx_get_nic_stats_v0);
969 
970 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
971 
972 	rc = oce_mbox_post(sc, &mbx, NULL);
973 
974 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
975 
976 	if (!rc)
977                 rc = fwcmd->hdr.u0.rsp.status;
978 	if (rc)
979 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
980 			      __FUNCTION__, rc);
981 	return rc;
982 }
983 
984 
985 
986 /**
987  * @brief Function to get NIC statistics
988  * @param sc 		software handle to the device
989  * @param *stats	pointer to where to store statistics
990  * @param reset_stats	resets statistics of set
991  * @returns		0 on success, EIO on failure
992  * @note		command depricated in Lancer
993  */
994 int
995 oce_mbox_get_nic_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem)
996 {
997 	struct oce_mbx mbx;
998 	struct mbx_get_nic_stats *fwcmd;
999 	int rc = 0;
1000 
1001 	bzero(&mbx, sizeof(struct oce_mbx));
1002 	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_nic_stats);
1003 	bzero(fwcmd, sizeof(struct mbx_get_nic_stats));
1004 
1005 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1006 				MBX_SUBSYSTEM_NIC,
1007 				NIC_GET_STATS,
1008 				MBX_TIMEOUT_SEC,
1009 				sizeof(struct mbx_get_nic_stats),
1010 				OCE_MBX_VER_V1);
1011 
1012 
1013 	mbx.u0.s.embedded = 0;  /* stats too large for embedded mbx rsp */
1014 	mbx.u0.s.sge_count = 1; /* using scatter gather instead */
1015 
1016 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
1017 	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
1018 	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
1019 	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_nic_stats);
1020 
1021 	mbx.payload_length = sizeof(struct mbx_get_nic_stats);
1022 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1023 
1024 	rc = oce_mbox_post(sc, &mbx, NULL);
1025 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
1026 	if (!rc)
1027                 rc = fwcmd->hdr.u0.rsp.status;
1028 	if (rc)
1029 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1030 			      __FUNCTION__, rc);
1031 	return rc;
1032 }
1033 
1034 
1035 /**
1036  * @brief Function to get pport (physical port) statistics
1037  * @param sc 		software handle to the device
1038  * @param *stats	pointer to where to store statistics
1039  * @param reset_stats	resets statistics of set
1040  * @returns		0 on success, EIO on failure
1041  */
1042 int
1043 oce_mbox_get_pport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem,
1044 				uint32_t reset_stats)
1045 {
1046 	struct oce_mbx mbx;
1047 	struct mbx_get_pport_stats *fwcmd;
1048 	int rc = 0;
1049 
1050 	bzero(&mbx, sizeof(struct oce_mbx));
1051 	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_pport_stats);
1052 	bzero(fwcmd, sizeof(struct mbx_get_pport_stats));
1053 
1054 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1055 				MBX_SUBSYSTEM_NIC,
1056 				NIC_GET_PPORT_STATS,
1057 				MBX_TIMEOUT_SEC,
1058 				sizeof(struct mbx_get_pport_stats),
1059 				OCE_MBX_VER_V0);
1060 
1061 	fwcmd->params.req.reset_stats = reset_stats;
1062 	fwcmd->params.req.port_number = sc->port_id;
1063 
1064 	mbx.u0.s.embedded = 0;	/* stats too large for embedded mbx rsp */
1065 	mbx.u0.s.sge_count = 1; /* using scatter gather instead */
1066 
1067 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
1068 	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
1069 	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
1070 	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_pport_stats);
1071 
1072 	mbx.payload_length = sizeof(struct mbx_get_pport_stats);
1073 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1074 
1075 	rc = oce_mbox_post(sc, &mbx, NULL);
1076 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
1077 
1078 	if (!rc)
1079                 rc = fwcmd->hdr.u0.rsp.status;
1080 	if (rc)
1081 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1082 			      __FUNCTION__, rc);
1083 	return rc;
1084 }
1085 
1086 
1087 /**
1088  * @brief Function to get vport (virtual port) statistics
1089  * @param sc 		software handle to the device
1090  * @param *stats	pointer to where to store statistics
1091  * @param reset_stats	resets statistics of set
1092  * @returns		0 on success, EIO on failure
1093  */
1094 int
1095 oce_mbox_get_vport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem,
1096 				uint32_t req_size, uint32_t reset_stats)
1097 {
1098 	struct oce_mbx mbx;
1099 	struct mbx_get_vport_stats *fwcmd;
1100 	int rc = 0;
1101 
1102 	bzero(&mbx, sizeof(struct oce_mbx));
1103 
1104 	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_vport_stats);
1105 	bzero(fwcmd, sizeof(struct mbx_get_vport_stats));
1106 
1107 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1108 				MBX_SUBSYSTEM_NIC,
1109 				NIC_GET_VPORT_STATS,
1110 				MBX_TIMEOUT_SEC,
1111 				sizeof(struct mbx_get_vport_stats),
1112 				OCE_MBX_VER_V0);
1113 
1114 	fwcmd->params.req.reset_stats = reset_stats;
1115 	fwcmd->params.req.vport_number = sc->if_id;
1116 
1117 	mbx.u0.s.embedded = 0;	/* stats too large for embedded mbx rsp */
1118 	mbx.u0.s.sge_count = 1; /* using scatter gather instead */
1119 
1120 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
1121 	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
1122 	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
1123 	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_vport_stats);
1124 
1125 	mbx.payload_length = sizeof(struct mbx_get_vport_stats);
1126 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1127 
1128 	rc = oce_mbox_post(sc, &mbx, NULL);
1129 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
1130 
1131 	if (!rc)
1132                 rc = fwcmd->hdr.u0.rsp.status;
1133 	if (rc)
1134 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1135 			      __FUNCTION__, rc);
1136 	return rc;
1137 }
1138 
1139 
1140 /**
1141  * @brief               Function to update the muticast filter with
1142  *                      values in dma_mem
1143  * @param sc            software handle to the device
1144  * @param dma_mem       pointer to dma memory region
1145  * @returns             0 on success, EIO on failure
1146  */
1147 int
1148 oce_update_multicast(POCE_SOFTC sc, POCE_DMA_MEM pdma_mem)
1149 {
1150 	struct oce_mbx mbx;
1151 	struct oce_mq_sge *sgl;
1152 	struct mbx_set_common_iface_multicast *req = NULL;
1153 	int rc = 0;
1154 
1155 	req = OCE_DMAPTR(pdma_mem, struct mbx_set_common_iface_multicast);
1156 	mbx_common_req_hdr_init(&req->hdr, 0, 0,
1157 				MBX_SUBSYSTEM_COMMON,
1158 				OPCODE_COMMON_SET_IFACE_MULTICAST,
1159 				MBX_TIMEOUT_SEC,
1160 				sizeof(struct mbx_set_common_iface_multicast),
1161 				OCE_MBX_VER_V0);
1162 
1163 	bzero(&mbx, sizeof(struct oce_mbx));
1164 
1165 	mbx.u0.s.embedded = 0; /*Non embeded*/
1166 	mbx.payload_length = sizeof(struct mbx_set_common_iface_multicast);
1167 	mbx.u0.s.sge_count = 1;
1168 	sgl = &mbx.payload.u0.u1.sgl[0];
1169 	sgl->pa_hi = htole32(upper_32_bits(pdma_mem->paddr));
1170 	sgl->pa_lo = htole32((pdma_mem->paddr) & 0xFFFFFFFF);
1171 	sgl->length = htole32(mbx.payload_length);
1172 
1173 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1174 
1175 	rc = oce_mbox_post(sc, &mbx, NULL);
1176 	if (!rc)
1177                 rc = req->hdr.u0.rsp.status;
1178 	if (rc)
1179 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1180 			      __FUNCTION__, rc);
1181 	return rc;
1182 }
1183 
1184 
1185 /**
1186  * @brief               Function to send passthrough Ioctls
1187  * @param sc            software handle to the device
1188  * @param dma_mem       pointer to dma memory region
1189  * @param req_size      size of dma_mem
1190  * @returns             0 on success, EIO on failure
1191  */
1192 int
1193 oce_pass_through_mbox(POCE_SOFTC sc, POCE_DMA_MEM dma_mem, uint32_t req_size)
1194 {
1195 	struct oce_mbx mbx;
1196 	struct oce_mq_sge *sgl;
1197 	int rc = 0;
1198 
1199 	bzero(&mbx, sizeof(struct oce_mbx));
1200 
1201 	mbx.u0.s.embedded  = 0; /*Non embeded*/
1202 	mbx.payload_length = req_size;
1203 	mbx.u0.s.sge_count = 1;
1204 	sgl = &mbx.payload.u0.u1.sgl[0];
1205 	sgl->pa_hi = htole32(upper_32_bits(dma_mem->paddr));
1206 	sgl->pa_lo = htole32((dma_mem->paddr) & 0xFFFFFFFF);
1207 	sgl->length = htole32(req_size);
1208 
1209 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1210 
1211 	rc = oce_mbox_post(sc, &mbx, NULL);
1212 	return rc;
1213 }
1214 
1215 
1216 int
1217 oce_mbox_macaddr_add(POCE_SOFTC sc, uint8_t *mac_addr,
1218 		 uint32_t if_id, uint32_t *pmac_id)
1219 {
1220 	struct oce_mbx mbx;
1221 	struct mbx_add_common_iface_mac *fwcmd;
1222 	int rc = 0;
1223 
1224 	bzero(&mbx, sizeof(struct oce_mbx));
1225 
1226 	fwcmd = (struct mbx_add_common_iface_mac *)&mbx.payload;
1227 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1228 				MBX_SUBSYSTEM_COMMON,
1229 				OPCODE_COMMON_ADD_IFACE_MAC,
1230 				MBX_TIMEOUT_SEC,
1231 				sizeof(struct mbx_add_common_iface_mac),
1232 				OCE_MBX_VER_V0);
1233 
1234 	fwcmd->params.req.if_id = (uint16_t) if_id;
1235 	bcopy(mac_addr, fwcmd->params.req.mac_address, 6);
1236 
1237 	mbx.u0.s.embedded = 1;
1238 	mbx.payload_length = sizeof(struct  mbx_add_common_iface_mac);
1239 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1240 	rc = oce_mbox_post(sc, &mbx, NULL);
1241 	if (!rc)
1242                 rc = fwcmd->hdr.u0.rsp.status;
1243 	if (rc) {
1244 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1245 			      __FUNCTION__, rc);
1246 		goto error;
1247 	}
1248 	*pmac_id = fwcmd->params.rsp.pmac_id;
1249 error:
1250 	return rc;
1251 }
1252 
1253 
1254 int
1255 oce_mbox_macaddr_del(POCE_SOFTC sc, uint32_t if_id, uint32_t pmac_id)
1256 {
1257 	struct oce_mbx mbx;
1258 	struct mbx_del_common_iface_mac *fwcmd;
1259 	int rc = 0;
1260 
1261 	bzero(&mbx, sizeof(struct oce_mbx));
1262 
1263 	fwcmd = (struct mbx_del_common_iface_mac *)&mbx.payload;
1264 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1265 				MBX_SUBSYSTEM_COMMON,
1266 				OPCODE_COMMON_DEL_IFACE_MAC,
1267 				MBX_TIMEOUT_SEC,
1268 				sizeof(struct mbx_del_common_iface_mac),
1269 				OCE_MBX_VER_V0);
1270 
1271 	fwcmd->params.req.if_id = (uint16_t)if_id;
1272 	fwcmd->params.req.pmac_id = pmac_id;
1273 
1274 	mbx.u0.s.embedded = 1;
1275 	mbx.payload_length = sizeof(struct  mbx_del_common_iface_mac);
1276 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1277 
1278 	rc = oce_mbox_post(sc, &mbx, NULL);
1279 	if (!rc)
1280                 rc = fwcmd->hdr.u0.rsp.status;
1281 	if (rc)
1282 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1283 			      __FUNCTION__, rc);
1284 	return rc;
1285 }
1286 
1287 
1288 
1289 int
1290 oce_mbox_check_native_mode(POCE_SOFTC sc)
1291 {
1292 	struct oce_mbx mbx;
1293 	struct mbx_common_set_function_cap *fwcmd;
1294 	int rc = 0;
1295 
1296 	bzero(&mbx, sizeof(struct oce_mbx));
1297 
1298 	fwcmd = (struct mbx_common_set_function_cap *)&mbx.payload;
1299 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1300 				MBX_SUBSYSTEM_COMMON,
1301 				OPCODE_COMMON_SET_FUNCTIONAL_CAPS,
1302 				MBX_TIMEOUT_SEC,
1303 				sizeof(struct mbx_common_set_function_cap),
1304 				OCE_MBX_VER_V0);
1305 
1306 	fwcmd->params.req.valid_capability_flags = CAP_SW_TIMESTAMPS |
1307 							CAP_BE3_NATIVE_ERX_API;
1308 
1309 	fwcmd->params.req.capability_flags = CAP_BE3_NATIVE_ERX_API;
1310 
1311 	mbx.u0.s.embedded = 1;
1312 	mbx.payload_length = sizeof(struct mbx_common_set_function_cap);
1313 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1314 
1315 	rc = oce_mbox_post(sc, &mbx, NULL);
1316 	if (!rc)
1317                 rc = fwcmd->hdr.u0.rsp.status;
1318 	if (rc) {
1319 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1320 			      __FUNCTION__, rc);
1321 		goto error;
1322 	}
1323 	sc->be3_native = fwcmd->params.rsp.capability_flags
1324 			& CAP_BE3_NATIVE_ERX_API;
1325 
1326 error:
1327 	return 0;
1328 }
1329 
1330 
1331 
1332 int
1333 oce_mbox_cmd_set_loopback(POCE_SOFTC sc, uint8_t port_num,
1334 		uint8_t loopback_type, uint8_t enable)
1335 {
1336 	struct oce_mbx mbx;
1337 	struct mbx_lowlevel_set_loopback_mode *fwcmd;
1338 	int rc = 0;
1339 
1340 
1341 	bzero(&mbx, sizeof(struct oce_mbx));
1342 
1343 	fwcmd = (struct mbx_lowlevel_set_loopback_mode *)&mbx.payload;
1344 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1345 				MBX_SUBSYSTEM_LOWLEVEL,
1346 				OPCODE_LOWLEVEL_SET_LOOPBACK_MODE,
1347 				MBX_TIMEOUT_SEC,
1348 				sizeof(struct mbx_lowlevel_set_loopback_mode),
1349 				OCE_MBX_VER_V0);
1350 
1351 	fwcmd->params.req.src_port = port_num;
1352 	fwcmd->params.req.dest_port = port_num;
1353 	fwcmd->params.req.loopback_type = loopback_type;
1354 	fwcmd->params.req.loopback_state = enable;
1355 
1356 	mbx.u0.s.embedded = 1;
1357 	mbx.payload_length = sizeof(struct  mbx_lowlevel_set_loopback_mode);
1358 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1359 
1360 	rc = oce_mbox_post(sc, &mbx, NULL);
1361 	if (!rc)
1362                 rc = fwcmd->hdr.u0.rsp.status;
1363 	if (rc)
1364 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1365 			      __FUNCTION__, rc);
1366 
1367 	return rc;
1368 
1369 }
1370 
1371 int
1372 oce_mbox_cmd_test_loopback(POCE_SOFTC sc, uint32_t port_num,
1373 	uint32_t loopback_type, uint32_t pkt_size, uint32_t num_pkts,
1374 	uint64_t pattern)
1375 {
1376 
1377 	struct oce_mbx mbx;
1378 	struct mbx_lowlevel_test_loopback_mode *fwcmd;
1379 	int rc = 0;
1380 
1381 
1382 	bzero(&mbx, sizeof(struct oce_mbx));
1383 
1384 	fwcmd = (struct mbx_lowlevel_test_loopback_mode *)&mbx.payload;
1385 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1386 				MBX_SUBSYSTEM_LOWLEVEL,
1387 				OPCODE_LOWLEVEL_TEST_LOOPBACK,
1388 				MBX_TIMEOUT_SEC,
1389 				sizeof(struct mbx_lowlevel_test_loopback_mode),
1390 				OCE_MBX_VER_V0);
1391 
1392 	fwcmd->params.req.pattern = pattern;
1393 	fwcmd->params.req.src_port = port_num;
1394 	fwcmd->params.req.dest_port = port_num;
1395 	fwcmd->params.req.pkt_size = pkt_size;
1396 	fwcmd->params.req.num_pkts = num_pkts;
1397 	fwcmd->params.req.loopback_type = loopback_type;
1398 
1399 	mbx.u0.s.embedded = 1;
1400 	mbx.payload_length = sizeof(struct  mbx_lowlevel_test_loopback_mode);
1401 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1402 
1403 	rc = oce_mbox_post(sc, &mbx, NULL);
1404 	if (!rc)
1405                 rc = fwcmd->hdr.u0.rsp.status;
1406 	if (rc)
1407 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1408 			      __FUNCTION__, rc);
1409 
1410 	return rc;
1411 }
1412 
1413 int
1414 oce_mbox_write_flashrom(POCE_SOFTC sc, uint32_t optype,uint32_t opcode,
1415 				POCE_DMA_MEM pdma_mem, uint32_t num_bytes)
1416 {
1417 
1418 	struct oce_mbx mbx;
1419 	struct oce_mq_sge *sgl = NULL;
1420 	struct mbx_common_read_write_flashrom *fwcmd = NULL;
1421 	int rc = 0, payload_len = 0;
1422 
1423 	bzero(&mbx, sizeof(struct oce_mbx));
1424 	fwcmd = OCE_DMAPTR(pdma_mem, struct mbx_common_read_write_flashrom);
1425 	payload_len = sizeof(struct mbx_common_read_write_flashrom) + 32*1024;
1426 
1427 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1428 				MBX_SUBSYSTEM_COMMON,
1429 				OPCODE_COMMON_WRITE_FLASHROM,
1430 				LONG_TIMEOUT,
1431 				payload_len,
1432 				OCE_MBX_VER_V0);
1433 
1434 	fwcmd->flash_op_type = optype;
1435 	fwcmd->flash_op_code = opcode;
1436 	fwcmd->data_buffer_size = num_bytes;
1437 
1438 	mbx.u0.s.embedded  = 0; /*Non embeded*/
1439 	mbx.payload_length = payload_len;
1440 	mbx.u0.s.sge_count = 1;
1441 
1442 	sgl = &mbx.payload.u0.u1.sgl[0];
1443 	sgl->pa_hi = upper_32_bits(pdma_mem->paddr);
1444 	sgl->pa_lo = pdma_mem->paddr & 0xFFFFFFFF;
1445 	sgl->length = payload_len;
1446 
1447 	/* post the command */
1448 	rc = oce_mbox_post(sc, &mbx, NULL);
1449 	if (!rc)
1450                 rc = fwcmd->hdr.u0.rsp.status;
1451 	if (rc)
1452 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1453 			      __FUNCTION__, rc);
1454 
1455 	return rc;
1456 
1457 }
1458 
1459 int
1460 oce_mbox_get_flashrom_crc(POCE_SOFTC sc, uint8_t *flash_crc,
1461 				uint32_t offset, uint32_t optype)
1462 {
1463 
1464 	int rc = 0, payload_len = 0;
1465 	struct oce_mbx mbx;
1466 	struct mbx_common_read_write_flashrom *fwcmd;
1467 
1468 	bzero(&mbx, sizeof(struct oce_mbx));
1469 
1470 	fwcmd = (struct mbx_common_read_write_flashrom *)&mbx.payload;
1471 
1472 	/* Firmware requires extra 4 bytes with this ioctl. Since there
1473 	   is enough room in the mbx payload it should be good enough
1474 	   Reference: Bug 14853
1475 	*/
1476 	payload_len = sizeof(struct mbx_common_read_write_flashrom) + 4;
1477 
1478 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1479 				MBX_SUBSYSTEM_COMMON,
1480 				OPCODE_COMMON_READ_FLASHROM,
1481 				MBX_TIMEOUT_SEC,
1482 				payload_len,
1483 				OCE_MBX_VER_V0);
1484 
1485 	fwcmd->flash_op_type = optype;
1486 	fwcmd->flash_op_code = FLASHROM_OPER_REPORT;
1487 	fwcmd->data_offset = offset;
1488 	fwcmd->data_buffer_size = 0x4;
1489 
1490 	mbx.u0.s.embedded  = 1;
1491 	mbx.payload_length = payload_len;
1492 
1493 	/* post the command */
1494 	rc = oce_mbox_post(sc, &mbx, NULL);
1495 	if (!rc)
1496                 rc = fwcmd->hdr.u0.rsp.status;
1497 	if (rc) {
1498 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1499 			      __FUNCTION__, rc);
1500 		goto error;
1501 	}
1502 	bcopy(fwcmd->data_buffer, flash_crc, 4);
1503 error:
1504 	return rc;
1505 }
1506 
1507 int
1508 oce_mbox_get_phy_info(POCE_SOFTC sc, struct oce_phy_info *phy_info)
1509 {
1510 
1511 	struct oce_mbx mbx;
1512 	struct mbx_common_phy_info *fwcmd;
1513 	int rc = 0;
1514 
1515 	bzero(&mbx, sizeof(struct oce_mbx));
1516 
1517 	fwcmd = (struct mbx_common_phy_info *)&mbx.payload;
1518 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1519 				MBX_SUBSYSTEM_COMMON,
1520 				OPCODE_COMMON_GET_PHY_CONFIG,
1521 				MBX_TIMEOUT_SEC,
1522 				sizeof(struct mbx_common_phy_info),
1523 				OCE_MBX_VER_V0);
1524 
1525 	mbx.u0.s.embedded = 1;
1526 	mbx.payload_length = sizeof(struct  mbx_common_phy_info);
1527 
1528 	/* now post the command */
1529 	rc = oce_mbox_post(sc, &mbx, NULL);
1530 	if (!rc)
1531                 rc = fwcmd->hdr.u0.rsp.status;
1532 	if (rc) {
1533 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1534 			      __FUNCTION__, rc);
1535 		goto error;
1536 	}
1537 	phy_info->phy_type = fwcmd->params.rsp.phy_info.phy_type;
1538 	phy_info->interface_type =
1539 			fwcmd->params.rsp.phy_info.interface_type;
1540 	phy_info->auto_speeds_supported =
1541 		fwcmd->params.rsp.phy_info.auto_speeds_supported;
1542 	phy_info->fixed_speeds_supported =
1543 		fwcmd->params.rsp.phy_info.fixed_speeds_supported;
1544 	phy_info->misc_params =fwcmd->params.rsp.phy_info.misc_params;
1545 error:
1546 	return rc;
1547 
1548 }
1549 
1550 
1551 int
1552 oce_mbox_lancer_write_flashrom(POCE_SOFTC sc, uint32_t data_size,
1553 			uint32_t data_offset, POCE_DMA_MEM pdma_mem,
1554 			uint32_t *written_data, uint32_t *additional_status)
1555 {
1556 
1557 	struct oce_mbx mbx;
1558 	struct mbx_lancer_common_write_object *fwcmd = NULL;
1559 	int rc = 0, payload_len = 0;
1560 
1561 	bzero(&mbx, sizeof(struct oce_mbx));
1562 	payload_len = sizeof(struct mbx_lancer_common_write_object);
1563 
1564 	mbx.u0.s.embedded  = 1;/* Embedded */
1565 	mbx.payload_length = payload_len;
1566 	fwcmd = (struct mbx_lancer_common_write_object *)&mbx.payload;
1567 
1568 	/* initialize the ioctl header */
1569 	mbx_common_req_hdr_init(&fwcmd->params.req.hdr, 0, 0,
1570 				MBX_SUBSYSTEM_COMMON,
1571 				OPCODE_COMMON_WRITE_OBJECT,
1572 				LONG_TIMEOUT,
1573 				payload_len,
1574 				OCE_MBX_VER_V0);
1575 
1576 	fwcmd->params.req.write_length = data_size;
1577 	if (data_size == 0)
1578 		fwcmd->params.req.eof = 1;
1579 	else
1580 		fwcmd->params.req.eof = 0;
1581 
1582 	strcpy(fwcmd->params.req.object_name, "/prg");
1583 	fwcmd->params.req.descriptor_count = 1;
1584 	fwcmd->params.req.write_offset = data_offset;
1585 	fwcmd->params.req.buffer_length = data_size;
1586 	fwcmd->params.req.address_lower = pdma_mem->paddr & 0xFFFFFFFF;
1587 	fwcmd->params.req.address_upper = upper_32_bits(pdma_mem->paddr);
1588 
1589 	/* post the command */
1590 	rc = oce_mbox_post(sc, &mbx, NULL);
1591 	if (!rc)
1592                 rc = fwcmd->params.rsp.status;
1593 	if (rc) {
1594 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1595 			      __FUNCTION__, rc);
1596 		goto error;
1597 	}
1598 	*written_data = fwcmd->params.rsp.actual_write_length;
1599 	*additional_status = fwcmd->params.rsp.additional_status;
1600 error:
1601 	return rc;
1602 
1603 }
1604 
1605 
1606 
1607 int
1608 oce_mbox_create_rq(struct oce_rq *rq)
1609 {
1610 
1611 	struct oce_mbx mbx;
1612 	struct mbx_create_nic_rq *fwcmd;
1613 	POCE_SOFTC sc = rq->parent;
1614 	int rc, num_pages = 0;
1615 
1616 	if (rq->qstate == QCREATED)
1617 		return 0;
1618 
1619 	bzero(&mbx, sizeof(struct oce_mbx));
1620 
1621 	fwcmd = (struct mbx_create_nic_rq *)&mbx.payload;
1622 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1623 				MBX_SUBSYSTEM_NIC,
1624 				NIC_CREATE_RQ, MBX_TIMEOUT_SEC,
1625 				sizeof(struct mbx_create_nic_rq),
1626 				OCE_MBX_VER_V0);
1627 
1628 	/* oce_page_list will also prepare pages */
1629 	num_pages = oce_page_list(rq->ring, &fwcmd->params.req.pages[0]);
1630 
1631 	if (IS_XE201(sc)) {
1632 		fwcmd->params.req.frag_size = rq->cfg.frag_size/2048;
1633 		fwcmd->params.req.page_size = 1;
1634 		fwcmd->hdr.u0.req.version = OCE_MBX_VER_V1;
1635 	} else
1636 		fwcmd->params.req.frag_size = OCE_LOG2(rq->cfg.frag_size);
1637 	fwcmd->params.req.num_pages = num_pages;
1638 	fwcmd->params.req.cq_id = rq->cq->cq_id;
1639 	fwcmd->params.req.if_id = sc->if_id;
1640 	fwcmd->params.req.max_frame_size = rq->cfg.mtu;
1641 	fwcmd->params.req.is_rss_queue = rq->cfg.is_rss_queue;
1642 
1643 	mbx.u0.s.embedded = 1;
1644 	mbx.payload_length = sizeof(struct mbx_create_nic_rq);
1645 
1646 	rc = oce_mbox_post(sc, &mbx, NULL);
1647 	if (!rc)
1648                 rc = fwcmd->hdr.u0.rsp.status;
1649 	if (rc) {
1650 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1651 			      __FUNCTION__, rc);
1652 		goto error;
1653 	}
1654 	rq->rq_id = fwcmd->params.rsp.rq_id;
1655 	rq->rss_cpuid = fwcmd->params.rsp.rss_cpuid;
1656 error:
1657 	return rc;
1658 
1659 }
1660 
1661 
1662 
1663 int
1664 oce_mbox_create_wq(struct oce_wq *wq)
1665 {
1666 	struct oce_mbx mbx;
1667 	struct mbx_create_nic_wq *fwcmd;
1668 	POCE_SOFTC sc = wq->parent;
1669 	int rc = 0, version, num_pages;
1670 
1671 	bzero(&mbx, sizeof(struct oce_mbx));
1672 
1673 	fwcmd = (struct mbx_create_nic_wq *)&mbx.payload;
1674 	if (IS_XE201(sc)) {
1675 		version = OCE_MBX_VER_V1;
1676 		fwcmd->params.req.if_id = sc->if_id;
1677 	} else
1678 		version = OCE_MBX_VER_V0;
1679 
1680 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1681 				MBX_SUBSYSTEM_NIC,
1682 				NIC_CREATE_WQ, MBX_TIMEOUT_SEC,
1683 				sizeof(struct mbx_create_nic_wq),
1684 				version);
1685 
1686 	num_pages = oce_page_list(wq->ring, &fwcmd->params.req.pages[0]);
1687 
1688 	fwcmd->params.req.nic_wq_type = wq->cfg.wq_type;
1689 	fwcmd->params.req.num_pages = num_pages;
1690 	fwcmd->params.req.wq_size = OCE_LOG2(wq->cfg.q_len) + 1;
1691 	fwcmd->params.req.cq_id = wq->cq->cq_id;
1692 	fwcmd->params.req.ulp_num = 1;
1693 
1694 	mbx.u0.s.embedded = 1;
1695 	mbx.payload_length = sizeof(struct mbx_create_nic_wq);
1696 
1697 	rc = oce_mbox_post(sc, &mbx, NULL);
1698 	if (!rc)
1699                 rc = fwcmd->hdr.u0.rsp.status;
1700 	if (rc) {
1701 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1702 			      __FUNCTION__, rc);
1703 		goto error;
1704 	}
1705 	wq->wq_id = LE_16(fwcmd->params.rsp.wq_id);
1706 error:
1707 	return rc;
1708 
1709 }
1710 
1711 
1712 
1713 int
1714 oce_mbox_create_eq(struct oce_eq *eq)
1715 {
1716 	struct oce_mbx mbx;
1717 	struct mbx_create_common_eq *fwcmd;
1718 	POCE_SOFTC sc = eq->parent;
1719 	int rc = 0;
1720 	uint32_t num_pages;
1721 
1722 	bzero(&mbx, sizeof(struct oce_mbx));
1723 
1724 	fwcmd = (struct mbx_create_common_eq *)&mbx.payload;
1725 
1726 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1727 				MBX_SUBSYSTEM_COMMON,
1728 				OPCODE_COMMON_CREATE_EQ, MBX_TIMEOUT_SEC,
1729 				sizeof(struct mbx_create_common_eq),
1730 				OCE_MBX_VER_V0);
1731 
1732 	num_pages = oce_page_list(eq->ring, &fwcmd->params.req.pages[0]);
1733 	fwcmd->params.req.ctx.num_pages = num_pages;
1734 	fwcmd->params.req.ctx.valid = 1;
1735 	fwcmd->params.req.ctx.size = (eq->eq_cfg.item_size == 4) ? 0 : 1;
1736 	fwcmd->params.req.ctx.count = OCE_LOG2(eq->eq_cfg.q_len / 256);
1737 	fwcmd->params.req.ctx.armed = 0;
1738 	fwcmd->params.req.ctx.delay_mult = eq->eq_cfg.cur_eqd;
1739 
1740 
1741 	mbx.u0.s.embedded = 1;
1742 	mbx.payload_length = sizeof(struct mbx_create_common_eq);
1743 
1744 	rc = oce_mbox_post(sc, &mbx, NULL);
1745 	if (!rc)
1746                 rc = fwcmd->hdr.u0.rsp.status;
1747 	if (rc) {
1748 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1749 			      __FUNCTION__, rc);
1750 		goto error;
1751 	}
1752 	eq->eq_id = LE_16(fwcmd->params.rsp.eq_id);
1753 error:
1754 	return rc;
1755 }
1756 
1757 
1758 
1759 int
1760 oce_mbox_cq_create(struct oce_cq *cq, uint32_t ncoalesce, uint32_t is_eventable)
1761 {
1762 	struct oce_mbx mbx;
1763 	struct mbx_create_common_cq *fwcmd;
1764 	POCE_SOFTC sc = cq->parent;
1765 	uint8_t version;
1766 	oce_cq_ctx_t *ctx;
1767 	uint32_t num_pages, page_size;
1768 	int rc = 0;
1769 
1770 
1771 	bzero(&mbx, sizeof(struct oce_mbx));
1772 
1773 	fwcmd = (struct mbx_create_common_cq *)&mbx.payload;
1774 
1775 	if (IS_XE201(sc))
1776 		version = OCE_MBX_VER_V2;
1777 	else
1778 		version = OCE_MBX_VER_V0;
1779 
1780 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1781 				MBX_SUBSYSTEM_COMMON,
1782 				OPCODE_COMMON_CREATE_CQ,
1783 				MBX_TIMEOUT_SEC,
1784 				sizeof(struct mbx_create_common_cq),
1785 				version);
1786 
1787 	ctx = &fwcmd->params.req.cq_ctx;
1788 
1789 	num_pages = oce_page_list(cq->ring, &fwcmd->params.req.pages[0]);
1790 	page_size =  1;  /* 1 for 4K */
1791 
1792 	if (version == OCE_MBX_VER_V2) {
1793 		ctx->v2.num_pages = LE_16(num_pages);
1794 		ctx->v2.page_size = page_size;
1795 		ctx->v2.eventable = is_eventable;
1796 		ctx->v2.valid = 1;
1797 		ctx->v2.count = OCE_LOG2(cq->cq_cfg.q_len / 256);
1798 		ctx->v2.nodelay = cq->cq_cfg.nodelay;
1799 		ctx->v2.coalesce_wm = ncoalesce;
1800 		ctx->v2.armed = 0;
1801 		ctx->v2.eq_id = cq->eq->eq_id;
1802 		if (ctx->v2.count == 3) {
1803 			if (cq->cq_cfg.q_len > (4*1024)-1)
1804 				ctx->v2.cqe_count = (4*1024)-1;
1805 			else
1806 				ctx->v2.cqe_count = cq->cq_cfg.q_len;
1807 		}
1808 	} else {
1809 		ctx->v0.num_pages = LE_16(num_pages);
1810 		ctx->v0.eventable = is_eventable;
1811 		ctx->v0.valid = 1;
1812 		ctx->v0.count = OCE_LOG2(cq->cq_cfg.q_len / 256);
1813 		ctx->v0.nodelay = cq->cq_cfg.nodelay;
1814 		ctx->v0.coalesce_wm = ncoalesce;
1815 		ctx->v0.armed = 0;
1816 		ctx->v0.eq_id = cq->eq->eq_id;
1817 	}
1818 
1819 	mbx.u0.s.embedded = 1;
1820 	mbx.payload_length = sizeof(struct mbx_create_common_cq);
1821 
1822 	rc = oce_mbox_post(sc, &mbx, NULL);
1823 	if (!rc)
1824                 rc = fwcmd->hdr.u0.rsp.status;
1825 	if (rc) {
1826 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1827 			      __FUNCTION__, rc);
1828 		goto error;
1829 	}
1830 	cq->cq_id = LE_16(fwcmd->params.rsp.cq_id);
1831 error:
1832 	return rc;
1833 
1834 }
1835 
1836 int
1837 oce_mbox_read_transrecv_data(POCE_SOFTC sc, uint32_t page_num)
1838 {
1839 	int rc = 0;
1840 	struct oce_mbx mbx;
1841 	struct mbx_read_common_transrecv_data *fwcmd;
1842 	struct oce_mq_sge *sgl;
1843 	OCE_DMA_MEM dma;
1844 
1845 	/* Allocate DMA mem*/
1846 	if (oce_dma_alloc(sc, sizeof(struct mbx_read_common_transrecv_data),
1847 				&dma, 0))
1848 		return ENOMEM;
1849 
1850 	fwcmd = OCE_DMAPTR(&dma, struct mbx_read_common_transrecv_data);
1851 	bzero(fwcmd, sizeof(struct mbx_read_common_transrecv_data));
1852 
1853 	bzero(&mbx, sizeof(struct oce_mbx));
1854 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1855 			MBX_SUBSYSTEM_COMMON,
1856 			OPCODE_COMMON_READ_TRANSRECEIVER_DATA,
1857 			MBX_TIMEOUT_SEC,
1858 			sizeof(struct mbx_read_common_transrecv_data),
1859 			OCE_MBX_VER_V0);
1860 
1861 	/* fill rest of mbx */
1862 	mbx.u0.s.embedded = 0;
1863 	mbx.payload_length = sizeof(struct mbx_read_common_transrecv_data);
1864 	mbx.u0.s.sge_count = 1;
1865 	sgl = &mbx.payload.u0.u1.sgl[0];
1866 	sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
1867 	sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
1868 	sgl->length = htole32(mbx.payload_length);
1869 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1870 
1871 	fwcmd->params.req.port = LE_32(sc->port_id);
1872 	fwcmd->params.req.page_num = LE_32(page_num);
1873 
1874 	/* command post */
1875 	rc = oce_mbox_post(sc, &mbx, NULL);
1876 	if (!rc)
1877                 rc = fwcmd->hdr.u0.rsp.status;
1878 	if (rc) {
1879 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1880 			      __FUNCTION__, rc);
1881 		goto error;
1882 	}
1883 	if(fwcmd->params.rsp.page_num == PAGE_NUM_A0)
1884 	{
1885 		bcopy((char *)fwcmd->params.rsp.page_data,
1886 				(char *)&sfp_vpd_dump_buffer[0],
1887 				TRANSCEIVER_A0_SIZE);
1888 	}
1889 
1890 	if(fwcmd->params.rsp.page_num == PAGE_NUM_A2)
1891 	{
1892 		bcopy((char *)fwcmd->params.rsp.page_data,
1893 				(char *)&sfp_vpd_dump_buffer[32],
1894 				TRANSCEIVER_A2_SIZE);
1895 	}
1896 error:
1897 	return rc;
1898 }
1899 
1900 void
1901 oce_mbox_eqd_modify_periodic(POCE_SOFTC sc, struct oce_set_eqd *set_eqd,
1902 				int num)
1903 {
1904 	struct oce_mbx mbx;
1905 	struct mbx_modify_common_eq_delay *fwcmd;
1906 	int rc = 0;
1907 	int i = 0;
1908 
1909 	bzero(&mbx, sizeof(struct oce_mbx));
1910 
1911 	/* Initialize MODIFY_EQ_DELAY ioctl header */
1912 	fwcmd = (struct mbx_modify_common_eq_delay *)&mbx.payload;
1913 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1914 				MBX_SUBSYSTEM_COMMON,
1915 				OPCODE_COMMON_MODIFY_EQ_DELAY,
1916 				MBX_TIMEOUT_SEC,
1917 				sizeof(struct mbx_modify_common_eq_delay),
1918 				OCE_MBX_VER_V0);
1919 	/* fill rest of mbx */
1920 	mbx.u0.s.embedded = 1;
1921 	mbx.payload_length = sizeof(struct mbx_modify_common_eq_delay);
1922 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1923 
1924 	fwcmd->params.req.num_eq = num;
1925 	for (i = 0; i < num; i++) {
1926 		fwcmd->params.req.delay[i].eq_id =
1927 					htole32(set_eqd[i].eq_id);
1928 		fwcmd->params.req.delay[i].phase = 0;
1929 		fwcmd->params.req.delay[i].dm =
1930 		htole32(set_eqd[i].delay_multiplier);
1931 	}
1932 
1933 
1934 	/* command post */
1935 	rc = oce_mbox_post(sc, &mbx, NULL);
1936 
1937 	if (!rc)
1938                 rc = fwcmd->hdr.u0.rsp.status;
1939 	if (rc)
1940 		device_printf(sc->dev,"%s failed - cmd status: %d\n",
1941 			      __FUNCTION__, rc);
1942 }
1943 
1944 
1945