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