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.
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.
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]
22 /* Copyright © 2003-2011 Emulex. All rights reserved. */
26 * Source file containing the implementation of the driver entry points
27 * and related helper functions
32 #include <oce_ioctl.h>
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
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 */
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";
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
);
80 static struct cb_ops oce_cb_ops
= {
81 nulldev
, /* cb_open */
82 nulldev
, /* cb_close */
83 nodev
, /* cb_strategy */
89 nodev
, /* cb_devmap */
91 nodev
, /* cb_segmap */
92 nochpoll
, /* cb_chpoll */
93 ddi_prop_op
, /* cb_prop_op */
101 static struct dev_ops oce_dev_ops
= {
102 DEVO_REV
, /* devo_rev */
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 */
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 */
122 static struct modlinkage oce_mod_linkage
= {
123 MODREV_1
, &oce_drv
, NULL
126 #define OCE_M_CB_FLAGS (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | \
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 */
142 oce_m_setprop
, /* set properties */
143 oce_m_getprop
, /* get properties */
144 oce_m_propinfo
/* properties info */
147 extern char *oce_priv_props
[];
151 _info(struct modinfo
*modinfop
)
153 return (mod_info(&oce_mod_linkage
, modinfop
));
161 /* install the module */
162 mac_init_ops(&oce_dev_ops
, "oce");
164 ret
= mod_install(&oce_mod_linkage
);
166 cmn_err(CE_WARN
, "mod_install failed rval=%x", ret
);
177 /* remove the module */
178 ret
= mod_remove(&oce_mod_linkage
);
183 mac_fini_ops(&oce_dev_ops
);
190 oce_attach(dev_info_t
*dip
, ddi_attach_cmd_t cmd
)
193 struct oce_dev
*dev
= NULL
;
195 uint8_t dev_index
= 0;
199 return (oce_resume(dip
));
201 return (DDI_FAILURE
);
208 dev
= kmem_zalloc(sizeof (struct oce_dev
), KM_SLEEP
);
210 /* populate the dev structure */
212 dev
->dev_id
= ddi_get_instance(dip
);
213 dev
->suspended
= B_FALSE
;
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
) {
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.");
228 dev
->dev_list_index
= dev_index
;
230 /* get the parameters */
234 * set the ddi driver private data pointer. This is
235 * sent to all mac callback entry points
237 ddi_set_driver_private(dip
, dev
);
239 dev
->attach_state
|= ATTACH_DEV_INIT
;
242 dev
->attach_state
|= ATTACH_FM_INIT
;
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
);
250 dev
->attach_state
|= ATTACH_PCI_CFG
;
252 ret
= oce_identify_hw(dev
);
254 if (ret
!= DDI_SUCCESS
) {
255 oce_log(dev
, CE_WARN
, MOD_CONFIG
, "%s",
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
);
266 /* Update the dev->rss */
267 oce_dev_rss_ready(dev
);
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
);
276 dev
->attach_state
|= ATTACH_PCI_INIT
;
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
);
285 dev
->attach_state
|= ATTACH_SETUP_INTR
;
287 /* initialize locks */
289 dev
->attach_state
|= ATTACH_LOCK_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
);
299 dev
->attach_state
|= ATTACH_HW_INIT
;
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");
307 dev
->attach_state
|= ATTACH_SETUP_TXRX
;
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");
315 dev
->attach_state
|= ATTACH_SETUP_ADAP
;
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
);
324 dev
->attach_state
|= ATTACH_STAT_INIT
;
327 oce_log(dev
, CE_NOTE
, MOD_CONFIG
,
328 "MAC_VERSION = 0x%x", MAC_VERSION
);
329 mac
= mac_alloc(MAC_VERSION
);
331 oce_log(dev
, CE_WARN
, MOD_CONFIG
, "%s",
332 "MAC allocation Failed");
336 * fill the mac structure before calling mac_register
338 mac
->m_type_ident
= MAC_PLUGIN_IDENT_ETHER
;
341 mac
->m_src_addr
= dev
->mac_addr
;
342 mac
->m_callbacks
= &oce_mac_cb
;
344 mac
->m_max_sdu
= dev
->mtu
;
345 mac
->m_margin
= VTAG_SIZE
;
346 mac
->m_priv_props
= oce_priv_props
;
348 oce_log(dev
, CE_NOTE
, MOD_CONFIG
,
349 "Driver Private structure = 0x%p", (void *)dev
);
351 /* now register with GLDv3 */
352 ret
= mac_register(mac
, (mac_handle_t
*)&dev
->mac_handle
);
353 /* regardless of the status, free mac_register */
356 if (ret
!= DDI_SUCCESS
) {
357 oce_log(dev
, CE_WARN
, MOD_CONFIG
,
358 "MAC registration failed :0x%x", ret
);
363 /* correct link status only after start */
364 dev
->link_status
= LINK_STATE_UNKNOWN
;
365 mac_link_update(dev
->mac_handle
, dev
->link_status
);
367 dev
->attach_state
|= ATTACH_MAC_REG
;
368 dev
->state
|= STATE_INIT
;
370 oce_log(dev
, CE_NOTE
, MOD_CONFIG
, "%s",
373 return (DDI_SUCCESS
);
376 oce_unconfigure(dev
);
377 return (DDI_FAILURE
);
381 oce_detach(dev_info_t
*dip
, ddi_detach_cmd_t cmd
)
387 dev
= ddi_get_driver_private(dip
);
389 return (DDI_FAILURE
);
391 oce_log(dev
, CE_NOTE
, MOD_CONFIG
,
392 "Detaching driver: cmd = 0x%x", cmd
);
396 return (DDI_FAILURE
);
398 return (oce_suspend(dip
));
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 ");
408 dev
->attach_state
&= ~ATTACH_MAC_REG
;
410 /* check if the detach is called with out stopping */
412 if (dev
->state
& STATE_MAC_STARTED
) {
413 dev
->state
&= ~STATE_MAC_STARTED
;
420 * Wait for Packets sent up to be freed
422 for (qid
= 0; qid
< dev
->rx_rings
; qid
++) {
423 pcnt
= oce_rx_pending(dev
, dev
->rq
[qid
], DEFAULT_DRAIN_TIME
);
425 oce_log(dev
, CE_WARN
, MOD_CONFIG
,
426 "%d Pending Buffers Detach failed", pcnt
);
427 return (DDI_FAILURE
);
430 oce_unconfigure(dev
);
432 return (DDI_SUCCESS
);
436 oce_quiesce(dev_info_t
*dip
)
438 int ret
= DDI_SUCCESS
;
439 struct oce_dev
*dev
= ddi_get_driver_private(dip
);
442 return (DDI_FAILURE
);
444 if (dev
->suspended
) {
445 return (DDI_SUCCESS
);
450 ret
= oce_reset_fun(dev
);
456 oce_suspend(dev_info_t
*dip
)
458 struct oce_dev
*dev
= ddi_get_driver_private(dip
);
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
) {
466 oce_unsetup_adapter(dev
);
468 dev
->state
&= ~STATE_MAC_STARTED
;
469 mutex_exit(&dev
->dev_lock
);
470 return (DDI_SUCCESS
);
474 oce_resume(dev_info_t
*dip
)
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
);
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
);
492 ret
= oce_start(dev
);
493 if (ret
!= DDI_SUCCESS
) {
494 mutex_exit(&dev
->dev_lock
);
495 return (DDI_FAILURE
);
498 dev
->suspended
= B_FALSE
;
499 dev
->state
|= STATE_MAC_STARTED
;
500 mutex_exit(&dev
->dev_lock
);
505 oce_init_locks(struct oce_dev
*dev
)
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 */
515 oce_destroy_locks(struct oce_dev
*dev
)
517 mutex_destroy(&dev
->dev_lock
);
518 mutex_destroy(&dev
->bmbx_lock
);
519 } /* oce_destroy_locks */
522 oce_unconfigure(struct oce_dev
*dev
)
524 uint32_t state
= dev
->attach_state
;
526 if (state
& ATTACH_MAC_REG
) {
527 (void) mac_unregister(dev
->mac_handle
);
529 if (state
& ATTACH_STAT_INIT
) {
532 if (state
& ATTACH_SETUP_ADAP
) {
533 oce_unsetup_adapter(dev
);
535 if (state
& ATTACH_SETUP_TXRX
) {
538 if (state
& ATTACH_HW_INIT
) {
541 if (state
& ATTACH_LOCK_INIT
) {
542 oce_destroy_locks(dev
);
544 if (state
& ATTACH_SETUP_INTR
) {
545 (void) oce_teardown_intr(dev
);
547 if (state
& ATTACH_PCI_INIT
) {
550 if (state
& ATTACH_PCI_CFG
) {
551 pci_config_teardown(&dev
->pci_cfg_handle
);
553 if (state
& ATTACH_FM_INIT
) {
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
));
561 } /* oce_unconfigure */
564 oce_get_params(struct oce_dev
*dev
)
570 * Allowed values for the driver parameters. If all values in a range
571 * is allowed, the the array has only one value.
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
,
579 uint32_t rx_bcl_values
[] = {SIZE_128
, SIZE_256
, SIZE_512
, SIZE_1K
,
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
,
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
};
593 dev
->rx_ring_size
= OCE_DEFAULT_RX_RING_SIZE
;
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
);
599 dev
->mtu
= oce_get_prop(dev
, (char *)mtu_prop_name
, OCE_MIN_MTU
,
600 OCE_MAX_MTU
, OCE_MIN_MTU
, mtu_values
);
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
);
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
);
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
);
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
);
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
);
617 dev
->lso_capable
= oce_get_prop(dev
, (char *)lso_capable_name
, 0,
618 1, 1, lso_capable_values
);
620 dev
->fm_caps
= oce_get_prop(dev
, (char *)fm_cap_name
,
621 DDI_FM_NOT_CAPABLE
, OCE_FM_CAPABILITY
, OCE_FM_CAPABILITY
,
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
);
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
);
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
);
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
);
637 log_level
= oce_get_prop(dev
, (char *)log_level_name
, 0,
638 OCE_MAX_LOG_SETTINGS
, OCE_DEFAULT_LOG_SETTINGS
, log_level_values
);
640 severity
= (uint16_t)(log_level
& 0xffff);
641 mod_mask
= (uint16_t)(log_level
>> 16);
642 if (mod_mask
> MOD_ISR
) {
645 if (severity
> CE_IGNORE
) {
649 dev
->mod_mask
= mod_mask
;
650 dev
->severity
= severity
;
651 } /* oce_get_params */
654 oce_get_prop(struct oce_dev
*dev
, char *propname
, int minval
, int maxval
,
655 int defval
, uint32_t *values
)
660 value
= ddi_prop_get_int(DDI_DEV_T_ANY
, dev
->dip
,
661 DDI_PROP_DONTPASS
, propname
, defval
);
669 while (values
[i
] != 0xdeadface) {
670 if (values
[i
] == value
) {
676 if ((i
!= 0) && (values
[i
] == 0xdeadface)) {