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]
23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
28 * Copyright (c) 2002-2005 Neterion, Inc.
33 * Description: Xge main Solaris specific initialization & routines
34 * for upper layer driver
39 static int xge_attach(dev_info_t
*dev_info
, ddi_attach_cmd_t cmd
);
40 static int xge_detach(dev_info_t
*dev_info
, ddi_detach_cmd_t cmd
);
41 static int xge_quiesce(dev_info_t
*dev_info
);
43 DDI_DEFINE_STREAM_OPS(xge_ops
, nulldev
, nulldev
, xge_attach
, xge_detach
,
44 nodev
, NULL
, D_MP
, NULL
, xge_quiesce
);
46 /* Standard Module linkage initialization for a Streams driver */
47 extern struct mod_ops mod_driverops
;
49 static struct modldrv modldrv
= {
50 &mod_driverops
, /* Type of module. This one is a driver */
51 XGELL_DESC
, /* short description */
52 &xge_ops
/* driver specific ops */
55 static struct modlinkage modlinkage
= {
56 MODREV_1
, {(void *)&modldrv
, NULL
}
59 /* Xge device attributes */
60 ddi_device_acc_attr_t xge_dev_attr
= {
65 ddi_device_acc_attr_t
*p_xge_dev_attr
= &xge_dev_attr
;
68 * xgell_callback_crit_err
70 * This function called by HAL on Serious Error event. XGE_HAL_EVENT_SERR.
71 * Upper layer must analyze it based on %type.
74 xge_callback_crit_err(void *userdata
, xge_hal_event_e type
, u64 serr_data
)
76 (void) xgell_onerr_reset(userdata
);
81 * This function called by HAL on XPAK alarms. Upper layer must log the msg
82 * based on the xpak alarm type
85 xge_xpak_alarm_log(void *userdata
, xge_hal_xpak_alarm_type_e type
)
88 case XGE_HAL_XPAK_ALARM_EXCESS_TEMP
:
89 xge_debug_osdep(XGE_ERR
, "%s", "Take Xframe NIC out of "
90 "service. Excessive temperatures may result in "
91 "premature transceiver failure \n");
94 case XGE_HAL_XPAK_ALARM_EXCESS_BIAS_CURRENT
:
95 xge_debug_osdep(XGE_ERR
, "%s", "Take Xframe NIC out of "
96 "service Excessive bias currents may indicate "
97 "imminent laser diode failure \n");
100 case XGE_HAL_XPAK_ALARM_EXCESS_LASER_OUTPUT
:
101 xge_debug_osdep(XGE_ERR
, "%s", "Take Xframe NIC out of "
102 "service Excessive laser output power may saturate "
103 "far-end receiver\n");
107 xge_debug_osdep(XGE_ERR
, "%s", "Undefined Xpak Alarm");
114 * xge_driver_init_hal
116 * To initialize HAL portion of driver.
118 static xge_hal_status_e
119 xge_driver_init_hal(void)
121 static xge_hal_driver_config_t driver_config
;
122 xge_hal_uld_cbs_t uld_callbacks
;
124 driver_config
.queue_size_initial
= 1;
125 driver_config
.queue_size_max
= 4;
127 uld_callbacks
.link_up
= xgell_callback_link_up
;
128 uld_callbacks
.link_down
= xgell_callback_link_down
;
129 uld_callbacks
.crit_err
= xge_callback_crit_err
;
130 uld_callbacks
.event
= NULL
;
131 uld_callbacks
.event_queued
= NULL
;
132 uld_callbacks
.before_device_poll
= NULL
;
133 uld_callbacks
.after_device_poll
= NULL
;
134 uld_callbacks
.sched_timer
= NULL
;
135 uld_callbacks
.xpak_alarm_log
= xge_xpak_alarm_log
;
137 return (xge_hal_driver_initialize(&driver_config
, &uld_callbacks
));
144 * Solaris standard _init function for a device driver
150 xge_hal_status_e status
;
152 status
= xge_driver_init_hal();
153 if (status
!= XGE_HAL_OK
) {
154 xge_debug_osdep(XGE_ERR
, "can't initialize the driver (%d)",
159 xge_hal_driver_debug_module_mask_set(0xffffffff);
160 xge_hal_driver_debug_level_set(XGE_TRACE
);
162 mac_init_ops(&xge_ops
, "xge");
163 if ((ret
= mod_install(&modlinkage
)) != 0) {
164 xge_hal_driver_terminate();
165 mac_fini_ops(&xge_ops
);
166 xge_debug_osdep(XGE_ERR
, "%s",
167 "Unable to install the driver");
177 * Solaris standard _fini function for device driver
184 ret
= mod_remove(&modlinkage
);
186 xge_hal_driver_terminate();
187 mac_fini_ops(&xge_ops
);
196 * Solaris standard _info function for device driver
199 _info(struct modinfo
*pModinfo
)
201 return (mod_info(&modlinkage
, pModinfo
));
206 * @arg: pointer to device private strucutre(hldev)
208 * This is the ISR scheduled by the OS to indicate to the
209 * driver that the receive/transmit operation is completed.
213 xge_isr(caddr_t arg0
, caddr_t arg1
)
215 xge_hal_status_e status
;
216 xge_hal_device_t
*hldev
= (xge_hal_device_t
*)arg0
;
217 xgelldev_t
*lldev
= xge_hal_device_private(hldev
);
219 if (!lldev
->is_initialized
) {
220 return (DDI_INTR_UNCLAIMED
);
223 status
= xge_hal_device_handle_irq(hldev
);
225 return ((status
== XGE_HAL_ERR_WRONG_IRQ
) ?
226 DDI_INTR_UNCLAIMED
: DDI_INTR_CLAIMED
);
230 * Interrupt handler for transmit when MSI-X interrupt mechasnism is used
234 xge_fifo_msix_isr(caddr_t arg0
, caddr_t arg1
)
237 xge_hal_channel_t
*channel
= (xge_hal_channel_t
*)arg0
;
238 xgelldev_t
*lldev
= xge_hal_device_private(channel
->devh
);
240 if (!lldev
->is_initialized
) {
241 return (DDI_INTR_UNCLAIMED
);
243 (void) xge_hal_device_poll_tx_channel(channel
, &got_tx
);
245 return (DDI_INTR_CLAIMED
);
249 * Interrupt handler for receive when MSI-X interrupt mechasnism is used
253 xge_ring_msix_isr(caddr_t arg0
, caddr_t arg1
)
256 xge_hal_channel_t
*channel
= (xge_hal_channel_t
*)arg0
;
257 xgelldev_t
*lldev
= xge_hal_device_private(channel
->devh
);
259 if (!lldev
->is_initialized
) {
260 return (DDI_INTR_UNCLAIMED
);
262 (void) xge_hal_device_poll_rx_channel(channel
, &got_rx
);
264 return (DDI_INTR_CLAIMED
);
268 * Configure single ring
271 xge_ring_config(dev_info_t
*dev_info
, xge_hal_device_config_t
*device_config
,
276 (void) xge_os_snprintf(msg
, MSG_SIZE
, "ring%d_configured", index
);
277 device_config
->ring
.queue
[index
].configured
=
278 ddi_prop_get_int(DDI_DEV_T_ANY
, dev_info
, DDI_PROP_DONTPASS
,
279 msg
, index
< XGELL_RX_RING_NUM_MAX
? 1 : 0);
281 /* no point to configure it further if unconfigured */
282 if (!device_config
->ring
.queue
[index
].configured
)
286 (void) xge_os_snprintf(msg
, MSG_SIZE
, "ring%d_max", index
);
287 device_config
->ring
.queue
[index
].max
=
288 ddi_prop_get_int(DDI_DEV_T_ANY
,
289 dev_info
, DDI_PROP_DONTPASS
, msg
,
290 XGE_HAL_DEFAULT_USE_HARDCODE
);
292 (void) xge_os_snprintf(msg
, MSG_SIZE
, "ring%d_initial", index
);
293 device_config
->ring
.queue
[index
].initial
=
294 ddi_prop_get_int(DDI_DEV_T_ANY
,
295 dev_info
, DDI_PROP_DONTPASS
, msg
,
296 XGE_HAL_DEFAULT_USE_HARDCODE
);
298 if (device_config
->ring
.queue
[index
].initial
==
299 XGE_HAL_DEFAULT_USE_HARDCODE
) {
300 device_config
->ring
.queue
[index
].initial
=
301 device_config
->ring
.queue
[index
].max
=
302 XGE_HAL_DEFAULT_RING_QUEUE_BLOCKS
;
305 (void) xge_os_snprintf(msg
, MSG_SIZE
, "ring%d_buffer_mode", index
);
306 device_config
->ring
.queue
[index
].buffer_mode
=
307 ddi_prop_get_int(DDI_DEV_T_ANY
,
308 dev_info
, DDI_PROP_DONTPASS
, msg
,
309 XGE_HAL_RING_QUEUE_BUFFER_MODE_DEFAULT
);
311 (void) xge_os_snprintf(msg
, MSG_SIZE
, "ring%d_dram_size_mb", index
);
312 device_config
->ring
.queue
[index
].dram_size_mb
=
313 ddi_prop_get_int(DDI_DEV_T_ANY
,
314 dev_info
, DDI_PROP_DONTPASS
, msg
,
315 XGE_HAL_DEFAULT_USE_HARDCODE
);
317 (void) xge_os_snprintf(msg
, MSG_SIZE
,
318 "ring%d_backoff_interval_us", index
);
319 device_config
->ring
.queue
[index
].backoff_interval_us
=
320 ddi_prop_get_int(DDI_DEV_T_ANY
,
321 dev_info
, DDI_PROP_DONTPASS
, msg
,
322 XGE_HAL_DEFAULT_BACKOFF_INTERVAL_US
);
324 (void) xge_os_snprintf(msg
, MSG_SIZE
, "ring%d_max_frm_len", index
);
325 device_config
->ring
.queue
[index
].max_frm_len
=
326 ddi_prop_get_int(DDI_DEV_T_ANY
,
327 dev_info
, DDI_PROP_DONTPASS
, msg
,
328 XGE_HAL_RING_USE_MTU
);
331 (void) xge_os_snprintf(msg
, MSG_SIZE
, "ring%d_priority", index
);
332 device_config
->ring
.queue
[index
].priority
=
333 ddi_prop_get_int(DDI_DEV_T_ANY
,
334 dev_info
, DDI_PROP_DONTPASS
, msg
,
335 XGE_HAL_DEFAULT_RING_PRIORITY
);
337 (void) xge_os_snprintf(msg
, MSG_SIZE
, "ring%d_urange_a", index
);
338 device_config
->ring
.queue
[index
].rti
.urange_a
=
339 ddi_prop_get_int(DDI_DEV_T_ANY
,
340 dev_info
, DDI_PROP_DONTPASS
, msg
,
341 XGE_HAL_DEFAULT_RX_URANGE_A
);
343 (void) xge_os_snprintf(msg
, MSG_SIZE
, "ring%d_ufc_a", index
);
344 device_config
->ring
.queue
[index
].rti
.ufc_a
=
345 ddi_prop_get_int(DDI_DEV_T_ANY
,
346 dev_info
, DDI_PROP_DONTPASS
, msg
,
347 XGE_HAL_DEFAULT_RX_UFC_A
);
349 (void) xge_os_snprintf(msg
, MSG_SIZE
, "ring%d_urange_b", index
);
350 device_config
->ring
.queue
[index
].rti
.urange_b
=
351 ddi_prop_get_int(DDI_DEV_T_ANY
,
352 dev_info
, DDI_PROP_DONTPASS
, msg
,
353 XGE_HAL_DEFAULT_RX_URANGE_B
);
355 (void) xge_os_snprintf(msg
, MSG_SIZE
, "ring%d_ufc_b", index
);
356 device_config
->ring
.queue
[index
].rti
.ufc_b
=
357 ddi_prop_get_int(DDI_DEV_T_ANY
,
358 dev_info
, DDI_PROP_DONTPASS
, msg
,
359 device_config
->mtu
> XGE_HAL_DEFAULT_MTU
?
360 XGE_HAL_DEFAULT_RX_UFC_B_J
:
361 XGE_HAL_DEFAULT_RX_UFC_B_N
);
363 (void) xge_os_snprintf(msg
, MSG_SIZE
, "ring%d_urange_c", index
);
364 device_config
->ring
.queue
[index
].rti
.urange_c
=
365 ddi_prop_get_int(DDI_DEV_T_ANY
,
366 dev_info
, DDI_PROP_DONTPASS
, msg
,
367 XGE_HAL_DEFAULT_RX_URANGE_C
);
369 (void) xge_os_snprintf(msg
, MSG_SIZE
, "ring%d_ufc_c", index
);
370 device_config
->ring
.queue
[index
].rti
.ufc_c
=
371 ddi_prop_get_int(DDI_DEV_T_ANY
,
372 dev_info
, DDI_PROP_DONTPASS
, msg
,
373 device_config
->mtu
> XGE_HAL_DEFAULT_MTU
?
374 XGE_HAL_DEFAULT_RX_UFC_C_J
:
375 XGE_HAL_DEFAULT_RX_UFC_C_N
);
377 (void) xge_os_snprintf(msg
, MSG_SIZE
, "ring%d_ufc_d", index
);
378 device_config
->ring
.queue
[index
].rti
.ufc_d
=
379 ddi_prop_get_int(DDI_DEV_T_ANY
,
380 dev_info
, DDI_PROP_DONTPASS
, msg
,
381 XGE_HAL_DEFAULT_RX_UFC_D
);
383 (void) xge_os_snprintf(msg
, MSG_SIZE
, "ring%d_timer_val", index
);
384 device_config
->ring
.queue
[index
].rti
.timer_val_us
=
385 ddi_prop_get_int(DDI_DEV_T_ANY
,
386 dev_info
, DDI_PROP_DONTPASS
, msg
,
387 XGE_HAL_DEFAULT_RX_TIMER_VAL
);
389 (void) xge_os_snprintf(msg
, MSG_SIZE
, "ring%d_timer_ac_en", index
);
390 device_config
->ring
.queue
[index
].rti
.timer_ac_en
=
391 ddi_prop_get_int(DDI_DEV_T_ANY
,
392 dev_info
, DDI_PROP_DONTPASS
, msg
,
393 XGE_HAL_DEFAULT_RX_TIMER_AC_EN
);
395 (void) xge_os_snprintf(msg
, MSG_SIZE
, "ring%d_indicate_max_pkts",
397 device_config
->ring
.queue
[index
].indicate_max_pkts
=
398 ddi_prop_get_int(DDI_DEV_T_ANY
,
399 dev_info
, DDI_PROP_DONTPASS
, msg
,
400 (device_config
->bimodal_interrupts
?
401 XGE_HAL_DEFAULT_INDICATE_MAX_PKTS_B
:
402 XGE_HAL_DEFAULT_INDICATE_MAX_PKTS_N
));
405 * Enable RTH steering if needed HERE!!!!
407 if (device_config
->rth_en
== XGE_HAL_RTH_ENABLE
)
408 device_config
->ring
.queue
[index
].rth_en
= 1;
412 * Configure single fifo
415 xge_fifo_config(dev_info_t
*dev_info
, xge_hal_device_config_t
*device_config
,
420 (void) xge_os_snprintf(msg
, MSG_SIZE
, "fifo%d_configured", index
);
421 device_config
->fifo
.queue
[index
].configured
=
422 ddi_prop_get_int(DDI_DEV_T_ANY
, dev_info
, DDI_PROP_DONTPASS
,
423 msg
, index
< XGELL_TX_RING_NUM_MAX
? 1 : 0);
425 /* no point to configure it further */
426 if (!device_config
->fifo
.queue
[index
].configured
)
430 (void) xge_os_snprintf(msg
, MSG_SIZE
, "fifo%d_max", index
);
431 device_config
->fifo
.queue
[index
].max
= ddi_prop_get_int(DDI_DEV_T_ANY
,
432 dev_info
, DDI_PROP_DONTPASS
, msg
,
433 XGE_HAL_DEFAULT_USE_HARDCODE
);
435 (void) xge_os_snprintf(msg
, MSG_SIZE
, "fifo%d_initial", index
);
436 device_config
->fifo
.queue
[index
].initial
=
437 ddi_prop_get_int(DDI_DEV_T_ANY
, dev_info
, DDI_PROP_DONTPASS
, msg
,
438 XGE_HAL_DEFAULT_USE_HARDCODE
);
441 if (device_config
->fifo
.queue
[index
].initial
==
442 XGE_HAL_DEFAULT_USE_HARDCODE
) {
443 if (device_config
->mtu
> XGE_HAL_DEFAULT_MTU
) {
444 device_config
->fifo
.queue
[index
].initial
=
445 device_config
->fifo
.queue
[index
].max
=
446 XGE_HAL_DEFAULT_FIFO_QUEUE_LENGTH_J
;
448 device_config
->fifo
.queue
[index
].initial
=
449 device_config
->fifo
.queue
[index
].max
=
450 XGE_HAL_DEFAULT_FIFO_QUEUE_LENGTH_N
;
454 if (device_config
->fifo
.queue
[index
].initial
==
455 XGE_HAL_DEFAULT_USE_HARDCODE
) {
456 device_config
->fifo
.queue
[index
].max
=
457 device_config
->fifo
.queue
[index
].initial
=
458 XGE_HAL_DEFAULT_FIFO_QUEUE_LENGTH_A
;
462 (void) xge_os_snprintf(msg
, MSG_SIZE
, "fifo%d_intr", index
);
463 device_config
->fifo
.queue
[index
].intr
= ddi_prop_get_int(DDI_DEV_T_ANY
,
464 dev_info
, DDI_PROP_DONTPASS
, msg
,
465 XGE_HAL_DEFAULT_FIFO_QUEUE_INTR
);
468 * TTI 0 configuration
470 (void) xge_os_snprintf(msg
, MSG_SIZE
, "fifo%d_tti_enable", index
);
471 device_config
->fifo
.queue
[index
].tti
[index
].enabled
= ddi_prop_get_int(
472 DDI_DEV_T_ANY
, dev_info
, DDI_PROP_DONTPASS
, msg
, 1);
474 (void) xge_os_snprintf(msg
, MSG_SIZE
, "fifo%d_tti_urange_a", index
);
475 device_config
->fifo
.queue
[index
].tti
[index
].urange_a
= ddi_prop_get_int(
476 DDI_DEV_T_ANY
, dev_info
, DDI_PROP_DONTPASS
, msg
,
477 XGE_HAL_DEFAULT_TX_URANGE_A
);
479 (void) xge_os_snprintf(msg
, MSG_SIZE
, "fifo%d_tti_ufc_a", index
);
480 device_config
->fifo
.queue
[index
].tti
[index
].ufc_a
= ddi_prop_get_int(
481 DDI_DEV_T_ANY
, dev_info
, DDI_PROP_DONTPASS
, msg
,
482 XGE_HAL_DEFAULT_TX_UFC_A
);
484 (void) xge_os_snprintf(msg
, MSG_SIZE
, "fifo%d_tti_urange_b", index
);
485 device_config
->fifo
.queue
[index
].tti
[index
].urange_b
= ddi_prop_get_int(
486 DDI_DEV_T_ANY
, dev_info
, DDI_PROP_DONTPASS
, msg
,
487 XGE_HAL_DEFAULT_TX_URANGE_B
);
489 (void) xge_os_snprintf(msg
, MSG_SIZE
, "fifo%d_tti_ufc_b", index
);
490 device_config
->fifo
.queue
[index
].tti
[index
].ufc_b
= ddi_prop_get_int(
491 DDI_DEV_T_ANY
, dev_info
, DDI_PROP_DONTPASS
, msg
,
492 XGE_HAL_DEFAULT_TX_UFC_B
);
494 (void) xge_os_snprintf(msg
, MSG_SIZE
, "fifo%d_tti_urange_c", index
);
495 device_config
->fifo
.queue
[index
].tti
[index
].urange_c
= ddi_prop_get_int(
496 DDI_DEV_T_ANY
, dev_info
, DDI_PROP_DONTPASS
, msg
,
497 XGE_HAL_DEFAULT_TX_URANGE_C
);
499 (void) xge_os_snprintf(msg
, MSG_SIZE
, "fifo%d_tti_ufc_c", index
);
500 device_config
->fifo
.queue
[index
].tti
[index
].ufc_c
= ddi_prop_get_int(
501 DDI_DEV_T_ANY
, dev_info
, DDI_PROP_DONTPASS
, msg
,
502 XGE_HAL_DEFAULT_TX_UFC_C
);
504 (void) xge_os_snprintf(msg
, MSG_SIZE
, "fifo%d_tti_ufc_d", index
);
505 device_config
->fifo
.queue
[index
].tti
[index
].ufc_d
= ddi_prop_get_int(
506 DDI_DEV_T_ANY
, dev_info
, DDI_PROP_DONTPASS
, msg
,
507 XGE_HAL_DEFAULT_TX_UFC_D
);
509 (void) xge_os_snprintf(msg
, MSG_SIZE
, "fifo%d_timer_ac_en", index
);
510 device_config
->fifo
.queue
[index
].tti
[index
].timer_ac_en
=
511 ddi_prop_get_int(DDI_DEV_T_ANY
, dev_info
, DDI_PROP_DONTPASS
, msg
,
512 XGE_HAL_DEFAULT_TX_TIMER_AC_EN
);
514 (void) xge_os_snprintf(msg
, MSG_SIZE
, "fifo%d_tti_timer_val", index
);
515 device_config
->fifo
.queue
[index
].tti
[index
].timer_val_us
=
516 ddi_prop_get_int(DDI_DEV_T_ANY
, dev_info
, DDI_PROP_DONTPASS
, msg
,
517 XGE_HAL_DEFAULT_TX_TIMER_VAL
);
519 (void) xge_os_snprintf(msg
, MSG_SIZE
, "fifo%d_tti_timer_ci_en", index
);
520 device_config
->fifo
.queue
[index
].tti
[index
].timer_ci_en
=
521 ddi_prop_get_int(DDI_DEV_T_ANY
, dev_info
, DDI_PROP_DONTPASS
, msg
,
522 XGE_HAL_DEFAULT_TX_TIMER_CI_EN
);
526 * xge_configuration_init
527 * @device_config: pointer to xge_hal_device_config_t
529 * This function will lookup properties from .conf file to init
530 * the configuration data structure. If a property is not in .conf
531 * file, the default value should be set.
534 xge_configuration_init(dev_info_t
*dev_info
,
535 xge_hal_device_config_t
*device_config
, xgell_config_t
*xgell_config
)
537 int i
, rings_configured
= 0, fifos_configured
= 0;
540 * Initialize link layer configuration first
542 xgell_config
->rx_dma_lowat
= ddi_prop_get_int(DDI_DEV_T_ANY
, dev_info
,
543 DDI_PROP_DONTPASS
, "rx_dma_lowat", XGELL_RX_DMA_LOWAT
);
544 xgell_config
->rx_pkt_burst
= ddi_prop_get_int(DDI_DEV_T_ANY
,
545 dev_info
, DDI_PROP_DONTPASS
, "rx_pkt_burst", XGELL_RX_PKT_BURST
);
546 xgell_config
->tx_dma_lowat
= ddi_prop_get_int(DDI_DEV_T_ANY
, dev_info
,
547 DDI_PROP_DONTPASS
, "tx_dma_lowat", XGELL_TX_DMA_LOWAT
);
548 xgell_config
->lso_enable
= ddi_prop_get_int(DDI_DEV_T_ANY
, dev_info
,
549 DDI_PROP_DONTPASS
, "lso_enable", XGELL_CONF_ENABLE_BY_DEFAULT
);
550 xgell_config
->msix_enable
= ddi_prop_get_int(DDI_DEV_T_ANY
, dev_info
,
551 DDI_PROP_DONTPASS
, "msix_enable", XGELL_CONF_ENABLE_BY_DEFAULT
);
553 xgell_config
->grouping
= ddi_prop_get_int(DDI_DEV_T_ANY
, dev_info
,
554 DDI_PROP_DONTPASS
, "grouping", XGELL_CONF_GROUP_POLICY_DEFAULT
);
556 switch (xgell_config
->grouping
) {
557 case XGELL_CONF_GROUP_POLICY_VIRT
:
559 * Enable layer 2 steering for better virtualization
561 device_config
->rth_en
= XGE_HAL_RTH_DISABLE
;
562 device_config
->rts_mac_en
= XGE_HAL_RTS_MAC_ENABLE
;
564 case XGELL_CONF_GROUP_POLICY_PERF
:
566 * Configure layer 4 RTH to hashing inbound traffic
568 device_config
->rth_en
= XGE_HAL_RTH_ENABLE
;
569 device_config
->rth_bucket_size
= XGE_HAL_MAX_RTH_BUCKET_SIZE
;
570 device_config
->rth_spdm_en
= XGE_HAL_RTH_SPDM_DISABLE
;
571 device_config
->rth_spdm_use_l4
= XGE_HAL_RTH_SPDM_USE_L4
;
573 device_config
->rts_mac_en
= XGE_HAL_RTS_MAC_DISABLE
;
575 case XGELL_CONF_GROUP_POLICY_BASIC
:
578 * Disable both RTS and RTH for single ring configuration
580 device_config
->rth_en
= XGE_HAL_RTH_DISABLE
;
581 device_config
->rts_mac_en
= XGE_HAL_RTS_MAC_DISABLE
;
586 * Initialize common properties
588 device_config
->mtu
= ddi_prop_get_int(DDI_DEV_T_ANY
,
589 dev_info
, DDI_PROP_DONTPASS
, "default_mtu",
590 XGE_HAL_DEFAULT_INITIAL_MTU
);
591 device_config
->isr_polling_cnt
= ddi_prop_get_int(DDI_DEV_T_ANY
,
592 dev_info
, DDI_PROP_DONTPASS
, "isr_polling_cnt",
593 XGE_HAL_DEFAULT_ISR_POLLING_CNT
);
594 device_config
->latency_timer
= ddi_prop_get_int(DDI_DEV_T_ANY
,
595 dev_info
, DDI_PROP_DONTPASS
, "latency_timer",
596 XGE_HAL_DEFAULT_LATENCY_TIMER
);
597 device_config
->max_splits_trans
= ddi_prop_get_int(DDI_DEV_T_ANY
,
598 dev_info
, DDI_PROP_DONTPASS
, "max_splits_trans",
599 XGE_HAL_DEFAULT_SPLIT_TRANSACTION
);
600 device_config
->mmrb_count
= ddi_prop_get_int(DDI_DEV_T_ANY
,
601 dev_info
, DDI_PROP_DONTPASS
, "mmrb_count",
602 XGE_HAL_DEFAULT_MMRB_COUNT
);
603 device_config
->shared_splits
= ddi_prop_get_int(DDI_DEV_T_ANY
,
604 dev_info
, DDI_PROP_DONTPASS
, "shared_splits",
605 XGE_HAL_DEFAULT_SHARED_SPLITS
);
606 device_config
->stats_refresh_time_sec
= ddi_prop_get_int(DDI_DEV_T_ANY
,
607 dev_info
, DDI_PROP_DONTPASS
, "stats_refresh_time",
608 XGE_HAL_DEFAULT_STATS_REFRESH_TIME
);
609 device_config
->device_poll_millis
= ddi_prop_get_int(DDI_DEV_T_ANY
,
610 dev_info
, DDI_PROP_DONTPASS
, "device_poll_millis",
611 XGE_HAL_DEFAULT_DEVICE_POLL_MILLIS
);
612 device_config
->pci_freq_mherz
= ddi_prop_get_int(DDI_DEV_T_ANY
,
613 dev_info
, DDI_PROP_DONTPASS
, "pci_freq_mherz",
614 XGE_HAL_DEFAULT_USE_HARDCODE
);
617 * Initialize ring properties
619 device_config
->ring
.memblock_size
= ddi_prop_get_int(DDI_DEV_T_ANY
,
620 dev_info
, DDI_PROP_DONTPASS
, "ring_memblock_size",
621 XGE_HAL_DEFAULT_RING_MEMBLOCK_SIZE
);
622 device_config
->ring
.strip_vlan_tag
= XGE_HAL_RING_DONOT_STRIP_VLAN_TAG
;
625 * Bimodal Interrupts - TTI 56 configuration
627 device_config
->bimodal_interrupts
= ddi_prop_get_int(
628 DDI_DEV_T_ANY
, dev_info
, DDI_PROP_DONTPASS
, "bimodal_interrupts",
629 XGE_HAL_DEFAULT_BIMODAL_INTERRUPTS
);
630 device_config
->bimodal_timer_lo_us
= ddi_prop_get_int(
631 DDI_DEV_T_ANY
, dev_info
, DDI_PROP_DONTPASS
, "bimodal_timer_lo_us",
632 XGE_HAL_DEFAULT_BIMODAL_TIMER_LO_US
);
633 device_config
->bimodal_timer_hi_us
= ddi_prop_get_int(
634 DDI_DEV_T_ANY
, dev_info
, DDI_PROP_DONTPASS
, "bimodal_timer_hi_us",
635 XGE_HAL_DEFAULT_BIMODAL_TIMER_HI_US
);
638 * Go through all possibly configured rings. Each ring could be
639 * configured individually. To enable/disable specific ring, just
640 * set ring->configured = [1|0].
642 * By default *all* rings enabled.
644 for (i
= 0; i
< XGE_HAL_MAX_RING_NUM
; i
++) {
645 xge_ring_config(dev_info
, device_config
, i
);
646 if (device_config
->ring
.queue
[i
].configured
)
651 * Initialize mac properties
653 device_config
->mac
.tmac_util_period
= ddi_prop_get_int(DDI_DEV_T_ANY
,
654 dev_info
, DDI_PROP_DONTPASS
, "mac_tmac_util_period",
655 XGE_HAL_DEFAULT_TMAC_UTIL_PERIOD
);
656 device_config
->mac
.rmac_util_period
= ddi_prop_get_int(DDI_DEV_T_ANY
,
657 dev_info
, DDI_PROP_DONTPASS
, "mac_rmac_util_period",
658 XGE_HAL_DEFAULT_RMAC_UTIL_PERIOD
);
659 device_config
->mac
.rmac_bcast_en
= ddi_prop_get_int(DDI_DEV_T_ANY
,
660 dev_info
, DDI_PROP_DONTPASS
, "mac_rmac_bcast_en",
661 1); /* HAL never provide a good named macro */
662 device_config
->mac
.rmac_pause_gen_en
= ddi_prop_get_int(DDI_DEV_T_ANY
,
663 dev_info
, DDI_PROP_DONTPASS
, "rmac_pause_gen_en",
664 XGE_HAL_DEFAULT_RMAC_PAUSE_GEN_DIS
);
665 device_config
->mac
.rmac_pause_rcv_en
= ddi_prop_get_int(DDI_DEV_T_ANY
,
666 dev_info
, DDI_PROP_DONTPASS
, "rmac_pause_rcv_en",
667 XGE_HAL_DEFAULT_RMAC_PAUSE_RCV_DIS
);
668 device_config
->mac
.rmac_pause_time
= ddi_prop_get_int(DDI_DEV_T_ANY
,
669 dev_info
, DDI_PROP_DONTPASS
, "mac_rmac_pause_time",
670 XGE_HAL_DEFAULT_RMAC_HIGH_PTIME
);
671 device_config
->mac
.mc_pause_threshold_q0q3
=
672 ddi_prop_get_int(DDI_DEV_T_ANY
,
673 dev_info
, DDI_PROP_DONTPASS
, "mac_mc_pause_threshold_q0q3",
674 XGE_HAL_DEFAULT_MC_PAUSE_THRESHOLD_Q0Q3
);
675 device_config
->mac
.mc_pause_threshold_q4q7
=
676 ddi_prop_get_int(DDI_DEV_T_ANY
,
677 dev_info
, DDI_PROP_DONTPASS
, "mac_mc_pause_threshold_q4q7",
678 XGE_HAL_DEFAULT_MC_PAUSE_THRESHOLD_Q4Q7
);
681 * Initialize fifo properties
683 device_config
->fifo
.max_frags
= ddi_prop_get_int(DDI_DEV_T_ANY
,
684 dev_info
, DDI_PROP_DONTPASS
, "fifo_max_frags",
685 XGE_HAL_DEFAULT_FIFO_FRAGS
);
686 device_config
->fifo
.reserve_threshold
= ddi_prop_get_int(DDI_DEV_T_ANY
,
687 dev_info
, DDI_PROP_DONTPASS
, "fifo_reserve_threshold",
688 XGE_HAL_DEFAULT_FIFO_RESERVE_THRESHOLD
);
689 device_config
->fifo
.memblock_size
= ddi_prop_get_int(DDI_DEV_T_ANY
,
690 dev_info
, DDI_PROP_DONTPASS
, "fifo_memblock_size",
691 XGE_HAL_DEFAULT_FIFO_MEMBLOCK_SIZE
);
692 #ifdef XGE_HAL_ALIGN_XMIT
693 device_config
->fifo
.alignment_size
= ddi_prop_get_int(DDI_DEV_T_ANY
,
694 dev_info
, DDI_PROP_DONTPASS
, "fifo_copied_frag_size",
695 XGE_HAL_DEFAULT_FIFO_ALIGNMENT_SIZE
);
696 device_config
->fifo
.max_aligned_frags
= ddi_prop_get_int(DDI_DEV_T_ANY
,
697 dev_info
, DDI_PROP_DONTPASS
, "fifo_copied_max_frags",
698 XGE_HAL_DEFAULT_FIFO_MAX_ALIGNED_FRAGS
);
702 * Go through all possibly configured fifos. Each fifo could be
703 * configured individually. To enable/disable specific fifo, just
704 * set fifo->configured = [0|1].
706 * By default *all* fifos enabled.
708 for (i
= 0; i
< XGE_HAL_MAX_FIFO_NUM
; i
++) {
709 xge_fifo_config(dev_info
, device_config
, i
);
710 if (device_config
->fifo
.queue
[i
].configured
)
715 * Initialize errors dumping
717 device_config
->dump_on_serr
= ddi_prop_get_int(DDI_DEV_T_ANY
,
718 dev_info
, DDI_PROP_DONTPASS
, "dump_on_serr",
720 device_config
->dump_on_serr
= ddi_prop_get_int(DDI_DEV_T_ANY
,
721 dev_info
, DDI_PROP_DONTPASS
, "dump_on_eccerr",
723 device_config
->dump_on_serr
= ddi_prop_get_int(DDI_DEV_T_ANY
,
724 dev_info
, DDI_PROP_DONTPASS
, "dump_on_parityerr",
730 device_config
->lro_sg_size
= ddi_prop_get_int(DDI_DEV_T_ANY
,
731 dev_info
, DDI_PROP_DONTPASS
, "lro_sg_size",
732 XGE_HAL_DEFAULT_LRO_SG_SIZE
);
733 device_config
->lro_frm_len
= ddi_prop_get_int(DDI_DEV_T_ANY
,
734 dev_info
, DDI_PROP_DONTPASS
, "lro_frm_len",
735 XGE_HAL_DEFAULT_LRO_FRM_LEN
);
738 * Initialize other link layer configuration first
740 xgell_config
->rx_buffer_total
= ddi_prop_get_int(DDI_DEV_T_ANY
,
741 dev_info
, DDI_PROP_DONTPASS
, "rx_buffer_total",
742 device_config
->ring
.queue
[XGELL_RX_RING_MAIN
].initial
*
743 XGELL_RX_BUFFER_TOTAL
);
744 xgell_config
->rx_buffer_total
+= XGELL_RX_BUFFER_RECYCLE_CACHE
;
745 xgell_config
->rx_buffer_post_hiwat
= ddi_prop_get_int(DDI_DEV_T_ANY
,
746 dev_info
, DDI_PROP_DONTPASS
, "rx_buffer_post_hiwat",
747 device_config
->ring
.queue
[XGELL_RX_RING_MAIN
].initial
*
748 XGELL_RX_BUFFER_POST_HIWAT
);
749 xgell_config
->rx_buffer_post_hiwat
+= XGELL_RX_BUFFER_RECYCLE_CACHE
;
755 * Allocate FIXED or MSIX interrupts.
758 xge_alloc_intrs(xgelldev_t
*lldev
)
760 dev_info_t
*dip
= lldev
->dev_info
;
761 int avail
, actual
, count
= 0;
762 int i
, intr_behavior
, ret
;
764 if (lldev
->intr_type
== DDI_INTR_TYPE_MSIX
) {
765 intr_behavior
= DDI_INTR_ALLOC_STRICT
;
766 (void) ddi_prop_create(DDI_DEV_T_NONE
, dip
,
767 DDI_PROP_CANSLEEP
, "#msix-request", NULL
, 0);
769 intr_behavior
= DDI_INTR_ALLOC_NORMAL
;
772 /* Get number of interrupts */
773 ret
= ddi_intr_get_nintrs(dip
, lldev
->intr_type
, &count
);
774 if ((ret
!= DDI_SUCCESS
) || (count
== 0)) {
775 xge_debug_osdep(XGE_ERR
, "ddi_intr_get_nintrs() failed, "
776 "ret: %d, count: %d", ret
, count
);
781 /* Get number of available interrupts */
782 ret
= ddi_intr_get_navail(dip
, lldev
->intr_type
, &avail
);
783 if ((ret
!= DDI_SUCCESS
) || (avail
== 0)) {
784 xge_debug_osdep(XGE_ERR
, "ddi_intr_get_navail() failure, "
785 "ret: %d, avail: %d", ret
, avail
);
790 if (avail
< lldev
->intr_cnt
) {
791 xge_debug_osdep(XGE_ERR
, "%d interrupts wanted while only "
792 "%d available", lldev
->intr_cnt
, avail
);
796 /* Allocate an array of interrupt handles */
797 lldev
->intr_table_size
= lldev
->intr_cnt
* sizeof (ddi_intr_handle_t
);
798 lldev
->intr_table
= kmem_alloc(lldev
->intr_table_size
, KM_SLEEP
);
800 /* Call ddi_intr_alloc() */
801 ret
= ddi_intr_alloc(dip
, lldev
->intr_table
, lldev
->intr_type
, 0,
802 lldev
->intr_cnt
, &actual
, intr_behavior
);
803 if ((ret
!= DDI_SUCCESS
) || (actual
== 0)) {
804 xge_debug_osdep(XGE_ERR
, "ddi_intr_alloc() failed %d", ret
);
808 xge_debug_osdep(XGE_TRACE
, "%s: Requested: %d, Granted: %d",
809 lldev
->intr_type
== DDI_INTR_TYPE_MSIX
? "MSI-X" :
810 "IRQA", count
, actual
);
812 if (lldev
->intr_cnt
!= actual
) {
813 xge_debug_osdep(XGE_ERR
, "Not enough resources granted");
818 * Get priority for first msi, assume remaining are all the same
820 if ((ret
= ddi_intr_get_pri(lldev
->intr_table
[0], &lldev
->intr_pri
)) !=
822 xge_debug_osdep(XGE_ERR
, "ddi_intr_get_pri() failed %d", ret
);
826 return (DDI_SUCCESS
);
829 /* Free already allocated intr */
830 for (i
= 0; i
< actual
; i
++) {
831 (void) ddi_intr_free(lldev
->intr_table
[i
]);
834 kmem_free(lldev
->intr_table
, lldev
->intr_table_size
);
835 lldev
->intr_table
= NULL
;
837 if (lldev
->intr_type
== DDI_INTR_TYPE_MSIX
)
838 (void) ddi_prop_remove(DDI_DEV_T_NONE
, dip
, "#msix-request");
839 return (DDI_FAILURE
);
845 * Free previously allocated interrupts.
848 xge_free_intrs(xgelldev_t
*lldev
)
851 dev_info_t
*dip
= lldev
->dev_info
;
853 /* Free already allocated intr */
854 for (i
= 0; i
< lldev
->intr_cnt
; i
++) {
855 (void) ddi_intr_free(lldev
->intr_table
[i
]);
857 kmem_free(lldev
->intr_table
, lldev
->intr_table_size
);
858 lldev
->intr_table
= NULL
;
860 if (lldev
->intr_type
== DDI_INTR_TYPE_MSIX
)
861 (void) ddi_prop_remove(DDI_DEV_T_NONE
, dip
, "#msix-request");
867 * Register FIXED or MSI interrupts.
870 xge_add_intrs(xgelldev_t
*lldev
)
873 xge_hal_device_t
*hldev
= lldev
->devh
;
874 xge_hal_device_config_t
*hal_conf
= &hldev
->config
;
875 xge_hal_ring_config_t
*ring_conf
= &hal_conf
->ring
;
876 xge_hal_fifo_config_t
*fifo_conf
= &hal_conf
->fifo
;
878 int msix_idx
= 1; /* 0 by default is reserved for Alarms. */
879 xge_hal_channel_t
*assigned
[XGELL_RX_RING_NUM_MAX
+
880 XGELL_TX_RING_NUM_MAX
+ 1];
882 xge_assert(lldev
->intr_table
!= NULL
);
883 switch (lldev
->intr_type
) {
884 case DDI_INTR_TYPE_FIXED
:
885 ret
= ddi_intr_add_handler(lldev
->intr_table
[0],
886 (ddi_intr_handler_t
*)xge_isr
,
888 if (ret
!= DDI_SUCCESS
) {
889 xge_debug_osdep(XGE_ERR
, "ddi_intr_add_handler(FIXED)"
891 return (DDI_FAILURE
);
895 case DDI_INTR_TYPE_MSIX
:
897 xge_list_for_each(item
, &hldev
->free_channels
) {
898 xge_hal_channel_t
*channel
= xge_container_of(item
,
899 xge_hal_channel_t
, item
);
900 i
= channel
->post_qid
;
901 if (channel
->type
== XGE_HAL_CHANNEL_TYPE_FIFO
) {
902 if (fifo_conf
->queue
[i
].configured
) {
903 assigned
[msix_idx
] = channel
;
907 if (ring_conf
->queue
[i
].configured
) {
908 assigned
[msix_idx
] = channel
;
913 for (i
= 0; i
< lldev
->intr_cnt
; i
++) {
914 uint_t (*intr
)(caddr_t
, caddr_t
);
917 /* partition MSIX vectors */
920 intr_arg
= (caddr_t
)hldev
;
921 xge_debug_osdep(XGE_TRACE
,
922 "Channel-A: using MSI-X #0");
923 } else if (assigned
[i
] && assigned
[i
]->type
==
924 XGE_HAL_CHANNEL_TYPE_FIFO
) {
925 intr
= xge_fifo_msix_isr
;
926 intr_arg
= (caddr_t
)assigned
[i
];
927 xge_debug_osdep(XGE_TRACE
, "Channel-Tx%d"
929 assigned
[i
]->post_qid
, i
);
930 } else if (assigned
[i
] && assigned
[i
]->type
==
931 XGE_HAL_CHANNEL_TYPE_RING
) {
932 intr
= xge_ring_msix_isr
;
933 intr_arg
= (caddr_t
)assigned
[i
];
934 xge_debug_osdep(XGE_TRACE
, "Channel-Rx%d: "
936 assigned
[i
]->post_qid
, i
);
938 ret
= ddi_intr_add_handler(lldev
->intr_table
[i
], intr
,
939 intr_arg
, (caddr_t
)(uintptr_t)i
);
940 if (ret
!= DDI_SUCCESS
) {
942 xge_debug_osdep(XGE_ERR
,
943 "ddi_intr_add_handler()"
945 for (j
= 0; j
< i
; j
++) {
946 (void) ddi_intr_remove_handler(
947 lldev
->intr_table
[j
]);
949 return (DDI_FAILURE
);
953 for (i
= 1; i
< msix_idx
; i
++)
954 (void) xge_hal_channel_msix_set(assigned
[i
], i
);
960 ret
= ddi_intr_get_cap(lldev
->intr_table
[0], &lldev
->intr_cap
);
961 if (ret
!= DDI_SUCCESS
) {
962 xge_debug_osdep(XGE_ERR
, "ddi_intr_get_cap() failed %d", ret
);
963 for (i
= 0; i
< lldev
->intr_cnt
; i
++) {
964 (void) ddi_intr_remove_handler(lldev
->intr_table
[i
]);
966 return (DDI_FAILURE
);
968 return (DDI_SUCCESS
);
975 * Enable FIXED or MSI interrupts
978 xge_enable_intrs(xgelldev_t
*lldev
)
982 if (lldev
->intr_cap
& DDI_INTR_FLAG_BLOCK
) {
983 /* Call ddi_intr_block_enable() for MSI(X) interrupts */
984 if ((ret
= ddi_intr_block_enable(lldev
->intr_table
,
985 lldev
->intr_cnt
)) != DDI_SUCCESS
) {
986 xge_debug_osdep(XGE_ERR
, "ddi_intr_enable() failed, "
988 return (DDI_FAILURE
);
991 /* Call ddi_intr_enable for MSI(X) or FIXED interrupts */
992 for (i
= 0; i
< lldev
->intr_cnt
; i
++) {
993 if ((ret
= ddi_intr_enable(lldev
->intr_table
[i
]))
997 xge_debug_osdep(XGE_ERR
, "ddi_intr_enable() "
998 "failed, ret 0x%x", ret
);
1001 for (j
= 0; j
< i
; j
++) {
1002 (void) ddi_intr_disable(
1003 lldev
->intr_table
[j
]);
1006 return (DDI_FAILURE
);
1011 return (DDI_SUCCESS
);
1015 * xge_disable_intrs:
1017 * Disable FIXED or MSI interrupts
1020 xge_disable_intrs(xgelldev_t
*lldev
)
1024 if (lldev
->intr_cap
& DDI_INTR_FLAG_BLOCK
) {
1025 /* Call ddi_intr_block_disable() */
1026 (void) ddi_intr_block_disable(lldev
->intr_table
,
1029 for (i
= 0; i
< lldev
->intr_cnt
; i
++) {
1030 (void) ddi_intr_disable(lldev
->intr_table
[i
]);
1038 * Unregister FIXED or MSI interrupts
1041 xge_rem_intrs(xgelldev_t
*lldev
)
1045 xge_assert(lldev
->intr_table
!= NULL
);
1047 /* Call ddi_intr_remove_handler() */
1048 for (i
= 0; i
< lldev
->intr_cnt
; i
++) {
1049 (void) ddi_intr_remove_handler(lldev
->intr_table
[i
]);
1055 * @dev_info: pointer to dev_info_t structure
1056 * @cmd: attach command to process
1058 * This is a solaris standard attach function. This
1059 * function initializes the Xframe identified
1060 * by the dev_info_t structure and setup the driver
1061 * data structures corresponding to the Xframe Card.
1062 * This function also registers the XFRAME device
1063 * instance with the MAC Layer.
1064 * If this function returns success then the OS
1065 * will attach the HBA controller to this
1069 xge_attach(dev_info_t
*dev_info
, ddi_attach_cmd_t cmd
)
1072 xgell_config_t
*xgell_config
;
1073 xge_hal_device_config_t
*device_config
;
1074 xge_hal_device_t
*hldev
;
1075 xge_hal_device_attr_t attr
;
1076 xge_hal_status_e status
;
1077 int ret
, intr_types
, i
;
1079 xge_debug_osdep(XGE_TRACE
, "XGE_ATTACH cmd %d", cmd
);
1087 xge_debug_osdep(XGE_ERR
, "%s", "resume unsupported yet");
1092 xge_debug_osdep(XGE_ERR
, "cmd 0x%x unrecognized", cmd
);
1097 xgell_config
= kmem_zalloc(sizeof (xgell_config_t
), KM_SLEEP
);
1098 device_config
= kmem_zalloc(sizeof (xge_hal_device_config_t
), KM_SLEEP
);
1101 * Initialize all configurations
1103 xge_configuration_init(dev_info
, device_config
, xgell_config
);
1105 /* Determine which types of interrupts supported */
1106 ret
= ddi_intr_get_supported_types(dev_info
, &intr_types
);
1107 if ((ret
!= DDI_SUCCESS
) || (!(intr_types
& DDI_INTR_TYPE_FIXED
))) {
1108 xge_debug_osdep(XGE_ERR
, "%s",
1109 "fixed type interrupt is not supported");
1114 ret
= ddi_regs_map_setup(dev_info
, 1, (caddr_t
*)&attr
.bar0
,
1115 0, 0, &xge_dev_attr
, &attr
.regh0
);
1116 if (ret
!= DDI_SUCCESS
) {
1117 xge_debug_osdep(XGE_ERR
, "unable to map bar0: [%d]", ret
);
1122 ret
= ddi_regs_map_setup(dev_info
, 2, (caddr_t
*)&attr
.bar1
,
1123 0, 0, &xge_dev_attr
, &attr
.regh1
);
1124 if (ret
!= DDI_SUCCESS
) {
1125 xge_debug_osdep(XGE_ERR
, "unable to map bar1: [%d]", ret
);
1129 /* map BAR2 MSI(X) */
1130 ret
= ddi_regs_map_setup(dev_info
, 2, (caddr_t
*)&attr
.bar2
,
1131 0, 0, &xge_dev_attr
, &attr
.regh2
);
1132 if (ret
!= DDI_SUCCESS
) {
1133 xge_debug_osdep(XGE_ERR
, "unable to map bar2: [%d]", ret
);
1137 /* preallocate memory for new HAL device and private LL part */
1138 hldev
= kmem_zalloc(sizeof (xge_hal_device_t
), KM_SLEEP
);
1140 /* Get the PCI Configuartion space handle */
1141 ret
= pci_config_setup(dev_info
, &attr
.cfgh
);
1142 if (ret
!= DDI_SUCCESS
) {
1143 xge_debug_osdep(XGE_ERR
, "%s", "can not setup config space");
1147 attr
.pdev
= dev_info
;
1149 ret
= xgell_device_alloc(hldev
, dev_info
, &ll
);
1150 if (ret
!= DDI_SUCCESS
) {
1151 xge_debug_osdep(XGE_ERR
,
1153 "unable to allocate new LL device");
1158 * Init multiple rings configuration
1160 switch (xgell_config
->grouping
) {
1161 case XGELL_CONF_GROUP_POLICY_VIRT
:
1162 ll
->init_rx_rings
= XGELL_RX_RING_NUM_MAX
; /* 8 */
1163 ll
->init_tx_rings
= XGELL_TX_RING_NUM_MAX
; /* 8 */
1164 ll
->init_rx_groups
= ll
->init_rx_rings
;
1166 case XGELL_CONF_GROUP_POLICY_PERF
:
1167 ll
->init_rx_rings
= XGELL_RX_RING_NUM_MAX
; /* 8 */
1168 ll
->init_tx_rings
= XGELL_TX_RING_NUM_MAX
; /* 8 */
1169 ll
->init_rx_groups
= 1;
1171 case XGELL_CONF_GROUP_POLICY_BASIC
:
1172 ll
->init_rx_rings
= XGELL_RX_RING_NUM_MIN
; /* 1 */
1173 ll
->init_tx_rings
= XGELL_TX_RING_NUM_MIN
; /* 1 */
1174 ll
->init_rx_groups
= ll
->init_rx_rings
;
1182 * Init MSI-X configuration
1184 if (xgell_config
->msix_enable
&& intr_types
& DDI_INTR_TYPE_MSIX
) {
1185 ll
->intr_type
= DDI_INTR_TYPE_MSIX
;
1187 for (i
= 0; i
< XGE_HAL_MAX_FIFO_NUM
; i
++)
1188 if (device_config
->fifo
.queue
[i
].configured
)
1190 for (i
= 0; i
< XGE_HAL_MAX_RING_NUM
; i
++)
1191 if (device_config
->ring
.queue
[i
].configured
)
1194 ll
->intr_type
= DDI_INTR_TYPE_FIXED
;
1199 * Allocate interrupt(s)
1201 while ((ret
= xge_alloc_intrs(ll
)) != DDI_SUCCESS
) {
1202 if (ll
->intr_type
== DDI_INTR_TYPE_MSIX
) {
1203 xgell_config
->msix_enable
= 0;
1204 ll
->intr_type
= DDI_INTR_TYPE_FIXED
;
1206 device_config
->intr_mode
= XGE_HAL_INTR_MODE_IRQLINE
;
1207 xge_debug_osdep(XGE_TRACE
,
1208 "Unable to allocate MSI-X handlers"
1209 " - defaulting to IRQA");
1215 if (ll
->intr_type
== DDI_INTR_TYPE_MSIX
) {
1216 device_config
->intr_mode
= XGE_HAL_INTR_MODE_MSIX
;
1217 device_config
->bimodal_interrupts
= 0;
1219 device_config
->intr_mode
= XGE_HAL_INTR_MODE_IRQLINE
;
1222 attr
.irqh
= ll
->intr_pri
;
1225 status
= xge_hal_device_initialize(hldev
, &attr
, device_config
);
1226 if (status
!= XGE_HAL_OK
) {
1228 case XGE_HAL_ERR_DRIVER_NOT_INITIALIZED
:
1229 xge_debug_osdep(XGE_ERR
, "%s",
1230 "driver is not initialized");
1233 case XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT
:
1234 xge_debug_osdep(XGE_ERR
, "%s",
1235 "device is not quiescent");
1238 case XGE_HAL_ERR_OUT_OF_MEMORY
:
1239 xge_debug_osdep(XGE_ERR
, "%s",
1240 "unable to allocate memory");
1244 xge_debug_osdep(XGE_ERR
,
1245 "can't initialize the device: %d", status
);
1251 /* register interrupt handler for handling xge device interrupts */
1252 ret
= xge_add_intrs(ll
);
1253 if (ret
!= DDI_SUCCESS
)
1256 /* allocate and register Link Layer */
1257 ret
= xgell_device_register(ll
, xgell_config
);
1258 if (ret
!= DDI_SUCCESS
) {
1262 /* store ll as a HAL private part */
1263 xge_hal_device_private_set(hldev
, ll
);
1265 kmem_free(device_config
, sizeof (xge_hal_device_config_t
));
1266 kmem_free(xgell_config
, sizeof (xgell_config_t
));
1268 return (DDI_SUCCESS
);
1273 xge_hal_device_terminate(hldev
);
1277 xgell_device_free(ll
);
1279 pci_config_teardown(&attr
.cfgh
);
1281 kmem_free(hldev
, sizeof (xge_hal_device_t
));
1283 ddi_regs_map_free(&attr
.regh2
);
1285 ddi_regs_map_free(&attr
.regh1
);
1287 ddi_regs_map_free(&attr
.regh0
);
1289 kmem_free(device_config
, sizeof (xge_hal_device_config_t
));
1290 kmem_free(xgell_config
, sizeof (xgell_config_t
));
1296 * quiesce(9E) entry point.
1298 * This function is called when the system is single-threaded at high
1299 * PIL with preemption disabled. Therefore, this function must not be
1302 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure.
1303 * DDI_FAILURE indicates an error condition and should almost never happen.
1306 xge_quiesce(dev_info_t
*dev_info
)
1308 xge_hal_device_t
*hldev
=
1309 (xge_hal_device_t
*)ddi_get_driver_private(dev_info
);
1311 xgelldev_t
*lldev
= xge_hal_device_private(hldev
);
1313 xge_hal_device_quiesce(hldev
, lldev
->devh
);
1315 return (DDI_SUCCESS
);
1320 * @dev_info: pointer to dev_info_t structure
1321 * @cmd: attach command to process
1323 * This function is called by OS when the system is about
1324 * to shutdown or when the super user tries to unload
1325 * the driver. This function frees all the memory allocated
1326 * during xge_attach() and also unregisters the Xframe
1327 * device instance from the GLD framework.
1330 xge_detach(dev_info_t
*dev_info
, ddi_detach_cmd_t cmd
)
1332 xge_hal_device_t
*hldev
;
1333 xge_hal_device_attr_t
*attr
;
1336 xge_debug_osdep(XGE_TRACE
, "XGE_DETACH cmd %d", cmd
);
1338 hldev
= (xge_hal_device_t
*)ddi_get_driver_private(dev_info
);
1339 attr
= xge_hal_device_attr(hldev
);
1340 lldev
= xge_hal_device_private(hldev
);
1346 case DDI_PM_SUSPEND
:
1347 xge_debug_osdep(XGE_ERR
, "%s", "suspend unsupported yet");
1348 return (DDI_FAILURE
);
1351 xge_debug_osdep(XGE_ERR
, "cmd 0x%x unrecognized", cmd
);
1352 return (DDI_FAILURE
);
1355 if (lldev
->is_initialized
) {
1356 xge_debug_osdep(XGE_ERR
, "%s",
1357 "can not detach: device is not unplumbed");
1358 return (DDI_FAILURE
);
1361 xge_hal_device_terminating(hldev
);
1362 if (xgell_device_unregister(lldev
) != DDI_SUCCESS
) {
1363 return (DDI_FAILURE
);
1365 xge_hal_device_terminate(hldev
);
1367 xge_rem_intrs(lldev
);
1368 xge_free_intrs(lldev
);
1369 xgell_device_free(lldev
);
1370 pci_config_teardown(&attr
->cfgh
);
1371 ddi_regs_map_free(&attr
->regh2
);
1372 ddi_regs_map_free(&attr
->regh1
);
1373 ddi_regs_map_free(&attr
->regh0
);
1374 kmem_free(hldev
, sizeof (xge_hal_device_t
));
1376 return (DDI_SUCCESS
);