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 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* 28 * Copyright (c) 2002-2005 Neterion, Inc. 29 * All right Reserved. 30 * 31 * FileName : xge.c 32 * 33 * Description: Xge main Solaris specific initialization & routines 34 * for upper layer driver 35 * 36 */ 37 #include "xgell.h" 38 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); 42 43 DDI_DEFINE_STREAM_OPS(xge_ops, nulldev, nulldev, xge_attach, xge_detach, 44 nodev, NULL, D_MP, NULL, xge_quiesce); 45 46 /* Standard Module linkage initialization for a Streams driver */ 47 extern struct mod_ops mod_driverops; 48 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 */ 53 }; 54 55 static struct modlinkage modlinkage = { 56 MODREV_1, {(void *)&modldrv, NULL} 57 }; 58 59 /* Xge device attributes */ 60 ddi_device_acc_attr_t xge_dev_attr = { 61 DDI_DEVICE_ATTR_V0, 62 DDI_NEVERSWAP_ACC, 63 DDI_STRICTORDER_ACC 64 }; 65 ddi_device_acc_attr_t *p_xge_dev_attr = &xge_dev_attr; 66 67 /* 68 * xge_event 69 * 70 * This function called by HAL to notify upper layer that some any 71 * event been produced. 72 */ 73 void 74 xge_event(xge_queue_item_t *item) 75 { 76 xgell_fifo_t *fifo = item->context; 77 xgelldev_t *lldev = fifo->lldev; 78 79 switch (item->event_type) { 80 case XGELL_EVENT_RESCHED_NEEDED: 81 if (lldev->is_initialized) { 82 if (xge_hal_channel_dtr_count(fifo->channelh) 83 >= XGELL_TX_LEVEL_HIGH) { 84 mac_tx_update(lldev->mh); 85 xge_debug_osdep(XGE_TRACE, "%s", 86 "mac_tx_update happened!"); 87 } 88 } 89 break; 90 default: 91 break; 92 } 93 } 94 95 /* 96 * xgell_callback_crit_err 97 * 98 * This function called by HAL on Serious Error event. XGE_HAL_EVENT_SERR. 99 * Upper layer must analyze it based on %type. 100 */ 101 static void 102 xge_callback_crit_err(void *userdata, xge_hal_event_e type, u64 serr_data) 103 { 104 (void) xgell_onerr_reset(userdata); 105 } 106 107 /* 108 * xge_xpak_alarm_log 109 * This function called by HAL on XPAK alarms. Upper layer must log the msg 110 * based on the xpak alarm type 111 */ 112 static void 113 xge_xpak_alarm_log(void *userdata, xge_hal_xpak_alarm_type_e type) 114 { 115 switch (type) { 116 case XGE_HAL_XPAK_ALARM_EXCESS_TEMP: 117 xge_debug_osdep(XGE_ERR, "%s", "Take Xframe NIC out of " 118 "service. Excessive temperatures may result in " 119 "premature transceiver failure \n"); 120 121 break; 122 case XGE_HAL_XPAK_ALARM_EXCESS_BIAS_CURRENT: 123 xge_debug_osdep(XGE_ERR, "%s", "Take Xframe NIC out of " 124 "service Excessive bias currents may indicate " 125 "imminent laser diode failure \n"); 126 127 break; 128 case XGE_HAL_XPAK_ALARM_EXCESS_LASER_OUTPUT: 129 xge_debug_osdep(XGE_ERR, "%s", "Take Xframe NIC out of " 130 "service Excessive laser output power may saturate " 131 "far-end receiver\n"); 132 133 break; 134 default: 135 xge_debug_osdep(XGE_ERR, "%s", "Undefined Xpak Alarm"); 136 break; 137 } 138 139 } 140 141 /* 142 * xge_queue_produce context 143 */ 144 static void 145 xge_callback_event_queued(xge_hal_device_h devh, int event_type) 146 { 147 if (event_type == XGELL_EVENT_RESCHED_NEEDED) { 148 (void) taskq_dispatch(system_taskq, xge_device_poll_now, devh, 149 TQ_NOSLEEP); 150 } 151 } 152 153 /* 154 * xge_driver_init_hal 155 * 156 * To initialize HAL portion of driver. 157 */ 158 static xge_hal_status_e 159 xge_driver_init_hal(void) 160 { 161 static xge_hal_driver_config_t driver_config; 162 xge_hal_uld_cbs_t uld_callbacks; 163 164 driver_config.queue_size_initial = 1; 165 driver_config.queue_size_max = 4; 166 167 uld_callbacks.link_up = xgell_callback_link_up; 168 uld_callbacks.link_down = xgell_callback_link_down; 169 uld_callbacks.crit_err = xge_callback_crit_err; 170 uld_callbacks.event = xge_event; 171 uld_callbacks.event_queued = xge_callback_event_queued; 172 uld_callbacks.before_device_poll = NULL; 173 uld_callbacks.after_device_poll = NULL; 174 uld_callbacks.sched_timer = NULL; 175 uld_callbacks.xpak_alarm_log = xge_xpak_alarm_log; 176 177 return (xge_hal_driver_initialize(&driver_config, &uld_callbacks)); 178 179 } 180 181 /* 182 * _init 183 * 184 * Solaris standard _init function for a device driver 185 */ 186 int 187 _init(void) 188 { 189 int ret = 0; 190 xge_hal_status_e status; 191 192 status = xge_driver_init_hal(); 193 if (status != XGE_HAL_OK) { 194 xge_debug_osdep(XGE_ERR, "can't initialize the driver (%d)", 195 status); 196 return (EINVAL); 197 } 198 199 xge_hal_driver_debug_module_mask_set(0xffffffff); 200 xge_hal_driver_debug_level_set(XGE_TRACE); 201 202 mac_init_ops(&xge_ops, "xge"); 203 if ((ret = mod_install(&modlinkage)) != 0) { 204 xge_hal_driver_terminate(); 205 mac_fini_ops(&xge_ops); 206 xge_debug_osdep(XGE_ERR, "%s", 207 "Unable to install the driver"); 208 return (ret); 209 } 210 211 return (0); 212 } 213 214 /* 215 * _fini 216 * 217 * Solaris standard _fini function for device driver 218 */ 219 int 220 _fini(void) 221 { 222 int ret; 223 224 ret = mod_remove(&modlinkage); 225 if (ret == 0) { 226 xge_hal_driver_terminate(); 227 mac_fini_ops(&xge_ops); 228 } 229 230 return (ret); 231 } 232 233 /* 234 * _info 235 * 236 * Solaris standard _info function for device driver 237 */ 238 int 239 _info(struct modinfo *pModinfo) 240 { 241 return (mod_info(&modlinkage, pModinfo)); 242 } 243 244 /* ARGSUSED */ 245 /* 246 * xge_isr 247 * @arg: pointer to device private strucutre(hldev) 248 * 249 * This is the ISR scheduled by the OS to indicate to the 250 * driver that the receive/transmit operation is completed. 251 */ 252 static uint_t 253 xge_isr(caddr_t arg0, caddr_t arg1) 254 { 255 xge_hal_status_e status; 256 xge_hal_device_t *hldev = (xge_hal_device_t *)arg0; 257 xgelldev_t *lldev = xge_hal_device_private(hldev); 258 259 if (!lldev->is_initialized) { 260 return (DDI_INTR_UNCLAIMED); 261 } 262 263 status = xge_hal_device_handle_irq(hldev); 264 265 return ((status == XGE_HAL_ERR_WRONG_IRQ) ? 266 DDI_INTR_UNCLAIMED : DDI_INTR_CLAIMED); 267 } 268 269 /* 270 * Interrupt handler for transmit when MSI-X interrupt mechasnism is used 271 */ 272 /* ARGSUSED */ 273 static uint_t 274 xge_fifo_msix_isr(caddr_t arg0, caddr_t arg1) 275 { 276 int got_tx; 277 xge_hal_channel_t *channel = (xge_hal_channel_t *)arg0; 278 xgelldev_t *lldev = xge_hal_device_private(channel->devh); 279 280 if (!lldev->is_initialized) { 281 return (DDI_INTR_UNCLAIMED); 282 } 283 (void) xge_hal_device_poll_tx_channel(channel, &got_tx); 284 285 return (DDI_INTR_CLAIMED); 286 } 287 288 /* 289 * Interrupt handler for receive when MSI-X interrupt mechasnism is used 290 */ 291 /* ARGSUSED */ 292 static uint_t 293 xge_ring_msix_isr(caddr_t arg0, caddr_t arg1) 294 { 295 int got_rx; 296 xge_hal_channel_t *channel = (xge_hal_channel_t *)arg0; 297 xgelldev_t *lldev = xge_hal_device_private(channel->devh); 298 299 if (!lldev->is_initialized) { 300 return (DDI_INTR_UNCLAIMED); 301 } 302 (void) xge_hal_device_poll_rx_channel(channel, &got_rx); 303 304 return (DDI_INTR_CLAIMED); 305 } 306 307 /* 308 * Configure single ring 309 */ 310 static void 311 xge_ring_config(dev_info_t *dev_info, 312 xge_hal_device_config_t *device_config, int num) 313 { 314 char msg[MSG_SIZE]; 315 316 (void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_configured", num); 317 device_config->ring.queue[num].configured = 318 ddi_prop_get_int(DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, 319 msg, num < XGELL_MAX_RING_DEFAULT ? 1 : 0); 320 321 /* no point to configure it further if unconfigured */ 322 if (!device_config->ring.queue[num].configured) 323 return; 324 325 #if defined(__sparc) 326 device_config->ring.queue[num].no_snoop_bits = 1; 327 #endif 328 329 (void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_max", num); 330 device_config->ring.queue[num].max = 331 ddi_prop_get_int(DDI_DEV_T_ANY, 332 dev_info, DDI_PROP_DONTPASS, msg, 333 XGE_HAL_DEFAULT_USE_HARDCODE); 334 335 (void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_initial", num); 336 device_config->ring.queue[num].initial = 337 ddi_prop_get_int(DDI_DEV_T_ANY, 338 dev_info, DDI_PROP_DONTPASS, msg, 339 XGE_HAL_DEFAULT_USE_HARDCODE); 340 341 if (device_config->ring.queue[num].initial == 342 XGE_HAL_DEFAULT_USE_HARDCODE) { 343 if (device_config->mtu > XGE_HAL_DEFAULT_MTU) { 344 device_config->ring.queue[num].initial = 345 device_config->ring.queue[num].max = 346 XGE_HAL_DEFAULT_RING_QUEUE_BLOCKS_J; 347 } else { 348 device_config->ring.queue[num].initial = 349 device_config->ring.queue[num].max = 350 XGE_HAL_DEFAULT_RING_QUEUE_BLOCKS_N; 351 } 352 } 353 354 (void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_buffer_mode", num); 355 device_config->ring.queue[num].buffer_mode = 356 ddi_prop_get_int(DDI_DEV_T_ANY, 357 dev_info, DDI_PROP_DONTPASS, msg, 358 XGE_HAL_RING_QUEUE_BUFFER_MODE_DEFAULT); 359 360 (void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_dram_size_mb", num); 361 device_config->ring.queue[num].dram_size_mb = 362 ddi_prop_get_int(DDI_DEV_T_ANY, 363 dev_info, DDI_PROP_DONTPASS, msg, 364 XGE_HAL_DEFAULT_USE_HARDCODE); 365 366 (void) xge_os_snprintf(msg, MSG_SIZE, 367 "ring%d_backoff_interval_us", num); 368 device_config->ring.queue[num].backoff_interval_us = 369 ddi_prop_get_int(DDI_DEV_T_ANY, 370 dev_info, DDI_PROP_DONTPASS, msg, 371 XGE_HAL_DEFAULT_BACKOFF_INTERVAL_US); 372 373 (void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_max_frm_len", num); 374 device_config->ring.queue[num].max_frm_len = 375 ddi_prop_get_int(DDI_DEV_T_ANY, 376 dev_info, DDI_PROP_DONTPASS, msg, 377 XGE_HAL_RING_USE_MTU); 378 379 380 (void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_priority", num); 381 device_config->ring.queue[num].priority = 382 ddi_prop_get_int(DDI_DEV_T_ANY, 383 dev_info, DDI_PROP_DONTPASS, msg, 384 XGE_HAL_DEFAULT_RING_PRIORITY); 385 386 (void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_urange_a", num); 387 device_config->ring.queue[num].rti.urange_a = 388 ddi_prop_get_int(DDI_DEV_T_ANY, 389 dev_info, DDI_PROP_DONTPASS, msg, 390 XGE_HAL_DEFAULT_RX_URANGE_A); 391 392 (void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_ufc_a", num); 393 device_config->ring.queue[num].rti.ufc_a = 394 ddi_prop_get_int(DDI_DEV_T_ANY, 395 dev_info, DDI_PROP_DONTPASS, msg, 396 XGE_HAL_DEFAULT_RX_UFC_A); 397 398 (void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_urange_b", num); 399 device_config->ring.queue[num].rti.urange_b = 400 ddi_prop_get_int(DDI_DEV_T_ANY, 401 dev_info, DDI_PROP_DONTPASS, msg, 402 XGE_HAL_DEFAULT_RX_URANGE_B); 403 404 (void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_ufc_b", num); 405 device_config->ring.queue[num].rti.ufc_b = 406 ddi_prop_get_int(DDI_DEV_T_ANY, 407 dev_info, DDI_PROP_DONTPASS, msg, 408 device_config->mtu > XGE_HAL_DEFAULT_MTU ? 409 XGE_HAL_DEFAULT_RX_UFC_B_J: 410 XGE_HAL_DEFAULT_RX_UFC_B_N); 411 412 (void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_urange_c", num); 413 device_config->ring.queue[num].rti.urange_c = 414 ddi_prop_get_int(DDI_DEV_T_ANY, 415 dev_info, DDI_PROP_DONTPASS, msg, 416 XGE_HAL_DEFAULT_RX_URANGE_C); 417 418 (void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_ufc_c", num); 419 device_config->ring.queue[num].rti.ufc_c = 420 ddi_prop_get_int(DDI_DEV_T_ANY, 421 dev_info, DDI_PROP_DONTPASS, msg, 422 device_config->mtu > XGE_HAL_DEFAULT_MTU ? 423 XGE_HAL_DEFAULT_RX_UFC_C_J: 424 XGE_HAL_DEFAULT_RX_UFC_C_N); 425 426 (void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_ufc_d", num); 427 device_config->ring.queue[num].rti.ufc_d = 428 ddi_prop_get_int(DDI_DEV_T_ANY, 429 dev_info, DDI_PROP_DONTPASS, msg, 430 XGE_HAL_DEFAULT_RX_UFC_D); 431 432 (void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_timer_val", num); 433 device_config->ring.queue[num].rti.timer_val_us = 434 ddi_prop_get_int(DDI_DEV_T_ANY, 435 dev_info, DDI_PROP_DONTPASS, msg, 436 XGE_HAL_DEFAULT_RX_TIMER_VAL); 437 438 (void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_timer_ac_en", num); 439 device_config->ring.queue[num].rti.timer_ac_en = 440 ddi_prop_get_int(DDI_DEV_T_ANY, 441 dev_info, DDI_PROP_DONTPASS, msg, 442 XGE_HAL_DEFAULT_RX_TIMER_AC_EN); 443 444 (void) xge_os_snprintf(msg, MSG_SIZE, "ring%d_indicate_max_pkts", num); 445 device_config->ring.queue[num].indicate_max_pkts = 446 ddi_prop_get_int(DDI_DEV_T_ANY, 447 dev_info, DDI_PROP_DONTPASS, msg, 448 (device_config->bimodal_interrupts ? 449 XGE_HAL_DEFAULT_INDICATE_MAX_PKTS_B : 450 XGE_HAL_DEFAULT_INDICATE_MAX_PKTS_N)); 451 452 if (device_config->ring.queue[num].configured) { 453 /* enable RTH steering by default */ 454 device_config->ring.queue[num].rth_en = 1; 455 device_config->rth_en = XGE_HAL_RTH_ENABLE; 456 device_config->rth_bucket_size = XGE_HAL_MAX_RTH_BUCKET_SIZE; 457 device_config->rth_spdm_en = XGE_HAL_RTH_SPDM_DISABLE; 458 device_config->rth_spdm_use_l4 = XGE_HAL_RTH_SPDM_USE_L4; 459 } 460 } 461 462 /* 463 * Configure single fifo 464 */ 465 static void 466 xge_fifo_config(dev_info_t *dev_info, 467 xge_hal_device_config_t *device_config, int num) 468 { 469 char msg[MSG_SIZE]; 470 471 (void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_configured", num); 472 device_config->fifo.queue[num].configured = 473 ddi_prop_get_int(DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, 474 msg, num < XGELL_MAX_FIFO_DEFAULT ? 1 : 0); 475 476 /* no point to configure it further */ 477 if (!device_config->fifo.queue[num].configured) 478 return; 479 480 #if defined(__sparc) 481 device_config->fifo.queue[num].no_snoop_bits = 1; 482 #endif 483 484 (void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_max", num); 485 device_config->fifo.queue[num].max = ddi_prop_get_int(DDI_DEV_T_ANY, 486 dev_info, DDI_PROP_DONTPASS, msg, 487 XGE_HAL_DEFAULT_USE_HARDCODE); 488 489 (void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_initial", num); 490 device_config->fifo.queue[num].initial = ddi_prop_get_int(DDI_DEV_T_ANY, 491 dev_info, DDI_PROP_DONTPASS, msg, 492 XGE_HAL_DEFAULT_USE_HARDCODE); 493 494 if (device_config->fifo.queue[num].initial == 495 XGE_HAL_DEFAULT_USE_HARDCODE) { 496 if (device_config->mtu > XGE_HAL_DEFAULT_MTU) { 497 device_config->fifo.queue[num].initial = 498 device_config->fifo.queue[num].max = 499 XGE_HAL_DEFAULT_FIFO_QUEUE_LENGTH_J; 500 } else { 501 device_config->fifo.queue[num].initial = 502 device_config->fifo.queue[num].max = 503 XGE_HAL_DEFAULT_FIFO_QUEUE_LENGTH_N; 504 } 505 } 506 507 (void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_intr", num); 508 device_config->fifo.queue[num].intr = ddi_prop_get_int(DDI_DEV_T_ANY, 509 dev_info, DDI_PROP_DONTPASS, msg, 510 XGE_HAL_DEFAULT_FIFO_QUEUE_INTR); 511 512 /* 513 * TTI 0 configuration 514 */ 515 (void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_tti_enable", num); 516 device_config->fifo.queue[num].tti[num].enabled = ddi_prop_get_int( 517 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg, 1); 518 519 (void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_tti_urange_a", num); 520 device_config->fifo.queue[num].tti[num].urange_a = ddi_prop_get_int( 521 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg, 522 XGE_HAL_DEFAULT_TX_URANGE_A); 523 524 (void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_tti_ufc_a", num); 525 device_config->fifo.queue[num].tti[num].ufc_a = ddi_prop_get_int( 526 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg, 527 XGE_HAL_DEFAULT_TX_UFC_A); 528 529 (void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_tti_urange_b", num); 530 device_config->fifo.queue[num].tti[num].urange_b = ddi_prop_get_int( 531 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg, 532 XGE_HAL_DEFAULT_TX_URANGE_B); 533 534 (void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_tti_ufc_b", num); 535 device_config->fifo.queue[num].tti[num].ufc_b = ddi_prop_get_int( 536 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg, 537 XGE_HAL_DEFAULT_TX_UFC_B); 538 539 (void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_tti_urange_c", num); 540 device_config->fifo.queue[num].tti[num].urange_c = ddi_prop_get_int( 541 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg, 542 XGE_HAL_DEFAULT_TX_URANGE_C); 543 544 (void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_tti_ufc_c", num); 545 device_config->fifo.queue[num].tti[num].ufc_c = ddi_prop_get_int( 546 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg, 547 XGE_HAL_DEFAULT_TX_UFC_C); 548 549 (void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_tti_ufc_d", num); 550 device_config->fifo.queue[num].tti[num].ufc_d = ddi_prop_get_int( 551 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg, 552 XGE_HAL_DEFAULT_TX_UFC_D); 553 554 (void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_timer_ac_en", num); 555 device_config->fifo.queue[num].tti[num].timer_ac_en = ddi_prop_get_int( 556 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg, 557 XGE_HAL_DEFAULT_TX_TIMER_AC_EN); 558 559 (void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_tti_timer_val", num); 560 device_config->fifo.queue[num].tti[num].timer_val_us = ddi_prop_get_int( 561 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg, 562 XGE_HAL_DEFAULT_TX_TIMER_VAL); 563 564 (void) xge_os_snprintf(msg, MSG_SIZE, "fifo%d_tti_timer_ci_en", num); 565 device_config->fifo.queue[num].tti[num].timer_ci_en = ddi_prop_get_int( 566 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, msg, 567 XGE_HAL_DEFAULT_TX_TIMER_CI_EN); 568 } 569 570 /* 571 * xge_configuration_init 572 * @device_config: pointer to xge_hal_device_config_t 573 * 574 * This function will lookup properties from .conf file to init 575 * the configuration data structure. If a property is not in .conf 576 * file, the default value should be set. 577 */ 578 static void 579 xge_configuration_init(dev_info_t *dev_info, 580 xge_hal_device_config_t *device_config, xgell_config_t *ll_config) 581 { 582 int i, rings_configured = 0, fifos_configured = 0; 583 584 /* 585 * Initialize common properties 586 */ 587 device_config->mtu = ddi_prop_get_int(DDI_DEV_T_ANY, 588 dev_info, DDI_PROP_DONTPASS, "default_mtu", 589 XGE_HAL_DEFAULT_INITIAL_MTU); 590 device_config->isr_polling_cnt = ddi_prop_get_int(DDI_DEV_T_ANY, 591 dev_info, DDI_PROP_DONTPASS, "isr_polling_cnt", 592 XGE_HAL_DEFAULT_ISR_POLLING_CNT); 593 device_config->latency_timer = ddi_prop_get_int(DDI_DEV_T_ANY, 594 dev_info, DDI_PROP_DONTPASS, "latency_timer", 595 XGE_HAL_DEFAULT_LATENCY_TIMER); 596 device_config->max_splits_trans = ddi_prop_get_int(DDI_DEV_T_ANY, 597 dev_info, DDI_PROP_DONTPASS, "max_splits_trans", 598 XGE_HAL_DEFAULT_SPLIT_TRANSACTION); 599 device_config->mmrb_count = ddi_prop_get_int(DDI_DEV_T_ANY, 600 dev_info, DDI_PROP_DONTPASS, "mmrb_count", 601 XGE_HAL_DEFAULT_MMRB_COUNT); 602 device_config->shared_splits = ddi_prop_get_int(DDI_DEV_T_ANY, 603 dev_info, DDI_PROP_DONTPASS, "shared_splits", 604 XGE_HAL_DEFAULT_SHARED_SPLITS); 605 device_config->stats_refresh_time_sec = ddi_prop_get_int(DDI_DEV_T_ANY, 606 dev_info, DDI_PROP_DONTPASS, "stats_refresh_time", 607 XGE_HAL_DEFAULT_STATS_REFRESH_TIME); 608 device_config->device_poll_millis = ddi_prop_get_int(DDI_DEV_T_ANY, 609 dev_info, DDI_PROP_DONTPASS, "device_poll_millis", 610 XGE_HAL_DEFAULT_DEVICE_POLL_MILLIS); 611 device_config->pci_freq_mherz = ddi_prop_get_int(DDI_DEV_T_ANY, 612 dev_info, DDI_PROP_DONTPASS, "pci_freq_mherz", 613 XGE_HAL_DEFAULT_USE_HARDCODE); 614 615 /* 616 * Initialize ring properties 617 */ 618 device_config->ring.memblock_size = ddi_prop_get_int(DDI_DEV_T_ANY, 619 dev_info, DDI_PROP_DONTPASS, "ring_memblock_size", 620 XGE_HAL_DEFAULT_RING_MEMBLOCK_SIZE); 621 device_config->ring.strip_vlan_tag = XGE_HAL_RING_DONOT_STRIP_VLAN_TAG; 622 623 /* 624 * Bimodal Interrupts - TTI 56 configuration 625 */ 626 device_config->bimodal_interrupts = ddi_prop_get_int( 627 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, "bimodal_interrupts", 628 XGE_HAL_DEFAULT_BIMODAL_INTERRUPTS); 629 device_config->bimodal_timer_lo_us = ddi_prop_get_int( 630 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, "bimodal_timer_lo_us", 631 XGE_HAL_DEFAULT_BIMODAL_TIMER_LO_US); 632 device_config->bimodal_timer_hi_us = ddi_prop_get_int( 633 DDI_DEV_T_ANY, dev_info, DDI_PROP_DONTPASS, "bimodal_timer_hi_us", 634 XGE_HAL_DEFAULT_BIMODAL_TIMER_HI_US); 635 636 /* 637 * MSI-X switch 638 */ 639 ll_config->msix_enable = ddi_prop_get_int(DDI_DEV_T_ANY, dev_info, 640 DDI_PROP_DONTPASS, "msix_enable", XGELL_CONF_ENABLE_BY_DEFAULT); 641 642 /* 643 * Go through all possibly configured rings. Each ring could be 644 * configured individually. To enable/disable specific ring, just 645 * set ring->configured = [1|0]. 646 * 647 * By default *all* rings enabled. 648 */ 649 for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) { 650 xge_ring_config(dev_info, device_config, i); 651 if (device_config->ring.queue[i].configured) 652 rings_configured++; 653 } 654 655 /* 656 * Initialize mac properties 657 */ 658 device_config->mac.tmac_util_period = ddi_prop_get_int(DDI_DEV_T_ANY, 659 dev_info, DDI_PROP_DONTPASS, "mac_tmac_util_period", 660 XGE_HAL_DEFAULT_TMAC_UTIL_PERIOD); 661 device_config->mac.rmac_util_period = ddi_prop_get_int(DDI_DEV_T_ANY, 662 dev_info, DDI_PROP_DONTPASS, "mac_rmac_util_period", 663 XGE_HAL_DEFAULT_RMAC_UTIL_PERIOD); 664 device_config->mac.rmac_bcast_en = ddi_prop_get_int(DDI_DEV_T_ANY, 665 dev_info, DDI_PROP_DONTPASS, "mac_rmac_bcast_en", 666 1); /* HAL never provide a good named macro */ 667 device_config->mac.rmac_pause_gen_en = ddi_prop_get_int(DDI_DEV_T_ANY, 668 dev_info, DDI_PROP_DONTPASS, "rmac_pause_gen_en", 669 XGE_HAL_DEFAULT_RMAC_PAUSE_GEN_DIS); 670 device_config->mac.rmac_pause_rcv_en = ddi_prop_get_int(DDI_DEV_T_ANY, 671 dev_info, DDI_PROP_DONTPASS, "rmac_pause_rcv_en", 672 XGE_HAL_DEFAULT_RMAC_PAUSE_RCV_DIS); 673 device_config->mac.rmac_pause_time = ddi_prop_get_int(DDI_DEV_T_ANY, 674 dev_info, DDI_PROP_DONTPASS, "mac_rmac_pause_time", 675 XGE_HAL_DEFAULT_RMAC_HIGH_PTIME); 676 device_config->mac.mc_pause_threshold_q0q3 = 677 ddi_prop_get_int(DDI_DEV_T_ANY, 678 dev_info, DDI_PROP_DONTPASS, "mac_mc_pause_threshold_q0q3", 679 XGE_HAL_DEFAULT_MC_PAUSE_THRESHOLD_Q0Q3); 680 device_config->mac.mc_pause_threshold_q4q7 = 681 ddi_prop_get_int(DDI_DEV_T_ANY, 682 dev_info, DDI_PROP_DONTPASS, "mac_mc_pause_threshold_q4q7", 683 XGE_HAL_DEFAULT_MC_PAUSE_THRESHOLD_Q4Q7); 684 685 /* 686 * Initialize fifo properties 687 */ 688 device_config->fifo.max_frags = ddi_prop_get_int(DDI_DEV_T_ANY, 689 dev_info, DDI_PROP_DONTPASS, "fifo_max_frags", 690 XGE_HAL_DEFAULT_FIFO_FRAGS); 691 device_config->fifo.reserve_threshold = ddi_prop_get_int(DDI_DEV_T_ANY, 692 dev_info, DDI_PROP_DONTPASS, "fifo_reserve_threshold", 693 XGE_HAL_DEFAULT_FIFO_RESERVE_THRESHOLD); 694 device_config->fifo.memblock_size = ddi_prop_get_int(DDI_DEV_T_ANY, 695 dev_info, DDI_PROP_DONTPASS, "fifo_memblock_size", 696 XGE_HAL_DEFAULT_FIFO_MEMBLOCK_SIZE); 697 #ifdef XGE_HAL_ALIGN_XMIT 698 device_config->fifo.alignment_size = ddi_prop_get_int(DDI_DEV_T_ANY, 699 dev_info, DDI_PROP_DONTPASS, "fifo_copied_frag_size", 700 XGE_HAL_DEFAULT_FIFO_ALIGNMENT_SIZE); 701 device_config->fifo.max_aligned_frags = ddi_prop_get_int(DDI_DEV_T_ANY, 702 dev_info, DDI_PROP_DONTPASS, "fifo_copied_max_frags", 703 XGE_HAL_DEFAULT_FIFO_MAX_ALIGNED_FRAGS); 704 #endif 705 706 /* 707 * Go through all possibly configured fifos. Each fifo could be 708 * configured individually. To enable/disable specific fifo, just 709 * set fifo->configured = [0|1]. 710 * 711 * By default *all* fifos enabled. 712 */ 713 for (i = 0; i < XGE_HAL_MAX_FIFO_NUM; i++) { 714 xge_fifo_config(dev_info, device_config, i); 715 if (device_config->fifo.queue[i].configured) 716 fifos_configured++; 717 } 718 719 /* 720 * Initialize errors dumping 721 */ 722 device_config->dump_on_serr = ddi_prop_get_int(DDI_DEV_T_ANY, 723 dev_info, DDI_PROP_DONTPASS, "dump_on_serr", 724 0); 725 device_config->dump_on_serr = ddi_prop_get_int(DDI_DEV_T_ANY, 726 dev_info, DDI_PROP_DONTPASS, "dump_on_eccerr", 727 0); 728 device_config->dump_on_serr = ddi_prop_get_int(DDI_DEV_T_ANY, 729 dev_info, DDI_PROP_DONTPASS, "dump_on_parityerr", 730 0); 731 732 /* 733 * LRO tunables 734 */ 735 device_config->lro_sg_size = ddi_prop_get_int(DDI_DEV_T_ANY, 736 dev_info, DDI_PROP_DONTPASS, "lro_sg_size", 737 XGE_HAL_DEFAULT_LRO_SG_SIZE); 738 device_config->lro_frm_len = ddi_prop_get_int(DDI_DEV_T_ANY, 739 dev_info, DDI_PROP_DONTPASS, "lro_frm_len", 740 XGE_HAL_DEFAULT_LRO_FRM_LEN); 741 742 /* 743 * Initialize link layer configuration 744 */ 745 ll_config->rx_buffer_total = ddi_prop_get_int(DDI_DEV_T_ANY, 746 dev_info, DDI_PROP_DONTPASS, "rx_buffer_total", 747 device_config->ring.queue[XGELL_RING_MAIN_QID].initial * 748 XGELL_RX_BUFFER_TOTAL); 749 ll_config->rx_buffer_total += XGELL_RX_BUFFER_RECYCLE_CACHE; 750 ll_config->rx_buffer_post_hiwat = ddi_prop_get_int(DDI_DEV_T_ANY, 751 dev_info, DDI_PROP_DONTPASS, "rx_buffer_post_hiwat", 752 device_config->ring.queue[XGELL_RING_MAIN_QID].initial * 753 XGELL_RX_BUFFER_POST_HIWAT); 754 ll_config->rx_buffer_post_hiwat += XGELL_RX_BUFFER_RECYCLE_CACHE; 755 ll_config->rx_pkt_burst = ddi_prop_get_int(DDI_DEV_T_ANY, 756 dev_info, DDI_PROP_DONTPASS, "rx_pkt_burst", 757 XGELL_RX_PKT_BURST); 758 ll_config->rx_dma_lowat = ddi_prop_get_int(DDI_DEV_T_ANY, dev_info, 759 DDI_PROP_DONTPASS, "rx_dma_lowat", XGELL_RX_DMA_LOWAT); 760 ll_config->tx_dma_lowat = ddi_prop_get_int(DDI_DEV_T_ANY, dev_info, 761 DDI_PROP_DONTPASS, "tx_dma_lowat", XGELL_TX_DMA_LOWAT); 762 ll_config->lso_enable = ddi_prop_get_int(DDI_DEV_T_ANY, dev_info, 763 DDI_PROP_DONTPASS, "lso_enable", XGELL_CONF_ENABLE_BY_DEFAULT); 764 } 765 766 767 /* 768 * xge_alloc_intrs: 769 * 770 * Allocate FIXED or MSIX interrupts. 771 */ 772 static int 773 xge_alloc_intrs(xgelldev_t *lldev) 774 { 775 dev_info_t *dip = lldev->dev_info; 776 int avail, actual, count = 0; 777 int i, intr_behavior, ret; 778 779 if (lldev->intr_type == DDI_INTR_TYPE_MSIX) { 780 intr_behavior = DDI_INTR_ALLOC_STRICT; 781 (void) ddi_prop_create(DDI_DEV_T_NONE, dip, 782 DDI_PROP_CANSLEEP, "#msix-request", NULL, 0); 783 } else { 784 intr_behavior = DDI_INTR_ALLOC_NORMAL; 785 } 786 787 /* Get number of interrupts */ 788 ret = ddi_intr_get_nintrs(dip, lldev->intr_type, &count); 789 if ((ret != DDI_SUCCESS) || (count == 0)) { 790 xge_debug_osdep(XGE_ERR, "ddi_intr_get_nintrs() failed, " 791 "ret: %d, count: %d", ret, count); 792 793 goto _err_exit0; 794 } 795 796 /* Get number of available interrupts */ 797 ret = ddi_intr_get_navail(dip, lldev->intr_type, &avail); 798 if ((ret != DDI_SUCCESS) || (avail == 0)) { 799 xge_debug_osdep(XGE_ERR, "ddi_intr_get_navail() failure, " 800 "ret: %d, avail: %d", ret, avail); 801 802 goto _err_exit0; 803 } 804 805 if (avail < lldev->intr_cnt) { 806 xge_debug_osdep(XGE_ERR, "%d interrupts wanted while only " 807 "%d available", lldev->intr_cnt, avail); 808 goto _err_exit0; 809 } 810 811 /* Allocate an array of interrupt handles */ 812 lldev->intr_table_size = lldev->intr_cnt * sizeof (ddi_intr_handle_t); 813 lldev->intr_table = kmem_alloc(lldev->intr_table_size, KM_SLEEP); 814 815 /* Call ddi_intr_alloc() */ 816 ret = ddi_intr_alloc(dip, lldev->intr_table, lldev->intr_type, 0, 817 lldev->intr_cnt, &actual, intr_behavior); 818 if ((ret != DDI_SUCCESS) || (actual == 0)) { 819 xge_debug_osdep(XGE_ERR, "ddi_intr_alloc() failed %d", ret); 820 goto _err_exit1; 821 } 822 823 xge_debug_osdep(XGE_TRACE, "%s: Requested: %d, Granted: %d", 824 lldev->intr_type == DDI_INTR_TYPE_MSIX ? "MSI-X" : 825 "IRQA", count, actual); 826 827 if (lldev->intr_cnt != actual) { 828 xge_debug_osdep(XGE_ERR, "Not enough resources granted"); 829 goto _err_exit2; 830 } 831 832 /* 833 * Get priority for first msi, assume remaining are all the same 834 */ 835 if ((ret = ddi_intr_get_pri(lldev->intr_table[0], &lldev->intr_pri)) != 836 DDI_SUCCESS) { 837 xge_debug_osdep(XGE_ERR, "ddi_intr_get_pri() failed %d", ret); 838 goto _err_exit2; 839 } 840 841 return (DDI_SUCCESS); 842 843 _err_exit2: 844 /* Free already allocated intr */ 845 for (i = 0; i < actual; i++) { 846 (void) ddi_intr_free(lldev->intr_table[i]); 847 } 848 _err_exit1: 849 kmem_free(lldev->intr_table, lldev->intr_table_size); 850 _err_exit0: 851 if (lldev->intr_type == DDI_INTR_TYPE_MSIX) 852 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "#msix-request"); 853 return (DDI_FAILURE); 854 } 855 856 /* 857 * xge_free_intrs: 858 * 859 * Free previously allocated interrupts. 860 */ 861 static void 862 xge_free_intrs(xgelldev_t *lldev) 863 { 864 int i; 865 dev_info_t *dip = lldev->dev_info; 866 867 /* Free already allocated intr */ 868 for (i = 0; i < lldev->intr_cnt; i++) { 869 (void) ddi_intr_free(lldev->intr_table[i]); 870 } 871 kmem_free(lldev->intr_table, lldev->intr_table_size); 872 873 if (lldev->intr_type == DDI_INTR_TYPE_MSIX) 874 (void) ddi_prop_remove(DDI_DEV_T_NONE, dip, "#msix-request"); 875 } 876 877 /* 878 * xge_add_intrs: 879 * 880 * Register FIXED or MSI interrupts. 881 */ 882 int 883 xge_add_intrs(xgelldev_t *lldev) 884 { 885 int i, ret; 886 xge_hal_device_t *hldev = lldev->devh; 887 xge_hal_device_config_t *hal_conf = &hldev->config; 888 xge_hal_ring_config_t *ring_conf = &hal_conf->ring; 889 xge_hal_fifo_config_t *fifo_conf = &hal_conf->fifo; 890 xge_list_t *item; 891 int msix_idx = 1; /* 0 by default is reserved for Alarms. */ 892 xge_hal_channel_t *assigned[XGELL_MAX_RING_DEFAULT + 893 XGELL_MAX_FIFO_DEFAULT + 1]; 894 895 switch (lldev->intr_type) { 896 case DDI_INTR_TYPE_FIXED: 897 ret = ddi_intr_add_handler(lldev->intr_table[0], 898 (ddi_intr_handler_t *)xge_isr, 899 (caddr_t)hldev, 0); 900 if (ret != DDI_SUCCESS) { 901 xge_debug_osdep(XGE_ERR, "ddi_intr_add_handler(FIXED)" 902 "failed %d", ret); 903 return (DDI_FAILURE); 904 } 905 break; 906 907 case DDI_INTR_TYPE_MSIX: 908 i = 0; 909 xge_list_for_each(item, &hldev->free_channels) { 910 xge_hal_channel_t *channel = xge_container_of(item, 911 xge_hal_channel_t, item); 912 i = channel->post_qid; 913 if (channel->type == XGE_HAL_CHANNEL_TYPE_FIFO) { 914 if (fifo_conf->queue[i].configured) { 915 assigned[msix_idx] = channel; 916 msix_idx++; 917 } 918 } else { 919 if (ring_conf->queue[i].configured) { 920 assigned[msix_idx] = channel; 921 msix_idx++; 922 } 923 } 924 } 925 for (i = 0; i < lldev->intr_cnt; i++) { 926 uint_t (*intr)(caddr_t, caddr_t); 927 caddr_t intr_arg; 928 929 /* partition MSIX vectors */ 930 if (i == 0) { 931 intr = xge_isr; 932 intr_arg = (caddr_t)hldev; 933 xge_debug_osdep(XGE_TRACE, 934 "Channel-A: using MSI-X #0"); 935 } else if (assigned[i] && assigned[i]->type == 936 XGE_HAL_CHANNEL_TYPE_FIFO) { 937 intr = xge_fifo_msix_isr; 938 intr_arg = (caddr_t)assigned[i]; 939 xge_debug_osdep(XGE_TRACE, "Channel-Tx%d" 940 "using MSI-X #%d", 941 assigned[i]->post_qid, i); 942 } else if (assigned[i] && assigned[i]->type == 943 XGE_HAL_CHANNEL_TYPE_RING) { 944 intr = xge_ring_msix_isr; 945 intr_arg = (caddr_t)assigned[i]; 946 xge_debug_osdep(XGE_TRACE, "Channel-Rx%d: " 947 "using MSI-X #%d", 948 assigned[i]->post_qid, i); 949 } 950 ret = ddi_intr_add_handler(lldev->intr_table[i], intr, 951 intr_arg, (caddr_t)(uintptr_t)i); 952 if (ret != DDI_SUCCESS) { 953 int j; 954 xge_debug_osdep(XGE_ERR, 955 "ddi_intr_add_handler()" 956 " failed %d", ret); 957 for (j = 0; j < i; j++) { 958 (void) ddi_intr_remove_handler( 959 lldev->intr_table[j]); 960 } 961 return (DDI_FAILURE); 962 } 963 } 964 965 for (i = 1; i < msix_idx; i++) 966 (void) xge_hal_channel_msix_set(assigned[i], i); 967 break; 968 969 default: 970 break; 971 } 972 ret = ddi_intr_get_cap(lldev->intr_table[0], &lldev->intr_cap); 973 if (ret != DDI_SUCCESS) { 974 xge_debug_osdep(XGE_ERR, "ddi_intr_get_cap() failed %d", ret); 975 for (i = 0; i < lldev->intr_cnt; i++) { 976 (void) ddi_intr_remove_handler(lldev->intr_table[i]); 977 } 978 return (DDI_FAILURE); 979 } 980 return (DDI_SUCCESS); 981 } 982 983 984 /* 985 * xge_enable_intrs: 986 * 987 * Enable FIXED or MSI interrupts 988 */ 989 int 990 xge_enable_intrs(xgelldev_t *lldev) 991 { 992 int ret, i; 993 994 if (lldev->intr_cap & DDI_INTR_FLAG_BLOCK) { 995 /* Call ddi_intr_block_enable() for MSI(X) interrupts */ 996 if ((ret = ddi_intr_block_enable(lldev->intr_table, 997 lldev->intr_cnt)) != DDI_SUCCESS) { 998 xge_debug_osdep(XGE_ERR, "ddi_intr_enable() failed, " 999 "ret 0x%x", ret); 1000 return (DDI_FAILURE); 1001 } 1002 } else { 1003 /* Call ddi_intr_enable for MSI(X) or FIXED interrupts */ 1004 for (i = 0; i < lldev->intr_cnt; i++) { 1005 if ((ret = ddi_intr_enable(lldev->intr_table[i])) 1006 != DDI_SUCCESS) { 1007 int j; 1008 1009 xge_debug_osdep(XGE_ERR, "ddi_intr_enable() " 1010 "failed, ret 0x%x", ret); 1011 1012 /* unwind */ 1013 for (j = 0; j < i; j++) { 1014 (void) ddi_intr_disable( 1015 lldev->intr_table[j]); 1016 } 1017 1018 return (DDI_FAILURE); 1019 } 1020 } 1021 } 1022 1023 return (DDI_SUCCESS); 1024 } 1025 1026 /* 1027 * xge_disable_intrs: 1028 * 1029 * Disable FIXED or MSI interrupts 1030 */ 1031 void 1032 xge_disable_intrs(xgelldev_t *lldev) 1033 { 1034 int i; 1035 1036 if (lldev->intr_cap & DDI_INTR_FLAG_BLOCK) { 1037 /* Call ddi_intr_block_disable() */ 1038 (void) ddi_intr_block_disable(lldev->intr_table, 1039 lldev->intr_cnt); 1040 } else { 1041 for (i = 0; i < lldev->intr_cnt; i++) { 1042 (void) ddi_intr_disable(lldev->intr_table[i]); 1043 } 1044 } 1045 } 1046 1047 /* 1048 * xge_rem_intrs: 1049 * 1050 * Unregister FIXED or MSI interrupts 1051 */ 1052 void 1053 xge_rem_intrs(xgelldev_t *lldev) 1054 { 1055 int i; 1056 1057 /* Call ddi_intr_remove_handler() */ 1058 for (i = 0; i < lldev->intr_cnt; i++) { 1059 (void) ddi_intr_remove_handler(lldev->intr_table[i]); 1060 } 1061 } 1062 1063 /* 1064 * xge_attach 1065 * @dev_info: pointer to dev_info_t structure 1066 * @cmd: attach command to process 1067 * 1068 * This is a solaris standard attach function. This 1069 * function initializes the Xframe identified 1070 * by the dev_info_t structure and setup the driver 1071 * data structures corresponding to the Xframe Card. 1072 * This function also registers the XFRAME device 1073 * instance with the MAC Layer. 1074 * If this function returns success then the OS 1075 * will attach the HBA controller to this 1076 * driver. 1077 */ 1078 static int 1079 xge_attach(dev_info_t *dev_info, ddi_attach_cmd_t cmd) 1080 { 1081 xgelldev_t *ll; 1082 xge_hal_device_config_t *device_config; 1083 xge_hal_device_t *hldev; 1084 xge_hal_device_attr_t attr; 1085 xge_hal_status_e status; 1086 xgell_config_t ll_config; 1087 int ret, intr_types, i; 1088 1089 xge_debug_osdep(XGE_TRACE, "XGE_ATTACH cmd %d", cmd); 1090 1091 switch (cmd) { 1092 case DDI_ATTACH: 1093 break; 1094 1095 case DDI_RESUME: 1096 case DDI_PM_RESUME: 1097 xge_debug_osdep(XGE_ERR, "%s", "resume unsupported yet"); 1098 ret = DDI_FAILURE; 1099 goto _exit0; 1100 1101 default: 1102 xge_debug_osdep(XGE_ERR, "cmd 0x%x unrecognized", cmd); 1103 ret = DDI_FAILURE; 1104 goto _exit0; 1105 } 1106 1107 device_config = kmem_zalloc(sizeof (xge_hal_device_config_t), KM_SLEEP); 1108 1109 /* Init device_config by lookup up properties from .conf file */ 1110 xge_configuration_init(dev_info, device_config, &ll_config); 1111 1112 /* Determine which types of interrupts supported */ 1113 ret = ddi_intr_get_supported_types(dev_info, &intr_types); 1114 if ((ret != DDI_SUCCESS) || (!(intr_types & DDI_INTR_TYPE_FIXED))) { 1115 xge_debug_osdep(XGE_ERR, "%s", 1116 "fixed type interrupt is not supported"); 1117 goto _exit0a; 1118 } 1119 1120 /* map BAR0 */ 1121 ret = ddi_regs_map_setup(dev_info, 1, (caddr_t *)&attr.bar0, 1122 (offset_t)0, (offset_t)0, &xge_dev_attr, &attr.regh0); 1123 if (ret != DDI_SUCCESS) { 1124 xge_debug_osdep(XGE_ERR, "unable to map bar0: [%d]", ret); 1125 goto _exit0a; 1126 } 1127 1128 /* map BAR1 */ 1129 ret = ddi_regs_map_setup(dev_info, 2, (caddr_t *)&attr.bar1, 1130 (offset_t)0, (offset_t)0, &xge_dev_attr, &attr.regh1); 1131 if (ret != DDI_SUCCESS) { 1132 xge_debug_osdep(XGE_ERR, "unable to map bar1: [%d]", ret); 1133 goto _exit1; 1134 } 1135 1136 /* map BAR2 MSI(X) */ 1137 ret = ddi_regs_map_setup(dev_info, 2, (caddr_t *)&attr.bar2, 1138 (offset_t)0, (offset_t)0, &xge_dev_attr, &attr.regh2); 1139 if (ret != DDI_SUCCESS) { 1140 xge_debug_osdep(XGE_ERR, "unable to map bar2: [%d]", ret); 1141 goto _exit1a; 1142 } 1143 1144 /* preallocate memory for new HAL device and private LL part */ 1145 hldev = kmem_zalloc(sizeof (xge_hal_device_t), KM_SLEEP); 1146 1147 /* Get the PCI Configuartion space handle */ 1148 ret = pci_config_setup(dev_info, &attr.cfgh); 1149 if (ret != DDI_SUCCESS) { 1150 xge_debug_osdep(XGE_ERR, "%s", "can not setup config space"); 1151 goto _exit2a; 1152 } 1153 1154 attr.pdev = dev_info; 1155 1156 ret = xgell_device_alloc(hldev, dev_info, &ll); 1157 if (ret != DDI_SUCCESS) { 1158 xge_debug_osdep(XGE_ERR, 1159 "%s", 1160 "unable to allocate new LL device"); 1161 goto _exit3; 1162 } 1163 1164 if (ll_config.msix_enable && intr_types & DDI_INTR_TYPE_MSIX) { 1165 ll->intr_type = DDI_INTR_TYPE_MSIX; 1166 ll->intr_cnt = 1; 1167 for (i = 0; i < XGE_HAL_MAX_FIFO_NUM; i++) 1168 if (device_config->fifo.queue[i].configured) 1169 ll->intr_cnt++; 1170 for (i = 0; i < XGE_HAL_MAX_RING_NUM; i++) 1171 if (device_config->ring.queue[i].configured) 1172 ll->intr_cnt++; 1173 } else { 1174 ll->intr_type = DDI_INTR_TYPE_FIXED; 1175 ll->intr_cnt = 1; 1176 } 1177 1178 while ((ret = xge_alloc_intrs(ll)) != DDI_SUCCESS) { 1179 if (ll->intr_type == DDI_INTR_TYPE_MSIX) { 1180 ll_config.msix_enable = 0; 1181 ll->intr_type = DDI_INTR_TYPE_FIXED; 1182 ll->intr_cnt = 1; 1183 device_config->intr_mode = XGE_HAL_INTR_MODE_IRQLINE; 1184 xge_debug_osdep(XGE_TRACE, 1185 "Unable to allocate MSI-X handlers" 1186 " - defaulting to IRQA"); 1187 continue; 1188 } 1189 goto _exit3a; 1190 } 1191 1192 if (ll->intr_type == DDI_INTR_TYPE_MSIX) { 1193 device_config->intr_mode = XGE_HAL_INTR_MODE_MSIX; 1194 device_config->bimodal_interrupts = 0; 1195 } else { 1196 device_config->intr_mode = XGE_HAL_INTR_MODE_IRQLINE; 1197 } 1198 1199 attr.irqh = ll->intr_pri; 1200 1201 /* initialize HW */ 1202 status = xge_hal_device_initialize(hldev, &attr, device_config); 1203 if (status != XGE_HAL_OK) { 1204 switch (status) { 1205 case XGE_HAL_ERR_DRIVER_NOT_INITIALIZED: 1206 xge_debug_osdep(XGE_ERR, "%s", 1207 "driver is not initialized"); 1208 ret = DDI_FAILURE; 1209 goto _exit3b; 1210 case XGE_HAL_ERR_DEVICE_IS_NOT_QUIESCENT: 1211 xge_debug_osdep(XGE_ERR, "%s", 1212 "device is not quiescent"); 1213 ret = DDI_EBUSY; 1214 goto _exit3b; 1215 case XGE_HAL_ERR_OUT_OF_MEMORY: 1216 xge_debug_osdep(XGE_ERR, "%s", 1217 "unable to allocate memory"); 1218 ret = DDI_ENOMEM; 1219 goto _exit3b; 1220 default: 1221 xge_debug_osdep(XGE_ERR, 1222 "can't initialize the device: %d", status); 1223 ret = DDI_FAILURE; 1224 goto _exit3b; 1225 } 1226 } 1227 1228 /* register interrupt handler for handling xge device interrupts */ 1229 ret = xge_add_intrs(ll); 1230 if (ret != DDI_SUCCESS) 1231 goto _exit4; 1232 1233 /* allocate and register Link Layer */ 1234 ret = xgell_device_register(ll, &ll_config); 1235 if (ret != DDI_SUCCESS) { 1236 goto _exit5; 1237 } 1238 1239 /* store ll as a HAL private part */ 1240 xge_hal_device_private_set(hldev, ll); 1241 1242 kmem_free(device_config, sizeof (xge_hal_device_config_t)); 1243 1244 return (DDI_SUCCESS); 1245 1246 _exit5: 1247 xge_rem_intrs(ll); 1248 _exit4: 1249 xge_hal_device_terminate(hldev); 1250 _exit3b: 1251 xge_free_intrs(ll); 1252 _exit3a: 1253 xgell_device_free(ll); 1254 _exit3: 1255 pci_config_teardown(&attr.cfgh); 1256 _exit2a: 1257 kmem_free(hldev, sizeof (xge_hal_device_t)); 1258 _exit2: 1259 ddi_regs_map_free(&attr.regh2); 1260 _exit1a: 1261 ddi_regs_map_free(&attr.regh1); 1262 _exit1: 1263 ddi_regs_map_free(&attr.regh0); 1264 _exit0a: 1265 kmem_free(device_config, sizeof (xge_hal_device_config_t)); 1266 _exit0: 1267 return (ret); 1268 } 1269 1270 /* 1271 * quiesce(9E) entry point. 1272 * 1273 * This function is called when the system is single-threaded at high 1274 * PIL with preemption disabled. Therefore, this function must not be 1275 * blocked. 1276 * 1277 * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure. 1278 * DDI_FAILURE indicates an error condition and should almost never happen. 1279 */ 1280 static int 1281 xge_quiesce(dev_info_t *dev_info) 1282 { 1283 xge_hal_device_t *hldev = 1284 (xge_hal_device_t *)ddi_get_driver_private(dev_info); 1285 1286 xgelldev_t *lldev = xge_hal_device_private(hldev); 1287 1288 xge_hal_device_quiesce(hldev, lldev->devh); 1289 1290 return (DDI_SUCCESS); 1291 } 1292 1293 /* 1294 * xge_detach 1295 * @dev_info: pointer to dev_info_t structure 1296 * @cmd: attach command to process 1297 * 1298 * This function is called by OS when the system is about 1299 * to shutdown or when the super user tries to unload 1300 * the driver. This function frees all the memory allocated 1301 * during xge_attch() and also unregisters the Xframe 1302 * device instance from the GLD framework. 1303 */ 1304 static int 1305 xge_detach(dev_info_t *dev_info, ddi_detach_cmd_t cmd) 1306 { 1307 xge_hal_device_t *hldev; 1308 xge_hal_device_attr_t *attr; 1309 xgelldev_t *lldev; 1310 1311 xge_debug_osdep(XGE_TRACE, "XGE_DETACH cmd %d", cmd); 1312 1313 hldev = (xge_hal_device_t *)ddi_get_driver_private(dev_info); 1314 attr = xge_hal_device_attr(hldev); 1315 lldev = xge_hal_device_private(hldev); 1316 1317 switch (cmd) { 1318 case DDI_DETACH: 1319 break; 1320 1321 case DDI_PM_SUSPEND: 1322 xge_debug_osdep(XGE_ERR, "%s", "suspend unsupported yet"); 1323 return (DDI_FAILURE); 1324 1325 default: 1326 xge_debug_osdep(XGE_ERR, "cmd 0x%x unrecognized", cmd); 1327 return (DDI_FAILURE); 1328 } 1329 1330 if (lldev->is_initialized) { 1331 xge_debug_osdep(XGE_ERR, "%s", 1332 "can not detach: device is not unplumbed"); 1333 return (DDI_FAILURE); 1334 } 1335 1336 xge_hal_device_terminating(hldev); 1337 if (xgell_device_unregister(lldev) != DDI_SUCCESS) { 1338 return (DDI_FAILURE); 1339 } 1340 xge_hal_device_terminate(hldev); 1341 1342 xge_rem_intrs(lldev); 1343 xge_free_intrs(lldev); 1344 xgell_device_free(lldev); 1345 pci_config_teardown(&attr->cfgh); 1346 ddi_regs_map_free(&attr->regh2); 1347 ddi_regs_map_free(&attr->regh1); 1348 ddi_regs_map_free(&attr->regh0); 1349 kmem_free(hldev, sizeof (xge_hal_device_t)); 1350 1351 return (DDI_SUCCESS); 1352 } 1353