1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * Copyright 2012 Milan Jurik. All rights reserved. 25 * Copyright 2016 OmniTI Computer Consulting, Inc. All rights reserved. 26 */ 27 28 /* 29 * SunOs MT STREAMS Hydra 10Gb Ethernet Device Driver. 30 */ 31 #include <hxge_impl.h> 32 #include <hxge_pfc.h> 33 34 /* 35 * PSARC/2007/453 MSI-X interrupt limit override 36 * (This PSARC case is limited to MSI-X vectors 37 * and SPARC platforms only). 38 */ 39 uint32_t hxge_msi_enable = 2; 40 41 /* 42 * Globals: tunable parameters (/etc/system or adb) 43 * 44 */ 45 uint32_t hxge_rbr_size = HXGE_RBR_RBB_DEFAULT; 46 uint32_t hxge_rbr_spare_size = 0; 47 uint32_t hxge_rcr_size = HXGE_RCR_DEFAULT; 48 uint32_t hxge_tx_ring_size = HXGE_TX_RING_DEFAULT; 49 uint32_t hxge_bcopy_thresh = TX_BCOPY_MAX; 50 uint32_t hxge_dvma_thresh = TX_FASTDVMA_MIN; 51 uint32_t hxge_dma_stream_thresh = TX_STREAM_MIN; 52 uint32_t hxge_jumbo_frame_size = MAX_FRAME_SIZE; 53 54 static hxge_os_mutex_t hxgedebuglock; 55 static int hxge_debug_init = 0; 56 57 /* 58 * Debugging flags: 59 * hxge_no_tx_lb : transmit load balancing 60 * hxge_tx_lb_policy: 0 - TCP/UDP port (default) 61 * 1 - From the Stack 62 * 2 - Destination IP Address 63 */ 64 uint32_t hxge_no_tx_lb = 0; 65 uint32_t hxge_tx_lb_policy = HXGE_TX_LB_TCPUDP; 66 67 /* 68 * Tunables to manage the receive buffer blocks. 69 * 70 * hxge_rx_threshold_hi: copy all buffers. 71 * hxge_rx_bcopy_size_type: receive buffer block size type. 72 * hxge_rx_threshold_lo: copy only up to tunable block size type. 73 */ 74 #if defined(__sparc) 75 hxge_rxbuf_threshold_t hxge_rx_threshold_hi = HXGE_RX_COPY_6; 76 hxge_rxbuf_threshold_t hxge_rx_threshold_lo = HXGE_RX_COPY_4; 77 #else 78 hxge_rxbuf_threshold_t hxge_rx_threshold_hi = HXGE_RX_COPY_NONE; 79 hxge_rxbuf_threshold_t hxge_rx_threshold_lo = HXGE_RX_COPY_NONE; 80 #endif 81 hxge_rxbuf_type_t hxge_rx_buf_size_type = RCR_PKTBUFSZ_0; 82 83 rtrace_t hpi_rtracebuf; 84 85 /* 86 * Function Prototypes 87 */ 88 static int hxge_attach(dev_info_t *, ddi_attach_cmd_t); 89 static int hxge_detach(dev_info_t *, ddi_detach_cmd_t); 90 static void hxge_unattach(p_hxge_t); 91 92 static hxge_status_t hxge_setup_system_dma_pages(p_hxge_t); 93 94 static hxge_status_t hxge_setup_mutexes(p_hxge_t); 95 static void hxge_destroy_mutexes(p_hxge_t); 96 97 static hxge_status_t hxge_map_regs(p_hxge_t hxgep); 98 static void hxge_unmap_regs(p_hxge_t hxgep); 99 100 static hxge_status_t hxge_add_intrs(p_hxge_t hxgep); 101 static void hxge_remove_intrs(p_hxge_t hxgep); 102 static hxge_status_t hxge_add_intrs_adv(p_hxge_t hxgep); 103 static hxge_status_t hxge_add_intrs_adv_type(p_hxge_t, uint32_t); 104 static hxge_status_t hxge_add_intrs_adv_type_fix(p_hxge_t, uint32_t); 105 static void hxge_intrs_enable(p_hxge_t hxgep); 106 static void hxge_intrs_disable(p_hxge_t hxgep); 107 static void hxge_suspend(p_hxge_t); 108 static hxge_status_t hxge_resume(p_hxge_t); 109 static hxge_status_t hxge_setup_dev(p_hxge_t); 110 static void hxge_destroy_dev(p_hxge_t); 111 static hxge_status_t hxge_alloc_mem_pool(p_hxge_t); 112 static void hxge_free_mem_pool(p_hxge_t); 113 static hxge_status_t hxge_alloc_rx_mem_pool(p_hxge_t); 114 static void hxge_free_rx_mem_pool(p_hxge_t); 115 static hxge_status_t hxge_alloc_tx_mem_pool(p_hxge_t); 116 static void hxge_free_tx_mem_pool(p_hxge_t); 117 static hxge_status_t hxge_dma_mem_alloc(p_hxge_t, dma_method_t, 118 struct ddi_dma_attr *, size_t, ddi_device_acc_attr_t *, uint_t, 119 p_hxge_dma_common_t); 120 static void hxge_dma_mem_free(p_hxge_dma_common_t); 121 static hxge_status_t hxge_alloc_rx_buf_dma(p_hxge_t, uint16_t, 122 p_hxge_dma_common_t *, size_t, size_t, uint32_t *); 123 static void hxge_free_rx_buf_dma(p_hxge_t, p_hxge_dma_common_t, uint32_t); 124 static hxge_status_t hxge_alloc_rx_cntl_dma(p_hxge_t, uint16_t, 125 p_hxge_dma_common_t *, struct ddi_dma_attr *, size_t); 126 static void hxge_free_rx_cntl_dma(p_hxge_t, p_hxge_dma_common_t); 127 static hxge_status_t hxge_alloc_tx_buf_dma(p_hxge_t, uint16_t, 128 p_hxge_dma_common_t *, size_t, size_t, uint32_t *); 129 static void hxge_free_tx_buf_dma(p_hxge_t, p_hxge_dma_common_t, uint32_t); 130 static hxge_status_t hxge_alloc_tx_cntl_dma(p_hxge_t, uint16_t, 131 p_hxge_dma_common_t *, size_t); 132 static void hxge_free_tx_cntl_dma(p_hxge_t, p_hxge_dma_common_t); 133 static int hxge_init_common_dev(p_hxge_t); 134 static void hxge_uninit_common_dev(p_hxge_t); 135 136 /* 137 * The next declarations are for the GLDv3 interface. 138 */ 139 static int hxge_m_start(void *); 140 static void hxge_m_stop(void *); 141 static int hxge_m_multicst(void *, boolean_t, const uint8_t *); 142 static int hxge_m_promisc(void *, boolean_t); 143 static void hxge_m_ioctl(void *, queue_t *, mblk_t *); 144 static hxge_status_t hxge_mac_register(p_hxge_t hxgep); 145 146 static boolean_t hxge_m_getcapab(void *, mac_capab_t, void *); 147 static boolean_t hxge_param_locked(mac_prop_id_t pr_num); 148 static int hxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 149 uint_t pr_valsize, const void *pr_val); 150 static int hxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 151 uint_t pr_valsize, void *pr_val); 152 static void hxge_m_propinfo(void *barg, const char *pr_name, 153 mac_prop_id_t pr_num, mac_prop_info_handle_t mph); 154 static int hxge_set_priv_prop(p_hxge_t hxgep, const char *pr_name, 155 uint_t pr_valsize, const void *pr_val); 156 static int hxge_get_priv_prop(p_hxge_t hxgep, const char *pr_name, 157 uint_t pr_valsize, void *pr_val); 158 static void hxge_link_poll(void *arg); 159 static void hxge_link_update(p_hxge_t hxge, link_state_t state); 160 static void hxge_msix_init(p_hxge_t hxgep); 161 162 char *hxge_priv_props[] = { 163 "_rxdma_intr_time", 164 "_rxdma_intr_pkts", 165 "_class_opt_ipv4_tcp", 166 "_class_opt_ipv4_udp", 167 "_class_opt_ipv4_ah", 168 "_class_opt_ipv4_sctp", 169 "_class_opt_ipv6_tcp", 170 "_class_opt_ipv6_udp", 171 "_class_opt_ipv6_ah", 172 "_class_opt_ipv6_sctp", 173 NULL 174 }; 175 176 #define HXGE_MAX_PRIV_PROPS \ 177 (sizeof (hxge_priv_props)/sizeof (mac_priv_prop_t)) 178 179 #define HXGE_MAGIC 0x4E584745UL 180 #define MAX_DUMP_SZ 256 181 182 #define HXGE_M_CALLBACK_FLAGS \ 183 (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP | MC_PROPINFO) 184 185 extern hxge_status_t hxge_pfc_set_default_mac_addr(p_hxge_t hxgep); 186 187 static mac_callbacks_t hxge_m_callbacks = { 188 HXGE_M_CALLBACK_FLAGS, 189 hxge_m_stat, 190 hxge_m_start, 191 hxge_m_stop, 192 hxge_m_promisc, 193 hxge_m_multicst, 194 NULL, 195 NULL, 196 NULL, 197 hxge_m_ioctl, 198 hxge_m_getcapab, 199 NULL, 200 NULL, 201 hxge_m_setprop, 202 hxge_m_getprop, 203 hxge_m_propinfo 204 }; 205 206 /* PSARC/2007/453 MSI-X interrupt limit override. */ 207 #define HXGE_MSIX_REQUEST_10G 8 208 static int hxge_create_msi_property(p_hxge_t); 209 210 /* Enable debug messages as necessary. */ 211 uint64_t hxge_debug_level = 0; 212 213 /* 214 * This list contains the instance structures for the Hydra 215 * devices present in the system. The lock exists to guarantee 216 * mutually exclusive access to the list. 217 */ 218 void *hxge_list = NULL; 219 void *hxge_hw_list = NULL; 220 hxge_os_mutex_t hxge_common_lock; 221 222 extern uint64_t hpi_debug_level; 223 224 extern hxge_status_t hxge_ldgv_init(p_hxge_t, int *, int *); 225 extern hxge_status_t hxge_ldgv_uninit(p_hxge_t); 226 extern hxge_status_t hxge_intr_ldgv_init(p_hxge_t); 227 extern void hxge_fm_init(p_hxge_t hxgep, ddi_device_acc_attr_t *reg_attr, 228 ddi_device_acc_attr_t *desc_attr, ddi_dma_attr_t *dma_attr); 229 extern void hxge_fm_fini(p_hxge_t hxgep); 230 231 /* 232 * Count used to maintain the number of buffers being used 233 * by Hydra instances and loaned up to the upper layers. 234 */ 235 uint32_t hxge_mblks_pending = 0; 236 237 /* 238 * Device register access attributes for PIO. 239 */ 240 static ddi_device_acc_attr_t hxge_dev_reg_acc_attr = { 241 DDI_DEVICE_ATTR_V0, 242 DDI_STRUCTURE_LE_ACC, 243 DDI_STRICTORDER_ACC, 244 }; 245 246 /* 247 * Device descriptor access attributes for DMA. 248 */ 249 static ddi_device_acc_attr_t hxge_dev_desc_dma_acc_attr = { 250 DDI_DEVICE_ATTR_V0, 251 DDI_STRUCTURE_LE_ACC, 252 DDI_STRICTORDER_ACC 253 }; 254 255 /* 256 * Device buffer access attributes for DMA. 257 */ 258 static ddi_device_acc_attr_t hxge_dev_buf_dma_acc_attr = { 259 DDI_DEVICE_ATTR_V0, 260 DDI_STRUCTURE_BE_ACC, 261 DDI_STRICTORDER_ACC 262 }; 263 264 ddi_dma_attr_t hxge_rx_rcr_desc_dma_attr = { 265 DMA_ATTR_V0, /* version number. */ 266 0, /* low address */ 267 0xffffffffffffffff, /* high address */ 268 0xffffffffffffffff, /* address counter max */ 269 0x80000, /* alignment */ 270 0xfc00fc, /* dlim_burstsizes */ 271 0x1, /* minimum transfer size */ 272 0xffffffffffffffff, /* maximum transfer size */ 273 0xffffffffffffffff, /* maximum segment size */ 274 1, /* scatter/gather list length */ 275 (unsigned int)1, /* granularity */ 276 0 /* attribute flags */ 277 }; 278 279 ddi_dma_attr_t hxge_tx_desc_dma_attr = { 280 DMA_ATTR_V0, /* version number. */ 281 0, /* low address */ 282 0xffffffffffffffff, /* high address */ 283 0xffffffffffffffff, /* address counter max */ 284 0x100000, /* alignment */ 285 0xfc00fc, /* dlim_burstsizes */ 286 0x1, /* minimum transfer size */ 287 0xffffffffffffffff, /* maximum transfer size */ 288 0xffffffffffffffff, /* maximum segment size */ 289 1, /* scatter/gather list length */ 290 (unsigned int)1, /* granularity */ 291 0 /* attribute flags */ 292 }; 293 294 ddi_dma_attr_t hxge_rx_rbr_desc_dma_attr = { 295 DMA_ATTR_V0, /* version number. */ 296 0, /* low address */ 297 0xffffffffffffffff, /* high address */ 298 0xffffffffffffffff, /* address counter max */ 299 0x40000, /* alignment */ 300 0xfc00fc, /* dlim_burstsizes */ 301 0x1, /* minimum transfer size */ 302 0xffffffffffffffff, /* maximum transfer size */ 303 0xffffffffffffffff, /* maximum segment size */ 304 1, /* scatter/gather list length */ 305 (unsigned int)1, /* granularity */ 306 0 /* attribute flags */ 307 }; 308 309 ddi_dma_attr_t hxge_rx_mbox_dma_attr = { 310 DMA_ATTR_V0, /* version number. */ 311 0, /* low address */ 312 0xffffffffffffffff, /* high address */ 313 0xffffffffffffffff, /* address counter max */ 314 #if defined(_BIG_ENDIAN) 315 0x2000, /* alignment */ 316 #else 317 0x1000, /* alignment */ 318 #endif 319 0xfc00fc, /* dlim_burstsizes */ 320 0x1, /* minimum transfer size */ 321 0xffffffffffffffff, /* maximum transfer size */ 322 0xffffffffffffffff, /* maximum segment size */ 323 5, /* scatter/gather list length */ 324 (unsigned int)1, /* granularity */ 325 0 /* attribute flags */ 326 }; 327 328 ddi_dma_attr_t hxge_tx_dma_attr = { 329 DMA_ATTR_V0, /* version number. */ 330 0, /* low address */ 331 0xffffffffffffffff, /* high address */ 332 0xffffffffffffffff, /* address counter max */ 333 #if defined(_BIG_ENDIAN) 334 0x2000, /* alignment */ 335 #else 336 0x1000, /* alignment */ 337 #endif 338 0xfc00fc, /* dlim_burstsizes */ 339 0x1, /* minimum transfer size */ 340 0xffffffffffffffff, /* maximum transfer size */ 341 0xffffffffffffffff, /* maximum segment size */ 342 5, /* scatter/gather list length */ 343 (unsigned int)1, /* granularity */ 344 0 /* attribute flags */ 345 }; 346 347 ddi_dma_attr_t hxge_rx_dma_attr = { 348 DMA_ATTR_V0, /* version number. */ 349 0, /* low address */ 350 0xffffffffffffffff, /* high address */ 351 0xffffffffffffffff, /* address counter max */ 352 0x10000, /* alignment */ 353 0xfc00fc, /* dlim_burstsizes */ 354 0x1, /* minimum transfer size */ 355 0xffffffffffffffff, /* maximum transfer size */ 356 0xffffffffffffffff, /* maximum segment size */ 357 1, /* scatter/gather list length */ 358 (unsigned int)1, /* granularity */ 359 DDI_DMA_RELAXED_ORDERING /* attribute flags */ 360 }; 361 362 ddi_dma_lim_t hxge_dma_limits = { 363 (uint_t)0, /* dlim_addr_lo */ 364 (uint_t)0xffffffff, /* dlim_addr_hi */ 365 (uint_t)0xffffffff, /* dlim_cntr_max */ 366 (uint_t)0xfc00fc, /* dlim_burstsizes for 32 and 64 bit xfers */ 367 0x1, /* dlim_minxfer */ 368 1024 /* dlim_speed */ 369 }; 370 371 dma_method_t hxge_force_dma = DVMA; 372 373 /* 374 * dma chunk sizes. 375 * 376 * Try to allocate the largest possible size 377 * so that fewer number of dma chunks would be managed 378 */ 379 size_t alloc_sizes[] = { 380 0x1000, 0x2000, 0x4000, 0x8000, 381 0x10000, 0x20000, 0x40000, 0x80000, 382 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000 383 }; 384 385 /* 386 * Translate "dev_t" to a pointer to the associated "dev_info_t". 387 */ 388 static int 389 hxge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 390 { 391 p_hxge_t hxgep = NULL; 392 int instance; 393 int status = DDI_SUCCESS; 394 int i; 395 396 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_attach")); 397 398 /* 399 * Get the device instance since we'll need to setup or retrieve a soft 400 * state for this instance. 401 */ 402 instance = ddi_get_instance(dip); 403 404 switch (cmd) { 405 case DDI_ATTACH: 406 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_ATTACH")); 407 break; 408 409 case DDI_RESUME: 410 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_RESUME")); 411 hxgep = (p_hxge_t)ddi_get_soft_state(hxge_list, instance); 412 if (hxgep == NULL) { 413 status = DDI_FAILURE; 414 break; 415 } 416 if (hxgep->dip != dip) { 417 status = DDI_FAILURE; 418 break; 419 } 420 if (hxgep->suspended == DDI_PM_SUSPEND) { 421 status = ddi_dev_is_needed(hxgep->dip, 0, 1); 422 } else { 423 (void) hxge_resume(hxgep); 424 } 425 goto hxge_attach_exit; 426 427 case DDI_PM_RESUME: 428 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_PM_RESUME")); 429 hxgep = (p_hxge_t)ddi_get_soft_state(hxge_list, instance); 430 if (hxgep == NULL) { 431 status = DDI_FAILURE; 432 break; 433 } 434 if (hxgep->dip != dip) { 435 status = DDI_FAILURE; 436 break; 437 } 438 (void) hxge_resume(hxgep); 439 goto hxge_attach_exit; 440 441 default: 442 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing unknown")); 443 status = DDI_FAILURE; 444 goto hxge_attach_exit; 445 } 446 447 if (ddi_soft_state_zalloc(hxge_list, instance) == DDI_FAILURE) { 448 status = DDI_FAILURE; 449 HXGE_ERROR_MSG((hxgep, DDI_CTL, 450 "ddi_soft_state_zalloc failed")); 451 goto hxge_attach_exit; 452 } 453 454 hxgep = ddi_get_soft_state(hxge_list, instance); 455 if (hxgep == NULL) { 456 status = HXGE_ERROR; 457 HXGE_ERROR_MSG((hxgep, DDI_CTL, 458 "ddi_get_soft_state failed")); 459 goto hxge_attach_fail2; 460 } 461 462 hxgep->drv_state = 0; 463 hxgep->dip = dip; 464 hxgep->instance = instance; 465 hxgep->p_dip = ddi_get_parent(dip); 466 hxgep->hxge_debug_level = hxge_debug_level; 467 hpi_debug_level = hxge_debug_level; 468 469 /* 470 * Initialize MMAC struture. 471 */ 472 (void) hxge_pfc_num_macs_get(hxgep, &hxgep->mmac.total); 473 hxgep->mmac.available = hxgep->mmac.total; 474 for (i = 0; i < hxgep->mmac.total; i++) { 475 hxgep->mmac.addrs[i].set = B_FALSE; 476 hxgep->mmac.addrs[i].primary = B_FALSE; 477 } 478 479 hxge_fm_init(hxgep, &hxge_dev_reg_acc_attr, &hxge_dev_desc_dma_acc_attr, 480 &hxge_rx_dma_attr); 481 482 status = hxge_map_regs(hxgep); 483 if (status != HXGE_OK) { 484 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "hxge_map_regs failed")); 485 goto hxge_attach_fail3; 486 } 487 488 status = hxge_init_common_dev(hxgep); 489 if (status != HXGE_OK) { 490 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 491 "hxge_init_common_dev failed")); 492 goto hxge_attach_fail4; 493 } 494 495 /* 496 * Setup the Ndd parameters for this instance. 497 */ 498 hxge_init_param(hxgep); 499 500 /* 501 * Setup Register Tracing Buffer. 502 */ 503 hpi_rtrace_buf_init((rtrace_t *)&hpi_rtracebuf); 504 505 /* init stats ptr */ 506 hxge_init_statsp(hxgep); 507 508 status = hxge_setup_mutexes(hxgep); 509 if (status != HXGE_OK) { 510 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "set mutex failed")); 511 goto hxge_attach_fail; 512 } 513 514 /* Scrub the MSI-X memory */ 515 hxge_msix_init(hxgep); 516 517 status = hxge_get_config_properties(hxgep); 518 if (status != HXGE_OK) { 519 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "get_hw create failed")); 520 goto hxge_attach_fail; 521 } 522 523 /* 524 * Setup the Kstats for the driver. 525 */ 526 hxge_setup_kstats(hxgep); 527 hxge_setup_param(hxgep); 528 529 status = hxge_setup_system_dma_pages(hxgep); 530 if (status != HXGE_OK) { 531 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "set dma page failed")); 532 goto hxge_attach_fail; 533 } 534 535 hxge_hw_id_init(hxgep); 536 hxge_hw_init_niu_common(hxgep); 537 538 status = hxge_setup_dev(hxgep); 539 if (status != DDI_SUCCESS) { 540 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "set dev failed")); 541 goto hxge_attach_fail; 542 } 543 544 status = hxge_add_intrs(hxgep); 545 if (status != DDI_SUCCESS) { 546 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "add_intr failed")); 547 goto hxge_attach_fail; 548 } 549 550 /* 551 * Enable interrupts. 552 */ 553 hxge_intrs_enable(hxgep); 554 555 if ((status = hxge_mac_register(hxgep)) != HXGE_OK) { 556 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 557 "unable to register to mac layer (%d)", status)); 558 goto hxge_attach_fail; 559 } 560 mac_link_update(hxgep->mach, LINK_STATE_UNKNOWN); 561 562 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "registered to mac (instance %d)", 563 instance)); 564 565 goto hxge_attach_exit; 566 567 hxge_attach_fail: 568 hxge_unattach(hxgep); 569 goto hxge_attach_fail1; 570 571 hxge_attach_fail4: 572 if (hxgep->hxge_hw_p) { 573 hxge_uninit_common_dev(hxgep); 574 hxgep->hxge_hw_p = NULL; 575 } 576 hxge_attach_fail3: 577 /* 578 * Unmap the register setup. 579 */ 580 hxge_unmap_regs(hxgep); 581 582 hxge_fm_fini(hxgep); 583 584 hxge_attach_fail2: 585 ddi_soft_state_free(hxge_list, hxgep->instance); 586 587 hxge_attach_fail1: 588 if (status != HXGE_OK) 589 status = (HXGE_ERROR | HXGE_DDI_FAILED); 590 hxgep = NULL; 591 592 hxge_attach_exit: 593 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_attach status = 0x%08x", 594 status)); 595 596 return (status); 597 } 598 599 static int 600 hxge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 601 { 602 int status = DDI_SUCCESS; 603 int instance; 604 p_hxge_t hxgep = NULL; 605 606 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_detach")); 607 instance = ddi_get_instance(dip); 608 hxgep = ddi_get_soft_state(hxge_list, instance); 609 if (hxgep == NULL) { 610 status = DDI_FAILURE; 611 goto hxge_detach_exit; 612 } 613 614 switch (cmd) { 615 case DDI_DETACH: 616 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_DETACH")); 617 break; 618 619 case DDI_PM_SUSPEND: 620 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_PM_SUSPEND")); 621 hxgep->suspended = DDI_PM_SUSPEND; 622 hxge_suspend(hxgep); 623 break; 624 625 case DDI_SUSPEND: 626 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "doing DDI_SUSPEND")); 627 if (hxgep->suspended != DDI_PM_SUSPEND) { 628 hxgep->suspended = DDI_SUSPEND; 629 hxge_suspend(hxgep); 630 } 631 break; 632 633 default: 634 status = DDI_FAILURE; 635 break; 636 } 637 638 if (cmd != DDI_DETACH) 639 goto hxge_detach_exit; 640 641 /* 642 * Stop the xcvr polling. 643 */ 644 hxgep->suspended = cmd; 645 646 if (hxgep->mach && (status = mac_unregister(hxgep->mach)) != 0) { 647 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 648 "<== hxge_detach status = 0x%08X", status)); 649 return (DDI_FAILURE); 650 } 651 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 652 "<== hxge_detach (mac_unregister) status = 0x%08X", status)); 653 654 hxge_unattach(hxgep); 655 hxgep = NULL; 656 657 hxge_detach_exit: 658 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_detach status = 0x%08X", 659 status)); 660 661 return (status); 662 } 663 664 static void 665 hxge_unattach(p_hxge_t hxgep) 666 { 667 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_unattach")); 668 669 if (hxgep == NULL || hxgep->dev_regs == NULL) { 670 return; 671 } 672 673 if (hxgep->hxge_hw_p) { 674 hxge_uninit_common_dev(hxgep); 675 hxgep->hxge_hw_p = NULL; 676 } 677 678 if (hxgep->hxge_timerid) { 679 hxge_stop_timer(hxgep, hxgep->hxge_timerid); 680 hxgep->hxge_timerid = 0; 681 } 682 683 /* Stop interrupts. */ 684 hxge_intrs_disable(hxgep); 685 686 /* Stop any further interrupts. */ 687 hxge_remove_intrs(hxgep); 688 689 /* Stop the device and free resources. */ 690 hxge_destroy_dev(hxgep); 691 692 /* Tear down the ndd parameters setup. */ 693 hxge_destroy_param(hxgep); 694 695 /* Tear down the kstat setup. */ 696 hxge_destroy_kstats(hxgep); 697 698 /* 699 * Remove the list of ndd parameters which were setup during attach. 700 */ 701 if (hxgep->dip) { 702 HXGE_DEBUG_MSG((hxgep, OBP_CTL, 703 " hxge_unattach: remove all properties")); 704 (void) ddi_prop_remove_all(hxgep->dip); 705 } 706 707 /* 708 * Reset RDC, TDC, PFC, and VMAC blocks from PEU to clear any 709 * previous state before unmapping the registers. 710 */ 711 HXGE_REG_WR32(hxgep->hpi_handle, BLOCK_RESET, 0x0000001E); 712 HXGE_DELAY(1000); 713 714 /* 715 * Unmap the register setup. 716 */ 717 hxge_unmap_regs(hxgep); 718 719 hxge_fm_fini(hxgep); 720 721 /* Destroy all mutexes. */ 722 hxge_destroy_mutexes(hxgep); 723 724 /* 725 * Free the soft state data structures allocated with this instance. 726 */ 727 ddi_soft_state_free(hxge_list, hxgep->instance); 728 729 HXGE_DEBUG_MSG((NULL, DDI_CTL, "<== hxge_unattach")); 730 } 731 732 static hxge_status_t 733 hxge_map_regs(p_hxge_t hxgep) 734 { 735 int ddi_status = DDI_SUCCESS; 736 p_dev_regs_t dev_regs; 737 738 #ifdef HXGE_DEBUG 739 char *sysname; 740 #endif 741 742 off_t regsize; 743 hxge_status_t status = HXGE_OK; 744 int nregs; 745 746 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_map_regs")); 747 748 if (ddi_dev_nregs(hxgep->dip, &nregs) != DDI_SUCCESS) 749 return (HXGE_ERROR); 750 751 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "hxge_map_regs: nregs: %d", nregs)); 752 753 hxgep->dev_regs = NULL; 754 dev_regs = KMEM_ZALLOC(sizeof (dev_regs_t), KM_SLEEP); 755 dev_regs->hxge_regh = NULL; 756 dev_regs->hxge_pciregh = NULL; 757 dev_regs->hxge_msix_regh = NULL; 758 759 (void) ddi_dev_regsize(hxgep->dip, 0, ®size); 760 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 761 "hxge_map_regs: pci config size 0x%x", regsize)); 762 763 ddi_status = ddi_regs_map_setup(hxgep->dip, 0, 764 (caddr_t *)&(dev_regs->hxge_pciregp), 0, 0, 765 &hxge_dev_reg_acc_attr, &dev_regs->hxge_pciregh); 766 if (ddi_status != DDI_SUCCESS) { 767 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 768 "ddi_map_regs, hxge bus config regs failed")); 769 goto hxge_map_regs_fail0; 770 } 771 772 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 773 "hxge_map_reg: PCI config addr 0x%0llx handle 0x%0llx", 774 dev_regs->hxge_pciregp, 775 dev_regs->hxge_pciregh)); 776 777 (void) ddi_dev_regsize(hxgep->dip, 1, ®size); 778 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 779 "hxge_map_regs: pio size 0x%x", regsize)); 780 781 /* set up the device mapped register */ 782 ddi_status = ddi_regs_map_setup(hxgep->dip, 1, 783 (caddr_t *)&(dev_regs->hxge_regp), 0, 0, 784 &hxge_dev_reg_acc_attr, &dev_regs->hxge_regh); 785 786 if (ddi_status != DDI_SUCCESS) { 787 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 788 "ddi_map_regs for Hydra global reg failed")); 789 goto hxge_map_regs_fail1; 790 } 791 792 /* set up the msi/msi-x mapped register */ 793 (void) ddi_dev_regsize(hxgep->dip, 2, ®size); 794 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 795 "hxge_map_regs: msix size 0x%x", regsize)); 796 797 ddi_status = ddi_regs_map_setup(hxgep->dip, 2, 798 (caddr_t *)&(dev_regs->hxge_msix_regp), 0, 0, 799 &hxge_dev_reg_acc_attr, &dev_regs->hxge_msix_regh); 800 801 if (ddi_status != DDI_SUCCESS) { 802 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 803 "ddi_map_regs for msi reg failed")); 804 goto hxge_map_regs_fail2; 805 } 806 807 hxgep->dev_regs = dev_regs; 808 809 HPI_PCI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_pciregh); 810 HPI_PCI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_pciregp); 811 HPI_MSI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_msix_regh); 812 HPI_MSI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_msix_regp); 813 814 HPI_ACC_HANDLE_SET(hxgep, dev_regs->hxge_regh); 815 HPI_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_regp); 816 817 HPI_REG_ACC_HANDLE_SET(hxgep, dev_regs->hxge_regh); 818 HPI_REG_ADD_HANDLE_SET(hxgep, (hpi_reg_ptr_t)dev_regs->hxge_regp); 819 820 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "hxge_map_reg: hardware addr 0x%0llx " 821 " handle 0x%0llx", dev_regs->hxge_regp, dev_regs->hxge_regh)); 822 823 goto hxge_map_regs_exit; 824 825 hxge_map_regs_fail2: 826 if (dev_regs->hxge_regh) { 827 ddi_regs_map_free(&dev_regs->hxge_regh); 828 } 829 830 hxge_map_regs_fail1: 831 if (dev_regs->hxge_pciregh) { 832 ddi_regs_map_free(&dev_regs->hxge_pciregh); 833 } 834 835 hxge_map_regs_fail0: 836 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "Freeing register set memory")); 837 kmem_free(dev_regs, sizeof (dev_regs_t)); 838 839 hxge_map_regs_exit: 840 if (ddi_status != DDI_SUCCESS) 841 status |= (HXGE_ERROR | HXGE_DDI_FAILED); 842 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_map_regs")); 843 return (status); 844 } 845 846 static void 847 hxge_unmap_regs(p_hxge_t hxgep) 848 { 849 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_unmap_regs")); 850 if (hxgep->dev_regs) { 851 if (hxgep->dev_regs->hxge_pciregh) { 852 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 853 "==> hxge_unmap_regs: bus")); 854 ddi_regs_map_free(&hxgep->dev_regs->hxge_pciregh); 855 hxgep->dev_regs->hxge_pciregh = NULL; 856 } 857 858 if (hxgep->dev_regs->hxge_regh) { 859 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 860 "==> hxge_unmap_regs: device registers")); 861 ddi_regs_map_free(&hxgep->dev_regs->hxge_regh); 862 hxgep->dev_regs->hxge_regh = NULL; 863 } 864 865 if (hxgep->dev_regs->hxge_msix_regh) { 866 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 867 "==> hxge_unmap_regs: device interrupts")); 868 ddi_regs_map_free(&hxgep->dev_regs->hxge_msix_regh); 869 hxgep->dev_regs->hxge_msix_regh = NULL; 870 } 871 kmem_free(hxgep->dev_regs, sizeof (dev_regs_t)); 872 hxgep->dev_regs = NULL; 873 } 874 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_unmap_regs")); 875 } 876 877 static hxge_status_t 878 hxge_setup_mutexes(p_hxge_t hxgep) 879 { 880 int ddi_status = DDI_SUCCESS; 881 hxge_status_t status = HXGE_OK; 882 883 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_mutexes")); 884 885 /* 886 * Get the interrupt cookie so the mutexes can be Initialised. 887 */ 888 ddi_status = ddi_get_iblock_cookie(hxgep->dip, 0, 889 &hxgep->interrupt_cookie); 890 891 if (ddi_status != DDI_SUCCESS) { 892 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 893 "<== hxge_setup_mutexes: failed 0x%x", ddi_status)); 894 goto hxge_setup_mutexes_exit; 895 } 896 897 /* 898 * Initialize mutex's for this device. 899 */ 900 MUTEX_INIT(hxgep->genlock, NULL, 901 MUTEX_DRIVER, (void *) hxgep->interrupt_cookie); 902 MUTEX_INIT(&hxgep->vmac_lock, NULL, 903 MUTEX_DRIVER, (void *) hxgep->interrupt_cookie); 904 MUTEX_INIT(&hxgep->ouraddr_lock, NULL, 905 MUTEX_DRIVER, (void *) hxgep->interrupt_cookie); 906 RW_INIT(&hxgep->filter_lock, NULL, 907 RW_DRIVER, (void *) hxgep->interrupt_cookie); 908 MUTEX_INIT(&hxgep->pio_lock, NULL, 909 MUTEX_DRIVER, (void *) hxgep->interrupt_cookie); 910 MUTEX_INIT(&hxgep->timeout.lock, NULL, 911 MUTEX_DRIVER, (void *) hxgep->interrupt_cookie); 912 913 hxge_setup_mutexes_exit: 914 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 915 "<== hxge_setup_mutexes status = %x", status)); 916 917 if (ddi_status != DDI_SUCCESS) 918 status |= (HXGE_ERROR | HXGE_DDI_FAILED); 919 920 return (status); 921 } 922 923 static void 924 hxge_destroy_mutexes(p_hxge_t hxgep) 925 { 926 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_destroy_mutexes")); 927 RW_DESTROY(&hxgep->filter_lock); 928 MUTEX_DESTROY(&hxgep->vmac_lock); 929 MUTEX_DESTROY(&hxgep->ouraddr_lock); 930 MUTEX_DESTROY(hxgep->genlock); 931 MUTEX_DESTROY(&hxgep->pio_lock); 932 MUTEX_DESTROY(&hxgep->timeout.lock); 933 934 if (hxge_debug_init == 1) { 935 MUTEX_DESTROY(&hxgedebuglock); 936 hxge_debug_init = 0; 937 } 938 939 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_destroy_mutexes")); 940 } 941 942 hxge_status_t 943 hxge_init(p_hxge_t hxgep) 944 { 945 hxge_status_t status = HXGE_OK; 946 947 HXGE_DEBUG_MSG((hxgep, STR_CTL, "==> hxge_init")); 948 949 if (hxgep->drv_state & STATE_HW_INITIALIZED) { 950 return (status); 951 } 952 953 /* 954 * Allocate system memory for the receive/transmit buffer blocks and 955 * receive/transmit descriptor rings. 956 */ 957 status = hxge_alloc_mem_pool(hxgep); 958 if (status != HXGE_OK) { 959 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "alloc mem failed\n")); 960 goto hxge_init_fail1; 961 } 962 963 /* 964 * Initialize and enable TXDMA channels. 965 */ 966 status = hxge_init_txdma_channels(hxgep); 967 if (status != HXGE_OK) { 968 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init txdma failed\n")); 969 goto hxge_init_fail3; 970 } 971 972 /* 973 * Initialize and enable RXDMA channels. 974 */ 975 status = hxge_init_rxdma_channels(hxgep); 976 if (status != HXGE_OK) { 977 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init rxdma failed\n")); 978 goto hxge_init_fail4; 979 } 980 981 /* 982 * Initialize TCAM 983 */ 984 status = hxge_classify_init(hxgep); 985 if (status != HXGE_OK) { 986 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init classify failed\n")); 987 goto hxge_init_fail5; 988 } 989 990 /* 991 * Initialize the VMAC block. 992 */ 993 status = hxge_vmac_init(hxgep); 994 if (status != HXGE_OK) { 995 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "init MAC failed\n")); 996 goto hxge_init_fail5; 997 } 998 999 /* Bringup - this may be unnecessary when PXE and FCODE available */ 1000 status = hxge_pfc_set_default_mac_addr(hxgep); 1001 if (status != HXGE_OK) { 1002 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 1003 "Default Address Failure\n")); 1004 goto hxge_init_fail5; 1005 } 1006 1007 /* 1008 * Enable hardware interrupts. 1009 */ 1010 hxge_intr_hw_enable(hxgep); 1011 hxgep->drv_state |= STATE_HW_INITIALIZED; 1012 1013 goto hxge_init_exit; 1014 1015 hxge_init_fail5: 1016 hxge_uninit_rxdma_channels(hxgep); 1017 hxge_init_fail4: 1018 hxge_uninit_txdma_channels(hxgep); 1019 hxge_init_fail3: 1020 hxge_free_mem_pool(hxgep); 1021 hxge_init_fail1: 1022 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 1023 "<== hxge_init status (failed) = 0x%08x", status)); 1024 return (status); 1025 1026 hxge_init_exit: 1027 1028 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_init status = 0x%08x", 1029 status)); 1030 1031 return (status); 1032 } 1033 1034 timeout_id_t 1035 hxge_start_timer(p_hxge_t hxgep, fptrv_t func, int msec) 1036 { 1037 if ((hxgep->suspended == 0) || (hxgep->suspended == DDI_RESUME)) { 1038 return (timeout(func, (caddr_t)hxgep, 1039 drv_usectohz(1000 * msec))); 1040 } 1041 return (NULL); 1042 } 1043 1044 /*ARGSUSED*/ 1045 void 1046 hxge_stop_timer(p_hxge_t hxgep, timeout_id_t timerid) 1047 { 1048 if (timerid) { 1049 (void) untimeout(timerid); 1050 } 1051 } 1052 1053 void 1054 hxge_uninit(p_hxge_t hxgep) 1055 { 1056 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_uninit")); 1057 1058 if (!(hxgep->drv_state & STATE_HW_INITIALIZED)) { 1059 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 1060 "==> hxge_uninit: not initialized")); 1061 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_uninit")); 1062 return; 1063 } 1064 1065 /* Stop timer */ 1066 if (hxgep->hxge_timerid) { 1067 hxge_stop_timer(hxgep, hxgep->hxge_timerid); 1068 hxgep->hxge_timerid = 0; 1069 } 1070 1071 (void) hxge_intr_hw_disable(hxgep); 1072 1073 /* Reset the receive VMAC side. */ 1074 (void) hxge_rx_vmac_disable(hxgep); 1075 1076 /* Free classification resources */ 1077 (void) hxge_classify_uninit(hxgep); 1078 1079 /* Reset the transmit/receive DMA side. */ 1080 (void) hxge_txdma_hw_mode(hxgep, HXGE_DMA_STOP); 1081 (void) hxge_rxdma_hw_mode(hxgep, HXGE_DMA_STOP); 1082 1083 hxge_uninit_txdma_channels(hxgep); 1084 hxge_uninit_rxdma_channels(hxgep); 1085 1086 /* Reset the transmit VMAC side. */ 1087 (void) hxge_tx_vmac_disable(hxgep); 1088 1089 hxge_free_mem_pool(hxgep); 1090 1091 hxgep->drv_state &= ~STATE_HW_INITIALIZED; 1092 1093 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_uninit")); 1094 } 1095 1096 /*ARGSUSED*/ 1097 /*VARARGS*/ 1098 void 1099 hxge_debug_msg(p_hxge_t hxgep, uint64_t level, char *fmt, ...) 1100 { 1101 char msg_buffer[1048]; 1102 char prefix_buffer[32]; 1103 int instance; 1104 uint64_t debug_level; 1105 int cmn_level = CE_CONT; 1106 va_list ap; 1107 1108 debug_level = (hxgep == NULL) ? hxge_debug_level : 1109 hxgep->hxge_debug_level; 1110 1111 if ((level & debug_level) || (level == HXGE_NOTE) || 1112 (level == HXGE_ERR_CTL)) { 1113 /* do the msg processing */ 1114 if (hxge_debug_init == 0) { 1115 MUTEX_INIT(&hxgedebuglock, NULL, MUTEX_DRIVER, NULL); 1116 hxge_debug_init = 1; 1117 } 1118 1119 MUTEX_ENTER(&hxgedebuglock); 1120 1121 if ((level & HXGE_NOTE)) { 1122 cmn_level = CE_NOTE; 1123 } 1124 1125 if (level & HXGE_ERR_CTL) { 1126 cmn_level = CE_WARN; 1127 } 1128 1129 va_start(ap, fmt); 1130 (void) vsprintf(msg_buffer, fmt, ap); 1131 va_end(ap); 1132 1133 if (hxgep == NULL) { 1134 instance = -1; 1135 (void) sprintf(prefix_buffer, "%s :", "hxge"); 1136 } else { 1137 instance = hxgep->instance; 1138 (void) sprintf(prefix_buffer, 1139 "%s%d :", "hxge", instance); 1140 } 1141 1142 MUTEX_EXIT(&hxgedebuglock); 1143 cmn_err(cmn_level, "%s %s\n", prefix_buffer, msg_buffer); 1144 } 1145 } 1146 1147 char * 1148 hxge_dump_packet(char *addr, int size) 1149 { 1150 uchar_t *ap = (uchar_t *)addr; 1151 int i; 1152 static char etherbuf[1024]; 1153 char *cp = etherbuf; 1154 char digits[] = "0123456789abcdef"; 1155 1156 if (!size) 1157 size = 60; 1158 1159 if (size > MAX_DUMP_SZ) { 1160 /* Dump the leading bytes */ 1161 for (i = 0; i < MAX_DUMP_SZ / 2; i++) { 1162 if (*ap > 0x0f) 1163 *cp++ = digits[*ap >> 4]; 1164 *cp++ = digits[*ap++ & 0xf]; 1165 *cp++ = ':'; 1166 } 1167 for (i = 0; i < 20; i++) 1168 *cp++ = '.'; 1169 /* Dump the last MAX_DUMP_SZ/2 bytes */ 1170 ap = (uchar_t *)(addr + (size - MAX_DUMP_SZ / 2)); 1171 for (i = 0; i < MAX_DUMP_SZ / 2; i++) { 1172 if (*ap > 0x0f) 1173 *cp++ = digits[*ap >> 4]; 1174 *cp++ = digits[*ap++ & 0xf]; 1175 *cp++ = ':'; 1176 } 1177 } else { 1178 for (i = 0; i < size; i++) { 1179 if (*ap > 0x0f) 1180 *cp++ = digits[*ap >> 4]; 1181 *cp++ = digits[*ap++ & 0xf]; 1182 *cp++ = ':'; 1183 } 1184 } 1185 *--cp = 0; 1186 return (etherbuf); 1187 } 1188 1189 static void 1190 hxge_suspend(p_hxge_t hxgep) 1191 { 1192 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_suspend")); 1193 1194 /* 1195 * Stop the link status timer before hxge_intrs_disable() to avoid 1196 * accessing the the MSIX table simultaneously. Note that the timer 1197 * routine polls for MSIX parity errors. 1198 */ 1199 MUTEX_ENTER(&hxgep->timeout.lock); 1200 if (hxgep->timeout.id) 1201 (void) untimeout(hxgep->timeout.id); 1202 MUTEX_EXIT(&hxgep->timeout.lock); 1203 1204 hxge_intrs_disable(hxgep); 1205 hxge_destroy_dev(hxgep); 1206 1207 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_suspend")); 1208 } 1209 1210 static hxge_status_t 1211 hxge_resume(p_hxge_t hxgep) 1212 { 1213 hxge_status_t status = HXGE_OK; 1214 1215 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_resume")); 1216 hxgep->suspended = DDI_RESUME; 1217 1218 (void) hxge_rxdma_hw_mode(hxgep, HXGE_DMA_START); 1219 (void) hxge_txdma_hw_mode(hxgep, HXGE_DMA_START); 1220 1221 (void) hxge_rx_vmac_enable(hxgep); 1222 (void) hxge_tx_vmac_enable(hxgep); 1223 1224 hxge_intrs_enable(hxgep); 1225 1226 hxgep->suspended = 0; 1227 1228 /* 1229 * Resume the link status timer after hxge_intrs_enable to avoid 1230 * accessing MSIX table simultaneously. 1231 */ 1232 MUTEX_ENTER(&hxgep->timeout.lock); 1233 hxgep->timeout.id = timeout(hxge_link_poll, (void *)hxgep, 1234 hxgep->timeout.ticks); 1235 MUTEX_EXIT(&hxgep->timeout.lock); 1236 1237 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 1238 "<== hxge_resume status = 0x%x", status)); 1239 1240 return (status); 1241 } 1242 1243 static hxge_status_t 1244 hxge_setup_dev(p_hxge_t hxgep) 1245 { 1246 hxge_status_t status = HXGE_OK; 1247 1248 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_dev")); 1249 1250 status = hxge_link_init(hxgep); 1251 if (fm_check_acc_handle(hxgep->dev_regs->hxge_regh) != DDI_FM_OK) { 1252 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 1253 "Bad register acc handle")); 1254 status = HXGE_ERROR; 1255 } 1256 1257 if (status != HXGE_OK) { 1258 HXGE_DEBUG_MSG((hxgep, MAC_CTL, 1259 " hxge_setup_dev status (link init 0x%08x)", status)); 1260 goto hxge_setup_dev_exit; 1261 } 1262 1263 hxge_setup_dev_exit: 1264 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 1265 "<== hxge_setup_dev status = 0x%08x", status)); 1266 1267 return (status); 1268 } 1269 1270 static void 1271 hxge_destroy_dev(p_hxge_t hxgep) 1272 { 1273 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_destroy_dev")); 1274 1275 (void) hxge_hw_stop(hxgep); 1276 1277 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_destroy_dev")); 1278 } 1279 1280 static hxge_status_t 1281 hxge_setup_system_dma_pages(p_hxge_t hxgep) 1282 { 1283 int ddi_status = DDI_SUCCESS; 1284 uint_t count; 1285 ddi_dma_cookie_t cookie; 1286 uint_t iommu_pagesize; 1287 hxge_status_t status = HXGE_OK; 1288 1289 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_setup_system_dma_pages")); 1290 1291 hxgep->sys_page_sz = ddi_ptob(hxgep->dip, (ulong_t)1); 1292 iommu_pagesize = dvma_pagesize(hxgep->dip); 1293 1294 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 1295 " hxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 1296 " default_block_size %d iommu_pagesize %d", 1297 hxgep->sys_page_sz, ddi_ptob(hxgep->dip, (ulong_t)1), 1298 hxgep->rx_default_block_size, iommu_pagesize)); 1299 1300 if (iommu_pagesize != 0) { 1301 if (hxgep->sys_page_sz == iommu_pagesize) { 1302 /* Hydra support up to 8K pages */ 1303 if (iommu_pagesize > 0x2000) 1304 hxgep->sys_page_sz = 0x2000; 1305 } else { 1306 if (hxgep->sys_page_sz > iommu_pagesize) 1307 hxgep->sys_page_sz = iommu_pagesize; 1308 } 1309 } 1310 1311 hxgep->sys_page_mask = ~(hxgep->sys_page_sz - 1); 1312 1313 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 1314 "==> hxge_setup_system_dma_pages: page %d (ddi_ptob %d) " 1315 "default_block_size %d page mask %d", 1316 hxgep->sys_page_sz, ddi_ptob(hxgep->dip, (ulong_t)1), 1317 hxgep->rx_default_block_size, hxgep->sys_page_mask)); 1318 1319 switch (hxgep->sys_page_sz) { 1320 default: 1321 hxgep->sys_page_sz = 0x1000; 1322 hxgep->sys_page_mask = ~(hxgep->sys_page_sz - 1); 1323 hxgep->rx_default_block_size = 0x1000; 1324 hxgep->rx_bksize_code = RBR_BKSIZE_4K; 1325 break; 1326 case 0x1000: 1327 hxgep->rx_default_block_size = 0x1000; 1328 hxgep->rx_bksize_code = RBR_BKSIZE_4K; 1329 break; 1330 case 0x2000: 1331 hxgep->rx_default_block_size = 0x2000; 1332 hxgep->rx_bksize_code = RBR_BKSIZE_8K; 1333 break; 1334 } 1335 1336 hxge_rx_dma_attr.dma_attr_align = hxgep->sys_page_sz; 1337 hxge_tx_dma_attr.dma_attr_align = hxgep->sys_page_sz; 1338 1339 /* 1340 * Get the system DMA burst size. 1341 */ 1342 ddi_status = ddi_dma_alloc_handle(hxgep->dip, &hxge_tx_dma_attr, 1343 DDI_DMA_DONTWAIT, 0, &hxgep->dmasparehandle); 1344 if (ddi_status != DDI_SUCCESS) { 1345 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 1346 "ddi_dma_alloc_handle: failed status 0x%x", ddi_status)); 1347 goto hxge_get_soft_properties_exit; 1348 } 1349 1350 ddi_status = ddi_dma_addr_bind_handle(hxgep->dmasparehandle, NULL, 1351 (caddr_t)hxgep->dmasparehandle, sizeof (hxgep->dmasparehandle), 1352 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, DDI_DMA_DONTWAIT, 0, 1353 &cookie, &count); 1354 if (ddi_status != DDI_DMA_MAPPED) { 1355 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 1356 "Binding spare handle to find system burstsize failed.")); 1357 ddi_status = DDI_FAILURE; 1358 goto hxge_get_soft_properties_fail1; 1359 } 1360 1361 hxgep->sys_burst_sz = ddi_dma_burstsizes(hxgep->dmasparehandle); 1362 (void) ddi_dma_unbind_handle(hxgep->dmasparehandle); 1363 1364 hxge_get_soft_properties_fail1: 1365 ddi_dma_free_handle(&hxgep->dmasparehandle); 1366 1367 hxge_get_soft_properties_exit: 1368 1369 if (ddi_status != DDI_SUCCESS) 1370 status |= (HXGE_ERROR | HXGE_DDI_FAILED); 1371 1372 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 1373 "<== hxge_setup_system_dma_pages status = 0x%08x", status)); 1374 1375 return (status); 1376 } 1377 1378 static hxge_status_t 1379 hxge_alloc_mem_pool(p_hxge_t hxgep) 1380 { 1381 hxge_status_t status = HXGE_OK; 1382 1383 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_alloc_mem_pool")); 1384 1385 status = hxge_alloc_rx_mem_pool(hxgep); 1386 if (status != HXGE_OK) { 1387 return (HXGE_ERROR); 1388 } 1389 1390 status = hxge_alloc_tx_mem_pool(hxgep); 1391 if (status != HXGE_OK) { 1392 hxge_free_rx_mem_pool(hxgep); 1393 return (HXGE_ERROR); 1394 } 1395 1396 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_alloc_mem_pool")); 1397 return (HXGE_OK); 1398 } 1399 1400 static void 1401 hxge_free_mem_pool(p_hxge_t hxgep) 1402 { 1403 HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_free_mem_pool")); 1404 1405 hxge_free_rx_mem_pool(hxgep); 1406 hxge_free_tx_mem_pool(hxgep); 1407 1408 HXGE_DEBUG_MSG((hxgep, MEM_CTL, "<== hxge_free_mem_pool")); 1409 } 1410 1411 static hxge_status_t 1412 hxge_alloc_rx_mem_pool(p_hxge_t hxgep) 1413 { 1414 int i, j; 1415 uint32_t ndmas, st_rdc; 1416 p_hxge_dma_pt_cfg_t p_all_cfgp; 1417 p_hxge_hw_pt_cfg_t p_cfgp; 1418 p_hxge_dma_pool_t dma_poolp; 1419 p_hxge_dma_common_t *dma_buf_p; 1420 p_hxge_dma_pool_t dma_rbr_cntl_poolp; 1421 p_hxge_dma_common_t *dma_rbr_cntl_p; 1422 p_hxge_dma_pool_t dma_rcr_cntl_poolp; 1423 p_hxge_dma_common_t *dma_rcr_cntl_p; 1424 p_hxge_dma_pool_t dma_mbox_cntl_poolp; 1425 p_hxge_dma_common_t *dma_mbox_cntl_p; 1426 size_t rx_buf_alloc_size; 1427 size_t rx_rbr_cntl_alloc_size; 1428 size_t rx_rcr_cntl_alloc_size; 1429 size_t rx_mbox_cntl_alloc_size; 1430 uint32_t *num_chunks; /* per dma */ 1431 hxge_status_t status = HXGE_OK; 1432 1433 uint32_t hxge_port_rbr_size; 1434 uint32_t hxge_port_rbr_spare_size; 1435 uint32_t hxge_port_rcr_size; 1436 1437 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_mem_pool")); 1438 1439 p_all_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config; 1440 p_cfgp = (p_hxge_hw_pt_cfg_t)&p_all_cfgp->hw_config; 1441 st_rdc = p_cfgp->start_rdc; 1442 ndmas = p_cfgp->max_rdcs; 1443 1444 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 1445 " hxge_alloc_rx_mem_pool st_rdc %d ndmas %d", st_rdc, ndmas)); 1446 1447 /* 1448 * Allocate memory for each receive DMA channel. 1449 */ 1450 dma_poolp = (p_hxge_dma_pool_t)KMEM_ZALLOC(sizeof (hxge_dma_pool_t), 1451 KM_SLEEP); 1452 dma_buf_p = (p_hxge_dma_common_t *)KMEM_ZALLOC( 1453 sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP); 1454 1455 dma_rbr_cntl_poolp = (p_hxge_dma_pool_t) 1456 KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP); 1457 dma_rbr_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC( 1458 sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP); 1459 dma_rcr_cntl_poolp = (p_hxge_dma_pool_t) 1460 KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP); 1461 dma_rcr_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC( 1462 sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP); 1463 dma_mbox_cntl_poolp = (p_hxge_dma_pool_t) 1464 KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP); 1465 dma_mbox_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC( 1466 sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP); 1467 1468 num_chunks = (uint32_t *)KMEM_ZALLOC(sizeof (uint32_t) * ndmas, 1469 KM_SLEEP); 1470 1471 /* 1472 * Assume that each DMA channel will be configured with default block 1473 * size. rbr block counts are mod of batch count (16). 1474 */ 1475 hxge_port_rbr_size = p_all_cfgp->rbr_size; 1476 hxge_port_rcr_size = p_all_cfgp->rcr_size; 1477 1478 if (!hxge_port_rbr_size) { 1479 hxge_port_rbr_size = HXGE_RBR_RBB_DEFAULT; 1480 } 1481 1482 if (hxge_port_rbr_size % HXGE_RXDMA_POST_BATCH) { 1483 hxge_port_rbr_size = (HXGE_RXDMA_POST_BATCH * 1484 (hxge_port_rbr_size / HXGE_RXDMA_POST_BATCH + 1)); 1485 } 1486 1487 p_all_cfgp->rbr_size = hxge_port_rbr_size; 1488 hxge_port_rbr_spare_size = hxge_rbr_spare_size; 1489 1490 if (hxge_port_rbr_spare_size % HXGE_RXDMA_POST_BATCH) { 1491 hxge_port_rbr_spare_size = (HXGE_RXDMA_POST_BATCH * 1492 (hxge_port_rbr_spare_size / HXGE_RXDMA_POST_BATCH + 1)); 1493 } 1494 1495 rx_buf_alloc_size = (hxgep->rx_default_block_size * 1496 (hxge_port_rbr_size + hxge_port_rbr_spare_size)); 1497 1498 /* 1499 * Addresses of receive block ring, receive completion ring and the 1500 * mailbox must be all cache-aligned (64 bytes). 1501 */ 1502 rx_rbr_cntl_alloc_size = hxge_port_rbr_size + hxge_port_rbr_spare_size; 1503 rx_rbr_cntl_alloc_size *= sizeof (rx_desc_t); 1504 rx_rcr_cntl_alloc_size = sizeof (rcr_entry_t) * hxge_port_rcr_size; 1505 rx_mbox_cntl_alloc_size = sizeof (rxdma_mailbox_t); 1506 1507 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_alloc_rx_mem_pool: " 1508 "hxge_port_rbr_size = %d hxge_port_rbr_spare_size = %d " 1509 "hxge_port_rcr_size = %d rx_cntl_alloc_size = %d", 1510 hxge_port_rbr_size, hxge_port_rbr_spare_size, 1511 hxge_port_rcr_size, rx_cntl_alloc_size)); 1512 1513 hxgep->hxge_port_rbr_size = hxge_port_rbr_size; 1514 hxgep->hxge_port_rcr_size = hxge_port_rcr_size; 1515 1516 /* 1517 * Allocate memory for receive buffers and descriptor rings. Replace 1518 * allocation functions with interface functions provided by the 1519 * partition manager when it is available. 1520 */ 1521 /* 1522 * Allocate memory for the receive buffer blocks. 1523 */ 1524 for (i = 0; i < ndmas; i++) { 1525 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 1526 " hxge_alloc_rx_mem_pool to alloc mem: " 1527 " dma %d dma_buf_p %llx &dma_buf_p %llx", 1528 i, dma_buf_p[i], &dma_buf_p[i])); 1529 1530 num_chunks[i] = 0; 1531 1532 status = hxge_alloc_rx_buf_dma(hxgep, st_rdc, &dma_buf_p[i], 1533 rx_buf_alloc_size, hxgep->rx_default_block_size, 1534 &num_chunks[i]); 1535 if (status != HXGE_OK) { 1536 break; 1537 } 1538 1539 st_rdc++; 1540 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 1541 " hxge_alloc_rx_mem_pool DONE alloc mem: " 1542 "dma %d dma_buf_p %llx &dma_buf_p %llx", i, 1543 dma_buf_p[i], &dma_buf_p[i])); 1544 } 1545 1546 if (i < ndmas) { 1547 goto hxge_alloc_rx_mem_fail1; 1548 } 1549 1550 /* 1551 * Allocate memory for descriptor rings and mailbox. 1552 */ 1553 st_rdc = p_cfgp->start_rdc; 1554 for (j = 0; j < ndmas; j++) { 1555 if ((status = hxge_alloc_rx_cntl_dma(hxgep, st_rdc, 1556 &dma_rbr_cntl_p[j], &hxge_rx_rbr_desc_dma_attr, 1557 rx_rbr_cntl_alloc_size)) != HXGE_OK) { 1558 break; 1559 } 1560 1561 if ((status = hxge_alloc_rx_cntl_dma(hxgep, st_rdc, 1562 &dma_rcr_cntl_p[j], &hxge_rx_rcr_desc_dma_attr, 1563 rx_rcr_cntl_alloc_size)) != HXGE_OK) { 1564 break; 1565 } 1566 1567 if ((status = hxge_alloc_rx_cntl_dma(hxgep, st_rdc, 1568 &dma_mbox_cntl_p[j], &hxge_rx_mbox_dma_attr, 1569 rx_mbox_cntl_alloc_size)) != HXGE_OK) { 1570 break; 1571 } 1572 st_rdc++; 1573 } 1574 1575 if (j < ndmas) { 1576 goto hxge_alloc_rx_mem_fail2; 1577 } 1578 1579 dma_poolp->ndmas = ndmas; 1580 dma_poolp->num_chunks = num_chunks; 1581 dma_poolp->buf_allocated = B_TRUE; 1582 hxgep->rx_buf_pool_p = dma_poolp; 1583 dma_poolp->dma_buf_pool_p = dma_buf_p; 1584 1585 dma_rbr_cntl_poolp->ndmas = ndmas; 1586 dma_rbr_cntl_poolp->buf_allocated = B_TRUE; 1587 hxgep->rx_rbr_cntl_pool_p = dma_rbr_cntl_poolp; 1588 dma_rbr_cntl_poolp->dma_buf_pool_p = dma_rbr_cntl_p; 1589 1590 dma_rcr_cntl_poolp->ndmas = ndmas; 1591 dma_rcr_cntl_poolp->buf_allocated = B_TRUE; 1592 hxgep->rx_rcr_cntl_pool_p = dma_rcr_cntl_poolp; 1593 dma_rcr_cntl_poolp->dma_buf_pool_p = dma_rcr_cntl_p; 1594 1595 dma_mbox_cntl_poolp->ndmas = ndmas; 1596 dma_mbox_cntl_poolp->buf_allocated = B_TRUE; 1597 hxgep->rx_mbox_cntl_pool_p = dma_mbox_cntl_poolp; 1598 dma_mbox_cntl_poolp->dma_buf_pool_p = dma_mbox_cntl_p; 1599 1600 goto hxge_alloc_rx_mem_pool_exit; 1601 1602 hxge_alloc_rx_mem_fail2: 1603 /* Free control buffers */ 1604 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 1605 "==> hxge_alloc_rx_mem_pool: freeing control bufs (%d)", j)); 1606 for (; j >= 0; j--) { 1607 hxge_free_rx_cntl_dma(hxgep, 1608 (p_hxge_dma_common_t)dma_rbr_cntl_p[j]); 1609 hxge_free_rx_cntl_dma(hxgep, 1610 (p_hxge_dma_common_t)dma_rcr_cntl_p[j]); 1611 hxge_free_rx_cntl_dma(hxgep, 1612 (p_hxge_dma_common_t)dma_mbox_cntl_p[j]); 1613 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 1614 "==> hxge_alloc_rx_mem_pool: control bufs freed (%d)", j)); 1615 } 1616 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 1617 "==> hxge_alloc_rx_mem_pool: control bufs freed (%d)", j)); 1618 1619 hxge_alloc_rx_mem_fail1: 1620 /* Free data buffers */ 1621 i--; 1622 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 1623 "==> hxge_alloc_rx_mem_pool: freeing data bufs (%d)", i)); 1624 for (; i >= 0; i--) { 1625 hxge_free_rx_buf_dma(hxgep, (p_hxge_dma_common_t)dma_buf_p[i], 1626 num_chunks[i]); 1627 } 1628 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 1629 "==> hxge_alloc_rx_mem_pool: data bufs freed (%d)", i)); 1630 1631 KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 1632 KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t)); 1633 KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t)); 1634 KMEM_FREE(dma_rbr_cntl_poolp, sizeof (hxge_dma_pool_t)); 1635 KMEM_FREE(dma_rbr_cntl_p, ndmas * sizeof (p_hxge_dma_common_t)); 1636 KMEM_FREE(dma_rcr_cntl_poolp, sizeof (hxge_dma_pool_t)); 1637 KMEM_FREE(dma_rcr_cntl_p, ndmas * sizeof (p_hxge_dma_common_t)); 1638 KMEM_FREE(dma_mbox_cntl_poolp, sizeof (hxge_dma_pool_t)); 1639 KMEM_FREE(dma_mbox_cntl_p, ndmas * sizeof (p_hxge_dma_common_t)); 1640 1641 hxge_alloc_rx_mem_pool_exit: 1642 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 1643 "<== hxge_alloc_rx_mem_pool:status 0x%08x", status)); 1644 1645 return (status); 1646 } 1647 1648 static void 1649 hxge_free_rx_mem_pool(p_hxge_t hxgep) 1650 { 1651 uint32_t i, ndmas; 1652 p_hxge_dma_pool_t dma_poolp; 1653 p_hxge_dma_common_t *dma_buf_p; 1654 p_hxge_dma_pool_t dma_rbr_cntl_poolp; 1655 p_hxge_dma_common_t *dma_rbr_cntl_p; 1656 p_hxge_dma_pool_t dma_rcr_cntl_poolp; 1657 p_hxge_dma_common_t *dma_rcr_cntl_p; 1658 p_hxge_dma_pool_t dma_mbox_cntl_poolp; 1659 p_hxge_dma_common_t *dma_mbox_cntl_p; 1660 uint32_t *num_chunks; 1661 1662 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "==> hxge_free_rx_mem_pool")); 1663 1664 dma_poolp = hxgep->rx_buf_pool_p; 1665 if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) { 1666 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_mem_pool " 1667 "(null rx buf pool or buf not allocated")); 1668 return; 1669 } 1670 1671 dma_rbr_cntl_poolp = hxgep->rx_rbr_cntl_pool_p; 1672 if (dma_rbr_cntl_poolp == NULL || 1673 (!dma_rbr_cntl_poolp->buf_allocated)) { 1674 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 1675 "<== hxge_free_rx_mem_pool " 1676 "(null rbr cntl buf pool or rbr cntl buf not allocated")); 1677 return; 1678 } 1679 1680 dma_rcr_cntl_poolp = hxgep->rx_rcr_cntl_pool_p; 1681 if (dma_rcr_cntl_poolp == NULL || 1682 (!dma_rcr_cntl_poolp->buf_allocated)) { 1683 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 1684 "<== hxge_free_rx_mem_pool " 1685 "(null rcr cntl buf pool or rcr cntl buf not allocated")); 1686 return; 1687 } 1688 1689 dma_mbox_cntl_poolp = hxgep->rx_mbox_cntl_pool_p; 1690 if (dma_mbox_cntl_poolp == NULL || 1691 (!dma_mbox_cntl_poolp->buf_allocated)) { 1692 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 1693 "<== hxge_free_rx_mem_pool " 1694 "(null mbox cntl buf pool or mbox cntl buf not allocated")); 1695 return; 1696 } 1697 1698 dma_buf_p = dma_poolp->dma_buf_pool_p; 1699 num_chunks = dma_poolp->num_chunks; 1700 1701 dma_rbr_cntl_p = dma_rbr_cntl_poolp->dma_buf_pool_p; 1702 dma_rcr_cntl_p = dma_rcr_cntl_poolp->dma_buf_pool_p; 1703 dma_mbox_cntl_p = dma_mbox_cntl_poolp->dma_buf_pool_p; 1704 ndmas = dma_rbr_cntl_poolp->ndmas; 1705 1706 for (i = 0; i < ndmas; i++) { 1707 hxge_free_rx_buf_dma(hxgep, dma_buf_p[i], num_chunks[i]); 1708 } 1709 1710 for (i = 0; i < ndmas; i++) { 1711 hxge_free_rx_cntl_dma(hxgep, dma_rbr_cntl_p[i]); 1712 hxge_free_rx_cntl_dma(hxgep, dma_rcr_cntl_p[i]); 1713 hxge_free_rx_cntl_dma(hxgep, dma_mbox_cntl_p[i]); 1714 } 1715 1716 for (i = 0; i < ndmas; i++) { 1717 KMEM_FREE(dma_buf_p[i], 1718 sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK); 1719 KMEM_FREE(dma_rbr_cntl_p[i], sizeof (hxge_dma_common_t)); 1720 KMEM_FREE(dma_rcr_cntl_p[i], sizeof (hxge_dma_common_t)); 1721 KMEM_FREE(dma_mbox_cntl_p[i], sizeof (hxge_dma_common_t)); 1722 } 1723 1724 KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 1725 KMEM_FREE(dma_rbr_cntl_p, ndmas * sizeof (p_hxge_dma_common_t)); 1726 KMEM_FREE(dma_rbr_cntl_poolp, sizeof (hxge_dma_pool_t)); 1727 KMEM_FREE(dma_rcr_cntl_p, ndmas * sizeof (p_hxge_dma_common_t)); 1728 KMEM_FREE(dma_rcr_cntl_poolp, sizeof (hxge_dma_pool_t)); 1729 KMEM_FREE(dma_mbox_cntl_p, ndmas * sizeof (p_hxge_dma_common_t)); 1730 KMEM_FREE(dma_mbox_cntl_poolp, sizeof (hxge_dma_pool_t)); 1731 KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t)); 1732 KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t)); 1733 1734 hxgep->rx_buf_pool_p = NULL; 1735 hxgep->rx_rbr_cntl_pool_p = NULL; 1736 hxgep->rx_rcr_cntl_pool_p = NULL; 1737 hxgep->rx_mbox_cntl_pool_p = NULL; 1738 1739 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_mem_pool")); 1740 } 1741 1742 static hxge_status_t 1743 hxge_alloc_rx_buf_dma(p_hxge_t hxgep, uint16_t dma_channel, 1744 p_hxge_dma_common_t *dmap, 1745 size_t alloc_size, size_t block_size, uint32_t *num_chunks) 1746 { 1747 p_hxge_dma_common_t rx_dmap; 1748 hxge_status_t status = HXGE_OK; 1749 size_t total_alloc_size; 1750 size_t allocated = 0; 1751 int i, size_index, array_size; 1752 1753 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_buf_dma")); 1754 1755 rx_dmap = (p_hxge_dma_common_t) 1756 KMEM_ZALLOC(sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK, KM_SLEEP); 1757 1758 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 1759 " alloc_rx_buf_dma rdc %d asize %x bsize %x bbuf %llx ", 1760 dma_channel, alloc_size, block_size, dmap)); 1761 1762 total_alloc_size = alloc_size; 1763 1764 i = 0; 1765 size_index = 0; 1766 array_size = sizeof (alloc_sizes) / sizeof (size_t); 1767 while ((size_index < array_size) && 1768 (alloc_sizes[size_index] < alloc_size)) 1769 size_index++; 1770 if (size_index >= array_size) { 1771 size_index = array_size - 1; 1772 } 1773 1774 while ((allocated < total_alloc_size) && 1775 (size_index >= 0) && (i < HXGE_DMA_BLOCK)) { 1776 rx_dmap[i].dma_chunk_index = i; 1777 rx_dmap[i].block_size = block_size; 1778 rx_dmap[i].alength = alloc_sizes[size_index]; 1779 rx_dmap[i].orig_alength = rx_dmap[i].alength; 1780 rx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 1781 rx_dmap[i].dma_channel = dma_channel; 1782 rx_dmap[i].contig_alloc_type = B_FALSE; 1783 1784 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 1785 "alloc_rx_buf_dma rdc %d chunk %d bufp %llx size %x " 1786 "i %d nblocks %d alength %d", 1787 dma_channel, i, &rx_dmap[i], block_size, 1788 i, rx_dmap[i].nblocks, rx_dmap[i].alength)); 1789 status = hxge_dma_mem_alloc(hxgep, hxge_force_dma, 1790 &hxge_rx_dma_attr, rx_dmap[i].alength, 1791 &hxge_dev_buf_dma_acc_attr, 1792 DDI_DMA_READ | DDI_DMA_STREAMING, 1793 (p_hxge_dma_common_t)(&rx_dmap[i])); 1794 if (status != HXGE_OK) { 1795 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 1796 " hxge_alloc_rx_buf_dma: Alloc Failed: " 1797 " for size: %d", alloc_sizes[size_index])); 1798 size_index--; 1799 } else { 1800 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 1801 " alloc_rx_buf_dma allocated rdc %d " 1802 "chunk %d size %x dvma %x bufp %llx ", 1803 dma_channel, i, rx_dmap[i].alength, 1804 rx_dmap[i].ioaddr_pp, &rx_dmap[i])); 1805 i++; 1806 allocated += alloc_sizes[size_index]; 1807 } 1808 } 1809 1810 if (allocated < total_alloc_size) { 1811 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 1812 " hxge_alloc_rx_buf_dma failed due to" 1813 " allocated(%d) < required(%d)", 1814 allocated, total_alloc_size)); 1815 goto hxge_alloc_rx_mem_fail1; 1816 } 1817 1818 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 1819 " alloc_rx_buf_dma rdc %d allocated %d chunks", dma_channel, i)); 1820 1821 *num_chunks = i; 1822 *dmap = rx_dmap; 1823 1824 goto hxge_alloc_rx_mem_exit; 1825 1826 hxge_alloc_rx_mem_fail1: 1827 KMEM_FREE(rx_dmap, sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK); 1828 1829 hxge_alloc_rx_mem_exit: 1830 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 1831 "<== hxge_alloc_rx_buf_dma status 0x%08x", status)); 1832 1833 return (status); 1834 } 1835 1836 /*ARGSUSED*/ 1837 static void 1838 hxge_free_rx_buf_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap, 1839 uint32_t num_chunks) 1840 { 1841 int i; 1842 1843 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 1844 "==> hxge_free_rx_buf_dma: # of chunks %d", num_chunks)); 1845 1846 for (i = 0; i < num_chunks; i++) { 1847 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, 1848 "==> hxge_free_rx_buf_dma: chunk %d dmap 0x%llx", i, dmap)); 1849 hxge_dma_mem_free(dmap++); 1850 } 1851 1852 HXGE_DEBUG_MSG((hxgep, MEM2_CTL, "<== hxge_free_rx_buf_dma")); 1853 } 1854 1855 /*ARGSUSED*/ 1856 static hxge_status_t 1857 hxge_alloc_rx_cntl_dma(p_hxge_t hxgep, uint16_t dma_channel, 1858 p_hxge_dma_common_t *dmap, struct ddi_dma_attr *attr, size_t size) 1859 { 1860 p_hxge_dma_common_t rx_dmap; 1861 hxge_status_t status = HXGE_OK; 1862 1863 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_rx_cntl_dma")); 1864 1865 rx_dmap = (p_hxge_dma_common_t) 1866 KMEM_ZALLOC(sizeof (hxge_dma_common_t), KM_SLEEP); 1867 1868 rx_dmap->contig_alloc_type = B_FALSE; 1869 1870 status = hxge_dma_mem_alloc(hxgep, hxge_force_dma, 1871 attr, size, &hxge_dev_desc_dma_acc_attr, 1872 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, rx_dmap); 1873 if (status != HXGE_OK) { 1874 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 1875 " hxge_alloc_rx_cntl_dma: Alloc Failed: " 1876 " for size: %d", size)); 1877 goto hxge_alloc_rx_cntl_dma_fail1; 1878 } 1879 1880 *dmap = rx_dmap; 1881 1882 goto hxge_alloc_rx_cntl_dma_exit; 1883 1884 hxge_alloc_rx_cntl_dma_fail1: 1885 KMEM_FREE(rx_dmap, sizeof (hxge_dma_common_t)); 1886 1887 hxge_alloc_rx_cntl_dma_exit: 1888 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 1889 "<== hxge_alloc_rx_cntl_dma status 0x%08x", status)); 1890 1891 return (status); 1892 } 1893 1894 /*ARGSUSED*/ 1895 static void 1896 hxge_free_rx_cntl_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap) 1897 { 1898 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_free_rx_cntl_dma")); 1899 1900 hxge_dma_mem_free(dmap); 1901 1902 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_free_rx_cntl_dma")); 1903 } 1904 1905 static hxge_status_t 1906 hxge_alloc_tx_mem_pool(p_hxge_t hxgep) 1907 { 1908 hxge_status_t status = HXGE_OK; 1909 int i, j; 1910 uint32_t ndmas, st_tdc; 1911 p_hxge_dma_pt_cfg_t p_all_cfgp; 1912 p_hxge_hw_pt_cfg_t p_cfgp; 1913 p_hxge_dma_pool_t dma_poolp; 1914 p_hxge_dma_common_t *dma_buf_p; 1915 p_hxge_dma_pool_t dma_cntl_poolp; 1916 p_hxge_dma_common_t *dma_cntl_p; 1917 size_t tx_buf_alloc_size; 1918 size_t tx_cntl_alloc_size; 1919 uint32_t *num_chunks; /* per dma */ 1920 1921 HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_alloc_tx_mem_pool")); 1922 1923 p_all_cfgp = (p_hxge_dma_pt_cfg_t)&hxgep->pt_config; 1924 p_cfgp = (p_hxge_hw_pt_cfg_t)&p_all_cfgp->hw_config; 1925 st_tdc = p_cfgp->start_tdc; 1926 ndmas = p_cfgp->max_tdcs; 1927 1928 HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_alloc_tx_mem_pool: " 1929 "p_cfgp 0x%016llx start_tdc %d ndmas %d hxgep->max_tdcs %d", 1930 p_cfgp, p_cfgp->start_tdc, p_cfgp->max_tdcs, hxgep->max_tdcs)); 1931 /* 1932 * Allocate memory for each transmit DMA channel. 1933 */ 1934 dma_poolp = (p_hxge_dma_pool_t)KMEM_ZALLOC(sizeof (hxge_dma_pool_t), 1935 KM_SLEEP); 1936 dma_buf_p = (p_hxge_dma_common_t *)KMEM_ZALLOC( 1937 sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP); 1938 1939 dma_cntl_poolp = (p_hxge_dma_pool_t) 1940 KMEM_ZALLOC(sizeof (hxge_dma_pool_t), KM_SLEEP); 1941 dma_cntl_p = (p_hxge_dma_common_t *)KMEM_ZALLOC( 1942 sizeof (p_hxge_dma_common_t) * ndmas, KM_SLEEP); 1943 1944 hxgep->hxge_port_tx_ring_size = hxge_tx_ring_size; 1945 1946 /* 1947 * Assume that each DMA channel will be configured with default 1948 * transmit bufer size for copying transmit data. (For packet payload 1949 * over this limit, packets will not be copied.) 1950 */ 1951 tx_buf_alloc_size = (hxge_bcopy_thresh * hxge_tx_ring_size); 1952 1953 /* 1954 * Addresses of transmit descriptor ring and the mailbox must be all 1955 * cache-aligned (64 bytes). 1956 */ 1957 tx_cntl_alloc_size = hxge_tx_ring_size; 1958 tx_cntl_alloc_size *= (sizeof (tx_desc_t)); 1959 tx_cntl_alloc_size += sizeof (txdma_mailbox_t); 1960 1961 num_chunks = (uint32_t *)KMEM_ZALLOC(sizeof (uint32_t) * ndmas, 1962 KM_SLEEP); 1963 1964 /* 1965 * Allocate memory for transmit buffers and descriptor rings. Replace 1966 * allocation functions with interface functions provided by the 1967 * partition manager when it is available. 1968 * 1969 * Allocate memory for the transmit buffer pool. 1970 */ 1971 for (i = 0; i < ndmas; i++) { 1972 num_chunks[i] = 0; 1973 status = hxge_alloc_tx_buf_dma(hxgep, st_tdc, &dma_buf_p[i], 1974 tx_buf_alloc_size, hxge_bcopy_thresh, &num_chunks[i]); 1975 if (status != HXGE_OK) { 1976 break; 1977 } 1978 st_tdc++; 1979 } 1980 1981 if (i < ndmas) { 1982 goto hxge_alloc_tx_mem_pool_fail1; 1983 } 1984 1985 st_tdc = p_cfgp->start_tdc; 1986 1987 /* 1988 * Allocate memory for descriptor rings and mailbox. 1989 */ 1990 for (j = 0; j < ndmas; j++) { 1991 status = hxge_alloc_tx_cntl_dma(hxgep, st_tdc, &dma_cntl_p[j], 1992 tx_cntl_alloc_size); 1993 if (status != HXGE_OK) { 1994 break; 1995 } 1996 st_tdc++; 1997 } 1998 1999 if (j < ndmas) { 2000 goto hxge_alloc_tx_mem_pool_fail2; 2001 } 2002 2003 dma_poolp->ndmas = ndmas; 2004 dma_poolp->num_chunks = num_chunks; 2005 dma_poolp->buf_allocated = B_TRUE; 2006 dma_poolp->dma_buf_pool_p = dma_buf_p; 2007 hxgep->tx_buf_pool_p = dma_poolp; 2008 2009 dma_cntl_poolp->ndmas = ndmas; 2010 dma_cntl_poolp->buf_allocated = B_TRUE; 2011 dma_cntl_poolp->dma_buf_pool_p = dma_cntl_p; 2012 hxgep->tx_cntl_pool_p = dma_cntl_poolp; 2013 2014 HXGE_DEBUG_MSG((hxgep, MEM_CTL, 2015 "==> hxge_alloc_tx_mem_pool: start_tdc %d " 2016 "ndmas %d poolp->ndmas %d", st_tdc, ndmas, dma_poolp->ndmas)); 2017 2018 goto hxge_alloc_tx_mem_pool_exit; 2019 2020 hxge_alloc_tx_mem_pool_fail2: 2021 /* Free control buffers */ 2022 j--; 2023 for (; j >= 0; j--) { 2024 hxge_free_tx_cntl_dma(hxgep, 2025 (p_hxge_dma_common_t)dma_cntl_p[j]); 2026 } 2027 2028 hxge_alloc_tx_mem_pool_fail1: 2029 /* Free data buffers */ 2030 i--; 2031 for (; i >= 0; i--) { 2032 hxge_free_tx_buf_dma(hxgep, (p_hxge_dma_common_t)dma_buf_p[i], 2033 num_chunks[i]); 2034 } 2035 2036 KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t)); 2037 KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t)); 2038 KMEM_FREE(dma_cntl_poolp, sizeof (hxge_dma_pool_t)); 2039 KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_hxge_dma_common_t)); 2040 KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 2041 2042 hxge_alloc_tx_mem_pool_exit: 2043 HXGE_DEBUG_MSG((hxgep, MEM_CTL, 2044 "<== hxge_alloc_tx_mem_pool:status 0x%08x", status)); 2045 2046 return (status); 2047 } 2048 2049 static hxge_status_t 2050 hxge_alloc_tx_buf_dma(p_hxge_t hxgep, uint16_t dma_channel, 2051 p_hxge_dma_common_t *dmap, size_t alloc_size, 2052 size_t block_size, uint32_t *num_chunks) 2053 { 2054 p_hxge_dma_common_t tx_dmap; 2055 hxge_status_t status = HXGE_OK; 2056 size_t total_alloc_size; 2057 size_t allocated = 0; 2058 int i, size_index, array_size; 2059 2060 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_tx_buf_dma")); 2061 2062 tx_dmap = (p_hxge_dma_common_t) 2063 KMEM_ZALLOC(sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK, KM_SLEEP); 2064 2065 total_alloc_size = alloc_size; 2066 i = 0; 2067 size_index = 0; 2068 array_size = sizeof (alloc_sizes) / sizeof (size_t); 2069 while ((size_index < array_size) && 2070 (alloc_sizes[size_index] < alloc_size)) 2071 size_index++; 2072 if (size_index >= array_size) { 2073 size_index = array_size - 1; 2074 } 2075 2076 while ((allocated < total_alloc_size) && 2077 (size_index >= 0) && (i < HXGE_DMA_BLOCK)) { 2078 tx_dmap[i].dma_chunk_index = i; 2079 tx_dmap[i].block_size = block_size; 2080 tx_dmap[i].alength = alloc_sizes[size_index]; 2081 tx_dmap[i].orig_alength = tx_dmap[i].alength; 2082 tx_dmap[i].nblocks = alloc_sizes[size_index] / block_size; 2083 tx_dmap[i].dma_channel = dma_channel; 2084 tx_dmap[i].contig_alloc_type = B_FALSE; 2085 2086 status = hxge_dma_mem_alloc(hxgep, hxge_force_dma, 2087 &hxge_tx_dma_attr, tx_dmap[i].alength, 2088 &hxge_dev_buf_dma_acc_attr, 2089 DDI_DMA_WRITE | DDI_DMA_STREAMING, 2090 (p_hxge_dma_common_t)(&tx_dmap[i])); 2091 if (status != HXGE_OK) { 2092 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 2093 " hxge_alloc_tx_buf_dma: Alloc Failed: " 2094 " for size: %d", alloc_sizes[size_index])); 2095 size_index--; 2096 } else { 2097 i++; 2098 allocated += alloc_sizes[size_index]; 2099 } 2100 } 2101 2102 if (allocated < total_alloc_size) { 2103 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 2104 " hxge_alloc_tx_buf_dma: failed due to" 2105 " allocated(%d) < required(%d)", 2106 allocated, total_alloc_size)); 2107 goto hxge_alloc_tx_mem_fail1; 2108 } 2109 2110 *num_chunks = i; 2111 *dmap = tx_dmap; 2112 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 2113 "==> hxge_alloc_tx_buf_dma dmap 0x%016llx num chunks %d", 2114 *dmap, i)); 2115 goto hxge_alloc_tx_mem_exit; 2116 2117 hxge_alloc_tx_mem_fail1: 2118 KMEM_FREE(tx_dmap, sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK); 2119 2120 hxge_alloc_tx_mem_exit: 2121 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 2122 "<== hxge_alloc_tx_buf_dma status 0x%08x", status)); 2123 2124 return (status); 2125 } 2126 2127 /*ARGSUSED*/ 2128 static void 2129 hxge_free_tx_buf_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap, 2130 uint32_t num_chunks) 2131 { 2132 int i; 2133 2134 HXGE_DEBUG_MSG((hxgep, MEM_CTL, "==> hxge_free_tx_buf_dma")); 2135 2136 for (i = 0; i < num_chunks; i++) { 2137 hxge_dma_mem_free(dmap++); 2138 } 2139 2140 HXGE_DEBUG_MSG((hxgep, MEM_CTL, "<== hxge_free_tx_buf_dma")); 2141 } 2142 2143 /*ARGSUSED*/ 2144 static hxge_status_t 2145 hxge_alloc_tx_cntl_dma(p_hxge_t hxgep, uint16_t dma_channel, 2146 p_hxge_dma_common_t *dmap, size_t size) 2147 { 2148 p_hxge_dma_common_t tx_dmap; 2149 hxge_status_t status = HXGE_OK; 2150 2151 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_alloc_tx_cntl_dma")); 2152 2153 tx_dmap = (p_hxge_dma_common_t)KMEM_ZALLOC(sizeof (hxge_dma_common_t), 2154 KM_SLEEP); 2155 2156 tx_dmap->contig_alloc_type = B_FALSE; 2157 2158 status = hxge_dma_mem_alloc(hxgep, hxge_force_dma, 2159 &hxge_tx_desc_dma_attr, size, &hxge_dev_desc_dma_acc_attr, 2160 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, tx_dmap); 2161 if (status != HXGE_OK) { 2162 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 2163 " hxge_alloc_tx_cntl_dma: Alloc Failed: " 2164 " for size: %d", size)); 2165 goto hxge_alloc_tx_cntl_dma_fail1; 2166 } 2167 2168 *dmap = tx_dmap; 2169 2170 goto hxge_alloc_tx_cntl_dma_exit; 2171 2172 hxge_alloc_tx_cntl_dma_fail1: 2173 KMEM_FREE(tx_dmap, sizeof (hxge_dma_common_t)); 2174 2175 hxge_alloc_tx_cntl_dma_exit: 2176 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 2177 "<== hxge_alloc_tx_cntl_dma status 0x%08x", status)); 2178 2179 return (status); 2180 } 2181 2182 /*ARGSUSED*/ 2183 static void 2184 hxge_free_tx_cntl_dma(p_hxge_t hxgep, p_hxge_dma_common_t dmap) 2185 { 2186 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "==> hxge_free_tx_cntl_dma")); 2187 2188 hxge_dma_mem_free(dmap); 2189 2190 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_free_tx_cntl_dma")); 2191 } 2192 2193 static void 2194 hxge_free_tx_mem_pool(p_hxge_t hxgep) 2195 { 2196 uint32_t i, ndmas; 2197 p_hxge_dma_pool_t dma_poolp; 2198 p_hxge_dma_common_t *dma_buf_p; 2199 p_hxge_dma_pool_t dma_cntl_poolp; 2200 p_hxge_dma_common_t *dma_cntl_p; 2201 uint32_t *num_chunks; 2202 2203 HXGE_DEBUG_MSG((hxgep, MEM3_CTL, "==> hxge_free_tx_mem_pool")); 2204 2205 dma_poolp = hxgep->tx_buf_pool_p; 2206 if (dma_poolp == NULL || (!dma_poolp->buf_allocated)) { 2207 HXGE_DEBUG_MSG((hxgep, MEM3_CTL, 2208 "<== hxge_free_tx_mem_pool " 2209 "(null rx buf pool or buf not allocated")); 2210 return; 2211 } 2212 2213 dma_cntl_poolp = hxgep->tx_cntl_pool_p; 2214 if (dma_cntl_poolp == NULL || (!dma_cntl_poolp->buf_allocated)) { 2215 HXGE_DEBUG_MSG((hxgep, MEM3_CTL, 2216 "<== hxge_free_tx_mem_pool " 2217 "(null tx cntl buf pool or cntl buf not allocated")); 2218 return; 2219 } 2220 2221 dma_buf_p = dma_poolp->dma_buf_pool_p; 2222 num_chunks = dma_poolp->num_chunks; 2223 2224 dma_cntl_p = dma_cntl_poolp->dma_buf_pool_p; 2225 ndmas = dma_cntl_poolp->ndmas; 2226 2227 for (i = 0; i < ndmas; i++) { 2228 hxge_free_tx_buf_dma(hxgep, dma_buf_p[i], num_chunks[i]); 2229 } 2230 2231 for (i = 0; i < ndmas; i++) { 2232 hxge_free_tx_cntl_dma(hxgep, dma_cntl_p[i]); 2233 } 2234 2235 for (i = 0; i < ndmas; i++) { 2236 KMEM_FREE(dma_buf_p[i], 2237 sizeof (hxge_dma_common_t) * HXGE_DMA_BLOCK); 2238 KMEM_FREE(dma_cntl_p[i], sizeof (hxge_dma_common_t)); 2239 } 2240 2241 KMEM_FREE(num_chunks, sizeof (uint32_t) * ndmas); 2242 KMEM_FREE(dma_cntl_p, ndmas * sizeof (p_hxge_dma_common_t)); 2243 KMEM_FREE(dma_cntl_poolp, sizeof (hxge_dma_pool_t)); 2244 KMEM_FREE(dma_buf_p, ndmas * sizeof (p_hxge_dma_common_t)); 2245 KMEM_FREE(dma_poolp, sizeof (hxge_dma_pool_t)); 2246 2247 hxgep->tx_buf_pool_p = NULL; 2248 hxgep->tx_cntl_pool_p = NULL; 2249 2250 HXGE_DEBUG_MSG((hxgep, MEM3_CTL, "<== hxge_free_tx_mem_pool")); 2251 } 2252 2253 /*ARGSUSED*/ 2254 static hxge_status_t 2255 hxge_dma_mem_alloc(p_hxge_t hxgep, dma_method_t method, 2256 struct ddi_dma_attr *dma_attrp, 2257 size_t length, ddi_device_acc_attr_t *acc_attr_p, uint_t xfer_flags, 2258 p_hxge_dma_common_t dma_p) 2259 { 2260 caddr_t kaddrp; 2261 int ddi_status = DDI_SUCCESS; 2262 2263 dma_p->dma_handle = NULL; 2264 dma_p->acc_handle = NULL; 2265 dma_p->kaddrp = NULL; 2266 2267 ddi_status = ddi_dma_alloc_handle(hxgep->dip, dma_attrp, 2268 DDI_DMA_DONTWAIT, NULL, &dma_p->dma_handle); 2269 if (ddi_status != DDI_SUCCESS) { 2270 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 2271 "hxge_dma_mem_alloc:ddi_dma_alloc_handle failed.")); 2272 return (HXGE_ERROR | HXGE_DDI_FAILED); 2273 } 2274 2275 ddi_status = ddi_dma_mem_alloc(dma_p->dma_handle, length, acc_attr_p, 2276 xfer_flags, DDI_DMA_DONTWAIT, 0, &kaddrp, &dma_p->alength, 2277 &dma_p->acc_handle); 2278 if (ddi_status != DDI_SUCCESS) { 2279 /* The caller will decide whether it is fatal */ 2280 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 2281 "hxge_dma_mem_alloc:ddi_dma_mem_alloc failed")); 2282 ddi_dma_free_handle(&dma_p->dma_handle); 2283 dma_p->dma_handle = NULL; 2284 return (HXGE_ERROR | HXGE_DDI_FAILED); 2285 } 2286 2287 if (dma_p->alength < length) { 2288 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 2289 "hxge_dma_mem_alloc:ddi_dma_mem_alloc < length.")); 2290 ddi_dma_mem_free(&dma_p->acc_handle); 2291 ddi_dma_free_handle(&dma_p->dma_handle); 2292 dma_p->acc_handle = NULL; 2293 dma_p->dma_handle = NULL; 2294 return (HXGE_ERROR); 2295 } 2296 2297 ddi_status = ddi_dma_addr_bind_handle(dma_p->dma_handle, NULL, 2298 kaddrp, dma_p->alength, xfer_flags, DDI_DMA_DONTWAIT, 0, 2299 &dma_p->dma_cookie, &dma_p->ncookies); 2300 if (ddi_status != DDI_DMA_MAPPED) { 2301 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 2302 "hxge_dma_mem_alloc:di_dma_addr_bind failed " 2303 "(staus 0x%x ncookies %d.)", ddi_status, dma_p->ncookies)); 2304 if (dma_p->acc_handle) { 2305 ddi_dma_mem_free(&dma_p->acc_handle); 2306 dma_p->acc_handle = NULL; 2307 } 2308 ddi_dma_free_handle(&dma_p->dma_handle); 2309 dma_p->dma_handle = NULL; 2310 return (HXGE_ERROR | HXGE_DDI_FAILED); 2311 } 2312 2313 if (dma_p->ncookies != 1) { 2314 HXGE_DEBUG_MSG((hxgep, DMA_CTL, 2315 "hxge_dma_mem_alloc:ddi_dma_addr_bind > 1 cookie" 2316 "(staus 0x%x ncookies %d.)", ddi_status, dma_p->ncookies)); 2317 if (dma_p->acc_handle) { 2318 ddi_dma_mem_free(&dma_p->acc_handle); 2319 dma_p->acc_handle = NULL; 2320 } 2321 (void) ddi_dma_unbind_handle(dma_p->dma_handle); 2322 ddi_dma_free_handle(&dma_p->dma_handle); 2323 dma_p->dma_handle = NULL; 2324 return (HXGE_ERROR); 2325 } 2326 2327 dma_p->kaddrp = kaddrp; 2328 dma_p->ioaddr_pp = (unsigned char *) dma_p->dma_cookie.dmac_laddress; 2329 2330 HPI_DMA_ACC_HANDLE_SET(dma_p, dma_p->acc_handle); 2331 2332 HXGE_DEBUG_MSG((hxgep, DMA_CTL, "<== hxge_dma_mem_alloc: " 2333 "dma buffer allocated: dma_p $%p " 2334 "return dmac_ladress from cookie $%p dmac_size %d " 2335 "dma_p->ioaddr_p $%p " 2336 "dma_p->orig_ioaddr_p $%p " 2337 "orig_vatopa $%p " 2338 "alength %d (0x%x) " 2339 "kaddrp $%p " 2340 "length %d (0x%x)", 2341 dma_p, 2342 dma_p->dma_cookie.dmac_laddress, 2343 dma_p->dma_cookie.dmac_size, 2344 dma_p->ioaddr_pp, 2345 dma_p->orig_ioaddr_pp, 2346 dma_p->orig_vatopa, 2347 dma_p->alength, dma_p->alength, 2348 kaddrp, 2349 length, length)); 2350 2351 return (HXGE_OK); 2352 } 2353 2354 static void 2355 hxge_dma_mem_free(p_hxge_dma_common_t dma_p) 2356 { 2357 if (dma_p == NULL) 2358 return; 2359 2360 if (dma_p->dma_handle != NULL) { 2361 if (dma_p->ncookies) { 2362 (void) ddi_dma_unbind_handle(dma_p->dma_handle); 2363 dma_p->ncookies = 0; 2364 } 2365 ddi_dma_free_handle(&dma_p->dma_handle); 2366 dma_p->dma_handle = NULL; 2367 } 2368 2369 if (dma_p->acc_handle != NULL) { 2370 ddi_dma_mem_free(&dma_p->acc_handle); 2371 dma_p->acc_handle = NULL; 2372 HPI_DMA_ACC_HANDLE_SET(dma_p, NULL); 2373 } 2374 2375 dma_p->kaddrp = NULL; 2376 dma_p->alength = 0; 2377 } 2378 2379 /* 2380 * hxge_m_start() -- start transmitting and receiving. 2381 * 2382 * This function is called by the MAC layer when the first 2383 * stream is open to prepare the hardware ready for sending 2384 * and transmitting packets. 2385 */ 2386 static int 2387 hxge_m_start(void *arg) 2388 { 2389 p_hxge_t hxgep = (p_hxge_t)arg; 2390 2391 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_start")); 2392 2393 MUTEX_ENTER(hxgep->genlock); 2394 2395 if (hxge_init(hxgep) != DDI_SUCCESS) { 2396 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 2397 "<== hxge_m_start: initialization failed")); 2398 MUTEX_EXIT(hxgep->genlock); 2399 return (EIO); 2400 } 2401 2402 if (hxgep->hxge_mac_state != HXGE_MAC_STARTED) { 2403 /* 2404 * Start timer to check the system error and tx hangs 2405 */ 2406 hxgep->hxge_timerid = hxge_start_timer(hxgep, 2407 hxge_check_hw_state, HXGE_CHECK_TIMER); 2408 2409 hxgep->hxge_mac_state = HXGE_MAC_STARTED; 2410 2411 hxgep->timeout.link_status = 0; 2412 hxgep->timeout.report_link_status = B_TRUE; 2413 hxgep->timeout.ticks = drv_usectohz(2 * 1000000); 2414 2415 /* Start the link status timer to check the link status */ 2416 MUTEX_ENTER(&hxgep->timeout.lock); 2417 hxgep->timeout.id = timeout(hxge_link_poll, (void *)hxgep, 2418 hxgep->timeout.ticks); 2419 MUTEX_EXIT(&hxgep->timeout.lock); 2420 } 2421 2422 MUTEX_EXIT(hxgep->genlock); 2423 2424 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_start")); 2425 2426 return (0); 2427 } 2428 2429 /* 2430 * hxge_m_stop(): stop transmitting and receiving. 2431 */ 2432 static void 2433 hxge_m_stop(void *arg) 2434 { 2435 p_hxge_t hxgep = (p_hxge_t)arg; 2436 2437 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_stop")); 2438 2439 if (hxgep->hxge_timerid) { 2440 hxge_stop_timer(hxgep, hxgep->hxge_timerid); 2441 hxgep->hxge_timerid = 0; 2442 } 2443 2444 /* Stop the link status timer before unregistering */ 2445 MUTEX_ENTER(&hxgep->timeout.lock); 2446 if (hxgep->timeout.id) { 2447 (void) untimeout(hxgep->timeout.id); 2448 hxgep->timeout.id = 0; 2449 } 2450 hxge_link_update(hxgep, LINK_STATE_DOWN); 2451 MUTEX_EXIT(&hxgep->timeout.lock); 2452 2453 MUTEX_ENTER(hxgep->genlock); 2454 2455 hxge_uninit(hxgep); 2456 2457 hxgep->hxge_mac_state = HXGE_MAC_STOPPED; 2458 2459 MUTEX_EXIT(hxgep->genlock); 2460 2461 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_stop")); 2462 } 2463 2464 static int 2465 hxge_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 2466 { 2467 p_hxge_t hxgep = (p_hxge_t)arg; 2468 struct ether_addr addrp; 2469 2470 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_m_multicst: add %d", add)); 2471 2472 bcopy(mca, (uint8_t *)&addrp, ETHERADDRL); 2473 2474 if (add) { 2475 if (hxge_add_mcast_addr(hxgep, &addrp)) { 2476 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 2477 "<== hxge_m_multicst: add multicast failed")); 2478 return (EINVAL); 2479 } 2480 } else { 2481 if (hxge_del_mcast_addr(hxgep, &addrp)) { 2482 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 2483 "<== hxge_m_multicst: del multicast failed")); 2484 return (EINVAL); 2485 } 2486 } 2487 2488 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_m_multicst")); 2489 2490 return (0); 2491 } 2492 2493 static int 2494 hxge_m_promisc(void *arg, boolean_t on) 2495 { 2496 p_hxge_t hxgep = (p_hxge_t)arg; 2497 2498 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "==> hxge_m_promisc: on %d", on)); 2499 2500 if (hxge_set_promisc(hxgep, on)) { 2501 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 2502 "<== hxge_m_promisc: set promisc failed")); 2503 return (EINVAL); 2504 } 2505 2506 HXGE_DEBUG_MSG((hxgep, MAC_CTL, "<== hxge_m_promisc: on %d", on)); 2507 2508 return (0); 2509 } 2510 2511 static void 2512 hxge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 2513 { 2514 p_hxge_t hxgep = (p_hxge_t)arg; 2515 struct iocblk *iocp = (struct iocblk *)mp->b_rptr; 2516 boolean_t need_privilege; 2517 int err; 2518 int cmd; 2519 2520 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_ioctl")); 2521 2522 iocp = (struct iocblk *)mp->b_rptr; 2523 iocp->ioc_error = 0; 2524 need_privilege = B_TRUE; 2525 cmd = iocp->ioc_cmd; 2526 2527 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "==> hxge_m_ioctl: cmd 0x%08x", cmd)); 2528 switch (cmd) { 2529 default: 2530 miocnak(wq, mp, 0, EINVAL); 2531 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_ioctl: invalid")); 2532 return; 2533 2534 case LB_GET_INFO_SIZE: 2535 case LB_GET_INFO: 2536 case LB_GET_MODE: 2537 need_privilege = B_FALSE; 2538 break; 2539 2540 case LB_SET_MODE: 2541 break; 2542 2543 case ND_GET: 2544 need_privilege = B_FALSE; 2545 break; 2546 case ND_SET: 2547 break; 2548 2549 case HXGE_GET_TX_RING_SZ: 2550 case HXGE_GET_TX_DESC: 2551 case HXGE_TX_SIDE_RESET: 2552 case HXGE_RX_SIDE_RESET: 2553 case HXGE_GLOBAL_RESET: 2554 case HXGE_RESET_MAC: 2555 case HXGE_PUT_TCAM: 2556 case HXGE_GET_TCAM: 2557 case HXGE_RTRACE: 2558 2559 need_privilege = B_FALSE; 2560 break; 2561 } 2562 2563 if (need_privilege) { 2564 err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); 2565 if (err != 0) { 2566 miocnak(wq, mp, 0, err); 2567 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 2568 "<== hxge_m_ioctl: no priv")); 2569 return; 2570 } 2571 } 2572 2573 switch (cmd) { 2574 case ND_GET: 2575 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "ND_GET command")); 2576 case ND_SET: 2577 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "ND_SET command")); 2578 hxge_param_ioctl(hxgep, wq, mp, iocp); 2579 break; 2580 2581 case LB_GET_MODE: 2582 case LB_SET_MODE: 2583 case LB_GET_INFO_SIZE: 2584 case LB_GET_INFO: 2585 hxge_loopback_ioctl(hxgep, wq, mp, iocp); 2586 break; 2587 2588 case HXGE_PUT_TCAM: 2589 case HXGE_GET_TCAM: 2590 case HXGE_GET_TX_RING_SZ: 2591 case HXGE_GET_TX_DESC: 2592 case HXGE_TX_SIDE_RESET: 2593 case HXGE_RX_SIDE_RESET: 2594 case HXGE_GLOBAL_RESET: 2595 case HXGE_RESET_MAC: 2596 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, 2597 "==> hxge_m_ioctl: cmd 0x%x", cmd)); 2598 hxge_hw_ioctl(hxgep, wq, mp, iocp); 2599 break; 2600 } 2601 2602 HXGE_DEBUG_MSG((hxgep, NEMO_CTL, "<== hxge_m_ioctl")); 2603 } 2604 2605 /*ARGSUSED*/ 2606 static int 2607 hxge_tx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num) 2608 { 2609 p_hxge_ring_handle_t rhp = (p_hxge_ring_handle_t)rdriver; 2610 p_hxge_t hxgep; 2611 p_tx_ring_t ring; 2612 2613 ASSERT(rhp != NULL); 2614 ASSERT((rhp->index >= 0) && (rhp->index < HXGE_MAX_TDCS)); 2615 2616 hxgep = rhp->hxgep; 2617 2618 /* 2619 * Get the ring pointer. 2620 */ 2621 ring = hxgep->tx_rings->rings[rhp->index]; 2622 2623 /* 2624 * Fill in the handle for the transmit. 2625 */ 2626 MUTEX_ENTER(&ring->lock); 2627 rhp->started = B_TRUE; 2628 ring->ring_handle = rhp->ring_handle; 2629 MUTEX_EXIT(&ring->lock); 2630 2631 return (0); 2632 } 2633 2634 static void 2635 hxge_tx_ring_stop(mac_ring_driver_t rdriver) 2636 { 2637 p_hxge_ring_handle_t rhp = (p_hxge_ring_handle_t)rdriver; 2638 p_hxge_t hxgep; 2639 p_tx_ring_t ring; 2640 2641 ASSERT(rhp != NULL); 2642 ASSERT((rhp->index >= 0) && (rhp->index < HXGE_MAX_TDCS)); 2643 2644 hxgep = rhp->hxgep; 2645 ring = hxgep->tx_rings->rings[rhp->index]; 2646 2647 MUTEX_ENTER(&ring->lock); 2648 ring->ring_handle = (mac_ring_handle_t)NULL; 2649 rhp->started = B_FALSE; 2650 MUTEX_EXIT(&ring->lock); 2651 } 2652 2653 static int 2654 hxge_rx_ring_start(mac_ring_driver_t rdriver, uint64_t mr_gen_num) 2655 { 2656 p_hxge_ring_handle_t rhp = (p_hxge_ring_handle_t)rdriver; 2657 p_hxge_t hxgep; 2658 p_rx_rcr_ring_t ring; 2659 int i; 2660 2661 ASSERT(rhp != NULL); 2662 ASSERT((rhp->index >= 0) && (rhp->index < HXGE_MAX_TDCS)); 2663 2664 hxgep = rhp->hxgep; 2665 2666 /* 2667 * Get pointer to ring. 2668 */ 2669 ring = hxgep->rx_rcr_rings->rcr_rings[rhp->index]; 2670 2671 MUTEX_ENTER(&ring->lock); 2672 2673 if (rhp->started) { 2674 MUTEX_EXIT(&ring->lock); 2675 return (0); 2676 } 2677 2678 /* 2679 * Set the ldvp and ldgp pointers to enable/disable 2680 * polling. 2681 */ 2682 for (i = 0; i < hxgep->ldgvp->maxldvs; i++) { 2683 if ((hxgep->ldgvp->ldvp[i].is_rxdma == 1) && 2684 (hxgep->ldgvp->ldvp[i].channel == rhp->index)) { 2685 ring->ldvp = &hxgep->ldgvp->ldvp[i]; 2686 ring->ldgp = hxgep->ldgvp->ldvp[i].ldgp; 2687 break; 2688 } 2689 } 2690 2691 rhp->started = B_TRUE; 2692 ring->rcr_mac_handle = rhp->ring_handle; 2693 ring->rcr_gen_num = mr_gen_num; 2694 MUTEX_EXIT(&ring->lock); 2695 2696 return (0); 2697 } 2698 2699 static void 2700 hxge_rx_ring_stop(mac_ring_driver_t rdriver) 2701 { 2702 p_hxge_ring_handle_t rhp = (p_hxge_ring_handle_t)rdriver; 2703 p_hxge_t hxgep; 2704 p_rx_rcr_ring_t ring; 2705 2706 ASSERT(rhp != NULL); 2707 ASSERT((rhp->index >= 0) && (rhp->index < HXGE_MAX_TDCS)); 2708 2709 hxgep = rhp->hxgep; 2710 ring = hxgep->rx_rcr_rings->rcr_rings[rhp->index]; 2711 2712 MUTEX_ENTER(&ring->lock); 2713 rhp->started = B_TRUE; 2714 ring->rcr_mac_handle = NULL; 2715 ring->ldvp = NULL; 2716 ring->ldgp = NULL; 2717 MUTEX_EXIT(&ring->lock); 2718 } 2719 2720 static int 2721 hxge_rx_group_start(mac_group_driver_t gdriver) 2722 { 2723 hxge_ring_group_t *group = (hxge_ring_group_t *)gdriver; 2724 2725 ASSERT(group->hxgep != NULL); 2726 ASSERT(group->hxgep->hxge_mac_state == HXGE_MAC_STARTED); 2727 2728 MUTEX_ENTER(group->hxgep->genlock); 2729 group->started = B_TRUE; 2730 MUTEX_EXIT(group->hxgep->genlock); 2731 2732 return (0); 2733 } 2734 2735 static void 2736 hxge_rx_group_stop(mac_group_driver_t gdriver) 2737 { 2738 hxge_ring_group_t *group = (hxge_ring_group_t *)gdriver; 2739 2740 ASSERT(group->hxgep != NULL); 2741 ASSERT(group->hxgep->hxge_mac_state == HXGE_MAC_STARTED); 2742 ASSERT(group->started == B_TRUE); 2743 2744 MUTEX_ENTER(group->hxgep->genlock); 2745 group->started = B_FALSE; 2746 MUTEX_EXIT(group->hxgep->genlock); 2747 } 2748 2749 static int 2750 hxge_mmac_get_slot(p_hxge_t hxgep, int *slot) 2751 { 2752 int i; 2753 2754 /* 2755 * Find an open slot. 2756 */ 2757 for (i = 0; i < hxgep->mmac.total; i++) { 2758 if (!hxgep->mmac.addrs[i].set) { 2759 *slot = i; 2760 return (0); 2761 } 2762 } 2763 2764 return (ENXIO); 2765 } 2766 2767 static int 2768 hxge_mmac_set_addr(p_hxge_t hxgep, int slot, const uint8_t *addr) 2769 { 2770 struct ether_addr eaddr; 2771 hxge_status_t status = HXGE_OK; 2772 2773 bcopy(addr, (uint8_t *)&eaddr, ETHERADDRL); 2774 2775 /* 2776 * Set new interface local address and re-init device. 2777 * This is destructive to any other streams attached 2778 * to this device. 2779 */ 2780 RW_ENTER_WRITER(&hxgep->filter_lock); 2781 status = hxge_pfc_set_mac_address(hxgep, slot, &eaddr); 2782 RW_EXIT(&hxgep->filter_lock); 2783 if (status != HXGE_OK) 2784 return (status); 2785 2786 hxgep->mmac.addrs[slot].set = B_TRUE; 2787 bcopy(addr, hxgep->mmac.addrs[slot].addr, ETHERADDRL); 2788 hxgep->mmac.available--; 2789 if (slot == HXGE_MAC_DEFAULT_ADDR_SLOT) 2790 hxgep->mmac.addrs[slot].primary = B_TRUE; 2791 2792 return (0); 2793 } 2794 2795 static int 2796 hxge_mmac_find_addr(p_hxge_t hxgep, const uint8_t *addr, int *slot) 2797 { 2798 int i, result; 2799 2800 for (i = 0; i < hxgep->mmac.total; i++) { 2801 if (hxgep->mmac.addrs[i].set) { 2802 result = memcmp(hxgep->mmac.addrs[i].addr, 2803 addr, ETHERADDRL); 2804 if (result == 0) { 2805 *slot = i; 2806 return (0); 2807 } 2808 } 2809 } 2810 2811 return (EINVAL); 2812 } 2813 2814 static int 2815 hxge_mmac_unset_addr(p_hxge_t hxgep, int slot) 2816 { 2817 hxge_status_t status; 2818 int i; 2819 2820 status = hxge_pfc_clear_mac_address(hxgep, slot); 2821 if (status != HXGE_OK) 2822 return (status); 2823 2824 for (i = 0; i < ETHERADDRL; i++) 2825 hxgep->mmac.addrs[slot].addr[i] = 0; 2826 2827 hxgep->mmac.addrs[slot].set = B_FALSE; 2828 if (slot == HXGE_MAC_DEFAULT_ADDR_SLOT) 2829 hxgep->mmac.addrs[slot].primary = B_FALSE; 2830 hxgep->mmac.available++; 2831 2832 return (0); 2833 } 2834 2835 static int 2836 hxge_rx_group_add_mac(void *arg, const uint8_t *mac_addr) 2837 { 2838 hxge_ring_group_t *group = arg; 2839 p_hxge_t hxgep = group->hxgep; 2840 int slot = 0; 2841 2842 ASSERT(group->type == MAC_RING_TYPE_RX); 2843 2844 MUTEX_ENTER(hxgep->genlock); 2845 2846 /* 2847 * Find a slot for the address. 2848 */ 2849 if (hxge_mmac_get_slot(hxgep, &slot) != 0) { 2850 MUTEX_EXIT(hxgep->genlock); 2851 return (ENOSPC); 2852 } 2853 2854 /* 2855 * Program the MAC address. 2856 */ 2857 if (hxge_mmac_set_addr(hxgep, slot, mac_addr) != 0) { 2858 MUTEX_EXIT(hxgep->genlock); 2859 return (ENOSPC); 2860 } 2861 2862 MUTEX_EXIT(hxgep->genlock); 2863 return (0); 2864 } 2865 2866 static int 2867 hxge_rx_group_rem_mac(void *arg, const uint8_t *mac_addr) 2868 { 2869 hxge_ring_group_t *group = arg; 2870 p_hxge_t hxgep = group->hxgep; 2871 int rv, slot; 2872 2873 ASSERT(group->type == MAC_RING_TYPE_RX); 2874 2875 MUTEX_ENTER(hxgep->genlock); 2876 2877 if ((rv = hxge_mmac_find_addr(hxgep, mac_addr, &slot)) != 0) { 2878 MUTEX_EXIT(hxgep->genlock); 2879 return (rv); 2880 } 2881 2882 if ((rv = hxge_mmac_unset_addr(hxgep, slot)) != 0) { 2883 MUTEX_EXIT(hxgep->genlock); 2884 return (rv); 2885 } 2886 2887 MUTEX_EXIT(hxgep->genlock); 2888 return (0); 2889 } 2890 2891 static void 2892 hxge_group_get(void *arg, mac_ring_type_t type, int groupid, 2893 mac_group_info_t *infop, mac_group_handle_t gh) 2894 { 2895 p_hxge_t hxgep = arg; 2896 hxge_ring_group_t *group; 2897 2898 ASSERT(type == MAC_RING_TYPE_RX); 2899 2900 switch (type) { 2901 case MAC_RING_TYPE_RX: 2902 group = &hxgep->rx_groups[groupid]; 2903 group->hxgep = hxgep; 2904 group->ghandle = gh; 2905 group->index = groupid; 2906 group->type = type; 2907 2908 infop->mgi_driver = (mac_group_driver_t)group; 2909 infop->mgi_start = hxge_rx_group_start; 2910 infop->mgi_stop = hxge_rx_group_stop; 2911 infop->mgi_addmac = hxge_rx_group_add_mac; 2912 infop->mgi_remmac = hxge_rx_group_rem_mac; 2913 infop->mgi_count = HXGE_MAX_RDCS; 2914 break; 2915 2916 case MAC_RING_TYPE_TX: 2917 default: 2918 break; 2919 } 2920 } 2921 2922 static int 2923 hxge_ring_get_htable_idx(p_hxge_t hxgep, mac_ring_type_t type, uint32_t channel) 2924 { 2925 int i; 2926 2927 ASSERT(hxgep->ldgvp != NULL); 2928 2929 switch (type) { 2930 case MAC_RING_TYPE_RX: 2931 for (i = 0; i < hxgep->ldgvp->maxldvs; i++) { 2932 if ((hxgep->ldgvp->ldvp[i].is_rxdma) && 2933 (hxgep->ldgvp->ldvp[i].channel == channel)) { 2934 return ((int) 2935 hxgep->ldgvp->ldvp[i].ldgp->htable_idx); 2936 } 2937 } 2938 break; 2939 2940 case MAC_RING_TYPE_TX: 2941 for (i = 0; i < hxgep->ldgvp->maxldvs; i++) { 2942 if ((hxgep->ldgvp->ldvp[i].is_txdma) && 2943 (hxgep->ldgvp->ldvp[i].channel == channel)) { 2944 return ((int) 2945 hxgep->ldgvp->ldvp[i].ldgp->htable_idx); 2946 } 2947 } 2948 break; 2949 2950 default: 2951 break; 2952 } 2953 2954 return (-1); 2955 } 2956 2957 /* 2958 * Callback function for the GLDv3 layer to register all rings. 2959 */ 2960 /*ARGSUSED*/ 2961 static void 2962 hxge_fill_ring(void *arg, mac_ring_type_t type, const int rg_index, 2963 const int index, mac_ring_info_t *infop, mac_ring_handle_t rh) 2964 { 2965 p_hxge_t hxgep = arg; 2966 2967 ASSERT(hxgep != NULL); 2968 ASSERT(infop != NULL); 2969 2970 switch (type) { 2971 case MAC_RING_TYPE_TX: { 2972 p_hxge_ring_handle_t rhp; 2973 mac_intr_t *mintr = &infop->mri_intr; 2974 p_hxge_intr_t intrp; 2975 int htable_idx; 2976 2977 ASSERT((index >= 0) && (index < HXGE_MAX_TDCS)); 2978 rhp = &hxgep->tx_ring_handles[index]; 2979 rhp->hxgep = hxgep; 2980 rhp->index = index; 2981 rhp->ring_handle = rh; 2982 infop->mri_driver = (mac_ring_driver_t)rhp; 2983 infop->mri_start = hxge_tx_ring_start; 2984 infop->mri_stop = hxge_tx_ring_stop; 2985 infop->mri_tx = hxge_tx_ring_send; 2986 infop->mri_stat = hxge_tx_ring_stat; 2987 2988 intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type; 2989 htable_idx = hxge_ring_get_htable_idx(hxgep, type, index); 2990 if (htable_idx >= 0) 2991 mintr->mi_ddi_handle = intrp->htable[htable_idx]; 2992 else 2993 mintr->mi_ddi_handle = NULL; 2994 break; 2995 } 2996 2997 case MAC_RING_TYPE_RX: { 2998 p_hxge_ring_handle_t rhp; 2999 mac_intr_t hxge_mac_intr; 3000 p_hxge_intr_t intrp; 3001 int htable_idx; 3002 3003 ASSERT((index >= 0) && (index < HXGE_MAX_RDCS)); 3004 rhp = &hxgep->rx_ring_handles[index]; 3005 rhp->hxgep = hxgep; 3006 rhp->index = index; 3007 rhp->ring_handle = rh; 3008 3009 /* 3010 * Entrypoint to enable interrupt (disable poll) and 3011 * disable interrupt (enable poll). 3012 */ 3013 hxge_mac_intr.mi_handle = (mac_intr_handle_t)rhp; 3014 hxge_mac_intr.mi_enable = (mac_intr_enable_t)hxge_disable_poll; 3015 hxge_mac_intr.mi_disable = (mac_intr_disable_t)hxge_enable_poll; 3016 3017 intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type; 3018 htable_idx = hxge_ring_get_htable_idx(hxgep, type, index); 3019 if (htable_idx >= 0) 3020 hxge_mac_intr.mi_ddi_handle = intrp->htable[htable_idx]; 3021 else 3022 hxge_mac_intr.mi_ddi_handle = NULL; 3023 3024 infop->mri_driver = (mac_ring_driver_t)rhp; 3025 infop->mri_start = hxge_rx_ring_start; 3026 infop->mri_stop = hxge_rx_ring_stop; 3027 infop->mri_intr = hxge_mac_intr; 3028 infop->mri_poll = hxge_rx_poll; 3029 infop->mri_stat = hxge_rx_ring_stat; 3030 break; 3031 } 3032 3033 default: 3034 break; 3035 } 3036 } 3037 3038 /*ARGSUSED*/ 3039 boolean_t 3040 hxge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 3041 { 3042 p_hxge_t hxgep = arg; 3043 3044 switch (cap) { 3045 case MAC_CAPAB_HCKSUM: { 3046 uint32_t *txflags = cap_data; 3047 3048 *txflags = HCKSUM_INET_PARTIAL; 3049 break; 3050 } 3051 3052 case MAC_CAPAB_RINGS: { 3053 mac_capab_rings_t *cap_rings = cap_data; 3054 3055 MUTEX_ENTER(hxgep->genlock); 3056 if (cap_rings->mr_type == MAC_RING_TYPE_RX) { 3057 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 3058 cap_rings->mr_rnum = HXGE_MAX_RDCS; 3059 cap_rings->mr_rget = hxge_fill_ring; 3060 cap_rings->mr_gnum = HXGE_MAX_RX_GROUPS; 3061 cap_rings->mr_gget = hxge_group_get; 3062 cap_rings->mr_gaddring = NULL; 3063 cap_rings->mr_gremring = NULL; 3064 } else { 3065 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 3066 cap_rings->mr_rnum = HXGE_MAX_TDCS; 3067 cap_rings->mr_rget = hxge_fill_ring; 3068 cap_rings->mr_gnum = 0; 3069 cap_rings->mr_gget = NULL; 3070 cap_rings->mr_gaddring = NULL; 3071 cap_rings->mr_gremring = NULL; 3072 } 3073 MUTEX_EXIT(hxgep->genlock); 3074 break; 3075 } 3076 3077 default: 3078 return (B_FALSE); 3079 } 3080 return (B_TRUE); 3081 } 3082 3083 static boolean_t 3084 hxge_param_locked(mac_prop_id_t pr_num) 3085 { 3086 /* 3087 * All adv_* parameters are locked (read-only) while 3088 * the device is in any sort of loopback mode ... 3089 */ 3090 switch (pr_num) { 3091 case MAC_PROP_ADV_1000FDX_CAP: 3092 case MAC_PROP_EN_1000FDX_CAP: 3093 case MAC_PROP_ADV_1000HDX_CAP: 3094 case MAC_PROP_EN_1000HDX_CAP: 3095 case MAC_PROP_ADV_100FDX_CAP: 3096 case MAC_PROP_EN_100FDX_CAP: 3097 case MAC_PROP_ADV_100HDX_CAP: 3098 case MAC_PROP_EN_100HDX_CAP: 3099 case MAC_PROP_ADV_10FDX_CAP: 3100 case MAC_PROP_EN_10FDX_CAP: 3101 case MAC_PROP_ADV_10HDX_CAP: 3102 case MAC_PROP_EN_10HDX_CAP: 3103 case MAC_PROP_AUTONEG: 3104 case MAC_PROP_FLOWCTRL: 3105 return (B_TRUE); 3106 } 3107 return (B_FALSE); 3108 } 3109 3110 /* 3111 * callback functions for set/get of properties 3112 */ 3113 static int 3114 hxge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 3115 uint_t pr_valsize, const void *pr_val) 3116 { 3117 hxge_t *hxgep = barg; 3118 p_hxge_stats_t statsp; 3119 int err = 0; 3120 uint32_t new_mtu, old_framesize, new_framesize; 3121 3122 HXGE_DEBUG_MSG((hxgep, DLADM_CTL, "==> hxge_m_setprop")); 3123 3124 statsp = hxgep->statsp; 3125 MUTEX_ENTER(hxgep->genlock); 3126 if (statsp->port_stats.lb_mode != hxge_lb_normal && 3127 hxge_param_locked(pr_num)) { 3128 /* 3129 * All adv_* parameters are locked (read-only) 3130 * while the device is in any sort of loopback mode. 3131 */ 3132 HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3133 "==> hxge_m_setprop: loopback mode: read only")); 3134 MUTEX_EXIT(hxgep->genlock); 3135 return (EBUSY); 3136 } 3137 3138 switch (pr_num) { 3139 /* 3140 * These properties are either not exist or read only 3141 */ 3142 case MAC_PROP_EN_1000FDX_CAP: 3143 case MAC_PROP_EN_100FDX_CAP: 3144 case MAC_PROP_EN_10FDX_CAP: 3145 case MAC_PROP_EN_1000HDX_CAP: 3146 case MAC_PROP_EN_100HDX_CAP: 3147 case MAC_PROP_EN_10HDX_CAP: 3148 case MAC_PROP_ADV_1000FDX_CAP: 3149 case MAC_PROP_ADV_1000HDX_CAP: 3150 case MAC_PROP_ADV_100FDX_CAP: 3151 case MAC_PROP_ADV_100HDX_CAP: 3152 case MAC_PROP_ADV_10FDX_CAP: 3153 case MAC_PROP_ADV_10HDX_CAP: 3154 case MAC_PROP_STATUS: 3155 case MAC_PROP_SPEED: 3156 case MAC_PROP_DUPLEX: 3157 case MAC_PROP_AUTONEG: 3158 /* 3159 * Flow control is handled in the shared domain and 3160 * it is readonly here. 3161 */ 3162 case MAC_PROP_FLOWCTRL: 3163 err = EINVAL; 3164 HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3165 "==> hxge_m_setprop: read only property %d", 3166 pr_num)); 3167 break; 3168 3169 case MAC_PROP_MTU: 3170 bcopy(pr_val, &new_mtu, sizeof (new_mtu)); 3171 HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3172 "==> hxge_m_setprop: set MTU: %d", new_mtu)); 3173 3174 new_framesize = new_mtu + MTU_TO_FRAME_SIZE; 3175 if (new_framesize == hxgep->vmac.maxframesize) { 3176 err = 0; 3177 break; 3178 } 3179 3180 if (hxgep->hxge_mac_state == HXGE_MAC_STARTED) { 3181 err = EBUSY; 3182 break; 3183 } 3184 3185 if (new_framesize < MIN_FRAME_SIZE || 3186 new_framesize > MAX_FRAME_SIZE) { 3187 err = EINVAL; 3188 break; 3189 } 3190 3191 old_framesize = hxgep->vmac.maxframesize; 3192 hxgep->vmac.maxframesize = (uint16_t)new_framesize; 3193 3194 if (hxge_vmac_set_framesize(hxgep)) { 3195 hxgep->vmac.maxframesize = 3196 (uint16_t)old_framesize; 3197 err = EINVAL; 3198 break; 3199 } 3200 3201 err = mac_maxsdu_update(hxgep->mach, new_mtu); 3202 if (err) { 3203 hxgep->vmac.maxframesize = 3204 (uint16_t)old_framesize; 3205 (void) hxge_vmac_set_framesize(hxgep); 3206 } 3207 3208 HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3209 "==> hxge_m_setprop: set MTU: %d maxframe %d", 3210 new_mtu, hxgep->vmac.maxframesize)); 3211 break; 3212 3213 case MAC_PROP_PRIVATE: 3214 HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3215 "==> hxge_m_setprop: private property")); 3216 err = hxge_set_priv_prop(hxgep, pr_name, pr_valsize, 3217 pr_val); 3218 break; 3219 3220 default: 3221 err = ENOTSUP; 3222 break; 3223 } 3224 3225 MUTEX_EXIT(hxgep->genlock); 3226 3227 HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3228 "<== hxge_m_setprop (return %d)", err)); 3229 3230 return (err); 3231 } 3232 3233 static int 3234 hxge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 3235 uint_t pr_valsize, void *pr_val) 3236 { 3237 hxge_t *hxgep = barg; 3238 p_hxge_stats_t statsp = hxgep->statsp; 3239 int err = 0; 3240 link_flowctrl_t fl; 3241 uint64_t tmp = 0; 3242 link_state_t ls; 3243 3244 HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3245 "==> hxge_m_getprop: pr_num %d", pr_num)); 3246 3247 switch (pr_num) { 3248 case MAC_PROP_DUPLEX: 3249 *(uint8_t *)pr_val = statsp->mac_stats.link_duplex; 3250 HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3251 "==> hxge_m_getprop: duplex mode %d", 3252 *(uint8_t *)pr_val)); 3253 break; 3254 3255 case MAC_PROP_SPEED: 3256 ASSERT(pr_valsize >= sizeof (uint64_t)); 3257 tmp = statsp->mac_stats.link_speed * 1000000ull; 3258 bcopy(&tmp, pr_val, sizeof (tmp)); 3259 break; 3260 3261 case MAC_PROP_STATUS: 3262 ASSERT(pr_valsize >= sizeof (link_state_t)); 3263 if (!statsp->mac_stats.link_up) 3264 ls = LINK_STATE_DOWN; 3265 else 3266 ls = LINK_STATE_UP; 3267 bcopy(&ls, pr_val, sizeof (ls)); 3268 break; 3269 3270 case MAC_PROP_FLOWCTRL: 3271 /* 3272 * Flow control is supported by the shared domain and 3273 * it is currently transmit only 3274 */ 3275 ASSERT(pr_valsize < sizeof (link_flowctrl_t)); 3276 fl = LINK_FLOWCTRL_TX; 3277 bcopy(&fl, pr_val, sizeof (fl)); 3278 break; 3279 case MAC_PROP_AUTONEG: 3280 /* 10G link only and it is not negotiable */ 3281 *(uint8_t *)pr_val = 0; 3282 break; 3283 case MAC_PROP_ADV_1000FDX_CAP: 3284 case MAC_PROP_ADV_100FDX_CAP: 3285 case MAC_PROP_ADV_10FDX_CAP: 3286 case MAC_PROP_ADV_1000HDX_CAP: 3287 case MAC_PROP_ADV_100HDX_CAP: 3288 case MAC_PROP_ADV_10HDX_CAP: 3289 case MAC_PROP_EN_1000FDX_CAP: 3290 case MAC_PROP_EN_100FDX_CAP: 3291 case MAC_PROP_EN_10FDX_CAP: 3292 case MAC_PROP_EN_1000HDX_CAP: 3293 case MAC_PROP_EN_100HDX_CAP: 3294 case MAC_PROP_EN_10HDX_CAP: 3295 err = ENOTSUP; 3296 break; 3297 3298 case MAC_PROP_PRIVATE: 3299 err = hxge_get_priv_prop(hxgep, pr_name, pr_valsize, 3300 pr_val); 3301 break; 3302 3303 default: 3304 err = ENOTSUP; 3305 break; 3306 } 3307 3308 HXGE_DEBUG_MSG((hxgep, DLADM_CTL, "<== hxge_m_getprop")); 3309 3310 return (err); 3311 } 3312 3313 static void 3314 hxge_m_propinfo(void *arg, const char *pr_name, 3315 mac_prop_id_t pr_num, mac_prop_info_handle_t prh) 3316 { 3317 _NOTE(ARGUNUSED(arg)); 3318 switch (pr_num) { 3319 case MAC_PROP_DUPLEX: 3320 case MAC_PROP_SPEED: 3321 case MAC_PROP_STATUS: 3322 case MAC_PROP_AUTONEG: 3323 case MAC_PROP_FLOWCTRL: 3324 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 3325 break; 3326 3327 case MAC_PROP_MTU: 3328 mac_prop_info_set_range_uint32(prh, 3329 MIN_FRAME_SIZE - MTU_TO_FRAME_SIZE, 3330 MAX_FRAME_SIZE - MTU_TO_FRAME_SIZE); 3331 break; 3332 3333 case MAC_PROP_PRIVATE: { 3334 char valstr[MAXNAMELEN]; 3335 3336 bzero(valstr, sizeof (valstr)); 3337 3338 /* Receive Interrupt Blanking Parameters */ 3339 if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 3340 (void) snprintf(valstr, sizeof (valstr), "%d", 3341 RXDMA_RCR_TO_DEFAULT); 3342 } else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 3343 (void) snprintf(valstr, sizeof (valstr), "%d", 3344 RXDMA_RCR_PTHRES_DEFAULT); 3345 3346 /* Classification and Load Distribution Configuration */ 3347 } else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0 || 3348 strcmp(pr_name, "_class_opt_ipv4_udp") == 0 || 3349 strcmp(pr_name, "_class_opt_ipv4_ah") == 0 || 3350 strcmp(pr_name, "_class_opt_ipv4_sctp") == 0 || 3351 strcmp(pr_name, "_class_opt_ipv6_tcp") == 0 || 3352 strcmp(pr_name, "_class_opt_ipv6_udp") == 0 || 3353 strcmp(pr_name, "_class_opt_ipv6_ah") == 0 || 3354 strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 3355 (void) snprintf(valstr, sizeof (valstr), "%d", 3356 HXGE_CLASS_TCAM_LOOKUP); 3357 } 3358 3359 if (strlen(valstr) > 0) 3360 mac_prop_info_set_default_str(prh, valstr); 3361 break; 3362 } 3363 } 3364 } 3365 3366 3367 /* ARGSUSED */ 3368 static int 3369 hxge_set_priv_prop(p_hxge_t hxgep, const char *pr_name, uint_t pr_valsize, 3370 const void *pr_val) 3371 { 3372 p_hxge_param_t param_arr = hxgep->param_arr; 3373 int err = 0; 3374 3375 HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3376 "==> hxge_set_priv_prop: name %s (value %s)", pr_name, pr_val)); 3377 3378 if (pr_val == NULL) { 3379 return (EINVAL); 3380 } 3381 3382 /* Blanking */ 3383 if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 3384 err = hxge_param_rx_intr_time(hxgep, NULL, NULL, 3385 (char *)pr_val, (caddr_t)¶m_arr[param_rxdma_intr_time]); 3386 } else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 3387 err = hxge_param_rx_intr_pkts(hxgep, NULL, NULL, 3388 (char *)pr_val, (caddr_t)¶m_arr[param_rxdma_intr_pkts]); 3389 3390 /* Classification */ 3391 } else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) { 3392 err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 3393 (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]); 3394 } else if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) { 3395 err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 3396 (caddr_t)¶m_arr[param_class_opt_ipv4_udp]); 3397 } else if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) { 3398 err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 3399 (caddr_t)¶m_arr[param_class_opt_ipv4_ah]); 3400 } else if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) { 3401 err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 3402 (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]); 3403 } else if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) { 3404 err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 3405 (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]); 3406 } else if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) { 3407 err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 3408 (caddr_t)¶m_arr[param_class_opt_ipv6_udp]); 3409 } else if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) { 3410 err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 3411 (caddr_t)¶m_arr[param_class_opt_ipv6_ah]); 3412 } else if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 3413 err = hxge_param_set_ip_opt(hxgep, NULL, NULL, (char *)pr_val, 3414 (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]); 3415 } else { 3416 err = ENOTSUP; 3417 } 3418 3419 HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3420 "<== hxge_set_priv_prop: err %d", err)); 3421 3422 return (err); 3423 } 3424 3425 static int 3426 hxge_get_priv_prop(p_hxge_t hxgep, const char *pr_name, uint_t pr_valsize, 3427 void *pr_val) 3428 { 3429 p_hxge_param_t param_arr = hxgep->param_arr; 3430 char valstr[MAXNAMELEN]; 3431 int err = 0; 3432 uint_t strsize; 3433 int value = 0; 3434 3435 HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3436 "==> hxge_get_priv_prop: property %s", pr_name)); 3437 3438 /* Receive Interrupt Blanking Parameters */ 3439 if (strcmp(pr_name, "_rxdma_intr_time") == 0) { 3440 value = hxgep->intr_timeout; 3441 } else if (strcmp(pr_name, "_rxdma_intr_pkts") == 0) { 3442 value = hxgep->intr_threshold; 3443 3444 /* Classification and Load Distribution Configuration */ 3445 } else if (strcmp(pr_name, "_class_opt_ipv4_tcp") == 0) { 3446 err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 3447 (caddr_t)¶m_arr[param_class_opt_ipv4_tcp]); 3448 3449 value = (int)param_arr[param_class_opt_ipv4_tcp].value; 3450 } else if (strcmp(pr_name, "_class_opt_ipv4_udp") == 0) { 3451 err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 3452 (caddr_t)¶m_arr[param_class_opt_ipv4_udp]); 3453 3454 value = (int)param_arr[param_class_opt_ipv4_udp].value; 3455 } else if (strcmp(pr_name, "_class_opt_ipv4_ah") == 0) { 3456 err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 3457 (caddr_t)¶m_arr[param_class_opt_ipv4_ah]); 3458 3459 value = (int)param_arr[param_class_opt_ipv4_ah].value; 3460 } else if (strcmp(pr_name, "_class_opt_ipv4_sctp") == 0) { 3461 err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 3462 (caddr_t)¶m_arr[param_class_opt_ipv4_sctp]); 3463 3464 value = (int)param_arr[param_class_opt_ipv4_sctp].value; 3465 } else if (strcmp(pr_name, "_class_opt_ipv6_tcp") == 0) { 3466 err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 3467 (caddr_t)¶m_arr[param_class_opt_ipv6_tcp]); 3468 3469 value = (int)param_arr[param_class_opt_ipv6_tcp].value; 3470 } else if (strcmp(pr_name, "_class_opt_ipv6_udp") == 0) { 3471 err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 3472 (caddr_t)¶m_arr[param_class_opt_ipv6_udp]); 3473 3474 value = (int)param_arr[param_class_opt_ipv6_udp].value; 3475 } else if (strcmp(pr_name, "_class_opt_ipv6_ah") == 0) { 3476 err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 3477 (caddr_t)¶m_arr[param_class_opt_ipv6_ah]); 3478 3479 value = (int)param_arr[param_class_opt_ipv6_ah].value; 3480 } else if (strcmp(pr_name, "_class_opt_ipv6_sctp") == 0) { 3481 err = hxge_param_get_ip_opt(hxgep, NULL, NULL, 3482 (caddr_t)¶m_arr[param_class_opt_ipv6_sctp]); 3483 3484 value = (int)param_arr[param_class_opt_ipv6_sctp].value; 3485 } else { 3486 err = ENOTSUP; 3487 } 3488 3489 if (err == 0) { 3490 (void) snprintf(valstr, sizeof (valstr), "0x%x", value); 3491 3492 strsize = (uint_t)strlen(valstr); 3493 if (pr_valsize < strsize) { 3494 err = ENOBUFS; 3495 } else { 3496 (void) strlcpy(pr_val, valstr, pr_valsize); 3497 } 3498 } 3499 3500 HXGE_DEBUG_MSG((hxgep, DLADM_CTL, 3501 "<== hxge_get_priv_prop: return %d", err)); 3502 3503 return (err); 3504 } 3505 /* 3506 * Module loading and removing entry points. 3507 */ 3508 DDI_DEFINE_STREAM_OPS(hxge_dev_ops, nulldev, nulldev, hxge_attach, hxge_detach, 3509 nodev, NULL, D_MP, NULL, NULL); 3510 3511 extern struct mod_ops mod_driverops; 3512 3513 #define HXGE_DESC_VER "HXGE 10Gb Ethernet Driver" 3514 3515 /* 3516 * Module linkage information for the kernel. 3517 */ 3518 static struct modldrv hxge_modldrv = { 3519 &mod_driverops, 3520 HXGE_DESC_VER, 3521 &hxge_dev_ops 3522 }; 3523 3524 static struct modlinkage modlinkage = { 3525 MODREV_1, (void *) &hxge_modldrv, NULL 3526 }; 3527 3528 int 3529 _init(void) 3530 { 3531 int status; 3532 3533 HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _init")); 3534 mac_init_ops(&hxge_dev_ops, "hxge"); 3535 status = ddi_soft_state_init(&hxge_list, sizeof (hxge_t), 0); 3536 if (status != 0) { 3537 HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL, 3538 "failed to init device soft state")); 3539 mac_fini_ops(&hxge_dev_ops); 3540 goto _init_exit; 3541 } 3542 3543 status = mod_install(&modlinkage); 3544 if (status != 0) { 3545 ddi_soft_state_fini(&hxge_list); 3546 HXGE_ERROR_MSG((NULL, HXGE_ERR_CTL, "Mod install failed")); 3547 goto _init_exit; 3548 } 3549 3550 MUTEX_INIT(&hxge_common_lock, NULL, MUTEX_DRIVER, NULL); 3551 3552 _init_exit: 3553 HXGE_DEBUG_MSG((NULL, MOD_CTL, "_init status = 0x%X", status)); 3554 3555 return (status); 3556 } 3557 3558 int 3559 _fini(void) 3560 { 3561 int status; 3562 3563 HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini")); 3564 3565 HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _fini: mod_remove")); 3566 3567 if (hxge_mblks_pending) 3568 return (EBUSY); 3569 3570 status = mod_remove(&modlinkage); 3571 if (status != DDI_SUCCESS) { 3572 HXGE_DEBUG_MSG((NULL, MOD_CTL, 3573 "Module removal failed 0x%08x", status)); 3574 goto _fini_exit; 3575 } 3576 3577 mac_fini_ops(&hxge_dev_ops); 3578 3579 ddi_soft_state_fini(&hxge_list); 3580 3581 MUTEX_DESTROY(&hxge_common_lock); 3582 3583 _fini_exit: 3584 HXGE_DEBUG_MSG((NULL, MOD_CTL, "_fini status = 0x%08x", status)); 3585 3586 return (status); 3587 } 3588 3589 int 3590 _info(struct modinfo *modinfop) 3591 { 3592 int status; 3593 3594 HXGE_DEBUG_MSG((NULL, MOD_CTL, "==> _info")); 3595 status = mod_info(&modlinkage, modinfop); 3596 HXGE_DEBUG_MSG((NULL, MOD_CTL, " _info status = 0x%X", status)); 3597 3598 return (status); 3599 } 3600 3601 /*ARGSUSED*/ 3602 static hxge_status_t 3603 hxge_add_intrs(p_hxge_t hxgep) 3604 { 3605 int intr_types; 3606 int type = 0; 3607 int ddi_status = DDI_SUCCESS; 3608 hxge_status_t status = HXGE_OK; 3609 3610 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs")); 3611 3612 hxgep->hxge_intr_type.intr_registered = B_FALSE; 3613 hxgep->hxge_intr_type.intr_enabled = B_FALSE; 3614 hxgep->hxge_intr_type.msi_intx_cnt = 0; 3615 hxgep->hxge_intr_type.intr_added = 0; 3616 hxgep->hxge_intr_type.niu_msi_enable = B_FALSE; 3617 hxgep->hxge_intr_type.intr_type = 0; 3618 3619 if (hxge_msi_enable) { 3620 hxgep->hxge_intr_type.niu_msi_enable = B_TRUE; 3621 } 3622 3623 /* Get the supported interrupt types */ 3624 if ((ddi_status = ddi_intr_get_supported_types(hxgep->dip, &intr_types)) 3625 != DDI_SUCCESS) { 3626 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_add_intrs: " 3627 "ddi_intr_get_supported_types failed: status 0x%08x", 3628 ddi_status)); 3629 return (HXGE_ERROR | HXGE_DDI_FAILED); 3630 } 3631 3632 hxgep->hxge_intr_type.intr_types = intr_types; 3633 3634 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: " 3635 "ddi_intr_get_supported_types: 0x%08x", intr_types)); 3636 3637 /* 3638 * Pick the interrupt type to use MSIX, MSI, INTX hxge_msi_enable: 3639 * (1): 1 - MSI 3640 * (2): 2 - MSI-X 3641 * others - FIXED 3642 */ 3643 switch (hxge_msi_enable) { 3644 default: 3645 type = DDI_INTR_TYPE_FIXED; 3646 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: " 3647 "use fixed (intx emulation) type %08x", type)); 3648 break; 3649 3650 case 2: 3651 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: " 3652 "ddi_intr_get_supported_types: 0x%08x", intr_types)); 3653 if (intr_types & DDI_INTR_TYPE_MSIX) { 3654 type = DDI_INTR_TYPE_MSIX; 3655 HXGE_DEBUG_MSG((hxgep, INT_CTL, 3656 "==> hxge_add_intrs: " 3657 "ddi_intr_get_supported_types: MSIX 0x%08x", type)); 3658 } else if (intr_types & DDI_INTR_TYPE_MSI) { 3659 type = DDI_INTR_TYPE_MSI; 3660 HXGE_DEBUG_MSG((hxgep, INT_CTL, 3661 "==> hxge_add_intrs: " 3662 "ddi_intr_get_supported_types: MSI 0x%08x", type)); 3663 } else if (intr_types & DDI_INTR_TYPE_FIXED) { 3664 type = DDI_INTR_TYPE_FIXED; 3665 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs: " 3666 "ddi_intr_get_supported_types: MSXED0x%08x", type)); 3667 } 3668 break; 3669 3670 case 1: 3671 if (intr_types & DDI_INTR_TYPE_MSI) { 3672 type = DDI_INTR_TYPE_MSI; 3673 HXGE_DEBUG_MSG((hxgep, INT_CTL, 3674 "==> hxge_add_intrs: " 3675 "ddi_intr_get_supported_types: MSI 0x%08x", type)); 3676 } else if (intr_types & DDI_INTR_TYPE_MSIX) { 3677 type = DDI_INTR_TYPE_MSIX; 3678 HXGE_DEBUG_MSG((hxgep, INT_CTL, 3679 "==> hxge_add_intrs: " 3680 "ddi_intr_get_supported_types: MSIX 0x%08x", type)); 3681 } else if (intr_types & DDI_INTR_TYPE_FIXED) { 3682 type = DDI_INTR_TYPE_FIXED; 3683 HXGE_DEBUG_MSG((hxgep, INT_CTL, 3684 "==> hxge_add_intrs: " 3685 "ddi_intr_get_supported_types: MSXED0x%08x", type)); 3686 } 3687 } 3688 3689 hxgep->hxge_intr_type.intr_type = type; 3690 if ((type == DDI_INTR_TYPE_MSIX || type == DDI_INTR_TYPE_MSI || 3691 type == DDI_INTR_TYPE_FIXED) && 3692 hxgep->hxge_intr_type.niu_msi_enable) { 3693 if ((status = hxge_add_intrs_adv(hxgep)) != DDI_SUCCESS) { 3694 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 3695 " hxge_add_intrs: " 3696 " hxge_add_intrs_adv failed: status 0x%08x", 3697 status)); 3698 return (status); 3699 } else { 3700 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_add_intrs: " 3701 "interrupts registered : type %d", type)); 3702 hxgep->hxge_intr_type.intr_registered = B_TRUE; 3703 3704 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 3705 "\nAdded advanced hxge add_intr_adv " 3706 "intr type 0x%x\n", type)); 3707 3708 return (status); 3709 } 3710 } 3711 3712 if (!hxgep->hxge_intr_type.intr_registered) { 3713 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 3714 "==> hxge_add_intrs: failed to register interrupts")); 3715 return (HXGE_ERROR | HXGE_DDI_FAILED); 3716 } 3717 3718 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs")); 3719 3720 return (status); 3721 } 3722 3723 /*ARGSUSED*/ 3724 static hxge_status_t 3725 hxge_add_intrs_adv(p_hxge_t hxgep) 3726 { 3727 int intr_type; 3728 p_hxge_intr_t intrp; 3729 hxge_status_t status; 3730 3731 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv")); 3732 3733 intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type; 3734 intr_type = intrp->intr_type; 3735 3736 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv: type 0x%x", 3737 intr_type)); 3738 3739 switch (intr_type) { 3740 case DDI_INTR_TYPE_MSI: /* 0x2 */ 3741 case DDI_INTR_TYPE_MSIX: /* 0x4 */ 3742 status = hxge_add_intrs_adv_type(hxgep, intr_type); 3743 break; 3744 3745 case DDI_INTR_TYPE_FIXED: /* 0x1 */ 3746 status = hxge_add_intrs_adv_type_fix(hxgep, intr_type); 3747 break; 3748 3749 default: 3750 status = HXGE_ERROR; 3751 break; 3752 } 3753 3754 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv")); 3755 3756 return (status); 3757 } 3758 3759 /*ARGSUSED*/ 3760 static hxge_status_t 3761 hxge_add_intrs_adv_type(p_hxge_t hxgep, uint32_t int_type) 3762 { 3763 dev_info_t *dip = hxgep->dip; 3764 p_hxge_ldg_t ldgp; 3765 p_hxge_intr_t intrp; 3766 uint_t *inthandler; 3767 void *arg1, *arg2; 3768 int behavior; 3769 int nintrs, navail; 3770 int nactual, nrequired, nrequest; 3771 int inum = 0; 3772 int loop = 0; 3773 int x, y; 3774 int ddi_status = DDI_SUCCESS; 3775 hxge_status_t status = HXGE_OK; 3776 3777 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv_type")); 3778 3779 intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type; 3780 3781 ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 3782 if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 3783 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 3784 "ddi_intr_get_nintrs() failed, status: 0x%x%, " 3785 "nintrs: %d", ddi_status, nintrs)); 3786 return (HXGE_ERROR | HXGE_DDI_FAILED); 3787 } 3788 3789 ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 3790 if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 3791 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 3792 "ddi_intr_get_navail() failed, status: 0x%x%, " 3793 "nintrs: %d", ddi_status, navail)); 3794 return (HXGE_ERROR | HXGE_DDI_FAILED); 3795 } 3796 3797 HXGE_DEBUG_MSG((hxgep, INT_CTL, 3798 "ddi_intr_get_navail() returned: intr type %d nintrs %d, navail %d", 3799 int_type, nintrs, navail)); 3800 3801 /* PSARC/2007/453 MSI-X interrupt limit override */ 3802 if (int_type == DDI_INTR_TYPE_MSIX) { 3803 nrequest = hxge_create_msi_property(hxgep); 3804 if (nrequest < navail) { 3805 navail = nrequest; 3806 HXGE_DEBUG_MSG((hxgep, INT_CTL, 3807 "hxge_add_intrs_adv_type: nintrs %d " 3808 "navail %d (nrequest %d)", 3809 nintrs, navail, nrequest)); 3810 } 3811 } 3812 3813 if (int_type == DDI_INTR_TYPE_MSI && !ISP2(navail)) { 3814 /* MSI must be power of 2 */ 3815 if ((navail & 16) == 16) { 3816 navail = 16; 3817 } else if ((navail & 8) == 8) { 3818 navail = 8; 3819 } else if ((navail & 4) == 4) { 3820 navail = 4; 3821 } else if ((navail & 2) == 2) { 3822 navail = 2; 3823 } else { 3824 navail = 1; 3825 } 3826 HXGE_DEBUG_MSG((hxgep, INT_CTL, 3827 "ddi_intr_get_navail(): (msi power of 2) nintrs %d, " 3828 "navail %d", nintrs, navail)); 3829 } 3830 3831 HXGE_DEBUG_MSG((hxgep, INT_CTL, 3832 "requesting: intr type %d nintrs %d, navail %d", 3833 int_type, nintrs, navail)); 3834 3835 behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 3836 DDI_INTR_ALLOC_NORMAL); 3837 intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 3838 intrp->htable = kmem_zalloc(intrp->intr_size, KM_SLEEP); 3839 3840 ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 3841 navail, &nactual, behavior); 3842 if (ddi_status != DDI_SUCCESS || nactual == 0) { 3843 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 3844 " ddi_intr_alloc() failed: %d", ddi_status)); 3845 kmem_free(intrp->htable, intrp->intr_size); 3846 return (HXGE_ERROR | HXGE_DDI_FAILED); 3847 } 3848 3849 HXGE_DEBUG_MSG((hxgep, INT_CTL, 3850 "ddi_intr_alloc() returned: navail %d nactual %d", 3851 navail, nactual)); 3852 3853 if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 3854 (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 3855 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 3856 " ddi_intr_get_pri() failed: %d", ddi_status)); 3857 /* Free already allocated interrupts */ 3858 for (y = 0; y < nactual; y++) { 3859 (void) ddi_intr_free(intrp->htable[y]); 3860 } 3861 3862 kmem_free(intrp->htable, intrp->intr_size); 3863 return (HXGE_ERROR | HXGE_DDI_FAILED); 3864 } 3865 3866 nrequired = 0; 3867 status = hxge_ldgv_init(hxgep, &nactual, &nrequired); 3868 if (status != HXGE_OK) { 3869 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 3870 "hxge_add_intrs_adv_typ:hxge_ldgv_init " 3871 "failed: 0x%x", status)); 3872 /* Free already allocated interrupts */ 3873 for (y = 0; y < nactual; y++) { 3874 (void) ddi_intr_free(intrp->htable[y]); 3875 } 3876 3877 kmem_free(intrp->htable, intrp->intr_size); 3878 return (status); 3879 } 3880 3881 ldgp = hxgep->ldgvp->ldgp; 3882 HXGE_DEBUG_MSG((hxgep, INT_CTL, 3883 "After hxge_ldgv_init(): nreq %d nactual %d", nrequired, nactual)); 3884 3885 if (nactual < nrequired) 3886 loop = nactual; 3887 else 3888 loop = nrequired; 3889 3890 for (x = 0; x < loop; x++, ldgp++) { 3891 ldgp->vector = (uint8_t)x; 3892 arg1 = ldgp->ldvp; 3893 arg2 = hxgep; 3894 if (ldgp->nldvs == 1) { 3895 inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 3896 HXGE_DEBUG_MSG((hxgep, INT_CTL, 3897 "hxge_add_intrs_adv_type: arg1 0x%x arg2 0x%x: " 3898 "1-1 int handler (entry %d)\n", 3899 arg1, arg2, x)); 3900 } else if (ldgp->nldvs > 1) { 3901 inthandler = (uint_t *)ldgp->sys_intr_handler; 3902 HXGE_DEBUG_MSG((hxgep, INT_CTL, 3903 "hxge_add_intrs_adv_type: arg1 0x%x arg2 0x%x: " 3904 "nldevs %d int handler (entry %d)\n", 3905 arg1, arg2, ldgp->nldvs, x)); 3906 } 3907 HXGE_DEBUG_MSG((hxgep, INT_CTL, 3908 "==> hxge_add_intrs_adv_type: ddi_add_intr(inum) #%d " 3909 "htable 0x%llx", x, intrp->htable[x])); 3910 3911 if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 3912 (ddi_intr_handler_t *)inthandler, arg1, arg2)) != 3913 DDI_SUCCESS) { 3914 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 3915 "==> hxge_add_intrs_adv_type: failed #%d " 3916 "status 0x%x", x, ddi_status)); 3917 for (y = 0; y < intrp->intr_added; y++) { 3918 (void) ddi_intr_remove_handler( 3919 intrp->htable[y]); 3920 } 3921 3922 /* Free already allocated intr */ 3923 for (y = 0; y < nactual; y++) { 3924 (void) ddi_intr_free(intrp->htable[y]); 3925 } 3926 kmem_free(intrp->htable, intrp->intr_size); 3927 3928 (void) hxge_ldgv_uninit(hxgep); 3929 3930 return (HXGE_ERROR | HXGE_DDI_FAILED); 3931 } 3932 3933 ldgp->htable_idx = x; 3934 intrp->intr_added++; 3935 } 3936 intrp->msi_intx_cnt = nactual; 3937 3938 HXGE_DEBUG_MSG((hxgep, INT_CTL, 3939 "Requested: %d, Allowed: %d msi_intx_cnt %d intr_added %d", 3940 navail, nactual, intrp->msi_intx_cnt, intrp->intr_added)); 3941 3942 (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 3943 (void) hxge_intr_ldgv_init(hxgep); 3944 3945 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv_type")); 3946 3947 return (status); 3948 } 3949 3950 /*ARGSUSED*/ 3951 static hxge_status_t 3952 hxge_add_intrs_adv_type_fix(p_hxge_t hxgep, uint32_t int_type) 3953 { 3954 dev_info_t *dip = hxgep->dip; 3955 p_hxge_ldg_t ldgp; 3956 p_hxge_intr_t intrp; 3957 uint_t *inthandler; 3958 void *arg1, *arg2; 3959 int behavior; 3960 int nintrs, navail; 3961 int nactual, nrequired; 3962 int inum = 0; 3963 int x, y; 3964 int ddi_status = DDI_SUCCESS; 3965 hxge_status_t status = HXGE_OK; 3966 3967 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_add_intrs_adv_type_fix")); 3968 intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type; 3969 3970 ddi_status = ddi_intr_get_nintrs(dip, int_type, &nintrs); 3971 if ((ddi_status != DDI_SUCCESS) || (nintrs == 0)) { 3972 HXGE_DEBUG_MSG((hxgep, INT_CTL, 3973 "ddi_intr_get_nintrs() failed, status: 0x%x%, " 3974 "nintrs: %d", status, nintrs)); 3975 return (HXGE_ERROR | HXGE_DDI_FAILED); 3976 } 3977 3978 ddi_status = ddi_intr_get_navail(dip, int_type, &navail); 3979 if ((ddi_status != DDI_SUCCESS) || (navail == 0)) { 3980 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 3981 "ddi_intr_get_navail() failed, status: 0x%x%, " 3982 "nintrs: %d", ddi_status, navail)); 3983 return (HXGE_ERROR | HXGE_DDI_FAILED); 3984 } 3985 3986 HXGE_DEBUG_MSG((hxgep, INT_CTL, 3987 "ddi_intr_get_navail() returned: nintrs %d, naavail %d", 3988 nintrs, navail)); 3989 3990 behavior = ((int_type == DDI_INTR_TYPE_FIXED) ? DDI_INTR_ALLOC_STRICT : 3991 DDI_INTR_ALLOC_NORMAL); 3992 intrp->intr_size = navail * sizeof (ddi_intr_handle_t); 3993 intrp->htable = kmem_alloc(intrp->intr_size, KM_SLEEP); 3994 ddi_status = ddi_intr_alloc(dip, intrp->htable, int_type, inum, 3995 navail, &nactual, behavior); 3996 if (ddi_status != DDI_SUCCESS || nactual == 0) { 3997 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 3998 " ddi_intr_alloc() failed: %d", ddi_status)); 3999 kmem_free(intrp->htable, intrp->intr_size); 4000 return (HXGE_ERROR | HXGE_DDI_FAILED); 4001 } 4002 4003 if ((ddi_status = ddi_intr_get_pri(intrp->htable[0], 4004 (uint_t *)&intrp->pri)) != DDI_SUCCESS) { 4005 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 4006 " ddi_intr_get_pri() failed: %d", ddi_status)); 4007 /* Free already allocated interrupts */ 4008 for (y = 0; y < nactual; y++) { 4009 (void) ddi_intr_free(intrp->htable[y]); 4010 } 4011 4012 kmem_free(intrp->htable, intrp->intr_size); 4013 return (HXGE_ERROR | HXGE_DDI_FAILED); 4014 } 4015 4016 nrequired = 0; 4017 status = hxge_ldgv_init(hxgep, &nactual, &nrequired); 4018 if (status != HXGE_OK) { 4019 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 4020 "hxge_add_intrs_adv_type_fix:hxge_ldgv_init " 4021 "failed: 0x%x", status)); 4022 /* Free already allocated interrupts */ 4023 for (y = 0; y < nactual; y++) { 4024 (void) ddi_intr_free(intrp->htable[y]); 4025 } 4026 4027 kmem_free(intrp->htable, intrp->intr_size); 4028 return (status); 4029 } 4030 4031 ldgp = hxgep->ldgvp->ldgp; 4032 for (x = 0; x < nrequired; x++, ldgp++) { 4033 ldgp->vector = (uint8_t)x; 4034 arg1 = ldgp->ldvp; 4035 arg2 = hxgep; 4036 if (ldgp->nldvs == 1) { 4037 inthandler = (uint_t *)ldgp->ldvp->ldv_intr_handler; 4038 HXGE_DEBUG_MSG((hxgep, INT_CTL, 4039 "hxge_add_intrs_adv_type_fix: " 4040 "1-1 int handler(%d) ldg %d ldv %d " 4041 "arg1 $%p arg2 $%p\n", 4042 x, ldgp->ldg, ldgp->ldvp->ldv, arg1, arg2)); 4043 } else if (ldgp->nldvs > 1) { 4044 inthandler = (uint_t *)ldgp->sys_intr_handler; 4045 HXGE_DEBUG_MSG((hxgep, INT_CTL, 4046 "hxge_add_intrs_adv_type_fix: " 4047 "shared ldv %d int handler(%d) ldv %d ldg %d" 4048 "arg1 0x%016llx arg2 0x%016llx\n", 4049 x, ldgp->nldvs, ldgp->ldg, ldgp->ldvp->ldv, 4050 arg1, arg2)); 4051 } 4052 4053 if ((ddi_status = ddi_intr_add_handler(intrp->htable[x], 4054 (ddi_intr_handler_t *)inthandler, arg1, arg2)) != 4055 DDI_SUCCESS) { 4056 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, 4057 "==> hxge_add_intrs_adv_type_fix: failed #%d " 4058 "status 0x%x", x, ddi_status)); 4059 for (y = 0; y < intrp->intr_added; y++) { 4060 (void) ddi_intr_remove_handler( 4061 intrp->htable[y]); 4062 } 4063 for (y = 0; y < nactual; y++) { 4064 (void) ddi_intr_free(intrp->htable[y]); 4065 } 4066 /* Free already allocated intr */ 4067 kmem_free(intrp->htable, intrp->intr_size); 4068 4069 (void) hxge_ldgv_uninit(hxgep); 4070 4071 return (HXGE_ERROR | HXGE_DDI_FAILED); 4072 } 4073 intrp->intr_added++; 4074 } 4075 4076 intrp->msi_intx_cnt = nactual; 4077 4078 (void) ddi_intr_get_cap(intrp->htable[0], &intrp->intr_cap); 4079 4080 status = hxge_intr_ldgv_init(hxgep); 4081 4082 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_add_intrs_adv_type_fix")); 4083 4084 return (status); 4085 } 4086 4087 /*ARGSUSED*/ 4088 static void 4089 hxge_remove_intrs(p_hxge_t hxgep) 4090 { 4091 int i, inum; 4092 p_hxge_intr_t intrp; 4093 4094 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_remove_intrs")); 4095 intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type; 4096 if (!intrp->intr_registered) { 4097 HXGE_DEBUG_MSG((hxgep, INT_CTL, 4098 "<== hxge_remove_intrs: interrupts not registered")); 4099 return; 4100 } 4101 4102 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_remove_intrs:advanced")); 4103 4104 if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 4105 (void) ddi_intr_block_disable(intrp->htable, 4106 intrp->intr_added); 4107 } else { 4108 for (i = 0; i < intrp->intr_added; i++) { 4109 (void) ddi_intr_disable(intrp->htable[i]); 4110 } 4111 } 4112 4113 for (inum = 0; inum < intrp->intr_added; inum++) { 4114 if (intrp->htable[inum]) { 4115 (void) ddi_intr_remove_handler(intrp->htable[inum]); 4116 } 4117 } 4118 4119 for (inum = 0; inum < intrp->msi_intx_cnt; inum++) { 4120 if (intrp->htable[inum]) { 4121 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 4122 "hxge_remove_intrs: ddi_intr_free inum %d " 4123 "msi_intx_cnt %d intr_added %d", 4124 inum, intrp->msi_intx_cnt, intrp->intr_added)); 4125 4126 (void) ddi_intr_free(intrp->htable[inum]); 4127 } 4128 } 4129 4130 kmem_free(intrp->htable, intrp->intr_size); 4131 intrp->intr_registered = B_FALSE; 4132 intrp->intr_enabled = B_FALSE; 4133 intrp->msi_intx_cnt = 0; 4134 intrp->intr_added = 0; 4135 4136 (void) hxge_ldgv_uninit(hxgep); 4137 4138 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_remove_intrs")); 4139 } 4140 4141 /*ARGSUSED*/ 4142 static void 4143 hxge_intrs_enable(p_hxge_t hxgep) 4144 { 4145 p_hxge_intr_t intrp; 4146 int i; 4147 int status; 4148 4149 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable")); 4150 4151 intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type; 4152 4153 if (!intrp->intr_registered) { 4154 HXGE_ERROR_MSG((hxgep, HXGE_ERR_CTL, "<== hxge_intrs_enable: " 4155 "interrupts are not registered")); 4156 return; 4157 } 4158 4159 if (intrp->intr_enabled) { 4160 HXGE_DEBUG_MSG((hxgep, INT_CTL, 4161 "<== hxge_intrs_enable: already enabled")); 4162 return; 4163 } 4164 4165 if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 4166 status = ddi_intr_block_enable(intrp->htable, 4167 intrp->intr_added); 4168 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable " 4169 "block enable - status 0x%x total inums #%d\n", 4170 status, intrp->intr_added)); 4171 } else { 4172 for (i = 0; i < intrp->intr_added; i++) { 4173 status = ddi_intr_enable(intrp->htable[i]); 4174 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_enable " 4175 "ddi_intr_enable:enable - status 0x%x " 4176 "total inums %d enable inum #%d\n", 4177 status, intrp->intr_added, i)); 4178 if (status == DDI_SUCCESS) { 4179 intrp->intr_enabled = B_TRUE; 4180 } 4181 } 4182 } 4183 4184 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_enable")); 4185 } 4186 4187 /*ARGSUSED*/ 4188 static void 4189 hxge_intrs_disable(p_hxge_t hxgep) 4190 { 4191 p_hxge_intr_t intrp; 4192 int i; 4193 4194 HXGE_DEBUG_MSG((hxgep, INT_CTL, "==> hxge_intrs_disable")); 4195 4196 intrp = (p_hxge_intr_t)&hxgep->hxge_intr_type; 4197 4198 if (!intrp->intr_registered) { 4199 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_disable: " 4200 "interrupts are not registered")); 4201 return; 4202 } 4203 4204 if (intrp->intr_cap & DDI_INTR_FLAG_BLOCK) { 4205 (void) ddi_intr_block_disable(intrp->htable, 4206 intrp->intr_added); 4207 } else { 4208 for (i = 0; i < intrp->intr_added; i++) { 4209 (void) ddi_intr_disable(intrp->htable[i]); 4210 } 4211 } 4212 4213 intrp->intr_enabled = B_FALSE; 4214 HXGE_DEBUG_MSG((hxgep, INT_CTL, "<== hxge_intrs_disable")); 4215 } 4216 4217 static hxge_status_t 4218 hxge_mac_register(p_hxge_t hxgep) 4219 { 4220 mac_register_t *macp; 4221 int status; 4222 4223 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "==> hxge_mac_register")); 4224 4225 if ((macp = mac_alloc(MAC_VERSION)) == NULL) 4226 return (HXGE_ERROR); 4227 4228 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 4229 macp->m_driver = hxgep; 4230 macp->m_dip = hxgep->dip; 4231 macp->m_src_addr = hxgep->ouraddr.ether_addr_octet; 4232 macp->m_callbacks = &hxge_m_callbacks; 4233 macp->m_min_sdu = 0; 4234 macp->m_max_sdu = hxgep->vmac.maxframesize - MTU_TO_FRAME_SIZE; 4235 macp->m_margin = VLAN_TAGSZ; 4236 macp->m_priv_props = hxge_priv_props; 4237 macp->m_v12n = MAC_VIRT_LEVEL1; 4238 4239 HXGE_DEBUG_MSG((hxgep, DDI_CTL, 4240 "hxge_mac_register: ether addr is %x:%x:%x:%x:%x:%x", 4241 macp->m_src_addr[0], 4242 macp->m_src_addr[1], 4243 macp->m_src_addr[2], 4244 macp->m_src_addr[3], 4245 macp->m_src_addr[4], 4246 macp->m_src_addr[5])); 4247 4248 status = mac_register(macp, &hxgep->mach); 4249 mac_free(macp); 4250 4251 if (status != 0) { 4252 cmn_err(CE_WARN, 4253 "hxge_mac_register failed (status %d instance %d)", 4254 status, hxgep->instance); 4255 return (HXGE_ERROR); 4256 } 4257 4258 HXGE_DEBUG_MSG((hxgep, DDI_CTL, "<== hxge_mac_register success " 4259 "(instance %d)", hxgep->instance)); 4260 4261 return (HXGE_OK); 4262 } 4263 4264 static int 4265 hxge_init_common_dev(p_hxge_t hxgep) 4266 { 4267 p_hxge_hw_list_t hw_p; 4268 dev_info_t *p_dip; 4269 4270 HXGE_DEBUG_MSG((hxgep, MOD_CTL, "==> hxge_init_common_dev")); 4271 4272 p_dip = hxgep->p_dip; 4273 MUTEX_ENTER(&hxge_common_lock); 4274 4275 /* 4276 * Loop through existing per Hydra hardware list. 4277 */ 4278 for (hw_p = hxge_hw_list; hw_p; hw_p = hw_p->next) { 4279 HXGE_DEBUG_MSG((hxgep, MOD_CTL, 4280 "==> hxge_init_common_dev: hw_p $%p parent dip $%p", 4281 hw_p, p_dip)); 4282 if (hw_p->parent_devp == p_dip) { 4283 hxgep->hxge_hw_p = hw_p; 4284 hw_p->ndevs++; 4285 hw_p->hxge_p = hxgep; 4286 HXGE_DEBUG_MSG((hxgep, MOD_CTL, 4287 "==> hxge_init_common_device: " 4288 "hw_p $%p parent dip $%p ndevs %d (found)", 4289 hw_p, p_dip, hw_p->ndevs)); 4290 break; 4291 } 4292 } 4293 4294 if (hw_p == NULL) { 4295 HXGE_DEBUG_MSG((hxgep, MOD_CTL, 4296 "==> hxge_init_common_dev: parent dip $%p (new)", p_dip)); 4297 hw_p = kmem_zalloc(sizeof (hxge_hw_list_t), KM_SLEEP); 4298 hw_p->parent_devp = p_dip; 4299 hw_p->magic = HXGE_MAGIC; 4300 hxgep->hxge_hw_p = hw_p; 4301 hw_p->ndevs++; 4302 hw_p->hxge_p = hxgep; 4303 hw_p->next = hxge_hw_list; 4304 4305 MUTEX_INIT(&hw_p->hxge_cfg_lock, NULL, MUTEX_DRIVER, NULL); 4306 MUTEX_INIT(&hw_p->hxge_tcam_lock, NULL, MUTEX_DRIVER, NULL); 4307 MUTEX_INIT(&hw_p->hxge_vlan_lock, NULL, MUTEX_DRIVER, NULL); 4308 4309 hxge_hw_list = hw_p; 4310 } 4311 MUTEX_EXIT(&hxge_common_lock); 4312 HXGE_DEBUG_MSG((hxgep, MOD_CTL, 4313 "==> hxge_init_common_dev (hxge_hw_list) $%p", hxge_hw_list)); 4314 HXGE_DEBUG_MSG((hxgep, MOD_CTL, "<== hxge_init_common_dev")); 4315 4316 return (HXGE_OK); 4317 } 4318 4319 static void 4320 hxge_uninit_common_dev(p_hxge_t hxgep) 4321 { 4322 p_hxge_hw_list_t hw_p, h_hw_p; 4323 dev_info_t *p_dip; 4324 4325 HXGE_DEBUG_MSG((hxgep, MOD_CTL, "==> hxge_uninit_common_dev")); 4326 if (hxgep->hxge_hw_p == NULL) { 4327 HXGE_DEBUG_MSG((hxgep, MOD_CTL, 4328 "<== hxge_uninit_common_dev (no common)")); 4329 return; 4330 } 4331 4332 MUTEX_ENTER(&hxge_common_lock); 4333 h_hw_p = hxge_hw_list; 4334 for (hw_p = hxge_hw_list; hw_p; hw_p = hw_p->next) { 4335 p_dip = hw_p->parent_devp; 4336 if (hxgep->hxge_hw_p == hw_p && p_dip == hxgep->p_dip && 4337 hxgep->hxge_hw_p->magic == HXGE_MAGIC && 4338 hw_p->magic == HXGE_MAGIC) { 4339 HXGE_DEBUG_MSG((hxgep, MOD_CTL, 4340 "==> hxge_uninit_common_dev: " 4341 "hw_p $%p parent dip $%p ndevs %d (found)", 4342 hw_p, p_dip, hw_p->ndevs)); 4343 4344 hxgep->hxge_hw_p = NULL; 4345 if (hw_p->ndevs) { 4346 hw_p->ndevs--; 4347 } 4348 hw_p->hxge_p = NULL; 4349 if (!hw_p->ndevs) { 4350 MUTEX_DESTROY(&hw_p->hxge_vlan_lock); 4351 MUTEX_DESTROY(&hw_p->hxge_tcam_lock); 4352 MUTEX_DESTROY(&hw_p->hxge_cfg_lock); 4353 HXGE_DEBUG_MSG((hxgep, MOD_CTL, 4354 "==> hxge_uninit_common_dev: " 4355 "hw_p $%p parent dip $%p ndevs %d (last)", 4356 hw_p, p_dip, hw_p->ndevs)); 4357 4358 if (hw_p == hxge_hw_list) { 4359 HXGE_DEBUG_MSG((hxgep, MOD_CTL, 4360 "==> hxge_uninit_common_dev:" 4361 "remove head " 4362 "hw_p $%p parent dip $%p " 4363 "ndevs %d (head)", 4364 hw_p, p_dip, hw_p->ndevs)); 4365 hxge_hw_list = hw_p->next; 4366 } else { 4367 HXGE_DEBUG_MSG((hxgep, MOD_CTL, 4368 "==> hxge_uninit_common_dev:" 4369 "remove middle " 4370 "hw_p $%p parent dip $%p " 4371 "ndevs %d (middle)", 4372 hw_p, p_dip, hw_p->ndevs)); 4373 h_hw_p->next = hw_p->next; 4374 } 4375 4376 KMEM_FREE(hw_p, sizeof (hxge_hw_list_t)); 4377 } 4378 break; 4379 } else { 4380 h_hw_p = hw_p; 4381 } 4382 } 4383 4384 MUTEX_EXIT(&hxge_common_lock); 4385 HXGE_DEBUG_MSG((hxgep, MOD_CTL, 4386 "==> hxge_uninit_common_dev (hxge_hw_list) $%p", hxge_hw_list)); 4387 4388 HXGE_DEBUG_MSG((hxgep, MOD_CTL, "<= hxge_uninit_common_dev")); 4389 } 4390 4391 #define HXGE_MSIX_ENTRIES 32 4392 #define HXGE_MSIX_WAIT_COUNT 10 4393 #define HXGE_MSIX_PARITY_CHECK_COUNT 30 4394 4395 static void 4396 hxge_link_poll(void *arg) 4397 { 4398 p_hxge_t hxgep = (p_hxge_t)arg; 4399 hpi_handle_t handle; 4400 cip_link_stat_t link_stat; 4401 hxge_timeout *to = &hxgep->timeout; 4402 4403 handle = HXGE_DEV_HPI_HANDLE(hxgep); 4404 HXGE_REG_RD32(handle, CIP_LINK_STAT, &link_stat.value); 4405 4406 if (to->report_link_status || 4407 (to->link_status != link_stat.bits.xpcs0_link_up)) { 4408 to->link_status = link_stat.bits.xpcs0_link_up; 4409 to->report_link_status = B_FALSE; 4410 4411 if (link_stat.bits.xpcs0_link_up) { 4412 hxge_link_update(hxgep, LINK_STATE_UP); 4413 } else { 4414 hxge_link_update(hxgep, LINK_STATE_DOWN); 4415 } 4416 } 4417 4418 /* Restart the link status timer to check the link status */ 4419 MUTEX_ENTER(&to->lock); 4420 to->id = timeout(hxge_link_poll, arg, to->ticks); 4421 MUTEX_EXIT(&to->lock); 4422 } 4423 4424 static void 4425 hxge_link_update(p_hxge_t hxgep, link_state_t state) 4426 { 4427 p_hxge_stats_t statsp = (p_hxge_stats_t)hxgep->statsp; 4428 4429 mac_link_update(hxgep->mach, state); 4430 if (state == LINK_STATE_UP) { 4431 statsp->mac_stats.link_speed = 10000; 4432 statsp->mac_stats.link_duplex = 2; 4433 statsp->mac_stats.link_up = 1; 4434 } else { 4435 statsp->mac_stats.link_speed = 0; 4436 statsp->mac_stats.link_duplex = 0; 4437 statsp->mac_stats.link_up = 0; 4438 } 4439 } 4440 4441 static void 4442 hxge_msix_init(p_hxge_t hxgep) 4443 { 4444 uint32_t data0; 4445 uint32_t data1; 4446 uint32_t data2; 4447 int i; 4448 uint32_t msix_entry0; 4449 uint32_t msix_entry1; 4450 uint32_t msix_entry2; 4451 uint32_t msix_entry3; 4452 4453 /* Change to use MSIx bar instead of indirect access */ 4454 for (i = 0; i < HXGE_MSIX_ENTRIES; i++) { 4455 data0 = 0xffffffff - i; 4456 data1 = 0xffffffff - i - 1; 4457 data2 = 0xffffffff - i - 2; 4458 4459 HXGE_REG_WR32(hxgep->hpi_msi_handle, i * 16, data0); 4460 HXGE_REG_WR32(hxgep->hpi_msi_handle, i * 16 + 4, data1); 4461 HXGE_REG_WR32(hxgep->hpi_msi_handle, i * 16 + 8, data2); 4462 HXGE_REG_WR32(hxgep->hpi_msi_handle, i * 16 + 12, 0); 4463 } 4464 4465 /* Initialize ram data out buffer. */ 4466 for (i = 0; i < HXGE_MSIX_ENTRIES; i++) { 4467 HXGE_REG_RD32(hxgep->hpi_msi_handle, i * 16, &msix_entry0); 4468 HXGE_REG_RD32(hxgep->hpi_msi_handle, i * 16 + 4, &msix_entry1); 4469 HXGE_REG_RD32(hxgep->hpi_msi_handle, i * 16 + 8, &msix_entry2); 4470 HXGE_REG_RD32(hxgep->hpi_msi_handle, i * 16 + 12, &msix_entry3); 4471 } 4472 } 4473 4474 /* 4475 * The following function is to support 4476 * PSARC/2007/453 MSI-X interrupt limit override. 4477 */ 4478 static int 4479 hxge_create_msi_property(p_hxge_t hxgep) 4480 { 4481 int nmsi; 4482 extern int ncpus; 4483 4484 HXGE_DEBUG_MSG((hxgep, MOD_CTL, "==>hxge_create_msi_property")); 4485 4486 (void) ddi_prop_create(DDI_DEV_T_NONE, hxgep->dip, 4487 DDI_PROP_CANSLEEP, "#msix-request", NULL, 0); 4488 /* 4489 * The maximum MSI-X requested will be 8. 4490 * If the # of CPUs is less than 8, we will reqeust 4491 * # MSI-X based on the # of CPUs. 4492 */ 4493 if (ncpus >= HXGE_MSIX_REQUEST_10G) { 4494 nmsi = HXGE_MSIX_REQUEST_10G; 4495 } else { 4496 nmsi = ncpus; 4497 } 4498 4499 HXGE_DEBUG_MSG((hxgep, MOD_CTL, 4500 "==>hxge_create_msi_property(10G): exists 0x%x (nmsi %d)", 4501 ddi_prop_exists(DDI_DEV_T_NONE, hxgep->dip, 4502 DDI_PROP_CANSLEEP, "#msix-request"), nmsi)); 4503 4504 HXGE_DEBUG_MSG((hxgep, MOD_CTL, "<==hxge_create_msi_property")); 4505 return (nmsi); 4506 } 4507