14d0e5007SSukumar Swaminathan /*
24d0e5007SSukumar Swaminathan  * CDDL HEADER START
34d0e5007SSukumar Swaminathan  *
44d0e5007SSukumar Swaminathan  * The contents of this file are subject to the terms of the
54d0e5007SSukumar Swaminathan  * Common Development and Distribution License (the "License").
64d0e5007SSukumar Swaminathan  * You may not use this file except in compliance with the License.
74d0e5007SSukumar Swaminathan  *
84d0e5007SSukumar Swaminathan  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
94d0e5007SSukumar Swaminathan  * or http://www.opensolaris.org/os/licensing.
104d0e5007SSukumar Swaminathan  * See the License for the specific language governing permissions
114d0e5007SSukumar Swaminathan  * and limitations under the License.
124d0e5007SSukumar Swaminathan  *
134d0e5007SSukumar Swaminathan  * When distributing Covered Code, include this CDDL HEADER in each
144d0e5007SSukumar Swaminathan  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
154d0e5007SSukumar Swaminathan  * If applicable, add the following below this CDDL HEADER, with the
164d0e5007SSukumar Swaminathan  * fields enclosed by brackets "[]" replaced with your own identifying
174d0e5007SSukumar Swaminathan  * information: Portions Copyright [yyyy] [name of copyright owner]
184d0e5007SSukumar Swaminathan  *
194d0e5007SSukumar Swaminathan  * CDDL HEADER END
204d0e5007SSukumar Swaminathan  */
214d0e5007SSukumar Swaminathan 
223abb112fSGarrett D'Amore /* Copyright © 2003-2011 Emulex. All rights reserved.  */
233abb112fSGarrett D'Amore 
24*15c07adcSJohn Levon /*
25*15c07adcSJohn Levon  * Copyright (c) 2018, Joyent, Inc.
26*15c07adcSJohn Levon  */
274d0e5007SSukumar Swaminathan 
284d0e5007SSukumar Swaminathan /*
294d0e5007SSukumar Swaminathan  * Source file containing the implementation of MBOX
304d0e5007SSukumar Swaminathan  * and related helper functions
314d0e5007SSukumar Swaminathan  */
324d0e5007SSukumar Swaminathan 
334d0e5007SSukumar Swaminathan #include <oce_impl.h>
344d0e5007SSukumar Swaminathan 
354d0e5007SSukumar Swaminathan static ddi_dma_attr_t oce_sgl_dma_attr = {
364d0e5007SSukumar Swaminathan 	DMA_ATTR_V0,		/* version number */
374d0e5007SSukumar Swaminathan 	0x0000000000000000ull,	/* low address */
384d0e5007SSukumar Swaminathan 	0xFFFFFFFFFFFFFFFFull,	/* high address */
394d0e5007SSukumar Swaminathan 	0x0000000000010000ull,	/* dma counter max */
404d0e5007SSukumar Swaminathan 	0x1000,			/* alignment 4K for mbx bufs */
414d0e5007SSukumar Swaminathan 	0x1,			/* burst sizes */
424d0e5007SSukumar Swaminathan 	0x00000004,		/* minimum transfer size */
434d0e5007SSukumar Swaminathan 	0x00000000FFFFFFFFull,	/* maximum transfer size */
444d0e5007SSukumar Swaminathan 	0xFFFFFFFFFFFFFFFFull,	/* maximum segment size */
454d0e5007SSukumar Swaminathan 	MAX_MBX_SGE,		/* scatter/gather list length */
464d0e5007SSukumar Swaminathan 	0x00000001,		/* granularity */
474d0e5007SSukumar Swaminathan 	0			/* DMA flags */
484d0e5007SSukumar Swaminathan };
494d0e5007SSukumar Swaminathan 
504d0e5007SSukumar Swaminathan static ddi_device_acc_attr_t oce_sgl_buf_accattr = {
514d0e5007SSukumar Swaminathan 	DDI_DEVICE_ATTR_V0,
524d0e5007SSukumar Swaminathan 	DDI_NEVERSWAP_ACC,
534d0e5007SSukumar Swaminathan 	DDI_STRICTORDER_ACC,
544d0e5007SSukumar Swaminathan };
554d0e5007SSukumar Swaminathan 
564d0e5007SSukumar Swaminathan /*
574d0e5007SSukumar Swaminathan  * common inline function to fill an ioctl request header
584d0e5007SSukumar Swaminathan  *
594d0e5007SSukumar Swaminathan  * hdr - pointer to a buffer where the header will be initialized
604d0e5007SSukumar Swaminathan  * dom - domain
614d0e5007SSukumar Swaminathan  * port - port number
624d0e5007SSukumar Swaminathan  * opcode - command code for this MBX
634d0e5007SSukumar Swaminathan  * timeout - timeout in seconds
644d0e5007SSukumar Swaminathan  * pyld_len - length of the command buffer described by this header
654d0e5007SSukumar Swaminathan  *
664d0e5007SSukumar Swaminathan  * return none
674d0e5007SSukumar Swaminathan  */
684d0e5007SSukumar Swaminathan void
mbx_common_req_hdr_init(struct mbx_hdr * hdr,uint8_t dom,uint8_t port,uint8_t subsys,uint8_t opcode,uint32_t timeout,uint32_t pyld_len)694d0e5007SSukumar Swaminathan mbx_common_req_hdr_init(struct mbx_hdr *hdr,
704d0e5007SSukumar Swaminathan     uint8_t dom, uint8_t port,
714d0e5007SSukumar Swaminathan     uint8_t subsys, uint8_t opcode,
724d0e5007SSukumar Swaminathan     uint32_t timeout, uint32_t pyld_len)
734d0e5007SSukumar Swaminathan {
744d0e5007SSukumar Swaminathan 	ASSERT(hdr != NULL);
754d0e5007SSukumar Swaminathan 
764d0e5007SSukumar Swaminathan 	hdr->u0.req.opcode = opcode;
774d0e5007SSukumar Swaminathan 	hdr->u0.req.subsystem = subsys;
784d0e5007SSukumar Swaminathan 	hdr->u0.req.port_number = port;
794d0e5007SSukumar Swaminathan 	hdr->u0.req.domain = dom;
804d0e5007SSukumar Swaminathan 
814d0e5007SSukumar Swaminathan 	hdr->u0.req.timeout = timeout;
824d0e5007SSukumar Swaminathan 	hdr->u0.req.request_length = pyld_len - sizeof (struct mbx_hdr);
835b9d3151SSukumar Swaminathan 	hdr->u0.req.rsvd0 = 0;
844d0e5007SSukumar Swaminathan } /* mbx_common_req_hdr_init */
854d0e5007SSukumar Swaminathan 
864d0e5007SSukumar Swaminathan /*
874d0e5007SSukumar Swaminathan  * function to initialize the hw with host endian information
884d0e5007SSukumar Swaminathan  *
894d0e5007SSukumar Swaminathan  * dev - software handle to the device
904d0e5007SSukumar Swaminathan  *
914d0e5007SSukumar Swaminathan  * return 0 on success, ETIMEDOUT on failure
924d0e5007SSukumar Swaminathan  */
934d0e5007SSukumar Swaminathan int
oce_mbox_init(struct oce_dev * dev)944d0e5007SSukumar Swaminathan oce_mbox_init(struct oce_dev *dev)
954d0e5007SSukumar Swaminathan {
964d0e5007SSukumar Swaminathan 	struct oce_bmbx *mbx;
974d0e5007SSukumar Swaminathan 	uint8_t *ptr;
984d0e5007SSukumar Swaminathan 	int ret = 0;
994d0e5007SSukumar Swaminathan 
1004d0e5007SSukumar Swaminathan 	ASSERT(dev != NULL);
1014d0e5007SSukumar Swaminathan 
1024d0e5007SSukumar Swaminathan 	mbx = (struct oce_bmbx *)DBUF_VA(dev->bmbx);
1034d0e5007SSukumar Swaminathan 	ptr = (uint8_t *)&mbx->mbx;
1044d0e5007SSukumar Swaminathan 
1054d0e5007SSukumar Swaminathan 	/* Endian Signature */
1064d0e5007SSukumar Swaminathan 	*ptr++ = 0xff;
1074d0e5007SSukumar Swaminathan 	*ptr++ = 0x12;
1084d0e5007SSukumar Swaminathan 	*ptr++ = 0x34;
1094d0e5007SSukumar Swaminathan 	*ptr++ = 0xff;
1104d0e5007SSukumar Swaminathan 	*ptr++ = 0xff;
1114d0e5007SSukumar Swaminathan 	*ptr++ = 0x56;
1124d0e5007SSukumar Swaminathan 	*ptr++ = 0x78;
1134d0e5007SSukumar Swaminathan 	*ptr   = 0xff;
1144d0e5007SSukumar Swaminathan 
1154d0e5007SSukumar Swaminathan 	ret = oce_mbox_dispatch(dev, 0);
11612d61dabSSukumar Swaminathan 
1174d0e5007SSukumar Swaminathan 	if (ret != 0)
1184d0e5007SSukumar Swaminathan 		oce_log(dev, CE_NOTE, MOD_CONFIG,
1194d0e5007SSukumar Swaminathan 		    "Failed to set endian %d", ret);
1204d0e5007SSukumar Swaminathan 
1214d0e5007SSukumar Swaminathan 	return (ret);
1224d0e5007SSukumar Swaminathan } /* oce_mbox_init */
1234d0e5007SSukumar Swaminathan 
1244d0e5007SSukumar Swaminathan /*
1254d0e5007SSukumar Swaminathan  * function to wait till we get a mbox ready after writing to the
1264d0e5007SSukumar Swaminathan  * mbox doorbell
1274d0e5007SSukumar Swaminathan  *
1284d0e5007SSukumar Swaminathan  * dev - software handle to the device
1294d0e5007SSukumar Swaminathan  *
1304d0e5007SSukumar Swaminathan  * return 0=ready, ETIMEDOUT=>not ready but timed out
1314d0e5007SSukumar Swaminathan  */
1324d0e5007SSukumar Swaminathan int
oce_mbox_wait(struct oce_dev * dev,uint32_t tmo_sec)1334d0e5007SSukumar Swaminathan oce_mbox_wait(struct oce_dev *dev, uint32_t tmo_sec)
1344d0e5007SSukumar Swaminathan {
1358d738d7dSSukumar Swaminathan 	clock_t tmo;
1364d0e5007SSukumar Swaminathan 	clock_t now, tstamp;
1374d0e5007SSukumar Swaminathan 	pd_mpu_mbox_db_t mbox_db;
1384d0e5007SSukumar Swaminathan 
1398d738d7dSSukumar Swaminathan 	tmo = (tmo_sec > 0) ? drv_usectohz(tmo_sec * 1000000) :
1408d738d7dSSukumar Swaminathan 	    drv_usectohz(DEFAULT_MQ_MBOX_TIMEOUT);
1418d738d7dSSukumar Swaminathan 
1423abb112fSGarrett D'Amore 	/* Add the default timeout to wait for a mailbox to complete */
1433abb112fSGarrett D'Amore 	tmo += drv_usectohz(MBX_READY_TIMEOUT);
1443abb112fSGarrett D'Amore 
1454d0e5007SSukumar Swaminathan 	tstamp = ddi_get_lbolt();
14612d61dabSSukumar Swaminathan 	for (;;) {
1474d0e5007SSukumar Swaminathan 		now = ddi_get_lbolt();
1484d0e5007SSukumar Swaminathan 		if ((now - tstamp) >= tmo) {
1494d0e5007SSukumar Swaminathan 			tmo = 0;
1504d0e5007SSukumar Swaminathan 			break;
1514d0e5007SSukumar Swaminathan 		}
1524d0e5007SSukumar Swaminathan 
1534d0e5007SSukumar Swaminathan 		mbox_db.dw0 = OCE_DB_READ32(dev, PD_MPU_MBOX_DB);
15412d61dabSSukumar Swaminathan 		if (oce_fm_check_acc_handle(dev, dev->db_handle) != DDI_FM_OK) {
15512d61dabSSukumar Swaminathan 			ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
15612d61dabSSukumar Swaminathan 			oce_fm_ereport(dev, DDI_FM_DEVICE_INVAL_STATE);
15712d61dabSSukumar Swaminathan 		}
15812d61dabSSukumar Swaminathan 
15912d61dabSSukumar Swaminathan 		if (mbox_db.bits.ready) {
16012d61dabSSukumar Swaminathan 			return (0);
16112d61dabSSukumar Swaminathan 		}
162*15c07adcSJohn Levon 		drv_usecwait(5);
16312d61dabSSukumar Swaminathan 	}
1644d0e5007SSukumar Swaminathan 
16512d61dabSSukumar Swaminathan 	return (ETIMEDOUT);
1664d0e5007SSukumar Swaminathan } /* oce_mbox_wait */
1674d0e5007SSukumar Swaminathan 
1684d0e5007SSukumar Swaminathan /*
1694d0e5007SSukumar Swaminathan  * function to dispatch a mailbox command present in the mq mbox
1704d0e5007SSukumar Swaminathan  *
1714d0e5007SSukumar Swaminathan  * dev - software handle to the device
1724d0e5007SSukumar Swaminathan  *
1734d0e5007SSukumar Swaminathan  * return 0 on success, ETIMEDOUT on failure
1744d0e5007SSukumar Swaminathan  */
1754d0e5007SSukumar Swaminathan int
oce_mbox_dispatch(struct oce_dev * dev,uint32_t tmo_sec)1764d0e5007SSukumar Swaminathan oce_mbox_dispatch(struct oce_dev *dev, uint32_t tmo_sec)
1774d0e5007SSukumar Swaminathan {
1784d0e5007SSukumar Swaminathan 	pd_mpu_mbox_db_t mbox_db;
1794d0e5007SSukumar Swaminathan 	uint32_t pa;
1804d0e5007SSukumar Swaminathan 	int ret;
1814d0e5007SSukumar Swaminathan 
18212d61dabSSukumar Swaminathan 	/* sync the bmbx */
18312d61dabSSukumar Swaminathan 	(void) DBUF_SYNC(dev->bmbx, DDI_DMA_SYNC_FORDEV);
18412d61dabSSukumar Swaminathan 
1854d0e5007SSukumar Swaminathan 	/* write 30 bits of address hi dword */
1864d0e5007SSukumar Swaminathan 	pa = (uint32_t)(DBUF_PA(dev->bmbx) >> 34);
1878d738d7dSSukumar Swaminathan 	bzero(&mbox_db, sizeof (pd_mpu_mbox_db_t));
1884d0e5007SSukumar Swaminathan 	mbox_db.bits.ready = 0;
1894d0e5007SSukumar Swaminathan 	mbox_db.bits.hi = 1;
1904d0e5007SSukumar Swaminathan 	mbox_db.bits.address = pa;
1914d0e5007SSukumar Swaminathan 
1924d0e5007SSukumar Swaminathan 	/* wait for mbox ready */
1934d0e5007SSukumar Swaminathan 	ret = oce_mbox_wait(dev, tmo_sec);
1944d0e5007SSukumar Swaminathan 	if (ret != 0) {
1954d0e5007SSukumar Swaminathan 		return (ret);
1964d0e5007SSukumar Swaminathan 	}
1974d0e5007SSukumar Swaminathan 
1984d0e5007SSukumar Swaminathan 	/* ring the doorbell */
1994d0e5007SSukumar Swaminathan 	OCE_DB_WRITE32(dev, PD_MPU_MBOX_DB, mbox_db.dw0);
2004d0e5007SSukumar Swaminathan 
20112d61dabSSukumar Swaminathan 	if (oce_fm_check_acc_handle(dev, dev->db_handle) != DDI_FM_OK) {
20212d61dabSSukumar Swaminathan 		ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
20312d61dabSSukumar Swaminathan 	}
20412d61dabSSukumar Swaminathan 
2054d0e5007SSukumar Swaminathan 	/* wait for mbox ready */
2064d0e5007SSukumar Swaminathan 	ret = oce_mbox_wait(dev, tmo_sec);
2074d0e5007SSukumar Swaminathan 	if (ret != 0) {
2088d738d7dSSukumar Swaminathan 		oce_log(dev, CE_NOTE, MOD_CONFIG,
2098d738d7dSSukumar Swaminathan 		    "BMBX TIMED OUT PROGRAMMING HI ADDR: %d", ret);
2108d738d7dSSukumar Swaminathan 		/* if mbx times out, hw is in invalid state */
2118d738d7dSSukumar Swaminathan 		ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
2128d738d7dSSukumar Swaminathan 		oce_fm_ereport(dev, DDI_FM_DEVICE_INVAL_STATE);
2134d0e5007SSukumar Swaminathan 		return (ret);
2144d0e5007SSukumar Swaminathan 	}
2154d0e5007SSukumar Swaminathan 
2164d0e5007SSukumar Swaminathan 	/* now write 30 bits of address lo dword */
2174d0e5007SSukumar Swaminathan 	pa = (uint32_t)(DBUF_PA(dev->bmbx) >> 4) & 0x3fffffff;
2184d0e5007SSukumar Swaminathan 	mbox_db.bits.ready = 0;
2194d0e5007SSukumar Swaminathan 	mbox_db.bits.hi = 0;
2204d0e5007SSukumar Swaminathan 	mbox_db.bits.address = pa;
2214d0e5007SSukumar Swaminathan 
2224d0e5007SSukumar Swaminathan 	/* ring the doorbell */
2234d0e5007SSukumar Swaminathan 	OCE_DB_WRITE32(dev, PD_MPU_MBOX_DB, mbox_db.dw0);
22412d61dabSSukumar Swaminathan 	if (oce_fm_check_acc_handle(dev, dev->db_handle) != DDI_FM_OK) {
22512d61dabSSukumar Swaminathan 		ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
22612d61dabSSukumar Swaminathan 	}
2274d0e5007SSukumar Swaminathan 
2284d0e5007SSukumar Swaminathan 	/* wait for mbox ready */
2294d0e5007SSukumar Swaminathan 	ret = oce_mbox_wait(dev, tmo_sec);
23012d61dabSSukumar Swaminathan 	/* sync */
23112d61dabSSukumar Swaminathan 	(void) ddi_dma_sync(DBUF_DHDL(dev->bmbx), 0, 0,
23212d61dabSSukumar Swaminathan 	    DDI_DMA_SYNC_FORKERNEL);
23312d61dabSSukumar Swaminathan 	if (oce_fm_check_dma_handle(dev, DBUF_DHDL(dev->bmbx)) != DDI_FM_OK) {
2344d0e5007SSukumar Swaminathan 		ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
23512d61dabSSukumar Swaminathan 		return (EIO);
2364d0e5007SSukumar Swaminathan 	}
2374d0e5007SSukumar Swaminathan 	return (ret);
2384d0e5007SSukumar Swaminathan } /* oce_mbox_dispatch */
2394d0e5007SSukumar Swaminathan 
2404d0e5007SSukumar Swaminathan /*
2414d0e5007SSukumar Swaminathan  * function to post a MBX to the mbox
2424d0e5007SSukumar Swaminathan  *
2434d0e5007SSukumar Swaminathan  * dev - software handle to the device
2444d0e5007SSukumar Swaminathan  * mbx - pointer to the MBX to send
2454d0e5007SSukumar Swaminathan  * mbxctx - pointer to the mbx context structure
2464d0e5007SSukumar Swaminathan  *
2474d0e5007SSukumar Swaminathan  * return 0 on success, ETIMEDOUT on failure
2484d0e5007SSukumar Swaminathan  */
2494d0e5007SSukumar Swaminathan int
oce_mbox_post(struct oce_dev * dev,struct oce_mbx * mbx,struct oce_mbx_ctx * mbxctx)2504d0e5007SSukumar Swaminathan oce_mbox_post(struct oce_dev *dev, struct oce_mbx *mbx,
2514d0e5007SSukumar Swaminathan     struct oce_mbx_ctx *mbxctx)
2524d0e5007SSukumar Swaminathan {
2534d0e5007SSukumar Swaminathan 	struct oce_mbx *mb_mbx = NULL;
2544d0e5007SSukumar Swaminathan 	struct oce_mq_cqe *mb_cqe = NULL;
2554d0e5007SSukumar Swaminathan 	struct oce_bmbx *mb = NULL;
2564d0e5007SSukumar Swaminathan 	int ret = 0;
2574d0e5007SSukumar Swaminathan 	uint32_t tmo = 0;
2584d0e5007SSukumar Swaminathan 
2594d0e5007SSukumar Swaminathan 	mutex_enter(&dev->bmbx_lock);
2604d0e5007SSukumar Swaminathan 
2614d0e5007SSukumar Swaminathan 	mb = (struct oce_bmbx *)DBUF_VA(dev->bmbx);
2624d0e5007SSukumar Swaminathan 	mb_mbx = &mb->mbx;
2634d0e5007SSukumar Swaminathan 
2644d0e5007SSukumar Swaminathan 	/* get the tmo */
2654d0e5007SSukumar Swaminathan 	tmo = mbx->tag[0];
2664d0e5007SSukumar Swaminathan 	mbx->tag[0] = 0;
2674d0e5007SSukumar Swaminathan 
2684d0e5007SSukumar Swaminathan 	/* copy mbx into mbox */
2694d0e5007SSukumar Swaminathan 	bcopy(mbx, mb_mbx, sizeof (struct oce_mbx));
2704d0e5007SSukumar Swaminathan 
2714d0e5007SSukumar Swaminathan 	/* now dispatch */
2724d0e5007SSukumar Swaminathan 	ret = oce_mbox_dispatch(dev, tmo);
2734d0e5007SSukumar Swaminathan 	if (ret != 0) {
274965eec0dSSukumar Swaminathan 		mutex_exit(&dev->bmbx_lock);
2754d0e5007SSukumar Swaminathan 		return (ret);
2764d0e5007SSukumar Swaminathan 	}
2774d0e5007SSukumar Swaminathan 
2784d0e5007SSukumar Swaminathan 	/* sync */
27912d61dabSSukumar Swaminathan 
2804d0e5007SSukumar Swaminathan 	(void) ddi_dma_sync(DBUF_DHDL(dev->bmbx), 0, 0,
2814d0e5007SSukumar Swaminathan 	    DDI_DMA_SYNC_FORKERNEL);
2824d0e5007SSukumar Swaminathan 	ret = oce_fm_check_dma_handle(dev, DBUF_DHDL(dev->bmbx));
2834d0e5007SSukumar Swaminathan 	if (ret != DDI_FM_OK) {
2844d0e5007SSukumar Swaminathan 		ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
2854d0e5007SSukumar Swaminathan 		mutex_exit(&dev->bmbx_lock);
2864d0e5007SSukumar Swaminathan 		return (EIO);
2874d0e5007SSukumar Swaminathan 	}
2884d0e5007SSukumar Swaminathan 
2894d0e5007SSukumar Swaminathan 	/*
2904d0e5007SSukumar Swaminathan 	 * the command completed successfully. Now get the
2914d0e5007SSukumar Swaminathan 	 * completion queue entry
2924d0e5007SSukumar Swaminathan 	 */
2934d0e5007SSukumar Swaminathan 	mb_cqe = &mb->cqe;
2944d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mb_cqe->u0.dw[0]), sizeof (struct oce_mq_cqe));
2954d0e5007SSukumar Swaminathan 
2963abb112fSGarrett D'Amore 	/* copy mbox mbx back */
2973abb112fSGarrett D'Amore 	bcopy(mb_mbx, mbx, sizeof (struct oce_mbx));
2983abb112fSGarrett D'Amore 
2994d0e5007SSukumar Swaminathan 	/* check mbox status */
3004d0e5007SSukumar Swaminathan 	if (mb_cqe->u0.s.completion_status != 0) {
3014d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG,
3023abb112fSGarrett D'Amore 		    "MBOX Command Failed with Status: %d %d",
3034d0e5007SSukumar Swaminathan 		    mb_cqe->u0.s.completion_status,
3044d0e5007SSukumar Swaminathan 		    mb_cqe->u0.s.extended_status);
3054d0e5007SSukumar Swaminathan 		mutex_exit(&dev->bmbx_lock);
3064d0e5007SSukumar Swaminathan 		return (EIO);
3074d0e5007SSukumar Swaminathan 	}
3084d0e5007SSukumar Swaminathan 
3094d0e5007SSukumar Swaminathan 	/*
3104d0e5007SSukumar Swaminathan 	 * store the mbx context in the cqe tag section so that
3114d0e5007SSukumar Swaminathan 	 * the upper layer handling the cqe can associate the mbx
3124d0e5007SSukumar Swaminathan 	 * with the response
3134d0e5007SSukumar Swaminathan 	 */
3144d0e5007SSukumar Swaminathan 	if (mbxctx) {
3154d0e5007SSukumar Swaminathan 		/* save context */
3164d0e5007SSukumar Swaminathan 		mbxctx->mbx = mb_mbx;
3174d0e5007SSukumar Swaminathan 		bcopy(&mbxctx, mb_cqe->u0.s.mq_tag,
3184d0e5007SSukumar Swaminathan 		    sizeof (struct oce_mbx_ctx *));
3194d0e5007SSukumar Swaminathan 	}
3204d0e5007SSukumar Swaminathan 
3214d0e5007SSukumar Swaminathan 	mutex_exit(&dev->bmbx_lock);
3224d0e5007SSukumar Swaminathan 	return (0);
3234d0e5007SSukumar Swaminathan } /* oce_mbox_post */
3244d0e5007SSukumar Swaminathan 
3254d0e5007SSukumar Swaminathan /*
3264d0e5007SSukumar Swaminathan  * function to get the firmware version
3274d0e5007SSukumar Swaminathan  *
3284d0e5007SSukumar Swaminathan  * dev - software handle to the device
3294d0e5007SSukumar Swaminathan  *
3304d0e5007SSukumar Swaminathan  * return 0 on success, EIO on failure
3314d0e5007SSukumar Swaminathan  */
3324d0e5007SSukumar Swaminathan int
oce_get_fw_version(struct oce_dev * dev)3334d0e5007SSukumar Swaminathan oce_get_fw_version(struct oce_dev *dev)
3344d0e5007SSukumar Swaminathan {
3354d0e5007SSukumar Swaminathan 	struct oce_mbx mbx;
3364d0e5007SSukumar Swaminathan 	struct mbx_get_common_fw_version *fwcmd;
3374d0e5007SSukumar Swaminathan 	int ret = 0;
3384d0e5007SSukumar Swaminathan 
3394d0e5007SSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
3404d0e5007SSukumar Swaminathan 
3414d0e5007SSukumar Swaminathan 	/* initialize the ioctl header */
3424d0e5007SSukumar Swaminathan 	fwcmd = (struct mbx_get_common_fw_version *)&mbx.payload;
3434d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
3444d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_COMMON,
3454d0e5007SSukumar Swaminathan 	    OPCODE_GET_COMMON_FW_VERSION,
3464d0e5007SSukumar Swaminathan 	    MBX_TIMEOUT_SEC,
3474d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_get_common_fw_version));
3484d0e5007SSukumar Swaminathan 
3494d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
3504d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = 1;
3514d0e5007SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_get_common_fw_version);
3524d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
3534d0e5007SSukumar Swaminathan 
3544d0e5007SSukumar Swaminathan 	/* now post the command */
3554d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
3564d0e5007SSukumar Swaminathan 
3578d738d7dSSukumar Swaminathan 	if (ret != 0) {
3584d0e5007SSukumar Swaminathan 		return (ret);
3594d0e5007SSukumar Swaminathan 	}
3604d0e5007SSukumar Swaminathan 	bcopy(fwcmd->params.rsp.fw_ver_str, dev->fw_version, 32);
3614d0e5007SSukumar Swaminathan 
3624d0e5007SSukumar Swaminathan 	oce_log(dev, CE_NOTE, MOD_CONFIG, "%s %s",
3634d0e5007SSukumar Swaminathan 	    fwcmd->params.rsp.fw_ver_str,
3644d0e5007SSukumar Swaminathan 	    fwcmd->params.rsp.fw_on_flash_ver_str);
3654d0e5007SSukumar Swaminathan 
3664d0e5007SSukumar Swaminathan 	return (0);
3674d0e5007SSukumar Swaminathan } /* oce_get_fw_version */
3684d0e5007SSukumar Swaminathan 
3694d0e5007SSukumar Swaminathan /*
3704d0e5007SSukumar Swaminathan  * function to invoke f/w reset via. mailbox
3714d0e5007SSukumar Swaminathan  * does not hold bootstap lock called by quiesce
3724d0e5007SSukumar Swaminathan  *
3734d0e5007SSukumar Swaminathan  * dev - software handle to the device
3744d0e5007SSukumar Swaminathan  *
3754d0e5007SSukumar Swaminathan  * return 0 on success, ETIMEDOUT on failure
3764d0e5007SSukumar Swaminathan  *
3774d0e5007SSukumar Swaminathan  */
3784d0e5007SSukumar Swaminathan int
oce_reset_fun(struct oce_dev * dev)3794d0e5007SSukumar Swaminathan oce_reset_fun(struct oce_dev *dev)
3804d0e5007SSukumar Swaminathan {
3814d0e5007SSukumar Swaminathan 	struct oce_mbx *mbx;
3824d0e5007SSukumar Swaminathan 	struct oce_bmbx *mb;
3834d0e5007SSukumar Swaminathan 	struct ioctl_common_function_reset *fwcmd;
3844d0e5007SSukumar Swaminathan 
3854d0e5007SSukumar Swaminathan 	mb = (struct oce_bmbx *)DBUF_VA(dev->bmbx);
3864d0e5007SSukumar Swaminathan 	mbx = &mb->mbx;
3874d0e5007SSukumar Swaminathan 	bzero(mbx, sizeof (struct oce_mbx));
3884d0e5007SSukumar Swaminathan 	/* initialize the ioctl header */
3894d0e5007SSukumar Swaminathan 	fwcmd = (struct ioctl_common_function_reset *)&mbx->payload;
3904d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
3914d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_COMMON,
3924d0e5007SSukumar Swaminathan 	    OPCODE_COMMON_FUNCTION_RESET,
3934d0e5007SSukumar Swaminathan 	    MBX_TIMEOUT_SEC,
3944d0e5007SSukumar Swaminathan 	    sizeof (struct ioctl_common_function_reset));
3954d0e5007SSukumar Swaminathan 
3964d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
3974d0e5007SSukumar Swaminathan 	mbx->u0.s.embedded = 1;
3984d0e5007SSukumar Swaminathan 	mbx->payload_length = sizeof (struct ioctl_common_function_reset);
3998d738d7dSSukumar Swaminathan 	DW_SWAP(u32ptr(mbx), mbx->payload_length + OCE_BMBX_RHDR_SZ);
4004d0e5007SSukumar Swaminathan 
4014d0e5007SSukumar Swaminathan 	return (oce_mbox_dispatch(dev, 0));
4024d0e5007SSukumar Swaminathan } /* oce_reset_fun */
4034d0e5007SSukumar Swaminathan 
4044d0e5007SSukumar Swaminathan /*
4054d0e5007SSukumar Swaminathan  * function to read the mac address associated with an interface
4064d0e5007SSukumar Swaminathan  *
4074d0e5007SSukumar Swaminathan  * dev - software handle to the device
4084d0e5007SSukumar Swaminathan  * if_id - interface id to read the address from
4094d0e5007SSukumar Swaminathan  * perm - set to 1 if reading the factory mac address. In this case
4104d0e5007SSukumar Swaminathan  *	if_id is ignored
4114d0e5007SSukumar Swaminathan  * type - type of the mac address, whether network or storage
4124d0e5007SSukumar Swaminathan  * mac - [OUTPUT] pointer to a buffer containing the mac address
4134d0e5007SSukumar Swaminathan  *	    when the command succeeds
4144d0e5007SSukumar Swaminathan  *
4154d0e5007SSukumar Swaminathan  * return 0 on success, EIO on failure
4164d0e5007SSukumar Swaminathan  */
4174d0e5007SSukumar Swaminathan int
oce_read_mac_addr(struct oce_dev * dev,uint32_t if_id,uint8_t perm,uint8_t type,struct mac_address_format * mac)4188d738d7dSSukumar Swaminathan oce_read_mac_addr(struct oce_dev *dev, uint32_t if_id, uint8_t perm,
4194d0e5007SSukumar Swaminathan     uint8_t type, struct mac_address_format *mac)
4204d0e5007SSukumar Swaminathan {
4214d0e5007SSukumar Swaminathan 	struct oce_mbx mbx;
4224d0e5007SSukumar Swaminathan 	struct mbx_query_common_iface_mac *fwcmd;
4234d0e5007SSukumar Swaminathan 	int ret = 0;
4244d0e5007SSukumar Swaminathan 
4254d0e5007SSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
4264d0e5007SSukumar Swaminathan 	/* initialize the ioctl header */
4274d0e5007SSukumar Swaminathan 	fwcmd = (struct mbx_query_common_iface_mac *)&mbx.payload;
4284d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
4294d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_COMMON,
4304d0e5007SSukumar Swaminathan 	    OPCODE_QUERY_COMMON_IFACE_MAC,
4314d0e5007SSukumar Swaminathan 	    MBX_TIMEOUT_SEC,
4324d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_query_common_iface_mac));
4334d0e5007SSukumar Swaminathan 
4344d0e5007SSukumar Swaminathan 	/* fill the command */
4354d0e5007SSukumar Swaminathan 	fwcmd->params.req.permanent = perm;
4364d0e5007SSukumar Swaminathan 	if (perm)
4378d738d7dSSukumar Swaminathan 		fwcmd->params.req.if_id = (uint16_t)if_id;
4384d0e5007SSukumar Swaminathan 	else
4394d0e5007SSukumar Swaminathan 		fwcmd->params.req.if_id = 0;
4404d0e5007SSukumar Swaminathan 	fwcmd->params.req.type = type;
4414d0e5007SSukumar Swaminathan 
4424d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
4434d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = 1;
4444d0e5007SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_query_common_iface_mac);
4454d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
4464d0e5007SSukumar Swaminathan 
4474d0e5007SSukumar Swaminathan 	/* now post the command */
4484d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
4498d738d7dSSukumar Swaminathan 	if (ret != 0) {
4504d0e5007SSukumar Swaminathan 		return (ret);
4514d0e5007SSukumar Swaminathan 	}
4524d0e5007SSukumar Swaminathan 
4534d0e5007SSukumar Swaminathan 	/* get the response */
4544d0e5007SSukumar Swaminathan 	oce_log(dev, CE_NOTE, MOD_CONFIG,
4554d0e5007SSukumar Swaminathan 	    "MAC addr size = 0x%x",
4564d0e5007SSukumar Swaminathan 	    LE_16(fwcmd->params.rsp.mac.size_of_struct));
4574d0e5007SSukumar Swaminathan 	oce_log(dev, CE_NOTE, MOD_CONFIG,
4584d0e5007SSukumar Swaminathan 	    "MAC_ADDR:0x%x:0x%x:0x%x:0x%x:0x%x:0x%x",
4594d0e5007SSukumar Swaminathan 	    fwcmd->params.rsp.mac.mac_addr[0],
4604d0e5007SSukumar Swaminathan 	    fwcmd->params.rsp.mac.mac_addr[1],
4614d0e5007SSukumar Swaminathan 	    fwcmd->params.rsp.mac.mac_addr[2],
4624d0e5007SSukumar Swaminathan 	    fwcmd->params.rsp.mac.mac_addr[3],
4634d0e5007SSukumar Swaminathan 	    fwcmd->params.rsp.mac.mac_addr[4],
4644d0e5007SSukumar Swaminathan 	    fwcmd->params.rsp.mac.mac_addr[5]);
4654d0e5007SSukumar Swaminathan 
4664d0e5007SSukumar Swaminathan 	/* copy the mac addres in the output parameter */
4674d0e5007SSukumar Swaminathan 	mac->size_of_struct = LE_16(fwcmd->params.rsp.mac.size_of_struct);
4684d0e5007SSukumar Swaminathan 	bcopy(&fwcmd->params.rsp.mac.mac_addr[0], &mac->mac_addr[0],
4694d0e5007SSukumar Swaminathan 	    mac->size_of_struct);
4704d0e5007SSukumar Swaminathan 
4714d0e5007SSukumar Swaminathan 	return (0);
4724d0e5007SSukumar Swaminathan } /* oce_read_mac_addr */
4734d0e5007SSukumar Swaminathan 
4744d0e5007SSukumar Swaminathan /*
4754d0e5007SSukumar Swaminathan  * function to create an interface using the OPCODE_CREATE_COMMON_IFACE
4764d0e5007SSukumar Swaminathan  * command
4774d0e5007SSukumar Swaminathan  *
4784d0e5007SSukumar Swaminathan  * dev - software handle to the device
4794d0e5007SSukumar Swaminathan  * cap_flags - capability flags
4804d0e5007SSukumar Swaminathan  * en_flags - enable capability flags
4814d0e5007SSukumar Swaminathan  * vlan_tag - optional vlan tag to associate with the if
4824d0e5007SSukumar Swaminathan  * mac_addr - pointer to a buffer containing the mac address
4834d0e5007SSukumar Swaminathan  * if_id - [OUTPUT] pointer to an integer to hold the ID of the
4844d0e5007SSukumar Swaminathan  *	    interface created
4854d0e5007SSukumar Swaminathan  *
4864d0e5007SSukumar Swaminathan  * return 0 on success, EIO on failure
4874d0e5007SSukumar Swaminathan  */
4884d0e5007SSukumar Swaminathan int
oce_if_create(struct oce_dev * dev,uint32_t cap_flags,uint32_t en_flags,uint16_t vlan_tag,uint8_t * mac_addr,uint32_t * if_id)4894d0e5007SSukumar Swaminathan oce_if_create(struct oce_dev *dev, uint32_t cap_flags, uint32_t en_flags,
4904d0e5007SSukumar Swaminathan     uint16_t vlan_tag, uint8_t *mac_addr,
4914d0e5007SSukumar Swaminathan     uint32_t *if_id)
4924d0e5007SSukumar Swaminathan {
4934d0e5007SSukumar Swaminathan 	struct oce_mbx mbx;
4944d0e5007SSukumar Swaminathan 	struct mbx_create_common_iface *fwcmd;
4954d0e5007SSukumar Swaminathan 	int ret = 0;
4964d0e5007SSukumar Swaminathan 
4974d0e5007SSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
4984d0e5007SSukumar Swaminathan 
4994d0e5007SSukumar Swaminathan 	/* initialize the ioctl header */
5004d0e5007SSukumar Swaminathan 	fwcmd = (struct mbx_create_common_iface *)&mbx.payload;
5014d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
5024d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_COMMON,
5034d0e5007SSukumar Swaminathan 	    OPCODE_CREATE_COMMON_IFACE,
5044d0e5007SSukumar Swaminathan 	    MBX_TIMEOUT_SEC,
5054d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_create_common_iface));
5064d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&fwcmd->hdr), sizeof (struct mbx_hdr));
5074d0e5007SSukumar Swaminathan 
5084d0e5007SSukumar Swaminathan 	/* fill the command */
5094d0e5007SSukumar Swaminathan 	fwcmd->params.req.version   = 0;
5104d0e5007SSukumar Swaminathan 	fwcmd->params.req.cap_flags = LE_32(cap_flags);
5114d0e5007SSukumar Swaminathan 	fwcmd->params.req.enable_flags   = LE_32(en_flags);
5124d0e5007SSukumar Swaminathan 	if (mac_addr != NULL) {
5134d0e5007SSukumar Swaminathan 		bcopy(mac_addr, &fwcmd->params.req.mac_addr[0],
5144d0e5007SSukumar Swaminathan 		    ETHERADDRL);
5154d0e5007SSukumar Swaminathan 		fwcmd->params.req.vlan_tag.u0.normal.vtag = LE_16(vlan_tag);
5164d0e5007SSukumar Swaminathan 		fwcmd->params.req.mac_invalid = B_FALSE;
5174d0e5007SSukumar Swaminathan 	} else {
5184d0e5007SSukumar Swaminathan 		fwcmd->params.req.mac_invalid = B_TRUE;
5194d0e5007SSukumar Swaminathan 	}
5204d0e5007SSukumar Swaminathan 
5214d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
5224d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = 1;
5234d0e5007SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_create_common_iface);
5244d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ);
5254d0e5007SSukumar Swaminathan 
5264d0e5007SSukumar Swaminathan 	/* now post the command */
5274d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
5288d738d7dSSukumar Swaminathan 	if (ret != 0) {
5294d0e5007SSukumar Swaminathan 		return (ret);
5304d0e5007SSukumar Swaminathan 	}
5314d0e5007SSukumar Swaminathan 
5328d738d7dSSukumar Swaminathan 
5338d738d7dSSukumar Swaminathan 
5344d0e5007SSukumar Swaminathan 	/* get response */
5354d0e5007SSukumar Swaminathan 	*if_id = LE_32(fwcmd->params.rsp.if_id);
5364d0e5007SSukumar Swaminathan 	oce_log(dev, CE_NOTE, MOD_CONFIG,
5374d0e5007SSukumar Swaminathan 	    "IF_ID = 0x%x", *if_id);
5384d0e5007SSukumar Swaminathan 
5394d0e5007SSukumar Swaminathan 	/* If asked to set mac addr save the pmac handle */
5404d0e5007SSukumar Swaminathan 	if (mac_addr != NULL) {
5414d0e5007SSukumar Swaminathan 		dev->pmac_id = LE_32(fwcmd->params.rsp.pmac_id);
5424d0e5007SSukumar Swaminathan 		oce_log(dev, CE_NOTE, MOD_CONFIG,
5434d0e5007SSukumar Swaminathan 		    "PMAC_ID = 0x%x", dev->pmac_id);
5444d0e5007SSukumar Swaminathan 	}
5454d0e5007SSukumar Swaminathan 	return (0);
5464d0e5007SSukumar Swaminathan } /* oce_if_create */
5474d0e5007SSukumar Swaminathan 
5484d0e5007SSukumar Swaminathan /*
5494d0e5007SSukumar Swaminathan  * function to delete an interface
5504d0e5007SSukumar Swaminathan  *
5514d0e5007SSukumar Swaminathan  * dev - software handle to the device
5524d0e5007SSukumar Swaminathan  * if_id - ID of the interface to delete
5534d0e5007SSukumar Swaminathan  *
5544d0e5007SSukumar Swaminathan  * return 0 on success, EIO on failure
5554d0e5007SSukumar Swaminathan  */
5564d0e5007SSukumar Swaminathan int
oce_if_del(struct oce_dev * dev,uint32_t if_id)5574d0e5007SSukumar Swaminathan oce_if_del(struct oce_dev *dev, uint32_t if_id)
5584d0e5007SSukumar Swaminathan {
5594d0e5007SSukumar Swaminathan 	struct oce_mbx mbx;
5604d0e5007SSukumar Swaminathan 	struct mbx_destroy_common_iface *fwcmd;
5614d0e5007SSukumar Swaminathan 	int ret = 0;
5624d0e5007SSukumar Swaminathan 
5634d0e5007SSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
5644d0e5007SSukumar Swaminathan 	/* initialize the ioctl header */
5654d0e5007SSukumar Swaminathan 	fwcmd = (struct mbx_destroy_common_iface *)&mbx.payload;
5664d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
5674d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_COMMON,
5684d0e5007SSukumar Swaminathan 	    OPCODE_DESTROY_COMMON_IFACE,
5694d0e5007SSukumar Swaminathan 	    MBX_TIMEOUT_SEC,
5704d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_destroy_common_iface));
5714d0e5007SSukumar Swaminathan 
5724d0e5007SSukumar Swaminathan 	/* fill the command */
5734d0e5007SSukumar Swaminathan 	fwcmd->params.req.if_id = if_id;
5744d0e5007SSukumar Swaminathan 
5754d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
5764d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = 1;
5774d0e5007SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_destroy_common_iface);
5784d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
5794d0e5007SSukumar Swaminathan 
5804d0e5007SSukumar Swaminathan 	/* post the command */
5814d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
5828d738d7dSSukumar Swaminathan 	return (ret);
5834d0e5007SSukumar Swaminathan } /* oce_if_del */
5844d0e5007SSukumar Swaminathan 
5854d0e5007SSukumar Swaminathan /*
5864d0e5007SSukumar Swaminathan  * function to query the link status from the hardware
5874d0e5007SSukumar Swaminathan  *
5884d0e5007SSukumar Swaminathan  * dev - software handle to the device
5894d0e5007SSukumar Swaminathan  * link_status - [OUT] pointer to the structure returning the link attributes
5904d0e5007SSukumar Swaminathan  *
5914d0e5007SSukumar Swaminathan  * return 0 on success, EIO on failure
5924d0e5007SSukumar Swaminathan  */
5934d0e5007SSukumar Swaminathan int
oce_get_link_status(struct oce_dev * dev,struct link_status * link)5944d0e5007SSukumar Swaminathan oce_get_link_status(struct oce_dev *dev, struct link_status *link)
5954d0e5007SSukumar Swaminathan {
5964d0e5007SSukumar Swaminathan 	struct oce_mbx mbx;
5974d0e5007SSukumar Swaminathan 	struct mbx_query_common_link_status *fwcmd;
5984d0e5007SSukumar Swaminathan 	int ret = 0;
5994d0e5007SSukumar Swaminathan 
6004d0e5007SSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
6014d0e5007SSukumar Swaminathan 
6024d0e5007SSukumar Swaminathan 	/* initialize the ioctl header */
6034d0e5007SSukumar Swaminathan 	fwcmd = (struct mbx_query_common_link_status *)&mbx.payload;
6044d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
6054d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_COMMON,
6064d0e5007SSukumar Swaminathan 	    OPCODE_QUERY_COMMON_LINK_STATUS,
6074d0e5007SSukumar Swaminathan 	    MBX_TIMEOUT_SEC,
6084d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_query_common_link_status));
6094d0e5007SSukumar Swaminathan 
6104d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
6114d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = 1;
6124d0e5007SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_query_common_link_status);
6134d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
6144d0e5007SSukumar Swaminathan 
6154d0e5007SSukumar Swaminathan 	/* post the command */
6164d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
6178d738d7dSSukumar Swaminathan 
6188d738d7dSSukumar Swaminathan 	if (ret != 0) {
6194d0e5007SSukumar Swaminathan 		return (ret);
6204d0e5007SSukumar Swaminathan 	}
6214d0e5007SSukumar Swaminathan 
6224d0e5007SSukumar Swaminathan 	/* interpret response */
6235b9d3151SSukumar Swaminathan 	bcopy(&fwcmd->params.rsp, link, sizeof (struct link_status));
6245b9d3151SSukumar Swaminathan 	link->logical_link_status = LE_32(link->logical_link_status);
6255b9d3151SSukumar Swaminathan 	link->qos_link_speed = LE_16(link->qos_link_speed);
6265b9d3151SSukumar Swaminathan 
6274d0e5007SSukumar Swaminathan 	return (0);
6284d0e5007SSukumar Swaminathan } /* oce_get_link_status */
6294d0e5007SSukumar Swaminathan 
6304d0e5007SSukumar Swaminathan /*
6314d0e5007SSukumar Swaminathan  * function to configure the rx filter on the interface
6324d0e5007SSukumar Swaminathan  *
6334d0e5007SSukumar Swaminathan  * dev - software handle to the device
6344d0e5007SSukumar Swaminathan  * filter - mbx command containing the filter parameters
6354d0e5007SSukumar Swaminathan  *
6364d0e5007SSukumar Swaminathan  * return 0 on success, EIO on failure
6374d0e5007SSukumar Swaminathan  */
6384d0e5007SSukumar Swaminathan int
oce_set_rx_filter(struct oce_dev * dev,struct mbx_set_common_ntwk_rx_filter * filter)6394d0e5007SSukumar Swaminathan oce_set_rx_filter(struct oce_dev *dev,
6404d0e5007SSukumar Swaminathan     struct mbx_set_common_ntwk_rx_filter *filter)
6414d0e5007SSukumar Swaminathan {
6424d0e5007SSukumar Swaminathan 	struct oce_mbx mbx;
6434d0e5007SSukumar Swaminathan 	struct mbx_set_common_ntwk_rx_filter *fwcmd;
6444d0e5007SSukumar Swaminathan 	int ret;
6454d0e5007SSukumar Swaminathan 
6464d0e5007SSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
6474d0e5007SSukumar Swaminathan 	fwcmd = (struct mbx_set_common_ntwk_rx_filter *)&mbx.payload;
6484d0e5007SSukumar Swaminathan 	/* fill the command */
6494d0e5007SSukumar Swaminathan 	bcopy(filter, fwcmd, sizeof (struct mbx_set_common_ntwk_rx_filter));
6504d0e5007SSukumar Swaminathan 
6514d0e5007SSukumar Swaminathan 	/* initialize the ioctl header */
6524d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
6534d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_COMMON,
6544d0e5007SSukumar Swaminathan 	    OPCODE_COMMON_NTWK_RX_FILTER,
6554d0e5007SSukumar Swaminathan 	    MBX_TIMEOUT_SEC,
6564d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_set_common_ntwk_rx_filter));
6574d0e5007SSukumar Swaminathan 
6584d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
6594d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = 1;
6604d0e5007SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_set_common_ntwk_rx_filter);
6614d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
6624d0e5007SSukumar Swaminathan 
6634d0e5007SSukumar Swaminathan 	/* post the command */
6644d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
6654d0e5007SSukumar Swaminathan 
6668d738d7dSSukumar Swaminathan 	return (ret);
6674d0e5007SSukumar Swaminathan } /* oce_set_rx_filter */
6684d0e5007SSukumar Swaminathan 
6694d0e5007SSukumar Swaminathan /*
6704d0e5007SSukumar Swaminathan  * function to send the mbx command to update the mcast table with fw
6714d0e5007SSukumar Swaminathan  *
6724d0e5007SSukumar Swaminathan  * dev - software handle to the device
6734d0e5007SSukumar Swaminathan  * mca_table - array of mcast address to update
6744d0e5007SSukumar Swaminathan  * mca_cnt - number of elements in mca_table
6754d0e5007SSukumar Swaminathan  * enable_promisc - flag to enable/disable mcast-promiscuous mode
6764d0e5007SSukumar Swaminathan  *
6774d0e5007SSukumar Swaminathan  * return 0 on success, EIO on failure
6784d0e5007SSukumar Swaminathan  */
6794d0e5007SSukumar Swaminathan int
oce_set_multicast_table(struct oce_dev * dev,uint32_t if_id,struct ether_addr * mca_table,uint16_t mca_cnt,boolean_t promisc)6808d738d7dSSukumar Swaminathan oce_set_multicast_table(struct oce_dev *dev, uint32_t if_id,
6818d738d7dSSukumar Swaminathan struct ether_addr *mca_table, uint16_t mca_cnt, boolean_t promisc)
6824d0e5007SSukumar Swaminathan {
6834d0e5007SSukumar Swaminathan 	struct oce_mbx mbx;
6844d0e5007SSukumar Swaminathan 	struct  mbx_set_common_iface_multicast *fwcmd;
6854d0e5007SSukumar Swaminathan 	int ret;
6864d0e5007SSukumar Swaminathan 
6874d0e5007SSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
6884d0e5007SSukumar Swaminathan 	fwcmd = (struct mbx_set_common_iface_multicast *)&mbx.payload;
6894d0e5007SSukumar Swaminathan 
6904d0e5007SSukumar Swaminathan 	/* initialize the ioctl header */
6914d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
6924d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_COMMON,
6934d0e5007SSukumar Swaminathan 	    OPCODE_SET_COMMON_IFACE_MULTICAST,
6944d0e5007SSukumar Swaminathan 	    MBX_TIMEOUT_SEC,
6954d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_set_common_iface_multicast));
6964d0e5007SSukumar Swaminathan 
6974d0e5007SSukumar Swaminathan 	/* fill the command */
6988d738d7dSSukumar Swaminathan 	fwcmd->params.req.if_id = (uint8_t)if_id;
6998d738d7dSSukumar Swaminathan 	if (mca_table != NULL) {
7008d738d7dSSukumar Swaminathan 		bcopy(mca_table, &fwcmd->params.req.mac[0],
7018d738d7dSSukumar Swaminathan 		    mca_cnt * ETHERADDRL);
7028d738d7dSSukumar Swaminathan 	}
7034d0e5007SSukumar Swaminathan 	fwcmd->params.req.num_mac = LE_16(mca_cnt);
7048d738d7dSSukumar Swaminathan 	fwcmd->params.req.promiscuous = (uint8_t)promisc;
7054d0e5007SSukumar Swaminathan 
7064d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
7074d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = B_TRUE;
7084d0e5007SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_set_common_iface_multicast);
7094d0e5007SSukumar Swaminathan 	/* Swap only MBX header + BOOTSTRAP HDR */
7104d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + OCE_MBX_RRHDR_SZ));
7114d0e5007SSukumar Swaminathan 
7124d0e5007SSukumar Swaminathan 	/* post the command */
7134d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
7148d738d7dSSukumar Swaminathan 
7158d738d7dSSukumar Swaminathan 	return (ret);
7164d0e5007SSukumar Swaminathan } /* oce_set_multicast_table */
7174d0e5007SSukumar Swaminathan 
7184d0e5007SSukumar Swaminathan /*
7194d0e5007SSukumar Swaminathan  * function to query the fw attributes from the hw
7204d0e5007SSukumar Swaminathan  *
7214d0e5007SSukumar Swaminathan  * dev - software handle to the device
7224d0e5007SSukumar Swaminathan  *
7234d0e5007SSukumar Swaminathan  * return 0 on success, EIO on failure
7244d0e5007SSukumar Swaminathan  */
7254d0e5007SSukumar Swaminathan int
oce_get_fw_config(struct oce_dev * dev)7264d0e5007SSukumar Swaminathan oce_get_fw_config(struct oce_dev *dev)
7274d0e5007SSukumar Swaminathan {
7284d0e5007SSukumar Swaminathan 	struct oce_mbx mbx;
7294d0e5007SSukumar Swaminathan 	struct mbx_common_query_fw_config *fwcmd;
7304d0e5007SSukumar Swaminathan 	int ret = 0;
7314d0e5007SSukumar Swaminathan 
7324d0e5007SSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
7334d0e5007SSukumar Swaminathan 	/* initialize the ioctl header */
7344d0e5007SSukumar Swaminathan 	fwcmd = (struct mbx_common_query_fw_config *)&mbx.payload;
7354d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
7364d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_COMMON,
7374d0e5007SSukumar Swaminathan 	    OPCODE_QUERY_COMMON_FIRMWARE_CONFIG,
7384d0e5007SSukumar Swaminathan 	    MBX_TIMEOUT_SEC,
7394d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_common_query_fw_config));
7404d0e5007SSukumar Swaminathan 
7414d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
7424d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = 1;
7434d0e5007SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_common_query_fw_config);
7444d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
7454d0e5007SSukumar Swaminathan 
7464d0e5007SSukumar Swaminathan 	/* now post the command */
7474d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
7488d738d7dSSukumar Swaminathan 
7498d738d7dSSukumar Swaminathan 	if (ret != 0) {
7504d0e5007SSukumar Swaminathan 		return (ret);
7514d0e5007SSukumar Swaminathan 	}
7524d0e5007SSukumar Swaminathan 
7534d0e5007SSukumar Swaminathan 	/* swap and copy into buffer */
7544d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(fwcmd), sizeof (struct mbx_common_query_fw_config));
7554d0e5007SSukumar Swaminathan 
7564d0e5007SSukumar Swaminathan 	dev->config_number = fwcmd->params.rsp.config_number;
7574d0e5007SSukumar Swaminathan 	dev->asic_revision = fwcmd->params.rsp.asic_revision;
7584d0e5007SSukumar Swaminathan 	dev->port_id = fwcmd->params.rsp.port_id;
7594d0e5007SSukumar Swaminathan 	dev->function_mode = fwcmd->params.rsp.function_mode;
7604d0e5007SSukumar Swaminathan 
7615b9d3151SSukumar Swaminathan 	/* get the max rings alloted for this function */
7625b9d3151SSukumar Swaminathan 	if (fwcmd->params.rsp.ulp[0].mode & ULP_NIC_MODE) {
7635b9d3151SSukumar Swaminathan 		dev->max_tx_rings = fwcmd->params.rsp.ulp[0].wq_count;
7645b9d3151SSukumar Swaminathan 		dev->max_rx_rings = fwcmd->params.rsp.ulp[0].rq_count;
7655b9d3151SSukumar Swaminathan 	} else {
7665b9d3151SSukumar Swaminathan 		dev->max_tx_rings = fwcmd->params.rsp.ulp[1].wq_count;
7675b9d3151SSukumar Swaminathan 		dev->max_rx_rings = fwcmd->params.rsp.ulp[1].rq_count;
7685b9d3151SSukumar Swaminathan 	}
7695b9d3151SSukumar Swaminathan 	dev->function_caps = fwcmd->params.rsp.function_caps;
7704d0e5007SSukumar Swaminathan 	return (0);
7714d0e5007SSukumar Swaminathan } /* oce_get_fw_config */
7724d0e5007SSukumar Swaminathan 
7734d0e5007SSukumar Swaminathan /*
7744d0e5007SSukumar Swaminathan  * function to retrieve statistic counters from the hardware
7754d0e5007SSukumar Swaminathan  *
7764d0e5007SSukumar Swaminathan  * dev - software handle to the device
7774d0e5007SSukumar Swaminathan  *
7784d0e5007SSukumar Swaminathan  * return 0 on success, EIO on failure
7794d0e5007SSukumar Swaminathan  */
7804d0e5007SSukumar Swaminathan int
oce_get_hw_stats(struct oce_dev * dev)7814d0e5007SSukumar Swaminathan oce_get_hw_stats(struct oce_dev *dev)
7824d0e5007SSukumar Swaminathan {
7834d0e5007SSukumar Swaminathan 	struct oce_mbx mbx;
7844d0e5007SSukumar Swaminathan 	struct mbx_get_nic_stats *fwcmd = dev->hw_stats;
7854d0e5007SSukumar Swaminathan 	int ret = 0;
7864d0e5007SSukumar Swaminathan 
7874d0e5007SSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
7884d0e5007SSukumar Swaminathan 	/* initialize the ioctl header */
7894d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
7904d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_NIC,
7914d0e5007SSukumar Swaminathan 	    OPCODE_GET_NIC_STATS,
7924d0e5007SSukumar Swaminathan 	    MBX_TIMEOUT_SEC,
7934d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_get_nic_stats));
7944d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(fwcmd), sizeof (struct mbx_get_nic_stats));
7954d0e5007SSukumar Swaminathan 
7964d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
7974d0e5007SSukumar Swaminathan 	mbx.payload.u0.u1.sgl[0].pa_lo = ADDR_LO(DBUF_PA(dev->stats_dbuf));
7984d0e5007SSukumar Swaminathan 	mbx.payload.u0.u1.sgl[0].pa_hi = ADDR_HI(DBUF_PA(dev->stats_dbuf));
7994d0e5007SSukumar Swaminathan 	mbx.payload.u0.u1.sgl[0].length = sizeof (struct mbx_get_nic_stats);
8004d0e5007SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_get_nic_stats);
8014d0e5007SSukumar Swaminathan 
8024d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = 0;
8034d0e5007SSukumar Swaminathan 	mbx.u0.s.sge_count = 1;
8044d0e5007SSukumar Swaminathan 
8054d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), sizeof (struct oce_mq_sge) + OCE_BMBX_RHDR_SZ);
8064d0e5007SSukumar Swaminathan 
8073abb112fSGarrett D'Amore 	bzero(&dev->hw_stats->params, sizeof (dev->hw_stats->params));
8083abb112fSGarrett D'Amore 
80912d61dabSSukumar Swaminathan 	/* sync for device */
81012d61dabSSukumar Swaminathan 	(void) DBUF_SYNC(dev->stats_dbuf, DDI_DMA_SYNC_FORDEV);
81112d61dabSSukumar Swaminathan 
8124d0e5007SSukumar Swaminathan 	/* now post the command */
8134d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
81412d61dabSSukumar Swaminathan 	/* sync the stats */
81512d61dabSSukumar Swaminathan 	(void) DBUF_SYNC(dev->stats_dbuf, DDI_DMA_SYNC_FORKERNEL);
81612d61dabSSukumar Swaminathan 
8174d0e5007SSukumar Swaminathan 	/* Check the mailbox status and command completion status */
8188d738d7dSSukumar Swaminathan 	if (ret != 0) {
8194d0e5007SSukumar Swaminathan 		return (ret);
8204d0e5007SSukumar Swaminathan 	}
8214d0e5007SSukumar Swaminathan 
8224d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(dev->hw_stats), sizeof (struct mbx_get_nic_stats));
8234d0e5007SSukumar Swaminathan 	return (0);
8244d0e5007SSukumar Swaminathan } /* oce_get_hw_stats */
8254d0e5007SSukumar Swaminathan 
8264d0e5007SSukumar Swaminathan /*
8274d0e5007SSukumar Swaminathan  * function to set the number of vectors with the cev
8284d0e5007SSukumar Swaminathan  *
8294d0e5007SSukumar Swaminathan  * dev - software handle to the device
8304d0e5007SSukumar Swaminathan  * num_vectors - number of MSI messages
8314d0e5007SSukumar Swaminathan  *
8324d0e5007SSukumar Swaminathan  * return 0 on success, EIO on failure
8334d0e5007SSukumar Swaminathan  */
8344d0e5007SSukumar Swaminathan int
oce_num_intr_vectors_set(struct oce_dev * dev,uint32_t num_vectors)8354d0e5007SSukumar Swaminathan oce_num_intr_vectors_set(struct oce_dev *dev, uint32_t num_vectors)
8364d0e5007SSukumar Swaminathan {
8374d0e5007SSukumar Swaminathan 	struct oce_mbx mbx;
8384d0e5007SSukumar Swaminathan 	struct mbx_common_cev_modify_msi_messages *fwcmd;
8394d0e5007SSukumar Swaminathan 	int ret = 0;
8404d0e5007SSukumar Swaminathan 
8414d0e5007SSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
8424d0e5007SSukumar Swaminathan 	/* initialize the ioctl header */
8434d0e5007SSukumar Swaminathan 	fwcmd = (struct mbx_common_cev_modify_msi_messages *)&mbx.payload;
8444d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
8454d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_COMMON,
8464d0e5007SSukumar Swaminathan 	    OPCODE_COMMON_CEV_MODIFY_MSI_MESSAGES,
8474d0e5007SSukumar Swaminathan 	    MBX_TIMEOUT_SEC,
8484d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_common_cev_modify_msi_messages));
8494d0e5007SSukumar Swaminathan 
8504d0e5007SSukumar Swaminathan 	/* fill the command */
8514d0e5007SSukumar Swaminathan 	fwcmd->params.req.num_msi_msgs = LE_32(num_vectors);
8524d0e5007SSukumar Swaminathan 
8534d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
8544d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = 1;
8554d0e5007SSukumar Swaminathan 	mbx.payload_length =
8564d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_common_cev_modify_msi_messages);
8574d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
8584d0e5007SSukumar Swaminathan 
8594d0e5007SSukumar Swaminathan 	/* post the command */
8604d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
8614d0e5007SSukumar Swaminathan 
8628d738d7dSSukumar Swaminathan 	return (ret);
8634d0e5007SSukumar Swaminathan } /* oce_num_intr_vectors_set */
8644d0e5007SSukumar Swaminathan 
8654d0e5007SSukumar Swaminathan /*
8664d0e5007SSukumar Swaminathan  * function to set flow control capability in the hardware
8674d0e5007SSukumar Swaminathan  *
8684d0e5007SSukumar Swaminathan  * dev - software handle to the device
8694d0e5007SSukumar Swaminathan  * flow_control - flow control flags to set
8704d0e5007SSukumar Swaminathan  *
8714d0e5007SSukumar Swaminathan  * return 0 on success, EIO on failure
8724d0e5007SSukumar Swaminathan  */
8734d0e5007SSukumar Swaminathan int
oce_set_flow_control(struct oce_dev * dev,uint32_t flow_control)8744d0e5007SSukumar Swaminathan oce_set_flow_control(struct oce_dev *dev, uint32_t flow_control)
8754d0e5007SSukumar Swaminathan {
8764d0e5007SSukumar Swaminathan 	struct oce_mbx mbx;
8774d0e5007SSukumar Swaminathan 	struct mbx_common_get_set_flow_control *fwcmd =
8784d0e5007SSukumar Swaminathan 	    (struct mbx_common_get_set_flow_control *)&mbx.payload;
8794d0e5007SSukumar Swaminathan 	int ret;
8804d0e5007SSukumar Swaminathan 
8814d0e5007SSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
8824d0e5007SSukumar Swaminathan 	/* initialize the ioctl header */
8834d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
8844d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_COMMON,
8854d0e5007SSukumar Swaminathan 	    OPCODE_SET_COMMON_FLOW_CONTROL,
8864d0e5007SSukumar Swaminathan 	    MBX_TIMEOUT_SEC,
8874d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_common_get_set_flow_control));
8884d0e5007SSukumar Swaminathan 
8894d0e5007SSukumar Swaminathan 	/* fill command */
8904d0e5007SSukumar Swaminathan 	if (flow_control & OCE_FC_TX)
8914d0e5007SSukumar Swaminathan 		fwcmd->tx_flow_control = 1;
8924d0e5007SSukumar Swaminathan 
8934d0e5007SSukumar Swaminathan 	if (flow_control & OCE_FC_RX)
8944d0e5007SSukumar Swaminathan 		fwcmd->rx_flow_control = 1;
8954d0e5007SSukumar Swaminathan 
8964d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
8974d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = 1;
8984d0e5007SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_common_get_set_flow_control);
8994d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
9004d0e5007SSukumar Swaminathan 
9014d0e5007SSukumar Swaminathan 	/* post the command */
9024d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
9034d0e5007SSukumar Swaminathan 
9048d738d7dSSukumar Swaminathan 	return (ret);
9054d0e5007SSukumar Swaminathan } /* oce_set_flow_control */
9064d0e5007SSukumar Swaminathan 
9074d0e5007SSukumar Swaminathan /*
9084d0e5007SSukumar Swaminathan  * function to get the current flow control setting with the hardware
9094d0e5007SSukumar Swaminathan  *
9104d0e5007SSukumar Swaminathan  * dev - software handle to the device
9114d0e5007SSukumar Swaminathan  * flow_control - [OUT] pointer to location where flow_control setting
9124d0e5007SSukumar Swaminathan  * is returned
9134d0e5007SSukumar Swaminathan  *
9144d0e5007SSukumar Swaminathan  * return 0 on success, EIO on failure
9154d0e5007SSukumar Swaminathan  */
9164d0e5007SSukumar Swaminathan int
oce_get_flow_control(struct oce_dev * dev,uint32_t * flow_control)9174d0e5007SSukumar Swaminathan oce_get_flow_control(struct oce_dev *dev, uint32_t *flow_control)
9184d0e5007SSukumar Swaminathan {
9194d0e5007SSukumar Swaminathan 	struct oce_mbx mbx;
9204d0e5007SSukumar Swaminathan 	struct mbx_common_get_set_flow_control *fwcmd;
9214d0e5007SSukumar Swaminathan 	int ret;
9224d0e5007SSukumar Swaminathan 
9234d0e5007SSukumar Swaminathan 	DEV_LOCK(dev);
9244d0e5007SSukumar Swaminathan 	if (dev->suspended) {
9254d0e5007SSukumar Swaminathan 		DEV_UNLOCK(dev);
9264d0e5007SSukumar Swaminathan 		return (EIO);
9274d0e5007SSukumar Swaminathan 	}
9284d0e5007SSukumar Swaminathan 	DEV_UNLOCK(dev);
9294d0e5007SSukumar Swaminathan 
9304d0e5007SSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
9314d0e5007SSukumar Swaminathan 	fwcmd = (struct mbx_common_get_set_flow_control *)&mbx.payload;
9324d0e5007SSukumar Swaminathan 
9334d0e5007SSukumar Swaminathan 	/* initialize the ioctl header */
9344d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
9354d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_COMMON,
9364d0e5007SSukumar Swaminathan 	    OPCODE_GET_COMMON_FLOW_CONTROL,
9374d0e5007SSukumar Swaminathan 	    MBX_TIMEOUT_SEC,
9384d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_common_get_set_flow_control));
9394d0e5007SSukumar Swaminathan 
9404d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
9414d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = 1;
9424d0e5007SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_common_get_set_flow_control);
9434d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
9444d0e5007SSukumar Swaminathan 
9454d0e5007SSukumar Swaminathan 	/* post the command */
9464d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
9474d0e5007SSukumar Swaminathan 
9488d738d7dSSukumar Swaminathan 	if (ret != 0) {
9494d0e5007SSukumar Swaminathan 		return (ret);
9504d0e5007SSukumar Swaminathan 	}
9514d0e5007SSukumar Swaminathan 
9524d0e5007SSukumar Swaminathan 	/* get the flow control */
9534d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(fwcmd),
9544d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_common_get_set_flow_control));
9554d0e5007SSukumar Swaminathan 	*flow_control = 0;
9564d0e5007SSukumar Swaminathan 	if (fwcmd->tx_flow_control)
9574d0e5007SSukumar Swaminathan 		*flow_control |= OCE_FC_TX;
9584d0e5007SSukumar Swaminathan 
9594d0e5007SSukumar Swaminathan 	if (fwcmd->rx_flow_control)
9604d0e5007SSukumar Swaminathan 		*flow_control |= OCE_FC_RX;
9614d0e5007SSukumar Swaminathan 
9624d0e5007SSukumar Swaminathan 	return (0);
9634d0e5007SSukumar Swaminathan } /* oce_get_flow_control */
9644d0e5007SSukumar Swaminathan 
9654d0e5007SSukumar Swaminathan /*
9664d0e5007SSukumar Swaminathan  * function to enable/disable device promiscuous mode
9674d0e5007SSukumar Swaminathan  *
9684d0e5007SSukumar Swaminathan  * dev - software handle to the device
9694d0e5007SSukumar Swaminathan  * enable - enable/disable flag
9704d0e5007SSukumar Swaminathan  *
9714d0e5007SSukumar Swaminathan  * return 0 on success, EIO on failure
9724d0e5007SSukumar Swaminathan  */
9734d0e5007SSukumar Swaminathan int
oce_set_promiscuous(struct oce_dev * dev,boolean_t enable)9744d0e5007SSukumar Swaminathan oce_set_promiscuous(struct oce_dev *dev, boolean_t enable)
9754d0e5007SSukumar Swaminathan {
9764d0e5007SSukumar Swaminathan 	struct oce_mbx mbx;
9774d0e5007SSukumar Swaminathan 	struct mbx_config_nic_promiscuous *fwcmd;
9784d0e5007SSukumar Swaminathan 	int ret;
9794d0e5007SSukumar Swaminathan 
9804d0e5007SSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
9814d0e5007SSukumar Swaminathan 
9824d0e5007SSukumar Swaminathan 	fwcmd = (struct mbx_config_nic_promiscuous *)&mbx.payload;
9834d0e5007SSukumar Swaminathan 
9844d0e5007SSukumar Swaminathan 	if (dev->port_id == 0) {
9854d0e5007SSukumar Swaminathan 		fwcmd->params.req.port0_promisc = (uint8_t)enable;
9864d0e5007SSukumar Swaminathan 
9874d0e5007SSukumar Swaminathan 	} else {
9884d0e5007SSukumar Swaminathan 		fwcmd->params.req.port1_promisc = (uint8_t)enable;
9894d0e5007SSukumar Swaminathan 	}
9904d0e5007SSukumar Swaminathan 
9914d0e5007SSukumar Swaminathan 	/* initialize the ioctl header */
9924d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
9934d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_NIC,
9944d0e5007SSukumar Swaminathan 	    OPCODE_CONFIG_NIC_PROMISCUOUS,
9954d0e5007SSukumar Swaminathan 	    MBX_TIMEOUT_SEC,
9964d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_config_nic_promiscuous));
9974d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
9984d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = 1;
9994d0e5007SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_config_nic_promiscuous);
10004d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
10014d0e5007SSukumar Swaminathan 
10024d0e5007SSukumar Swaminathan 	/* post the command */
10034d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
10044d0e5007SSukumar Swaminathan 
10058d738d7dSSukumar Swaminathan 	return (ret);
10064d0e5007SSukumar Swaminathan }
10074d0e5007SSukumar Swaminathan 
10084d0e5007SSukumar Swaminathan /*
10094d0e5007SSukumar Swaminathan  * function to add a unicast address to an interface
10104d0e5007SSukumar Swaminathan  *
10114d0e5007SSukumar Swaminathan  * dev - software handle to the device
10124d0e5007SSukumar Swaminathan  * mac - unicast address
10134d0e5007SSukumar Swaminathan  *
10144d0e5007SSukumar Swaminathan  * return 0 on success, EIO on failure
10154d0e5007SSukumar Swaminathan  */
10164d0e5007SSukumar Swaminathan int
oce_add_mac(struct oce_dev * dev,uint32_t if_id,const uint8_t * mac,uint32_t * pmac_id)10178d738d7dSSukumar Swaminathan oce_add_mac(struct oce_dev *dev, uint32_t if_id,
10188d738d7dSSukumar Swaminathan 			const uint8_t *mac, uint32_t *pmac_id)
10194d0e5007SSukumar Swaminathan {
10204d0e5007SSukumar Swaminathan 	struct oce_mbx mbx;
10214d0e5007SSukumar Swaminathan 	struct mbx_add_common_iface_mac *fwcmd;
10224d0e5007SSukumar Swaminathan 	int ret;
10234d0e5007SSukumar Swaminathan 
10244d0e5007SSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
10254d0e5007SSukumar Swaminathan 	fwcmd = (struct mbx_add_common_iface_mac *)&mbx.payload;
10268d738d7dSSukumar Swaminathan 	fwcmd->params.req.if_id = LE_32(if_id);
10274d0e5007SSukumar Swaminathan 	bcopy(mac, &fwcmd->params.req.mac_address[0], ETHERADDRL);
10284d0e5007SSukumar Swaminathan 
10294d0e5007SSukumar Swaminathan 	/* initialize the ioctl header */
10304d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
10314d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_COMMON,
10324d0e5007SSukumar Swaminathan 	    OPCODE_ADD_COMMON_IFACE_MAC,
10334d0e5007SSukumar Swaminathan 	    MBX_TIMEOUT_SEC,
10344d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_add_common_iface_mac));
10354d0e5007SSukumar Swaminathan 
10364d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
10374d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = 1;
10384d0e5007SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_add_common_iface_mac);
10394d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ + OCE_MBX_RRHDR_SZ);
10404d0e5007SSukumar Swaminathan 
10414d0e5007SSukumar Swaminathan 	/* post the command */
10424d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
10434d0e5007SSukumar Swaminathan 
10448d738d7dSSukumar Swaminathan 	if (ret != 0) {
10454d0e5007SSukumar Swaminathan 		return (ret);
10464d0e5007SSukumar Swaminathan 	}
10478d738d7dSSukumar Swaminathan 
10484d0e5007SSukumar Swaminathan 	*pmac_id = LE_32(fwcmd->params.rsp.pmac_id);
10494d0e5007SSukumar Swaminathan 	return (0);
10504d0e5007SSukumar Swaminathan }
10514d0e5007SSukumar Swaminathan 
10524d0e5007SSukumar Swaminathan /*
10534d0e5007SSukumar Swaminathan  * function to delete an unicast address associated with an interface
10544d0e5007SSukumar Swaminathan  *
10554d0e5007SSukumar Swaminathan  * dev - software handle to the device
10564d0e5007SSukumar Swaminathan  * pmac_id - handle to the address added using ace_add_mac
10574d0e5007SSukumar Swaminathan  *
10584d0e5007SSukumar Swaminathan  * return 0 on success, EIO on failure
10594d0e5007SSukumar Swaminathan  */
10604d0e5007SSukumar Swaminathan int
oce_del_mac(struct oce_dev * dev,uint32_t if_id,uint32_t * pmac_id)10618d738d7dSSukumar Swaminathan oce_del_mac(struct oce_dev *dev,  uint32_t if_id, uint32_t *pmac_id)
10624d0e5007SSukumar Swaminathan {
10634d0e5007SSukumar Swaminathan 	struct oce_mbx mbx;
10644d0e5007SSukumar Swaminathan 	struct mbx_del_common_iface_mac *fwcmd;
10654d0e5007SSukumar Swaminathan 	int ret;
10664d0e5007SSukumar Swaminathan 
10674d0e5007SSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
10684d0e5007SSukumar Swaminathan 	fwcmd = (struct mbx_del_common_iface_mac *)&mbx.payload;
10698d738d7dSSukumar Swaminathan 	fwcmd->params.req.if_id = if_id;
10704d0e5007SSukumar Swaminathan 	fwcmd->params.req.pmac_id = *pmac_id;
10714d0e5007SSukumar Swaminathan 
10724d0e5007SSukumar Swaminathan 	/* initialize the ioctl header */
10734d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
10744d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_COMMON,
10754d0e5007SSukumar Swaminathan 	    OPCODE_DEL_COMMON_IFACE_MAC,
10764d0e5007SSukumar Swaminathan 	    MBX_TIMEOUT_SEC,
10774d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_add_common_iface_mac));
10784d0e5007SSukumar Swaminathan 
10794d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
10804d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = 1;
10814d0e5007SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_del_common_iface_mac);
10824d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), mbx.payload_length + OCE_BMBX_RHDR_SZ);
10834d0e5007SSukumar Swaminathan 
10844d0e5007SSukumar Swaminathan 	/* post the command */
10854d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
10864d0e5007SSukumar Swaminathan 
10878d738d7dSSukumar Swaminathan 	return (ret);
10884d0e5007SSukumar Swaminathan }
10894d0e5007SSukumar Swaminathan 
10904d0e5007SSukumar Swaminathan 
10914d0e5007SSukumar Swaminathan /*
10924d0e5007SSukumar Swaminathan  * function to send the mbx command to configure vlan
10934d0e5007SSukumar Swaminathan  *
10944d0e5007SSukumar Swaminathan  * dev - software handle to the device
10954d0e5007SSukumar Swaminathan  * vtag_arr - array of vlan tags
10964d0e5007SSukumar Swaminathan  * vtag_cnt - number of elements in array
10974d0e5007SSukumar Swaminathan  * untagged - boolean TRUE/FLASE
10984d0e5007SSukumar Swaminathan  * enable_promisc - flag to enable/disable VLAN promiscuous mode
10994d0e5007SSukumar Swaminathan  *
11004d0e5007SSukumar Swaminathan  * return 0 on success, EIO on failure
11014d0e5007SSukumar Swaminathan  */
11024d0e5007SSukumar Swaminathan int
oce_config_vlan(struct oce_dev * dev,uint32_t if_id,struct normal_vlan * vtag_arr,uint8_t vtag_cnt,boolean_t untagged,boolean_t enable_promisc)11038d738d7dSSukumar Swaminathan oce_config_vlan(struct oce_dev *dev, uint32_t if_id,
11044d0e5007SSukumar Swaminathan     struct normal_vlan *vtag_arr, uint8_t vtag_cnt,
11054d0e5007SSukumar Swaminathan     boolean_t untagged, boolean_t enable_promisc)
11064d0e5007SSukumar Swaminathan {
11074d0e5007SSukumar Swaminathan 	struct oce_mbx mbx;
11084d0e5007SSukumar Swaminathan 	struct  mbx_common_config_vlan *fwcmd;
11094d0e5007SSukumar Swaminathan 	int ret;
11104d0e5007SSukumar Swaminathan 
11114d0e5007SSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
11124d0e5007SSukumar Swaminathan 	fwcmd = (struct mbx_common_config_vlan *)&mbx.payload;
11134d0e5007SSukumar Swaminathan 
11144d0e5007SSukumar Swaminathan 	/* initialize the ioctl header */
11154d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
11164d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_COMMON,
11174d0e5007SSukumar Swaminathan 	    OPCODE_CONFIG_COMMON_IFACE_VLAN,
11184d0e5007SSukumar Swaminathan 	    MBX_TIMEOUT_SEC,
11194d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_common_config_vlan));
11204d0e5007SSukumar Swaminathan 
11218d738d7dSSukumar Swaminathan 	fwcmd->params.req.if_id	= (uint8_t)if_id;
11224d0e5007SSukumar Swaminathan 	fwcmd->params.req.promisc = (uint8_t)enable_promisc;
11234d0e5007SSukumar Swaminathan 	fwcmd->params.req.untagged = (uint8_t)untagged;
11244d0e5007SSukumar Swaminathan 	fwcmd->params.req.num_vlans = vtag_cnt;
11254d0e5007SSukumar Swaminathan 
11264d0e5007SSukumar Swaminathan 	/* Set the vlan tag filter on hw */
11274d0e5007SSukumar Swaminathan 	if (!enable_promisc) {
11284d0e5007SSukumar Swaminathan 		bcopy(fwcmd->params.req.tags.normal_vlans, vtag_arr,
11294d0e5007SSukumar Swaminathan 		    vtag_cnt * sizeof (struct normal_vlan));
11304d0e5007SSukumar Swaminathan 	}
11314d0e5007SSukumar Swaminathan 
11324d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
11334d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = B_TRUE;
11344d0e5007SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_common_config_vlan);
11354d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + mbx.payload_length));
11364d0e5007SSukumar Swaminathan 
11374d0e5007SSukumar Swaminathan 	/* post the command */
11384d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
11394d0e5007SSukumar Swaminathan 
11408d738d7dSSukumar Swaminathan 	return (ret);
11414d0e5007SSukumar Swaminathan } /* oce_config_vlan */
11424d0e5007SSukumar Swaminathan 
11434d0e5007SSukumar Swaminathan 
11444d0e5007SSukumar Swaminathan /*
11454d0e5007SSukumar Swaminathan  * function to enable or disable the link
11464d0e5007SSukumar Swaminathan  *
11474d0e5007SSukumar Swaminathan  * dev - software handle to the device
11484d0e5007SSukumar Swaminathan  * mca_table - array of mcast address to update
11494d0e5007SSukumar Swaminathan  * mca_cnt - number of elements in mca_table
11504d0e5007SSukumar Swaminathan  * enable_promisc - flag to enable/disable mcast-promiscuous mode
11514d0e5007SSukumar Swaminathan  *
11524d0e5007SSukumar Swaminathan  * return 0 on success, EIO on failure
11534d0e5007SSukumar Swaminathan  */
11544d0e5007SSukumar Swaminathan int
oce_config_link(struct oce_dev * dev,boolean_t enable)11554d0e5007SSukumar Swaminathan oce_config_link(struct oce_dev *dev, boolean_t enable)
11564d0e5007SSukumar Swaminathan {
11574d0e5007SSukumar Swaminathan 	struct oce_mbx mbx;
11584d0e5007SSukumar Swaminathan 	struct  mbx_common_func_link_cfg *fwcmd;
11594d0e5007SSukumar Swaminathan 	int ret;
11604d0e5007SSukumar Swaminathan 
11614d0e5007SSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
11624d0e5007SSukumar Swaminathan 	fwcmd = (struct mbx_common_func_link_cfg *)&mbx.payload;
11634d0e5007SSukumar Swaminathan 
11644d0e5007SSukumar Swaminathan 	/* initialize the ioctl header */
11654d0e5007SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
11664d0e5007SSukumar Swaminathan 	    MBX_SUBSYSTEM_COMMON,
11674d0e5007SSukumar Swaminathan 	    OPCODE_COMMON_FUNCTION_LINK_CONFIG,
11684d0e5007SSukumar Swaminathan 	    MBX_TIMEOUT_SEC,
11694d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_common_config_vlan));
11704d0e5007SSukumar Swaminathan 
11714d0e5007SSukumar Swaminathan 	fwcmd->params.req.enable = enable;
11724d0e5007SSukumar Swaminathan 
11734d0e5007SSukumar Swaminathan 	/* fill rest of mbx */
11744d0e5007SSukumar Swaminathan 	mbx.u0.s.embedded = B_TRUE;
11754d0e5007SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_common_func_link_cfg);
11764d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + mbx.payload_length));
11774d0e5007SSukumar Swaminathan 
11784d0e5007SSukumar Swaminathan 	/* post the command */
11794d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
11804d0e5007SSukumar Swaminathan 
11818d738d7dSSukumar Swaminathan 	return (ret);
11824d0e5007SSukumar Swaminathan } /* oce_config_link */
11834d0e5007SSukumar Swaminathan 
11845b9d3151SSukumar Swaminathan int
oce_config_rss(struct oce_dev * dev,uint16_t if_id,char * hkey,char * itbl,int tbl_sz,uint16_t rss_type,uint8_t flush)11855b9d3151SSukumar Swaminathan oce_config_rss(struct oce_dev *dev, uint16_t if_id, char *hkey, char *itbl,
11865b9d3151SSukumar Swaminathan     int  tbl_sz, uint16_t rss_type, uint8_t flush)
11875b9d3151SSukumar Swaminathan {
11885b9d3151SSukumar Swaminathan 	struct oce_mbx mbx;
11895b9d3151SSukumar Swaminathan 	struct mbx_config_nic_rss *fwcmd;
11905b9d3151SSukumar Swaminathan 	int i;
11915b9d3151SSukumar Swaminathan 	int ret = 0;
11925b9d3151SSukumar Swaminathan 
11935b9d3151SSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
11945b9d3151SSukumar Swaminathan 	fwcmd = (struct mbx_config_nic_rss *)&mbx.payload;
11955b9d3151SSukumar Swaminathan 
11965b9d3151SSukumar Swaminathan 	/* initialize the ioctl header */
11975b9d3151SSukumar Swaminathan 	mbx_common_req_hdr_init(&fwcmd->hdr, 0, 0,
11985b9d3151SSukumar Swaminathan 	    MBX_SUBSYSTEM_NIC,
11995b9d3151SSukumar Swaminathan 	    OPCODE_CONFIG_NIC_RSS,
12005b9d3151SSukumar Swaminathan 	    MBX_TIMEOUT_SEC,
12015b9d3151SSukumar Swaminathan 	    sizeof (struct mbx_config_nic_rss));
12025b9d3151SSukumar Swaminathan 	fwcmd->params.req.enable_rss = LE_16(rss_type);
12035b9d3151SSukumar Swaminathan 	fwcmd->params.req.flush = flush;
12045b9d3151SSukumar Swaminathan 	fwcmd->params.req.if_id = LE_32(if_id);
12055b9d3151SSukumar Swaminathan 
12065b9d3151SSukumar Swaminathan 	if (hkey != NULL) {
12075b9d3151SSukumar Swaminathan 		bcopy(hkey, fwcmd->params.req.hash, OCE_HKEY_SIZE);
12085b9d3151SSukumar Swaminathan 	}
12095b9d3151SSukumar Swaminathan 
12105b9d3151SSukumar Swaminathan 
12115b9d3151SSukumar Swaminathan 	/* Fill the indirection table */
12125b9d3151SSukumar Swaminathan 	for (i = 0; i < tbl_sz; i++) {
12135b9d3151SSukumar Swaminathan 		fwcmd->params.req.cputable[i] = itbl[i];
12145b9d3151SSukumar Swaminathan 	}
12155b9d3151SSukumar Swaminathan 
12165b9d3151SSukumar Swaminathan 	fwcmd->params.req.cpu_tbl_sz_log2 = LE_16(OCE_LOG2(tbl_sz));
12175b9d3151SSukumar Swaminathan 
12185b9d3151SSukumar Swaminathan 	/* fill rest of mbx */
12195b9d3151SSukumar Swaminathan 	mbx.u0.s.embedded = B_TRUE;
12205b9d3151SSukumar Swaminathan 	mbx.payload_length = sizeof (struct mbx_config_nic_rss);
12215b9d3151SSukumar Swaminathan 	DW_SWAP(u32ptr(&mbx), (OCE_BMBX_RHDR_SZ + OCE_MBX_RRHDR_SZ));
12225b9d3151SSukumar Swaminathan 
12235b9d3151SSukumar Swaminathan 	/* post the command */
12245b9d3151SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
12255b9d3151SSukumar Swaminathan 
12265b9d3151SSukumar Swaminathan 	return (ret);
12275b9d3151SSukumar Swaminathan }
12284d0e5007SSukumar Swaminathan 
12294d0e5007SSukumar Swaminathan /*
12304d0e5007SSukumar Swaminathan  * function called from the gld ioctl entry point to send a mbx to fw
12314d0e5007SSukumar Swaminathan  *
12324d0e5007SSukumar Swaminathan  * dev - software handle to the device
12334d0e5007SSukumar Swaminathan  * mp - mblk_t containing the user data
12344d0e5007SSukumar Swaminathan  * payload_len = [OUT] pointer to return the length of the payload written
12354d0e5007SSukumar Swaminathan  *
12364d0e5007SSukumar Swaminathan  * return 0 on Success
12374d0e5007SSukumar Swaminathan  */
12384d0e5007SSukumar Swaminathan int
oce_issue_mbox(struct oce_dev * dev,queue_t * wq,mblk_t * mp,uint32_t * payload_len)12394d0e5007SSukumar Swaminathan oce_issue_mbox(struct oce_dev *dev, queue_t *wq, mblk_t *mp,
12404d0e5007SSukumar Swaminathan     uint32_t *payload_len)
12414d0e5007SSukumar Swaminathan {
12424d0e5007SSukumar Swaminathan 	int ret;
12434d0e5007SSukumar Swaminathan 	struct oce_mbx mbx;
12444d0e5007SSukumar Swaminathan 	struct mbx_hdr hdr;
12454d0e5007SSukumar Swaminathan 	ddi_dma_handle_t dma_handle;
12464d0e5007SSukumar Swaminathan 	boolean_t is_embedded = B_FALSE;
12474d0e5007SSukumar Swaminathan 	uint32_t payload_length;
12484d0e5007SSukumar Swaminathan 	int num_buf = 0;
12494d0e5007SSukumar Swaminathan 	int alloc_len;
12504d0e5007SSukumar Swaminathan 	caddr_t sg_va;
12514d0e5007SSukumar Swaminathan 	ddi_acc_handle_t acc_handle;
12524d0e5007SSukumar Swaminathan 	size_t actual_len;
12534d0e5007SSukumar Swaminathan 
12544d0e5007SSukumar Swaminathan 	_NOTE(ARGUNUSED(wq));
12554d0e5007SSukumar Swaminathan 
12564d0e5007SSukumar Swaminathan 	bzero(&mbx, sizeof (struct oce_mbx));
12574d0e5007SSukumar Swaminathan 
12584d0e5007SSukumar Swaminathan 	bcopy(mp->b_cont->b_rptr, &hdr, sizeof (struct mbx_hdr));
12594d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&hdr), sizeof (struct mbx_hdr));
12604d0e5007SSukumar Swaminathan 
12614d0e5007SSukumar Swaminathan 	payload_length = hdr.u0.req.request_length +
12624d0e5007SSukumar Swaminathan 	    sizeof (struct mbx_hdr);
12634d0e5007SSukumar Swaminathan 
12644d0e5007SSukumar Swaminathan 	is_embedded = (payload_length <= sizeof (struct oce_mbx_payload));
12654d0e5007SSukumar Swaminathan 
12663abb112fSGarrett D'Amore 	alloc_len = msgdsize(mp->b_cont);
12674d0e5007SSukumar Swaminathan 
12684d0e5007SSukumar Swaminathan 	oce_log(dev, CE_NOTE, MOD_CONFIG, "Mailbox: "
12694d0e5007SSukumar Swaminathan 	    "DW[0] 0x%x DW[1] 0x%x DW[2]0x%x DW[3]0x%x,"
12704d0e5007SSukumar Swaminathan 	    "MBLKL(%lu)  ALLOCLEN(%d)",
12714d0e5007SSukumar Swaminathan 	    hdr.u0.dw[0], hdr.u0.dw[1],
12724d0e5007SSukumar Swaminathan 	    hdr.u0.dw[2], hdr.u0.dw[3],
12734d0e5007SSukumar Swaminathan 	    MBLKL(mp->b_cont), alloc_len);
12744d0e5007SSukumar Swaminathan 
12753abb112fSGarrett D'Amore 	/* get the timeout from the command header */
12763abb112fSGarrett D'Amore 	mbx.tag[0] = hdr.u0.req.timeout;
12773abb112fSGarrett D'Amore 
12784d0e5007SSukumar Swaminathan 	if (hdr.u0.req.opcode == OPCODE_WRITE_COMMON_FLASHROM) {
12794d0e5007SSukumar Swaminathan 		struct mbx_common_read_write_flashrom *fwcmd =
12804d0e5007SSukumar Swaminathan 		    (struct mbx_common_read_write_flashrom *)
12814d0e5007SSukumar Swaminathan 		    mp->b_cont->b_rptr;
12824d0e5007SSukumar Swaminathan 
12834d0e5007SSukumar Swaminathan 		if (dev->cookie != 0 && dev->cookie != hdr.u0.req.rsvd0)
12844d0e5007SSukumar Swaminathan 			return (EINVAL);
12854d0e5007SSukumar Swaminathan 
12864d0e5007SSukumar Swaminathan 		if (dev->cookie == 0)
12874d0e5007SSukumar Swaminathan 			dev->cookie = hdr.u0.req.rsvd0;
12884d0e5007SSukumar Swaminathan 		hdr.u0.req.rsvd0 = 0;
12894d0e5007SSukumar Swaminathan 
12904d0e5007SSukumar Swaminathan 		oce_log(dev, CE_NOTE, MOD_CONFIG, "Mailbox params:"
12914d0e5007SSukumar Swaminathan 		    "OPCODE(%d) OPTYPE = %d  SIZE = %d  OFFSET = %d",
12924d0e5007SSukumar Swaminathan 		    fwcmd->flash_op_code, fwcmd->flash_op_type,
12934d0e5007SSukumar Swaminathan 		    fwcmd->data_buffer_size, fwcmd->data_offset);
12944d0e5007SSukumar Swaminathan 	}
12954d0e5007SSukumar Swaminathan 
12964d0e5007SSukumar Swaminathan 	if (!is_embedded) {
12973abb112fSGarrett D'Amore 		mblk_t *tmp = NULL;
12984d0e5007SSukumar Swaminathan 		ddi_dma_cookie_t cookie;
12994d0e5007SSukumar Swaminathan 		uint32_t count = 0;
13003abb112fSGarrett D'Amore 		int offset = 0;
13014d0e5007SSukumar Swaminathan 
13024d0e5007SSukumar Swaminathan 		/* allocate dma handle */
13034d0e5007SSukumar Swaminathan 		ret = ddi_dma_alloc_handle(dev->dip,
13044d0e5007SSukumar Swaminathan 		    &oce_sgl_dma_attr, DDI_DMA_DONTWAIT, NULL,
13054d0e5007SSukumar Swaminathan 		    &dma_handle);
13064d0e5007SSukumar Swaminathan 		if (ret != DDI_SUCCESS) {
13074d0e5007SSukumar Swaminathan 			oce_log(dev, CE_NOTE, MOD_CONFIG, "%s",
13084d0e5007SSukumar Swaminathan 			    "Failed to alloc DMA handle");
13094d0e5007SSukumar Swaminathan 			ret = ENOMEM;
13104d0e5007SSukumar Swaminathan 			goto fail;
13114d0e5007SSukumar Swaminathan 		}
13124d0e5007SSukumar Swaminathan 
13134d0e5007SSukumar Swaminathan 		/* allocate the DMA-able memory */
13144d0e5007SSukumar Swaminathan 		ret = ddi_dma_mem_alloc(dma_handle, alloc_len,
13154d0e5007SSukumar Swaminathan 		    &oce_sgl_buf_accattr,
13164d0e5007SSukumar Swaminathan 		    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
13174d0e5007SSukumar Swaminathan 		    DDI_DMA_DONTWAIT,
13184d0e5007SSukumar Swaminathan 		    NULL, &sg_va, &actual_len, &acc_handle);
13194d0e5007SSukumar Swaminathan 		if (ret != DDI_SUCCESS) {
13204d0e5007SSukumar Swaminathan 			oce_log(dev, CE_NOTE, MOD_CONFIG, "%s",
13214d0e5007SSukumar Swaminathan 			    "Failed to alloc DMA memory");
13224d0e5007SSukumar Swaminathan 			ret = ENOMEM;
13234d0e5007SSukumar Swaminathan 			goto dma_alloc_fail;
13244d0e5007SSukumar Swaminathan 		}
13254d0e5007SSukumar Swaminathan 
13263abb112fSGarrett D'Amore 		for (tmp = mp->b_cont; tmp != NULL; tmp = tmp->b_cont) {
13273abb112fSGarrett D'Amore 			bcopy((caddr_t)tmp->b_rptr, sg_va + offset, MBLKL(tmp));
13283abb112fSGarrett D'Amore 			offset += MBLKL(tmp);
13293abb112fSGarrett D'Amore 		}
13304d0e5007SSukumar Swaminathan 
13314d0e5007SSukumar Swaminathan 		/* bind mblk mem to handle */
13324d0e5007SSukumar Swaminathan 		ret = ddi_dma_addr_bind_handle(
13334d0e5007SSukumar Swaminathan 		    dma_handle,
13344d0e5007SSukumar Swaminathan 		    (struct as *)0, sg_va,
13353abb112fSGarrett D'Amore 		    alloc_len,
13364d0e5007SSukumar Swaminathan 		    DDI_DMA_RDWR | DDI_DMA_CONSISTENT,
13374d0e5007SSukumar Swaminathan 		    DDI_DMA_DONTWAIT, NULL, &cookie, &count);
13384d0e5007SSukumar Swaminathan 		if (ret != DDI_DMA_MAPPED) {
13394d0e5007SSukumar Swaminathan 			ret = ENOMEM;
13404d0e5007SSukumar Swaminathan 			oce_log(dev, CE_NOTE, MOD_CONFIG,
13414d0e5007SSukumar Swaminathan 			    "Failed to bind DMA handle ret code: %d",
13424d0e5007SSukumar Swaminathan 			    ret);
13434d0e5007SSukumar Swaminathan 			goto dma_bind_fail;
13444d0e5007SSukumar Swaminathan 		}
13454d0e5007SSukumar Swaminathan 
13464d0e5007SSukumar Swaminathan 		for (num_buf = 0; num_buf < count; num_buf++) {
13474d0e5007SSukumar Swaminathan 			/* fill the mbx sglist */
13484d0e5007SSukumar Swaminathan 			mbx.payload.u0.u1.sgl[num_buf].pa_lo =
13494d0e5007SSukumar Swaminathan 			    ADDR_LO(cookie.dmac_laddress);
13504d0e5007SSukumar Swaminathan 			mbx.payload.u0.u1.sgl[num_buf].pa_hi =
13514d0e5007SSukumar Swaminathan 			    ADDR_HI(cookie.dmac_laddress);
13524d0e5007SSukumar Swaminathan 			mbx.payload.u0.u1.sgl[num_buf].length =
13534d0e5007SSukumar Swaminathan 			    (uint32_t)cookie.dmac_size;
13544d0e5007SSukumar Swaminathan 			mbx.payload_length +=
13554d0e5007SSukumar Swaminathan 			    mbx.payload.u0.u1.sgl[num_buf].length;
13564d0e5007SSukumar Swaminathan 			mbx.u0.s.sge_count++;
13574d0e5007SSukumar Swaminathan 
13584d0e5007SSukumar Swaminathan 			if (count > 1)
13594d0e5007SSukumar Swaminathan 				(void) ddi_dma_nextcookie(dma_handle, &cookie);
13604d0e5007SSukumar Swaminathan 		}
13614d0e5007SSukumar Swaminathan 		mbx.u0.s.embedded = 0;
13624d0e5007SSukumar Swaminathan 
13634d0e5007SSukumar Swaminathan 		DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ +
13644d0e5007SSukumar Swaminathan 		    (sizeof (struct oce_mq_sge) * count));
13654d0e5007SSukumar Swaminathan 	} else {
13664d0e5007SSukumar Swaminathan 		/* fill rest of mbx */
13674d0e5007SSukumar Swaminathan 		mbx.u0.s.embedded = 1;
13684d0e5007SSukumar Swaminathan 		mbx.payload_length = payload_length;
13694d0e5007SSukumar Swaminathan 		bcopy(mp->b_cont->b_rptr, &mbx.payload, payload_length);
13704d0e5007SSukumar Swaminathan 
13714d0e5007SSukumar Swaminathan 		DW_SWAP(u32ptr(&mbx), OCE_BMBX_RHDR_SZ);
13724d0e5007SSukumar Swaminathan 	}
13734d0e5007SSukumar Swaminathan 
13744d0e5007SSukumar Swaminathan 	/* now post the command */
13754d0e5007SSukumar Swaminathan 	ret = oce_mbox_post(dev, &mbx, NULL);
13764d0e5007SSukumar Swaminathan 
13774d0e5007SSukumar Swaminathan 	bcopy(mp->b_cont->b_rptr, &hdr, sizeof (struct mbx_hdr));
13784d0e5007SSukumar Swaminathan 	DW_SWAP(u32ptr(&hdr), sizeof (struct mbx_hdr));
13794d0e5007SSukumar Swaminathan 
13804d0e5007SSukumar Swaminathan 	if (ret != DDI_SUCCESS) {
13814d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG,
13824d0e5007SSukumar Swaminathan 		    "Failed to post the mailbox: %d", ret);
13834d0e5007SSukumar Swaminathan 
13844d0e5007SSukumar Swaminathan 		*payload_len = hdr.u0.rsp.rsp_length +
13854d0e5007SSukumar Swaminathan 		    sizeof (struct mbx_hdr);
13864d0e5007SSukumar Swaminathan 		if (is_embedded) {
13874d0e5007SSukumar Swaminathan 			bcopy(&mbx.payload, mp->b_cont->b_rptr,
13884d0e5007SSukumar Swaminathan 			    MBLKL(mp->b_cont));
13894d0e5007SSukumar Swaminathan 			goto fail;
13904d0e5007SSukumar Swaminathan 		} else {
13914d0e5007SSukumar Swaminathan 			(void) ddi_dma_sync(dma_handle, 0, 0,
13924d0e5007SSukumar Swaminathan 			    DDI_DMA_SYNC_FORKERNEL);
139312d61dabSSukumar Swaminathan 
139412d61dabSSukumar Swaminathan 			if (oce_fm_check_dma_handle(dev, dma_handle) !=
139512d61dabSSukumar Swaminathan 			    DDI_FM_OK) {
139612d61dabSSukumar Swaminathan 				ddi_fm_service_impact(dev->dip,
139712d61dabSSukumar Swaminathan 				    DDI_SERVICE_DEGRADED);
139812d61dabSSukumar Swaminathan 			}
13994d0e5007SSukumar Swaminathan 			bcopy(sg_va, mp->b_cont->b_rptr,
14004d0e5007SSukumar Swaminathan 			    sizeof (struct mbx_hdr));
14014d0e5007SSukumar Swaminathan 			goto post_fail;
14024d0e5007SSukumar Swaminathan 		}
14034d0e5007SSukumar Swaminathan 	}
14044d0e5007SSukumar Swaminathan 
14054d0e5007SSukumar Swaminathan 	if (hdr.u0.req.opcode == OPCODE_WRITE_COMMON_FLASHROM) {
14064d0e5007SSukumar Swaminathan 		struct mbx_common_read_write_flashrom *fwcmd =
14074d0e5007SSukumar Swaminathan 		    (struct mbx_common_read_write_flashrom *)
14084d0e5007SSukumar Swaminathan 		    mp->b_cont->b_rptr;
14094d0e5007SSukumar Swaminathan 
14104d0e5007SSukumar Swaminathan 		if (LE_32(fwcmd->flash_op_code) == MGMT_FLASHROM_OPCODE_FLASH)
14114d0e5007SSukumar Swaminathan 			dev->cookie = 0;
14124d0e5007SSukumar Swaminathan 	}
14134d0e5007SSukumar Swaminathan 
14144d0e5007SSukumar Swaminathan 	payload_length = hdr.u0.rsp.rsp_length + sizeof (struct mbx_hdr);
14154d0e5007SSukumar Swaminathan 
14164d0e5007SSukumar Swaminathan 	/* Copy the response back only if this is an embedded mbx cmd */
14174d0e5007SSukumar Swaminathan 	if (is_embedded) {
14184d0e5007SSukumar Swaminathan 		bcopy(&mbx.payload, mp->b_cont->b_rptr,
14194d0e5007SSukumar Swaminathan 		    min(payload_length, MBLKL(mp->b_cont)));
14204d0e5007SSukumar Swaminathan 	} else {
14213abb112fSGarrett D'Amore 		mblk_t *tmp = NULL;
14223abb112fSGarrett D'Amore 		int offset = 0;
14234d0e5007SSukumar Swaminathan 		/* sync */
14244d0e5007SSukumar Swaminathan 		(void) ddi_dma_sync(dma_handle, 0, 0,
14254d0e5007SSukumar Swaminathan 		    DDI_DMA_SYNC_FORKERNEL);
142612d61dabSSukumar Swaminathan 		if (oce_fm_check_dma_handle(dev, dma_handle) != DDI_FM_OK) {
142712d61dabSSukumar Swaminathan 			ddi_fm_service_impact(dev->dip, DDI_SERVICE_DEGRADED);
142812d61dabSSukumar Swaminathan 		}
14294d0e5007SSukumar Swaminathan 
14304d0e5007SSukumar Swaminathan 		/* copy back from kernel allocated buffer to user buffer  */
14313abb112fSGarrett D'Amore 		for (tmp = mp->b_cont; tmp != NULL; tmp = tmp->b_cont) {
14323abb112fSGarrett D'Amore 			bcopy(sg_va + offset, tmp->b_rptr, MBLKL(tmp));
14333abb112fSGarrett D'Amore 			offset += MBLKL(tmp);
14343abb112fSGarrett D'Amore 		}
14354d0e5007SSukumar Swaminathan 
14364d0e5007SSukumar Swaminathan 		/* unbind and free dma handles */
14374d0e5007SSukumar Swaminathan 		(void) ddi_dma_unbind_handle(dma_handle);
14384d0e5007SSukumar Swaminathan 		ddi_dma_mem_free(&acc_handle);
14394d0e5007SSukumar Swaminathan 		ddi_dma_free_handle(&dma_handle);
14404d0e5007SSukumar Swaminathan 	}
14414d0e5007SSukumar Swaminathan 
14424d0e5007SSukumar Swaminathan 	*payload_len = payload_length;
14434d0e5007SSukumar Swaminathan 
14444d0e5007SSukumar Swaminathan 	return (0);
14454d0e5007SSukumar Swaminathan 
14464d0e5007SSukumar Swaminathan post_fail:
14474d0e5007SSukumar Swaminathan 	(void) ddi_dma_unbind_handle(dma_handle);
14484d0e5007SSukumar Swaminathan 
14494d0e5007SSukumar Swaminathan dma_bind_fail:
14504d0e5007SSukumar Swaminathan 	ddi_dma_mem_free(&acc_handle);
14514d0e5007SSukumar Swaminathan 
14524d0e5007SSukumar Swaminathan dma_alloc_fail:
14534d0e5007SSukumar Swaminathan 	ddi_dma_free_handle(&dma_handle);
14544d0e5007SSukumar Swaminathan 
14554d0e5007SSukumar Swaminathan fail:
14564d0e5007SSukumar Swaminathan alloc_err:
14574d0e5007SSukumar Swaminathan 	if (hdr.u0.req.opcode == OPCODE_WRITE_COMMON_FLASHROM) {
14584d0e5007SSukumar Swaminathan 		dev->cookie = 0;
14594d0e5007SSukumar Swaminathan 	}
14604d0e5007SSukumar Swaminathan 	return (ret);
14614d0e5007SSukumar Swaminathan }
1462