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.  */
234d0e5007SSukumar Swaminathan 
2415c07adcSJohn Levon /*
2515c07adcSJohn Levon  * Copyright (c) 2018, Joyent, Inc.
2615c07adcSJohn Levon  */
2715c07adcSJohn Levon 
284d0e5007SSukumar Swaminathan /*
294d0e5007SSukumar Swaminathan  * Source file containing the implementation of the driver entry points
304d0e5007SSukumar Swaminathan  * and related helper functions
314d0e5007SSukumar Swaminathan  */
324d0e5007SSukumar Swaminathan 
334d0e5007SSukumar Swaminathan #include <oce_impl.h>
344d0e5007SSukumar Swaminathan #include <oce_ioctl.h>
354d0e5007SSukumar Swaminathan 
364d0e5007SSukumar Swaminathan /* array of properties supported by this driver */
370dc2366fSVenugopal Iyer char *oce_priv_props[] = {
380dc2366fSVenugopal Iyer 	"_tx_ring_size",
390dc2366fSVenugopal Iyer 	"_tx_bcopy_limit",
400dc2366fSVenugopal Iyer 	"_rx_ring_size",
411878b971SVenugopal Iyer 	"_rx_bcopy_limit",
420dc2366fSVenugopal Iyer 	NULL
434d0e5007SSukumar Swaminathan };
444d0e5007SSukumar Swaminathan 
455b9d3151SSukumar Swaminathan extern int pow10[];
465b9d3151SSukumar Swaminathan 
474d0e5007SSukumar Swaminathan /* ---[ static function declarations ]----------------------------------- */
484d0e5007SSukumar Swaminathan static int oce_set_priv_prop(struct oce_dev *dev, const char *name,
494d0e5007SSukumar Swaminathan     uint_t size, const void *val);
504d0e5007SSukumar Swaminathan 
514d0e5007SSukumar Swaminathan static int oce_get_priv_prop(struct oce_dev *dev, const char *name,
520dc2366fSVenugopal Iyer     uint_t size, void *val);
534d0e5007SSukumar Swaminathan 
544d0e5007SSukumar Swaminathan /* ---[ GLD entry points ]----------------------------------------------- */
554d0e5007SSukumar Swaminathan int
oce_m_start(void * arg)564d0e5007SSukumar Swaminathan oce_m_start(void *arg)
574d0e5007SSukumar Swaminathan {
584d0e5007SSukumar Swaminathan 	struct oce_dev *dev = arg;
594d0e5007SSukumar Swaminathan 	int ret;
604d0e5007SSukumar Swaminathan 
614d0e5007SSukumar Swaminathan 	mutex_enter(&dev->dev_lock);
624d0e5007SSukumar Swaminathan 
634d0e5007SSukumar Swaminathan 	if (dev->state & STATE_MAC_STARTED) {
644d0e5007SSukumar Swaminathan 		mutex_exit(&dev->dev_lock);
654d0e5007SSukumar Swaminathan 		return (0);
664d0e5007SSukumar Swaminathan 	}
674d0e5007SSukumar Swaminathan 
684d0e5007SSukumar Swaminathan 	if (dev->suspended) {
694d0e5007SSukumar Swaminathan 		mutex_exit(&dev->dev_lock);
704d0e5007SSukumar Swaminathan 		return (EIO);
714d0e5007SSukumar Swaminathan 	}
724d0e5007SSukumar Swaminathan 	ret = oce_start(dev);
734d0e5007SSukumar Swaminathan 	if (ret != DDI_SUCCESS) {
744d0e5007SSukumar Swaminathan 		mutex_exit(&dev->dev_lock);
754d0e5007SSukumar Swaminathan 		return (EIO);
764d0e5007SSukumar Swaminathan 	}
774d0e5007SSukumar Swaminathan 
784d0e5007SSukumar Swaminathan 	dev->state |= STATE_MAC_STARTED;
794d0e5007SSukumar Swaminathan 	mutex_exit(&dev->dev_lock);
804d0e5007SSukumar Swaminathan 
814d0e5007SSukumar Swaminathan 
824d0e5007SSukumar Swaminathan 	return (DDI_SUCCESS);
834d0e5007SSukumar Swaminathan }
844d0e5007SSukumar Swaminathan 
854d0e5007SSukumar Swaminathan int
oce_start(struct oce_dev * dev)864d0e5007SSukumar Swaminathan oce_start(struct oce_dev *dev)
874d0e5007SSukumar Swaminathan {
884d0e5007SSukumar Swaminathan 	int qidx = 0;
895b9d3151SSukumar Swaminathan 	struct link_status link = {0};
904d0e5007SSukumar Swaminathan 
914d0e5007SSukumar Swaminathan 	/* get link status */
925b9d3151SSukumar Swaminathan 	(void) oce_get_link_status(dev, &link);
934d0e5007SSukumar Swaminathan 
945b9d3151SSukumar Swaminathan 	dev->link_status  = (link.logical_link_status == NTWK_LOGICAL_LINK_UP) ?
955b9d3151SSukumar Swaminathan 	    LINK_STATE_UP : LINK_STATE_DOWN;
965b9d3151SSukumar Swaminathan 
975b9d3151SSukumar Swaminathan 	dev->link_speed = link.qos_link_speed ? link.qos_link_speed * 10 :
985b9d3151SSukumar Swaminathan 	    pow10[link.mac_speed];
998d738d7dSSukumar Swaminathan 
1005b9d3151SSukumar Swaminathan 	mac_link_update(dev->mac_handle, dev->link_status);
1015b9d3151SSukumar Swaminathan 
1025b9d3151SSukumar Swaminathan 	for (qidx = 0; qidx < dev->nwqs; qidx++) {
1035b9d3151SSukumar Swaminathan 		(void) oce_start_wq(dev->wq[qidx]);
1045b9d3151SSukumar Swaminathan 	}
1055b9d3151SSukumar Swaminathan 	for (qidx = 0; qidx < dev->nrqs; qidx++) {
1065b9d3151SSukumar Swaminathan 		(void) oce_start_rq(dev->rq[qidx]);
1075b9d3151SSukumar Swaminathan 	}
1088d738d7dSSukumar Swaminathan 	(void) oce_start_mq(dev->mq);
1098d738d7dSSukumar Swaminathan 	/* enable interrupts */
1108d738d7dSSukumar Swaminathan 	oce_ei(dev);
1114d0e5007SSukumar Swaminathan 	/* arm the eqs */
1124d0e5007SSukumar Swaminathan 	for (qidx = 0; qidx < dev->neqs; qidx++) {
1134d0e5007SSukumar Swaminathan 		oce_arm_eq(dev, dev->eq[qidx]->eq_id, 0, B_TRUE, B_FALSE);
1144d0e5007SSukumar Swaminathan 	}
1155b9d3151SSukumar Swaminathan 	/* TODO update state */
1164d0e5007SSukumar Swaminathan 	return (DDI_SUCCESS);
1174d0e5007SSukumar Swaminathan } /* oce_start */
1184d0e5007SSukumar Swaminathan 
1194d0e5007SSukumar Swaminathan 
1204d0e5007SSukumar Swaminathan void
oce_m_stop(void * arg)1214d0e5007SSukumar Swaminathan oce_m_stop(void *arg)
1224d0e5007SSukumar Swaminathan {
1234d0e5007SSukumar Swaminathan 	struct oce_dev *dev = arg;
1244d0e5007SSukumar Swaminathan 
1254d0e5007SSukumar Swaminathan 	/* disable interrupts */
1264d0e5007SSukumar Swaminathan 
1274d0e5007SSukumar Swaminathan 	mutex_enter(&dev->dev_lock);
1284d0e5007SSukumar Swaminathan 	if (dev->suspended) {
1294d0e5007SSukumar Swaminathan 		mutex_exit(&dev->dev_lock);
1304d0e5007SSukumar Swaminathan 		return;
1314d0e5007SSukumar Swaminathan 	}
1328d738d7dSSukumar Swaminathan 	dev->state |= STATE_MAC_STOPPING;
1334d0e5007SSukumar Swaminathan 	oce_stop(dev);
1344d0e5007SSukumar Swaminathan 	dev->state &= ~(STATE_MAC_STOPPING | STATE_MAC_STARTED);
1354d0e5007SSukumar Swaminathan 	mutex_exit(&dev->dev_lock);
1364d0e5007SSukumar Swaminathan }
1378d738d7dSSukumar Swaminathan /* called with Tx/Rx comp locks held */
1384d0e5007SSukumar Swaminathan void
oce_stop(struct oce_dev * dev)1394d0e5007SSukumar Swaminathan oce_stop(struct oce_dev *dev)
1404d0e5007SSukumar Swaminathan {
1415b9d3151SSukumar Swaminathan 	int qidx;
1428d738d7dSSukumar Swaminathan 	/* disable interrupts */
1438d738d7dSSukumar Swaminathan 	oce_di(dev);
1445b9d3151SSukumar Swaminathan 	for (qidx = 0; qidx < dev->nwqs; qidx++) {
1455b9d3151SSukumar Swaminathan 		mutex_enter(&dev->wq[qidx]->tx_lock);
1465b9d3151SSukumar Swaminathan 	}
1478d738d7dSSukumar Swaminathan 	mutex_enter(&dev->mq->lock);
1488d738d7dSSukumar Swaminathan 	/* complete the pending Tx */
1495b9d3151SSukumar Swaminathan 	for (qidx = 0; qidx < dev->nwqs; qidx++)
1505b9d3151SSukumar Swaminathan 		oce_clean_wq(dev->wq[qidx]);
1518d738d7dSSukumar Swaminathan 	/* Release all the locks */
1528d738d7dSSukumar Swaminathan 	mutex_exit(&dev->mq->lock);
1535b9d3151SSukumar Swaminathan 	for (qidx = 0; qidx < dev->nwqs; qidx++)
1545b9d3151SSukumar Swaminathan 		mutex_exit(&dev->wq[qidx]->tx_lock);
1555b9d3151SSukumar Swaminathan 	if (dev->link_status == LINK_STATE_UP) {
1565b9d3151SSukumar Swaminathan 		dev->link_status = LINK_STATE_UNKNOWN;
1575b9d3151SSukumar Swaminathan 		mac_link_update(dev->mac_handle, dev->link_status);
1585b9d3151SSukumar Swaminathan 	}
1594d0e5007SSukumar Swaminathan 
1604d0e5007SSukumar Swaminathan } /* oce_stop */
1614d0e5007SSukumar Swaminathan 
1624d0e5007SSukumar Swaminathan int
oce_m_multicast(void * arg,boolean_t add,const uint8_t * mca)1634d0e5007SSukumar Swaminathan oce_m_multicast(void *arg, boolean_t add, const uint8_t *mca)
1644d0e5007SSukumar Swaminathan {
1654d0e5007SSukumar Swaminathan 	struct oce_dev *dev = (struct oce_dev *)arg;
1664d0e5007SSukumar Swaminathan 	struct ether_addr  *mca_drv_list;
1678d738d7dSSukumar Swaminathan 	struct ether_addr  mca_hw_list[OCE_MAX_MCA];
1685b9d3151SSukumar Swaminathan 	uint16_t new_mcnt = dev->num_mca;
1694d0e5007SSukumar Swaminathan 	int ret;
1704d0e5007SSukumar Swaminathan 	int i;
1714d0e5007SSukumar Swaminathan 
1724d0e5007SSukumar Swaminathan 	/* check the address */
1734d0e5007SSukumar Swaminathan 	if ((mca[0] & 0x1) == 0) {
1744d0e5007SSukumar Swaminathan 		return (EINVAL);
1754d0e5007SSukumar Swaminathan 	}
1764d0e5007SSukumar Swaminathan 	/* Allocate the local array for holding the addresses temporarily */
177*ce17336eSAndy Fiddaman 	bzero(&mca_hw_list, sizeof (mca_hw_list));
1784d0e5007SSukumar Swaminathan 	mca_drv_list = &dev->multi_cast[0];
1798d738d7dSSukumar Swaminathan 
1808d738d7dSSukumar Swaminathan 	DEV_LOCK(dev);
1814d0e5007SSukumar Swaminathan 	if (add) {
1824d0e5007SSukumar Swaminathan 		/* check if we exceeded hw max  supported */
1835b9d3151SSukumar Swaminathan 		if (new_mcnt < OCE_MAX_MCA) {
1848d738d7dSSukumar Swaminathan 			/* copy entire dev mca to the mbx */
1858d738d7dSSukumar Swaminathan 			bcopy((void*)mca_drv_list,
1868d738d7dSSukumar Swaminathan 			    (void*)mca_hw_list,
1878d738d7dSSukumar Swaminathan 			    (dev->num_mca * sizeof (struct ether_addr)));
1888d738d7dSSukumar Swaminathan 			/* Append the new one to local list */
1898d738d7dSSukumar Swaminathan 			bcopy(mca, &mca_hw_list[dev->num_mca],
1908d738d7dSSukumar Swaminathan 			    sizeof (struct ether_addr));
1914d0e5007SSukumar Swaminathan 		}
1925b9d3151SSukumar Swaminathan 		new_mcnt++;
1934d0e5007SSukumar Swaminathan 	} else {
1948d738d7dSSukumar Swaminathan 		struct ether_addr *hwlistp = &mca_hw_list[0];
1954d0e5007SSukumar Swaminathan 		for (i = 0; i < dev->num_mca; i++) {
1964d0e5007SSukumar Swaminathan 			/* copy only if it does not match */
1974d0e5007SSukumar Swaminathan 			if (bcmp((mca_drv_list + i), mca, ETHERADDRL)) {
1984d0e5007SSukumar Swaminathan 				bcopy(mca_drv_list + i, hwlistp,
1994d0e5007SSukumar Swaminathan 				    ETHERADDRL);
2004d0e5007SSukumar Swaminathan 				hwlistp++;
2015b9d3151SSukumar Swaminathan 			} else {
2025b9d3151SSukumar Swaminathan 				new_mcnt--;
2034d0e5007SSukumar Swaminathan 			}
2044d0e5007SSukumar Swaminathan 		}
2054d0e5007SSukumar Swaminathan 	}
2064d0e5007SSukumar Swaminathan 
2074d0e5007SSukumar Swaminathan 	if (dev->suspended) {
2084d0e5007SSukumar Swaminathan 		goto finish;
2094d0e5007SSukumar Swaminathan 	}
2105b9d3151SSukumar Swaminathan 	if (new_mcnt > OCE_MAX_MCA) {
2115b9d3151SSukumar Swaminathan 		ret = oce_set_multicast_table(dev, dev->if_id, &mca_hw_list[0],
2125b9d3151SSukumar Swaminathan 		    OCE_MAX_MCA, B_TRUE);
2138d738d7dSSukumar Swaminathan 	} else {
2148d738d7dSSukumar Swaminathan 		ret = oce_set_multicast_table(dev, dev->if_id,
2158d738d7dSSukumar Swaminathan 		    &mca_hw_list[0], new_mcnt, B_FALSE);
2168d738d7dSSukumar Swaminathan 	}
21715c07adcSJohn Levon 	if (ret != 0) {
2183abb112fSGarrett D'Amore 		oce_log(dev, CE_WARN, MOD_CONFIG,
2193abb112fSGarrett D'Amore 		    "mcast %s fails", add ? "ADD" : "DEL");
2208d738d7dSSukumar Swaminathan 		DEV_UNLOCK(dev);
2214d0e5007SSukumar Swaminathan 		return (EIO);
2224d0e5007SSukumar Swaminathan 	}
2234d0e5007SSukumar Swaminathan 	/*
2244d0e5007SSukumar Swaminathan 	 *  Copy the local structure to dev structure
2254d0e5007SSukumar Swaminathan 	 */
2264d0e5007SSukumar Swaminathan finish:
2278d738d7dSSukumar Swaminathan 	if (new_mcnt && new_mcnt <= OCE_MAX_MCA) {
2288d738d7dSSukumar Swaminathan 		bcopy(mca_hw_list, mca_drv_list,
2298d738d7dSSukumar Swaminathan 		    new_mcnt * sizeof (struct ether_addr));
2305b9d3151SSukumar Swaminathan 
2315b9d3151SSukumar Swaminathan 		dev->num_mca = (uint16_t)new_mcnt;
2328d738d7dSSukumar Swaminathan 	}
2338d738d7dSSukumar Swaminathan 	DEV_UNLOCK(dev);
2343abb112fSGarrett D'Amore 	oce_log(dev, CE_NOTE, MOD_CONFIG,
2353abb112fSGarrett D'Amore 	    "mcast %s, addr=%02x:%02x:%02x:%02x:%02x:%02x, num_mca=%d",
2363abb112fSGarrett D'Amore 	    add ? "ADD" : "DEL",
2373abb112fSGarrett D'Amore 	    mca[0], mca[1], mca[2], mca[3], mca[4], mca[5],
2383abb112fSGarrett D'Amore 	    dev->num_mca);
2394d0e5007SSukumar Swaminathan 	return (0);
2404d0e5007SSukumar Swaminathan } /* oce_m_multicast */
2414d0e5007SSukumar Swaminathan 
2424d0e5007SSukumar Swaminathan int
oce_m_unicast(void * arg,const uint8_t * uca)2434d0e5007SSukumar Swaminathan oce_m_unicast(void *arg, const uint8_t *uca)
2444d0e5007SSukumar Swaminathan {
2454d0e5007SSukumar Swaminathan 	struct oce_dev *dev = arg;
2464d0e5007SSukumar Swaminathan 	int ret;
2474d0e5007SSukumar Swaminathan 
2484d0e5007SSukumar Swaminathan 	DEV_LOCK(dev);
2494d0e5007SSukumar Swaminathan 	if (dev->suspended) {
2504d0e5007SSukumar Swaminathan 		bcopy(uca, dev->unicast_addr, ETHERADDRL);
2513abb112fSGarrett D'Amore 		dev->num_smac = 0;
2524d0e5007SSukumar Swaminathan 		DEV_UNLOCK(dev);
2534d0e5007SSukumar Swaminathan 		return (DDI_SUCCESS);
2544d0e5007SSukumar Swaminathan 	}
2554d0e5007SSukumar Swaminathan 
2564d0e5007SSukumar Swaminathan 	/* Delete previous one and add new one */
2578d738d7dSSukumar Swaminathan 	ret = oce_del_mac(dev, dev->if_id, &dev->pmac_id);
2584d0e5007SSukumar Swaminathan 	if (ret != DDI_SUCCESS) {
2598d738d7dSSukumar Swaminathan 		DEV_UNLOCK(dev);
2604d0e5007SSukumar Swaminathan 		return (EIO);
2614d0e5007SSukumar Swaminathan 	}
2623abb112fSGarrett D'Amore 	dev->num_smac = 0;
2635b9d3151SSukumar Swaminathan 	bzero(dev->unicast_addr, ETHERADDRL);
2644d0e5007SSukumar Swaminathan 
2654d0e5007SSukumar Swaminathan 	/* Set the New MAC addr earlier is no longer valid */
2668d738d7dSSukumar Swaminathan 	ret = oce_add_mac(dev, dev->if_id, uca, &dev->pmac_id);
2674d0e5007SSukumar Swaminathan 	if (ret != DDI_SUCCESS) {
2688d738d7dSSukumar Swaminathan 		DEV_UNLOCK(dev);
2694d0e5007SSukumar Swaminathan 		return (EIO);
2704d0e5007SSukumar Swaminathan 	}
2715b9d3151SSukumar Swaminathan 	bcopy(uca, dev->unicast_addr, ETHERADDRL);
2723abb112fSGarrett D'Amore 	dev->num_smac = 1;
2738d738d7dSSukumar Swaminathan 	DEV_UNLOCK(dev);
2744d0e5007SSukumar Swaminathan 	return (ret);
2754d0e5007SSukumar Swaminathan } /* oce_m_unicast */
2764d0e5007SSukumar Swaminathan 
2775b9d3151SSukumar Swaminathan /*
2785b9d3151SSukumar Swaminathan  * Hashing policy for load balancing over the set of TX rings
2795b9d3151SSukumar Swaminathan  * available to the driver.
2805b9d3151SSukumar Swaminathan  */
2814d0e5007SSukumar Swaminathan mblk_t *
oce_m_send(void * arg,mblk_t * mp)2824d0e5007SSukumar Swaminathan oce_m_send(void *arg, mblk_t *mp)
2834d0e5007SSukumar Swaminathan {
2844d0e5007SSukumar Swaminathan 	struct oce_dev *dev = arg;
2854d0e5007SSukumar Swaminathan 	mblk_t *nxt_pkt;
2864d0e5007SSukumar Swaminathan 	mblk_t *rmp = NULL;
2878d738d7dSSukumar Swaminathan 	struct oce_wq *wq;
2884d0e5007SSukumar Swaminathan 
2894d0e5007SSukumar Swaminathan 	DEV_LOCK(dev);
2908d738d7dSSukumar Swaminathan 	if (dev->suspended || !(dev->state & STATE_MAC_STARTED)) {
2914d0e5007SSukumar Swaminathan 		DEV_UNLOCK(dev);
2924d0e5007SSukumar Swaminathan 		freemsg(mp);
2934d0e5007SSukumar Swaminathan 		return (NULL);
2944d0e5007SSukumar Swaminathan 	}
2954d0e5007SSukumar Swaminathan 	DEV_UNLOCK(dev);
2965b9d3151SSukumar Swaminathan 	/*
2975b9d3151SSukumar Swaminathan 	 * Hash to pick a wq
2985b9d3151SSukumar Swaminathan 	 */
2995b9d3151SSukumar Swaminathan 	wq = oce_get_wq(dev, mp);
3004d0e5007SSukumar Swaminathan 
3014d0e5007SSukumar Swaminathan 	while (mp != NULL) {
3024d0e5007SSukumar Swaminathan 		/* Save the Pointer since mp will be freed in case of copy */
3034d0e5007SSukumar Swaminathan 		nxt_pkt = mp->b_next;
3044d0e5007SSukumar Swaminathan 		mp->b_next = NULL;
3054d0e5007SSukumar Swaminathan 		/* Hardcode wq since we have only one */
3068d738d7dSSukumar Swaminathan 		rmp = oce_send_packet(wq, mp);
3074d0e5007SSukumar Swaminathan 		if (rmp != NULL) {
3088d738d7dSSukumar Swaminathan 			/* reschedule Tx */
3098d738d7dSSukumar Swaminathan 			wq->resched = B_TRUE;
3108d738d7dSSukumar Swaminathan 			oce_arm_cq(dev, wq->cq->cq_id, 0, B_TRUE);
3114d0e5007SSukumar Swaminathan 			/* restore the chain */
3124d0e5007SSukumar Swaminathan 			rmp->b_next = nxt_pkt;
3134d0e5007SSukumar Swaminathan 			break;
3144d0e5007SSukumar Swaminathan 		}
3154d0e5007SSukumar Swaminathan 		mp  = nxt_pkt;
3164d0e5007SSukumar Swaminathan 	}
3174d0e5007SSukumar Swaminathan 	return (rmp);
3184d0e5007SSukumar Swaminathan } /* oce_send */
3194d0e5007SSukumar Swaminathan 
3204d0e5007SSukumar Swaminathan boolean_t
oce_m_getcap(void * arg,mac_capab_t cap,void * data)3214d0e5007SSukumar Swaminathan oce_m_getcap(void *arg, mac_capab_t cap, void *data)
3224d0e5007SSukumar Swaminathan {
3234d0e5007SSukumar Swaminathan 	struct oce_dev *dev = arg;
3244d0e5007SSukumar Swaminathan 	boolean_t ret = B_TRUE;
3254d0e5007SSukumar Swaminathan 	switch (cap) {
3264d0e5007SSukumar Swaminathan 
3274d0e5007SSukumar Swaminathan 	case MAC_CAPAB_HCKSUM: {
3284d0e5007SSukumar Swaminathan 		uint32_t *csum_flags = u32ptr(data);
3294d0e5007SSukumar Swaminathan 		*csum_flags = HCKSUM_ENABLE |
3304d0e5007SSukumar Swaminathan 		    HCKSUM_INET_FULL_V4 |
3314d0e5007SSukumar Swaminathan 		    HCKSUM_IPHDRCKSUM;
3324d0e5007SSukumar Swaminathan 		break;
3334d0e5007SSukumar Swaminathan 	}
3344d0e5007SSukumar Swaminathan 	case MAC_CAPAB_LSO: {
3354d0e5007SSukumar Swaminathan 		mac_capab_lso_t *mcap_lso = (mac_capab_lso_t *)data;
3364d0e5007SSukumar Swaminathan 		if (dev->lso_capable) {
3374d0e5007SSukumar Swaminathan 			mcap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4;
3384d0e5007SSukumar Swaminathan 			mcap_lso->lso_basic_tcp_ipv4.lso_max = OCE_LSO_MAX_SIZE;
3394d0e5007SSukumar Swaminathan 		} else {
3404d0e5007SSukumar Swaminathan 			ret = B_FALSE;
3414d0e5007SSukumar Swaminathan 		}
3424d0e5007SSukumar Swaminathan 		break;
3434d0e5007SSukumar Swaminathan 	}
3444d0e5007SSukumar Swaminathan 	default:
3454d0e5007SSukumar Swaminathan 		ret = B_FALSE;
3464d0e5007SSukumar Swaminathan 		break;
3474d0e5007SSukumar Swaminathan 	}
3484d0e5007SSukumar Swaminathan 	return (ret);
3494d0e5007SSukumar Swaminathan } /* oce_m_getcap */
3504d0e5007SSukumar Swaminathan 
3514d0e5007SSukumar Swaminathan int
oce_m_setprop(void * arg,const char * name,mac_prop_id_t id,uint_t size,const void * val)3524d0e5007SSukumar Swaminathan oce_m_setprop(void *arg, const char *name, mac_prop_id_t id,
3534d0e5007SSukumar Swaminathan     uint_t size, const void *val)
3544d0e5007SSukumar Swaminathan {
3554d0e5007SSukumar Swaminathan 	struct oce_dev *dev = arg;
3564d0e5007SSukumar Swaminathan 	int ret = 0;
3574d0e5007SSukumar Swaminathan 
3588d738d7dSSukumar Swaminathan 	DEV_LOCK(dev);
3594d0e5007SSukumar Swaminathan 	switch (id) {
3604d0e5007SSukumar Swaminathan 	case MAC_PROP_MTU: {
3614d0e5007SSukumar Swaminathan 		uint32_t mtu;
3624d0e5007SSukumar Swaminathan 
3634d0e5007SSukumar Swaminathan 		bcopy(val, &mtu, sizeof (uint32_t));
3644d0e5007SSukumar Swaminathan 
3654d0e5007SSukumar Swaminathan 		if (dev->mtu == mtu) {
3664d0e5007SSukumar Swaminathan 			ret = 0;
3674d0e5007SSukumar Swaminathan 			break;
3684d0e5007SSukumar Swaminathan 		}
3694d0e5007SSukumar Swaminathan 
3704d0e5007SSukumar Swaminathan 		if (mtu != OCE_MIN_MTU && mtu != OCE_MAX_MTU) {
3714d0e5007SSukumar Swaminathan 			ret = EINVAL;
3724d0e5007SSukumar Swaminathan 			break;
3734d0e5007SSukumar Swaminathan 		}
3744d0e5007SSukumar Swaminathan 
3754d0e5007SSukumar Swaminathan 		ret = mac_maxsdu_update(dev->mac_handle, mtu);
3764d0e5007SSukumar Swaminathan 		if (0 == ret) {
3774d0e5007SSukumar Swaminathan 			dev->mtu = mtu;
3784d0e5007SSukumar Swaminathan 			break;
3794d0e5007SSukumar Swaminathan 		}
3804d0e5007SSukumar Swaminathan 		break;
3814d0e5007SSukumar Swaminathan 	}
3824d0e5007SSukumar Swaminathan 
3834d0e5007SSukumar Swaminathan 	case MAC_PROP_FLOWCTRL: {
3844d0e5007SSukumar Swaminathan 		link_flowctrl_t flowctrl;
3854d0e5007SSukumar Swaminathan 		uint32_t fc = 0;
3864d0e5007SSukumar Swaminathan 
3874d0e5007SSukumar Swaminathan 		bcopy(val, &flowctrl, sizeof (link_flowctrl_t));
3884d0e5007SSukumar Swaminathan 
3894d0e5007SSukumar Swaminathan 		switch (flowctrl) {
3904d0e5007SSukumar Swaminathan 		case LINK_FLOWCTRL_NONE:
3914d0e5007SSukumar Swaminathan 			fc = 0;
3924d0e5007SSukumar Swaminathan 			break;
3934d0e5007SSukumar Swaminathan 
3944d0e5007SSukumar Swaminathan 		case LINK_FLOWCTRL_RX:
3954d0e5007SSukumar Swaminathan 			fc = OCE_FC_RX;
3964d0e5007SSukumar Swaminathan 			break;
3974d0e5007SSukumar Swaminathan 
3984d0e5007SSukumar Swaminathan 		case LINK_FLOWCTRL_TX:
3994d0e5007SSukumar Swaminathan 			fc = OCE_FC_TX;
4004d0e5007SSukumar Swaminathan 			break;
4014d0e5007SSukumar Swaminathan 
4024d0e5007SSukumar Swaminathan 		case LINK_FLOWCTRL_BI:
4034d0e5007SSukumar Swaminathan 			fc = OCE_FC_RX | OCE_FC_TX;
4044d0e5007SSukumar Swaminathan 			break;
4054d0e5007SSukumar Swaminathan 		default:
4064d0e5007SSukumar Swaminathan 			ret = EINVAL;
4074d0e5007SSukumar Swaminathan 			break;
4084d0e5007SSukumar Swaminathan 		} /* switch flowctrl */
4094d0e5007SSukumar Swaminathan 
4104d0e5007SSukumar Swaminathan 		if (ret)
4114d0e5007SSukumar Swaminathan 			break;
4124d0e5007SSukumar Swaminathan 
4134d0e5007SSukumar Swaminathan 		if (fc == dev->flow_control)
4144d0e5007SSukumar Swaminathan 			break;
4154d0e5007SSukumar Swaminathan 
4164d0e5007SSukumar Swaminathan 		if (dev->suspended) {
4174d0e5007SSukumar Swaminathan 			dev->flow_control = fc;
4184d0e5007SSukumar Swaminathan 			break;
4194d0e5007SSukumar Swaminathan 		}
4204d0e5007SSukumar Swaminathan 		/* call to set flow control */
4214d0e5007SSukumar Swaminathan 		ret = oce_set_flow_control(dev, fc);
4224d0e5007SSukumar Swaminathan 		/* store the new fc setting on success */
4234d0e5007SSukumar Swaminathan 		if (ret == 0) {
4244d0e5007SSukumar Swaminathan 		dev->flow_control = fc;
4254d0e5007SSukumar Swaminathan 		}
4264d0e5007SSukumar Swaminathan 		break;
4274d0e5007SSukumar Swaminathan 	}
4284d0e5007SSukumar Swaminathan 
4294d0e5007SSukumar Swaminathan 	case MAC_PROP_PRIVATE:
4304d0e5007SSukumar Swaminathan 		ret = oce_set_priv_prop(dev, name, size, val);
4314d0e5007SSukumar Swaminathan 		break;
4324d0e5007SSukumar Swaminathan 
4334d0e5007SSukumar Swaminathan 	default:
4344d0e5007SSukumar Swaminathan 		ret = ENOTSUP;
4354d0e5007SSukumar Swaminathan 		break;
4364d0e5007SSukumar Swaminathan 	} /* switch id */
4374d0e5007SSukumar Swaminathan 
4388d738d7dSSukumar Swaminathan 	DEV_UNLOCK(dev);
4394d0e5007SSukumar Swaminathan 	return (ret);
4404d0e5007SSukumar Swaminathan } /* oce_m_setprop */
4414d0e5007SSukumar Swaminathan 
4424d0e5007SSukumar Swaminathan int
oce_m_getprop(void * arg,const char * name,mac_prop_id_t id,uint_t size,void * val)4434d0e5007SSukumar Swaminathan oce_m_getprop(void *arg, const char *name, mac_prop_id_t id,
4440dc2366fSVenugopal Iyer     uint_t size, void *val)
4454d0e5007SSukumar Swaminathan {
4464d0e5007SSukumar Swaminathan 	struct oce_dev *dev = arg;
4474d0e5007SSukumar Swaminathan 	uint32_t ret = 0;
4484d0e5007SSukumar Swaminathan 
4494d0e5007SSukumar Swaminathan 	switch (id) {
4500dc2366fSVenugopal Iyer 	case MAC_PROP_ADV_10GFDX_CAP:
4510dc2366fSVenugopal Iyer 	case MAC_PROP_EN_10GFDX_CAP:
4524d0e5007SSukumar Swaminathan 		*(uint8_t *)val = 0x01;
4534d0e5007SSukumar Swaminathan 		break;
4544d0e5007SSukumar Swaminathan 
4554d0e5007SSukumar Swaminathan 	case MAC_PROP_DUPLEX: {
4560dc2366fSVenugopal Iyer 		uint32_t *mode = (uint32_t *)val;
4574d0e5007SSukumar Swaminathan 
4580dc2366fSVenugopal Iyer 		ASSERT(size >= sizeof (link_duplex_t));
4590dc2366fSVenugopal Iyer 		if (dev->state & STATE_MAC_STARTED)
4600dc2366fSVenugopal Iyer 			*mode = LINK_DUPLEX_FULL;
4610dc2366fSVenugopal Iyer 		else
4620dc2366fSVenugopal Iyer 			*mode = LINK_DUPLEX_UNKNOWN;
4634d0e5007SSukumar Swaminathan 		break;
4644d0e5007SSukumar Swaminathan 	}
4654d0e5007SSukumar Swaminathan 
4664d0e5007SSukumar Swaminathan 	case MAC_PROP_SPEED: {
4670dc2366fSVenugopal Iyer 		uint64_t *speed = (uint64_t *)val;
4685b9d3151SSukumar Swaminathan 		struct link_status link = {0};
4694d0e5007SSukumar Swaminathan 
4700dc2366fSVenugopal Iyer 		ASSERT(size >= sizeof (uint64_t));
4710dc2366fSVenugopal Iyer 		*speed = 0;
4725b9d3151SSukumar Swaminathan 
4735b9d3151SSukumar Swaminathan 		if (dev->state & STATE_MAC_STARTED) {
4745b9d3151SSukumar Swaminathan 			if (dev->link_speed < 0) {
4755b9d3151SSukumar Swaminathan 				(void) oce_get_link_status(dev, &link);
4765b9d3151SSukumar Swaminathan 				dev->link_speed = link.qos_link_speed ?
4775b9d3151SSukumar Swaminathan 				    link.qos_link_speed * 10 :
4785b9d3151SSukumar Swaminathan 				    pow10[link.mac_speed];
4795b9d3151SSukumar Swaminathan 			}
4805b9d3151SSukumar Swaminathan 
4815b9d3151SSukumar Swaminathan 			*speed = dev->link_speed * 1000000ull;
4824d0e5007SSukumar Swaminathan 		}
4834d0e5007SSukumar Swaminathan 		break;
4844d0e5007SSukumar Swaminathan 	}
4854d0e5007SSukumar Swaminathan 
4864d0e5007SSukumar Swaminathan 	case MAC_PROP_FLOWCTRL: {
4874d0e5007SSukumar Swaminathan 		link_flowctrl_t *fc = (link_flowctrl_t *)val;
4884d0e5007SSukumar Swaminathan 
4890dc2366fSVenugopal Iyer 		ASSERT(size >= sizeof (link_flowctrl_t));
4900dc2366fSVenugopal Iyer 		if (dev->flow_control & OCE_FC_TX &&
4910dc2366fSVenugopal Iyer 		    dev->flow_control & OCE_FC_RX)
4920dc2366fSVenugopal Iyer 			*fc = LINK_FLOWCTRL_BI;
4930dc2366fSVenugopal Iyer 		else if (dev->flow_control == OCE_FC_TX)
4940dc2366fSVenugopal Iyer 			*fc = LINK_FLOWCTRL_TX;
4950dc2366fSVenugopal Iyer 		else if (dev->flow_control == OCE_FC_RX)
4960dc2366fSVenugopal Iyer 			*fc = LINK_FLOWCTRL_RX;
4970dc2366fSVenugopal Iyer 		else if (dev->flow_control == 0)
4980dc2366fSVenugopal Iyer 			*fc = LINK_FLOWCTRL_NONE;
4990dc2366fSVenugopal Iyer 		else
5004d0e5007SSukumar Swaminathan 			ret = EINVAL;
5014d0e5007SSukumar Swaminathan 		break;
5024d0e5007SSukumar Swaminathan 	}
5034d0e5007SSukumar Swaminathan 
5040dc2366fSVenugopal Iyer 	case MAC_PROP_PRIVATE:
5050dc2366fSVenugopal Iyer 		ret = oce_get_priv_prop(dev, name, size, val);
5064d0e5007SSukumar Swaminathan 		break;
5070dc2366fSVenugopal Iyer 
5084d0e5007SSukumar Swaminathan 	default:
5098d738d7dSSukumar Swaminathan 		ret = ENOTSUP;
5104d0e5007SSukumar Swaminathan 		break;
5114d0e5007SSukumar Swaminathan 	} /* switch id */
5124d0e5007SSukumar Swaminathan 	return (ret);
5134d0e5007SSukumar Swaminathan } /* oce_m_getprop */
5144d0e5007SSukumar Swaminathan 
5150dc2366fSVenugopal Iyer void
oce_m_propinfo(void * arg,const char * name,mac_prop_id_t pr_num,mac_prop_info_handle_t prh)5160dc2366fSVenugopal Iyer oce_m_propinfo(void *arg, const char *name, mac_prop_id_t pr_num,
5170dc2366fSVenugopal Iyer     mac_prop_info_handle_t prh)
5180dc2366fSVenugopal Iyer {
5190dc2366fSVenugopal Iyer 	_NOTE(ARGUNUSED(arg));
5200dc2366fSVenugopal Iyer 
5210dc2366fSVenugopal Iyer 	switch (pr_num) {
5220dc2366fSVenugopal Iyer 	case MAC_PROP_AUTONEG:
5230dc2366fSVenugopal Iyer 	case MAC_PROP_EN_AUTONEG:
5240dc2366fSVenugopal Iyer 	case MAC_PROP_ADV_1000FDX_CAP:
5250dc2366fSVenugopal Iyer 	case MAC_PROP_EN_1000FDX_CAP:
5260dc2366fSVenugopal Iyer 	case MAC_PROP_ADV_1000HDX_CAP:
5270dc2366fSVenugopal Iyer 	case MAC_PROP_EN_1000HDX_CAP:
5280dc2366fSVenugopal Iyer 	case MAC_PROP_ADV_100FDX_CAP:
5290dc2366fSVenugopal Iyer 	case MAC_PROP_EN_100FDX_CAP:
5300dc2366fSVenugopal Iyer 	case MAC_PROP_ADV_100HDX_CAP:
5310dc2366fSVenugopal Iyer 	case MAC_PROP_EN_100HDX_CAP:
5320dc2366fSVenugopal Iyer 	case MAC_PROP_ADV_10FDX_CAP:
5330dc2366fSVenugopal Iyer 	case MAC_PROP_EN_10FDX_CAP:
5340dc2366fSVenugopal Iyer 	case MAC_PROP_ADV_10HDX_CAP:
5350dc2366fSVenugopal Iyer 	case MAC_PROP_EN_10HDX_CAP:
5360dc2366fSVenugopal Iyer 	case MAC_PROP_ADV_100T4_CAP:
5370dc2366fSVenugopal Iyer 	case MAC_PROP_EN_100T4_CAP:
5380dc2366fSVenugopal Iyer 	case MAC_PROP_ADV_10GFDX_CAP:
5390dc2366fSVenugopal Iyer 	case MAC_PROP_EN_10GFDX_CAP:
5400dc2366fSVenugopal Iyer 	case MAC_PROP_SPEED:
5410dc2366fSVenugopal Iyer 	case MAC_PROP_DUPLEX:
5420dc2366fSVenugopal Iyer 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
5430dc2366fSVenugopal Iyer 		break;
5440dc2366fSVenugopal Iyer 
5450dc2366fSVenugopal Iyer 	case MAC_PROP_MTU:
5460dc2366fSVenugopal Iyer 		mac_prop_info_set_range_uint32(prh, OCE_MIN_MTU, OCE_MAX_MTU);
5470dc2366fSVenugopal Iyer 		break;
5480dc2366fSVenugopal Iyer 
5490dc2366fSVenugopal Iyer 	case MAC_PROP_PRIVATE: {
5500dc2366fSVenugopal Iyer 		char valstr[64];
5510dc2366fSVenugopal Iyer 		int value;
5520dc2366fSVenugopal Iyer 
5530dc2366fSVenugopal Iyer 		if (strcmp(name, "_tx_ring_size") == 0) {
5540dc2366fSVenugopal Iyer 			value = OCE_DEFAULT_TX_RING_SIZE;
5550dc2366fSVenugopal Iyer 		} else if (strcmp(name, "_rx_ring_size") == 0) {
5560dc2366fSVenugopal Iyer 			value = OCE_DEFAULT_RX_RING_SIZE;
5570dc2366fSVenugopal Iyer 		} else {
5580dc2366fSVenugopal Iyer 			return;
5590dc2366fSVenugopal Iyer 		}
5600dc2366fSVenugopal Iyer 
5610dc2366fSVenugopal Iyer 		(void) snprintf(valstr, sizeof (valstr), "%d", value);
5620dc2366fSVenugopal Iyer 		mac_prop_info_set_default_str(prh, valstr);
56312d61dabSSukumar Swaminathan 		mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ);
5640dc2366fSVenugopal Iyer 		break;
5650dc2366fSVenugopal Iyer 	}
5660dc2366fSVenugopal Iyer 	}
5670dc2366fSVenugopal Iyer } /* oce_m_propinfo */
5680dc2366fSVenugopal Iyer 
5694d0e5007SSukumar Swaminathan /*
5704d0e5007SSukumar Swaminathan  * function to handle dlpi streams message from GLDv3 mac layer
5714d0e5007SSukumar Swaminathan  */
5724d0e5007SSukumar Swaminathan void
oce_m_ioctl(void * arg,queue_t * wq,mblk_t * mp)5734d0e5007SSukumar Swaminathan oce_m_ioctl(void *arg, queue_t *wq, mblk_t *mp)
5744d0e5007SSukumar Swaminathan {
5754d0e5007SSukumar Swaminathan 	struct oce_dev *dev = arg;
5764d0e5007SSukumar Swaminathan 	struct  iocblk *iocp;
5774d0e5007SSukumar Swaminathan 	int cmd;
5784d0e5007SSukumar Swaminathan 	uint32_t payload_length;
5794d0e5007SSukumar Swaminathan 	int ret;
5804d0e5007SSukumar Swaminathan 
5814d0e5007SSukumar Swaminathan 	iocp = (struct iocblk *)voidptr(mp->b_rptr);
5824d0e5007SSukumar Swaminathan 	iocp->ioc_error = 0;
5834d0e5007SSukumar Swaminathan 	cmd = iocp->ioc_cmd;
5844d0e5007SSukumar Swaminathan 
5854d0e5007SSukumar Swaminathan 	DEV_LOCK(dev);
5864d0e5007SSukumar Swaminathan 	if (dev->suspended) {
5874d0e5007SSukumar Swaminathan 		miocnak(wq, mp, 0, EINVAL);
5884d0e5007SSukumar Swaminathan 		DEV_UNLOCK(dev);
5894d0e5007SSukumar Swaminathan 		return;
5904d0e5007SSukumar Swaminathan 	}
5914d0e5007SSukumar Swaminathan 	DEV_UNLOCK(dev);
5924d0e5007SSukumar Swaminathan 
5934d0e5007SSukumar Swaminathan 	switch (cmd) {
5944d0e5007SSukumar Swaminathan 
5954d0e5007SSukumar Swaminathan 	case OCE_ISSUE_MBOX: {
5964d0e5007SSukumar Swaminathan 		ret = oce_issue_mbox(dev, wq, mp, &payload_length);
5973abb112fSGarrett D'Amore 		miocack(wq, mp, payload_length, ret);
5983abb112fSGarrett D'Amore 		break;
5993abb112fSGarrett D'Amore 	}
6003abb112fSGarrett D'Amore 	case OCE_QUERY_DRIVER_DATA: {
6013abb112fSGarrett D'Amore 		struct oce_driver_query *drv_query =
6023abb112fSGarrett D'Amore 		    (struct oce_driver_query *)(void *)mp->b_cont->b_rptr;
6033abb112fSGarrett D'Amore 
6043abb112fSGarrett D'Amore 		/* if the driver version does not match bail */
6053abb112fSGarrett D'Amore 		if (drv_query->version != OCN_VERSION_SUPPORTED) {
6063abb112fSGarrett D'Amore 			oce_log(dev, CE_NOTE, MOD_CONFIG, "%s",
6073abb112fSGarrett D'Amore 			    "One Connect version mismatch");
6083abb112fSGarrett D'Amore 			miocnak(wq, mp, 0, ENOTSUP);
6093abb112fSGarrett D'Amore 			break;
6103abb112fSGarrett D'Amore 		}
6113abb112fSGarrett D'Amore 
6123abb112fSGarrett D'Amore 		/* fill the return values */
6133abb112fSGarrett D'Amore 		bcopy(OCE_MOD_NAME, drv_query->driver_name,
6143abb112fSGarrett D'Amore 		    (sizeof (OCE_MOD_NAME) > 32) ?
6153abb112fSGarrett D'Amore 		    31 : sizeof (OCE_MOD_NAME));
6163abb112fSGarrett D'Amore 		drv_query->driver_name[31] = '\0';
6173abb112fSGarrett D'Amore 
6183abb112fSGarrett D'Amore 		bcopy(OCE_VERSION, drv_query->driver_version,
6193abb112fSGarrett D'Amore 		    (sizeof (OCE_VERSION) > 32) ? 31 :
6203abb112fSGarrett D'Amore 		    sizeof (OCE_VERSION));
6213abb112fSGarrett D'Amore 		drv_query->driver_version[31] = '\0';
6223abb112fSGarrett D'Amore 
6233abb112fSGarrett D'Amore 		if (dev->num_smac == 0) {
6243abb112fSGarrett D'Amore 			drv_query->num_smac = 1;
6253abb112fSGarrett D'Amore 			bcopy(dev->mac_addr, drv_query->smac_addr[0],
6263abb112fSGarrett D'Amore 			    ETHERADDRL);
6274d0e5007SSukumar Swaminathan 		} else {
6283abb112fSGarrett D'Amore 			drv_query->num_smac = dev->num_smac;
6293abb112fSGarrett D'Amore 			bcopy(dev->unicast_addr, drv_query->smac_addr[0],
6303abb112fSGarrett D'Amore 			    ETHERADDRL);
6314d0e5007SSukumar Swaminathan 		}
6323abb112fSGarrett D'Amore 
6333abb112fSGarrett D'Amore 		bcopy(dev->mac_addr, drv_query->pmac_addr, ETHERADDRL);
6343abb112fSGarrett D'Amore 
6353abb112fSGarrett D'Amore 		payload_length = sizeof (struct oce_driver_query);
6363abb112fSGarrett D'Amore 		miocack(wq, mp, payload_length, 0);
6374d0e5007SSukumar Swaminathan 		break;
6384d0e5007SSukumar Swaminathan 	}
6394d0e5007SSukumar Swaminathan 
6404d0e5007SSukumar Swaminathan 	default:
6414d0e5007SSukumar Swaminathan 		miocnak(wq, mp, 0, ENOTSUP);
6424d0e5007SSukumar Swaminathan 		break;
6434d0e5007SSukumar Swaminathan 	}
6444d0e5007SSukumar Swaminathan } /* oce_m_ioctl */
6454d0e5007SSukumar Swaminathan 
6464d0e5007SSukumar Swaminathan int
oce_m_promiscuous(void * arg,boolean_t enable)6474d0e5007SSukumar Swaminathan oce_m_promiscuous(void *arg, boolean_t enable)
6484d0e5007SSukumar Swaminathan {
6494d0e5007SSukumar Swaminathan 	struct oce_dev *dev = arg;
6504d0e5007SSukumar Swaminathan 	int ret = 0;
6514d0e5007SSukumar Swaminathan 
6524d0e5007SSukumar Swaminathan 	DEV_LOCK(dev);
6534d0e5007SSukumar Swaminathan 
6544d0e5007SSukumar Swaminathan 	if (dev->promisc == enable) {
6554d0e5007SSukumar Swaminathan 		DEV_UNLOCK(dev);
6564d0e5007SSukumar Swaminathan 		return (ret);
6574d0e5007SSukumar Swaminathan 	}
6584d0e5007SSukumar Swaminathan 
6594d0e5007SSukumar Swaminathan 	if (dev->suspended) {
6608d738d7dSSukumar Swaminathan 		/* remember the setting */
6618d738d7dSSukumar Swaminathan 		dev->promisc = enable;
6624d0e5007SSukumar Swaminathan 		DEV_UNLOCK(dev);
6634d0e5007SSukumar Swaminathan 		return (ret);
6644d0e5007SSukumar Swaminathan 	}
6654d0e5007SSukumar Swaminathan 
6664d0e5007SSukumar Swaminathan 	ret = oce_set_promiscuous(dev, enable);
6678d738d7dSSukumar Swaminathan 	if (ret == DDI_SUCCESS)
6688d738d7dSSukumar Swaminathan 		dev->promisc = enable;
6698d738d7dSSukumar Swaminathan 	DEV_UNLOCK(dev);
6704d0e5007SSukumar Swaminathan 	return (ret);
6714d0e5007SSukumar Swaminathan } /* oce_m_promiscuous */
6724d0e5007SSukumar Swaminathan 
6734d0e5007SSukumar Swaminathan /*
6744d0e5007SSukumar Swaminathan  * function to set a private property.
6754d0e5007SSukumar Swaminathan  * Called from the set_prop GLD entry point
6764d0e5007SSukumar Swaminathan  *
6774d0e5007SSukumar Swaminathan  * dev - sofware handle to the device
6784d0e5007SSukumar Swaminathan  * name - string containing the property name
6794d0e5007SSukumar Swaminathan  * size - length of the string in name
6804d0e5007SSukumar Swaminathan  * val - pointer to a location where the value to set is stored
6814d0e5007SSukumar Swaminathan  *
6824d0e5007SSukumar Swaminathan  * return EINVAL => invalid value in val 0 => success
6834d0e5007SSukumar Swaminathan  */
6844d0e5007SSukumar Swaminathan static int
oce_set_priv_prop(struct oce_dev * dev,const char * name,uint_t size,const void * val)6854d0e5007SSukumar Swaminathan oce_set_priv_prop(struct oce_dev *dev, const char *name,
6864d0e5007SSukumar Swaminathan     uint_t size, const void *val)
6874d0e5007SSukumar Swaminathan {
6884d0e5007SSukumar Swaminathan 	int ret = ENOTSUP;
6894d0e5007SSukumar Swaminathan 	long result;
6904d0e5007SSukumar Swaminathan 
6914d0e5007SSukumar Swaminathan 	_NOTE(ARGUNUSED(size));
6924d0e5007SSukumar Swaminathan 
6934d0e5007SSukumar Swaminathan 	if (NULL == val) {
6944d0e5007SSukumar Swaminathan 		ret = EINVAL;
6954d0e5007SSukumar Swaminathan 		return (ret);
6964d0e5007SSukumar Swaminathan 	}
6974d0e5007SSukumar Swaminathan 
6984d0e5007SSukumar Swaminathan 	if (strcmp(name, "_tx_bcopy_limit") == 0) {
6994d0e5007SSukumar Swaminathan 		(void) ddi_strtol(val, (char **)NULL, 0, &result);
7004d0e5007SSukumar Swaminathan 		if (result <= OCE_WQ_BUF_SIZE) {
7018d738d7dSSukumar Swaminathan 			if (result != dev->tx_bcopy_limit)
7028d738d7dSSukumar Swaminathan 				dev->tx_bcopy_limit = (uint32_t)result;
7038d738d7dSSukumar Swaminathan 			ret = 0;
7048d738d7dSSukumar Swaminathan 		} else {
7058d738d7dSSukumar Swaminathan 			ret = EINVAL;
7068d738d7dSSukumar Swaminathan 		}
7078d738d7dSSukumar Swaminathan 	}
7088d738d7dSSukumar Swaminathan 	if (strcmp(name, "_rx_bcopy_limit") == 0) {
7098d738d7dSSukumar Swaminathan 		(void) ddi_strtol(val, (char **)NULL, 0, &result);
7108d738d7dSSukumar Swaminathan 		if (result <= OCE_RQ_BUF_SIZE) {
7118d738d7dSSukumar Swaminathan 			if (result != dev->rx_bcopy_limit)
7128d738d7dSSukumar Swaminathan 				dev->rx_bcopy_limit = (uint32_t)result;
7134d0e5007SSukumar Swaminathan 			ret = 0;
7144d0e5007SSukumar Swaminathan 		} else {
7154d0e5007SSukumar Swaminathan 			ret = EINVAL;
7164d0e5007SSukumar Swaminathan 		}
7174d0e5007SSukumar Swaminathan 	}
7184d0e5007SSukumar Swaminathan 
7194d0e5007SSukumar Swaminathan 	return (ret);
7204d0e5007SSukumar Swaminathan } /* oce_set_priv_prop */
7214d0e5007SSukumar Swaminathan 
7224d0e5007SSukumar Swaminathan /*
7234d0e5007SSukumar Swaminathan  * function to get the value of a private property. Called from get_prop
7244d0e5007SSukumar Swaminathan  *
7254d0e5007SSukumar Swaminathan  * dev - software handle to the device
7264d0e5007SSukumar Swaminathan  * name - string containing the property name
7274d0e5007SSukumar Swaminathan  * size - length of the string contained name
7284d0e5007SSukumar Swaminathan  * val - [OUT] pointer to the location where the result is returned
7294d0e5007SSukumar Swaminathan  *
7304d0e5007SSukumar Swaminathan  * return EINVAL => invalid request 0 => success
7314d0e5007SSukumar Swaminathan  */
7324d0e5007SSukumar Swaminathan static int
oce_get_priv_prop(struct oce_dev * dev,const char * name,uint_t size,void * val)7334d0e5007SSukumar Swaminathan oce_get_priv_prop(struct oce_dev *dev, const char *name,
7340dc2366fSVenugopal Iyer     uint_t size, void *val)
7354d0e5007SSukumar Swaminathan {
7364d0e5007SSukumar Swaminathan 	int value;
7374d0e5007SSukumar Swaminathan 
7384d0e5007SSukumar Swaminathan 	if (strcmp(name, "_tx_ring_size") == 0) {
7390dc2366fSVenugopal Iyer 		value = dev->tx_ring_size;
7400dc2366fSVenugopal Iyer 	} else if (strcmp(name, "_tx_bcopy_limit") == 0) {
7418d738d7dSSukumar Swaminathan 		value = dev->tx_bcopy_limit;
7420dc2366fSVenugopal Iyer 	} else if (strcmp(name, "_rx_ring_size") == 0) {
7430dc2366fSVenugopal Iyer 		value = dev->rx_ring_size;
7440dc2366fSVenugopal Iyer 	} else if (strcmp(name, "_rx_bcopy_limit") == 0) {
7458d738d7dSSukumar Swaminathan 		value = dev->rx_bcopy_limit;
7460dc2366fSVenugopal Iyer 	} else {
7470dc2366fSVenugopal Iyer 		return (ENOTSUP);
7484d0e5007SSukumar Swaminathan 	}
7494d0e5007SSukumar Swaminathan 
7500dc2366fSVenugopal Iyer 	(void) snprintf(val, size, "%d", value);
7510dc2366fSVenugopal Iyer 	return (0);
7524d0e5007SSukumar Swaminathan } /* oce_get_priv_prop */
753