xref: /freebsd/sys/dev/oce/oce_mbox.c (revision e0dd0fe31e16b4fd3be4a4dc55af844205d6f4ba)
12f345d8eSLuigi Rizzo /*-
27282444bSPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
37282444bSPedro F. Giffuni  *
4291a1934SXin LI  * Copyright (C) 2013 Emulex
52f345d8eSLuigi Rizzo  * All rights reserved.
62f345d8eSLuigi Rizzo  *
72f345d8eSLuigi Rizzo  * Redistribution and use in source and binary forms, with or without
82f345d8eSLuigi Rizzo  * modification, are permitted provided that the following conditions are met:
92f345d8eSLuigi Rizzo  *
102f345d8eSLuigi Rizzo  * 1. Redistributions of source code must retain the above copyright notice,
112f345d8eSLuigi Rizzo  *    this list of conditions and the following disclaimer.
122f345d8eSLuigi Rizzo  *
132f345d8eSLuigi Rizzo  * 2. Redistributions in binary form must reproduce the above copyright
142f345d8eSLuigi Rizzo  *    notice, this list of conditions and the following disclaimer in the
152f345d8eSLuigi Rizzo  *    documentation and/or other materials provided with the distribution.
162f345d8eSLuigi Rizzo  *
172f345d8eSLuigi Rizzo  * 3. Neither the name of the Emulex Corporation nor the names of its
182f345d8eSLuigi Rizzo  *    contributors may be used to endorse or promote products derived from
192f345d8eSLuigi Rizzo  *    this software without specific prior written permission.
202f345d8eSLuigi Rizzo  *
212f345d8eSLuigi Rizzo  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
222f345d8eSLuigi Rizzo  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
232f345d8eSLuigi Rizzo  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
242f345d8eSLuigi Rizzo  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
252f345d8eSLuigi Rizzo  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
262f345d8eSLuigi Rizzo  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
272f345d8eSLuigi Rizzo  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
282f345d8eSLuigi Rizzo  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
292f345d8eSLuigi Rizzo  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
302f345d8eSLuigi Rizzo  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
312f345d8eSLuigi Rizzo  * POSSIBILITY OF SUCH DAMAGE.
322f345d8eSLuigi Rizzo  *
332f345d8eSLuigi Rizzo  * Contact Information:
342f345d8eSLuigi Rizzo  * freebsd-drivers@emulex.com
352f345d8eSLuigi Rizzo  *
362f345d8eSLuigi Rizzo  * Emulex
372f345d8eSLuigi Rizzo  * 3333 Susan Street
382f345d8eSLuigi Rizzo  * Costa Mesa, CA 92626
392f345d8eSLuigi Rizzo  */
402f345d8eSLuigi Rizzo 
412f345d8eSLuigi Rizzo /* $FreeBSD$ */
422f345d8eSLuigi Rizzo 
43cdaba892SXin LI #include "oce_if.h"
442f345d8eSLuigi Rizzo 
45dced0d18SJosh Paetzel int
46dced0d18SJosh Paetzel oce_wait_ready(POCE_SOFTC sc)
47dced0d18SJosh Paetzel {
48dced0d18SJosh Paetzel #define SLIPORT_READY_TIMEOUT 30000
49dced0d18SJosh Paetzel 	uint32_t sliport_status, i;
50dced0d18SJosh Paetzel 
51dced0d18SJosh Paetzel 	if (!IS_XE201(sc))
52dced0d18SJosh Paetzel 		return (-1);
53dced0d18SJosh Paetzel 
54dced0d18SJosh Paetzel 	for (i = 0; i < SLIPORT_READY_TIMEOUT; i++) {
55dced0d18SJosh Paetzel 		sliport_status = OCE_READ_REG32(sc, db, SLIPORT_STATUS_OFFSET);
56dced0d18SJosh Paetzel 		if (sliport_status & SLIPORT_STATUS_RDY_MASK)
57dced0d18SJosh Paetzel 			return 0;
58dced0d18SJosh Paetzel 
59dced0d18SJosh Paetzel 		if (sliport_status & SLIPORT_STATUS_ERR_MASK &&
60dced0d18SJosh Paetzel 			!(sliport_status & SLIPORT_STATUS_RN_MASK)) {
61dced0d18SJosh Paetzel 			device_printf(sc->dev, "Error detected in the card\n");
62dced0d18SJosh Paetzel 			return EIO;
63dced0d18SJosh Paetzel 		}
64dced0d18SJosh Paetzel 
65dced0d18SJosh Paetzel 		DELAY(1000);
66dced0d18SJosh Paetzel 	}
67dced0d18SJosh Paetzel 
68dced0d18SJosh Paetzel 	device_printf(sc->dev, "Firmware wait timed out\n");
69dced0d18SJosh Paetzel 
70dced0d18SJosh Paetzel 	return (-1);
71dced0d18SJosh Paetzel }
72dced0d18SJosh Paetzel 
732f345d8eSLuigi Rizzo /**
742f345d8eSLuigi Rizzo  * @brief Reset (firmware) common function
752f345d8eSLuigi Rizzo  * @param sc		software handle to the device
762f345d8eSLuigi Rizzo  * @returns		0 on success, ETIMEDOUT on failure
772f345d8eSLuigi Rizzo  */
782f345d8eSLuigi Rizzo int
792f345d8eSLuigi Rizzo oce_reset_fun(POCE_SOFTC sc)
802f345d8eSLuigi Rizzo {
812f345d8eSLuigi Rizzo 	struct oce_mbx *mbx;
822f345d8eSLuigi Rizzo 	struct oce_bmbx *mb;
832f345d8eSLuigi Rizzo 	struct ioctl_common_function_reset *fwcmd;
842f345d8eSLuigi Rizzo 	int rc = 0;
852f345d8eSLuigi Rizzo 
86dced0d18SJosh Paetzel 	if (IS_XE201(sc)) {
87dced0d18SJosh Paetzel 		OCE_WRITE_REG32(sc, db, SLIPORT_CONTROL_OFFSET,
88dced0d18SJosh Paetzel 					SLI_PORT_CONTROL_IP_MASK);
89dced0d18SJosh Paetzel 
90dced0d18SJosh Paetzel 		rc = oce_wait_ready(sc);
91dced0d18SJosh Paetzel 		if (rc) {
92dced0d18SJosh Paetzel 			device_printf(sc->dev, "Firmware reset Failed\n");
93dced0d18SJosh Paetzel 		}
94dced0d18SJosh Paetzel 
95dced0d18SJosh Paetzel 		return rc;
96dced0d18SJosh Paetzel 	}
97dced0d18SJosh Paetzel 
982f345d8eSLuigi Rizzo 	mb = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
992f345d8eSLuigi Rizzo 	mbx = &mb->mbx;
1002f345d8eSLuigi Rizzo 	bzero(mbx, sizeof(struct oce_mbx));
1012f345d8eSLuigi Rizzo 
1022f345d8eSLuigi Rizzo 	fwcmd = (struct ioctl_common_function_reset *)&mbx->payload;
1032f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1042f345d8eSLuigi Rizzo 			MBX_SUBSYSTEM_COMMON,
1052f345d8eSLuigi Rizzo 			OPCODE_COMMON_FUNCTION_RESET,
1062f345d8eSLuigi Rizzo 			10,	/* MBX_TIMEOUT_SEC */
1072f345d8eSLuigi Rizzo 			sizeof(struct
1082f345d8eSLuigi Rizzo 				ioctl_common_function_reset),
1092f345d8eSLuigi Rizzo 			OCE_MBX_VER_V0);
1102f345d8eSLuigi Rizzo 
1112f345d8eSLuigi Rizzo 	mbx->u0.s.embedded = 1;
1122f345d8eSLuigi Rizzo 	mbx->payload_length =
1132f345d8eSLuigi Rizzo 		sizeof(struct ioctl_common_function_reset);
1142f345d8eSLuigi Rizzo 
1152f345d8eSLuigi Rizzo 	rc = oce_mbox_dispatch(sc, 2);
1162f345d8eSLuigi Rizzo 
1172f345d8eSLuigi Rizzo 	return rc;
1182f345d8eSLuigi Rizzo }
1192f345d8eSLuigi Rizzo 
1202f345d8eSLuigi Rizzo 
1212f345d8eSLuigi Rizzo /**
1222f345d8eSLuigi Rizzo  * @brief  		This funtions tells firmware we are
1232f345d8eSLuigi Rizzo  *			done with commands.
1242f345d8eSLuigi Rizzo  * @param sc            software handle to the device
1252f345d8eSLuigi Rizzo  * @returns             0 on success, ETIMEDOUT on failure
1262f345d8eSLuigi Rizzo  */
1272f345d8eSLuigi Rizzo int
1282f345d8eSLuigi Rizzo oce_fw_clean(POCE_SOFTC sc)
1292f345d8eSLuigi Rizzo {
1302f345d8eSLuigi Rizzo 	struct oce_bmbx *mbx;
1312f345d8eSLuigi Rizzo 	uint8_t *ptr;
1322f345d8eSLuigi Rizzo 	int ret = 0;
1332f345d8eSLuigi Rizzo 
1342f345d8eSLuigi Rizzo 	mbx = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
1352f345d8eSLuigi Rizzo 	ptr = (uint8_t *) &mbx->mbx;
1362f345d8eSLuigi Rizzo 
1372f345d8eSLuigi Rizzo 	/* Endian Signature */
1382f345d8eSLuigi Rizzo 	*ptr++ = 0xff;
1392f345d8eSLuigi Rizzo 	*ptr++ = 0xaa;
1402f345d8eSLuigi Rizzo 	*ptr++ = 0xbb;
1412f345d8eSLuigi Rizzo 	*ptr++ = 0xff;
1422f345d8eSLuigi Rizzo 	*ptr++ = 0xff;
1432f345d8eSLuigi Rizzo 	*ptr++ = 0xcc;
1442f345d8eSLuigi Rizzo 	*ptr++ = 0xdd;
1452f345d8eSLuigi Rizzo 	*ptr = 0xff;
1462f345d8eSLuigi Rizzo 
1472f345d8eSLuigi Rizzo 	ret = oce_mbox_dispatch(sc, 2);
1482f345d8eSLuigi Rizzo 
1492f345d8eSLuigi Rizzo 	return ret;
1502f345d8eSLuigi Rizzo }
1512f345d8eSLuigi Rizzo 
1522f345d8eSLuigi Rizzo 
1532f345d8eSLuigi Rizzo /**
1542f345d8eSLuigi Rizzo  * @brief Mailbox wait
1552f345d8eSLuigi Rizzo  * @param sc		software handle to the device
1562f345d8eSLuigi Rizzo  * @param tmo_sec	timeout in seconds
1572f345d8eSLuigi Rizzo  */
1582f345d8eSLuigi Rizzo static int
1592f345d8eSLuigi Rizzo oce_mbox_wait(POCE_SOFTC sc, uint32_t tmo_sec)
1602f345d8eSLuigi Rizzo {
1612f345d8eSLuigi Rizzo 	tmo_sec *= 10000;
1622f345d8eSLuigi Rizzo 	pd_mpu_mbox_db_t mbox_db;
1632f345d8eSLuigi Rizzo 
1642f345d8eSLuigi Rizzo 	for (;;) {
1652f345d8eSLuigi Rizzo 		if (tmo_sec != 0) {
1662f345d8eSLuigi Rizzo 			if (--tmo_sec == 0)
1672f345d8eSLuigi Rizzo 				break;
1682f345d8eSLuigi Rizzo 		}
1692f345d8eSLuigi Rizzo 
1702f345d8eSLuigi Rizzo 		mbox_db.dw0 = OCE_READ_REG32(sc, db, PD_MPU_MBOX_DB);
1712f345d8eSLuigi Rizzo 
1722f345d8eSLuigi Rizzo 		if (mbox_db.bits.ready)
1732f345d8eSLuigi Rizzo 			return 0;
1742f345d8eSLuigi Rizzo 
1752f345d8eSLuigi Rizzo 		DELAY(100);
1762f345d8eSLuigi Rizzo 	}
1772f345d8eSLuigi Rizzo 
1782f345d8eSLuigi Rizzo 	device_printf(sc->dev, "Mailbox timed out\n");
1792f345d8eSLuigi Rizzo 
1802f345d8eSLuigi Rizzo 	return ETIMEDOUT;
1812f345d8eSLuigi Rizzo }
1822f345d8eSLuigi Rizzo 
1832f345d8eSLuigi Rizzo 
1842f345d8eSLuigi Rizzo /**
1852f345d8eSLuigi Rizzo  * @brief Mailbox dispatch
1862f345d8eSLuigi Rizzo  * @param sc		software handle to the device
1872f345d8eSLuigi Rizzo  * @param tmo_sec	timeout in seconds
1882f345d8eSLuigi Rizzo  */
1892f345d8eSLuigi Rizzo int
1902f345d8eSLuigi Rizzo oce_mbox_dispatch(POCE_SOFTC sc, uint32_t tmo_sec)
1912f345d8eSLuigi Rizzo {
1922f345d8eSLuigi Rizzo 	pd_mpu_mbox_db_t mbox_db;
1932f345d8eSLuigi Rizzo 	uint32_t pa;
1942f345d8eSLuigi Rizzo 	int rc;
1952f345d8eSLuigi Rizzo 
1962f345d8eSLuigi Rizzo 	oce_dma_sync(&sc->bsmbx, BUS_DMASYNC_PREWRITE);
1972f345d8eSLuigi Rizzo 	pa = (uint32_t) ((uint64_t) sc->bsmbx.paddr >> 34);
1982f345d8eSLuigi Rizzo 	bzero(&mbox_db, sizeof(pd_mpu_mbox_db_t));
1992f345d8eSLuigi Rizzo 	mbox_db.bits.ready = 0;
2002f345d8eSLuigi Rizzo 	mbox_db.bits.hi = 1;
2012f345d8eSLuigi Rizzo 	mbox_db.bits.address = pa;
2022f345d8eSLuigi Rizzo 
2032f345d8eSLuigi Rizzo 	rc = oce_mbox_wait(sc, tmo_sec);
2042f345d8eSLuigi Rizzo 	if (rc == 0) {
2052f345d8eSLuigi Rizzo 		OCE_WRITE_REG32(sc, db, PD_MPU_MBOX_DB, mbox_db.dw0);
2062f345d8eSLuigi Rizzo 
2072f345d8eSLuigi Rizzo 		pa = (uint32_t) ((uint64_t) sc->bsmbx.paddr >> 4) & 0x3fffffff;
2082f345d8eSLuigi Rizzo 		mbox_db.bits.ready = 0;
2092f345d8eSLuigi Rizzo 		mbox_db.bits.hi = 0;
2102f345d8eSLuigi Rizzo 		mbox_db.bits.address = pa;
2112f345d8eSLuigi Rizzo 
2122f345d8eSLuigi Rizzo 		rc = oce_mbox_wait(sc, tmo_sec);
2132f345d8eSLuigi Rizzo 
2142f345d8eSLuigi Rizzo 		if (rc == 0) {
2152f345d8eSLuigi Rizzo 			OCE_WRITE_REG32(sc, db, PD_MPU_MBOX_DB, mbox_db.dw0);
2162f345d8eSLuigi Rizzo 
2172f345d8eSLuigi Rizzo 			rc = oce_mbox_wait(sc, tmo_sec);
2182f345d8eSLuigi Rizzo 
2192f345d8eSLuigi Rizzo 			oce_dma_sync(&sc->bsmbx, BUS_DMASYNC_POSTWRITE);
2202f345d8eSLuigi Rizzo 		}
2212f345d8eSLuigi Rizzo 	}
2222f345d8eSLuigi Rizzo 
2232f345d8eSLuigi Rizzo 	return rc;
2242f345d8eSLuigi Rizzo }
2252f345d8eSLuigi Rizzo 
2262f345d8eSLuigi Rizzo 
2272f345d8eSLuigi Rizzo 
2282f345d8eSLuigi Rizzo /**
2292f345d8eSLuigi Rizzo  * @brief 		Mailbox common request header initialization
2302f345d8eSLuigi Rizzo  * @param hdr		mailbox header
2312f345d8eSLuigi Rizzo  * @param dom		domain
2322f345d8eSLuigi Rizzo  * @param port		port
2332f345d8eSLuigi Rizzo  * @param subsys	subsystem
2342f345d8eSLuigi Rizzo  * @param opcode	opcode
2352f345d8eSLuigi Rizzo  * @param timeout	timeout
2362f345d8eSLuigi Rizzo  * @param pyld_len	payload length
2372f345d8eSLuigi Rizzo  */
2382f345d8eSLuigi Rizzo void
2392f345d8eSLuigi Rizzo mbx_common_req_hdr_init(struct mbx_hdr *hdr,
2402f345d8eSLuigi Rizzo 			uint8_t dom, uint8_t port,
2412f345d8eSLuigi Rizzo 			uint8_t subsys, uint8_t opcode,
2422f345d8eSLuigi Rizzo 			uint32_t timeout, uint32_t pyld_len,
2432f345d8eSLuigi Rizzo 			uint8_t version)
2442f345d8eSLuigi Rizzo {
2452f345d8eSLuigi Rizzo 	hdr->u0.req.opcode = opcode;
2462f345d8eSLuigi Rizzo 	hdr->u0.req.subsystem = subsys;
2472f345d8eSLuigi Rizzo 	hdr->u0.req.port_number = port;
2482f345d8eSLuigi Rizzo 	hdr->u0.req.domain = dom;
2492f345d8eSLuigi Rizzo 
2502f345d8eSLuigi Rizzo 	hdr->u0.req.timeout = timeout;
2512f345d8eSLuigi Rizzo 	hdr->u0.req.request_length = pyld_len - sizeof(struct mbx_hdr);
2522f345d8eSLuigi Rizzo 	hdr->u0.req.version = version;
2532f345d8eSLuigi Rizzo }
2542f345d8eSLuigi Rizzo 
2552f345d8eSLuigi Rizzo 
2562f345d8eSLuigi Rizzo 
2572f345d8eSLuigi Rizzo /**
2582f345d8eSLuigi Rizzo  * @brief Function to initialize the hw with host endian information
2592f345d8eSLuigi Rizzo  * @param sc		software handle to the device
2602f345d8eSLuigi Rizzo  * @returns		0 on success, ETIMEDOUT on failure
2612f345d8eSLuigi Rizzo  */
2622f345d8eSLuigi Rizzo int
2632f345d8eSLuigi Rizzo oce_mbox_init(POCE_SOFTC sc)
2642f345d8eSLuigi Rizzo {
2652f345d8eSLuigi Rizzo 	struct oce_bmbx *mbx;
2662f345d8eSLuigi Rizzo 	uint8_t *ptr;
2672f345d8eSLuigi Rizzo 	int ret = 0;
2682f345d8eSLuigi Rizzo 
2692f345d8eSLuigi Rizzo 	if (sc->flags & OCE_FLAGS_MBOX_ENDIAN_RQD) {
2702f345d8eSLuigi Rizzo 		mbx = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
2712f345d8eSLuigi Rizzo 		ptr = (uint8_t *) &mbx->mbx;
2722f345d8eSLuigi Rizzo 
2732f345d8eSLuigi Rizzo 		/* Endian Signature */
2742f345d8eSLuigi Rizzo 		*ptr++ = 0xff;
2752f345d8eSLuigi Rizzo 		*ptr++ = 0x12;
2762f345d8eSLuigi Rizzo 		*ptr++ = 0x34;
2772f345d8eSLuigi Rizzo 		*ptr++ = 0xff;
2782f345d8eSLuigi Rizzo 		*ptr++ = 0xff;
2792f345d8eSLuigi Rizzo 		*ptr++ = 0x56;
2802f345d8eSLuigi Rizzo 		*ptr++ = 0x78;
2812f345d8eSLuigi Rizzo 		*ptr = 0xff;
2822f345d8eSLuigi Rizzo 
2832f345d8eSLuigi Rizzo 		ret = oce_mbox_dispatch(sc, 0);
2842f345d8eSLuigi Rizzo 	}
2852f345d8eSLuigi Rizzo 
2862f345d8eSLuigi Rizzo 	return ret;
2872f345d8eSLuigi Rizzo }
2882f345d8eSLuigi Rizzo 
2892f345d8eSLuigi Rizzo 
2902f345d8eSLuigi Rizzo /**
2912f345d8eSLuigi Rizzo  * @brief 		Function to get the firmware version
2922f345d8eSLuigi Rizzo  * @param sc		software handle to the device
2932f345d8eSLuigi Rizzo  * @returns		0 on success, EIO on failure
2942f345d8eSLuigi Rizzo  */
2952f345d8eSLuigi Rizzo int
2962f345d8eSLuigi Rizzo oce_get_fw_version(POCE_SOFTC sc)
2972f345d8eSLuigi Rizzo {
2982f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
2992f345d8eSLuigi Rizzo 	struct mbx_get_common_fw_version *fwcmd;
3002f345d8eSLuigi Rizzo 	int ret = 0;
3012f345d8eSLuigi Rizzo 
3022f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
3032f345d8eSLuigi Rizzo 
3042f345d8eSLuigi Rizzo 	fwcmd = (struct mbx_get_common_fw_version *)&mbx.payload;
3052f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
3062f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_COMMON,
3072f345d8eSLuigi Rizzo 				OPCODE_COMMON_GET_FW_VERSION,
3082f345d8eSLuigi Rizzo 				MBX_TIMEOUT_SEC,
3092f345d8eSLuigi Rizzo 				sizeof(struct mbx_get_common_fw_version),
3102f345d8eSLuigi Rizzo 				OCE_MBX_VER_V0);
3112f345d8eSLuigi Rizzo 
3122f345d8eSLuigi Rizzo 	mbx.u0.s.embedded = 1;
3132f345d8eSLuigi Rizzo 	mbx.payload_length = sizeof(struct mbx_get_common_fw_version);
3142f345d8eSLuigi Rizzo 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
3152f345d8eSLuigi Rizzo 
3162f345d8eSLuigi Rizzo 	ret = oce_mbox_post(sc, &mbx, NULL);
317cdaba892SXin LI 	if (!ret)
318cdaba892SXin LI                 ret = fwcmd->hdr.u0.rsp.status;
319cdaba892SXin LI 	if (ret) {
3205fbb6830SXin LI 		device_printf(sc->dev,
3215fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
3225fbb6830SXin LI 			      __FUNCTION__, ret,
3235fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
324cdaba892SXin LI 		goto error;
325cdaba892SXin LI 	}
3262f345d8eSLuigi Rizzo 
3272f345d8eSLuigi Rizzo 	bcopy(fwcmd->params.rsp.fw_ver_str, sc->fw_version, 32);
328cdaba892SXin LI error:
329cdaba892SXin LI 	return ret;
3302f345d8eSLuigi Rizzo }
3312f345d8eSLuigi Rizzo 
3322f345d8eSLuigi Rizzo 
3332f345d8eSLuigi Rizzo /**
3349bd3250aSLuigi Rizzo  * @brief	Firmware will send gracious notifications during
3359bd3250aSLuigi Rizzo  *		attach only after sending first mcc commnad. We
3369bd3250aSLuigi Rizzo  *		use MCC queue only for getting async and mailbox
3379bd3250aSLuigi Rizzo  *		for sending cmds. So to get gracious notifications
3389bd3250aSLuigi Rizzo  *		atleast send one dummy command on mcc.
3399bd3250aSLuigi Rizzo  */
3409bd3250aSLuigi Rizzo int
3419bd3250aSLuigi Rizzo oce_first_mcc_cmd(POCE_SOFTC sc)
3429bd3250aSLuigi Rizzo {
3439bd3250aSLuigi Rizzo 	struct oce_mbx *mbx;
3449bd3250aSLuigi Rizzo 	struct oce_mq *mq = sc->mq;
3459bd3250aSLuigi Rizzo 	struct mbx_get_common_fw_version *fwcmd;
3469bd3250aSLuigi Rizzo 	uint32_t reg_value;
3479bd3250aSLuigi Rizzo 
3489bd3250aSLuigi Rizzo 	mbx = RING_GET_PRODUCER_ITEM_VA(mq->ring, struct oce_mbx);
3499bd3250aSLuigi Rizzo 	bzero(mbx, sizeof(struct oce_mbx));
3509bd3250aSLuigi Rizzo 
3519bd3250aSLuigi Rizzo 	fwcmd = (struct mbx_get_common_fw_version *)&mbx->payload;
3529bd3250aSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
3539bd3250aSLuigi Rizzo 				MBX_SUBSYSTEM_COMMON,
3549bd3250aSLuigi Rizzo 				OPCODE_COMMON_GET_FW_VERSION,
3559bd3250aSLuigi Rizzo 				MBX_TIMEOUT_SEC,
3569bd3250aSLuigi Rizzo 				sizeof(struct mbx_get_common_fw_version),
3579bd3250aSLuigi Rizzo 				OCE_MBX_VER_V0);
3589bd3250aSLuigi Rizzo 	mbx->u0.s.embedded = 1;
3599bd3250aSLuigi Rizzo 	mbx->payload_length = sizeof(struct mbx_get_common_fw_version);
3609bd3250aSLuigi Rizzo 	bus_dmamap_sync(mq->ring->dma.tag, mq->ring->dma.map,
3619bd3250aSLuigi Rizzo 				BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE);
3629bd3250aSLuigi Rizzo 	RING_PUT(mq->ring, 1);
3639bd3250aSLuigi Rizzo 	reg_value = (1 << 16) | mq->mq_id;
3649bd3250aSLuigi Rizzo 	OCE_WRITE_REG32(sc, db, PD_MQ_DB, reg_value);
3659bd3250aSLuigi Rizzo 
3669bd3250aSLuigi Rizzo 	return 0;
3679bd3250aSLuigi Rizzo }
3689bd3250aSLuigi Rizzo 
3699bd3250aSLuigi Rizzo /**
3702f345d8eSLuigi Rizzo  * @brief		Function to post a MBX to the mbox
3712f345d8eSLuigi Rizzo  * @param sc		software handle to the device
3722f345d8eSLuigi Rizzo  * @param mbx 		pointer to the MBX to send
3732f345d8eSLuigi Rizzo  * @param mbxctx	pointer to the mbx context structure
3742f345d8eSLuigi Rizzo  * @returns		0 on success, error on failure
3752f345d8eSLuigi Rizzo  */
3762f345d8eSLuigi Rizzo int
3772f345d8eSLuigi Rizzo oce_mbox_post(POCE_SOFTC sc, struct oce_mbx *mbx, struct oce_mbx_ctx *mbxctx)
3782f345d8eSLuigi Rizzo {
3792f345d8eSLuigi Rizzo 	struct oce_mbx *mb_mbx = NULL;
3802f345d8eSLuigi Rizzo 	struct oce_mq_cqe *mb_cqe = NULL;
3812f345d8eSLuigi Rizzo 	struct oce_bmbx *mb = NULL;
3822f345d8eSLuigi Rizzo 	int rc = 0;
3832f345d8eSLuigi Rizzo 	uint32_t tmo = 0;
3842f345d8eSLuigi Rizzo 	uint32_t cstatus = 0;
3852f345d8eSLuigi Rizzo 	uint32_t xstatus = 0;
3862f345d8eSLuigi Rizzo 
3872f345d8eSLuigi Rizzo 	LOCK(&sc->bmbx_lock);
3882f345d8eSLuigi Rizzo 
3892f345d8eSLuigi Rizzo 	mb = OCE_DMAPTR(&sc->bsmbx, struct oce_bmbx);
3902f345d8eSLuigi Rizzo 	mb_mbx = &mb->mbx;
3912f345d8eSLuigi Rizzo 
3922f345d8eSLuigi Rizzo 	/* get the tmo */
3932f345d8eSLuigi Rizzo 	tmo = mbx->tag[0];
3942f345d8eSLuigi Rizzo 	mbx->tag[0] = 0;
3952f345d8eSLuigi Rizzo 
3962f345d8eSLuigi Rizzo 	/* copy mbx into mbox */
3972f345d8eSLuigi Rizzo 	bcopy(mbx, mb_mbx, sizeof(struct oce_mbx));
3982f345d8eSLuigi Rizzo 
3992f345d8eSLuigi Rizzo 	/* now dispatch */
4002f345d8eSLuigi Rizzo 	rc = oce_mbox_dispatch(sc, tmo);
4012f345d8eSLuigi Rizzo 	if (rc == 0) {
4022f345d8eSLuigi Rizzo 		/*
4032f345d8eSLuigi Rizzo 		 * the command completed successfully. Now get the
4042f345d8eSLuigi Rizzo 		 * completion queue entry
4052f345d8eSLuigi Rizzo 		 */
4062f345d8eSLuigi Rizzo 		mb_cqe = &mb->cqe;
4072f345d8eSLuigi Rizzo 		DW_SWAP(u32ptr(&mb_cqe->u0.dw[0]), sizeof(struct oce_mq_cqe));
4082f345d8eSLuigi Rizzo 
4092f345d8eSLuigi Rizzo 		/* copy mbox mbx back */
4102f345d8eSLuigi Rizzo 		bcopy(mb_mbx, mbx, sizeof(struct oce_mbx));
4112f345d8eSLuigi Rizzo 
4122f345d8eSLuigi Rizzo 		/* pick up the mailbox status */
4132f345d8eSLuigi Rizzo 		cstatus = mb_cqe->u0.s.completion_status;
4142f345d8eSLuigi Rizzo 		xstatus = mb_cqe->u0.s.extended_status;
4152f345d8eSLuigi Rizzo 
4162f345d8eSLuigi Rizzo 		/*
4172f345d8eSLuigi Rizzo 		 * store the mbx context in the cqe tag section so that
4182f345d8eSLuigi Rizzo 		 * the upper layer handling the cqe can associate the mbx
4192f345d8eSLuigi Rizzo 		 * with the response
4202f345d8eSLuigi Rizzo 		 */
4212f345d8eSLuigi Rizzo 		if (cstatus == 0 && mbxctx) {
4222f345d8eSLuigi Rizzo 			/* save context */
4232f345d8eSLuigi Rizzo 			mbxctx->mbx = mb_mbx;
4242f345d8eSLuigi Rizzo 			bcopy(&mbxctx, mb_cqe->u0.s.mq_tag,
4252f345d8eSLuigi Rizzo 				sizeof(struct oce_mbx_ctx *));
4262f345d8eSLuigi Rizzo 		}
4272f345d8eSLuigi Rizzo 	}
4282f345d8eSLuigi Rizzo 
4292f345d8eSLuigi Rizzo 	UNLOCK(&sc->bmbx_lock);
4302f345d8eSLuigi Rizzo 
4312f345d8eSLuigi Rizzo 	return rc;
4322f345d8eSLuigi Rizzo }
4332f345d8eSLuigi Rizzo 
4342f345d8eSLuigi Rizzo /**
4352f345d8eSLuigi Rizzo  * @brief Function to read the mac address associated with an interface
4362f345d8eSLuigi Rizzo  * @param sc		software handle to the device
4372f345d8eSLuigi Rizzo  * @param if_id 	interface id to read the address from
4382f345d8eSLuigi Rizzo  * @param perm 		set to 1 if reading the factory mac address.
4392f345d8eSLuigi Rizzo  *			In this case if_id is ignored
4402f345d8eSLuigi Rizzo  * @param type 		type of the mac address, whether network or storage
4412f345d8eSLuigi Rizzo  * @param[out] mac 	[OUTPUT] pointer to a buffer containing the
4422f345d8eSLuigi Rizzo  *			mac address when the command succeeds.
4432f345d8eSLuigi Rizzo  * @returns		0 on success, EIO on failure
4442f345d8eSLuigi Rizzo  */
4452f345d8eSLuigi Rizzo int
4462f345d8eSLuigi Rizzo oce_read_mac_addr(POCE_SOFTC sc, uint32_t if_id,
4472f345d8eSLuigi Rizzo 		uint8_t perm, uint8_t type, struct mac_address_format *mac)
4482f345d8eSLuigi Rizzo {
4492f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
4502f345d8eSLuigi Rizzo 	struct mbx_query_common_iface_mac *fwcmd;
4512f345d8eSLuigi Rizzo 	int ret = 0;
4522f345d8eSLuigi Rizzo 
4532f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
4542f345d8eSLuigi Rizzo 
4552f345d8eSLuigi Rizzo 	fwcmd = (struct mbx_query_common_iface_mac *)&mbx.payload;
4562f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
4572f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_COMMON,
4582f345d8eSLuigi Rizzo 				OPCODE_COMMON_QUERY_IFACE_MAC,
4592f345d8eSLuigi Rizzo 				MBX_TIMEOUT_SEC,
4602f345d8eSLuigi Rizzo 				sizeof(struct mbx_query_common_iface_mac),
4612f345d8eSLuigi Rizzo 				OCE_MBX_VER_V0);
4622f345d8eSLuigi Rizzo 
4632f345d8eSLuigi Rizzo 	fwcmd->params.req.permanent = perm;
4642f345d8eSLuigi Rizzo 	if (!perm)
4652f345d8eSLuigi Rizzo 		fwcmd->params.req.if_id = (uint16_t) if_id;
4662f345d8eSLuigi Rizzo 	else
4672f345d8eSLuigi Rizzo 		fwcmd->params.req.if_id = 0;
4682f345d8eSLuigi Rizzo 
4692f345d8eSLuigi Rizzo 	fwcmd->params.req.type = type;
4702f345d8eSLuigi Rizzo 
4712f345d8eSLuigi Rizzo 	mbx.u0.s.embedded = 1;
4722f345d8eSLuigi Rizzo 	mbx.payload_length = sizeof(struct mbx_query_common_iface_mac);
4732f345d8eSLuigi Rizzo 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
4742f345d8eSLuigi Rizzo 
4752f345d8eSLuigi Rizzo 	ret = oce_mbox_post(sc, &mbx, NULL);
476cdaba892SXin LI 	if (!ret)
477cdaba892SXin LI                 ret = fwcmd->hdr.u0.rsp.status;
478cdaba892SXin LI 	if (ret) {
4795fbb6830SXin LI 		device_printf(sc->dev,
4805fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
4815fbb6830SXin LI 			      __FUNCTION__, ret,
4825fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
483cdaba892SXin LI 		goto error;
484cdaba892SXin LI 	}
4852f345d8eSLuigi Rizzo 
4862f345d8eSLuigi Rizzo 	/* copy the mac addres in the output parameter */
4872f345d8eSLuigi Rizzo 	mac->size_of_struct = fwcmd->params.rsp.mac.size_of_struct;
4882f345d8eSLuigi Rizzo 	bcopy(&fwcmd->params.rsp.mac.mac_addr[0], &mac->mac_addr[0],
4892f345d8eSLuigi Rizzo 		mac->size_of_struct);
490cdaba892SXin LI error:
491cdaba892SXin LI 	return ret;
4922f345d8eSLuigi Rizzo }
4932f345d8eSLuigi Rizzo 
4942f345d8eSLuigi Rizzo /**
4952f345d8eSLuigi Rizzo  * @brief Function to query the fw attributes from the hw
4962f345d8eSLuigi Rizzo  * @param sc		software handle to the device
4972f345d8eSLuigi Rizzo  * @returns		0 on success, EIO on failure
4982f345d8eSLuigi Rizzo  */
4992f345d8eSLuigi Rizzo int
5002f345d8eSLuigi Rizzo oce_get_fw_config(POCE_SOFTC sc)
5012f345d8eSLuigi Rizzo {
5022f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
5032f345d8eSLuigi Rizzo 	struct mbx_common_query_fw_config *fwcmd;
5042f345d8eSLuigi Rizzo 	int ret = 0;
5052f345d8eSLuigi Rizzo 
5062f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
5072f345d8eSLuigi Rizzo 
5082f345d8eSLuigi Rizzo 	fwcmd = (struct mbx_common_query_fw_config *)&mbx.payload;
5092f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
5102f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_COMMON,
5112f345d8eSLuigi Rizzo 				OPCODE_COMMON_QUERY_FIRMWARE_CONFIG,
5122f345d8eSLuigi Rizzo 				MBX_TIMEOUT_SEC,
5132f345d8eSLuigi Rizzo 				sizeof(struct mbx_common_query_fw_config),
5142f345d8eSLuigi Rizzo 				OCE_MBX_VER_V0);
5152f345d8eSLuigi Rizzo 
5162f345d8eSLuigi Rizzo 	mbx.u0.s.embedded = 1;
5172f345d8eSLuigi Rizzo 	mbx.payload_length = sizeof(struct mbx_common_query_fw_config);
5182f345d8eSLuigi Rizzo 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
5192f345d8eSLuigi Rizzo 
5202f345d8eSLuigi Rizzo 	ret = oce_mbox_post(sc, &mbx, NULL);
521cdaba892SXin LI 	if (!ret)
522cdaba892SXin LI                 ret = fwcmd->hdr.u0.rsp.status;
523cdaba892SXin LI 	if (ret) {
5245fbb6830SXin LI 		device_printf(sc->dev,
5255fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
5265fbb6830SXin LI 			      __FUNCTION__, ret,
5275fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
528cdaba892SXin LI 		goto error;
529cdaba892SXin LI 	}
5302f345d8eSLuigi Rizzo 
5312f345d8eSLuigi Rizzo 	DW_SWAP(u32ptr(fwcmd), sizeof(struct mbx_common_query_fw_config));
5322f345d8eSLuigi Rizzo 
5335fbb6830SXin LI 	sc->config_number = HOST_32(fwcmd->params.rsp.config_number);
5345fbb6830SXin LI 	sc->asic_revision = HOST_32(fwcmd->params.rsp.asic_revision);
5355fbb6830SXin LI 	sc->port_id	  = HOST_32(fwcmd->params.rsp.port_id);
5365fbb6830SXin LI 	sc->function_mode = HOST_32(fwcmd->params.rsp.function_mode);
537c2625e6eSJosh Paetzel 	if ((sc->function_mode & (ULP_NIC_MODE | ULP_RDMA_MODE)) ==
538c2625e6eSJosh Paetzel 	    (ULP_NIC_MODE | ULP_RDMA_MODE)) {
539c2625e6eSJosh Paetzel 	  sc->rdma_flags = OCE_RDMA_FLAG_SUPPORTED;
540c2625e6eSJosh Paetzel 	}
5415fbb6830SXin LI 	sc->function_caps = HOST_32(fwcmd->params.rsp.function_caps);
5422f345d8eSLuigi Rizzo 
5432f345d8eSLuigi Rizzo 	if (fwcmd->params.rsp.ulp[0].ulp_mode & ULP_NIC_MODE) {
5445fbb6830SXin LI 		sc->max_tx_rings = HOST_32(fwcmd->params.rsp.ulp[0].nic_wq_tot);
5455fbb6830SXin LI 		sc->max_rx_rings = HOST_32(fwcmd->params.rsp.ulp[0].lro_rqid_tot);
5462f345d8eSLuigi Rizzo 	} else {
5475fbb6830SXin LI 		sc->max_tx_rings = HOST_32(fwcmd->params.rsp.ulp[1].nic_wq_tot);
5485fbb6830SXin LI 		sc->max_rx_rings = HOST_32(fwcmd->params.rsp.ulp[1].lro_rqid_tot);
5492f345d8eSLuigi Rizzo 	}
5502f345d8eSLuigi Rizzo 
551cdaba892SXin LI error:
552cdaba892SXin LI 	return ret;
5532f345d8eSLuigi Rizzo 
5542f345d8eSLuigi Rizzo }
5552f345d8eSLuigi Rizzo 
5562f345d8eSLuigi Rizzo /**
5572f345d8eSLuigi Rizzo  *
5582f345d8eSLuigi Rizzo  * @brief function to create a device interface
5592f345d8eSLuigi Rizzo  * @param sc		software handle to the device
5602f345d8eSLuigi Rizzo  * @param cap_flags	capability flags
5612f345d8eSLuigi Rizzo  * @param en_flags	enable capability flags
5622f345d8eSLuigi Rizzo  * @param vlan_tag	optional vlan tag to associate with the if
5632f345d8eSLuigi Rizzo  * @param mac_addr	pointer to a buffer containing the mac address
5642f345d8eSLuigi Rizzo  * @param[out] if_id	[OUTPUT] pointer to an integer to hold the ID of the
5652f345d8eSLuigi Rizzo  interface created
5662f345d8eSLuigi Rizzo  * @returns		0 on success, EIO on failure
5672f345d8eSLuigi Rizzo  */
5682f345d8eSLuigi Rizzo int
5692f345d8eSLuigi Rizzo oce_if_create(POCE_SOFTC sc,
5702f345d8eSLuigi Rizzo 		uint32_t cap_flags,
5712f345d8eSLuigi Rizzo 		uint32_t en_flags,
5722f345d8eSLuigi Rizzo 		uint16_t vlan_tag,
5732f345d8eSLuigi Rizzo 		uint8_t *mac_addr,
5742f345d8eSLuigi Rizzo 		uint32_t *if_id)
5752f345d8eSLuigi Rizzo {
5762f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
5772f345d8eSLuigi Rizzo 	struct mbx_create_common_iface *fwcmd;
5782f345d8eSLuigi Rizzo 	int rc = 0;
5792f345d8eSLuigi Rizzo 
5802f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
5812f345d8eSLuigi Rizzo 
5822f345d8eSLuigi Rizzo 	fwcmd = (struct mbx_create_common_iface *)&mbx.payload;
5832f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
5842f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_COMMON,
5852f345d8eSLuigi Rizzo 				OPCODE_COMMON_CREATE_IFACE,
5862f345d8eSLuigi Rizzo 				MBX_TIMEOUT_SEC,
5872f345d8eSLuigi Rizzo 				sizeof(struct mbx_create_common_iface),
5882f345d8eSLuigi Rizzo 				OCE_MBX_VER_V0);
5892f345d8eSLuigi Rizzo 	DW_SWAP(u32ptr(&fwcmd->hdr), sizeof(struct mbx_hdr));
5902f345d8eSLuigi Rizzo 
5912f345d8eSLuigi Rizzo 	fwcmd->params.req.version = 0;
5922f345d8eSLuigi Rizzo 	fwcmd->params.req.cap_flags = LE_32(cap_flags);
5932f345d8eSLuigi Rizzo 	fwcmd->params.req.enable_flags = LE_32(en_flags);
5942f345d8eSLuigi Rizzo 	if (mac_addr != NULL) {
5952f345d8eSLuigi Rizzo 		bcopy(mac_addr, &fwcmd->params.req.mac_addr[0], 6);
5962f345d8eSLuigi Rizzo 		fwcmd->params.req.vlan_tag.u0.normal.vtag = LE_16(vlan_tag);
5972f345d8eSLuigi Rizzo 		fwcmd->params.req.mac_invalid = 0;
5982f345d8eSLuigi Rizzo 	} else {
5992f345d8eSLuigi Rizzo 		fwcmd->params.req.mac_invalid = 1;
6002f345d8eSLuigi Rizzo 	}
6012f345d8eSLuigi Rizzo 
6022f345d8eSLuigi Rizzo 	mbx.u0.s.embedded = 1;
6032f345d8eSLuigi Rizzo 	mbx.payload_length = sizeof(struct mbx_create_common_iface);
6042f345d8eSLuigi Rizzo 	DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ);
6052f345d8eSLuigi Rizzo 
6062f345d8eSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
607cdaba892SXin LI 	if (!rc)
608cdaba892SXin LI                 rc = fwcmd->hdr.u0.rsp.status;
609cdaba892SXin LI 	if (rc) {
6105fbb6830SXin LI 		device_printf(sc->dev,
6115fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
6125fbb6830SXin LI 			      __FUNCTION__, rc,
6135fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
614cdaba892SXin LI 		goto error;
615cdaba892SXin LI 	}
6162f345d8eSLuigi Rizzo 
6175fbb6830SXin LI 	*if_id = HOST_32(fwcmd->params.rsp.if_id);
6182f345d8eSLuigi Rizzo 
6192f345d8eSLuigi Rizzo 	if (mac_addr != NULL)
6205fbb6830SXin LI 		sc->pmac_id = HOST_32(fwcmd->params.rsp.pmac_id);
621cdaba892SXin LI error:
622cdaba892SXin LI 	return rc;
6232f345d8eSLuigi Rizzo }
6242f345d8eSLuigi Rizzo 
6252f345d8eSLuigi Rizzo /**
6262f345d8eSLuigi Rizzo  * @brief		Function to delete an interface
6272f345d8eSLuigi Rizzo  * @param sc 		software handle to the device
6282f345d8eSLuigi Rizzo  * @param if_id		ID of the interface to delete
6292f345d8eSLuigi Rizzo  * @returns		0 on success, EIO on failure
6302f345d8eSLuigi Rizzo  */
6312f345d8eSLuigi Rizzo int
6322f345d8eSLuigi Rizzo oce_if_del(POCE_SOFTC sc, uint32_t if_id)
6332f345d8eSLuigi Rizzo {
6342f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
6352f345d8eSLuigi Rizzo 	struct mbx_destroy_common_iface *fwcmd;
6362f345d8eSLuigi Rizzo 	int rc = 0;
6372f345d8eSLuigi Rizzo 
6382f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
6392f345d8eSLuigi Rizzo 
6402f345d8eSLuigi Rizzo 	fwcmd = (struct mbx_destroy_common_iface *)&mbx.payload;
6412f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
6422f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_COMMON,
6432f345d8eSLuigi Rizzo 				OPCODE_COMMON_DESTROY_IFACE,
6442f345d8eSLuigi Rizzo 				MBX_TIMEOUT_SEC,
6452f345d8eSLuigi Rizzo 				sizeof(struct mbx_destroy_common_iface),
6462f345d8eSLuigi Rizzo 				OCE_MBX_VER_V0);
6472f345d8eSLuigi Rizzo 
6482f345d8eSLuigi Rizzo 	fwcmd->params.req.if_id = if_id;
6492f345d8eSLuigi Rizzo 
6502f345d8eSLuigi Rizzo 	mbx.u0.s.embedded = 1;
6512f345d8eSLuigi Rizzo 	mbx.payload_length = sizeof(struct mbx_destroy_common_iface);
6522f345d8eSLuigi Rizzo 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
6532f345d8eSLuigi Rizzo 
6542f345d8eSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
655cdaba892SXin LI 	if (!rc)
656cdaba892SXin LI                 rc = fwcmd->hdr.u0.rsp.status;
657cdaba892SXin LI 	if (rc)
6585fbb6830SXin LI 		device_printf(sc->dev,
6595fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
6605fbb6830SXin LI 			      __FUNCTION__, rc,
6615fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
6622f345d8eSLuigi Rizzo 	return rc;
6632f345d8eSLuigi Rizzo }
6642f345d8eSLuigi Rizzo 
6652f345d8eSLuigi Rizzo /**
6662f345d8eSLuigi Rizzo  * @brief Function to send the mbx command to configure vlan
6672f345d8eSLuigi Rizzo  * @param sc 		software handle to the device
6682f345d8eSLuigi Rizzo  * @param if_id 	interface identifier index
6692f345d8eSLuigi Rizzo  * @param vtag_arr	array of vlan tags
6702f345d8eSLuigi Rizzo  * @param vtag_cnt	number of elements in array
6712f345d8eSLuigi Rizzo  * @param untagged	boolean TRUE/FLASE
6722f345d8eSLuigi Rizzo  * @param enable_promisc flag to enable/disable VLAN promiscuous mode
6732f345d8eSLuigi Rizzo  * @returns		0 on success, EIO on failure
6742f345d8eSLuigi Rizzo  */
6752f345d8eSLuigi Rizzo int
6762f345d8eSLuigi Rizzo oce_config_vlan(POCE_SOFTC sc,
6772f345d8eSLuigi Rizzo 		uint32_t if_id,
6782f345d8eSLuigi Rizzo 		struct normal_vlan *vtag_arr,
6792f345d8eSLuigi Rizzo 		uint8_t vtag_cnt, uint32_t untagged, uint32_t enable_promisc)
6802f345d8eSLuigi Rizzo {
6812f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
6822f345d8eSLuigi Rizzo 	struct mbx_common_config_vlan *fwcmd;
6835fbb6830SXin LI 	int rc = 0;
6845fbb6830SXin LI 
6855fbb6830SXin LI 	if (sc->vlans_added > sc->max_vlans)
6865fbb6830SXin LI 		goto vlan_promisc;
6872f345d8eSLuigi Rizzo 
6882f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
6892f345d8eSLuigi Rizzo 	fwcmd = (struct mbx_common_config_vlan *)&mbx.payload;
6902f345d8eSLuigi Rizzo 
6912f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
6922f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_COMMON,
6932f345d8eSLuigi Rizzo 				OPCODE_COMMON_CONFIG_IFACE_VLAN,
6942f345d8eSLuigi Rizzo 				MBX_TIMEOUT_SEC,
6952f345d8eSLuigi Rizzo 				sizeof(struct mbx_common_config_vlan),
6962f345d8eSLuigi Rizzo 				OCE_MBX_VER_V0);
6972f345d8eSLuigi Rizzo 
6982f345d8eSLuigi Rizzo 	fwcmd->params.req.if_id = (uint8_t) if_id;
6992f345d8eSLuigi Rizzo 	fwcmd->params.req.promisc = (uint8_t) enable_promisc;
7002f345d8eSLuigi Rizzo 	fwcmd->params.req.untagged = (uint8_t) untagged;
7012f345d8eSLuigi Rizzo 	fwcmd->params.req.num_vlans = vtag_cnt;
7022f345d8eSLuigi Rizzo 
7032f345d8eSLuigi Rizzo 	if (!enable_promisc) {
7042f345d8eSLuigi Rizzo 		bcopy(vtag_arr, fwcmd->params.req.tags.normal_vlans,
7052f345d8eSLuigi Rizzo 			vtag_cnt * sizeof(struct normal_vlan));
7062f345d8eSLuigi Rizzo 	}
7072f345d8eSLuigi Rizzo 	mbx.u0.s.embedded = 1;
7082f345d8eSLuigi Rizzo 	mbx.payload_length = sizeof(struct mbx_common_config_vlan);
7092f345d8eSLuigi Rizzo 	DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + mbx.payload_length));
7102f345d8eSLuigi Rizzo 
7112f345d8eSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
712cdaba892SXin LI 	if (!rc)
713cdaba892SXin LI                 rc = fwcmd->hdr.u0.rsp.status;
714cdaba892SXin LI 	if (rc)
7155fbb6830SXin LI 		device_printf(sc->dev,
7165fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
7175fbb6830SXin LI 			      __FUNCTION__, rc,
7185fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
7195fbb6830SXin LI 
7205fbb6830SXin LI 	goto done;
7215fbb6830SXin LI 
7225fbb6830SXin LI vlan_promisc:
7235fbb6830SXin LI 	/* Enable Vlan Promis */
7245fbb6830SXin LI 	oce_rxf_set_promiscuous(sc, (1 << 1));
7255fbb6830SXin LI 	device_printf(sc->dev,"Enabling Vlan Promisc Mode\n");
7265fbb6830SXin LI done:
7275fbb6830SXin LI 	return rc;
7282f345d8eSLuigi Rizzo 
7292f345d8eSLuigi Rizzo }
7302f345d8eSLuigi Rizzo 
7312f345d8eSLuigi Rizzo /**
7322f345d8eSLuigi Rizzo  * @brief Function to set flow control capability in the hardware
7332f345d8eSLuigi Rizzo  * @param sc 		software handle to the device
7342f345d8eSLuigi Rizzo  * @param flow_control	flow control flags to set
7352f345d8eSLuigi Rizzo  * @returns		0 on success, EIO on failure
7362f345d8eSLuigi Rizzo  */
7372f345d8eSLuigi Rizzo int
7382f345d8eSLuigi Rizzo oce_set_flow_control(POCE_SOFTC sc, uint32_t flow_control)
7392f345d8eSLuigi Rizzo {
7402f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
7412f345d8eSLuigi Rizzo 	struct mbx_common_get_set_flow_control *fwcmd =
7422f345d8eSLuigi Rizzo 		(struct mbx_common_get_set_flow_control *)&mbx.payload;
7432f345d8eSLuigi Rizzo 	int rc;
7442f345d8eSLuigi Rizzo 
7452f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
7462f345d8eSLuigi Rizzo 
7472f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
7482f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_COMMON,
7492f345d8eSLuigi Rizzo 				OPCODE_COMMON_SET_FLOW_CONTROL,
7502f345d8eSLuigi Rizzo 				MBX_TIMEOUT_SEC,
7512f345d8eSLuigi Rizzo 				sizeof(struct mbx_common_get_set_flow_control),
7522f345d8eSLuigi Rizzo 				OCE_MBX_VER_V0);
7532f345d8eSLuigi Rizzo 
7542f345d8eSLuigi Rizzo 	if (flow_control & OCE_FC_TX)
7552f345d8eSLuigi Rizzo 		fwcmd->tx_flow_control = 1;
7562f345d8eSLuigi Rizzo 
7572f345d8eSLuigi Rizzo 	if (flow_control & OCE_FC_RX)
7582f345d8eSLuigi Rizzo 		fwcmd->rx_flow_control = 1;
7592f345d8eSLuigi Rizzo 
7602f345d8eSLuigi Rizzo 	mbx.u0.s.embedded = 1;
7612f345d8eSLuigi Rizzo 	mbx.payload_length = sizeof(struct mbx_common_get_set_flow_control);
7622f345d8eSLuigi Rizzo 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
7632f345d8eSLuigi Rizzo 
7642f345d8eSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
765cdaba892SXin LI 	if (!rc)
766cdaba892SXin LI                 rc = fwcmd->hdr.u0.rsp.status;
767cdaba892SXin LI 	if (rc)
7685fbb6830SXin LI 		device_printf(sc->dev,
7695fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
7705fbb6830SXin LI 			      __FUNCTION__, rc,
7715fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
7722f345d8eSLuigi Rizzo 	return rc;
7732f345d8eSLuigi Rizzo }
7742f345d8eSLuigi Rizzo 
7752f345d8eSLuigi Rizzo /**
7762f345d8eSLuigi Rizzo  * @brief Initialize the RSS CPU indirection table
7772f345d8eSLuigi Rizzo  *
7782f345d8eSLuigi Rizzo  * The table is used to choose the queue to place the incomming packets.
7792f345d8eSLuigi Rizzo  * Incomming packets are hashed.  The lowest bits in the hash result
7802f345d8eSLuigi Rizzo  * are used as the index into the CPU indirection table.
7812f345d8eSLuigi Rizzo  * Each entry in the table contains the RSS CPU-ID returned by the NIC
7822f345d8eSLuigi Rizzo  * create.  Based on the CPU ID, the receive completion is routed to
7832f345d8eSLuigi Rizzo  * the corresponding RSS CQs.  (Non-RSS packets are always completed
7842f345d8eSLuigi Rizzo  * on the default (0) CQ).
7852f345d8eSLuigi Rizzo  *
7862f345d8eSLuigi Rizzo  * @param sc 		software handle to the device
7872f345d8eSLuigi Rizzo  * @param *fwcmd	pointer to the rss mbox command
7882f345d8eSLuigi Rizzo  * @returns		none
7892f345d8eSLuigi Rizzo  */
7902f345d8eSLuigi Rizzo static int
7912f345d8eSLuigi Rizzo oce_rss_itbl_init(POCE_SOFTC sc, struct mbx_config_nic_rss *fwcmd)
7922f345d8eSLuigi Rizzo {
7932f345d8eSLuigi Rizzo 	int i = 0, j = 0, rc = 0;
7942f345d8eSLuigi Rizzo 	uint8_t *tbl = fwcmd->params.req.cputable;
795291a1934SXin LI 	struct oce_rq *rq = NULL;
7962f345d8eSLuigi Rizzo 
7972f345d8eSLuigi Rizzo 
798291a1934SXin LI 	for (j = 0; j < INDIRECTION_TABLE_ENTRIES ; j += (sc->nrqs - 1)) {
799291a1934SXin LI 		for_all_rss_queues(sc, rq, i) {
800291a1934SXin LI 			if ((j + i) >= INDIRECTION_TABLE_ENTRIES)
801291a1934SXin LI 				break;
802291a1934SXin LI 			tbl[j + i] = rq->rss_cpuid;
8032f345d8eSLuigi Rizzo 		}
8042f345d8eSLuigi Rizzo 	}
8052f345d8eSLuigi Rizzo 	if (i == 0) {
8062f345d8eSLuigi Rizzo 		device_printf(sc->dev, "error: Invalid number of RSS RQ's\n");
8072f345d8eSLuigi Rizzo 		rc = ENXIO;
8082f345d8eSLuigi Rizzo 
8092f345d8eSLuigi Rizzo 	}
8102f345d8eSLuigi Rizzo 
8112f345d8eSLuigi Rizzo 	/* fill log2 value indicating the size of the CPU table */
8122f345d8eSLuigi Rizzo 	if (rc == 0)
813c2625e6eSJosh Paetzel 		fwcmd->params.req.cpu_tbl_sz_log2 = LE_16(OCE_LOG2(INDIRECTION_TABLE_ENTRIES));
8142f345d8eSLuigi Rizzo 
8152f345d8eSLuigi Rizzo 	return rc;
8162f345d8eSLuigi Rizzo }
8172f345d8eSLuigi Rizzo 
8182f345d8eSLuigi Rizzo /**
8192f345d8eSLuigi Rizzo  * @brief Function to set flow control capability in the hardware
8202f345d8eSLuigi Rizzo  * @param sc 		software handle to the device
8212f345d8eSLuigi Rizzo  * @param if_id 	interface id to read the address from
8222f345d8eSLuigi Rizzo  * @param enable_rss	0=disable, RSS_ENABLE_xxx flags otherwise
8232f345d8eSLuigi Rizzo  * @returns		0 on success, EIO on failure
8242f345d8eSLuigi Rizzo  */
8252f345d8eSLuigi Rizzo int
8262f345d8eSLuigi Rizzo oce_config_nic_rss(POCE_SOFTC sc, uint32_t if_id, uint16_t enable_rss)
8272f345d8eSLuigi Rizzo {
8282f345d8eSLuigi Rizzo 	int rc;
8292f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
8302f345d8eSLuigi Rizzo 	struct mbx_config_nic_rss *fwcmd =
8312f345d8eSLuigi Rizzo 				(struct mbx_config_nic_rss *)&mbx.payload;
832cdaba892SXin LI 	int version;
8332f345d8eSLuigi Rizzo 
8342f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
8352f345d8eSLuigi Rizzo 
836291a1934SXin LI 	if (IS_XE201(sc) || IS_SH(sc)) {
837cdaba892SXin LI 		version = OCE_MBX_VER_V1;
838cdaba892SXin LI 		fwcmd->params.req.enable_rss = RSS_ENABLE_UDP_IPV4 |
839cdaba892SXin LI 					       RSS_ENABLE_UDP_IPV6;
840cdaba892SXin LI 	} else
841cdaba892SXin LI 		version = OCE_MBX_VER_V0;
842cdaba892SXin LI 
8432f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
8442f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_NIC,
8452f345d8eSLuigi Rizzo 				NIC_CONFIG_RSS,
8462f345d8eSLuigi Rizzo 				MBX_TIMEOUT_SEC,
8472f345d8eSLuigi Rizzo 				sizeof(struct mbx_config_nic_rss),
848cdaba892SXin LI 				version);
8492f345d8eSLuigi Rizzo 	if (enable_rss)
850cdaba892SXin LI 		fwcmd->params.req.enable_rss |= (RSS_ENABLE_IPV4 |
8512f345d8eSLuigi Rizzo 					         RSS_ENABLE_TCP_IPV4 |
8522f345d8eSLuigi Rizzo 						 RSS_ENABLE_IPV6 |
8532f345d8eSLuigi Rizzo 						 RSS_ENABLE_TCP_IPV6);
854c2625e6eSJosh Paetzel 
855c2625e6eSJosh Paetzel 	if(!sc->enable_hwlro)
8562f345d8eSLuigi Rizzo 		fwcmd->params.req.flush = OCE_FLUSH;
857c2625e6eSJosh Paetzel 	else
858c2625e6eSJosh Paetzel 		fwcmd->params.req.flush = 0;
859c2625e6eSJosh Paetzel 
8602f345d8eSLuigi Rizzo 	fwcmd->params.req.if_id = LE_32(if_id);
8612f345d8eSLuigi Rizzo 
862c2625e6eSJosh Paetzel 	srandom(arc4random());	/* random entropy seed */
8632f345d8eSLuigi Rizzo 	read_random(fwcmd->params.req.hash, sizeof(fwcmd->params.req.hash));
8642f345d8eSLuigi Rizzo 
8652f345d8eSLuigi Rizzo 	rc = oce_rss_itbl_init(sc, fwcmd);
8662f345d8eSLuigi Rizzo 	if (rc == 0) {
8672f345d8eSLuigi Rizzo 		mbx.u0.s.embedded = 1;
8682f345d8eSLuigi Rizzo 		mbx.payload_length = sizeof(struct mbx_config_nic_rss);
8692f345d8eSLuigi Rizzo 		DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
8702f345d8eSLuigi Rizzo 
8712f345d8eSLuigi Rizzo 		rc = oce_mbox_post(sc, &mbx, NULL);
872cdaba892SXin LI 		if (!rc)
873cdaba892SXin LI                 	rc = fwcmd->hdr.u0.rsp.status;
874cdaba892SXin LI 		if (rc)
8755fbb6830SXin LI 		device_printf(sc->dev,
8765fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
8775fbb6830SXin LI 			      __FUNCTION__, rc,
8785fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
8792f345d8eSLuigi Rizzo 	}
8802f345d8eSLuigi Rizzo 	return rc;
8812f345d8eSLuigi Rizzo }
8822f345d8eSLuigi Rizzo 
8832f345d8eSLuigi Rizzo /**
8842f345d8eSLuigi Rizzo  * @brief 		RXF function to enable/disable device promiscuous mode
8852f345d8eSLuigi Rizzo  * @param sc		software handle to the device
8862f345d8eSLuigi Rizzo  * @param enable	enable/disable flag
8872f345d8eSLuigi Rizzo  * @returns		0 on success, EIO on failure
8882f345d8eSLuigi Rizzo  * @note
8892f345d8eSLuigi Rizzo  *	The NIC_CONFIG_PROMISCUOUS command deprecated for Lancer.
8902f345d8eSLuigi Rizzo  *	This function uses the COMMON_SET_IFACE_RX_FILTER command instead.
8912f345d8eSLuigi Rizzo  */
8922f345d8eSLuigi Rizzo int
8935fbb6830SXin LI oce_rxf_set_promiscuous(POCE_SOFTC sc, uint8_t enable)
8942f345d8eSLuigi Rizzo {
8952f345d8eSLuigi Rizzo 	struct mbx_set_common_iface_rx_filter *fwcmd;
8962f345d8eSLuigi Rizzo 	int sz = sizeof(struct mbx_set_common_iface_rx_filter);
8972f345d8eSLuigi Rizzo 	iface_rx_filter_ctx_t *req;
8982f345d8eSLuigi Rizzo 	OCE_DMA_MEM sgl;
8992f345d8eSLuigi Rizzo 	int rc;
9002f345d8eSLuigi Rizzo 
9012f345d8eSLuigi Rizzo 	/* allocate mbx payload's dma scatter/gather memory */
9022f345d8eSLuigi Rizzo 	rc = oce_dma_alloc(sc, sz, &sgl, 0);
9032f345d8eSLuigi Rizzo 	if (rc)
9042f345d8eSLuigi Rizzo 		return rc;
9052f345d8eSLuigi Rizzo 
9062f345d8eSLuigi Rizzo 	fwcmd = OCE_DMAPTR(&sgl, struct mbx_set_common_iface_rx_filter);
9072f345d8eSLuigi Rizzo 
9082f345d8eSLuigi Rizzo 	req =  &fwcmd->params.req;
9092f345d8eSLuigi Rizzo 	req->iface_flags_mask = MBX_RX_IFACE_FLAGS_PROMISCUOUS |
9102f345d8eSLuigi Rizzo 				MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS;
9115fbb6830SXin LI 	/* Bit 0 Mac promisc, Bit 1 Vlan promisc */
9125fbb6830SXin LI 	if (enable & 0x01)
9135fbb6830SXin LI 		req->iface_flags = MBX_RX_IFACE_FLAGS_PROMISCUOUS;
9145fbb6830SXin LI 
9155fbb6830SXin LI 	if (enable & 0x02)
916c2625e6eSJosh Paetzel 		req->iface_flags |= MBX_RX_IFACE_FLAGS_VLAN_PROMISCUOUS;
9175fbb6830SXin LI 
9182f345d8eSLuigi Rizzo 	req->if_id = sc->if_id;
9192f345d8eSLuigi Rizzo 
9202f345d8eSLuigi Rizzo 	rc = oce_set_common_iface_rx_filter(sc, &sgl);
9212f345d8eSLuigi Rizzo 	oce_dma_free(sc, &sgl);
9222f345d8eSLuigi Rizzo 
9232f345d8eSLuigi Rizzo 	return rc;
9242f345d8eSLuigi Rizzo }
9252f345d8eSLuigi Rizzo 
9262f345d8eSLuigi Rizzo 
9272f345d8eSLuigi Rizzo /**
9282f345d8eSLuigi Rizzo  * @brief 			Function modify and select rx filter options
9292f345d8eSLuigi Rizzo  * @param sc			software handle to the device
9302f345d8eSLuigi Rizzo  * @param sgl			scatter/gather request/response
9312f345d8eSLuigi Rizzo  * @returns			0 on success, error code on failure
9322f345d8eSLuigi Rizzo  */
9332f345d8eSLuigi Rizzo int
9342f345d8eSLuigi Rizzo oce_set_common_iface_rx_filter(POCE_SOFTC sc, POCE_DMA_MEM sgl)
9352f345d8eSLuigi Rizzo {
9362f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
9372f345d8eSLuigi Rizzo 	int mbx_sz = sizeof(struct mbx_set_common_iface_rx_filter);
9382f345d8eSLuigi Rizzo 	struct mbx_set_common_iface_rx_filter *fwcmd;
9392f345d8eSLuigi Rizzo 	int rc;
9402f345d8eSLuigi Rizzo 
9412f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
9422f345d8eSLuigi Rizzo 	fwcmd = OCE_DMAPTR(sgl, struct mbx_set_common_iface_rx_filter);
9432f345d8eSLuigi Rizzo 
9442f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
9452f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_COMMON,
9462f345d8eSLuigi Rizzo 				OPCODE_COMMON_SET_IFACE_RX_FILTER,
9472f345d8eSLuigi Rizzo 				MBX_TIMEOUT_SEC,
9482f345d8eSLuigi Rizzo 				mbx_sz,
9492f345d8eSLuigi Rizzo 				OCE_MBX_VER_V0);
9502f345d8eSLuigi Rizzo 
9512f345d8eSLuigi Rizzo 	oce_dma_sync(sgl, BUS_DMASYNC_PREWRITE);
9522f345d8eSLuigi Rizzo 	mbx.u0.s.embedded = 0;
9532f345d8eSLuigi Rizzo 	mbx.u0.s.sge_count = 1;
9542f345d8eSLuigi Rizzo 	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(sgl->paddr);
9552f345d8eSLuigi Rizzo 	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(sgl->paddr);
9562f345d8eSLuigi Rizzo 	mbx.payload.u0.u1.sgl[0].length = mbx_sz;
9572f345d8eSLuigi Rizzo 	mbx.payload_length = mbx_sz;
9582f345d8eSLuigi Rizzo 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
9592f345d8eSLuigi Rizzo 
9602f345d8eSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
961cdaba892SXin LI 	if (!rc)
962cdaba892SXin LI                 rc = fwcmd->hdr.u0.rsp.status;
963cdaba892SXin LI 	if (rc)
9645fbb6830SXin LI 		device_printf(sc->dev,
9655fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
9665fbb6830SXin LI 			      __FUNCTION__, rc,
9675fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
9685fbb6830SXin LI 	return rc;
9692f345d8eSLuigi Rizzo }
9702f345d8eSLuigi Rizzo 
9712f345d8eSLuigi Rizzo /**
9722f345d8eSLuigi Rizzo  * @brief Function to query the link status from the hardware
9732f345d8eSLuigi Rizzo  * @param sc 		software handle to the device
9742f345d8eSLuigi Rizzo  * @param[out] link	pointer to the structure returning link attributes
9752f345d8eSLuigi Rizzo  * @returns		0 on success, EIO on failure
9762f345d8eSLuigi Rizzo  */
9772f345d8eSLuigi Rizzo int
9782f345d8eSLuigi Rizzo oce_get_link_status(POCE_SOFTC sc, struct link_status *link)
9792f345d8eSLuigi Rizzo {
9802f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
9812f345d8eSLuigi Rizzo 	struct mbx_query_common_link_config *fwcmd;
982cdaba892SXin LI 	int rc = 0, version;
9832f345d8eSLuigi Rizzo 
9842f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
9852f345d8eSLuigi Rizzo 
986b41206d8SXin LI 	IS_BE2(sc) ? (version = OCE_MBX_VER_V0) : (version = OCE_MBX_VER_V1);
987cdaba892SXin LI 
9882f345d8eSLuigi Rizzo 	fwcmd = (struct mbx_query_common_link_config *)&mbx.payload;
9892f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
9902f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_COMMON,
9912f345d8eSLuigi Rizzo 				OPCODE_COMMON_QUERY_LINK_CONFIG,
9922f345d8eSLuigi Rizzo 				MBX_TIMEOUT_SEC,
9932f345d8eSLuigi Rizzo 				sizeof(struct mbx_query_common_link_config),
994cdaba892SXin LI 				version);
9952f345d8eSLuigi Rizzo 
9962f345d8eSLuigi Rizzo 	mbx.u0.s.embedded = 1;
9972f345d8eSLuigi Rizzo 	mbx.payload_length = sizeof(struct mbx_query_common_link_config);
9982f345d8eSLuigi Rizzo 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
9992f345d8eSLuigi Rizzo 
10002f345d8eSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
10012f345d8eSLuigi Rizzo 
1002cdaba892SXin LI 	if (!rc)
1003cdaba892SXin LI                 rc = fwcmd->hdr.u0.rsp.status;
10042f345d8eSLuigi Rizzo 	if (rc) {
10055fbb6830SXin LI 		device_printf(sc->dev,
10065fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
10075fbb6830SXin LI 			      __FUNCTION__, rc,
10085fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
1009cdaba892SXin LI 		goto error;
1010cdaba892SXin LI 	}
10112f345d8eSLuigi Rizzo 	/* interpret response */
1012a4f734b4SXin LI 	link->qos_link_speed = HOST_16(fwcmd->params.rsp.qos_link_speed);
1013a4f734b4SXin LI 	link->phys_port_speed = fwcmd->params.rsp.physical_port_speed;
1014a4f734b4SXin LI 	link->logical_link_status = fwcmd->params.rsp.logical_link_status;
1015cdaba892SXin LI error:
10162f345d8eSLuigi Rizzo 	return rc;
10172f345d8eSLuigi Rizzo }
10182f345d8eSLuigi Rizzo 
10192f345d8eSLuigi Rizzo 
10202f345d8eSLuigi Rizzo /**
10212f345d8eSLuigi Rizzo  * @brief Function to get NIC statistics
10222f345d8eSLuigi Rizzo  * @param sc            software handle to the device
10232f345d8eSLuigi Rizzo  * @param *stats        pointer to where to store statistics
10242f345d8eSLuigi Rizzo  * @param reset_stats   resets statistics of set
10252f345d8eSLuigi Rizzo  * @returns             0 on success, EIO on failure
10262f345d8eSLuigi Rizzo  * @note                command depricated in Lancer
10272f345d8eSLuigi Rizzo  */
1028c2625e6eSJosh Paetzel #define OCE_MBOX_GET_NIC_STATS(sc, pstats_dma_mem, version) 				\
1029c2625e6eSJosh Paetzel int 											\
1030c2625e6eSJosh Paetzel oce_mbox_get_nic_stats_v##version(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem) 		\
1031c2625e6eSJosh Paetzel { 											\
1032c2625e6eSJosh Paetzel         struct oce_mbx mbx; 								\
1033c2625e6eSJosh Paetzel         struct mbx_get_nic_stats_v##version *fwcmd; 					\
1034c2625e6eSJosh Paetzel         int rc = 0; 									\
1035c2625e6eSJosh Paetzel 											\
1036c2625e6eSJosh Paetzel         bzero(&mbx, sizeof(struct oce_mbx)); 						\
1037c2625e6eSJosh Paetzel         fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_nic_stats_v##version); 	\
1038c2625e6eSJosh Paetzel         bzero(fwcmd, sizeof(*fwcmd)); 							\
1039c2625e6eSJosh Paetzel 											\
1040c2625e6eSJosh Paetzel         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0, 					\
1041c2625e6eSJosh Paetzel                                 MBX_SUBSYSTEM_NIC, 					\
1042c2625e6eSJosh Paetzel                                 NIC_GET_STATS, 						\
1043c2625e6eSJosh Paetzel                                 MBX_TIMEOUT_SEC, 					\
1044c2625e6eSJosh Paetzel                                 sizeof(*fwcmd), 					\
1045c2625e6eSJosh Paetzel                                 OCE_MBX_VER_V##version); 				\
1046c2625e6eSJosh Paetzel 											\
1047c2625e6eSJosh Paetzel         mbx.u0.s.embedded = 0;  /* stats too large for embedded mbx rsp */ 		\
1048c2625e6eSJosh Paetzel         mbx.u0.s.sge_count = 1; /* using scatter gather instead */ 			\
1049c2625e6eSJosh Paetzel 											\
1050c2625e6eSJosh Paetzel         oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE); 				\
1051c2625e6eSJosh Paetzel         mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);		\
1052c2625e6eSJosh Paetzel         mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr); 		\
1053c2625e6eSJosh Paetzel         mbx.payload.u0.u1.sgl[0].length = sizeof(*fwcmd); 				\
1054c2625e6eSJosh Paetzel         mbx.payload_length = sizeof(*fwcmd); 						\
1055c2625e6eSJosh Paetzel         DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ); 			\
1056c2625e6eSJosh Paetzel 											\
1057c2625e6eSJosh Paetzel         rc = oce_mbox_post(sc, &mbx, NULL); 						\
1058c2625e6eSJosh Paetzel         oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE); 				\
1059c2625e6eSJosh Paetzel         if (!rc) 									\
1060c2625e6eSJosh Paetzel                 rc = fwcmd->hdr.u0.rsp.status; 						\
1061c2625e6eSJosh Paetzel         if (rc) 									\
1062c2625e6eSJosh Paetzel                 device_printf(sc->dev, 							\
1063c2625e6eSJosh Paetzel                               "%s failed - cmd status: %d addi status: %d\n", 		\
1064c2625e6eSJosh Paetzel                               __FUNCTION__, rc, 					\
1065c2625e6eSJosh Paetzel                               fwcmd->hdr.u0.rsp.additional_status); 			\
1066c2625e6eSJosh Paetzel         return rc; 									\
106714410265SConrad Meyer }
1068764c812dSJosh Paetzel 
1069c2625e6eSJosh Paetzel OCE_MBOX_GET_NIC_STATS(sc, pstats_dma_mem, 0);
1070c2625e6eSJosh Paetzel OCE_MBOX_GET_NIC_STATS(sc, pstats_dma_mem, 1);
1071c2625e6eSJosh Paetzel OCE_MBOX_GET_NIC_STATS(sc, pstats_dma_mem, 2);
1072c2625e6eSJosh Paetzel 
10732f345d8eSLuigi Rizzo 
10742f345d8eSLuigi Rizzo /**
10752f345d8eSLuigi Rizzo  * @brief Function to get pport (physical port) statistics
10762f345d8eSLuigi Rizzo  * @param sc 		software handle to the device
10772f345d8eSLuigi Rizzo  * @param *stats	pointer to where to store statistics
10782f345d8eSLuigi Rizzo  * @param reset_stats	resets statistics of set
10792f345d8eSLuigi Rizzo  * @returns		0 on success, EIO on failure
10802f345d8eSLuigi Rizzo  */
10812f345d8eSLuigi Rizzo int
10822f345d8eSLuigi Rizzo oce_mbox_get_pport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem,
10832f345d8eSLuigi Rizzo 				uint32_t reset_stats)
10842f345d8eSLuigi Rizzo {
10852f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
10862f345d8eSLuigi Rizzo 	struct mbx_get_pport_stats *fwcmd;
10872f345d8eSLuigi Rizzo 	int rc = 0;
10882f345d8eSLuigi Rizzo 
10892f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
10902f345d8eSLuigi Rizzo 	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_pport_stats);
10912f345d8eSLuigi Rizzo 	bzero(fwcmd, sizeof(struct mbx_get_pport_stats));
10922f345d8eSLuigi Rizzo 
10932f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
10942f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_NIC,
10952f345d8eSLuigi Rizzo 				NIC_GET_PPORT_STATS,
10962f345d8eSLuigi Rizzo 				MBX_TIMEOUT_SEC,
10972f345d8eSLuigi Rizzo 				sizeof(struct mbx_get_pport_stats),
10982f345d8eSLuigi Rizzo 				OCE_MBX_VER_V0);
10992f345d8eSLuigi Rizzo 
11002f345d8eSLuigi Rizzo 	fwcmd->params.req.reset_stats = reset_stats;
1101cdaba892SXin LI 	fwcmd->params.req.port_number = sc->port_id;
11022f345d8eSLuigi Rizzo 
11032f345d8eSLuigi Rizzo 	mbx.u0.s.embedded = 0;	/* stats too large for embedded mbx rsp */
11042f345d8eSLuigi Rizzo 	mbx.u0.s.sge_count = 1; /* using scatter gather instead */
11052f345d8eSLuigi Rizzo 
11062f345d8eSLuigi Rizzo 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
11072f345d8eSLuigi Rizzo 	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
11082f345d8eSLuigi Rizzo 	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
11092f345d8eSLuigi Rizzo 	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_pport_stats);
11102f345d8eSLuigi Rizzo 
11112f345d8eSLuigi Rizzo 	mbx.payload_length = sizeof(struct mbx_get_pport_stats);
11122f345d8eSLuigi Rizzo 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
11132f345d8eSLuigi Rizzo 
11142f345d8eSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
11152f345d8eSLuigi Rizzo 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
11162f345d8eSLuigi Rizzo 
1117cdaba892SXin LI 	if (!rc)
1118cdaba892SXin LI                 rc = fwcmd->hdr.u0.rsp.status;
1119cdaba892SXin LI 	if (rc)
11205fbb6830SXin LI 		device_printf(sc->dev,
11215fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
11225fbb6830SXin LI 			      __FUNCTION__, rc,
11235fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
11242f345d8eSLuigi Rizzo 	return rc;
11252f345d8eSLuigi Rizzo }
11262f345d8eSLuigi Rizzo 
11272f345d8eSLuigi Rizzo 
11282f345d8eSLuigi Rizzo /**
11292f345d8eSLuigi Rizzo  * @brief Function to get vport (virtual port) statistics
11302f345d8eSLuigi Rizzo  * @param sc 		software handle to the device
11312f345d8eSLuigi Rizzo  * @param *stats	pointer to where to store statistics
11322f345d8eSLuigi Rizzo  * @param reset_stats	resets statistics of set
11332f345d8eSLuigi Rizzo  * @returns		0 on success, EIO on failure
11342f345d8eSLuigi Rizzo  */
11352f345d8eSLuigi Rizzo int
11362f345d8eSLuigi Rizzo oce_mbox_get_vport_stats(POCE_SOFTC sc, POCE_DMA_MEM pstats_dma_mem,
11372f345d8eSLuigi Rizzo 				uint32_t req_size, uint32_t reset_stats)
11382f345d8eSLuigi Rizzo {
11392f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
11402f345d8eSLuigi Rizzo 	struct mbx_get_vport_stats *fwcmd;
11412f345d8eSLuigi Rizzo 	int rc = 0;
11422f345d8eSLuigi Rizzo 
11432f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
11442f345d8eSLuigi Rizzo 
11452f345d8eSLuigi Rizzo 	fwcmd = OCE_DMAPTR(pstats_dma_mem, struct mbx_get_vport_stats);
11462f345d8eSLuigi Rizzo 	bzero(fwcmd, sizeof(struct mbx_get_vport_stats));
11472f345d8eSLuigi Rizzo 
11482f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
11492f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_NIC,
11502f345d8eSLuigi Rizzo 				NIC_GET_VPORT_STATS,
11512f345d8eSLuigi Rizzo 				MBX_TIMEOUT_SEC,
11522f345d8eSLuigi Rizzo 				sizeof(struct mbx_get_vport_stats),
11532f345d8eSLuigi Rizzo 				OCE_MBX_VER_V0);
11542f345d8eSLuigi Rizzo 
11552f345d8eSLuigi Rizzo 	fwcmd->params.req.reset_stats = reset_stats;
11562f345d8eSLuigi Rizzo 	fwcmd->params.req.vport_number = sc->if_id;
11572f345d8eSLuigi Rizzo 
11582f345d8eSLuigi Rizzo 	mbx.u0.s.embedded = 0;	/* stats too large for embedded mbx rsp */
11592f345d8eSLuigi Rizzo 	mbx.u0.s.sge_count = 1; /* using scatter gather instead */
11602f345d8eSLuigi Rizzo 
11612f345d8eSLuigi Rizzo 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_PREWRITE);
11622f345d8eSLuigi Rizzo 	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(pstats_dma_mem->paddr);
11632f345d8eSLuigi Rizzo 	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(pstats_dma_mem->paddr);
11642f345d8eSLuigi Rizzo 	mbx.payload.u0.u1.sgl[0].length = sizeof(struct mbx_get_vport_stats);
11652f345d8eSLuigi Rizzo 
11662f345d8eSLuigi Rizzo 	mbx.payload_length = sizeof(struct mbx_get_vport_stats);
11672f345d8eSLuigi Rizzo 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
11682f345d8eSLuigi Rizzo 
11692f345d8eSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
11702f345d8eSLuigi Rizzo 	oce_dma_sync(pstats_dma_mem, BUS_DMASYNC_POSTWRITE);
11712f345d8eSLuigi Rizzo 
1172cdaba892SXin LI 	if (!rc)
1173cdaba892SXin LI                 rc = fwcmd->hdr.u0.rsp.status;
1174cdaba892SXin LI 	if (rc)
11755fbb6830SXin LI 		device_printf(sc->dev,
11765fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
11775fbb6830SXin LI 			      __FUNCTION__, rc,
11785fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
11792f345d8eSLuigi Rizzo 	return rc;
11802f345d8eSLuigi Rizzo }
11812f345d8eSLuigi Rizzo 
11822f345d8eSLuigi Rizzo 
11832f345d8eSLuigi Rizzo /**
11842f345d8eSLuigi Rizzo  * @brief               Function to update the muticast filter with
11852f345d8eSLuigi Rizzo  *                      values in dma_mem
11862f345d8eSLuigi Rizzo  * @param sc            software handle to the device
11872f345d8eSLuigi Rizzo  * @param dma_mem       pointer to dma memory region
11882f345d8eSLuigi Rizzo  * @returns             0 on success, EIO on failure
11892f345d8eSLuigi Rizzo  */
11902f345d8eSLuigi Rizzo int
11912f345d8eSLuigi Rizzo oce_update_multicast(POCE_SOFTC sc, POCE_DMA_MEM pdma_mem)
11922f345d8eSLuigi Rizzo {
11932f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
11942f345d8eSLuigi Rizzo 	struct oce_mq_sge *sgl;
11952f345d8eSLuigi Rizzo 	struct mbx_set_common_iface_multicast *req = NULL;
11962f345d8eSLuigi Rizzo 	int rc = 0;
11972f345d8eSLuigi Rizzo 
11982f345d8eSLuigi Rizzo 	req = OCE_DMAPTR(pdma_mem, struct mbx_set_common_iface_multicast);
11992f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&req->hdr, 0, 0,
12002f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_COMMON,
12012f345d8eSLuigi Rizzo 				OPCODE_COMMON_SET_IFACE_MULTICAST,
12022f345d8eSLuigi Rizzo 				MBX_TIMEOUT_SEC,
12032f345d8eSLuigi Rizzo 				sizeof(struct mbx_set_common_iface_multicast),
12042f345d8eSLuigi Rizzo 				OCE_MBX_VER_V0);
12052f345d8eSLuigi Rizzo 
12062f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
12072f345d8eSLuigi Rizzo 
12082f345d8eSLuigi Rizzo 	mbx.u0.s.embedded = 0; /*Non embeded*/
12092f345d8eSLuigi Rizzo 	mbx.payload_length = sizeof(struct mbx_set_common_iface_multicast);
12102f345d8eSLuigi Rizzo 	mbx.u0.s.sge_count = 1;
12112f345d8eSLuigi Rizzo 	sgl = &mbx.payload.u0.u1.sgl[0];
12122f345d8eSLuigi Rizzo 	sgl->pa_hi = htole32(upper_32_bits(pdma_mem->paddr));
12132f345d8eSLuigi Rizzo 	sgl->pa_lo = htole32((pdma_mem->paddr) & 0xFFFFFFFF);
12142f345d8eSLuigi Rizzo 	sgl->length = htole32(mbx.payload_length);
12152f345d8eSLuigi Rizzo 
12162f345d8eSLuigi Rizzo 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
12172f345d8eSLuigi Rizzo 
12182f345d8eSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
1219cdaba892SXin LI 	if (!rc)
1220cdaba892SXin LI                 rc = req->hdr.u0.rsp.status;
1221cdaba892SXin LI 	if (rc)
12225fbb6830SXin LI 		device_printf(sc->dev,
12235fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
12245fbb6830SXin LI 			      __FUNCTION__, rc,
12255fbb6830SXin LI 			      req->hdr.u0.rsp.additional_status);
12262f345d8eSLuigi Rizzo 	return rc;
12272f345d8eSLuigi Rizzo }
12282f345d8eSLuigi Rizzo 
12292f345d8eSLuigi Rizzo 
12302f345d8eSLuigi Rizzo /**
12312f345d8eSLuigi Rizzo  * @brief               Function to send passthrough Ioctls
12322f345d8eSLuigi Rizzo  * @param sc            software handle to the device
12332f345d8eSLuigi Rizzo  * @param dma_mem       pointer to dma memory region
12342f345d8eSLuigi Rizzo  * @param req_size      size of dma_mem
12352f345d8eSLuigi Rizzo  * @returns             0 on success, EIO on failure
12362f345d8eSLuigi Rizzo  */
12372f345d8eSLuigi Rizzo int
12382f345d8eSLuigi Rizzo oce_pass_through_mbox(POCE_SOFTC sc, POCE_DMA_MEM dma_mem, uint32_t req_size)
12392f345d8eSLuigi Rizzo {
12402f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
12412f345d8eSLuigi Rizzo 	struct oce_mq_sge *sgl;
12422f345d8eSLuigi Rizzo 	int rc = 0;
12432f345d8eSLuigi Rizzo 
12442f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
12452f345d8eSLuigi Rizzo 
12462f345d8eSLuigi Rizzo 	mbx.u0.s.embedded  = 0; /*Non embeded*/
12472f345d8eSLuigi Rizzo 	mbx.payload_length = req_size;
12482f345d8eSLuigi Rizzo 	mbx.u0.s.sge_count = 1;
12492f345d8eSLuigi Rizzo 	sgl = &mbx.payload.u0.u1.sgl[0];
12502f345d8eSLuigi Rizzo 	sgl->pa_hi = htole32(upper_32_bits(dma_mem->paddr));
12512f345d8eSLuigi Rizzo 	sgl->pa_lo = htole32((dma_mem->paddr) & 0xFFFFFFFF);
12522f345d8eSLuigi Rizzo 	sgl->length = htole32(req_size);
12532f345d8eSLuigi Rizzo 
12542f345d8eSLuigi Rizzo 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
12552f345d8eSLuigi Rizzo 
12562f345d8eSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
12572f345d8eSLuigi Rizzo 	return rc;
12582f345d8eSLuigi Rizzo }
12592f345d8eSLuigi Rizzo 
12602f345d8eSLuigi Rizzo 
12612f345d8eSLuigi Rizzo int
12622f345d8eSLuigi Rizzo oce_mbox_macaddr_add(POCE_SOFTC sc, uint8_t *mac_addr,
12632f345d8eSLuigi Rizzo 		 uint32_t if_id, uint32_t *pmac_id)
12642f345d8eSLuigi Rizzo {
12652f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
12662f345d8eSLuigi Rizzo 	struct mbx_add_common_iface_mac *fwcmd;
12672f345d8eSLuigi Rizzo 	int rc = 0;
12682f345d8eSLuigi Rizzo 
12692f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
12702f345d8eSLuigi Rizzo 
12712f345d8eSLuigi Rizzo 	fwcmd = (struct mbx_add_common_iface_mac *)&mbx.payload;
12722f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
12732f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_COMMON,
12742f345d8eSLuigi Rizzo 				OPCODE_COMMON_ADD_IFACE_MAC,
12752f345d8eSLuigi Rizzo 				MBX_TIMEOUT_SEC,
12762f345d8eSLuigi Rizzo 				sizeof(struct mbx_add_common_iface_mac),
12772f345d8eSLuigi Rizzo 				OCE_MBX_VER_V0);
12782f345d8eSLuigi Rizzo 
12792f345d8eSLuigi Rizzo 	fwcmd->params.req.if_id = (uint16_t) if_id;
12802f345d8eSLuigi Rizzo 	bcopy(mac_addr, fwcmd->params.req.mac_address, 6);
12812f345d8eSLuigi Rizzo 
12822f345d8eSLuigi Rizzo 	mbx.u0.s.embedded = 1;
12832f345d8eSLuigi Rizzo 	mbx.payload_length = sizeof(struct  mbx_add_common_iface_mac);
12842f345d8eSLuigi Rizzo 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
12852f345d8eSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
1286cdaba892SXin LI 	if (!rc)
1287cdaba892SXin LI                 rc = fwcmd->hdr.u0.rsp.status;
1288cdaba892SXin LI 	if (rc) {
12895fbb6830SXin LI 		device_printf(sc->dev,
12905fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
12915fbb6830SXin LI 			      __FUNCTION__, rc,
12925fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
1293cdaba892SXin LI 		goto error;
1294cdaba892SXin LI 	}
12952f345d8eSLuigi Rizzo 	*pmac_id = fwcmd->params.rsp.pmac_id;
1296cdaba892SXin LI error:
12972f345d8eSLuigi Rizzo 	return rc;
12982f345d8eSLuigi Rizzo }
12992f345d8eSLuigi Rizzo 
13002f345d8eSLuigi Rizzo 
13012f345d8eSLuigi Rizzo int
13022f345d8eSLuigi Rizzo oce_mbox_macaddr_del(POCE_SOFTC sc, uint32_t if_id, uint32_t pmac_id)
13032f345d8eSLuigi Rizzo {
13042f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
13052f345d8eSLuigi Rizzo 	struct mbx_del_common_iface_mac *fwcmd;
13062f345d8eSLuigi Rizzo 	int rc = 0;
13072f345d8eSLuigi Rizzo 
13082f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
13092f345d8eSLuigi Rizzo 
13102f345d8eSLuigi Rizzo 	fwcmd = (struct mbx_del_common_iface_mac *)&mbx.payload;
13112f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
13122f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_COMMON,
13132f345d8eSLuigi Rizzo 				OPCODE_COMMON_DEL_IFACE_MAC,
13142f345d8eSLuigi Rizzo 				MBX_TIMEOUT_SEC,
13152f345d8eSLuigi Rizzo 				sizeof(struct mbx_del_common_iface_mac),
13162f345d8eSLuigi Rizzo 				OCE_MBX_VER_V0);
13172f345d8eSLuigi Rizzo 
13182f345d8eSLuigi Rizzo 	fwcmd->params.req.if_id = (uint16_t)if_id;
13192f345d8eSLuigi Rizzo 	fwcmd->params.req.pmac_id = pmac_id;
13202f345d8eSLuigi Rizzo 
13212f345d8eSLuigi Rizzo 	mbx.u0.s.embedded = 1;
13222f345d8eSLuigi Rizzo 	mbx.payload_length = sizeof(struct  mbx_del_common_iface_mac);
13232f345d8eSLuigi Rizzo 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
13242f345d8eSLuigi Rizzo 
13252f345d8eSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
1326cdaba892SXin LI 	if (!rc)
1327cdaba892SXin LI                 rc = fwcmd->hdr.u0.rsp.status;
1328cdaba892SXin LI 	if (rc)
13295fbb6830SXin LI 		device_printf(sc->dev,
13305fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
13315fbb6830SXin LI 			      __FUNCTION__, rc,
13325fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
13332f345d8eSLuigi Rizzo 	return rc;
13342f345d8eSLuigi Rizzo }
13352f345d8eSLuigi Rizzo 
13362f345d8eSLuigi Rizzo 
13372f345d8eSLuigi Rizzo 
13382f345d8eSLuigi Rizzo int
13392f345d8eSLuigi Rizzo oce_mbox_check_native_mode(POCE_SOFTC sc)
13402f345d8eSLuigi Rizzo {
13412f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
13422f345d8eSLuigi Rizzo 	struct mbx_common_set_function_cap *fwcmd;
13432f345d8eSLuigi Rizzo 	int rc = 0;
13442f345d8eSLuigi Rizzo 
13452f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
13462f345d8eSLuigi Rizzo 
13472f345d8eSLuigi Rizzo 	fwcmd = (struct mbx_common_set_function_cap *)&mbx.payload;
13482f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
13492f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_COMMON,
13502f345d8eSLuigi Rizzo 				OPCODE_COMMON_SET_FUNCTIONAL_CAPS,
13512f345d8eSLuigi Rizzo 				MBX_TIMEOUT_SEC,
13522f345d8eSLuigi Rizzo 				sizeof(struct mbx_common_set_function_cap),
13532f345d8eSLuigi Rizzo 				OCE_MBX_VER_V0);
13542f345d8eSLuigi Rizzo 
13552f345d8eSLuigi Rizzo 	fwcmd->params.req.valid_capability_flags = CAP_SW_TIMESTAMPS |
13562f345d8eSLuigi Rizzo 							CAP_BE3_NATIVE_ERX_API;
13572f345d8eSLuigi Rizzo 
13582f345d8eSLuigi Rizzo 	fwcmd->params.req.capability_flags = CAP_BE3_NATIVE_ERX_API;
13592f345d8eSLuigi Rizzo 
13602f345d8eSLuigi Rizzo 	mbx.u0.s.embedded = 1;
13612f345d8eSLuigi Rizzo 	mbx.payload_length = sizeof(struct mbx_common_set_function_cap);
13622f345d8eSLuigi Rizzo 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
13632f345d8eSLuigi Rizzo 
13642f345d8eSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
1365cdaba892SXin LI 	if (!rc)
1366cdaba892SXin LI                 rc = fwcmd->hdr.u0.rsp.status;
1367cdaba892SXin LI 	if (rc) {
13685fbb6830SXin LI 		device_printf(sc->dev,
13695fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
13705fbb6830SXin LI 			      __FUNCTION__, rc,
13715fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
1372cdaba892SXin LI 		goto error;
1373cdaba892SXin LI 	}
13745fbb6830SXin LI 	sc->be3_native = HOST_32(fwcmd->params.rsp.capability_flags)
13752f345d8eSLuigi Rizzo 			& CAP_BE3_NATIVE_ERX_API;
13762f345d8eSLuigi Rizzo 
1377cdaba892SXin LI error:
13782f345d8eSLuigi Rizzo 	return 0;
13792f345d8eSLuigi Rizzo }
13802f345d8eSLuigi Rizzo 
13812f345d8eSLuigi Rizzo 
13822f345d8eSLuigi Rizzo 
13832f345d8eSLuigi Rizzo int
13842f345d8eSLuigi Rizzo oce_mbox_cmd_set_loopback(POCE_SOFTC sc, uint8_t port_num,
13852f345d8eSLuigi Rizzo 		uint8_t loopback_type, uint8_t enable)
13862f345d8eSLuigi Rizzo {
13872f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
13882f345d8eSLuigi Rizzo 	struct mbx_lowlevel_set_loopback_mode *fwcmd;
13892f345d8eSLuigi Rizzo 	int rc = 0;
13902f345d8eSLuigi Rizzo 
13912f345d8eSLuigi Rizzo 
13922f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
13932f345d8eSLuigi Rizzo 
13942f345d8eSLuigi Rizzo 	fwcmd = (struct mbx_lowlevel_set_loopback_mode *)&mbx.payload;
13952f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
13962f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_LOWLEVEL,
13972f345d8eSLuigi Rizzo 				OPCODE_LOWLEVEL_SET_LOOPBACK_MODE,
13982f345d8eSLuigi Rizzo 				MBX_TIMEOUT_SEC,
13992f345d8eSLuigi Rizzo 				sizeof(struct mbx_lowlevel_set_loopback_mode),
14002f345d8eSLuigi Rizzo 				OCE_MBX_VER_V0);
14012f345d8eSLuigi Rizzo 
14022f345d8eSLuigi Rizzo 	fwcmd->params.req.src_port = port_num;
14032f345d8eSLuigi Rizzo 	fwcmd->params.req.dest_port = port_num;
14042f345d8eSLuigi Rizzo 	fwcmd->params.req.loopback_type = loopback_type;
14052f345d8eSLuigi Rizzo 	fwcmd->params.req.loopback_state = enable;
14062f345d8eSLuigi Rizzo 
14072f345d8eSLuigi Rizzo 	mbx.u0.s.embedded = 1;
14082f345d8eSLuigi Rizzo 	mbx.payload_length = sizeof(struct  mbx_lowlevel_set_loopback_mode);
14092f345d8eSLuigi Rizzo 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
14102f345d8eSLuigi Rizzo 
14112f345d8eSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
1412cdaba892SXin LI 	if (!rc)
1413cdaba892SXin LI                 rc = fwcmd->hdr.u0.rsp.status;
1414cdaba892SXin LI 	if (rc)
14155fbb6830SXin LI 		device_printf(sc->dev,
14165fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
14175fbb6830SXin LI 			      __FUNCTION__, rc,
14185fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
14192f345d8eSLuigi Rizzo 
14202f345d8eSLuigi Rizzo 	return rc;
14212f345d8eSLuigi Rizzo 
14222f345d8eSLuigi Rizzo }
14232f345d8eSLuigi Rizzo 
14242f345d8eSLuigi Rizzo int
14252f345d8eSLuigi Rizzo oce_mbox_cmd_test_loopback(POCE_SOFTC sc, uint32_t port_num,
14262f345d8eSLuigi Rizzo 	uint32_t loopback_type, uint32_t pkt_size, uint32_t num_pkts,
14272f345d8eSLuigi Rizzo 	uint64_t pattern)
14282f345d8eSLuigi Rizzo {
14292f345d8eSLuigi Rizzo 
14302f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
14312f345d8eSLuigi Rizzo 	struct mbx_lowlevel_test_loopback_mode *fwcmd;
14322f345d8eSLuigi Rizzo 	int rc = 0;
14332f345d8eSLuigi Rizzo 
14342f345d8eSLuigi Rizzo 
14352f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
14362f345d8eSLuigi Rizzo 
14372f345d8eSLuigi Rizzo 	fwcmd = (struct mbx_lowlevel_test_loopback_mode *)&mbx.payload;
14382f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
14392f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_LOWLEVEL,
14402f345d8eSLuigi Rizzo 				OPCODE_LOWLEVEL_TEST_LOOPBACK,
14412f345d8eSLuigi Rizzo 				MBX_TIMEOUT_SEC,
14422f345d8eSLuigi Rizzo 				sizeof(struct mbx_lowlevel_test_loopback_mode),
14432f345d8eSLuigi Rizzo 				OCE_MBX_VER_V0);
14442f345d8eSLuigi Rizzo 
14452f345d8eSLuigi Rizzo 	fwcmd->params.req.pattern = pattern;
14462f345d8eSLuigi Rizzo 	fwcmd->params.req.src_port = port_num;
14472f345d8eSLuigi Rizzo 	fwcmd->params.req.dest_port = port_num;
14482f345d8eSLuigi Rizzo 	fwcmd->params.req.pkt_size = pkt_size;
14492f345d8eSLuigi Rizzo 	fwcmd->params.req.num_pkts = num_pkts;
14502f345d8eSLuigi Rizzo 	fwcmd->params.req.loopback_type = loopback_type;
14512f345d8eSLuigi Rizzo 
14522f345d8eSLuigi Rizzo 	mbx.u0.s.embedded = 1;
14532f345d8eSLuigi Rizzo 	mbx.payload_length = sizeof(struct  mbx_lowlevel_test_loopback_mode);
14542f345d8eSLuigi Rizzo 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
14552f345d8eSLuigi Rizzo 
14562f345d8eSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
1457cdaba892SXin LI 	if (!rc)
1458cdaba892SXin LI                 rc = fwcmd->hdr.u0.rsp.status;
14592f345d8eSLuigi Rizzo 	if (rc)
14605fbb6830SXin LI 		device_printf(sc->dev,
14615fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
14625fbb6830SXin LI 			      __FUNCTION__, rc,
14635fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
14642f345d8eSLuigi Rizzo 
1465cdaba892SXin LI 	return rc;
14662f345d8eSLuigi Rizzo }
14672f345d8eSLuigi Rizzo 
14682f345d8eSLuigi Rizzo int
14692f345d8eSLuigi Rizzo oce_mbox_write_flashrom(POCE_SOFTC sc, uint32_t optype,uint32_t opcode,
14702f345d8eSLuigi Rizzo 				POCE_DMA_MEM pdma_mem, uint32_t num_bytes)
14712f345d8eSLuigi Rizzo {
14722f345d8eSLuigi Rizzo 
14732f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
14742f345d8eSLuigi Rizzo 	struct oce_mq_sge *sgl = NULL;
14752f345d8eSLuigi Rizzo 	struct mbx_common_read_write_flashrom *fwcmd = NULL;
14762f345d8eSLuigi Rizzo 	int rc = 0, payload_len = 0;
14772f345d8eSLuigi Rizzo 
14782f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
14792f345d8eSLuigi Rizzo 	fwcmd = OCE_DMAPTR(pdma_mem, struct mbx_common_read_write_flashrom);
14802f345d8eSLuigi Rizzo 	payload_len = sizeof(struct mbx_common_read_write_flashrom) + 32*1024;
14812f345d8eSLuigi Rizzo 
14822f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
14832f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_COMMON,
14842f345d8eSLuigi Rizzo 				OPCODE_COMMON_WRITE_FLASHROM,
14852f345d8eSLuigi Rizzo 				LONG_TIMEOUT,
14862f345d8eSLuigi Rizzo 				payload_len,
14872f345d8eSLuigi Rizzo 				OCE_MBX_VER_V0);
14882f345d8eSLuigi Rizzo 
14895fbb6830SXin LI 	fwcmd->flash_op_type = LE_32(optype);
14905fbb6830SXin LI 	fwcmd->flash_op_code = LE_32(opcode);
14915fbb6830SXin LI 	fwcmd->data_buffer_size = LE_32(num_bytes);
14922f345d8eSLuigi Rizzo 
14932f345d8eSLuigi Rizzo 	mbx.u0.s.embedded  = 0; /*Non embeded*/
14942f345d8eSLuigi Rizzo 	mbx.payload_length = payload_len;
14952f345d8eSLuigi Rizzo 	mbx.u0.s.sge_count = 1;
14962f345d8eSLuigi Rizzo 
14972f345d8eSLuigi Rizzo 	sgl = &mbx.payload.u0.u1.sgl[0];
14982f345d8eSLuigi Rizzo 	sgl->pa_hi = upper_32_bits(pdma_mem->paddr);
14992f345d8eSLuigi Rizzo 	sgl->pa_lo = pdma_mem->paddr & 0xFFFFFFFF;
15002f345d8eSLuigi Rizzo 	sgl->length = payload_len;
15012f345d8eSLuigi Rizzo 
15022f345d8eSLuigi Rizzo 	/* post the command */
15039bd3250aSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
1504cdaba892SXin LI 	if (!rc)
15052f345d8eSLuigi Rizzo                 rc = fwcmd->hdr.u0.rsp.status;
1506cdaba892SXin LI 	if (rc)
15075fbb6830SXin LI 		device_printf(sc->dev,
15085fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
15095fbb6830SXin LI 			      __FUNCTION__, rc,
15105fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
15112f345d8eSLuigi Rizzo 
15122f345d8eSLuigi Rizzo 	return rc;
15132f345d8eSLuigi Rizzo 
15142f345d8eSLuigi Rizzo }
15152f345d8eSLuigi Rizzo 
15162f345d8eSLuigi Rizzo int
15172f345d8eSLuigi Rizzo oce_mbox_get_flashrom_crc(POCE_SOFTC sc, uint8_t *flash_crc,
15182f345d8eSLuigi Rizzo 				uint32_t offset, uint32_t optype)
15192f345d8eSLuigi Rizzo {
15202f345d8eSLuigi Rizzo 
15212f345d8eSLuigi Rizzo 	int rc = 0, payload_len = 0;
15222f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
15232f345d8eSLuigi Rizzo 	struct mbx_common_read_write_flashrom *fwcmd;
15242f345d8eSLuigi Rizzo 
15252f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
15262f345d8eSLuigi Rizzo 
15272f345d8eSLuigi Rizzo 	fwcmd = (struct mbx_common_read_write_flashrom *)&mbx.payload;
15282f345d8eSLuigi Rizzo 
15292f345d8eSLuigi Rizzo 	/* Firmware requires extra 4 bytes with this ioctl. Since there
15302f345d8eSLuigi Rizzo 	   is enough room in the mbx payload it should be good enough
15312f345d8eSLuigi Rizzo 	   Reference: Bug 14853
15322f345d8eSLuigi Rizzo 	*/
15332f345d8eSLuigi Rizzo 	payload_len = sizeof(struct mbx_common_read_write_flashrom) + 4;
15342f345d8eSLuigi Rizzo 
15352f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
15362f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_COMMON,
15372f345d8eSLuigi Rizzo 				OPCODE_COMMON_READ_FLASHROM,
15382f345d8eSLuigi Rizzo 				MBX_TIMEOUT_SEC,
15392f345d8eSLuigi Rizzo 				payload_len,
15402f345d8eSLuigi Rizzo 				OCE_MBX_VER_V0);
15412f345d8eSLuigi Rizzo 
15422f345d8eSLuigi Rizzo 	fwcmd->flash_op_type = optype;
15432f345d8eSLuigi Rizzo 	fwcmd->flash_op_code = FLASHROM_OPER_REPORT;
15442f345d8eSLuigi Rizzo 	fwcmd->data_offset = offset;
15452f345d8eSLuigi Rizzo 	fwcmd->data_buffer_size = 0x4;
15462f345d8eSLuigi Rizzo 
15472f345d8eSLuigi Rizzo 	mbx.u0.s.embedded  = 1;
15482f345d8eSLuigi Rizzo 	mbx.payload_length = payload_len;
15492f345d8eSLuigi Rizzo 
15502f345d8eSLuigi Rizzo 	/* post the command */
15512f345d8eSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
1552cdaba892SXin LI 	if (!rc)
15532f345d8eSLuigi Rizzo                 rc = fwcmd->hdr.u0.rsp.status;
1554cdaba892SXin LI 	if (rc) {
15555fbb6830SXin LI 		device_printf(sc->dev,
15565fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
15575fbb6830SXin LI 			      __FUNCTION__, rc,
15585fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
1559cdaba892SXin LI 		goto error;
15602f345d8eSLuigi Rizzo 	}
1561cdaba892SXin LI 	bcopy(fwcmd->data_buffer, flash_crc, 4);
1562cdaba892SXin LI error:
15632f345d8eSLuigi Rizzo 	return rc;
15642f345d8eSLuigi Rizzo }
15652f345d8eSLuigi Rizzo 
15662f345d8eSLuigi Rizzo int
15672f345d8eSLuigi Rizzo oce_mbox_get_phy_info(POCE_SOFTC sc, struct oce_phy_info *phy_info)
15682f345d8eSLuigi Rizzo {
15692f345d8eSLuigi Rizzo 
15702f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
15712f345d8eSLuigi Rizzo 	struct mbx_common_phy_info *fwcmd;
15722f345d8eSLuigi Rizzo 	int rc = 0;
15732f345d8eSLuigi Rizzo 
15742f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
15752f345d8eSLuigi Rizzo 
15762f345d8eSLuigi Rizzo 	fwcmd = (struct mbx_common_phy_info *)&mbx.payload;
15772f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
15782f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_COMMON,
15792f345d8eSLuigi Rizzo 				OPCODE_COMMON_GET_PHY_CONFIG,
15802f345d8eSLuigi Rizzo 				MBX_TIMEOUT_SEC,
15812f345d8eSLuigi Rizzo 				sizeof(struct mbx_common_phy_info),
15822f345d8eSLuigi Rizzo 				OCE_MBX_VER_V0);
15832f345d8eSLuigi Rizzo 
15842f345d8eSLuigi Rizzo 	mbx.u0.s.embedded = 1;
15852f345d8eSLuigi Rizzo 	mbx.payload_length = sizeof(struct  mbx_common_phy_info);
15862f345d8eSLuigi Rizzo 
15872f345d8eSLuigi Rizzo 	/* now post the command */
15882f345d8eSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
1589cdaba892SXin LI 	if (!rc)
15902f345d8eSLuigi Rizzo                 rc = fwcmd->hdr.u0.rsp.status;
1591cdaba892SXin LI 	if (rc) {
15925fbb6830SXin LI 		device_printf(sc->dev,
15935fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
15945fbb6830SXin LI 			      __FUNCTION__, rc,
15955fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
1596cdaba892SXin LI 		goto error;
1597cdaba892SXin LI 	}
15985fbb6830SXin LI 	phy_info->phy_type = HOST_16(fwcmd->params.rsp.phy_info.phy_type);
15992f345d8eSLuigi Rizzo 	phy_info->interface_type =
16005fbb6830SXin LI 			HOST_16(fwcmd->params.rsp.phy_info.interface_type);
16012f345d8eSLuigi Rizzo 	phy_info->auto_speeds_supported =
16025fbb6830SXin LI 		HOST_16(fwcmd->params.rsp.phy_info.auto_speeds_supported);
16032f345d8eSLuigi Rizzo 	phy_info->fixed_speeds_supported =
16045fbb6830SXin LI 		HOST_16(fwcmd->params.rsp.phy_info.fixed_speeds_supported);
16055fbb6830SXin LI 	phy_info->misc_params = HOST_32(fwcmd->params.rsp.phy_info.misc_params);
1606cdaba892SXin LI error:
16072f345d8eSLuigi Rizzo 	return rc;
16082f345d8eSLuigi Rizzo 
16092f345d8eSLuigi Rizzo }
16102f345d8eSLuigi Rizzo 
16112f345d8eSLuigi Rizzo 
16122f345d8eSLuigi Rizzo int
16132f345d8eSLuigi Rizzo oce_mbox_lancer_write_flashrom(POCE_SOFTC sc, uint32_t data_size,
16142f345d8eSLuigi Rizzo 			uint32_t data_offset, POCE_DMA_MEM pdma_mem,
16152f345d8eSLuigi Rizzo 			uint32_t *written_data, uint32_t *additional_status)
16162f345d8eSLuigi Rizzo {
16172f345d8eSLuigi Rizzo 
16182f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
16192f345d8eSLuigi Rizzo 	struct mbx_lancer_common_write_object *fwcmd = NULL;
16202f345d8eSLuigi Rizzo 	int rc = 0, payload_len = 0;
16212f345d8eSLuigi Rizzo 
16222f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
16232f345d8eSLuigi Rizzo 	payload_len = sizeof(struct mbx_lancer_common_write_object);
16242f345d8eSLuigi Rizzo 
16252f345d8eSLuigi Rizzo 	mbx.u0.s.embedded  = 1;/* Embedded */
16262f345d8eSLuigi Rizzo 	mbx.payload_length = payload_len;
16272f345d8eSLuigi Rizzo 	fwcmd = (struct mbx_lancer_common_write_object *)&mbx.payload;
16282f345d8eSLuigi Rizzo 
16292f345d8eSLuigi Rizzo 	/* initialize the ioctl header */
16302f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->params.req.hdr, 0, 0,
16312f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_COMMON,
16322f345d8eSLuigi Rizzo 				OPCODE_COMMON_WRITE_OBJECT,
16332f345d8eSLuigi Rizzo 				LONG_TIMEOUT,
16342f345d8eSLuigi Rizzo 				payload_len,
16352f345d8eSLuigi Rizzo 				OCE_MBX_VER_V0);
16362f345d8eSLuigi Rizzo 
16372f345d8eSLuigi Rizzo 	fwcmd->params.req.write_length = data_size;
16382f345d8eSLuigi Rizzo 	if (data_size == 0)
16392f345d8eSLuigi Rizzo 		fwcmd->params.req.eof = 1;
16402f345d8eSLuigi Rizzo 	else
16412f345d8eSLuigi Rizzo 		fwcmd->params.req.eof = 0;
16422f345d8eSLuigi Rizzo 
16432f345d8eSLuigi Rizzo 	strcpy(fwcmd->params.req.object_name, "/prg");
16442f345d8eSLuigi Rizzo 	fwcmd->params.req.descriptor_count = 1;
16452f345d8eSLuigi Rizzo 	fwcmd->params.req.write_offset = data_offset;
16462f345d8eSLuigi Rizzo 	fwcmd->params.req.buffer_length = data_size;
16472f345d8eSLuigi Rizzo 	fwcmd->params.req.address_lower = pdma_mem->paddr & 0xFFFFFFFF;
16482f345d8eSLuigi Rizzo 	fwcmd->params.req.address_upper = upper_32_bits(pdma_mem->paddr);
16492f345d8eSLuigi Rizzo 
16502f345d8eSLuigi Rizzo 	/* post the command */
16512f345d8eSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
1652cdaba892SXin LI 	if (!rc)
1653cdaba892SXin LI                 rc = fwcmd->params.rsp.status;
16542f345d8eSLuigi Rizzo 	if (rc) {
16555fbb6830SXin LI 		device_printf(sc->dev,
16565fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
16575fbb6830SXin LI 			      __FUNCTION__, rc,
16585fbb6830SXin LI 			      fwcmd->params.rsp.additional_status);
1659cdaba892SXin LI 		goto error;
1660cdaba892SXin LI 	}
16615fbb6830SXin LI 	*written_data = HOST_32(fwcmd->params.rsp.actual_write_length);
16622f345d8eSLuigi Rizzo 	*additional_status = fwcmd->params.rsp.additional_status;
1663cdaba892SXin LI error:
16642f345d8eSLuigi Rizzo 	return rc;
16652f345d8eSLuigi Rizzo 
16662f345d8eSLuigi Rizzo }
16672f345d8eSLuigi Rizzo 
16682f345d8eSLuigi Rizzo 
16692f345d8eSLuigi Rizzo 
16702f345d8eSLuigi Rizzo int
16712f345d8eSLuigi Rizzo oce_mbox_create_rq(struct oce_rq *rq)
16722f345d8eSLuigi Rizzo {
16732f345d8eSLuigi Rizzo 
16742f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
16752f345d8eSLuigi Rizzo 	struct mbx_create_nic_rq *fwcmd;
16762f345d8eSLuigi Rizzo 	POCE_SOFTC sc = rq->parent;
16772f345d8eSLuigi Rizzo 	int rc, num_pages = 0;
16782f345d8eSLuigi Rizzo 
16792f345d8eSLuigi Rizzo 	if (rq->qstate == QCREATED)
16802f345d8eSLuigi Rizzo 		return 0;
16812f345d8eSLuigi Rizzo 
16822f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
16832f345d8eSLuigi Rizzo 
16842f345d8eSLuigi Rizzo 	fwcmd = (struct mbx_create_nic_rq *)&mbx.payload;
16852f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
16862f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_NIC,
16872f345d8eSLuigi Rizzo 				NIC_CREATE_RQ, MBX_TIMEOUT_SEC,
16882f345d8eSLuigi Rizzo 				sizeof(struct mbx_create_nic_rq),
16892f345d8eSLuigi Rizzo 				OCE_MBX_VER_V0);
16902f345d8eSLuigi Rizzo 
16912f345d8eSLuigi Rizzo 	/* oce_page_list will also prepare pages */
16922f345d8eSLuigi Rizzo 	num_pages = oce_page_list(rq->ring, &fwcmd->params.req.pages[0]);
16932f345d8eSLuigi Rizzo 
16942f345d8eSLuigi Rizzo 	if (IS_XE201(sc)) {
16952f345d8eSLuigi Rizzo 		fwcmd->params.req.frag_size = rq->cfg.frag_size/2048;
16962f345d8eSLuigi Rizzo 		fwcmd->params.req.page_size = 1;
16972f345d8eSLuigi Rizzo 		fwcmd->hdr.u0.req.version = OCE_MBX_VER_V1;
16982f345d8eSLuigi Rizzo 	} else
16992f345d8eSLuigi Rizzo 		fwcmd->params.req.frag_size = OCE_LOG2(rq->cfg.frag_size);
17002f345d8eSLuigi Rizzo 	fwcmd->params.req.num_pages = num_pages;
17012f345d8eSLuigi Rizzo 	fwcmd->params.req.cq_id = rq->cq->cq_id;
17022f345d8eSLuigi Rizzo 	fwcmd->params.req.if_id = sc->if_id;
17032f345d8eSLuigi Rizzo 	fwcmd->params.req.max_frame_size = rq->cfg.mtu;
17042f345d8eSLuigi Rizzo 	fwcmd->params.req.is_rss_queue = rq->cfg.is_rss_queue;
17052f345d8eSLuigi Rizzo 
17062f345d8eSLuigi Rizzo 	mbx.u0.s.embedded = 1;
17072f345d8eSLuigi Rizzo 	mbx.payload_length = sizeof(struct mbx_create_nic_rq);
17082f345d8eSLuigi Rizzo 
17092f345d8eSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
1710cdaba892SXin LI 	if (!rc)
1711cdaba892SXin LI                 rc = fwcmd->hdr.u0.rsp.status;
1712cdaba892SXin LI 	if (rc) {
17135fbb6830SXin LI 		device_printf(sc->dev,
17145fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
17155fbb6830SXin LI 			      __FUNCTION__, rc,
17165fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
17172f345d8eSLuigi Rizzo 		goto error;
1718cdaba892SXin LI 	}
17195fbb6830SXin LI 	rq->rq_id = HOST_16(fwcmd->params.rsp.rq_id);
17202f345d8eSLuigi Rizzo 	rq->rss_cpuid = fwcmd->params.rsp.rss_cpuid;
17212f345d8eSLuigi Rizzo error:
17222f345d8eSLuigi Rizzo 	return rc;
17232f345d8eSLuigi Rizzo 
17242f345d8eSLuigi Rizzo }
17252f345d8eSLuigi Rizzo 
17262f345d8eSLuigi Rizzo 
17272f345d8eSLuigi Rizzo 
17282f345d8eSLuigi Rizzo int
17292f345d8eSLuigi Rizzo oce_mbox_create_wq(struct oce_wq *wq)
17302f345d8eSLuigi Rizzo {
17312f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
17322f345d8eSLuigi Rizzo 	struct mbx_create_nic_wq *fwcmd;
17332f345d8eSLuigi Rizzo 	POCE_SOFTC sc = wq->parent;
17342f345d8eSLuigi Rizzo 	int rc = 0, version, num_pages;
17352f345d8eSLuigi Rizzo 
17362f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
17372f345d8eSLuigi Rizzo 
17382f345d8eSLuigi Rizzo 	fwcmd = (struct mbx_create_nic_wq *)&mbx.payload;
17395fbb6830SXin LI 	if (IS_XE201(sc))
17402f345d8eSLuigi Rizzo 		version = OCE_MBX_VER_V1;
17415fbb6830SXin LI 	else if(IS_BE(sc))
1742291a1934SXin LI 		IS_PROFILE_SUPER_NIC(sc) ? (version = OCE_MBX_VER_V2)
1743291a1934SXin LI 					 : (version = OCE_MBX_VER_V0);
1744291a1934SXin LI 	else
1745291a1934SXin LI 		version = OCE_MBX_VER_V2;
17462f345d8eSLuigi Rizzo 
17475fbb6830SXin LI 	if (version > OCE_MBX_VER_V0)
17485fbb6830SXin LI 		fwcmd->params.req.if_id = sc->if_id;
17495fbb6830SXin LI 
17502f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
17512f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_NIC,
17522f345d8eSLuigi Rizzo 				NIC_CREATE_WQ, MBX_TIMEOUT_SEC,
17532f345d8eSLuigi Rizzo 				sizeof(struct mbx_create_nic_wq),
17542f345d8eSLuigi Rizzo 				version);
17552f345d8eSLuigi Rizzo 
17562f345d8eSLuigi Rizzo 	num_pages = oce_page_list(wq->ring, &fwcmd->params.req.pages[0]);
17572f345d8eSLuigi Rizzo 
17582f345d8eSLuigi Rizzo 	fwcmd->params.req.nic_wq_type = wq->cfg.wq_type;
17592f345d8eSLuigi Rizzo 	fwcmd->params.req.num_pages = num_pages;
17602f345d8eSLuigi Rizzo 	fwcmd->params.req.wq_size = OCE_LOG2(wq->cfg.q_len) + 1;
17612f345d8eSLuigi Rizzo 	fwcmd->params.req.cq_id = wq->cq->cq_id;
17622f345d8eSLuigi Rizzo 	fwcmd->params.req.ulp_num = 1;
17632f345d8eSLuigi Rizzo 
17642f345d8eSLuigi Rizzo 	mbx.u0.s.embedded = 1;
17652f345d8eSLuigi Rizzo 	mbx.payload_length = sizeof(struct mbx_create_nic_wq);
17662f345d8eSLuigi Rizzo 
17672f345d8eSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
1768cdaba892SXin LI 	if (!rc)
1769cdaba892SXin LI                 rc = fwcmd->hdr.u0.rsp.status;
1770cdaba892SXin LI 	if (rc) {
17715fbb6830SXin LI 		device_printf(sc->dev,
17725fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
17735fbb6830SXin LI 			      __FUNCTION__, rc,
17745fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
17752f345d8eSLuigi Rizzo 		goto error;
1776cdaba892SXin LI 	}
17775fbb6830SXin LI 	wq->wq_id = HOST_16(fwcmd->params.rsp.wq_id);
1778291a1934SXin LI 	if (version == OCE_MBX_VER_V2)
17795fbb6830SXin LI 		wq->db_offset = HOST_32(fwcmd->params.rsp.db_offset);
1780291a1934SXin LI 	else
1781291a1934SXin LI 		wq->db_offset = PD_TXULP_DB;
17822f345d8eSLuigi Rizzo error:
17832f345d8eSLuigi Rizzo 	return rc;
17842f345d8eSLuigi Rizzo 
17852f345d8eSLuigi Rizzo }
17862f345d8eSLuigi Rizzo 
17872f345d8eSLuigi Rizzo 
17882f345d8eSLuigi Rizzo 
17892f345d8eSLuigi Rizzo int
17902f345d8eSLuigi Rizzo oce_mbox_create_eq(struct oce_eq *eq)
17912f345d8eSLuigi Rizzo {
17922f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
17932f345d8eSLuigi Rizzo 	struct mbx_create_common_eq *fwcmd;
17942f345d8eSLuigi Rizzo 	POCE_SOFTC sc = eq->parent;
17952f345d8eSLuigi Rizzo 	int rc = 0;
17962f345d8eSLuigi Rizzo 	uint32_t num_pages;
17972f345d8eSLuigi Rizzo 
17982f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
17992f345d8eSLuigi Rizzo 
18002f345d8eSLuigi Rizzo 	fwcmd = (struct mbx_create_common_eq *)&mbx.payload;
18012f345d8eSLuigi Rizzo 
18022f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
18032f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_COMMON,
18042f345d8eSLuigi Rizzo 				OPCODE_COMMON_CREATE_EQ, MBX_TIMEOUT_SEC,
18052f345d8eSLuigi Rizzo 				sizeof(struct mbx_create_common_eq),
18062f345d8eSLuigi Rizzo 				OCE_MBX_VER_V0);
18072f345d8eSLuigi Rizzo 
18082f345d8eSLuigi Rizzo 	num_pages = oce_page_list(eq->ring, &fwcmd->params.req.pages[0]);
18092f345d8eSLuigi Rizzo 	fwcmd->params.req.ctx.num_pages = num_pages;
18102f345d8eSLuigi Rizzo 	fwcmd->params.req.ctx.valid = 1;
18112f345d8eSLuigi Rizzo 	fwcmd->params.req.ctx.size = (eq->eq_cfg.item_size == 4) ? 0 : 1;
18122f345d8eSLuigi Rizzo 	fwcmd->params.req.ctx.count = OCE_LOG2(eq->eq_cfg.q_len / 256);
18132f345d8eSLuigi Rizzo 	fwcmd->params.req.ctx.armed = 0;
18142f345d8eSLuigi Rizzo 	fwcmd->params.req.ctx.delay_mult = eq->eq_cfg.cur_eqd;
18152f345d8eSLuigi Rizzo 
18162f345d8eSLuigi Rizzo 
18172f345d8eSLuigi Rizzo 	mbx.u0.s.embedded = 1;
18182f345d8eSLuigi Rizzo 	mbx.payload_length = sizeof(struct mbx_create_common_eq);
18192f345d8eSLuigi Rizzo 
18202f345d8eSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
1821cdaba892SXin LI 	if (!rc)
1822cdaba892SXin LI                 rc = fwcmd->hdr.u0.rsp.status;
1823cdaba892SXin LI 	if (rc) {
18245fbb6830SXin LI 		device_printf(sc->dev,
18255fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
18265fbb6830SXin LI 			      __FUNCTION__, rc,
18275fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
18282f345d8eSLuigi Rizzo 		goto error;
1829cdaba892SXin LI 	}
18305fbb6830SXin LI 	eq->eq_id = HOST_16(fwcmd->params.rsp.eq_id);
18312f345d8eSLuigi Rizzo error:
18322f345d8eSLuigi Rizzo 	return rc;
18332f345d8eSLuigi Rizzo }
18342f345d8eSLuigi Rizzo 
18352f345d8eSLuigi Rizzo 
18362f345d8eSLuigi Rizzo 
18372f345d8eSLuigi Rizzo int
18382f345d8eSLuigi Rizzo oce_mbox_cq_create(struct oce_cq *cq, uint32_t ncoalesce, uint32_t is_eventable)
18392f345d8eSLuigi Rizzo {
18402f345d8eSLuigi Rizzo 	struct oce_mbx mbx;
18412f345d8eSLuigi Rizzo 	struct mbx_create_common_cq *fwcmd;
18422f345d8eSLuigi Rizzo 	POCE_SOFTC sc = cq->parent;
18432f345d8eSLuigi Rizzo 	uint8_t version;
18442f345d8eSLuigi Rizzo 	oce_cq_ctx_t *ctx;
18452f345d8eSLuigi Rizzo 	uint32_t num_pages, page_size;
18462f345d8eSLuigi Rizzo 	int rc = 0;
18472f345d8eSLuigi Rizzo 
18482f345d8eSLuigi Rizzo 
18492f345d8eSLuigi Rizzo 	bzero(&mbx, sizeof(struct oce_mbx));
18502f345d8eSLuigi Rizzo 
18512f345d8eSLuigi Rizzo 	fwcmd = (struct mbx_create_common_cq *)&mbx.payload;
18522f345d8eSLuigi Rizzo 
18532f345d8eSLuigi Rizzo 	if (IS_XE201(sc))
18542f345d8eSLuigi Rizzo 		version = OCE_MBX_VER_V2;
18552f345d8eSLuigi Rizzo 	else
18562f345d8eSLuigi Rizzo 		version = OCE_MBX_VER_V0;
18572f345d8eSLuigi Rizzo 
18582f345d8eSLuigi Rizzo 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
18592f345d8eSLuigi Rizzo 				MBX_SUBSYSTEM_COMMON,
18602f345d8eSLuigi Rizzo 				OPCODE_COMMON_CREATE_CQ,
18612f345d8eSLuigi Rizzo 				MBX_TIMEOUT_SEC,
18622f345d8eSLuigi Rizzo 				sizeof(struct mbx_create_common_cq),
18632f345d8eSLuigi Rizzo 				version);
18642f345d8eSLuigi Rizzo 
18652f345d8eSLuigi Rizzo 	ctx = &fwcmd->params.req.cq_ctx;
18662f345d8eSLuigi Rizzo 
18672f345d8eSLuigi Rizzo 	num_pages = oce_page_list(cq->ring, &fwcmd->params.req.pages[0]);
18682f345d8eSLuigi Rizzo 	page_size =  1;  /* 1 for 4K */
18692f345d8eSLuigi Rizzo 
18702f345d8eSLuigi Rizzo 	if (version == OCE_MBX_VER_V2) {
18712f345d8eSLuigi Rizzo 		ctx->v2.num_pages = LE_16(num_pages);
18722f345d8eSLuigi Rizzo 		ctx->v2.page_size = page_size;
18732f345d8eSLuigi Rizzo 		ctx->v2.eventable = is_eventable;
18742f345d8eSLuigi Rizzo 		ctx->v2.valid = 1;
18752f345d8eSLuigi Rizzo 		ctx->v2.count = OCE_LOG2(cq->cq_cfg.q_len / 256);
18762f345d8eSLuigi Rizzo 		ctx->v2.nodelay = cq->cq_cfg.nodelay;
18772f345d8eSLuigi Rizzo 		ctx->v2.coalesce_wm = ncoalesce;
18782f345d8eSLuigi Rizzo 		ctx->v2.armed = 0;
18792f345d8eSLuigi Rizzo 		ctx->v2.eq_id = cq->eq->eq_id;
18802f345d8eSLuigi Rizzo 		if (ctx->v2.count == 3) {
1881c236d647SWarner Losh 			if ((u_int)cq->cq_cfg.q_len > (4*1024)-1)
18822f345d8eSLuigi Rizzo 				ctx->v2.cqe_count = (4*1024)-1;
18832f345d8eSLuigi Rizzo 			else
18842f345d8eSLuigi Rizzo 				ctx->v2.cqe_count = cq->cq_cfg.q_len;
18852f345d8eSLuigi Rizzo 		}
18862f345d8eSLuigi Rizzo 	} else {
18872f345d8eSLuigi Rizzo 		ctx->v0.num_pages = LE_16(num_pages);
18882f345d8eSLuigi Rizzo 		ctx->v0.eventable = is_eventable;
18892f345d8eSLuigi Rizzo 		ctx->v0.valid = 1;
18902f345d8eSLuigi Rizzo 		ctx->v0.count = OCE_LOG2(cq->cq_cfg.q_len / 256);
18912f345d8eSLuigi Rizzo 		ctx->v0.nodelay = cq->cq_cfg.nodelay;
18922f345d8eSLuigi Rizzo 		ctx->v0.coalesce_wm = ncoalesce;
18932f345d8eSLuigi Rizzo 		ctx->v0.armed = 0;
18942f345d8eSLuigi Rizzo 		ctx->v0.eq_id = cq->eq->eq_id;
18952f345d8eSLuigi Rizzo 	}
18962f345d8eSLuigi Rizzo 
18972f345d8eSLuigi Rizzo 	mbx.u0.s.embedded = 1;
18982f345d8eSLuigi Rizzo 	mbx.payload_length = sizeof(struct mbx_create_common_cq);
18992f345d8eSLuigi Rizzo 
19002f345d8eSLuigi Rizzo 	rc = oce_mbox_post(sc, &mbx, NULL);
1901cdaba892SXin LI 	if (!rc)
1902cdaba892SXin LI                 rc = fwcmd->hdr.u0.rsp.status;
1903cdaba892SXin LI 	if (rc) {
19045fbb6830SXin LI 		device_printf(sc->dev,
19055fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
19065fbb6830SXin LI 			      __FUNCTION__, rc,
19075fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
19082f345d8eSLuigi Rizzo 		goto error;
1909cdaba892SXin LI 	}
19105fbb6830SXin LI 	cq->cq_id = HOST_16(fwcmd->params.rsp.cq_id);
19112f345d8eSLuigi Rizzo error:
19122f345d8eSLuigi Rizzo 	return rc;
19132f345d8eSLuigi Rizzo 
19142f345d8eSLuigi Rizzo }
1915cdaba892SXin LI 
1916cdaba892SXin LI int
1917cdaba892SXin LI oce_mbox_read_transrecv_data(POCE_SOFTC sc, uint32_t page_num)
1918cdaba892SXin LI {
1919cdaba892SXin LI 	int rc = 0;
1920cdaba892SXin LI 	struct oce_mbx mbx;
1921cdaba892SXin LI 	struct mbx_read_common_transrecv_data *fwcmd;
1922cdaba892SXin LI 	struct oce_mq_sge *sgl;
1923cdaba892SXin LI 	OCE_DMA_MEM dma;
1924cdaba892SXin LI 
1925cdaba892SXin LI 	/* Allocate DMA mem*/
1926cdaba892SXin LI 	if (oce_dma_alloc(sc, sizeof(struct mbx_read_common_transrecv_data),
1927cdaba892SXin LI 				&dma, 0))
1928cdaba892SXin LI 		return ENOMEM;
1929cdaba892SXin LI 
1930cdaba892SXin LI 	fwcmd = OCE_DMAPTR(&dma, struct mbx_read_common_transrecv_data);
1931cdaba892SXin LI 	bzero(fwcmd, sizeof(struct mbx_read_common_transrecv_data));
1932cdaba892SXin LI 
1933cdaba892SXin LI 	bzero(&mbx, sizeof(struct oce_mbx));
1934cdaba892SXin LI 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1935cdaba892SXin LI 			MBX_SUBSYSTEM_COMMON,
1936cdaba892SXin LI 			OPCODE_COMMON_READ_TRANSRECEIVER_DATA,
1937cdaba892SXin LI 			MBX_TIMEOUT_SEC,
1938cdaba892SXin LI 			sizeof(struct mbx_read_common_transrecv_data),
1939cdaba892SXin LI 			OCE_MBX_VER_V0);
1940cdaba892SXin LI 
1941cdaba892SXin LI 	/* fill rest of mbx */
1942cdaba892SXin LI 	mbx.u0.s.embedded = 0;
1943cdaba892SXin LI 	mbx.payload_length = sizeof(struct mbx_read_common_transrecv_data);
1944cdaba892SXin LI 	mbx.u0.s.sge_count = 1;
1945cdaba892SXin LI 	sgl = &mbx.payload.u0.u1.sgl[0];
1946cdaba892SXin LI 	sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
1947cdaba892SXin LI 	sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
1948cdaba892SXin LI 	sgl->length = htole32(mbx.payload_length);
1949cdaba892SXin LI 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
1950cdaba892SXin LI 
1951cdaba892SXin LI 	fwcmd->params.req.port = LE_32(sc->port_id);
1952cdaba892SXin LI 	fwcmd->params.req.page_num = LE_32(page_num);
1953cdaba892SXin LI 
1954cdaba892SXin LI 	/* command post */
1955cdaba892SXin LI 	rc = oce_mbox_post(sc, &mbx, NULL);
1956cdaba892SXin LI 	if (!rc)
1957cdaba892SXin LI 		rc = fwcmd->hdr.u0.rsp.status;
1958cdaba892SXin LI 	if (rc) {
19595fbb6830SXin LI 		device_printf(sc->dev,
19605fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
19615fbb6830SXin LI 			      __FUNCTION__, rc,
19625fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
1963cdaba892SXin LI 		goto error;
1964cdaba892SXin LI 	}
1965cdaba892SXin LI 	if(fwcmd->params.rsp.page_num == PAGE_NUM_A0)
1966cdaba892SXin LI 	{
1967cdaba892SXin LI 		bcopy((char *)fwcmd->params.rsp.page_data,
1968*e0dd0fe3SXin LI 		      &sfp_vpd_dump_buffer[0],
1969cdaba892SXin LI 		      TRANSCEIVER_A0_SIZE);
1970cdaba892SXin LI 	}
1971cdaba892SXin LI 
1972cdaba892SXin LI 	if(fwcmd->params.rsp.page_num == PAGE_NUM_A2)
1973cdaba892SXin LI 	{
1974cdaba892SXin LI 		bcopy((char *)fwcmd->params.rsp.page_data,
1975*e0dd0fe3SXin LI 		      &sfp_vpd_dump_buffer[TRANSCEIVER_A0_SIZE],
1976cdaba892SXin LI 		      TRANSCEIVER_A2_SIZE);
1977cdaba892SXin LI 	}
1978cdaba892SXin LI error:
1979291a1934SXin LI 	oce_dma_free(sc, &dma);
1980cdaba892SXin LI 	return rc;
1981cdaba892SXin LI }
1982cdaba892SXin LI 
1983cdaba892SXin LI void
1984cdaba892SXin LI oce_mbox_eqd_modify_periodic(POCE_SOFTC sc, struct oce_set_eqd *set_eqd,
1985cdaba892SXin LI 				int num)
1986cdaba892SXin LI {
1987cdaba892SXin LI 	struct oce_mbx mbx;
1988cdaba892SXin LI 	struct mbx_modify_common_eq_delay *fwcmd;
1989cdaba892SXin LI 	int rc = 0;
1990cdaba892SXin LI 	int i = 0;
1991cdaba892SXin LI 
1992cdaba892SXin LI 	bzero(&mbx, sizeof(struct oce_mbx));
1993cdaba892SXin LI 
1994cdaba892SXin LI 	/* Initialize MODIFY_EQ_DELAY ioctl header */
1995cdaba892SXin LI 	fwcmd = (struct mbx_modify_common_eq_delay *)&mbx.payload;
1996cdaba892SXin LI 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
1997cdaba892SXin LI 				MBX_SUBSYSTEM_COMMON,
1998cdaba892SXin LI 				OPCODE_COMMON_MODIFY_EQ_DELAY,
1999cdaba892SXin LI 				MBX_TIMEOUT_SEC,
2000cdaba892SXin LI 				sizeof(struct mbx_modify_common_eq_delay),
2001cdaba892SXin LI 				OCE_MBX_VER_V0);
2002cdaba892SXin LI 	/* fill rest of mbx */
2003cdaba892SXin LI 	mbx.u0.s.embedded = 1;
2004cdaba892SXin LI 	mbx.payload_length = sizeof(struct mbx_modify_common_eq_delay);
2005cdaba892SXin LI 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
2006cdaba892SXin LI 
2007cdaba892SXin LI 	fwcmd->params.req.num_eq = num;
2008cdaba892SXin LI 	for (i = 0; i < num; i++) {
2009cdaba892SXin LI 		fwcmd->params.req.delay[i].eq_id =
2010cdaba892SXin LI 					htole32(set_eqd[i].eq_id);
2011cdaba892SXin LI 		fwcmd->params.req.delay[i].phase = 0;
2012cdaba892SXin LI 		fwcmd->params.req.delay[i].dm =
2013cdaba892SXin LI 		htole32(set_eqd[i].delay_multiplier);
2014cdaba892SXin LI 	}
2015cdaba892SXin LI 
2016cdaba892SXin LI 
2017cdaba892SXin LI 	/* command post */
2018cdaba892SXin LI 	rc = oce_mbox_post(sc, &mbx, NULL);
2019cdaba892SXin LI 
2020cdaba892SXin LI 	if (!rc)
2021cdaba892SXin LI 		rc = fwcmd->hdr.u0.rsp.status;
2022cdaba892SXin LI 	if (rc)
20235fbb6830SXin LI 		device_printf(sc->dev,
20245fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
20255fbb6830SXin LI 			      __FUNCTION__, rc,
20265fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
2027cdaba892SXin LI }
2028cdaba892SXin LI 
2029291a1934SXin LI int
2030b41206d8SXin LI oce_get_profile_config(POCE_SOFTC sc, uint32_t max_rss)
2031291a1934SXin LI {
2032291a1934SXin LI 	struct oce_mbx mbx;
2033291a1934SXin LI 	struct mbx_common_get_profile_config *fwcmd;
2034291a1934SXin LI 	int rc = 0;
2035291a1934SXin LI 	int version = 0;
2036291a1934SXin LI 	struct oce_mq_sge *sgl;
2037291a1934SXin LI 	OCE_DMA_MEM dma;
2038291a1934SXin LI 	uint32_t desc_count = 0;
2039291a1934SXin LI 	struct oce_nic_resc_desc *nic_desc = NULL;
2040291a1934SXin LI 	int i;
2041291a1934SXin LI 	boolean_t nic_desc_valid = FALSE;
2042cdaba892SXin LI 
2043291a1934SXin LI 	if (IS_BE2(sc))
2044291a1934SXin LI 		return -1;
2045291a1934SXin LI 
2046291a1934SXin LI 	/* Allocate DMA mem*/
2047291a1934SXin LI 	if (oce_dma_alloc(sc, sizeof(struct mbx_common_get_profile_config),
2048291a1934SXin LI 			  &dma, 0))
2049291a1934SXin LI 		return ENOMEM;
2050291a1934SXin LI 
2051291a1934SXin LI 	/* Initialize MODIFY_EQ_DELAY ioctl header */
2052291a1934SXin LI 	fwcmd = OCE_DMAPTR(&dma, struct mbx_common_get_profile_config);
2053291a1934SXin LI 	bzero(fwcmd, sizeof(struct mbx_common_get_profile_config));
2054291a1934SXin LI 
2055b41206d8SXin LI 	if (!IS_XE201(sc))
2056291a1934SXin LI 		version = OCE_MBX_VER_V1;
2057291a1934SXin LI 	else
2058291a1934SXin LI 		version = OCE_MBX_VER_V0;
2059291a1934SXin LI 
2060291a1934SXin LI 	bzero(&mbx, sizeof(struct oce_mbx));
2061291a1934SXin LI 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
2062291a1934SXin LI 				MBX_SUBSYSTEM_COMMON,
2063291a1934SXin LI 				OPCODE_COMMON_GET_PROFILE_CONFIG,
2064291a1934SXin LI 				MBX_TIMEOUT_SEC,
2065291a1934SXin LI 				sizeof(struct mbx_common_get_profile_config),
2066291a1934SXin LI 				version);
2067291a1934SXin LI 	/* fill rest of mbx */
2068291a1934SXin LI 	mbx.u0.s.embedded = 0;
2069291a1934SXin LI 	mbx.payload_length = sizeof(struct mbx_common_get_profile_config);
2070291a1934SXin LI 	mbx.u0.s.sge_count = 1;
2071291a1934SXin LI 	sgl = &mbx.payload.u0.u1.sgl[0];
2072291a1934SXin LI 	sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
2073291a1934SXin LI 	sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
2074291a1934SXin LI 	sgl->length = htole32(mbx.payload_length);
2075291a1934SXin LI 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
2076291a1934SXin LI 
2077291a1934SXin LI 	fwcmd->params.req.type = ACTIVE_PROFILE;
2078291a1934SXin LI 
2079291a1934SXin LI 	/* command post */
2080291a1934SXin LI 	rc = oce_mbox_post(sc, &mbx, NULL);
2081291a1934SXin LI 	if (!rc)
2082291a1934SXin LI 		rc = fwcmd->hdr.u0.rsp.status;
2083291a1934SXin LI 	if (rc) {
20845fbb6830SXin LI 		device_printf(sc->dev,
20855fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
20865fbb6830SXin LI 			      __FUNCTION__, rc,
20875fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
2088291a1934SXin LI 		goto error;
2089291a1934SXin LI 	}
2090291a1934SXin LI 
2091291a1934SXin LI 	nic_desc = (struct oce_nic_resc_desc *) fwcmd->params.rsp.resources;
2092291a1934SXin LI 	desc_count = HOST_32(fwcmd->params.rsp.desc_count);
2093291a1934SXin LI 	for (i = 0; i < desc_count; i++) {
2094291a1934SXin LI 		if ((nic_desc->desc_type == NIC_RESC_DESC_TYPE_V0) ||
2095291a1934SXin LI 		    (nic_desc->desc_type == NIC_RESC_DESC_TYPE_V1)) {
2096291a1934SXin LI 			nic_desc_valid = TRUE;
2097291a1934SXin LI 			break;
2098291a1934SXin LI 		}
2099291a1934SXin LI 		nic_desc = (struct oce_nic_resc_desc *) \
2100291a1934SXin LI 				((char *)nic_desc + nic_desc->desc_len);
2101291a1934SXin LI 	}
2102291a1934SXin LI 	if (!nic_desc_valid) {
2103291a1934SXin LI 		rc = -1;
2104291a1934SXin LI 		goto error;
2105291a1934SXin LI 	}
2106291a1934SXin LI 	else {
2107b41206d8SXin LI 		sc->max_vlans = HOST_16(nic_desc->vlan_count);
2108b41206d8SXin LI 		sc->nwqs = HOST_16(nic_desc->txq_count);
2109291a1934SXin LI 		if (sc->nwqs)
2110291a1934SXin LI 			sc->nwqs = MIN(sc->nwqs, OCE_MAX_WQ);
2111291a1934SXin LI 		else
2112291a1934SXin LI 			sc->nwqs = OCE_MAX_WQ;
2113291a1934SXin LI 
2114b41206d8SXin LI 		sc->nrssqs = HOST_16(nic_desc->rssq_count);
2115b41206d8SXin LI 		if (sc->nrssqs)
2116b41206d8SXin LI 			sc->nrssqs = MIN(sc->nrssqs, max_rss);
2117b41206d8SXin LI 		else
2118b41206d8SXin LI 			sc->nrssqs = max_rss;
211974b8d63dSPedro F. Giffuni 		sc->nrqs =  sc->nrssqs + 1; /* 1 for def RX */
2120b41206d8SXin LI 
2121291a1934SXin LI 	}
2122291a1934SXin LI error:
2123291a1934SXin LI 	oce_dma_free(sc, &dma);
2124291a1934SXin LI 	return rc;
2125291a1934SXin LI 
2126291a1934SXin LI }
2127291a1934SXin LI 
2128291a1934SXin LI int
2129291a1934SXin LI oce_get_func_config(POCE_SOFTC sc)
2130291a1934SXin LI {
2131291a1934SXin LI 	struct oce_mbx mbx;
2132291a1934SXin LI 	struct mbx_common_get_func_config *fwcmd;
2133291a1934SXin LI 	int rc = 0;
2134291a1934SXin LI 	int version = 0;
2135291a1934SXin LI 	struct oce_mq_sge *sgl;
2136291a1934SXin LI 	OCE_DMA_MEM dma;
2137291a1934SXin LI 	uint32_t desc_count = 0;
2138291a1934SXin LI 	struct oce_nic_resc_desc *nic_desc = NULL;
2139291a1934SXin LI 	int i;
2140291a1934SXin LI 	boolean_t nic_desc_valid = FALSE;
2141291a1934SXin LI 	uint32_t max_rss = 0;
2142291a1934SXin LI 
2143291a1934SXin LI 	if ((IS_BE(sc) || IS_SH(sc)) && (!sc->be3_native))
2144291a1934SXin LI 		max_rss = OCE_LEGACY_MODE_RSS;
2145291a1934SXin LI 	else
2146291a1934SXin LI 		max_rss = OCE_MAX_RSS;
2147291a1934SXin LI 
2148291a1934SXin LI 	/* Allocate DMA mem*/
2149291a1934SXin LI 	if (oce_dma_alloc(sc, sizeof(struct mbx_common_get_func_config),
2150291a1934SXin LI 			  &dma, 0))
2151291a1934SXin LI 		return ENOMEM;
2152291a1934SXin LI 
2153291a1934SXin LI 	/* Initialize MODIFY_EQ_DELAY ioctl header */
2154291a1934SXin LI 	fwcmd = OCE_DMAPTR(&dma, struct mbx_common_get_func_config);
2155291a1934SXin LI 	bzero(fwcmd, sizeof(struct mbx_common_get_func_config));
2156291a1934SXin LI 
2157291a1934SXin LI 	if (IS_SH(sc))
2158291a1934SXin LI 		version = OCE_MBX_VER_V1;
2159291a1934SXin LI 	else
2160291a1934SXin LI 		version = OCE_MBX_VER_V0;
2161291a1934SXin LI 
2162291a1934SXin LI 	bzero(&mbx, sizeof(struct oce_mbx));
2163291a1934SXin LI 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
2164291a1934SXin LI 				MBX_SUBSYSTEM_COMMON,
2165291a1934SXin LI 				OPCODE_COMMON_GET_FUNCTION_CONFIG,
2166291a1934SXin LI 				MBX_TIMEOUT_SEC,
2167291a1934SXin LI 				sizeof(struct mbx_common_get_func_config),
2168291a1934SXin LI 				version);
2169291a1934SXin LI 	/* fill rest of mbx */
2170291a1934SXin LI 	mbx.u0.s.embedded = 0;
2171291a1934SXin LI 	mbx.payload_length = sizeof(struct mbx_common_get_func_config);
2172291a1934SXin LI 	mbx.u0.s.sge_count = 1;
2173291a1934SXin LI 	sgl = &mbx.payload.u0.u1.sgl[0];
2174291a1934SXin LI 	sgl->pa_hi = htole32(upper_32_bits(dma.paddr));
2175291a1934SXin LI 	sgl->pa_lo = htole32((dma.paddr) & 0xFFFFFFFF);
2176291a1934SXin LI 	sgl->length = htole32(mbx.payload_length);
2177291a1934SXin LI 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
2178291a1934SXin LI 
2179291a1934SXin LI 	/* command post */
2180291a1934SXin LI 	rc = oce_mbox_post(sc, &mbx, NULL);
2181291a1934SXin LI 	if (!rc)
2182291a1934SXin LI 		rc = fwcmd->hdr.u0.rsp.status;
2183291a1934SXin LI 	if (rc) {
21845fbb6830SXin LI 		device_printf(sc->dev,
21855fbb6830SXin LI 			      "%s failed - cmd status: %d addi status: %d\n",
21865fbb6830SXin LI 			      __FUNCTION__, rc,
21875fbb6830SXin LI 			      fwcmd->hdr.u0.rsp.additional_status);
2188291a1934SXin LI 		goto error;
2189291a1934SXin LI 	}
2190291a1934SXin LI 
2191291a1934SXin LI 	nic_desc = (struct oce_nic_resc_desc *) fwcmd->params.rsp.resources;
2192291a1934SXin LI 	desc_count = HOST_32(fwcmd->params.rsp.desc_count);
2193291a1934SXin LI 	for (i = 0; i < desc_count; i++) {
2194291a1934SXin LI 		if ((nic_desc->desc_type == NIC_RESC_DESC_TYPE_V0) ||
2195291a1934SXin LI 		    (nic_desc->desc_type == NIC_RESC_DESC_TYPE_V1)) {
2196291a1934SXin LI 			nic_desc_valid = TRUE;
2197291a1934SXin LI 			break;
2198291a1934SXin LI 		}
2199291a1934SXin LI 		nic_desc = (struct oce_nic_resc_desc *) \
2200291a1934SXin LI 				((char *)nic_desc + nic_desc->desc_len);
2201291a1934SXin LI 	}
2202291a1934SXin LI 	if (!nic_desc_valid) {
2203291a1934SXin LI 		rc = -1;
2204291a1934SXin LI 		goto error;
2205291a1934SXin LI 	}
2206291a1934SXin LI 	else {
22075fbb6830SXin LI 		sc->max_vlans = nic_desc->vlan_count;
2208291a1934SXin LI 		sc->nwqs = HOST_32(nic_desc->txq_count);
2209291a1934SXin LI                 if (sc->nwqs)
2210291a1934SXin LI                         sc->nwqs = MIN(sc->nwqs, OCE_MAX_WQ);
2211291a1934SXin LI                 else
2212291a1934SXin LI                         sc->nwqs = OCE_MAX_WQ;
2213291a1934SXin LI 
2214291a1934SXin LI 		sc->nrssqs = HOST_32(nic_desc->rssq_count);
2215291a1934SXin LI 		if (sc->nrssqs)
2216291a1934SXin LI 			sc->nrssqs = MIN(sc->nrssqs, max_rss);
2217291a1934SXin LI 		else
2218291a1934SXin LI 			sc->nrssqs = max_rss;
221974b8d63dSPedro F. Giffuni 		sc->nrqs =  sc->nrssqs + 1; /* 1 for def RX */
2220291a1934SXin LI 	}
2221291a1934SXin LI error:
2222291a1934SXin LI 	oce_dma_free(sc, &dma);
2223291a1934SXin LI 	return rc;
2224291a1934SXin LI 
2225291a1934SXin LI }
2226c2625e6eSJosh Paetzel 
2227c2625e6eSJosh Paetzel /* hw lro functions */
2228c2625e6eSJosh Paetzel 
2229c2625e6eSJosh Paetzel int
2230c2625e6eSJosh Paetzel oce_mbox_nic_query_lro_capabilities(POCE_SOFTC sc, uint32_t *lro_rq_cnt, uint32_t *lro_flags)
2231c2625e6eSJosh Paetzel {
2232c2625e6eSJosh Paetzel         struct oce_mbx mbx;
2233c2625e6eSJosh Paetzel         struct mbx_nic_query_lro_capabilities *fwcmd;
2234c2625e6eSJosh Paetzel         int rc = 0;
2235c2625e6eSJosh Paetzel 
2236c2625e6eSJosh Paetzel         bzero(&mbx, sizeof(struct oce_mbx));
2237c2625e6eSJosh Paetzel 
2238c2625e6eSJosh Paetzel         fwcmd = (struct mbx_nic_query_lro_capabilities *)&mbx.payload;
2239c2625e6eSJosh Paetzel         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
2240c2625e6eSJosh Paetzel                                 MBX_SUBSYSTEM_NIC,
2241c2625e6eSJosh Paetzel                                 0x20,MBX_TIMEOUT_SEC,
2242c2625e6eSJosh Paetzel                                 sizeof(struct mbx_nic_query_lro_capabilities),
2243c2625e6eSJosh Paetzel                                 OCE_MBX_VER_V0);
2244c2625e6eSJosh Paetzel 
2245c2625e6eSJosh Paetzel         mbx.u0.s.embedded = 1;
2246c2625e6eSJosh Paetzel         mbx.payload_length = sizeof(struct mbx_nic_query_lro_capabilities);
2247c2625e6eSJosh Paetzel 
2248c2625e6eSJosh Paetzel         rc = oce_mbox_post(sc, &mbx, NULL);
2249c2625e6eSJosh Paetzel         if (!rc)
2250c2625e6eSJosh Paetzel                 rc = fwcmd->hdr.u0.rsp.status;
2251c2625e6eSJosh Paetzel         if (rc) {
2252c2625e6eSJosh Paetzel                 device_printf(sc->dev,
2253c2625e6eSJosh Paetzel                               "%s failed - cmd status: %d addi status: %d\n",
2254c2625e6eSJosh Paetzel                               __FUNCTION__, rc,
2255c2625e6eSJosh Paetzel                               fwcmd->hdr.u0.rsp.additional_status);
2256c2625e6eSJosh Paetzel 
2257c2625e6eSJosh Paetzel                 return rc;
2258c2625e6eSJosh Paetzel         }
2259c2625e6eSJosh Paetzel         if(lro_flags)
2260c2625e6eSJosh Paetzel                 *lro_flags = HOST_32(fwcmd->params.rsp.lro_flags);
2261c2625e6eSJosh Paetzel 
2262c2625e6eSJosh Paetzel         if(lro_rq_cnt)
2263c2625e6eSJosh Paetzel                 *lro_rq_cnt = HOST_16(fwcmd->params.rsp.lro_rq_cnt);
2264c2625e6eSJosh Paetzel 
2265c2625e6eSJosh Paetzel         return rc;
2266c2625e6eSJosh Paetzel }
2267c2625e6eSJosh Paetzel 
2268c2625e6eSJosh Paetzel int
2269c2625e6eSJosh Paetzel oce_mbox_nic_set_iface_lro_config(POCE_SOFTC sc, int enable)
2270c2625e6eSJosh Paetzel {
2271c2625e6eSJosh Paetzel         struct oce_mbx mbx;
2272c2625e6eSJosh Paetzel         struct mbx_nic_set_iface_lro_config *fwcmd;
2273c2625e6eSJosh Paetzel         int rc = 0;
2274c2625e6eSJosh Paetzel 
2275c2625e6eSJosh Paetzel         bzero(&mbx, sizeof(struct oce_mbx));
2276c2625e6eSJosh Paetzel 
2277c2625e6eSJosh Paetzel         fwcmd = (struct mbx_nic_set_iface_lro_config *)&mbx.payload;
2278c2625e6eSJosh Paetzel         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
2279c2625e6eSJosh Paetzel                                 MBX_SUBSYSTEM_NIC,
2280c2625e6eSJosh Paetzel                                 0x26,MBX_TIMEOUT_SEC,
2281c2625e6eSJosh Paetzel                                 sizeof(struct mbx_nic_set_iface_lro_config),
2282c2625e6eSJosh Paetzel                                 OCE_MBX_VER_V0);
2283c2625e6eSJosh Paetzel 
2284c2625e6eSJosh Paetzel         mbx.u0.s.embedded = 1;
2285c2625e6eSJosh Paetzel         mbx.payload_length = sizeof(struct mbx_nic_set_iface_lro_config);
2286c2625e6eSJosh Paetzel 
2287c2625e6eSJosh Paetzel         fwcmd->params.req.iface_id = sc->if_id;
2288c2625e6eSJosh Paetzel         fwcmd->params.req.lro_flags = 0;
2289c2625e6eSJosh Paetzel 
2290c2625e6eSJosh Paetzel         if(enable) {
2291c2625e6eSJosh Paetzel                 fwcmd->params.req.lro_flags = LRO_FLAGS_HASH_MODE | LRO_FLAGS_RSS_MODE;
2292c2625e6eSJosh Paetzel                 fwcmd->params.req.lro_flags |= LRO_FLAGS_CLSC_IPV4 | LRO_FLAGS_CLSC_IPV6;
2293c2625e6eSJosh Paetzel 
2294c2625e6eSJosh Paetzel                 fwcmd->params.req.max_clsc_byte_cnt = 64*1024; /* min = 2974, max = 0xfa59 */
2295c2625e6eSJosh Paetzel                 fwcmd->params.req.max_clsc_seg_cnt = 43; /* min = 2, max = 64 */
2296c2625e6eSJosh Paetzel                 fwcmd->params.req.max_clsc_usec_delay = 18; /* min = 1, max = 256 */
2297c2625e6eSJosh Paetzel                 fwcmd->params.req.min_clsc_frame_byte_cnt = 0; /* min = 1, max = 9014 */
2298c2625e6eSJosh Paetzel         }
2299c2625e6eSJosh Paetzel 
2300c2625e6eSJosh Paetzel         rc = oce_mbox_post(sc, &mbx, NULL);
2301c2625e6eSJosh Paetzel         if (!rc)
2302c2625e6eSJosh Paetzel                 rc = fwcmd->hdr.u0.rsp.status;
2303c2625e6eSJosh Paetzel         if (rc) {
2304c2625e6eSJosh Paetzel                 device_printf(sc->dev,
2305c2625e6eSJosh Paetzel                               "%s failed - cmd status: %d addi status: %d\n",
2306c2625e6eSJosh Paetzel                               __FUNCTION__, rc,
2307c2625e6eSJosh Paetzel                               fwcmd->hdr.u0.rsp.additional_status);
2308c2625e6eSJosh Paetzel 
2309c2625e6eSJosh Paetzel                 return rc;
2310c2625e6eSJosh Paetzel         }
2311c2625e6eSJosh Paetzel         return rc;
2312c2625e6eSJosh Paetzel }
2313c2625e6eSJosh Paetzel 
2314c2625e6eSJosh Paetzel int
2315c2625e6eSJosh Paetzel oce_mbox_create_rq_v2(struct oce_rq *rq)
2316c2625e6eSJosh Paetzel {
2317c2625e6eSJosh Paetzel         struct oce_mbx mbx;
2318c2625e6eSJosh Paetzel         struct mbx_create_nic_rq_v2 *fwcmd;
2319c2625e6eSJosh Paetzel         POCE_SOFTC sc = rq->parent;
2320c2625e6eSJosh Paetzel         int rc = 0, num_pages = 0;
2321c2625e6eSJosh Paetzel 
2322c2625e6eSJosh Paetzel         if (rq->qstate == QCREATED)
2323c2625e6eSJosh Paetzel                 return 0;
2324c2625e6eSJosh Paetzel 
2325c2625e6eSJosh Paetzel         bzero(&mbx, sizeof(struct oce_mbx));
2326c2625e6eSJosh Paetzel 
2327c2625e6eSJosh Paetzel         fwcmd = (struct mbx_create_nic_rq_v2 *)&mbx.payload;
2328c2625e6eSJosh Paetzel         mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
2329c2625e6eSJosh Paetzel                                 MBX_SUBSYSTEM_NIC,
2330c2625e6eSJosh Paetzel                                 0x08, MBX_TIMEOUT_SEC,
2331c2625e6eSJosh Paetzel                                 sizeof(struct mbx_create_nic_rq_v2),
2332c2625e6eSJosh Paetzel                                 OCE_MBX_VER_V2);
2333c2625e6eSJosh Paetzel 
2334c2625e6eSJosh Paetzel         /* oce_page_list will also prepare pages */
2335c2625e6eSJosh Paetzel         num_pages = oce_page_list(rq->ring, &fwcmd->params.req.pages[0]);
2336c2625e6eSJosh Paetzel 
2337c2625e6eSJosh Paetzel         fwcmd->params.req.cq_id = rq->cq->cq_id;
2338c2625e6eSJosh Paetzel         fwcmd->params.req.frag_size = rq->cfg.frag_size/2048;
2339c2625e6eSJosh Paetzel         fwcmd->params.req.num_pages = num_pages;
2340c2625e6eSJosh Paetzel 
2341c2625e6eSJosh Paetzel         fwcmd->params.req.if_id = sc->if_id;
2342c2625e6eSJosh Paetzel 
2343c2625e6eSJosh Paetzel         fwcmd->params.req.max_frame_size = rq->cfg.mtu;
2344c2625e6eSJosh Paetzel         fwcmd->params.req.page_size = 1;
2345c2625e6eSJosh Paetzel         if(rq->cfg.is_rss_queue) {
2346c2625e6eSJosh Paetzel                 fwcmd->params.req.rq_flags = (NIC_RQ_FLAGS_RSS | NIC_RQ_FLAGS_LRO);
2347c2625e6eSJosh Paetzel         }else {
2348c2625e6eSJosh Paetzel                 device_printf(sc->dev,
2349c2625e6eSJosh Paetzel                         "non rss lro queue should not be created \n");
2350c2625e6eSJosh Paetzel                 goto error;
2351c2625e6eSJosh Paetzel         }
2352c2625e6eSJosh Paetzel         mbx.u0.s.embedded = 1;
2353c2625e6eSJosh Paetzel         mbx.payload_length = sizeof(struct mbx_create_nic_rq_v2);
2354c2625e6eSJosh Paetzel 
2355c2625e6eSJosh Paetzel         rc = oce_mbox_post(sc, &mbx, NULL);
2356c2625e6eSJosh Paetzel         if (!rc)
2357c2625e6eSJosh Paetzel                 rc = fwcmd->hdr.u0.rsp.status;
2358c2625e6eSJosh Paetzel         if (rc) {
2359c2625e6eSJosh Paetzel                 device_printf(sc->dev,
2360c2625e6eSJosh Paetzel                               "%s failed - cmd status: %d addi status: %d\n",
2361c2625e6eSJosh Paetzel                               __FUNCTION__, rc,
2362c2625e6eSJosh Paetzel                               fwcmd->hdr.u0.rsp.additional_status);
2363c2625e6eSJosh Paetzel                 goto error;
2364c2625e6eSJosh Paetzel         }
2365c2625e6eSJosh Paetzel         rq->rq_id = HOST_16(fwcmd->params.rsp.rq_id);
2366c2625e6eSJosh Paetzel         rq->rss_cpuid = fwcmd->params.rsp.rss_cpuid;
2367c2625e6eSJosh Paetzel 
2368c2625e6eSJosh Paetzel error:
2369c2625e6eSJosh Paetzel         return rc;
2370c2625e6eSJosh Paetzel }
2371c2625e6eSJosh Paetzel 
2372