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 2008 NetXen, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 /* 26 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 27 * Use is subject to license terms. 28 */ 29 30 /* 31 * Copyright (c) 2018, Joyent, Inc. 32 */ 33 34 #include <sys/types.h> 35 #include <sys/conf.h> 36 #include <sys/debug.h> 37 #include <sys/stropts.h> 38 #include <sys/stream.h> 39 #include <sys/strlog.h> 40 #include <sys/kmem.h> 41 #include <sys/stat.h> 42 #include <sys/kstat.h> 43 #include <sys/vtrace.h> 44 #include <sys/dlpi.h> 45 #include <sys/strsun.h> 46 #include <sys/ethernet.h> 47 #include <sys/modctl.h> 48 #include <sys/errno.h> 49 #include <sys/dditypes.h> 50 #include <sys/ddi.h> 51 #include <sys/sunddi.h> 52 #include <sys/sysmacros.h> 53 #include <sys/pci.h> 54 #include <sys/ddi_intr.h> 55 56 #include "unm_nic.h" 57 #include "unm_nic_hw.h" 58 #include "unm_brdcfg.h" 59 #include "nic_cmn.h" 60 #include "nic_phan_reg.h" 61 #include "unm_nic_ioctl.h" 62 #include "nx_hw_pci_regs.h" 63 64 char ident[] = "Netxen nic driver v" UNM_NIC_VERSIONID; 65 char unm_nic_driver_name[] = "ntxn"; 66 int verbmsg = 0; 67 68 static char txbcopythreshold_propname[] = "tx_bcopy_threshold"; 69 static char rxbcopythreshold_propname[] = "rx_bcopy_threshold"; 70 static char rxringsize_propname[] = "rx_ring_size"; 71 static char jumborxringsize_propname[] = "jumbo_rx_ring_size"; 72 static char txringsize_propname[] = "tx_ring_size"; 73 static char defaultmtu_propname[] = "default_mtu"; 74 static char dmesg_propname[] = "verbose_driver"; 75 76 #define STRUCT_COPY(a, b) bcopy(&(b), &(a), sizeof (a)) 77 78 extern int unm_register_mac(unm_adapter *adapter); 79 extern void unm_fini_kstats(unm_adapter* adapter); 80 extern void unm_nic_remove(unm_adapter *adapter); 81 extern int unm_nic_suspend(unm_adapter *); 82 extern uint_t unm_intr(caddr_t, caddr_t); 83 84 /* Data access requirements. */ 85 static struct ddi_device_acc_attr unm_dev_attr = { 86 DDI_DEVICE_ATTR_V0, 87 DDI_STRUCTURE_LE_ACC, 88 DDI_STRICTORDER_ACC 89 }; 90 91 static struct ddi_device_acc_attr unm_buf_attr = { 92 DDI_DEVICE_ATTR_V0, 93 DDI_NEVERSWAP_ACC, 94 DDI_STRICTORDER_ACC 95 }; 96 97 static ddi_dma_attr_t unm_dma_attr_desc = { 98 DMA_ATTR_V0, /* dma_attr_version */ 99 0, /* dma_attr_addr_lo */ 100 0xffffffffull, /* dma_attr_addr_hi */ 101 0x000fffffull, /* dma_attr_count_max */ 102 4096, /* dma_attr_align */ 103 0x000fffffull, /* dma_attr_burstsizes */ 104 4, /* dma_attr_minxfer */ 105 0x003fffffull, /* dma_attr_maxxfer */ 106 0xffffffffull, /* dma_attr_seg */ 107 1, /* dma_attr_sgllen */ 108 1, /* dma_attr_granular */ 109 0 /* dma_attr_flags */ 110 }; 111 112 static ddi_dma_attr_t unm_dma_attr_rxbuf = { 113 DMA_ATTR_V0, /* dma_attr_version */ 114 0, /* dma_attr_addr_lo */ 115 0x7ffffffffULL, /* dma_attr_addr_hi */ 116 0xffffull, /* dma_attr_count_max */ 117 4096, /* dma_attr_align */ 118 0xfff8ull, /* dma_attr_burstsizes */ 119 1, /* dma_attr_minxfer */ 120 0xffffffffull, /* dma_attr_maxxfer */ 121 0xffffull, /* dma_attr_seg */ 122 1, /* dma_attr_sgllen */ 123 1, /* dma_attr_granular */ 124 0 /* dma_attr_flags */ 125 }; 126 127 static ddi_dma_attr_t unm_dma_attr_cmddesc = { 128 DMA_ATTR_V0, /* dma_attr_version */ 129 0, /* dma_attr_addr_lo */ 130 0x7ffffffffULL, /* dma_attr_addr_hi */ 131 0xffffull, /* dma_attr_count_max */ 132 1, /* dma_attr_align */ 133 0xfff8ull, /* dma_attr_burstsizes */ 134 1, /* dma_attr_minxfer */ 135 0xffff0ull, /* dma_attr_maxxfer */ 136 0xffffull, /* dma_attr_seg */ 137 16, /* dma_attr_sgllen */ 138 1, /* dma_attr_granular */ 139 0 /* dma_attr_flags */ 140 }; 141 142 static struct nx_legacy_intr_set legacy_intr[] = NX_LEGACY_INTR_CONFIG; 143 144 static int 145 check_hw_init(struct unm_adapter_s *adapter) 146 { 147 u32 val; 148 int ret = 0; 149 150 adapter->unm_nic_hw_read_wx(adapter, UNM_CAM_RAM(0x1fc), &val, 4); 151 if (val == 0x55555555) { 152 /* This is the first boot after power up */ 153 adapter->unm_nic_hw_read_wx(adapter, UNM_ROMUSB_GLB_SW_RESET, 154 &val, 4); 155 if (val != 0x80000f) 156 ret = -1; 157 158 if (NX_IS_REVISION_P2(adapter->ahw.revision_id)) { 159 /* Start P2 boot loader */ 160 adapter->unm_nic_pci_write_normalize(adapter, 161 UNM_CAM_RAM(0x1fc), UNM_BDINFO_MAGIC); 162 adapter->unm_nic_pci_write_normalize(adapter, 163 UNM_ROMUSB_GLB_PEGTUNE_DONE, 1); 164 } 165 } 166 return (ret); 167 } 168 169 170 static int 171 unm_get_flash_block(unm_adapter *adapter, int base, int size, uint32_t *buf) 172 { 173 int i, addr; 174 uint32_t *ptr32; 175 176 addr = base; 177 ptr32 = buf; 178 for (i = 0; i < size / sizeof (uint32_t); i++) { 179 if (rom_fast_read(adapter, addr, (int *)ptr32) == -1) 180 return (-1); 181 ptr32++; 182 addr += sizeof (uint32_t); 183 } 184 if ((char *)buf + size > (char *)ptr32) { 185 int local; 186 187 if (rom_fast_read(adapter, addr, &local) == -1) 188 return (-1); 189 (void) memcpy(ptr32, &local, 190 (uintptr_t)((char *)buf + size) - (uintptr_t)(char *)ptr32); 191 } 192 193 return (0); 194 } 195 196 197 static int 198 get_flash_mac_addr(struct unm_adapter_s *adapter, u64 mac[]) 199 { 200 uint32_t *pmac = (uint32_t *)&mac[0]; 201 202 if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { 203 uint32_t temp, crbaddr; 204 uint16_t *pmac16 = (uint16_t *)pmac; 205 206 // FOR P3, read from CAM RAM 207 208 int pci_func = adapter->ahw.pci_func; 209 pmac16 += (4 * pci_func); 210 crbaddr = CRB_MAC_BLOCK_START + (4 * ((pci_func/2) * 3)) + 211 (4 * (pci_func & 1)); 212 213 adapter->unm_nic_hw_read_wx(adapter, crbaddr, &temp, 4); 214 if (pci_func & 1) { 215 *pmac16++ = (temp >> 16); 216 adapter->unm_nic_hw_read_wx(adapter, crbaddr+4, 217 &temp, 4); 218 *pmac16++ = (temp & 0xffff); 219 *pmac16++ = (temp >> 16); 220 *pmac16 = 0; 221 } else { 222 *pmac16++ = (temp & 0xffff); 223 *pmac16++ = (temp >> 16); 224 adapter->unm_nic_hw_read_wx(adapter, crbaddr+4, 225 &temp, 4); 226 *pmac16++ = (temp & 0xffff); 227 *pmac16 = 0; 228 } 229 return (0); 230 } 231 232 233 if (unm_get_flash_block(adapter, USER_START + 234 offsetof(unm_user_info_t, mac_addr), FLASH_NUM_PORTS * sizeof (U64), 235 pmac) == -1) 236 return (-1); 237 238 if (*mac == ~0ULL) { 239 if (unm_get_flash_block(adapter, USER_START_OLD + 240 offsetof(unm_old_user_info_t, mac_addr), 241 FLASH_NUM_PORTS * sizeof (U64), pmac) == -1) 242 return (-1); 243 244 if (*mac == ~0ULL) 245 return (-1); 246 } 247 248 return (0); 249 } 250 251 static int 252 unm_initialize_dummy_dma(unm_adapter *adapter) 253 { 254 uint32_t hi, lo, temp; 255 ddi_dma_cookie_t cookie; 256 257 if (unm_pci_alloc_consistent(adapter, UNM_HOST_DUMMY_DMA_SIZE, 258 (caddr_t *)&adapter->dummy_dma.addr, &cookie, 259 &adapter->dummy_dma.dma_handle, 260 &adapter->dummy_dma.acc_handle) != DDI_SUCCESS) { 261 cmn_err(CE_WARN, "%s%d: Unable to alloc dummy dma buf\n", 262 adapter->name, adapter->instance); 263 return (DDI_ENOMEM); 264 } 265 266 adapter->dummy_dma.phys_addr = cookie.dmac_laddress; 267 268 hi = (adapter->dummy_dma.phys_addr >> 32) & 0xffffffff; 269 lo = adapter->dummy_dma.phys_addr & 0xffffffff; 270 271 UNM_READ_LOCK(&adapter->adapter_lock); 272 adapter->unm_nic_hw_write_wx(adapter, CRB_HOST_DUMMY_BUF_ADDR_HI, 273 &hi, 4); 274 adapter->unm_nic_hw_write_wx(adapter, CRB_HOST_DUMMY_BUF_ADDR_LO, 275 &lo, 4); 276 if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { 277 temp = DUMMY_BUF_INIT; 278 adapter->unm_nic_hw_write_wx(adapter, CRB_HOST_DUMMY_BUF, 279 &temp, 4); 280 } 281 UNM_READ_UNLOCK(&adapter->adapter_lock); 282 283 return (DDI_SUCCESS); 284 } 285 286 void 287 unm_free_dummy_dma(unm_adapter *adapter) 288 { 289 if (adapter->dummy_dma.addr) { 290 unm_pci_free_consistent(&adapter->dummy_dma.dma_handle, 291 &adapter->dummy_dma.acc_handle); 292 adapter->dummy_dma.addr = NULL; 293 } 294 } 295 296 static int 297 unm_pci_cfg_init(unm_adapter *adapter) 298 { 299 hardware_context *hwcontext; 300 ddi_acc_handle_t pci_cfg_hdl; 301 int *reg_options; 302 dev_info_t *dip; 303 uint_t noptions; 304 int ret; 305 uint16_t vendor_id, pci_cmd_word; 306 uint8_t base_class, sub_class, prog_class; 307 uint32_t pexsizes; 308 struct nx_legacy_intr_set *legacy_intrp; 309 310 hwcontext = &adapter->ahw; 311 pci_cfg_hdl = adapter->pci_cfg_handle; 312 dip = adapter->dip; 313 314 vendor_id = pci_config_get16(pci_cfg_hdl, PCI_CONF_VENID); 315 316 if (vendor_id != 0x4040) { 317 cmn_err(CE_WARN, "%s%d: vendor id %x not 0x4040\n", 318 adapter->name, adapter->instance, vendor_id); 319 return (DDI_FAILURE); 320 } 321 322 ret = ddi_prop_lookup_int_array(DDI_DEV_T_ANY, 323 dip, 0, "reg", ®_options, &noptions); 324 if (ret != DDI_PROP_SUCCESS) { 325 cmn_err(CE_WARN, "%s%d: Could not determine reg property\n", 326 adapter->name, adapter->instance); 327 return (DDI_FAILURE); 328 } 329 330 hwcontext->pci_func = (reg_options[0] >> 8) & 0x7; 331 ddi_prop_free(reg_options); 332 333 base_class = pci_config_get8(pci_cfg_hdl, PCI_CONF_BASCLASS); 334 sub_class = pci_config_get8(pci_cfg_hdl, PCI_CONF_SUBCLASS); 335 prog_class = pci_config_get8(pci_cfg_hdl, PCI_CONF_PROGCLASS); 336 337 /* 338 * Need this check so that MEZZ card mgmt interface ntxn0 could fail 339 * attach & return and proceed to next interfaces ntxn1 and ntxn2 340 */ 341 if ((base_class != 0x02) || (sub_class != 0) || (prog_class != 0)) { 342 cmn_err(CE_WARN, "%s%d: Base/sub/prog class problem %d/%d/%d\n", 343 adapter->name, adapter->instance, base_class, sub_class, 344 prog_class); 345 return (DDI_FAILURE); 346 } 347 348 hwcontext->revision_id = pci_config_get8(pci_cfg_hdl, PCI_CONF_REVID); 349 350 /* 351 * Refuse to work with dubious P3 cards. 352 */ 353 if ((hwcontext->revision_id >= NX_P3_A0) && 354 (hwcontext->revision_id < NX_P3_B1)) { 355 cmn_err(CE_WARN, "%s%d: NetXen chip revs between 0x%x-0x%x " 356 "is unsupported\n", adapter->name, adapter->instance, 357 NX_P3_A0, NX_P3_B0); 358 return (DDI_FAILURE); 359 } 360 361 /* 362 * Save error reporting settings; clear [19:16] error status bits. 363 * Set max read request [14:12] to 0 for 128 bytes. Set max payload 364 * size[7:5] to 0 for for 128 bytes. 365 */ 366 if (NX_IS_REVISION_P2(hwcontext->revision_id)) { 367 pexsizes = pci_config_get32(pci_cfg_hdl, 0xd8); 368 pexsizes &= 7; 369 pexsizes |= 0xF0000; 370 pci_config_put32(pci_cfg_hdl, 0xd8, pexsizes); 371 } 372 373 pci_cmd_word = pci_config_get16(pci_cfg_hdl, PCI_CONF_COMM); 374 pci_cmd_word |= (PCI_COMM_INTX_DISABLE | PCI_COMM_SERR_ENABLE); 375 pci_config_put16(pci_cfg_hdl, PCI_CONF_COMM, pci_cmd_word); 376 377 if (hwcontext->revision_id >= NX_P3_B0) 378 legacy_intrp = &legacy_intr[hwcontext->pci_func]; 379 else 380 legacy_intrp = &legacy_intr[0]; 381 382 adapter->legacy_intr.int_vec_bit = legacy_intrp->int_vec_bit; 383 adapter->legacy_intr.tgt_status_reg = legacy_intrp->tgt_status_reg; 384 adapter->legacy_intr.tgt_mask_reg = legacy_intrp->tgt_mask_reg; 385 adapter->legacy_intr.pci_int_reg = legacy_intrp->pci_int_reg; 386 387 return (DDI_SUCCESS); 388 } 389 390 static void 391 unm_free_tx_dmahdl(unm_adapter *adapter) 392 { 393 int i; 394 unm_dmah_node_t *nodep; 395 396 mutex_enter(&adapter->tx_lock); 397 nodep = &adapter->tx_dma_hdls[0]; 398 399 for (i = 0; i < adapter->MaxTxDescCount + EXTRA_HANDLES; i++) { 400 if (nodep->dmahdl != NULL) { 401 ddi_dma_free_handle(&nodep->dmahdl); 402 nodep->dmahdl = NULL; 403 } 404 nodep->next = NULL; 405 nodep++; 406 } 407 408 adapter->dmahdl_pool = NULL; 409 adapter->freehdls = 0; 410 mutex_exit(&adapter->tx_lock); 411 } 412 413 static int 414 unm_alloc_tx_dmahdl(unm_adapter *adapter) 415 { 416 int i; 417 unm_dmah_node_t *nodep = &adapter->tx_dma_hdls[0]; 418 419 mutex_enter(&adapter->tx_lock); 420 for (i = 0; i < adapter->MaxTxDescCount + EXTRA_HANDLES; i++) { 421 if (ddi_dma_alloc_handle(adapter->dip, &unm_dma_attr_cmddesc, 422 DDI_DMA_DONTWAIT, NULL, &nodep->dmahdl) != DDI_SUCCESS) { 423 mutex_exit(&adapter->tx_lock); 424 goto alloc_hdl_fail; 425 } 426 427 if (i > 0) 428 nodep->next = nodep - 1; 429 nodep++; 430 } 431 432 adapter->dmahdl_pool = nodep - 1; 433 adapter->freehdls = i; 434 mutex_exit(&adapter->tx_lock); 435 436 return (DDI_SUCCESS); 437 438 alloc_hdl_fail: 439 unm_free_tx_dmahdl(adapter); 440 cmn_err(CE_WARN, "%s%d: Failed transmit ring dma handle allocation\n", 441 adapter->name, adapter->instance); 442 return (DDI_FAILURE); 443 } 444 445 static void 446 unm_free_dma_mem(dma_area_t *dma_p) 447 { 448 if (dma_p->dma_hdl != NULL) { 449 if (dma_p->ncookies) { 450 (void) ddi_dma_unbind_handle(dma_p->dma_hdl); 451 dma_p->ncookies = 0; 452 } 453 } 454 if (dma_p->acc_hdl != NULL) { 455 ddi_dma_mem_free(&dma_p->acc_hdl); 456 dma_p->acc_hdl = NULL; 457 } 458 if (dma_p->dma_hdl != NULL) { 459 ddi_dma_free_handle(&dma_p->dma_hdl); 460 dma_p->dma_hdl = NULL; 461 } 462 } 463 464 static int 465 unm_alloc_dma_mem(unm_adapter *adapter, int size, uint_t dma_flag, 466 ddi_dma_attr_t *dma_attr_p, dma_area_t *dma_p) 467 { 468 int ret; 469 caddr_t vaddr; 470 size_t actual_size; 471 ddi_dma_cookie_t cookie; 472 473 ret = ddi_dma_alloc_handle(adapter->dip, 474 dma_attr_p, DDI_DMA_DONTWAIT, 475 NULL, &dma_p->dma_hdl); 476 if (ret != DDI_SUCCESS) { 477 cmn_err(CE_WARN, "%s%d: Failed ddi_dma_alloc_handle\n", 478 adapter->name, adapter->instance); 479 goto dma_mem_fail; 480 } 481 482 ret = ddi_dma_mem_alloc(dma_p->dma_hdl, 483 size, &adapter->gc_attr_desc, 484 dma_flag & (DDI_DMA_STREAMING | DDI_DMA_CONSISTENT), 485 DDI_DMA_DONTWAIT, NULL, &vaddr, &actual_size, 486 &dma_p->acc_hdl); 487 if (ret != DDI_SUCCESS) { 488 cmn_err(CE_WARN, "%s%d: ddi_dma_mem_alloc() failed\n", 489 adapter->name, adapter->instance); 490 goto dma_mem_fail; 491 } 492 493 if (actual_size < size) { 494 cmn_err(CE_WARN, "%s%d: ddi_dma_mem_alloc() allocated small\n", 495 adapter->name, adapter->instance); 496 goto dma_mem_fail; 497 } 498 499 ret = ddi_dma_addr_bind_handle(dma_p->dma_hdl, 500 NULL, vaddr, size, dma_flag, DDI_DMA_DONTWAIT, 501 NULL, &cookie, &dma_p->ncookies); 502 if (ret != DDI_DMA_MAPPED || dma_p->ncookies != 1) { 503 cmn_err(CE_WARN, "%s%d: ddi_dma_addr_bind_handle() failed, " 504 "%d, %d\n", adapter->name, adapter->instance, ret, 505 dma_p->ncookies); 506 goto dma_mem_fail; 507 } 508 509 dma_p->dma_addr = cookie.dmac_laddress; 510 dma_p->vaddr = vaddr; 511 (void) memset(vaddr, 0, size); 512 513 return (DDI_SUCCESS); 514 515 dma_mem_fail: 516 unm_free_dma_mem(dma_p); 517 return (DDI_FAILURE); 518 } 519 520 static void 521 unm_free_tx_buffers(unm_adapter *adapter) 522 { 523 int i; 524 dma_area_t *dma_p; 525 struct unm_cmd_buffer *cmd_buf; 526 unm_dmah_node_t *nodep; 527 528 cmd_buf = &adapter->cmd_buf_arr[0]; 529 530 for (i = 0; i < adapter->MaxTxDescCount; i++) { 531 dma_p = &cmd_buf->dma_area; 532 unm_free_dma_mem(dma_p); 533 nodep = cmd_buf->head; 534 while (nodep != NULL) { 535 (void) ddi_dma_unbind_handle(nodep->dmahdl); 536 nodep = nodep->next; 537 } 538 if (cmd_buf->msg != NULL) 539 freemsg(cmd_buf->msg); 540 cmd_buf++; 541 } 542 adapter->freecmds = 0; 543 } 544 545 static int 546 unm_alloc_tx_buffers(unm_adapter *adapter) 547 { 548 int i, ret, size, allocated = 0; 549 dma_area_t *dma_p; 550 struct unm_cmd_buffer *cmd_buf; 551 552 cmd_buf = &adapter->cmd_buf_arr[0]; 553 size = adapter->maxmtu; 554 555 for (i = 0; i < adapter->MaxTxDescCount; i++) { 556 dma_p = &cmd_buf->dma_area; 557 ret = unm_alloc_dma_mem(adapter, size, 558 DDI_DMA_WRITE | DDI_DMA_STREAMING, 559 &unm_dma_attr_rxbuf, dma_p); 560 if (ret != DDI_SUCCESS) 561 goto alloc_tx_buffer_fail; 562 563 allocated++; 564 cmd_buf++; 565 } 566 adapter->freecmds = adapter->MaxTxDescCount; 567 return (DDI_SUCCESS); 568 569 alloc_tx_buffer_fail: 570 571 cmd_buf = &adapter->cmd_buf_arr[0]; 572 for (i = 0; i < allocated; i++) { 573 dma_p = &cmd_buf->dma_area; 574 unm_free_dma_mem(dma_p); 575 cmd_buf++; 576 } 577 cmn_err(CE_WARN, "%s%d: Failed transmit ring memory allocation\n", 578 adapter->name, adapter->instance); 579 return (DDI_FAILURE); 580 } 581 582 /* 583 * Called by freemsg() to "free" the resource. 584 */ 585 static void 586 unm_rx_buffer_recycle(char *arg) 587 { 588 unm_rx_buffer_t *rx_buffer = (unm_rx_buffer_t *)(uintptr_t)arg; 589 unm_adapter *adapter = rx_buffer->adapter; 590 unm_rcv_desc_ctx_t *rcv_desc = rx_buffer->rcv_desc; 591 592 rx_buffer->mp = desballoc(rx_buffer->dma_info.vaddr, 593 rcv_desc->dma_size, 0, &rx_buffer->rx_recycle); 594 595 if (rx_buffer->mp == NULL) 596 adapter->stats.desballocfailed++; 597 598 mutex_enter(rcv_desc->recycle_lock); 599 rx_buffer->next = rcv_desc->recycle_list; 600 rcv_desc->recycle_list = rx_buffer; 601 rcv_desc->rx_buf_recycle++; 602 mutex_exit(rcv_desc->recycle_lock); 603 } 604 605 static void 606 unm_destroy_rx_ring(unm_rcv_desc_ctx_t *rcv_desc) 607 { 608 uint32_t i, total_buf; 609 unm_rx_buffer_t *buf_pool; 610 611 total_buf = rcv_desc->rx_buf_total; 612 buf_pool = rcv_desc->rx_buf_pool; 613 for (i = 0; i < total_buf; i++) { 614 if (buf_pool->mp != NULL) 615 freemsg(buf_pool->mp); 616 unm_free_dma_mem(&buf_pool->dma_info); 617 buf_pool++; 618 } 619 620 kmem_free(rcv_desc->rx_buf_pool, sizeof (unm_rx_buffer_t) * total_buf); 621 rcv_desc->rx_buf_pool = NULL; 622 rcv_desc->pool_list = NULL; 623 rcv_desc->recycle_list = NULL; 624 rcv_desc->rx_buf_free = 0; 625 626 mutex_destroy(rcv_desc->pool_lock); 627 mutex_destroy(rcv_desc->recycle_lock); 628 } 629 630 static int 631 unm_create_rx_ring(unm_adapter *adapter, unm_rcv_desc_ctx_t *rcv_desc) 632 { 633 int i, ret, allocate = 0, sreoff; 634 uint32_t total_buf; 635 dma_area_t *dma_info; 636 unm_rx_buffer_t *rx_buffer; 637 638 sreoff = adapter->ahw.cut_through ? 0 : IP_ALIGNMENT_BYTES; 639 640 /* temporarily set the total rx buffers two times of MaxRxDescCount */ 641 total_buf = rcv_desc->rx_buf_total = rcv_desc->MaxRxDescCount * 2; 642 643 rcv_desc->rx_buf_pool = kmem_zalloc(sizeof (unm_rx_buffer_t) * 644 total_buf, KM_SLEEP); 645 rx_buffer = rcv_desc->rx_buf_pool; 646 for (i = 0; i < total_buf; i++) { 647 dma_info = &rx_buffer->dma_info; 648 ret = unm_alloc_dma_mem(adapter, rcv_desc->buf_size, 649 DDI_DMA_READ | DDI_DMA_STREAMING, 650 &unm_dma_attr_rxbuf, dma_info); 651 if (ret != DDI_SUCCESS) 652 goto alloc_mem_failed; 653 else { 654 allocate++; 655 dma_info->vaddr = (void *) ((char *)dma_info->vaddr + 656 sreoff); 657 dma_info->dma_addr += sreoff; 658 rx_buffer->rx_recycle.free_func = 659 unm_rx_buffer_recycle; 660 rx_buffer->rx_recycle.free_arg = (caddr_t)rx_buffer; 661 rx_buffer->next = NULL; 662 rx_buffer->mp = desballoc(dma_info->vaddr, 663 rcv_desc->dma_size, 0, &rx_buffer->rx_recycle); 664 if (rx_buffer->mp == NULL) 665 adapter->stats.desballocfailed++; 666 rx_buffer->rcv_desc = rcv_desc; 667 rx_buffer->adapter = adapter; 668 rx_buffer++; 669 } 670 } 671 672 for (i = 0; i < (total_buf - 1); i++) { 673 rcv_desc->rx_buf_pool[i].next = &rcv_desc->rx_buf_pool[i + 1]; 674 } 675 676 rcv_desc->pool_list = rcv_desc->rx_buf_pool; 677 rcv_desc->recycle_list = NULL; 678 rcv_desc->rx_buf_free = total_buf; 679 680 mutex_init(rcv_desc->pool_lock, NULL, 681 MUTEX_DRIVER, (DDI_INTR_PRI(adapter->intr_pri))); 682 mutex_init(rcv_desc->recycle_lock, NULL, 683 MUTEX_DRIVER, (DDI_INTR_PRI(adapter->intr_pri))); 684 685 return (DDI_SUCCESS); 686 687 alloc_mem_failed: 688 rx_buffer = rcv_desc->rx_buf_pool; 689 for (i = 0; i < allocate; i++, rx_buffer++) { 690 dma_info = &rx_buffer->dma_info; 691 if (rx_buffer->mp != NULL) 692 freemsg(rx_buffer->mp); 693 unm_free_dma_mem(dma_info); 694 } 695 696 kmem_free(rcv_desc->rx_buf_pool, sizeof (unm_rx_buffer_t) * total_buf); 697 rcv_desc->rx_buf_pool = NULL; 698 699 cmn_err(CE_WARN, "%s%d: Failed receive ring resource allocation\n", 700 adapter->name, adapter->instance); 701 return (DDI_FAILURE); 702 } 703 704 static void 705 unm_check_options(unm_adapter *adapter) 706 { 707 int i, ring, tx_desc, rx_desc, rx_jdesc, maxrx; 708 unm_recv_context_t *recv_ctx; 709 unm_rcv_desc_ctx_t *rcv_desc; 710 uint8_t revid = adapter->ahw.revision_id; 711 dev_info_t *dip = adapter->dip; 712 713 /* 714 * Reduce number of regular rcv desc to half on x86. 715 */ 716 maxrx = MAX_RCV_DESCRIPTORS; 717 #if !defined(_LP64) 718 maxrx /= 2; 719 #endif /* !_LP64 */ 720 721 verbmsg = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 722 dmesg_propname, 0); 723 724 adapter->tx_bcopy_threshold = ddi_prop_get_int(DDI_DEV_T_ANY, 725 dip, DDI_PROP_DONTPASS, txbcopythreshold_propname, 726 UNM_TX_BCOPY_THRESHOLD); 727 adapter->rx_bcopy_threshold = ddi_prop_get_int(DDI_DEV_T_ANY, 728 dip, DDI_PROP_DONTPASS, rxbcopythreshold_propname, 729 UNM_RX_BCOPY_THRESHOLD); 730 731 tx_desc = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 732 txringsize_propname, MAX_CMD_DESCRIPTORS_HOST); 733 if (tx_desc >= 256 && tx_desc <= MAX_CMD_DESCRIPTORS && ISP2(tx_desc)) { 734 adapter->MaxTxDescCount = tx_desc; 735 } else { 736 cmn_err(CE_WARN, "%s%d: TxRingSize defaulting to %d, since " 737 ".conf value is not 2 power aligned in range 256 - %d\n", 738 adapter->name, adapter->instance, MAX_CMD_DESCRIPTORS_HOST, 739 MAX_CMD_DESCRIPTORS); 740 adapter->MaxTxDescCount = MAX_CMD_DESCRIPTORS_HOST; 741 } 742 743 rx_desc = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 744 rxringsize_propname, maxrx); 745 if (rx_desc >= NX_MIN_DRIVER_RDS_SIZE && 746 rx_desc <= NX_MAX_SUPPORTED_RDS_SIZE && ISP2(rx_desc)) { 747 adapter->MaxRxDescCount = rx_desc; 748 } else { 749 cmn_err(CE_WARN, "%s%d: RxRingSize defaulting to %d, since " 750 ".conf value is not 2 power aligned in range %d - %d\n", 751 adapter->name, adapter->instance, MAX_RCV_DESCRIPTORS, 752 NX_MIN_DRIVER_RDS_SIZE, NX_MAX_SUPPORTED_RDS_SIZE); 753 adapter->MaxRxDescCount = MAX_RCV_DESCRIPTORS; 754 } 755 756 rx_jdesc = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 757 jumborxringsize_propname, MAX_JUMBO_RCV_DESCRIPTORS); 758 if (rx_jdesc >= NX_MIN_DRIVER_RDS_SIZE && 759 rx_jdesc <= NX_MAX_SUPPORTED_JUMBO_RDS_SIZE && ISP2(rx_jdesc)) { 760 adapter->MaxJumboRxDescCount = rx_jdesc; 761 } else { 762 cmn_err(CE_WARN, "%s%d: JumboRingSize defaulting to %d, since " 763 ".conf value is not 2 power aligned in range %d - %d\n", 764 adapter->name, adapter->instance, MAX_JUMBO_RCV_DESCRIPTORS, 765 NX_MIN_DRIVER_RDS_SIZE, NX_MAX_SUPPORTED_JUMBO_RDS_SIZE); 766 adapter->MaxJumboRxDescCount = MAX_JUMBO_RCV_DESCRIPTORS; 767 } 768 769 /* 770 * Solaris does not use LRO, but older firmware needs to have a 771 * couple of descriptors for initialization. 772 */ 773 adapter->MaxLroRxDescCount = (adapter->fw_major < 4) ? 2 : 0; 774 775 adapter->mtu = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 776 DDI_PROP_DONTPASS, defaultmtu_propname, MTU_SIZE); 777 778 if (adapter->mtu < MTU_SIZE) { 779 cmn_err(CE_WARN, "Raising mtu to %d\n", MTU_SIZE); 780 adapter->mtu = MTU_SIZE; 781 } 782 adapter->maxmtu = NX_IS_REVISION_P2(revid) ? P2_MAX_MTU : P3_MAX_MTU; 783 if (adapter->mtu > adapter->maxmtu) { 784 cmn_err(CE_WARN, "Lowering mtu to %d\n", adapter->maxmtu); 785 adapter->mtu = adapter->maxmtu; 786 } 787 788 adapter->maxmtu = adapter->mtu + NX_MAX_ETHERHDR; 789 790 /* 791 * If we are not expecting to receive jumbo frames, save memory and 792 * do not allocate. 793 */ 794 if (adapter->mtu <= MTU_SIZE) 795 adapter->MaxJumboRxDescCount = NX_MIN_DRIVER_RDS_SIZE; 796 797 for (i = 0; i < MAX_RCV_CTX; ++i) { 798 recv_ctx = &adapter->recv_ctx[i]; 799 800 for (ring = 0; ring < adapter->max_rds_rings; ring++) { 801 rcv_desc = &recv_ctx->rcv_desc[ring]; 802 803 switch (RCV_DESC_TYPE(ring)) { 804 case RCV_DESC_NORMAL: 805 rcv_desc->MaxRxDescCount = 806 adapter->MaxRxDescCount; 807 if (adapter->ahw.cut_through) { 808 rcv_desc->dma_size = 809 NX_CT_DEFAULT_RX_BUF_LEN; 810 rcv_desc->buf_size = rcv_desc->dma_size; 811 } else { 812 rcv_desc->dma_size = 813 NX_RX_NORMAL_BUF_MAX_LEN; 814 rcv_desc->buf_size = 815 rcv_desc->dma_size + 816 IP_ALIGNMENT_BYTES; 817 } 818 break; 819 820 case RCV_DESC_JUMBO: 821 rcv_desc->MaxRxDescCount = 822 adapter->MaxJumboRxDescCount; 823 if (adapter->ahw.cut_through) { 824 rcv_desc->dma_size = 825 rcv_desc->buf_size = 826 NX_P3_RX_JUMBO_BUF_MAX_LEN; 827 } else { 828 if (NX_IS_REVISION_P2(revid)) 829 rcv_desc->dma_size = 830 NX_P2_RX_JUMBO_BUF_MAX_LEN; 831 else 832 rcv_desc->dma_size = 833 NX_P3_RX_JUMBO_BUF_MAX_LEN; 834 rcv_desc->buf_size = 835 rcv_desc->dma_size + 836 IP_ALIGNMENT_BYTES; 837 } 838 break; 839 840 case RCV_RING_LRO: 841 rcv_desc->MaxRxDescCount = 842 adapter->MaxLroRxDescCount; 843 rcv_desc->buf_size = MAX_RX_LRO_BUFFER_LENGTH; 844 rcv_desc->dma_size = RX_LRO_DMA_MAP_LEN; 845 break; 846 default: 847 break; 848 } 849 } 850 } 851 } 852 853 static void 854 vector128M(unm_adapter *aptr) 855 { 856 aptr->unm_nic_pci_change_crbwindow = &unm_nic_pci_change_crbwindow_128M; 857 aptr->unm_crb_writelit_adapter = &unm_crb_writelit_adapter_128M; 858 aptr->unm_nic_hw_write_wx = &unm_nic_hw_write_wx_128M; 859 aptr->unm_nic_hw_read_wx = &unm_nic_hw_read_wx_128M; 860 aptr->unm_nic_hw_write_ioctl = &unm_nic_hw_write_ioctl_128M; 861 aptr->unm_nic_hw_read_ioctl = &unm_nic_hw_read_ioctl_128M; 862 aptr->unm_nic_pci_mem_write = &unm_nic_pci_mem_write_128M; 863 aptr->unm_nic_pci_mem_read = &unm_nic_pci_mem_read_128M; 864 aptr->unm_nic_pci_write_immediate = &unm_nic_pci_write_immediate_128M; 865 aptr->unm_nic_pci_read_immediate = &unm_nic_pci_read_immediate_128M; 866 aptr->unm_nic_pci_write_normalize = &unm_nic_pci_write_normalize_128M; 867 aptr->unm_nic_pci_read_normalize = &unm_nic_pci_read_normalize_128M; 868 aptr->unm_nic_pci_set_window = &unm_nic_pci_set_window_128M; 869 aptr->unm_nic_clear_statistics = &unm_nic_clear_statistics_128M; 870 aptr->unm_nic_fill_statistics = &unm_nic_fill_statistics_128M; 871 } 872 873 static void 874 vector2M(unm_adapter *aptr) 875 { 876 aptr->unm_nic_pci_change_crbwindow = &unm_nic_pci_change_crbwindow_2M; 877 aptr->unm_crb_writelit_adapter = &unm_crb_writelit_adapter_2M; 878 aptr->unm_nic_hw_write_wx = &unm_nic_hw_write_wx_2M; 879 aptr->unm_nic_hw_read_wx = &unm_nic_hw_read_wx_2M; 880 aptr->unm_nic_hw_write_ioctl = &unm_nic_hw_write_wx_2M; 881 aptr->unm_nic_hw_read_ioctl = &unm_nic_hw_read_wx_2M; 882 aptr->unm_nic_pci_mem_write = &unm_nic_pci_mem_write_2M; 883 aptr->unm_nic_pci_mem_read = &unm_nic_pci_mem_read_2M; 884 aptr->unm_nic_pci_write_immediate = &unm_nic_pci_write_immediate_2M; 885 aptr->unm_nic_pci_read_immediate = &unm_nic_pci_read_immediate_2M; 886 aptr->unm_nic_pci_write_normalize = &unm_nic_pci_write_normalize_2M; 887 aptr->unm_nic_pci_read_normalize = &unm_nic_pci_read_normalize_2M; 888 aptr->unm_nic_pci_set_window = &unm_nic_pci_set_window_2M; 889 aptr->unm_nic_clear_statistics = &unm_nic_clear_statistics_2M; 890 aptr->unm_nic_fill_statistics = &unm_nic_fill_statistics_2M; 891 } 892 893 static int 894 unm_pci_map_setup(unm_adapter *adapter) 895 { 896 int ret; 897 caddr_t reg_base, db_base; 898 caddr_t mem_ptr0, mem_ptr1 = NULL, mem_ptr2 = NULL; 899 unsigned long pci_len0; 900 unsigned long first_page_group_start, first_page_group_end; 901 902 off_t regsize, dbsize = UNM_DB_MAPSIZE_BYTES; 903 dev_info_t *dip = adapter->dip; 904 905 adapter->ahw.qdr_sn_window = adapter->ahw.ddr_mn_window = -1; 906 907 /* map register space */ 908 909 ret = ddi_dev_regsize(dip, 1, ®size); 910 if (ret != DDI_SUCCESS) { 911 cmn_err(CE_WARN, "%s%d: failed to read reg size for bar0\n", 912 adapter->name, adapter->instance); 913 return (DDI_FAILURE); 914 } 915 916 ret = ddi_regs_map_setup(dip, 1, ®_base, 0, 917 regsize, &unm_dev_attr, &adapter->regs_handle); 918 if (ret != DDI_SUCCESS) { 919 cmn_err(CE_WARN, "%s%d: failed to map registers\n", 920 adapter->name, adapter->instance); 921 return (DDI_FAILURE); 922 } 923 924 mem_ptr0 = reg_base; 925 926 if (regsize == UNM_PCI_128MB_SIZE) { 927 pci_len0 = FIRST_PAGE_GROUP_SIZE; 928 mem_ptr1 = mem_ptr0 + SECOND_PAGE_GROUP_START; 929 mem_ptr2 = mem_ptr0 + THIRD_PAGE_GROUP_START; 930 first_page_group_start = FIRST_PAGE_GROUP_START; 931 first_page_group_end = FIRST_PAGE_GROUP_END; 932 vector128M(adapter); 933 } else if (regsize == UNM_PCI_32MB_SIZE) { 934 pci_len0 = 0; 935 mem_ptr1 = mem_ptr0; 936 mem_ptr2 = mem_ptr0 + 937 (THIRD_PAGE_GROUP_START - SECOND_PAGE_GROUP_START); 938 first_page_group_start = 0; 939 first_page_group_end = 0; 940 vector128M(adapter); 941 } else if (regsize == UNM_PCI_2MB_SIZE) { 942 pci_len0 = UNM_PCI_2MB_SIZE; 943 first_page_group_start = 0; 944 first_page_group_end = 0; 945 adapter->ahw.ddr_mn_window = adapter->ahw.qdr_sn_window = 0; 946 adapter->ahw.mn_win_crb = 0x100000 + PCIX_MN_WINDOW + 947 (adapter->ahw.pci_func * 0x20); 948 if (adapter->ahw.pci_func < 4) 949 adapter->ahw.ms_win_crb = 0x100000 + PCIX_SN_WINDOW + 950 (adapter->ahw.pci_func * 0x20); 951 else 952 adapter->ahw.ms_win_crb = 0x100000 + PCIX_SN_WINDOW + 953 0xA0 + ((adapter->ahw.pci_func - 4) * 0x10); 954 vector2M(adapter); 955 } else { 956 cmn_err(CE_WARN, "%s%d: invalid pci regs map size %ld\n", 957 adapter->name, adapter->instance, regsize); 958 ddi_regs_map_free(&adapter->regs_handle); 959 return (DDI_FAILURE); 960 } 961 962 adapter->ahw.pci_base0 = (unsigned long)mem_ptr0; 963 adapter->ahw.pci_len0 = pci_len0; 964 adapter->ahw.pci_base1 = (unsigned long)mem_ptr1; 965 adapter->ahw.pci_len1 = SECOND_PAGE_GROUP_SIZE; 966 adapter->ahw.pci_base2 = (unsigned long)mem_ptr2; 967 adapter->ahw.pci_len2 = THIRD_PAGE_GROUP_SIZE; 968 adapter->ahw.crb_base = 969 PCI_OFFSET_SECOND_RANGE(adapter, UNM_PCI_CRBSPACE); 970 971 adapter->ahw.first_page_group_start = first_page_group_start; 972 adapter->ahw.first_page_group_end = first_page_group_end; 973 974 /* map doorbell */ 975 976 ret = ddi_regs_map_setup(dip, 2, &db_base, 0, 977 dbsize, &unm_dev_attr, &adapter->db_handle); 978 if (ret != DDI_SUCCESS) { 979 cmn_err(CE_WARN, "%s%d: failed to map doorbell\n", 980 adapter->name, adapter->instance); 981 ddi_regs_map_free(&adapter->regs_handle); 982 return (DDI_FAILURE); 983 } 984 985 adapter->ahw.db_base = (unsigned long)db_base; 986 adapter->ahw.db_len = dbsize; 987 988 return (DDI_SUCCESS); 989 } 990 991 static int 992 unm_initialize_intr(unm_adapter *adapter) 993 { 994 995 int ret; 996 int type, count, avail, actual; 997 998 ret = ddi_intr_get_supported_types(adapter->dip, &type); 999 if (ret != DDI_SUCCESS) { 1000 cmn_err(CE_WARN, "%s%d: ddi_intr_get_supported_types() " 1001 "failed\n", adapter->name, adapter->instance); 1002 return (DDI_FAILURE); 1003 } 1004 1005 type = DDI_INTR_TYPE_MSI; 1006 ret = ddi_intr_get_nintrs(adapter->dip, type, &count); 1007 if ((ret == DDI_SUCCESS) && (count > 0)) 1008 goto found_msi; 1009 1010 type = DDI_INTR_TYPE_FIXED; 1011 ret = ddi_intr_get_nintrs(adapter->dip, type, &count); 1012 if ((ret != DDI_SUCCESS) || (count == 0)) { 1013 cmn_err(CE_WARN, 1014 "ddi_intr_get_nintrs() failure ret=%d\n", ret); 1015 return (DDI_FAILURE); 1016 } 1017 1018 found_msi: 1019 adapter->intr_type = type; 1020 adapter->flags &= ~(UNM_NIC_MSI_ENABLED | UNM_NIC_MSIX_ENABLED); 1021 if (type == DDI_INTR_TYPE_MSI) 1022 adapter->flags |= UNM_NIC_MSI_ENABLED; 1023 1024 /* Get number of available interrupts */ 1025 ret = ddi_intr_get_navail(adapter->dip, type, &avail); 1026 if ((ret != DDI_SUCCESS) || (avail == 0)) { 1027 cmn_err(CE_WARN, "ddi_intr_get_navail() failure, ret=%d\n", 1028 ret); 1029 return (DDI_FAILURE); 1030 } 1031 1032 ret = ddi_intr_alloc(adapter->dip, &adapter->intr_handle, 1033 type, 0, 1, &actual, DDI_INTR_ALLOC_NORMAL); 1034 if ((ret != DDI_SUCCESS) || (actual == 0)) { 1035 cmn_err(CE_WARN, "ddi_intr_alloc() failure: %d\n", ret); 1036 return (DDI_FAILURE); 1037 } 1038 1039 ret = ddi_intr_get_pri(adapter->intr_handle, &adapter->intr_pri); 1040 if (ret != DDI_SUCCESS) { 1041 cmn_err(CE_WARN, "ddi_intr_get_pri() failure: %d\n", ret); 1042 } 1043 1044 /* Call ddi_intr_add_handler() */ 1045 ret = ddi_intr_add_handler(adapter->intr_handle, unm_intr, 1046 (caddr_t)adapter, NULL); 1047 if (ret != DDI_SUCCESS) { 1048 cmn_err(CE_WARN, "%s%d: ddi_intr_add_handler() failure\n", 1049 adapter->name, adapter->instance); 1050 (void) ddi_intr_free(adapter->intr_handle); 1051 return (DDI_FAILURE); 1052 } 1053 1054 /* Add softintr if required */ 1055 1056 return (DDI_SUCCESS); 1057 1058 } 1059 1060 void 1061 unm_destroy_intr(unm_adapter *adapter) 1062 { 1063 /* disable interrupt */ 1064 if (adapter->intr_type == DDI_INTR_TYPE_MSI) 1065 (void) ddi_intr_block_disable(&adapter->intr_handle, 1); 1066 else 1067 (void) ddi_intr_disable(adapter->intr_handle); 1068 1069 (void) ddi_intr_remove_handler(adapter->intr_handle); 1070 (void) ddi_intr_free(adapter->intr_handle); 1071 1072 /* Remove the software intr handler */ 1073 } 1074 1075 static void 1076 netxen_set_port_mode(unm_adapter *adapter) 1077 { 1078 static int wol_port_mode = UNM_PORT_MODE_AUTO_NEG_1G; 1079 static int port_mode = UNM_PORT_MODE_AUTO_NEG; 1080 int btype = adapter->ahw.boardcfg.board_type, data = 0; 1081 1082 if (btype == UNM_BRDTYPE_P3_HMEZ || btype == UNM_BRDTYPE_P3_XG_LOM) { 1083 data = port_mode; /* set to port_mode normally */ 1084 if ((port_mode != UNM_PORT_MODE_802_3_AP) && 1085 (port_mode != UNM_PORT_MODE_XG) && 1086 (port_mode != UNM_PORT_MODE_AUTO_NEG_1G) && 1087 (port_mode != UNM_PORT_MODE_AUTO_NEG_XG)) 1088 data = UNM_PORT_MODE_AUTO_NEG; 1089 1090 adapter->unm_nic_hw_write_wx(adapter, UNM_PORT_MODE_ADDR, 1091 &data, 4); 1092 1093 if ((wol_port_mode != UNM_PORT_MODE_802_3_AP) && 1094 (wol_port_mode != UNM_PORT_MODE_XG) && 1095 (wol_port_mode != UNM_PORT_MODE_AUTO_NEG_1G) && 1096 (wol_port_mode != UNM_PORT_MODE_AUTO_NEG_XG)) 1097 wol_port_mode = UNM_PORT_MODE_AUTO_NEG; 1098 1099 adapter->unm_nic_hw_write_wx(adapter, UNM_WOL_PORT_MODE, 1100 &wol_port_mode, 4); 1101 } 1102 } 1103 1104 static void 1105 netxen_pcie_strap_init(unm_adapter *adapter) 1106 { 1107 ddi_acc_handle_t pcihdl = adapter->pci_cfg_handle; 1108 u32 chicken, control, c8c9value = 0xF1000; 1109 1110 adapter->unm_nic_hw_read_wx(adapter, UNM_PCIE_REG(PCIE_CHICKEN3), 1111 &chicken, 4); 1112 1113 chicken &= 0xFCFFFFFF; /* clear chicken3 25:24 */ 1114 control = pci_config_get32(pcihdl, 0xD0); 1115 if ((control & 0x000F0000) != 0x00020000) /* is it gen1? */ 1116 chicken |= 0x01000000; 1117 adapter->unm_nic_hw_write_wx(adapter, UNM_PCIE_REG(PCIE_CHICKEN3), 1118 &chicken, 4); 1119 control = pci_config_get32(pcihdl, 0xC8); 1120 control = pci_config_get32(pcihdl, 0xC8); 1121 pci_config_put32(pcihdl, 0xC8, c8c9value); 1122 } 1123 1124 static int 1125 netxen_read_mac_addr(unm_adapter *adapter) 1126 { 1127 u64 mac_addr[8 + 1]; 1128 unsigned char *p; 1129 int i; 1130 1131 if (get_flash_mac_addr(adapter, mac_addr) != 0) 1132 return (-1); 1133 1134 if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) 1135 p = (unsigned char *)&mac_addr[adapter->ahw.pci_func]; 1136 else 1137 p = (unsigned char *)&mac_addr[adapter->portnum]; 1138 1139 for (i = 0; i < 6; i++) 1140 adapter->mac_addr[i] = p[5 - i]; 1141 1142 if (unm_nic_macaddr_set(adapter, adapter->mac_addr) != 0) 1143 return (-1); 1144 1145 return (0); 1146 } 1147 1148 static int 1149 unmattach(dev_info_t *dip, ddi_attach_cmd_t cmd) 1150 { 1151 unm_adapter *adapter; 1152 int i, first_driver = 0; 1153 int ret, temp; 1154 1155 switch (cmd) { 1156 case DDI_ATTACH: 1157 break; 1158 case DDI_RESUME: 1159 case DDI_PM_RESUME: 1160 default: 1161 return (DDI_FAILURE); 1162 } 1163 1164 adapter = kmem_zalloc(sizeof (unm_adapter), KM_SLEEP); 1165 adapter->dip = dip; 1166 ddi_set_driver_private(dip, adapter); 1167 adapter->instance = ddi_get_instance(dip); 1168 1169 adapter->name = ddi_driver_name(dip); 1170 1171 ret = pci_config_setup(dip, &adapter->pci_cfg_handle); 1172 if (ret != DDI_SUCCESS) { 1173 cmn_err(CE_WARN, "%s%d: pci_config_setup failed\n", 1174 adapter->name, adapter->instance); 1175 goto attach_setup_err; 1176 } 1177 1178 ret = unm_pci_cfg_init(adapter); 1179 if (ret != DDI_SUCCESS) 1180 goto attach_err; 1181 1182 ret = unm_pci_map_setup(adapter); 1183 if (ret != DDI_SUCCESS) 1184 goto attach_err; 1185 1186 if (unm_initialize_intr(adapter) != DDI_SUCCESS) 1187 goto attach_unmap_regs; 1188 1189 rw_init(&adapter->adapter_lock, NULL, 1190 RW_DRIVER, DDI_INTR_PRI(adapter->intr_pri)); 1191 mutex_init(&adapter->tx_lock, NULL, 1192 MUTEX_DRIVER, (DDI_INTR_PRI(adapter->intr_pri))); 1193 mutex_init(&adapter->lock, NULL, 1194 MUTEX_DRIVER, (DDI_INTR_PRI(adapter->intr_pri))); 1195 1196 adapter->portnum = (int8_t)adapter->ahw.pci_func; 1197 1198 /* 1199 * Set the CRB window to invalid. If any register in window 0 is 1200 * accessed it should set window to 0 and then reset it to 1. 1201 */ 1202 adapter->curr_window = 255; 1203 1204 adapter->fw_major = adapter->unm_nic_pci_read_normalize(adapter, 1205 UNM_FW_VERSION_MAJOR); 1206 1207 if (adapter->fw_major < 4) 1208 adapter->max_rds_rings = 3; 1209 else 1210 adapter->max_rds_rings = 2; 1211 1212 STRUCT_COPY(adapter->gc_dma_attr_desc, unm_dma_attr_desc); 1213 STRUCT_COPY(adapter->gc_attr_desc, unm_buf_attr); 1214 1215 ret = unm_nic_get_board_info(adapter); 1216 if (ret != DDI_SUCCESS) { 1217 cmn_err(CE_WARN, "%s%d: error reading board config\n", 1218 adapter->name, adapter->instance); 1219 goto attach_destroy_intr; 1220 } 1221 1222 /* Mezz cards have PCI function 0, 2, 3 enabled */ 1223 switch (adapter->ahw.boardcfg.board_type) { 1224 case UNM_BRDTYPE_P2_SB31_10G_IMEZ: 1225 case UNM_BRDTYPE_P2_SB31_10G_HMEZ: 1226 if (adapter->ahw.pci_func >= 2) { 1227 adapter->portnum = adapter->ahw.pci_func - 2; 1228 } 1229 default: 1230 break; 1231 } 1232 1233 if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) { 1234 temp = UNM_CRB_READ_VAL_ADAPTER(UNM_MIU_MN_CONTROL, adapter); 1235 adapter->ahw.cut_through = NX_IS_SYSTEM_CUT_THROUGH(temp); 1236 if (adapter->ahw.pci_func == 0) 1237 first_driver = 1; 1238 } else { 1239 if (adapter->portnum == 0) 1240 first_driver = 1; 1241 } 1242 1243 unm_check_options(adapter); 1244 1245 if (first_driver) { 1246 int first_boot = adapter->unm_nic_pci_read_normalize(adapter, 1247 UNM_CAM_RAM(0x1fc)); 1248 1249 if (check_hw_init(adapter) != 0) { 1250 cmn_err(CE_WARN, "%s%d: Error in HW init sequence\n", 1251 adapter->name, adapter->instance); 1252 goto attach_destroy_intr; 1253 } 1254 1255 if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) 1256 netxen_set_port_mode(adapter); 1257 1258 if (first_boot != 0x55555555) { 1259 temp = 0; 1260 adapter->unm_nic_hw_write_wx(adapter, CRB_CMDPEG_STATE, 1261 &temp, 4); 1262 if (pinit_from_rom(adapter, 0) != 0) 1263 goto attach_destroy_intr; 1264 1265 drv_usecwait(500); 1266 1267 ret = load_from_flash(adapter); 1268 if (ret != DDI_SUCCESS) 1269 goto attach_destroy_intr; 1270 } 1271 1272 if (ret = unm_initialize_dummy_dma(adapter)) 1273 goto attach_destroy_intr; 1274 1275 /* 1276 * Tell the hardware our version number. 1277 */ 1278 i = (_UNM_NIC_MAJOR << 16) | 1279 ((_UNM_NIC_MINOR << 8)) | (_UNM_NIC_SUBVERSION); 1280 adapter->unm_nic_hw_write_wx(adapter, CRB_DRIVER_VERSION, 1281 &i, 4); 1282 1283 /* Unlock the HW, prompting the boot sequence */ 1284 if ((first_boot == 0x55555555) && 1285 (NX_IS_REVISION_P2(adapter->ahw.revision_id))) 1286 adapter->unm_nic_pci_write_normalize(adapter, 1287 UNM_ROMUSB_GLB_PEGTUNE_DONE, 1); 1288 1289 /* Handshake with the card before we register the devices. */ 1290 if (phantom_init(adapter, 0) != DDI_SUCCESS) 1291 goto attach_destroy_intr; 1292 } 1293 1294 if (NX_IS_REVISION_P3(adapter->ahw.revision_id)) 1295 netxen_pcie_strap_init(adapter); 1296 1297 /* 1298 * See if the firmware gave us a virtual-physical port mapping. 1299 */ 1300 adapter->physical_port = adapter->portnum; 1301 i = adapter->unm_nic_pci_read_normalize(adapter, 1302 CRB_V2P(adapter->portnum)); 1303 if (i != 0x55555555) 1304 adapter->physical_port = (uint16_t)i; 1305 1306 adapter->ahw.linkup = 0; 1307 1308 if (receive_peg_ready(adapter)) { 1309 ret = -EIO; 1310 goto free_dummy_dma; 1311 } 1312 1313 if (netxen_read_mac_addr(adapter)) 1314 cmn_err(CE_WARN, "%s%d: Failed to read MAC addr\n", 1315 adapter->name, adapter->instance); 1316 1317 unm_nic_flash_print(adapter); 1318 1319 if (verbmsg != 0) { 1320 switch (adapter->ahw.board_type) { 1321 case UNM_NIC_GBE: 1322 cmn_err(CE_NOTE, "%s: QUAD GbE port %d initialized\n", 1323 unm_nic_driver_name, adapter->portnum); 1324 break; 1325 1326 case UNM_NIC_XGBE: 1327 cmn_err(CE_NOTE, "%s: XGbE port %d initialized\n", 1328 unm_nic_driver_name, adapter->portnum); 1329 break; 1330 } 1331 } 1332 1333 ret = unm_register_mac(adapter); 1334 if (ret != DDI_SUCCESS) { 1335 cmn_err(CE_NOTE, "%s%d: Mac registration error\n", 1336 adapter->name, adapter->instance); 1337 goto free_dummy_dma; 1338 } 1339 1340 return (DDI_SUCCESS); 1341 1342 free_dummy_dma: 1343 if (first_driver) 1344 unm_free_dummy_dma(adapter); 1345 attach_destroy_intr: 1346 unm_destroy_intr(adapter); 1347 attach_unmap_regs: 1348 ddi_regs_map_free(&(adapter->regs_handle)); 1349 ddi_regs_map_free(&(adapter->db_handle)); 1350 attach_err: 1351 pci_config_teardown(&adapter->pci_cfg_handle); 1352 attach_setup_err: 1353 kmem_free(adapter, sizeof (unm_adapter)); 1354 return (ret); 1355 } 1356 1357 static int 1358 unmdetach(dev_info_t *dip, ddi_detach_cmd_t cmd) 1359 { 1360 unm_adapter *adapter = (unm_adapter *)ddi_get_driver_private(dip); 1361 1362 if (adapter == NULL) 1363 return (DDI_FAILURE); 1364 1365 switch (cmd) { 1366 case DDI_DETACH: 1367 unm_fini_kstats(adapter); 1368 adapter->kstats[0] = NULL; 1369 1370 if (adapter->pci_cfg_handle != NULL) 1371 pci_config_teardown(&adapter->pci_cfg_handle); 1372 1373 unm_nd_cleanup(adapter); 1374 unm_nic_remove(adapter); 1375 return (DDI_SUCCESS); 1376 1377 case DDI_SUSPEND: 1378 return (unm_nic_suspend(adapter)); 1379 1380 default: 1381 break; 1382 } 1383 1384 return (DDI_FAILURE); 1385 } 1386 1387 int 1388 create_rxtx_rings(unm_adapter *adapter) 1389 { 1390 unm_recv_context_t *recv_ctx; 1391 unm_rcv_desc_ctx_t *rcv_desc; 1392 int i, ring; 1393 1394 adapter->cmd_buf_arr = (struct unm_cmd_buffer *)kmem_zalloc( 1395 sizeof (struct unm_cmd_buffer) * adapter->MaxTxDescCount, 1396 KM_SLEEP); 1397 1398 for (i = 0; i < MAX_RCV_CTX; ++i) { 1399 recv_ctx = &adapter->recv_ctx[i]; 1400 1401 for (ring = 0; ring < adapter->max_rds_rings; ring++) { 1402 rcv_desc = &recv_ctx->rcv_desc[ring]; 1403 if (unm_create_rx_ring(adapter, rcv_desc) != 1404 DDI_SUCCESS) 1405 goto attach_free_cmdbufs; 1406 } 1407 } 1408 1409 if (unm_alloc_tx_dmahdl(adapter) != DDI_SUCCESS) 1410 goto attach_free_cmdbufs; 1411 1412 if (unm_alloc_tx_buffers(adapter) != DDI_SUCCESS) 1413 goto attach_free_tx_dmahdl; 1414 1415 return (DDI_SUCCESS); 1416 1417 attach_free_tx_buffers: 1418 unm_free_tx_buffers(adapter); 1419 attach_free_tx_dmahdl: 1420 unm_free_tx_dmahdl(adapter); 1421 attach_free_cmdbufs: 1422 kmem_free(adapter->cmd_buf_arr, sizeof (struct unm_cmd_buffer) * 1423 adapter->MaxTxDescCount); 1424 for (i = 0; i < MAX_RCV_CTX; ++i) { 1425 recv_ctx = &adapter->recv_ctx[i]; 1426 1427 for (ring = 0; ring < adapter->max_rds_rings; ring++) { 1428 rcv_desc = &recv_ctx->rcv_desc[ring]; 1429 if (rcv_desc->rx_buf_pool != NULL) 1430 unm_destroy_rx_ring(rcv_desc); 1431 } 1432 } 1433 return (DDI_FAILURE); 1434 } 1435 1436 void 1437 destroy_rxtx_rings(unm_adapter *adapter) 1438 { 1439 unm_recv_context_t *recv_ctx; 1440 unm_rcv_desc_ctx_t *rcv_desc; 1441 int ctx, ring; 1442 1443 unm_free_tx_buffers(adapter); 1444 unm_free_tx_dmahdl(adapter); 1445 1446 for (ctx = 0; ctx < MAX_RCV_CTX; ++ctx) { 1447 recv_ctx = &adapter->recv_ctx[ctx]; 1448 for (ring = 0; ring < adapter->max_rds_rings; ring++) { 1449 rcv_desc = &recv_ctx->rcv_desc[ring]; 1450 if (rcv_desc->rx_buf_pool != NULL) 1451 unm_destroy_rx_ring(rcv_desc); 1452 } 1453 } 1454 1455 if (adapter->cmd_buf_arr != NULL) 1456 kmem_free(adapter->cmd_buf_arr, 1457 sizeof (struct unm_cmd_buffer) * adapter->MaxTxDescCount); 1458 } 1459 1460 #ifdef SOLARIS11 1461 DDI_DEFINE_STREAM_OPS(unm_ops, nulldev, nulldev, unmattach, unmdetach, 1462 nodev, NULL, D_MP, NULL, NULL); 1463 #else 1464 DDI_DEFINE_STREAM_OPS(unm_ops, nulldev, nulldev, unmattach, unmdetach, 1465 nodev, NULL, D_MP, NULL); 1466 #endif 1467 1468 static struct modldrv modldrv = { 1469 &mod_driverops, /* Type of module. This one is a driver */ 1470 ident, 1471 &unm_ops, /* driver ops */ 1472 }; 1473 1474 static struct modlinkage modlinkage = { 1475 MODREV_1, 1476 (&modldrv), 1477 NULL 1478 }; 1479 1480 1481 int 1482 _init(void) 1483 { 1484 int ret; 1485 1486 unm_ops.devo_cb_ops->cb_str = NULL; 1487 mac_init_ops(&unm_ops, "ntxn"); 1488 1489 ret = mod_install(&modlinkage); 1490 if (ret != DDI_SUCCESS) { 1491 mac_fini_ops(&unm_ops); 1492 cmn_err(CE_WARN, "ntxn: mod_install failed\n"); 1493 } 1494 1495 return (ret); 1496 } 1497 1498 1499 int 1500 _fini(void) 1501 { 1502 int ret; 1503 1504 ret = mod_remove(&modlinkage); 1505 if (ret == DDI_SUCCESS) 1506 mac_fini_ops(&unm_ops); 1507 return (ret); 1508 } 1509 1510 int 1511 _info(struct modinfo *modinfop) 1512 { 1513 return (mod_info(&modlinkage, modinfop)); 1514 } 1515