1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /* Copyright © 2003-2011 Emulex. All rights reserved.  */
23 
24 
25 /*
26  * Source file containing the implementation of the driver entry points
27  * and related helper functions
28  */
29 
30 #include <oce_impl.h>
31 #include <oce_stat.h>
32 #include <oce_ioctl.h>
33 
34 #define	ATTACH_DEV_INIT 	0x1
35 #define	ATTACH_FM_INIT		0x2
36 #define	ATTACH_PCI_CFG		0x4
37 #define	ATTACH_LOCK_INIT	0x8
38 #define	ATTACH_PCI_INIT 	0x10
39 #define	ATTACH_HW_INIT		0x20
40 #define	ATTACH_SETUP_TXRX 	0x40
41 #define	ATTACH_SETUP_ADAP	0x80
42 #define	ATTACH_SETUP_INTR	0x100
43 #define	ATTACH_STAT_INIT	0x200
44 #define	ATTACH_MAC_REG		0x400
45 
46 /* ---[ globals and externs ]-------------------------------------------- */
47 const char oce_ident_string[] = OCE_IDENT_STRING;
48 const char oce_mod_name[] = OCE_MOD_NAME;
49 struct oce_dev *oce_dev_list[MAX_DEVS + 1];	/* Last entry is invalid */
50 
51 /* driver properties */
52 static const char flow_control[]	 = "flow_control";
53 static const char mtu_prop_name[]	 = "oce_default_mtu";
54 static const char tx_ring_size_name[]	 = "tx_ring_size";
55 static const char tx_bcopy_limit_name[]	 = "tx_bcopy_limit";
56 static const char rx_bcopy_limit_name[]	 = "rx_bcopy_limit";
57 static const char rx_frag_size_name[]	 = "rx_frag_size";
58 static const char rx_max_bufs_name[]	 = "rx_max_bufs";
59 static const char fm_cap_name[]		 = "oce_fm_capability";
60 static const char log_level_name[]	 = "oce_log_level";
61 static const char lso_capable_name[]	 = "lso_capable";
62 static const char rx_pkt_per_intr_name[] = "rx_pkts_per_intr";
63 static const char tx_reclaim_threshold_name[] = "tx_reclaim_threshold";
64 static const char rx_rings_name[]	 = "max_rx_rings";
65 static const char tx_rings_name[]	 = "max_tx_rings";
66 
67 /* --[ static function prototypes here ]------------------------------- */
68 static int oce_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd);
69 static int oce_detach(dev_info_t *dip, ddi_detach_cmd_t cmd);
70 static int oce_quiesce(dev_info_t *dip);
71 static int oce_suspend(dev_info_t *dip);
72 static int oce_resume(dev_info_t *dip);
73 static void oce_unconfigure(struct oce_dev *dev);
74 static void oce_init_locks(struct oce_dev *dev);
75 static void oce_destroy_locks(struct oce_dev *dev);
76 static void oce_get_params(struct oce_dev *dev);
77 static int oce_get_prop(struct oce_dev *dev, char *propname, int minval,
78     int maxval, int defval, uint32_t *values);
79 
80 static struct cb_ops oce_cb_ops = {
81 	nulldev,		/* cb_open */
82 	nulldev,		/* cb_close */
83 	nodev,			/* cb_strategy */
84 	nodev,			/* cb_print */
85 	nodev,			/* cb_dump */
86 	nodev,			/* cb_read */
87 	nodev,			/* cb_write */
88 	nodev,			/* cb_ioctl */
89 	nodev,			/* cb_devmap */
90 	nodev,			/* cb_mmap */
91 	nodev,			/* cb_segmap */
92 	nochpoll,		/* cb_chpoll */
93 	ddi_prop_op,	/* cb_prop_op */
94 	NULL,			/* cb_stream */
95 	D_MP,			/* cb_flag */
96 	CB_REV,			/* cb_rev */
97 	nodev,			/* cb_aread */
98 	nodev			/* cb_awrite */
99 };
100 
101 static struct dev_ops oce_dev_ops = {
102 	DEVO_REV,	/* devo_rev */
103 	0,		/* devo_refcnt */
104 	NULL,		/* devo_getinfo */
105 	NULL,		/* devo_identify */
106 	nulldev,	/* devo_probe */
107 	oce_attach,	/* devo_attach */
108 	oce_detach,	/* devo_detach */
109 	nodev,		/* devo_reset */
110 	&oce_cb_ops,	/* devo_cb_ops */
111 	NULL,		/* devo_bus_ops */
112 	nodev,		/* devo_power */
113 	oce_quiesce	/* devo_quiesce */
114 };
115 
116 static struct modldrv oce_drv = {
117 	&mod_driverops,	/* Type of module.  This one is a driver */
118 	(char *)oce_ident_string, /* Description string */
119 	&oce_dev_ops,	/* driver ops */
120 };
121 
122 static struct modlinkage oce_mod_linkage = {
123 	MODREV_1, &oce_drv, NULL
124 };
125 
126 #define	OCE_M_CB_FLAGS	(MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | \
127     MC_PROPINFO)
128 static mac_callbacks_t oce_mac_cb = {
129 	OCE_M_CB_FLAGS,		/* mc_callbacks */
130 	oce_m_stat,		/* mc_getstat */
131 	oce_m_start,		/* mc_start */
132 	oce_m_stop,		/* mc_stop */
133 	oce_m_promiscuous,	/* mc_setpromisc */
134 	oce_m_multicast,	/* mc_multicast */
135 	oce_m_unicast,		/* mc_unicast */
136 	oce_m_send,		/* mc_tx */
137 	NULL,			/* mc_reserve */
138 	oce_m_ioctl,		/* mc_ioctl */
139 	oce_m_getcap,		/* mc_getcapab */
140 	NULL,			/* open */
141 	NULL,			/* close */
142 	oce_m_setprop,		/* set properties */
143 	oce_m_getprop,		/* get properties */
144 	oce_m_propinfo		/* properties info */
145 };
146 
147 extern char *oce_priv_props[];
148 
149 /* Module Init */
150 int
_info(struct modinfo * modinfop)151 _info(struct modinfo *modinfop)
152 {
153 	return (mod_info(&oce_mod_linkage, modinfop));
154 } /* _info */
155 
156 int
_init(void)157 _init(void)
158 {
159 	int ret = 0;
160 
161 	/* install the module */
162 	mac_init_ops(&oce_dev_ops, "oce");
163 
164 	ret = mod_install(&oce_mod_linkage);
165 	if (ret) {
166 		cmn_err(CE_WARN, "mod_install failed  rval=%x", ret);
167 	}
168 
169 	return (ret);
170 } /* _init */
171 
172 
173 int
_fini(void)174 _fini(void)
175 {
176 	int ret = 0;
177 	/* remove the module */
178 	ret = mod_remove(&oce_mod_linkage);
179 	if (ret != 0) {
180 		return (ret);
181 	}
182 
183 	mac_fini_ops(&oce_dev_ops);
184 
185 	return (ret);
186 } /* _fini */
187 
188 
189 static int
oce_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)190 oce_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
191 {
192 	int ret = 0;
193 	struct oce_dev *dev = NULL;
194 	mac_register_t *mac;
195 	uint8_t dev_index = 0;
196 
197 	switch (cmd) {
198 	case DDI_RESUME:
199 		return (oce_resume(dip));
200 	default:
201 		return (DDI_FAILURE);
202 
203 	case DDI_ATTACH:
204 		break;
205 	}
206 
207 	/* allocate dev */
208 	dev = kmem_zalloc(sizeof (struct oce_dev), KM_SLEEP);
209 
210 	/* populate the dev structure */
211 	dev->dip = dip;
212 	dev->dev_id = ddi_get_instance(dip);
213 	dev->suspended = B_FALSE;
214 
215 	dev->dev_list_index = MAX_DEVS;
216 	while (dev_index < MAX_DEVS) {
217 		(void) atomic_cas_ptr(&oce_dev_list[dev_index], NULL, dev);
218 		if (oce_dev_list[dev_index] == dev) {
219 			break;
220 		}
221 		dev_index++;
222 	}
223 	if (dev_index == MAX_DEVS) {
224 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
225 		    "Too many oce devices on the system. Failed to attach.");
226 		goto attach_fail;
227 	}
228 	dev->dev_list_index = dev_index;
229 
230 	/* get the parameters */
231 	oce_get_params(dev);
232 
233 	/*
234 	 * set the ddi driver private data pointer. This is
235 	 * sent to all mac callback entry points
236 	 */
237 	ddi_set_driver_private(dip, dev);
238 
239 	dev->attach_state |= ATTACH_DEV_INIT;
240 
241 	oce_fm_init(dev);
242 	dev->attach_state |= ATTACH_FM_INIT;
243 
244 	ret = pci_config_setup(dev->dip, &dev->pci_cfg_handle);
245 	if (ret != DDI_SUCCESS) {
246 		oce_log(dev, CE_WARN, MOD_CONFIG,
247 		    "Map PCI config failed with  %d", ret);
248 		goto attach_fail;
249 	}
250 	dev->attach_state |= ATTACH_PCI_CFG;
251 
252 	ret = oce_identify_hw(dev);
253 
254 	if (ret != DDI_SUCCESS) {
255 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
256 		    "Device Unknown");
257 		goto attach_fail;
258 	}
259 
260 	ret = oce_get_bdf(dev);
261 	if (ret != DDI_SUCCESS) {
262 		oce_log(dev, CE_WARN, MOD_CONFIG,
263 		    "Failed to read BDF, status = 0x%x", ret);
264 		goto attach_fail;
265 	}
266 	/* Update the dev->rss */
267 	oce_dev_rss_ready(dev);
268 
269 	/* setup PCI bars */
270 	ret = oce_pci_init(dev);
271 	if (ret != DDI_SUCCESS) {
272 		oce_log(dev, CE_WARN, MOD_CONFIG,
273 		    "PCI initialization failed with %d", ret);
274 		goto attach_fail;
275 	}
276 	dev->attach_state |= ATTACH_PCI_INIT;
277 
278 	ret = oce_setup_intr(dev);
279 	if (ret != DDI_SUCCESS) {
280 		oce_log(dev, CE_WARN, MOD_CONFIG,
281 		    "Interrupt setup failed with %d", ret);
282 		goto attach_fail;
283 
284 	}
285 	dev->attach_state |= ATTACH_SETUP_INTR;
286 
287 	/* initialize locks */
288 	oce_init_locks(dev);
289 	dev->attach_state |= ATTACH_LOCK_INIT;
290 
291 
292 	/* HW init */
293 	ret = oce_hw_init(dev);
294 	if (ret != DDI_SUCCESS) {
295 		oce_log(dev, CE_WARN, MOD_CONFIG,
296 		    "HW initialization failed with %d", ret);
297 		goto attach_fail;
298 	}
299 	dev->attach_state |= ATTACH_HW_INIT;
300 
301 	ret = oce_init_txrx(dev);
302 	if (ret  != DDI_SUCCESS) {
303 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
304 		    "Failed to init rings");
305 		goto attach_fail;
306 	}
307 	dev->attach_state |= ATTACH_SETUP_TXRX;
308 
309 	ret = oce_setup_adapter(dev);
310 	if (ret != DDI_SUCCESS) {
311 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
312 		    "Failed to setup adapter");
313 		goto attach_fail;
314 	}
315 	dev->attach_state |=  ATTACH_SETUP_ADAP;
316 
317 
318 	ret = oce_stat_init(dev);
319 	if (ret != DDI_SUCCESS) {
320 		oce_log(dev, CE_WARN, MOD_CONFIG,
321 		    "kstat setup Failed with %d", ret);
322 		goto attach_fail;
323 	}
324 	dev->attach_state |= ATTACH_STAT_INIT;
325 
326 	/* mac_register_t */
327 	oce_log(dev, CE_NOTE, MOD_CONFIG,
328 	    "MAC_VERSION = 0x%x", MAC_VERSION);
329 	mac = mac_alloc(MAC_VERSION);
330 	if (mac == NULL) {
331 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
332 		    "MAC allocation Failed");
333 		goto attach_fail;
334 	}
335 	/*
336 	 * fill the mac structure before calling mac_register
337 	 */
338 	mac->m_type_ident = MAC_PLUGIN_IDENT_ETHER;
339 	mac->m_driver = dev;
340 	mac->m_dip = dip;
341 	mac->m_src_addr = dev->mac_addr;
342 	mac->m_callbacks = &oce_mac_cb;
343 	mac->m_min_sdu = 0;
344 	mac->m_max_sdu = dev->mtu;
345 	mac->m_margin = VTAG_SIZE;
346 	mac->m_priv_props = oce_priv_props;
347 
348 	oce_log(dev, CE_NOTE, MOD_CONFIG,
349 	    "Driver Private structure = 0x%p", (void *)dev);
350 
351 	/* now register with GLDv3 */
352 	ret = mac_register(mac, (mac_handle_t *)&dev->mac_handle);
353 	/* regardless of the status, free mac_register */
354 	mac_free(mac);
355 	mac = NULL;
356 	if (ret != DDI_SUCCESS) {
357 		oce_log(dev, CE_WARN, MOD_CONFIG,
358 		    "MAC registration failed :0x%x", ret);
359 		goto attach_fail;
360 
361 	}
362 
363 	/* correct link status only after start */
364 	dev->link_status = LINK_STATE_UNKNOWN;
365 	mac_link_update(dev->mac_handle, dev->link_status);
366 
367 	dev->attach_state |= ATTACH_MAC_REG;
368 	dev->state |= STATE_INIT;
369 
370 	oce_log(dev, CE_NOTE, MOD_CONFIG, "%s",
371 	    "ATTACH SUCCESS");
372 
373 	return (DDI_SUCCESS);
374 
375 attach_fail:
376 	oce_unconfigure(dev);
377 	return (DDI_FAILURE);
378 } /* oce_attach */
379 
380 static int
oce_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)381 oce_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
382 {
383 	struct oce_dev *dev;
384 	int pcnt = 0;
385 	int qid;
386 
387 	dev = ddi_get_driver_private(dip);
388 	if (dev == NULL) {
389 		return (DDI_FAILURE);
390 	}
391 	oce_log(dev, CE_NOTE, MOD_CONFIG,
392 	    "Detaching driver: cmd = 0x%x", cmd);
393 
394 	switch (cmd) {
395 	default:
396 		return (DDI_FAILURE);
397 	case DDI_SUSPEND:
398 		return (oce_suspend(dip));
399 	case DDI_DETACH:
400 		break;
401 	} /* switch cmd */
402 
403 	/* Fail detach if MAC unregister is unsuccessfule */
404 	if (mac_unregister(dev->mac_handle) != 0) {
405 		oce_log(dev, CE_WARN, MOD_CONFIG, "%s",
406 		    "Failed to unregister MAC ");
407 	}
408 	dev->attach_state &= ~ATTACH_MAC_REG;
409 
410 	/* check if the detach is called with out stopping */
411 	DEV_LOCK(dev);
412 	if (dev->state & STATE_MAC_STARTED) {
413 		dev->state &= ~STATE_MAC_STARTED;
414 		oce_stop(dev);
415 		DEV_UNLOCK(dev);
416 	} else
417 		DEV_UNLOCK(dev);
418 
419 	/*
420 	 * Wait for Packets sent up to be freed
421 	 */
422 	for (qid = 0; qid < dev->rx_rings; qid++) {
423 		pcnt = oce_rx_pending(dev, dev->rq[qid], DEFAULT_DRAIN_TIME);
424 		if (pcnt != 0) {
425 			oce_log(dev, CE_WARN, MOD_CONFIG,
426 			    "%d Pending Buffers Detach failed", pcnt);
427 			return (DDI_FAILURE);
428 		}
429 	}
430 	oce_unconfigure(dev);
431 
432 	return (DDI_SUCCESS);
433 } /* oce_detach */
434 
435 static int
oce_quiesce(dev_info_t * dip)436 oce_quiesce(dev_info_t *dip)
437 {
438 	int ret = DDI_SUCCESS;
439 	struct oce_dev *dev = ddi_get_driver_private(dip);
440 
441 	if (dev == NULL) {
442 		return (DDI_FAILURE);
443 	}
444 	if (dev->suspended) {
445 		return (DDI_SUCCESS);
446 	}
447 
448 	oce_chip_di(dev);
449 
450 	ret = oce_reset_fun(dev);
451 
452 	return (ret);
453 }
454 
455 static int
oce_suspend(dev_info_t * dip)456 oce_suspend(dev_info_t *dip)
457 {
458 	struct oce_dev *dev = ddi_get_driver_private(dip);
459 
460 	mutex_enter(&dev->dev_lock);
461 	/* Suspend the card */
462 	dev->suspended = B_TRUE;
463 	/* stop the adapter */
464 	if (dev->state & STATE_MAC_STARTED) {
465 		oce_stop(dev);
466 		oce_unsetup_adapter(dev);
467 	}
468 	dev->state &= ~STATE_MAC_STARTED;
469 	mutex_exit(&dev->dev_lock);
470 	return (DDI_SUCCESS);
471 } /* oce_suspend */
472 
473 static int
oce_resume(dev_info_t * dip)474 oce_resume(dev_info_t *dip)
475 {
476 	struct oce_dev *dev;
477 	int ret;
478 
479 	/* get the dev pointer from dip */
480 	dev = ddi_get_driver_private(dip);
481 	mutex_enter(&dev->dev_lock);
482 	if (!dev->suspended) {
483 		mutex_exit(&dev->dev_lock);
484 		return (DDI_SUCCESS);
485 	}
486 	if (!(dev->state & STATE_MAC_STARTED)) {
487 		ret = oce_setup_adapter(dev);
488 		if (ret != DDI_SUCCESS) {
489 			mutex_exit(&dev->dev_lock);
490 			return (DDI_FAILURE);
491 		}
492 		ret = oce_start(dev);
493 		if (ret != DDI_SUCCESS) {
494 			mutex_exit(&dev->dev_lock);
495 			return (DDI_FAILURE);
496 		}
497 	}
498 	dev->suspended = B_FALSE;
499 	dev->state |= STATE_MAC_STARTED;
500 	mutex_exit(&dev->dev_lock);
501 	return (ret);
502 } /* oce_resume */
503 
504 static void
oce_init_locks(struct oce_dev * dev)505 oce_init_locks(struct oce_dev *dev)
506 {
507 	/* initialize locks */
508 	mutex_init(&dev->dev_lock, NULL, MUTEX_DRIVER,
509 	    DDI_INTR_PRI(dev->intr_pri));
510 	mutex_init(&dev->bmbx_lock, NULL, MUTEX_DRIVER,
511 	    DDI_INTR_PRI(dev->intr_pri));
512 } /* oce_init_locks */
513 
514 static void
oce_destroy_locks(struct oce_dev * dev)515 oce_destroy_locks(struct oce_dev *dev)
516 {
517 	mutex_destroy(&dev->dev_lock);
518 	mutex_destroy(&dev->bmbx_lock);
519 } /* oce_destroy_locks */
520 
521 static void
oce_unconfigure(struct oce_dev * dev)522 oce_unconfigure(struct oce_dev *dev)
523 {
524 	uint32_t state = dev->attach_state;
525 
526 	if (state & ATTACH_MAC_REG) {
527 		(void) mac_unregister(dev->mac_handle);
528 	}
529 	if (state & ATTACH_STAT_INIT) {
530 		oce_stat_fini(dev);
531 	}
532 	if (state & ATTACH_SETUP_ADAP) {
533 		oce_unsetup_adapter(dev);
534 	}
535 	if (state & ATTACH_SETUP_TXRX) {
536 		oce_fini_txrx(dev);
537 	}
538 	if (state & ATTACH_HW_INIT) {
539 		oce_hw_fini(dev);
540 	}
541 	if (state & ATTACH_LOCK_INIT) {
542 		oce_destroy_locks(dev);
543 	}
544 	if (state & ATTACH_SETUP_INTR) {
545 		(void) oce_teardown_intr(dev);
546 	}
547 	if (state & ATTACH_PCI_INIT) {
548 		oce_pci_fini(dev);
549 	}
550 	if (state & ATTACH_PCI_CFG) {
551 		pci_config_teardown(&dev->pci_cfg_handle);
552 	}
553 	if (state & ATTACH_FM_INIT) {
554 		oce_fm_fini(dev);
555 	}
556 	if (state & ATTACH_DEV_INIT) {
557 		ddi_set_driver_private(dev->dip, NULL);
558 		oce_dev_list[dev->dev_list_index] = NULL;
559 		kmem_free(dev, sizeof (struct oce_dev));
560 	}
561 } /* oce_unconfigure */
562 
563 static void
oce_get_params(struct oce_dev * dev)564 oce_get_params(struct oce_dev *dev)
565 {
566 	uint32_t log_level;
567 	uint16_t mod_mask;
568 	uint16_t severity;
569 	/*
570 	 * Allowed values for the driver parameters. If all values in a range
571 	 * is allowed, the the array has only one value.
572 	 */
573 	uint32_t fc_values[] = {OCE_FC_NONE, OCE_FC_TX, OCE_FC_RX,
574 	    OCE_DEFAULT_FLOW_CONTROL, END};
575 	uint32_t mtu_values[] = {OCE_MIN_MTU, OCE_MAX_MTU, END};
576 	uint32_t tx_rs_values[] = {SIZE_256, SIZE_512, SIZE_1K, SIZE_2K, END};
577 	uint32_t tx_bcl_values[] = {SIZE_128, SIZE_256, SIZE_512, SIZE_1K,
578 	    SIZE_2K, END};
579 	uint32_t rx_bcl_values[] = {SIZE_128, SIZE_256, SIZE_512, SIZE_1K,
580 	    SIZE_2K, END};
581 	uint32_t rq_fs_values[] = {SIZE_2K, SIZE_4K, SIZE_8K, END};
582 	uint32_t rq_mb_values[] = {SIZE_2K, SIZE_4K, SIZE_8K, END};
583 	uint32_t lso_capable_values[] = {0, 1, END};
584 	uint32_t fm_caps_values[] = {DDI_FM_NOT_CAPABLE, OCE_FM_CAPABILITY,
585 	    END};
586 	uint32_t tx_rt_values[] = {END};
587 	uint32_t rx_ppi_values[] = {END};
588 	uint32_t rx_rings_values[] = {END};
589 	uint32_t tx_rings_values[] = {END};
590 	uint32_t log_level_values[] = {END};
591 
592 	/* non tunables  */
593 	dev->rx_ring_size = OCE_DEFAULT_RX_RING_SIZE;
594 
595 	/* configurable parameters */
596 	dev->flow_control = oce_get_prop(dev, (char *)flow_control, OCE_FC_NONE,
597 	    OCE_DEFAULT_FLOW_CONTROL, OCE_DEFAULT_FLOW_CONTROL, fc_values);
598 
599 	dev->mtu = oce_get_prop(dev, (char *)mtu_prop_name, OCE_MIN_MTU,
600 	    OCE_MAX_MTU, OCE_MIN_MTU, mtu_values);
601 
602 	dev->tx_ring_size = oce_get_prop(dev, (char *)tx_ring_size_name,
603 	    SIZE_256, SIZE_2K, OCE_DEFAULT_TX_RING_SIZE, tx_rs_values);
604 
605 	dev->tx_bcopy_limit = oce_get_prop(dev, (char *)tx_bcopy_limit_name,
606 	    SIZE_128, SIZE_2K, OCE_DEFAULT_TX_BCOPY_LIMIT, tx_bcl_values);
607 
608 	dev->rx_bcopy_limit = oce_get_prop(dev, (char *)rx_bcopy_limit_name,
609 	    SIZE_128, SIZE_2K, OCE_DEFAULT_RX_BCOPY_LIMIT, rx_bcl_values);
610 
611 	dev->rq_frag_size = oce_get_prop(dev, (char *)rx_frag_size_name,
612 	    SIZE_2K, SIZE_8K, OCE_RQ_BUF_SIZE, rq_fs_values);
613 
614 	dev->rq_max_bufs = oce_get_prop(dev, (char *)rx_max_bufs_name, SIZE_2K,
615 	    SIZE_8K, OCE_RQ_NUM_BUFFERS, rq_mb_values);
616 
617 	dev->lso_capable = oce_get_prop(dev, (char *)lso_capable_name, 0,
618 	    1, 1, lso_capable_values);
619 
620 	dev->fm_caps = oce_get_prop(dev, (char *)fm_cap_name,
621 	    DDI_FM_NOT_CAPABLE, OCE_FM_CAPABILITY, OCE_FM_CAPABILITY,
622 	    fm_caps_values);
623 
624 	dev->tx_reclaim_threshold = oce_get_prop(dev,
625 	    (char *)tx_reclaim_threshold_name, 0, dev->tx_ring_size/2,
626 	    OCE_DEFAULT_TX_RECLAIM_THRESHOLD, tx_rt_values);
627 
628 	dev->rx_pkt_per_intr = oce_get_prop(dev, (char *)rx_pkt_per_intr_name,
629 	    0, dev->rx_ring_size/2, OCE_DEFAULT_RX_PKT_PER_INTR, rx_ppi_values);
630 
631 	dev->rx_rings = oce_get_prop(dev, (char *)rx_rings_name,
632 	    OCE_MIN_RQ, OCE_MAX_RQ, OCE_DEFAULT_RQS, rx_rings_values);
633 
634 	dev->tx_rings = oce_get_prop(dev, (char *)tx_rings_name,
635 	    OCE_DEFAULT_WQS, OCE_DEFAULT_WQS, OCE_DEFAULT_WQS, tx_rings_values);
636 
637 	log_level = oce_get_prop(dev, (char *)log_level_name, 0,
638 	    OCE_MAX_LOG_SETTINGS, OCE_DEFAULT_LOG_SETTINGS, log_level_values);
639 
640 	severity = (uint16_t)(log_level & 0xffff);
641 	mod_mask = (uint16_t)(log_level >> 16);
642 	if (mod_mask > MOD_ISR) {
643 		mod_mask = 0;
644 	}
645 	if (severity > CE_IGNORE) {
646 		severity = 0;
647 	}
648 
649 	dev->mod_mask = mod_mask;
650 	dev->severity = severity;
651 } /* oce_get_params */
652 
653 static int
oce_get_prop(struct oce_dev * dev,char * propname,int minval,int maxval,int defval,uint32_t * values)654 oce_get_prop(struct oce_dev *dev, char *propname, int minval, int maxval,
655     int defval, uint32_t *values)
656 {
657 	int value = 0;
658 	int i = 0;
659 
660 	value = ddi_prop_get_int(DDI_DEV_T_ANY, dev->dip,
661 	    DDI_PROP_DONTPASS, propname, defval);
662 
663 	if (value > maxval)
664 		value = maxval;
665 
666 	if (value < minval)
667 		value = minval;
668 
669 	while (values[i] != 0xdeadface) {
670 		if (values[i] == value) {
671 			break;
672 		}
673 		i++;
674 	}
675 
676 	if ((i != 0) && (values[i] == 0xdeadface)) {
677 		value = defval;
678 	}
679 
680 	return (value);
681 }
682