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 
22*3abb112fSGarrett D'Amore /* Copyright © 2003-2011 Emulex. All rights reserved.  */
23*3abb112fSGarrett D'Amore 
244d0e5007SSukumar Swaminathan 
254d0e5007SSukumar Swaminathan /*
264d0e5007SSukumar Swaminathan  * Source file containing the implementation of the driver entry points
274d0e5007SSukumar Swaminathan  * and related helper functions
284d0e5007SSukumar Swaminathan  */
294d0e5007SSukumar Swaminathan 
304d0e5007SSukumar Swaminathan #include <oce_impl.h>
314d0e5007SSukumar Swaminathan #include <oce_stat.h>
324d0e5007SSukumar Swaminathan #include <oce_ioctl.h>
334d0e5007SSukumar Swaminathan 
344d0e5007SSukumar Swaminathan #define	ATTACH_DEV_INIT 	0x1
354d0e5007SSukumar Swaminathan #define	ATTACH_FM_INIT		0x2
36*3abb112fSGarrett D'Amore #define	ATTACH_PCI_CFG		0x4
37*3abb112fSGarrett D'Amore #define	ATTACH_LOCK_INIT	0x8
38*3abb112fSGarrett D'Amore #define	ATTACH_PCI_INIT 	0x10
39*3abb112fSGarrett D'Amore #define	ATTACH_HW_INIT		0x20
40*3abb112fSGarrett D'Amore #define	ATTACH_SETUP_TXRX 	0x40
41*3abb112fSGarrett D'Amore #define	ATTACH_SETUP_ADAP	0x80
42*3abb112fSGarrett D'Amore #define	ATTACH_SETUP_INTR	0x100
43*3abb112fSGarrett D'Amore #define	ATTACH_STAT_INIT	0x200
44*3abb112fSGarrett D'Amore #define	ATTACH_MAC_REG		0x400
454d0e5007SSukumar Swaminathan 
464d0e5007SSukumar Swaminathan /* ---[ globals and externs ]-------------------------------------------- */
474d0e5007SSukumar Swaminathan const char oce_ident_string[] = OCE_IDENT_STRING;
484d0e5007SSukumar Swaminathan const char oce_mod_name[] = OCE_MOD_NAME;
49*3abb112fSGarrett D'Amore struct oce_dev *oce_dev_list[MAX_DEVS + 1];	/* Last entry is invalid */
504d0e5007SSukumar Swaminathan 
514d0e5007SSukumar Swaminathan /* driver properties */
525b9d3151SSukumar Swaminathan static const char flow_control[]	 = "flow_control";
535b9d3151SSukumar Swaminathan static const char mtu_prop_name[]	 = "oce_default_mtu";
545b9d3151SSukumar Swaminathan static const char tx_ring_size_name[]	 = "tx_ring_size";
555b9d3151SSukumar Swaminathan static const char tx_bcopy_limit_name[]	 = "tx_bcopy_limit";
565b9d3151SSukumar Swaminathan static const char rx_bcopy_limit_name[]	 = "rx_bcopy_limit";
575b9d3151SSukumar Swaminathan static const char rx_frag_size_name[]	 = "rx_frag_size";
585b9d3151SSukumar Swaminathan static const char rx_max_bufs_name[]	 = "rx_max_bufs";
595b9d3151SSukumar Swaminathan static const char fm_cap_name[]		 = "oce_fm_capability";
605b9d3151SSukumar Swaminathan static const char log_level_name[]	 = "oce_log_level";
615b9d3151SSukumar Swaminathan static const char lso_capable_name[]	 = "lso_capable";
625b9d3151SSukumar Swaminathan static const char rx_pkt_per_intr_name[] = "rx_pkts_per_intr";
635b9d3151SSukumar Swaminathan static const char tx_reclaim_threshold_name[] = "tx_reclaim_threshold";
645b9d3151SSukumar Swaminathan static const char rx_rings_name[]	 = "max_rx_rings";
655b9d3151SSukumar Swaminathan static const char tx_rings_name[]	 = "max_tx_rings";
664d0e5007SSukumar Swaminathan 
674d0e5007SSukumar Swaminathan /* --[ static function prototypes here ]------------------------------- */
684d0e5007SSukumar Swaminathan static int oce_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd);
694d0e5007SSukumar Swaminathan static int oce_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
704d0e5007SSukumar Swaminathan static int oce_quiesce(dev_info_t *dip);
714d0e5007SSukumar Swaminathan static int oce_suspend(dev_info_t *dip);
724d0e5007SSukumar Swaminathan static int oce_resume(dev_info_t *dip);
734d0e5007SSukumar Swaminathan static void oce_unconfigure(struct oce_dev *dev);
744d0e5007SSukumar Swaminathan static void oce_init_locks(struct oce_dev *dev);
754d0e5007SSukumar Swaminathan static void oce_destroy_locks(struct oce_dev *dev);
764d0e5007SSukumar Swaminathan static void oce_get_params(struct oce_dev *dev);
775b9d3151SSukumar Swaminathan static int oce_get_prop(struct oce_dev *dev, char *propname, int minval,
785b9d3151SSukumar Swaminathan     int maxval, int defval, uint32_t *values);
794d0e5007SSukumar Swaminathan 
804d0e5007SSukumar Swaminathan static struct cb_ops oce_cb_ops = {
814d0e5007SSukumar Swaminathan 	nulldev,		/* cb_open */
824d0e5007SSukumar Swaminathan 	nulldev,		/* cb_close */
834d0e5007SSukumar Swaminathan 	nodev,			/* cb_strategy */
844d0e5007SSukumar Swaminathan 	nodev,			/* cb_print */
854d0e5007SSukumar Swaminathan 	nodev,			/* cb_dump */
864d0e5007SSukumar Swaminathan 	nodev,			/* cb_read */
874d0e5007SSukumar Swaminathan 	nodev,			/* cb_write */
884d0e5007SSukumar Swaminathan 	nodev,			/* cb_ioctl */
894d0e5007SSukumar Swaminathan 	nodev,			/* cb_devmap */
904d0e5007SSukumar Swaminathan 	nodev,			/* cb_mmap */
914d0e5007SSukumar Swaminathan 	nodev,			/* cb_segmap */
924d0e5007SSukumar Swaminathan 	nochpoll,		/* cb_chpoll */
934d0e5007SSukumar Swaminathan 	ddi_prop_op,	/* cb_prop_op */
944d0e5007SSukumar Swaminathan 	NULL,			/* cb_stream */
954d0e5007SSukumar Swaminathan 	D_MP,			/* cb_flag */
964d0e5007SSukumar Swaminathan 	CB_REV,			/* cb_rev */
974d0e5007SSukumar Swaminathan 	nodev,			/* cb_aread */
984d0e5007SSukumar Swaminathan 	nodev			/* cb_awrite */
994d0e5007SSukumar Swaminathan };
1004d0e5007SSukumar Swaminathan 
1014d0e5007SSukumar Swaminathan static struct dev_ops oce_dev_ops = {
1024d0e5007SSukumar Swaminathan 	DEVO_REV,	/* devo_rev */
1034d0e5007SSukumar Swaminathan 	0,		/* devo_refcnt */
1044d0e5007SSukumar Swaminathan 	NULL,		/* devo_getinfo */
1054d0e5007SSukumar Swaminathan 	NULL,		/* devo_identify */
1064d0e5007SSukumar Swaminathan 	nulldev,	/* devo_probe */
1074d0e5007SSukumar Swaminathan 	oce_attach,	/* devo_attach */
1084d0e5007SSukumar Swaminathan 	oce_detach,	/* devo_detach */
1094d0e5007SSukumar Swaminathan 	nodev,		/* devo_reset */
1104d0e5007SSukumar Swaminathan 	&oce_cb_ops,	/* devo_cb_ops */
1114d0e5007SSukumar Swaminathan 	NULL,		/* devo_bus_ops */
1124d0e5007SSukumar Swaminathan 	nodev,		/* devo_power */
1134d0e5007SSukumar Swaminathan 	oce_quiesce	/* devo_quiesce */
1144d0e5007SSukumar Swaminathan };
1154d0e5007SSukumar Swaminathan 
1164d0e5007SSukumar Swaminathan static struct modldrv oce_drv = {
1174d0e5007SSukumar Swaminathan 	&mod_driverops,	/* Type of module.  This one is a driver */
1184d0e5007SSukumar Swaminathan 	(char *)oce_ident_string, /* Description string */
1194d0e5007SSukumar Swaminathan 	&oce_dev_ops,	/* driver ops */
1204d0e5007SSukumar Swaminathan };
1214d0e5007SSukumar Swaminathan 
1224d0e5007SSukumar Swaminathan static struct modlinkage oce_mod_linkage = {
1234d0e5007SSukumar Swaminathan 	MODREV_1, &oce_drv, NULL
1244d0e5007SSukumar Swaminathan };
1254d0e5007SSukumar Swaminathan 
1260dc2366fSVenugopal Iyer #define	OCE_M_CB_FLAGS	(MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | \
1270dc2366fSVenugopal Iyer     MC_PROPINFO)
1284d0e5007SSukumar Swaminathan static mac_callbacks_t oce_mac_cb = {
1294d0e5007SSukumar Swaminathan 	OCE_M_CB_FLAGS,		/* mc_callbacks */
1304d0e5007SSukumar Swaminathan 	oce_m_stat,		/* mc_getstat */
1314d0e5007SSukumar Swaminathan 	oce_m_start,		/* mc_start */
1324d0e5007SSukumar Swaminathan 	oce_m_stop,		/* mc_stop */
1334d0e5007SSukumar Swaminathan 	oce_m_promiscuous,	/* mc_setpromisc */
1344d0e5007SSukumar Swaminathan 	oce_m_multicast,	/* mc_multicast */
1354d0e5007SSukumar Swaminathan 	oce_m_unicast,		/* mc_unicast */
1364d0e5007SSukumar Swaminathan 	oce_m_send,		/* mc_tx */
13712d61dabSSukumar Swaminathan 	NULL,			/* mc_reserve */
1384d0e5007SSukumar Swaminathan 	oce_m_ioctl,		/* mc_ioctl */
1394d0e5007SSukumar Swaminathan 	oce_m_getcap,		/* mc_getcapab */
1404d0e5007SSukumar Swaminathan 	NULL,			/* open */
1414d0e5007SSukumar Swaminathan 	NULL,			/* close */
1424d0e5007SSukumar Swaminathan 	oce_m_setprop,		/* set properties */
1430dc2366fSVenugopal Iyer 	oce_m_getprop,		/* get properties */
1440dc2366fSVenugopal Iyer 	oce_m_propinfo		/* properties info */
1454d0e5007SSukumar Swaminathan };
1464d0e5007SSukumar Swaminathan 
1470dc2366fSVenugopal Iyer extern char *oce_priv_props[];
1484d0e5007SSukumar Swaminathan 
1494d0e5007SSukumar Swaminathan /* Module Init */
1504d0e5007SSukumar Swaminathan int
_info(struct modinfo * modinfop)1514d0e5007SSukumar Swaminathan _info(struct modinfo *modinfop)
1524d0e5007SSukumar Swaminathan {
1534d0e5007SSukumar Swaminathan 	return (mod_info(&oce_mod_linkage, modinfop));
1544d0e5007SSukumar Swaminathan } /* _info */
1554d0e5007SSukumar Swaminathan 
1564d0e5007SSukumar Swaminathan int
_init(void)1574d0e5007SSukumar Swaminathan _init(void)
1584d0e5007SSukumar Swaminathan {
1594d0e5007SSukumar Swaminathan 	int ret = 0;
1604d0e5007SSukumar Swaminathan 
1614d0e5007SSukumar Swaminathan 	/* install the module */
1624d0e5007SSukumar Swaminathan 	mac_init_ops(&oce_dev_ops, "oce");
1634d0e5007SSukumar Swaminathan 
1644d0e5007SSukumar Swaminathan 	ret = mod_install(&oce_mod_linkage);
1654d0e5007SSukumar Swaminathan 	if (ret) {
1664d0e5007SSukumar Swaminathan 		cmn_err(CE_WARN, "mod_install failed  rval=%x", ret);
1674d0e5007SSukumar Swaminathan 	}
1684d0e5007SSukumar Swaminathan 
1694d0e5007SSukumar Swaminathan 	return (ret);
1704d0e5007SSukumar Swaminathan } /* _init */
1714d0e5007SSukumar Swaminathan 
1724d0e5007SSukumar Swaminathan 
1734d0e5007SSukumar Swaminathan int
_fini(void)1744d0e5007SSukumar Swaminathan _fini(void)
1754d0e5007SSukumar Swaminathan {
1764d0e5007SSukumar Swaminathan 	int ret = 0;
1774d0e5007SSukumar Swaminathan 	/* remove the module */
1784d0e5007SSukumar Swaminathan 	ret = mod_remove(&oce_mod_linkage);
1794d0e5007SSukumar Swaminathan 	if (ret != 0) {
1804d0e5007SSukumar Swaminathan 		return (ret);
1814d0e5007SSukumar Swaminathan 	}
1824d0e5007SSukumar Swaminathan 
1834d0e5007SSukumar Swaminathan 	mac_fini_ops(&oce_dev_ops);
1844d0e5007SSukumar Swaminathan 
1854d0e5007SSukumar Swaminathan 	return (ret);
1864d0e5007SSukumar Swaminathan } /* _fini */
1874d0e5007SSukumar Swaminathan 
1884d0e5007SSukumar Swaminathan 
1894d0e5007SSukumar Swaminathan static int
oce_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)1904d0e5007SSukumar Swaminathan oce_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
1914d0e5007SSukumar Swaminathan {
1924d0e5007SSukumar Swaminathan 	int ret = 0;
1934d0e5007SSukumar Swaminathan 	struct oce_dev *dev = NULL;
1944d0e5007SSukumar Swaminathan 	mac_register_t *mac;
195*3abb112fSGarrett D'Amore 	uint8_t dev_index = 0;
1964d0e5007SSukumar Swaminathan 
1974d0e5007SSukumar Swaminathan 	switch (cmd) {
1984d0e5007SSukumar Swaminathan 	case DDI_RESUME:
1994d0e5007SSukumar Swaminathan 		return (oce_resume(dip));
2004d0e5007SSukumar Swaminathan 	default:
2014d0e5007SSukumar Swaminathan 		return (DDI_FAILURE);
2024d0e5007SSukumar Swaminathan 
2034d0e5007SSukumar Swaminathan 	case DDI_ATTACH:
2044d0e5007SSukumar Swaminathan 		break;
2054d0e5007SSukumar Swaminathan 	}
2064d0e5007SSukumar Swaminathan 
2074d0e5007SSukumar Swaminathan 	/* allocate dev */
2085b9d3151SSukumar Swaminathan 	dev = kmem_zalloc(sizeof (struct oce_dev), KM_SLEEP);
2094d0e5007SSukumar Swaminathan 
2104d0e5007SSukumar Swaminathan 	/* populate the dev structure */
2114d0e5007SSukumar Swaminathan 	dev->dip = dip;
2124d0e5007SSukumar Swaminathan 	dev->dev_id = ddi_get_instance(dip);
2134d0e5007SSukumar Swaminathan 	dev->suspended = B_FALSE;
2144d0e5007SSukumar Swaminathan 
215*3abb112fSGarrett D'Amore 	dev->dev_list_index = MAX_DEVS;
216*3abb112fSGarrett D'Amore 	while (dev_index < MAX_DEVS) {
217*3abb112fSGarrett D'Amore 		(void) atomic_cas_ptr(&oce_dev_list[dev_index], NULL, dev);
218*3abb112fSGarrett D'Amore 		if (oce_dev_list[dev_index] == dev) {
219*3abb112fSGarrett D'Amore 			break;
220*3abb112fSGarrett D'Amore 		}
221*3abb112fSGarrett D'Amore 		dev_index++;
222*3abb112fSGarrett D'Amore 	}
223*3abb112fSGarrett D'Amore 	if (dev_index == MAX_DEVS) {
224*3abb112fSGarrett D'Amore 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
225*3abb112fSGarrett D'Amore 		    "Too many oce devices on the system. Failed to attach.");
226*3abb112fSGarrett D'Amore 		goto attach_fail;
227*3abb112fSGarrett D'Amore 	}
228*3abb112fSGarrett D'Amore 	dev->dev_list_index = dev_index;
229*3abb112fSGarrett D'Amore 
2304d0e5007SSukumar Swaminathan 	/* get the parameters */
2314d0e5007SSukumar Swaminathan 	oce_get_params(dev);
2324d0e5007SSukumar Swaminathan 
2334d0e5007SSukumar Swaminathan 	/*
2344d0e5007SSukumar Swaminathan 	 * set the ddi driver private data pointer. This is
2354d0e5007SSukumar Swaminathan 	 * sent to all mac callback entry points
2364d0e5007SSukumar Swaminathan 	 */
2374d0e5007SSukumar Swaminathan 	ddi_set_driver_private(dip, dev);
2384d0e5007SSukumar Swaminathan 
2394d0e5007SSukumar Swaminathan 	dev->attach_state |= ATTACH_DEV_INIT;
2404d0e5007SSukumar Swaminathan 
2414d0e5007SSukumar Swaminathan 	oce_fm_init(dev);
2424d0e5007SSukumar Swaminathan 	dev->attach_state |= ATTACH_FM_INIT;
2435b9d3151SSukumar Swaminathan 
244*3abb112fSGarrett D'Amore 	ret = pci_config_setup(dev->dip, &dev->pci_cfg_handle);
245*3abb112fSGarrett D'Amore 	if (ret != DDI_SUCCESS) {
246*3abb112fSGarrett D'Amore 		oce_log(dev, CE_WARN, MOD_CONFIG,
247*3abb112fSGarrett D'Amore 		    "Map PCI config failed with  %d", ret);
248*3abb112fSGarrett D'Amore 		goto attach_fail;
249*3abb112fSGarrett D'Amore 	}
250*3abb112fSGarrett D'Amore 	dev->attach_state |= ATTACH_PCI_CFG;
251*3abb112fSGarrett D'Amore 
252*3abb112fSGarrett D'Amore 	ret = oce_identify_hw(dev);
253*3abb112fSGarrett D'Amore 
254*3abb112fSGarrett D'Amore 	if (ret != DDI_SUCCESS) {
255*3abb112fSGarrett D'Amore 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
256*3abb112fSGarrett D'Amore 		    "Device Unknown");
257*3abb112fSGarrett D'Amore 		goto attach_fail;
258*3abb112fSGarrett D'Amore 	}
259*3abb112fSGarrett D'Amore 
260*3abb112fSGarrett D'Amore 	ret = oce_get_bdf(dev);
261*3abb112fSGarrett D'Amore 	if (ret != DDI_SUCCESS) {
262*3abb112fSGarrett D'Amore 		oce_log(dev, CE_WARN, MOD_CONFIG,
263*3abb112fSGarrett D'Amore 		    "Failed to read BDF, status = 0x%x", ret);
264*3abb112fSGarrett D'Amore 		goto attach_fail;
265*3abb112fSGarrett D'Amore 	}
266*3abb112fSGarrett D'Amore 	/* Update the dev->rss */
267*3abb112fSGarrett D'Amore 	oce_dev_rss_ready(dev);
268*3abb112fSGarrett D'Amore 
2695b9d3151SSukumar Swaminathan 	/* setup PCI bars */
2705b9d3151SSukumar Swaminathan 	ret = oce_pci_init(dev);
2715b9d3151SSukumar Swaminathan 	if (ret != DDI_SUCCESS) {
2725b9d3151SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG,
2735b9d3151SSukumar Swaminathan 		    "PCI initialization failed with %d", ret);
2745b9d3151SSukumar Swaminathan 		goto attach_fail;
2755b9d3151SSukumar Swaminathan 	}
2765b9d3151SSukumar Swaminathan 	dev->attach_state |= ATTACH_PCI_INIT;
2775b9d3151SSukumar Swaminathan 
2784d0e5007SSukumar Swaminathan 	ret = oce_setup_intr(dev);
2794d0e5007SSukumar Swaminathan 	if (ret != DDI_SUCCESS) {
2804d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG,
2814d0e5007SSukumar Swaminathan 		    "Interrupt setup failed with %d", ret);
2824d0e5007SSukumar Swaminathan 		goto attach_fail;
2838d738d7dSSukumar Swaminathan 
2844d0e5007SSukumar Swaminathan 	}
2855b9d3151SSukumar Swaminathan 	dev->attach_state |= ATTACH_SETUP_INTR;
2864d0e5007SSukumar Swaminathan 
2874d0e5007SSukumar Swaminathan 	/* initialize locks */
2884d0e5007SSukumar Swaminathan 	oce_init_locks(dev);
2894d0e5007SSukumar Swaminathan 	dev->attach_state |= ATTACH_LOCK_INIT;
2904d0e5007SSukumar Swaminathan 
2914d0e5007SSukumar Swaminathan 
2928d738d7dSSukumar Swaminathan 	/* HW init */
2938d738d7dSSukumar Swaminathan 	ret = oce_hw_init(dev);
2948d738d7dSSukumar Swaminathan 	if (ret != DDI_SUCCESS) {
2954d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG,
2968d738d7dSSukumar Swaminathan 		    "HW initialization failed with %d", ret);
2974d0e5007SSukumar Swaminathan 		goto attach_fail;
2984d0e5007SSukumar Swaminathan 	}
2998d738d7dSSukumar Swaminathan 	dev->attach_state |= ATTACH_HW_INIT;
3004d0e5007SSukumar Swaminathan 
3018d738d7dSSukumar Swaminathan 	ret = oce_init_txrx(dev);
3028d738d7dSSukumar Swaminathan 	if (ret  != DDI_SUCCESS) {
3038d738d7dSSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
3048d738d7dSSukumar Swaminathan 		    "Failed to init rings");
3054d0e5007SSukumar Swaminathan 		goto attach_fail;
3064d0e5007SSukumar Swaminathan 	}
3078d738d7dSSukumar Swaminathan 	dev->attach_state |= ATTACH_SETUP_TXRX;
3084d0e5007SSukumar Swaminathan 
3098d738d7dSSukumar Swaminathan 	ret = oce_setup_adapter(dev);
3108d738d7dSSukumar Swaminathan 	if (ret != DDI_SUCCESS) {
3118d738d7dSSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
3128d738d7dSSukumar Swaminathan 		    "Failed to setup adapter");
3134d0e5007SSukumar Swaminathan 		goto attach_fail;
3144d0e5007SSukumar Swaminathan 	}
3158d738d7dSSukumar Swaminathan 	dev->attach_state |=  ATTACH_SETUP_ADAP;
3164d0e5007SSukumar Swaminathan 
3174d0e5007SSukumar Swaminathan 
3184d0e5007SSukumar Swaminathan 	ret = oce_stat_init(dev);
3194d0e5007SSukumar Swaminathan 	if (ret != DDI_SUCCESS) {
3204d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG,
3214d0e5007SSukumar Swaminathan 		    "kstat setup Failed with %d", ret);
3224d0e5007SSukumar Swaminathan 		goto attach_fail;
3234d0e5007SSukumar Swaminathan 	}
3244d0e5007SSukumar Swaminathan 	dev->attach_state |= ATTACH_STAT_INIT;
3254d0e5007SSukumar Swaminathan 
3264d0e5007SSukumar Swaminathan 	/* mac_register_t */
3274d0e5007SSukumar Swaminathan 	oce_log(dev, CE_NOTE, MOD_CONFIG,
3284d0e5007SSukumar Swaminathan 	    "MAC_VERSION = 0x%x", MAC_VERSION);
3294d0e5007SSukumar Swaminathan 	mac = mac_alloc(MAC_VERSION);
3304d0e5007SSukumar Swaminathan 	if (mac == NULL) {
3314d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
3324d0e5007SSukumar Swaminathan 		    "MAC allocation Failed");
3334d0e5007SSukumar Swaminathan 		goto attach_fail;
3344d0e5007SSukumar Swaminathan 	}
3354d0e5007SSukumar Swaminathan 	/*
3364d0e5007SSukumar Swaminathan 	 * fill the mac structure before calling mac_register
3374d0e5007SSukumar Swaminathan 	 */
3384d0e5007SSukumar Swaminathan 	mac->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
3394d0e5007SSukumar Swaminathan 	mac->m_driver = dev;
3404d0e5007SSukumar Swaminathan 	mac->m_dip = dip;
3414d0e5007SSukumar Swaminathan 	mac->m_src_addr = dev->mac_addr;
3424d0e5007SSukumar Swaminathan 	mac->m_callbacks = &oce_mac_cb;
3434d0e5007SSukumar Swaminathan 	mac->m_min_sdu = 0;
3444d0e5007SSukumar Swaminathan 	mac->m_max_sdu = dev->mtu;
345*3abb112fSGarrett D'Amore 	mac->m_margin = VTAG_SIZE;
3464d0e5007SSukumar Swaminathan 	mac->m_priv_props = oce_priv_props;
3474d0e5007SSukumar Swaminathan 
3484d0e5007SSukumar Swaminathan 	oce_log(dev, CE_NOTE, MOD_CONFIG,
3494d0e5007SSukumar Swaminathan 	    "Driver Private structure = 0x%p", (void *)dev);
3504d0e5007SSukumar Swaminathan 
3514d0e5007SSukumar Swaminathan 	/* now register with GLDv3 */
3524d0e5007SSukumar Swaminathan 	ret = mac_register(mac, (mac_handle_t *)&dev->mac_handle);
3534d0e5007SSukumar Swaminathan 	/* regardless of the status, free mac_register */
3544d0e5007SSukumar Swaminathan 	mac_free(mac);
3554d0e5007SSukumar Swaminathan 	mac = NULL;
3564d0e5007SSukumar Swaminathan 	if (ret != DDI_SUCCESS) {
3574d0e5007SSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG,
3584d0e5007SSukumar Swaminathan 		    "MAC registration failed :0x%x", ret);
3594d0e5007SSukumar Swaminathan 		goto attach_fail;
3604d0e5007SSukumar Swaminathan 
3614d0e5007SSukumar Swaminathan 	}
3624d0e5007SSukumar Swaminathan 
3634d0e5007SSukumar Swaminathan 	/* correct link status only after start */
3645b9d3151SSukumar Swaminathan 	dev->link_status = LINK_STATE_UNKNOWN;
3655b9d3151SSukumar Swaminathan 	mac_link_update(dev->mac_handle, dev->link_status);
3664d0e5007SSukumar Swaminathan 
3674d0e5007SSukumar Swaminathan 	dev->attach_state |= ATTACH_MAC_REG;
3684d0e5007SSukumar Swaminathan 	dev->state |= STATE_INIT;
36912d61dabSSukumar Swaminathan 
3704d0e5007SSukumar Swaminathan 	oce_log(dev, CE_NOTE, MOD_CONFIG, "%s",
3714d0e5007SSukumar Swaminathan 	    "ATTACH SUCCESS");
3724d0e5007SSukumar Swaminathan 
3734d0e5007SSukumar Swaminathan 	return (DDI_SUCCESS);
3744d0e5007SSukumar Swaminathan 
3754d0e5007SSukumar Swaminathan attach_fail:
3764d0e5007SSukumar Swaminathan 	oce_unconfigure(dev);
3774d0e5007SSukumar Swaminathan 	return (DDI_FAILURE);
3784d0e5007SSukumar Swaminathan } /* oce_attach */
3794d0e5007SSukumar Swaminathan 
3804d0e5007SSukumar Swaminathan static int
oce_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)3814d0e5007SSukumar Swaminathan oce_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
3824d0e5007SSukumar Swaminathan {
3838d738d7dSSukumar Swaminathan 	struct oce_dev *dev;
3848d738d7dSSukumar Swaminathan 	int pcnt = 0;
3855b9d3151SSukumar Swaminathan 	int qid;
3864d0e5007SSukumar Swaminathan 
3878d738d7dSSukumar Swaminathan 	dev = ddi_get_driver_private(dip);
3888d738d7dSSukumar Swaminathan 	if (dev == NULL) {
3898d738d7dSSukumar Swaminathan 		return (DDI_FAILURE);
3908d738d7dSSukumar Swaminathan 	}
3914d0e5007SSukumar Swaminathan 	oce_log(dev, CE_NOTE, MOD_CONFIG,
3924d0e5007SSukumar Swaminathan 	    "Detaching driver: cmd = 0x%x", cmd);
3934d0e5007SSukumar Swaminathan 
3944d0e5007SSukumar Swaminathan 	switch (cmd) {
3958d738d7dSSukumar Swaminathan 	default:
3968d738d7dSSukumar Swaminathan 		return (DDI_FAILURE);
3978d738d7dSSukumar Swaminathan 	case DDI_SUSPEND:
3988d738d7dSSukumar Swaminathan 		return (oce_suspend(dip));
3994d0e5007SSukumar Swaminathan 	case DDI_DETACH:
4004d0e5007SSukumar Swaminathan 		break;
4018d738d7dSSukumar Swaminathan 	} /* switch cmd */
4024d0e5007SSukumar Swaminathan 
4038d738d7dSSukumar Swaminathan 	/* Fail detach if MAC unregister is unsuccessfule */
4048d738d7dSSukumar Swaminathan 	if (mac_unregister(dev->mac_handle) != 0) {
4058d738d7dSSukumar Swaminathan 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
4068d738d7dSSukumar Swaminathan 		    "Failed to unregister MAC ");
4078d738d7dSSukumar Swaminathan 	}
4088d738d7dSSukumar Swaminathan 	dev->attach_state &= ~ATTACH_MAC_REG;
4094d0e5007SSukumar Swaminathan 
4108d738d7dSSukumar Swaminathan 	/* check if the detach is called with out stopping */
4118d738d7dSSukumar Swaminathan 	DEV_LOCK(dev);
4128d738d7dSSukumar Swaminathan 	if (dev->state & STATE_MAC_STARTED) {
4138d738d7dSSukumar Swaminathan 		dev->state &= ~STATE_MAC_STARTED;
4148d738d7dSSukumar Swaminathan 		oce_stop(dev);
4158d738d7dSSukumar Swaminathan 		DEV_UNLOCK(dev);
4168d738d7dSSukumar Swaminathan 	} else
4178d738d7dSSukumar Swaminathan 		DEV_UNLOCK(dev);
4188d738d7dSSukumar Swaminathan 
4198d738d7dSSukumar Swaminathan 	/*
4208d738d7dSSukumar Swaminathan 	 * Wait for Packets sent up to be freed
4218d738d7dSSukumar Swaminathan 	 */
4225b9d3151SSukumar Swaminathan 	for (qid = 0; qid < dev->rx_rings; qid++) {
4235b9d3151SSukumar Swaminathan 		pcnt = oce_rx_pending(dev, dev->rq[qid], DEFAULT_DRAIN_TIME);
4245b9d3151SSukumar Swaminathan 		if (pcnt != 0) {
4255b9d3151SSukumar Swaminathan 			oce_log(dev, CE_WARN, MOD_CONFIG,
4265b9d3151SSukumar Swaminathan 			    "%d Pending Buffers Detach failed", pcnt);
4275b9d3151SSukumar Swaminathan 			return (DDI_FAILURE);
4285b9d3151SSukumar Swaminathan 		}
4298d738d7dSSukumar Swaminathan 	}
4308d738d7dSSukumar Swaminathan 	oce_unconfigure(dev);
4318d738d7dSSukumar Swaminathan 
4324d0e5007SSukumar Swaminathan 	return (DDI_SUCCESS);
4334d0e5007SSukumar Swaminathan } /* oce_detach */
4344d0e5007SSukumar Swaminathan 
4354d0e5007SSukumar Swaminathan static int
oce_quiesce(dev_info_t * dip)4364d0e5007SSukumar Swaminathan oce_quiesce(dev_info_t *dip)
4374d0e5007SSukumar Swaminathan {
4384d0e5007SSukumar Swaminathan 	int ret = DDI_SUCCESS;
4394d0e5007SSukumar Swaminathan 	struct oce_dev *dev = ddi_get_driver_private(dip);
4404d0e5007SSukumar Swaminathan 
4414d0e5007SSukumar Swaminathan 	if (dev == NULL) {
4424d0e5007SSukumar Swaminathan 		return (DDI_FAILURE);
4434d0e5007SSukumar Swaminathan 	}
4444d0e5007SSukumar Swaminathan 	if (dev->suspended) {
4454d0e5007SSukumar Swaminathan 		return (DDI_SUCCESS);
4464d0e5007SSukumar Swaminathan 	}
4474d0e5007SSukumar Swaminathan 
4488d738d7dSSukumar Swaminathan 	oce_chip_di(dev);
4494d0e5007SSukumar Swaminathan 
4504d0e5007SSukumar Swaminathan 	ret = oce_reset_fun(dev);
4514d0e5007SSukumar Swaminathan 
4524d0e5007SSukumar Swaminathan 	return (ret);
4534d0e5007SSukumar Swaminathan }
4544d0e5007SSukumar Swaminathan 
4554d0e5007SSukumar Swaminathan static int
oce_suspend(dev_info_t * dip)4564d0e5007SSukumar Swaminathan oce_suspend(dev_info_t *dip)
4574d0e5007SSukumar Swaminathan {
4584d0e5007SSukumar Swaminathan 	struct oce_dev *dev = ddi_get_driver_private(dip);
4594d0e5007SSukumar Swaminathan 
4604d0e5007SSukumar Swaminathan 	mutex_enter(&dev->dev_lock);
4614d0e5007SSukumar Swaminathan 	/* Suspend the card */
4624d0e5007SSukumar Swaminathan 	dev->suspended = B_TRUE;
4634d0e5007SSukumar Swaminathan 	/* stop the adapter */
4644d0e5007SSukumar Swaminathan 	if (dev->state & STATE_MAC_STARTED) {
4654d0e5007SSukumar Swaminathan 		oce_stop(dev);
4668d738d7dSSukumar Swaminathan 		oce_unsetup_adapter(dev);
4674d0e5007SSukumar Swaminathan 	}
4684d0e5007SSukumar Swaminathan 	dev->state &= ~STATE_MAC_STARTED;
4694d0e5007SSukumar Swaminathan 	mutex_exit(&dev->dev_lock);
4704d0e5007SSukumar Swaminathan 	return (DDI_SUCCESS);
4714d0e5007SSukumar Swaminathan } /* oce_suspend */
4724d0e5007SSukumar Swaminathan 
4734d0e5007SSukumar Swaminathan static int
oce_resume(dev_info_t * dip)4744d0e5007SSukumar Swaminathan oce_resume(dev_info_t *dip)
4754d0e5007SSukumar Swaminathan {
4764d0e5007SSukumar Swaminathan 	struct oce_dev *dev;
4774d0e5007SSukumar Swaminathan 	int ret;
4784d0e5007SSukumar Swaminathan 
4794d0e5007SSukumar Swaminathan 	/* get the dev pointer from dip */
4804d0e5007SSukumar Swaminathan 	dev = ddi_get_driver_private(dip);
4814d0e5007SSukumar Swaminathan 	mutex_enter(&dev->dev_lock);
4824d0e5007SSukumar Swaminathan 	if (!dev->suspended) {
4834d0e5007SSukumar Swaminathan 		mutex_exit(&dev->dev_lock);
4844d0e5007SSukumar Swaminathan 		return (DDI_SUCCESS);
4854d0e5007SSukumar Swaminathan 	}
4865b9d3151SSukumar Swaminathan 	if (!(dev->state & STATE_MAC_STARTED)) {
4878d738d7dSSukumar Swaminathan 		ret = oce_setup_adapter(dev);
4888d738d7dSSukumar Swaminathan 		if (ret != DDI_SUCCESS) {
4898d738d7dSSukumar Swaminathan 			mutex_exit(&dev->dev_lock);
4908d738d7dSSukumar Swaminathan 			return (DDI_FAILURE);
4918d738d7dSSukumar Swaminathan 		}
4924d0e5007SSukumar Swaminathan 		ret = oce_start(dev);
4934d0e5007SSukumar Swaminathan 		if (ret != DDI_SUCCESS) {
4944d0e5007SSukumar Swaminathan 			mutex_exit(&dev->dev_lock);
4954d0e5007SSukumar Swaminathan 			return (DDI_FAILURE);
4964d0e5007SSukumar Swaminathan 		}
4974d0e5007SSukumar Swaminathan 	}
4984d0e5007SSukumar Swaminathan 	dev->suspended = B_FALSE;
4994d0e5007SSukumar Swaminathan 	dev->state |= STATE_MAC_STARTED;
5004d0e5007SSukumar Swaminathan 	mutex_exit(&dev->dev_lock);
5014d0e5007SSukumar Swaminathan 	return (ret);
5024d0e5007SSukumar Swaminathan } /* oce_resume */
5034d0e5007SSukumar Swaminathan 
5044d0e5007SSukumar Swaminathan static void
oce_init_locks(struct oce_dev * dev)5054d0e5007SSukumar Swaminathan oce_init_locks(struct oce_dev *dev)
5064d0e5007SSukumar Swaminathan {
5074d0e5007SSukumar Swaminathan 	/* initialize locks */
5084d0e5007SSukumar Swaminathan 	mutex_init(&dev->dev_lock, NULL, MUTEX_DRIVER,
5094d0e5007SSukumar Swaminathan 	    DDI_INTR_PRI(dev->intr_pri));
5104d0e5007SSukumar Swaminathan 	mutex_init(&dev->bmbx_lock, NULL, MUTEX_DRIVER,
5114d0e5007SSukumar Swaminathan 	    DDI_INTR_PRI(dev->intr_pri));
5124d0e5007SSukumar Swaminathan } /* oce_init_locks */
5134d0e5007SSukumar Swaminathan 
5144d0e5007SSukumar Swaminathan static void
oce_destroy_locks(struct oce_dev * dev)5154d0e5007SSukumar Swaminathan oce_destroy_locks(struct oce_dev *dev)
5164d0e5007SSukumar Swaminathan {
5174d0e5007SSukumar Swaminathan 	mutex_destroy(&dev->dev_lock);
5184d0e5007SSukumar Swaminathan 	mutex_destroy(&dev->bmbx_lock);
5194d0e5007SSukumar Swaminathan } /* oce_destroy_locks */
5204d0e5007SSukumar Swaminathan 
5214d0e5007SSukumar Swaminathan static void
oce_unconfigure(struct oce_dev * dev)5224d0e5007SSukumar Swaminathan oce_unconfigure(struct oce_dev *dev)
5234d0e5007SSukumar Swaminathan {
5244d0e5007SSukumar Swaminathan 	uint32_t state = dev->attach_state;
5254d0e5007SSukumar Swaminathan 
5264d0e5007SSukumar Swaminathan 	if (state & ATTACH_MAC_REG) {
5274d0e5007SSukumar Swaminathan 		(void) mac_unregister(dev->mac_handle);
5284d0e5007SSukumar Swaminathan 	}
5294d0e5007SSukumar Swaminathan 	if (state & ATTACH_STAT_INIT) {
5304d0e5007SSukumar Swaminathan 		oce_stat_fini(dev);
5314d0e5007SSukumar Swaminathan 	}
5328d738d7dSSukumar Swaminathan 	if (state & ATTACH_SETUP_ADAP) {
5338d738d7dSSukumar Swaminathan 		oce_unsetup_adapter(dev);
5348d738d7dSSukumar Swaminathan 	}
5358d738d7dSSukumar Swaminathan 	if (state & ATTACH_SETUP_TXRX) {
5368d738d7dSSukumar Swaminathan 		oce_fini_txrx(dev);
5378d738d7dSSukumar Swaminathan 	}
5388d738d7dSSukumar Swaminathan 	if (state & ATTACH_HW_INIT) {
5398d738d7dSSukumar Swaminathan 		oce_hw_fini(dev);
5404d0e5007SSukumar Swaminathan 	}
5414d0e5007SSukumar Swaminathan 	if (state & ATTACH_LOCK_INIT) {
5424d0e5007SSukumar Swaminathan 		oce_destroy_locks(dev);
5434d0e5007SSukumar Swaminathan 	}
5445b9d3151SSukumar Swaminathan 	if (state & ATTACH_SETUP_INTR) {
5455b9d3151SSukumar Swaminathan 		(void) oce_teardown_intr(dev);
5465b9d3151SSukumar Swaminathan 	}
5475b9d3151SSukumar Swaminathan 	if (state & ATTACH_PCI_INIT) {
5485b9d3151SSukumar Swaminathan 		oce_pci_fini(dev);
5495b9d3151SSukumar Swaminathan 	}
550*3abb112fSGarrett D'Amore 	if (state & ATTACH_PCI_CFG) {
551*3abb112fSGarrett D'Amore 		pci_config_teardown(&dev->pci_cfg_handle);
552*3abb112fSGarrett D'Amore 	}
5534d0e5007SSukumar Swaminathan 	if (state & ATTACH_FM_INIT) {
5544d0e5007SSukumar Swaminathan 		oce_fm_fini(dev);
5554d0e5007SSukumar Swaminathan 	}
5564d0e5007SSukumar Swaminathan 	if (state & ATTACH_DEV_INIT) {
5574d0e5007SSukumar Swaminathan 		ddi_set_driver_private(dev->dip, NULL);
558*3abb112fSGarrett D'Amore 		oce_dev_list[dev->dev_list_index] = NULL;
5594d0e5007SSukumar Swaminathan 		kmem_free(dev, sizeof (struct oce_dev));
5604d0e5007SSukumar Swaminathan 	}
5614d0e5007SSukumar Swaminathan } /* oce_unconfigure */
5624d0e5007SSukumar Swaminathan 
5634d0e5007SSukumar Swaminathan static void
oce_get_params(struct oce_dev * dev)5644d0e5007SSukumar Swaminathan oce_get_params(struct oce_dev *dev)
5654d0e5007SSukumar Swaminathan {
5664d0e5007SSukumar Swaminathan 	uint32_t log_level;
5674d0e5007SSukumar Swaminathan 	uint16_t mod_mask;
5684d0e5007SSukumar Swaminathan 	uint16_t severity;
5695b9d3151SSukumar Swaminathan 	/*
5705b9d3151SSukumar Swaminathan 	 * Allowed values for the driver parameters. If all values in a range
5715b9d3151SSukumar Swaminathan 	 * is allowed, the the array has only one value.
5725b9d3151SSukumar Swaminathan 	 */
5735b9d3151SSukumar Swaminathan 	uint32_t fc_values[] = {OCE_FC_NONE, OCE_FC_TX, OCE_FC_RX,
5745b9d3151SSukumar Swaminathan 	    OCE_DEFAULT_FLOW_CONTROL, END};
5755b9d3151SSukumar Swaminathan 	uint32_t mtu_values[] = {OCE_MIN_MTU, OCE_MAX_MTU, END};
5765b9d3151SSukumar Swaminathan 	uint32_t tx_rs_values[] = {SIZE_256, SIZE_512, SIZE_1K, SIZE_2K, END};
5775b9d3151SSukumar Swaminathan 	uint32_t tx_bcl_values[] = {SIZE_128, SIZE_256, SIZE_512, SIZE_1K,
5785b9d3151SSukumar Swaminathan 	    SIZE_2K, END};
5795b9d3151SSukumar Swaminathan 	uint32_t rx_bcl_values[] = {SIZE_128, SIZE_256, SIZE_512, SIZE_1K,
5805b9d3151SSukumar Swaminathan 	    SIZE_2K, END};
5815b9d3151SSukumar Swaminathan 	uint32_t rq_fs_values[] = {SIZE_2K, SIZE_4K, SIZE_8K, END};
5825b9d3151SSukumar Swaminathan 	uint32_t rq_mb_values[] = {SIZE_2K, SIZE_4K, SIZE_8K, END};
5835b9d3151SSukumar Swaminathan 	uint32_t lso_capable_values[] = {0, 1, END};
5845b9d3151SSukumar Swaminathan 	uint32_t fm_caps_values[] = {DDI_FM_NOT_CAPABLE, OCE_FM_CAPABILITY,
5855b9d3151SSukumar Swaminathan 	    END};
5865b9d3151SSukumar Swaminathan 	uint32_t tx_rt_values[] = {END};
5875b9d3151SSukumar Swaminathan 	uint32_t rx_ppi_values[] = {END};
5885b9d3151SSukumar Swaminathan 	uint32_t rx_rings_values[] = {END};
5895b9d3151SSukumar Swaminathan 	uint32_t tx_rings_values[] = {END};
5905b9d3151SSukumar Swaminathan 	uint32_t log_level_values[] = {END};
5914d0e5007SSukumar Swaminathan 
5924d0e5007SSukumar Swaminathan 	/* non tunables  */
5934d0e5007SSukumar Swaminathan 	dev->rx_ring_size = OCE_DEFAULT_RX_RING_SIZE;
5944d0e5007SSukumar Swaminathan 
5954d0e5007SSukumar Swaminathan 	/* configurable parameters */
5965b9d3151SSukumar Swaminathan 	dev->flow_control = oce_get_prop(dev, (char *)flow_control, OCE_FC_NONE,
5975b9d3151SSukumar Swaminathan 	    OCE_DEFAULT_FLOW_CONTROL, OCE_DEFAULT_FLOW_CONTROL, fc_values);
5985b9d3151SSukumar Swaminathan 
5995b9d3151SSukumar Swaminathan 	dev->mtu = oce_get_prop(dev, (char *)mtu_prop_name, OCE_MIN_MTU,
6005b9d3151SSukumar Swaminathan 	    OCE_MAX_MTU, OCE_MIN_MTU, mtu_values);
6015b9d3151SSukumar Swaminathan 
6025b9d3151SSukumar Swaminathan 	dev->tx_ring_size = oce_get_prop(dev, (char *)tx_ring_size_name,
6035b9d3151SSukumar Swaminathan 	    SIZE_256, SIZE_2K, OCE_DEFAULT_TX_RING_SIZE, tx_rs_values);
6045b9d3151SSukumar Swaminathan 
6055b9d3151SSukumar Swaminathan 	dev->tx_bcopy_limit = oce_get_prop(dev, (char *)tx_bcopy_limit_name,
6065b9d3151SSukumar Swaminathan 	    SIZE_128, SIZE_2K, OCE_DEFAULT_TX_BCOPY_LIMIT, tx_bcl_values);
6075b9d3151SSukumar Swaminathan 
6085b9d3151SSukumar Swaminathan 	dev->rx_bcopy_limit = oce_get_prop(dev, (char *)rx_bcopy_limit_name,
6095b9d3151SSukumar Swaminathan 	    SIZE_128, SIZE_2K, OCE_DEFAULT_RX_BCOPY_LIMIT, rx_bcl_values);
6105b9d3151SSukumar Swaminathan 
6115b9d3151SSukumar Swaminathan 	dev->rq_frag_size = oce_get_prop(dev, (char *)rx_frag_size_name,
6125b9d3151SSukumar Swaminathan 	    SIZE_2K, SIZE_8K, OCE_RQ_BUF_SIZE, rq_fs_values);
6135b9d3151SSukumar Swaminathan 
6145b9d3151SSukumar Swaminathan 	dev->rq_max_bufs = oce_get_prop(dev, (char *)rx_max_bufs_name, SIZE_2K,
6155b9d3151SSukumar Swaminathan 	    SIZE_8K, OCE_RQ_NUM_BUFFERS, rq_mb_values);
6165b9d3151SSukumar Swaminathan 
6175b9d3151SSukumar Swaminathan 	dev->lso_capable = oce_get_prop(dev, (char *)lso_capable_name, 0,
6185b9d3151SSukumar Swaminathan 	    1, 1, lso_capable_values);
6194d0e5007SSukumar Swaminathan 
6205b9d3151SSukumar Swaminathan 	dev->fm_caps = oce_get_prop(dev, (char *)fm_cap_name,
6215b9d3151SSukumar Swaminathan 	    DDI_FM_NOT_CAPABLE, OCE_FM_CAPABILITY, OCE_FM_CAPABILITY,
6225b9d3151SSukumar Swaminathan 	    fm_caps_values);
6234d0e5007SSukumar Swaminathan 
6245b9d3151SSukumar Swaminathan 	dev->tx_reclaim_threshold = oce_get_prop(dev,
6255b9d3151SSukumar Swaminathan 	    (char *)tx_reclaim_threshold_name, 0, dev->tx_ring_size/2,
6265b9d3151SSukumar Swaminathan 	    OCE_DEFAULT_TX_RECLAIM_THRESHOLD, tx_rt_values);
6274d0e5007SSukumar Swaminathan 
6285b9d3151SSukumar Swaminathan 	dev->rx_pkt_per_intr = oce_get_prop(dev, (char *)rx_pkt_per_intr_name,
6295b9d3151SSukumar Swaminathan 	    0, dev->rx_ring_size/2, OCE_DEFAULT_RX_PKT_PER_INTR, rx_ppi_values);
6304d0e5007SSukumar Swaminathan 
6315b9d3151SSukumar Swaminathan 	dev->rx_rings = oce_get_prop(dev, (char *)rx_rings_name,
632*3abb112fSGarrett D'Amore 	    OCE_MIN_RQ, OCE_MAX_RQ, OCE_DEFAULT_RQS, rx_rings_values);
6334d0e5007SSukumar Swaminathan 
6345b9d3151SSukumar Swaminathan 	dev->tx_rings = oce_get_prop(dev, (char *)tx_rings_name,
6355b9d3151SSukumar Swaminathan 	    OCE_DEFAULT_WQS, OCE_DEFAULT_WQS, OCE_DEFAULT_WQS, tx_rings_values);
6365b9d3151SSukumar Swaminathan 
6375b9d3151SSukumar Swaminathan 	log_level = oce_get_prop(dev, (char *)log_level_name, 0,
6385b9d3151SSukumar Swaminathan 	    OCE_MAX_LOG_SETTINGS, OCE_DEFAULT_LOG_SETTINGS, log_level_values);
6394d0e5007SSukumar Swaminathan 
6404d0e5007SSukumar Swaminathan 	severity = (uint16_t)(log_level & 0xffff);
6414d0e5007SSukumar Swaminathan 	mod_mask = (uint16_t)(log_level >> 16);
6424d0e5007SSukumar Swaminathan 	if (mod_mask > MOD_ISR) {
6434d0e5007SSukumar Swaminathan 		mod_mask = 0;
6444d0e5007SSukumar Swaminathan 	}
6454d0e5007SSukumar Swaminathan 	if (severity > CE_IGNORE) {
6464d0e5007SSukumar Swaminathan 		severity = 0;
6474d0e5007SSukumar Swaminathan 	}
6484d0e5007SSukumar Swaminathan 
6494d0e5007SSukumar Swaminathan 	dev->mod_mask = mod_mask;
6504d0e5007SSukumar Swaminathan 	dev->severity = severity;
6514d0e5007SSukumar Swaminathan } /* oce_get_params */
6525b9d3151SSukumar Swaminathan 
6535b9d3151SSukumar Swaminathan static int
oce_get_prop(struct oce_dev * dev,char * propname,int minval,int maxval,int defval,uint32_t * values)6545b9d3151SSukumar Swaminathan oce_get_prop(struct oce_dev *dev, char *propname, int minval, int maxval,
6555b9d3151SSukumar Swaminathan     int defval, uint32_t *values)
6565b9d3151SSukumar Swaminathan {
6575b9d3151SSukumar Swaminathan 	int value = 0;
6585b9d3151SSukumar Swaminathan 	int i = 0;
6595b9d3151SSukumar Swaminathan 
6605b9d3151SSukumar Swaminathan 	value = ddi_prop_get_int(DDI_DEV_T_ANY, dev->dip,
6615b9d3151SSukumar Swaminathan 	    DDI_PROP_DONTPASS, propname, defval);
6625b9d3151SSukumar Swaminathan 
6635b9d3151SSukumar Swaminathan 	if (value > maxval)
6645b9d3151SSukumar Swaminathan 		value = maxval;
6655b9d3151SSukumar Swaminathan 
6665b9d3151SSukumar Swaminathan 	if (value < minval)
6675b9d3151SSukumar Swaminathan 		value = minval;
6685b9d3151SSukumar Swaminathan 
6695b9d3151SSukumar Swaminathan 	while (values[i] != 0xdeadface) {
6705b9d3151SSukumar Swaminathan 		if (values[i] == value) {
6715b9d3151SSukumar Swaminathan 			break;
6725b9d3151SSukumar Swaminathan 		}
6735b9d3151SSukumar Swaminathan 		i++;
6745b9d3151SSukumar Swaminathan 	}
6755b9d3151SSukumar Swaminathan 
6765b9d3151SSukumar Swaminathan 	if ((i != 0) && (values[i] == 0xdeadface)) {
6775b9d3151SSukumar Swaminathan 		value = defval;
6785b9d3151SSukumar Swaminathan 	}
6795b9d3151SSukumar Swaminathan 
6805b9d3151SSukumar Swaminathan 	return (value);
6815b9d3151SSukumar Swaminathan }
682