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