1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2007-2009 Myricom, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #ifndef lint 28 static const char __idstring[] = 29 "@(#)$Id: myri10ge.c,v 1.186 2009-06-29 13:47:22 gallatin Exp $"; 30 #endif 31 32 #define MXGEFW_NDIS 33 #include "myri10ge_var.h" 34 #include "rss_eth_z8e.h" 35 #include "rss_ethp_z8e.h" 36 #include "mcp_gen_header.h" 37 38 #define MYRI10GE_MAX_ETHER_MTU 9014 39 40 #define MYRI10GE_ETH_STOPPED 0 41 #define MYRI10GE_ETH_STOPPING 1 42 #define MYRI10GE_ETH_STARTING 2 43 #define MYRI10GE_ETH_RUNNING 3 44 #define MYRI10GE_ETH_OPEN_FAILED 4 45 #define MYRI10GE_ETH_SUSPENDED_RUNNING 5 46 47 static int myri10ge_small_bytes = 510; 48 static int myri10ge_intr_coal_delay = 125; 49 static int myri10ge_flow_control = 1; 50 #if #cpu(i386) || defined __i386 || defined i386 || \ 51 defined __i386__ || #cpu(x86_64) || defined __x86_64__ 52 static int myri10ge_nvidia_ecrc_enable = 1; 53 #endif 54 static int myri10ge_mtu_override = 0; 55 static int myri10ge_tx_copylen = 512; 56 static int myri10ge_deassert_wait = 1; 57 static int myri10ge_verbose = 0; 58 static int myri10ge_watchdog_reset = 0; 59 static int myri10ge_use_msix = 1; 60 static int myri10ge_max_slices = -1; 61 static int myri10ge_use_msi = 1; 62 int myri10ge_force_firmware = 0; 63 static boolean_t myri10ge_use_lso = B_TRUE; 64 static int myri10ge_rss_hash = MXGEFW_RSS_HASH_TYPE_SRC_DST_PORT; 65 static int myri10ge_tx_hash = 1; 66 static int myri10ge_lro = 1; 67 static int myri10ge_lro_cnt = 8; 68 int myri10ge_lro_max_aggr = 2; 69 static int myri10ge_lso_copy = 0; 70 static mblk_t *myri10ge_send_wrapper(void *arg, mblk_t *mp); 71 int myri10ge_tx_handles_initial = 128; 72 73 static kmutex_t myri10ge_param_lock; 74 static void* myri10ge_db_lastfree; 75 76 static int myri10ge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd); 77 static int myri10ge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd); 78 static int myri10ge_quiesce(dev_info_t *dip); 79 80 DDI_DEFINE_STREAM_OPS(myri10ge_ops, nulldev, nulldev, myri10ge_attach, 81 myri10ge_detach, nodev, NULL, D_MP, NULL, myri10ge_quiesce); 82 83 84 static struct modldrv modldrv = { 85 &mod_driverops, 86 "Myricom 10G driver (10GbE)", 87 &myri10ge_ops, 88 }; 89 90 91 static struct modlinkage modlinkage = { 92 MODREV_1, 93 {&modldrv, NULL}, 94 }; 95 96 unsigned char myri10ge_broadcastaddr[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 97 98 static ddi_dma_attr_t myri10ge_misc_dma_attr = { 99 DMA_ATTR_V0, /* version number. */ 100 (uint64_t)0, /* low address */ 101 (uint64_t)0xffffffffffffffffULL, /* high address */ 102 (uint64_t)0x7ffffff, /* address counter max */ 103 (uint64_t)4096, /* alignment */ 104 (uint_t)0x7f, /* burstsizes for 32b and 64b xfers */ 105 (uint32_t)0x1, /* minimum transfer size */ 106 (uint64_t)0x7fffffff, /* maximum transfer size */ 107 (uint64_t)0x7fffffff, /* maximum segment size */ 108 1, /* scatter/gather list length */ 109 1, /* granularity */ 110 0 /* attribute flags */ 111 }; 112 113 /* 114 * The Myri10GE NIC has the following constraints on receive buffers: 115 * 1) Buffers which cross a 4KB boundary must be aligned to 4KB 116 * 2) Buffers which are not aligned to 4KB must not cross a 4KB boundary 117 */ 118 119 static ddi_dma_attr_t myri10ge_rx_jumbo_dma_attr = { 120 DMA_ATTR_V0, /* version number. */ 121 (uint64_t)0, /* low address */ 122 (uint64_t)0xffffffffffffffffULL, /* high address */ 123 (uint64_t)0x7ffffff, /* address counter max */ 124 (uint64_t)4096, /* alignment */ 125 (uint_t)0x7f, /* burstsizes for 32b and 64b xfers */ 126 (uint32_t)0x1, /* minimum transfer size */ 127 (uint64_t)0x7fffffff, /* maximum transfer size */ 128 UINT64_MAX, /* maximum segment size */ 129 1, /* scatter/gather list length */ 130 1, /* granularity */ 131 0 /* attribute flags */ 132 }; 133 134 static ddi_dma_attr_t myri10ge_rx_std_dma_attr = { 135 DMA_ATTR_V0, /* version number. */ 136 (uint64_t)0, /* low address */ 137 (uint64_t)0xffffffffffffffffULL, /* high address */ 138 (uint64_t)0x7ffffff, /* address counter max */ 139 #if defined sparc64 || defined __sparcv9 140 (uint64_t)4096, /* alignment */ 141 #else 142 (uint64_t)0x80, /* alignment */ 143 #endif 144 (uint_t)0x7f, /* burstsizes for 32b and 64b xfers */ 145 (uint32_t)0x1, /* minimum transfer size */ 146 (uint64_t)0x7fffffff, /* maximum transfer size */ 147 #if defined sparc64 || defined __sparcv9 148 UINT64_MAX, /* maximum segment size */ 149 #else 150 (uint64_t)0xfff, /* maximum segment size */ 151 #endif 152 1, /* scatter/gather list length */ 153 1, /* granularity */ 154 0 /* attribute flags */ 155 }; 156 157 static ddi_dma_attr_t myri10ge_tx_dma_attr = { 158 DMA_ATTR_V0, /* version number. */ 159 (uint64_t)0, /* low address */ 160 (uint64_t)0xffffffffffffffffULL, /* high address */ 161 (uint64_t)0x7ffffff, /* address counter max */ 162 (uint64_t)1, /* alignment */ 163 (uint_t)0x7f, /* burstsizes for 32b and 64b xfers */ 164 (uint32_t)0x1, /* minimum transfer size */ 165 (uint64_t)0x7fffffff, /* maximum transfer size */ 166 UINT64_MAX, /* maximum segment size */ 167 INT32_MAX, /* scatter/gather list length */ 168 1, /* granularity */ 169 0 /* attribute flags */ 170 }; 171 172 #if defined sparc64 || defined __sparcv9 173 #define WC 0 174 #else 175 #define WC 1 176 #endif 177 178 struct ddi_device_acc_attr myri10ge_dev_access_attr = { 179 DDI_DEVICE_ATTR_V0, /* version */ 180 DDI_NEVERSWAP_ACC, /* endian flash */ 181 #if WC 182 DDI_MERGING_OK_ACC /* data order */ 183 #else 184 DDI_STRICTORDER_ACC 185 #endif 186 }; 187 188 static void myri10ge_watchdog(void *arg); 189 190 #ifdef MYRICOM_PRIV 191 int myri10ge_mtu = MYRI10GE_MAX_ETHER_MTU + MXGEFW_PAD + VLAN_TAGSZ; 192 #else 193 int myri10ge_mtu = ETHERMAX + MXGEFW_PAD + VLAN_TAGSZ; 194 #endif 195 int myri10ge_bigbufs_initial = 1024; 196 int myri10ge_bigbufs_max = 4096; 197 198 199 caddr_t 200 myri10ge_dma_alloc(dev_info_t *dip, size_t len, 201 ddi_dma_attr_t *attr, ddi_device_acc_attr_t *accattr, 202 uint_t alloc_flags, int bind_flags, struct myri10ge_dma_stuff *dma, 203 int warn, int (*wait)(caddr_t)) 204 { 205 caddr_t kaddr; 206 size_t real_length; 207 ddi_dma_cookie_t cookie; 208 uint_t count; 209 int err; 210 211 err = ddi_dma_alloc_handle(dip, attr, wait, 212 NULL, &dma->handle); 213 if (err != DDI_SUCCESS) { 214 if (warn) 215 cmn_err(CE_WARN, 216 "myri10ge: ddi_dma_alloc_handle failed\n"); 217 goto abort_with_nothing; 218 } 219 220 err = ddi_dma_mem_alloc(dma->handle, len, accattr, alloc_flags, 221 wait, NULL, &kaddr, &real_length, 222 &dma->acc_handle); 223 if (err != DDI_SUCCESS) { 224 if (warn) 225 cmn_err(CE_WARN, 226 "myri10ge: ddi_dma_mem_alloc failed\n"); 227 goto abort_with_handle; 228 } 229 230 err = ddi_dma_addr_bind_handle(dma->handle, NULL, kaddr, len, 231 bind_flags, wait, NULL, &cookie, &count); 232 233 if (err != DDI_SUCCESS) { 234 if (warn) 235 cmn_err(CE_WARN, 236 "myri10ge: ddi_dma_addr_bind_handle failed\n"); 237 goto abort_with_mem; 238 } 239 240 if (count != 1) { 241 if (warn) 242 cmn_err(CE_WARN, 243 "myri10ge: got too many dma segments "); 244 goto abort_with_bind; 245 } 246 dma->low = htonl(MYRI10GE_LOWPART_TO_U32(cookie.dmac_laddress)); 247 dma->high = htonl(MYRI10GE_HIGHPART_TO_U32(cookie.dmac_laddress)); 248 return (kaddr); 249 250 abort_with_bind: 251 (void) ddi_dma_unbind_handle(dma->handle); 252 253 abort_with_mem: 254 ddi_dma_mem_free(&dma->acc_handle); 255 256 abort_with_handle: 257 ddi_dma_free_handle(&dma->handle); 258 abort_with_nothing: 259 if (warn) { 260 cmn_err(CE_WARN, "myri10ge: myri10ge_dma_alloc failed.\n "); 261 cmn_err(CE_WARN, "args: dip=%p len=0x%lx ddi_dma_attr=%p\n", 262 (void*) dip, len, (void*) attr); 263 cmn_err(CE_WARN, 264 "args: ddi_device_acc_attr=%p alloc_flags=0x%x\n", 265 (void*) accattr, alloc_flags); 266 cmn_err(CE_WARN, "args: bind_flags=0x%x dmastuff=%p", 267 bind_flags, (void*) dma); 268 } 269 return (NULL); 270 271 } 272 273 void 274 myri10ge_dma_free(struct myri10ge_dma_stuff *dma) 275 { 276 (void) ddi_dma_unbind_handle(dma->handle); 277 ddi_dma_mem_free(&dma->acc_handle); 278 ddi_dma_free_handle(&dma->handle); 279 } 280 281 static inline void 282 myri10ge_pio_copy32(void *to, uint32_t *from32, size_t size) 283 { 284 register volatile uint32_t *to32; 285 size_t i; 286 287 to32 = (volatile uint32_t *) to; 288 for (i = (size / 4); i; i--) { 289 *to32 = *from32; 290 to32++; 291 from32++; 292 } 293 } 294 295 #if defined(_LP64) 296 static inline void 297 myri10ge_pio_copy64(void *to, uint64_t *from64, size_t size) 298 { 299 register volatile uint64_t *to64; 300 size_t i; 301 302 to64 = (volatile uint64_t *) to; 303 for (i = (size / 8); i; i--) { 304 *to64 = *from64; 305 to64++; 306 from64++; 307 } 308 } 309 #endif 310 311 /* 312 * This routine copies memory from the host to the NIC. 313 * The "size" argument must always be a multiple of 314 * the size of long (4 or 8 bytes), and to/from must also 315 * be naturally aligned. 316 */ 317 static inline void 318 myri10ge_pio_copy(void *to, void *from, size_t size) 319 { 320 #if !defined(_LP64) 321 ASSERT((size % 4) == 0); 322 myri10ge_pio_copy32(to, (uint32_t *)from, size); 323 #else 324 ASSERT((size % 8) == 0); 325 myri10ge_pio_copy64(to, (uint64_t *)from, size); 326 #endif 327 } 328 329 330 /* 331 * Due to various bugs in Solaris (especially bug 6186772 where the 332 * TCP/UDP checksum is calculated incorrectly on mblk chains with more 333 * than two elements), and the design bug where hardware checksums are 334 * ignored on mblk chains with more than 2 elements, we need to 335 * allocate private pool of physically contiguous receive buffers. 336 */ 337 338 static void 339 myri10ge_jpool_init(struct myri10ge_slice_state *ss) 340 { 341 struct myri10ge_jpool_stuff *jpool = &ss->jpool; 342 343 bzero(jpool, sizeof (*jpool)); 344 mutex_init(&jpool->mtx, NULL, MUTEX_DRIVER, 345 ss->mgp->icookie); 346 jpool->head = NULL; 347 } 348 349 static void 350 myri10ge_jpool_fini(struct myri10ge_slice_state *ss) 351 { 352 struct myri10ge_jpool_stuff *jpool = &ss->jpool; 353 354 if (jpool->head != NULL) { 355 cmn_err(CE_WARN, 356 "%s: BUG! myri10ge_jpool_fini called on non-empty pool\n", 357 ss->mgp->name); 358 } 359 mutex_destroy(&jpool->mtx); 360 } 361 362 363 /* 364 * copy an array of mcp_kreq_ether_recv_t's to the mcp. Copy 365 * at most 32 bytes at a time, so as to avoid involving the software 366 * pio handler in the nic. We re-write the first segment's low 367 * DMA address to mark it valid only after we write the entire chunk 368 * in a burst 369 */ 370 static inline void 371 myri10ge_submit_8rx(mcp_kreq_ether_recv_t *dst, mcp_kreq_ether_recv_t *src) 372 { 373 src->addr_low |= BE_32(1); 374 myri10ge_pio_copy(dst, src, 4 * sizeof (*src)); 375 mb(); 376 myri10ge_pio_copy(dst + 4, src + 4, 4 * sizeof (*src)); 377 mb(); 378 src->addr_low &= ~(BE_32(1)); 379 dst->addr_low = src->addr_low; 380 mb(); 381 } 382 383 static void 384 myri10ge_pull_jpool(struct myri10ge_slice_state *ss) 385 { 386 struct myri10ge_jpool_stuff *jpool = &ss->jpool; 387 struct myri10ge_jpool_entry *jtail, *j, *jfree; 388 volatile uintptr_t *putp; 389 uintptr_t put; 390 int i; 391 392 /* find tail */ 393 jtail = NULL; 394 if (jpool->head != NULL) { 395 j = jpool->head; 396 while (j->next != NULL) 397 j = j->next; 398 jtail = j; 399 } 400 401 /* 402 * iterate over all per-CPU caches, and add contents into 403 * jpool 404 */ 405 for (i = 0; i < MYRI10GE_MAX_CPUS; i++) { 406 /* take per-CPU free list */ 407 putp = (void *)&jpool->cpu[i & MYRI10GE_MAX_CPU_MASK].head; 408 if (*putp == NULL) 409 continue; 410 put = atomic_swap_ulong(putp, 0); 411 jfree = (struct myri10ge_jpool_entry *)put; 412 413 /* append to pool */ 414 if (jtail == NULL) { 415 jpool->head = jfree; 416 } else { 417 jtail->next = jfree; 418 } 419 j = jfree; 420 while (j->next != NULL) 421 j = j->next; 422 jtail = j; 423 } 424 } 425 426 /* 427 * Transfers buffers from the free pool to the nic 428 * Must be called holding the jpool mutex. 429 */ 430 431 static inline void 432 myri10ge_restock_jumbos(struct myri10ge_slice_state *ss) 433 { 434 struct myri10ge_jpool_stuff *jpool = &ss->jpool; 435 struct myri10ge_jpool_entry *j; 436 myri10ge_rx_ring_t *rx; 437 int i, idx, limit; 438 439 rx = &ss->rx_big; 440 limit = ss->j_rx_cnt + (rx->mask + 1); 441 442 for (i = rx->cnt; i != limit; i++) { 443 idx = i & (rx->mask); 444 j = jpool->head; 445 if (j == NULL) { 446 myri10ge_pull_jpool(ss); 447 j = jpool->head; 448 if (j == NULL) { 449 break; 450 } 451 } 452 jpool->head = j->next; 453 rx->info[idx].j = j; 454 rx->shadow[idx].addr_low = j->dma.low; 455 rx->shadow[idx].addr_high = j->dma.high; 456 /* copy 4 descriptors (32-bytes) to the mcp at a time */ 457 if ((idx & 7) == 7) { 458 myri10ge_submit_8rx(&rx->lanai[idx - 7], 459 &rx->shadow[idx - 7]); 460 } 461 } 462 rx->cnt = i; 463 } 464 465 /* 466 * Transfer buffers from the nic to the free pool. 467 * Should be called holding the jpool mutex 468 */ 469 470 static inline void 471 myri10ge_unstock_jumbos(struct myri10ge_slice_state *ss) 472 { 473 struct myri10ge_jpool_stuff *jpool = &ss->jpool; 474 struct myri10ge_jpool_entry *j; 475 myri10ge_rx_ring_t *rx; 476 int i; 477 478 mutex_enter(&jpool->mtx); 479 rx = &ss->rx_big; 480 481 for (i = 0; i < rx->mask + 1; i++) { 482 j = rx->info[i].j; 483 rx->info[i].j = NULL; 484 if (j == NULL) 485 continue; 486 j->next = jpool->head; 487 jpool->head = j; 488 } 489 mutex_exit(&jpool->mtx); 490 491 } 492 493 494 /* 495 * Free routine which is called when the mblk allocated via 496 * esballoc() is freed. Here we return the jumbo buffer 497 * to the free pool, and possibly pass some jumbo buffers 498 * to the nic 499 */ 500 501 static void 502 myri10ge_jfree_rtn(void *arg) 503 { 504 struct myri10ge_jpool_entry *j = (struct myri10ge_jpool_entry *)arg; 505 struct myri10ge_jpool_stuff *jpool; 506 volatile uintptr_t *putp; 507 uintptr_t old, new; 508 509 jpool = &j->ss->jpool; 510 511 /* prepend buffer locklessly to per-CPU freelist */ 512 putp = (void *)&jpool->cpu[CPU->cpu_seqid & MYRI10GE_MAX_CPU_MASK].head; 513 new = (uintptr_t)j; 514 do { 515 old = *putp; 516 j->next = (void *)old; 517 } while (atomic_cas_ulong(putp, old, new) != old); 518 } 519 520 static void 521 myri10ge_remove_jbuf(struct myri10ge_jpool_entry *j) 522 { 523 (void) ddi_dma_unbind_handle(j->dma_handle); 524 ddi_dma_mem_free(&j->acc_handle); 525 ddi_dma_free_handle(&j->dma_handle); 526 kmem_free(j, sizeof (*j)); 527 } 528 529 530 /* 531 * Allocates one physically contiguous descriptor 532 * and add it to the jumbo buffer pool. 533 */ 534 535 static int 536 myri10ge_add_jbuf(struct myri10ge_slice_state *ss) 537 { 538 struct myri10ge_jpool_entry *j; 539 struct myri10ge_jpool_stuff *jpool = &ss->jpool; 540 ddi_dma_attr_t *rx_dma_attr; 541 size_t real_length; 542 ddi_dma_cookie_t cookie; 543 uint_t count; 544 int err; 545 546 if (myri10ge_mtu < 2048) 547 rx_dma_attr = &myri10ge_rx_std_dma_attr; 548 else 549 rx_dma_attr = &myri10ge_rx_jumbo_dma_attr; 550 551 again: 552 j = (struct myri10ge_jpool_entry *) 553 kmem_alloc(sizeof (*j), KM_SLEEP); 554 err = ddi_dma_alloc_handle(ss->mgp->dip, rx_dma_attr, 555 DDI_DMA_DONTWAIT, NULL, &j->dma_handle); 556 if (err != DDI_SUCCESS) 557 goto abort_with_j; 558 559 err = ddi_dma_mem_alloc(j->dma_handle, myri10ge_mtu, 560 &myri10ge_dev_access_attr, DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 561 NULL, &j->buf, &real_length, &j->acc_handle); 562 if (err != DDI_SUCCESS) 563 goto abort_with_handle; 564 565 err = ddi_dma_addr_bind_handle(j->dma_handle, NULL, j->buf, 566 real_length, DDI_DMA_READ|DDI_DMA_STREAMING, DDI_DMA_DONTWAIT, 567 NULL, &cookie, &count); 568 if (err != DDI_SUCCESS) 569 goto abort_with_mem; 570 571 /* 572 * Make certain std MTU buffers do not cross a 4KB boundary: 573 * 574 * Setting dma_attr_align=4096 will do this, but the system 575 * will only allocate 1 RX buffer per 4KB page, rather than 2. 576 * Setting dma_attr_granular=4096 *seems* to work around this, 577 * but I'm paranoid about future systems no longer honoring 578 * this, so fall back to the safe, but memory wasting way if a 579 * buffer crosses a 4KB boundary. 580 */ 581 582 if (rx_dma_attr == &myri10ge_rx_std_dma_attr && 583 rx_dma_attr->dma_attr_align != 4096) { 584 uint32_t start, end; 585 586 start = MYRI10GE_LOWPART_TO_U32(cookie.dmac_laddress); 587 end = start + myri10ge_mtu; 588 if (((end >> 12) != (start >> 12)) && (start & 4095U)) { 589 printf("std buffer crossed a 4KB boundary!\n"); 590 myri10ge_remove_jbuf(j); 591 rx_dma_attr->dma_attr_align = 4096; 592 rx_dma_attr->dma_attr_seg = UINT64_MAX; 593 goto again; 594 } 595 } 596 597 j->dma.low = 598 htonl(MYRI10GE_LOWPART_TO_U32(cookie.dmac_laddress)); 599 j->dma.high = 600 htonl(MYRI10GE_HIGHPART_TO_U32(cookie.dmac_laddress)); 601 j->ss = ss; 602 603 604 j->free_func.free_func = myri10ge_jfree_rtn; 605 j->free_func.free_arg = (char *)j; 606 mutex_enter(&jpool->mtx); 607 j->next = jpool->head; 608 jpool->head = j; 609 jpool->num_alloc++; 610 mutex_exit(&jpool->mtx); 611 return (0); 612 613 abort_with_mem: 614 ddi_dma_mem_free(&j->acc_handle); 615 616 abort_with_handle: 617 ddi_dma_free_handle(&j->dma_handle); 618 619 abort_with_j: 620 kmem_free(j, sizeof (*j)); 621 622 /* 623 * If an allocation failed, perhaps it failed because it could 624 * not satisfy granularity requirement. Disable that, and 625 * try agin. 626 */ 627 if (rx_dma_attr == &myri10ge_rx_std_dma_attr && 628 rx_dma_attr->dma_attr_align != 4096) { 629 cmn_err(CE_NOTE, 630 "!alloc failed, reverting to gran=1\n"); 631 rx_dma_attr->dma_attr_align = 4096; 632 rx_dma_attr->dma_attr_seg = UINT64_MAX; 633 goto again; 634 } 635 return (err); 636 } 637 638 static int 639 myri10ge_jfree_cnt(struct myri10ge_jpool_stuff *jpool) 640 { 641 int i; 642 struct myri10ge_jpool_entry *j; 643 644 mutex_enter(&jpool->mtx); 645 j = jpool->head; 646 i = 0; 647 while (j != NULL) { 648 i++; 649 j = j->next; 650 } 651 mutex_exit(&jpool->mtx); 652 return (i); 653 } 654 655 static int 656 myri10ge_add_jbufs(struct myri10ge_slice_state *ss, int num, int total) 657 { 658 struct myri10ge_jpool_stuff *jpool = &ss->jpool; 659 int allocated = 0; 660 int err; 661 int needed; 662 663 /* 664 * if total is set, user wants "num" jbufs in the pool, 665 * otherwise the user wants to "num" additional jbufs 666 * added to the pool 667 */ 668 if (total && jpool->num_alloc) { 669 allocated = myri10ge_jfree_cnt(jpool); 670 needed = num - allocated; 671 } else { 672 needed = num; 673 } 674 675 while (needed > 0) { 676 needed--; 677 err = myri10ge_add_jbuf(ss); 678 if (err == 0) { 679 allocated++; 680 } 681 } 682 return (allocated); 683 } 684 685 static void 686 myri10ge_remove_jbufs(struct myri10ge_slice_state *ss) 687 { 688 struct myri10ge_jpool_stuff *jpool = &ss->jpool; 689 struct myri10ge_jpool_entry *j; 690 691 mutex_enter(&jpool->mtx); 692 myri10ge_pull_jpool(ss); 693 while (jpool->head != NULL) { 694 jpool->num_alloc--; 695 j = jpool->head; 696 jpool->head = j->next; 697 myri10ge_remove_jbuf(j); 698 } 699 mutex_exit(&jpool->mtx); 700 } 701 702 static void 703 myri10ge_carve_up_jbufs_into_small_ring(struct myri10ge_slice_state *ss) 704 { 705 struct myri10ge_jpool_stuff *jpool = &ss->jpool; 706 struct myri10ge_jpool_entry *j = NULL; 707 caddr_t ptr; 708 uint32_t dma_low, dma_high; 709 int idx, len; 710 unsigned int alloc_size; 711 712 dma_low = dma_high = len = 0; 713 alloc_size = myri10ge_small_bytes + MXGEFW_PAD; 714 ptr = NULL; 715 for (idx = 0; idx < ss->rx_small.mask + 1; idx++) { 716 /* Allocate a jumbo frame and carve it into small frames */ 717 if (len < alloc_size) { 718 mutex_enter(&jpool->mtx); 719 /* remove jumbo from freelist */ 720 j = jpool->head; 721 jpool->head = j->next; 722 /* place it onto small list */ 723 j->next = ss->small_jpool; 724 ss->small_jpool = j; 725 mutex_exit(&jpool->mtx); 726 len = myri10ge_mtu; 727 dma_low = ntohl(j->dma.low); 728 dma_high = ntohl(j->dma.high); 729 ptr = j->buf; 730 } 731 ss->rx_small.info[idx].ptr = ptr; 732 ss->rx_small.shadow[idx].addr_low = htonl(dma_low); 733 ss->rx_small.shadow[idx].addr_high = htonl(dma_high); 734 len -= alloc_size; 735 ptr += alloc_size; 736 dma_low += alloc_size; 737 } 738 } 739 740 /* 741 * Return the jumbo bufs we carved up for small to the jumbo pool 742 */ 743 744 static void 745 myri10ge_release_small_jbufs(struct myri10ge_slice_state *ss) 746 { 747 struct myri10ge_jpool_stuff *jpool = &ss->jpool; 748 struct myri10ge_jpool_entry *j = NULL; 749 750 mutex_enter(&jpool->mtx); 751 while (ss->small_jpool != NULL) { 752 j = ss->small_jpool; 753 ss->small_jpool = j->next; 754 j->next = jpool->head; 755 jpool->head = j; 756 } 757 mutex_exit(&jpool->mtx); 758 ss->jbufs_for_smalls = 0; 759 } 760 761 static int 762 myri10ge_add_tx_handle(struct myri10ge_slice_state *ss) 763 { 764 myri10ge_tx_ring_t *tx = &ss->tx; 765 struct myri10ge_priv *mgp = ss->mgp; 766 struct myri10ge_tx_dma_handle *handle; 767 int err; 768 769 handle = kmem_zalloc(sizeof (*handle), KM_SLEEP); 770 err = ddi_dma_alloc_handle(mgp->dip, 771 &myri10ge_tx_dma_attr, 772 DDI_DMA_SLEEP, NULL, 773 &handle->h); 774 if (err) { 775 static int limit = 0; 776 if (limit == 0) 777 cmn_err(CE_WARN, "%s: Falled to alloc tx dma handle\n", 778 mgp->name); 779 limit++; 780 kmem_free(handle, sizeof (*handle)); 781 return (err); 782 } 783 mutex_enter(&tx->handle_lock); 784 MYRI10GE_SLICE_STAT_INC(tx_handles_alloced); 785 handle->next = tx->free_tx_handles; 786 tx->free_tx_handles = handle; 787 mutex_exit(&tx->handle_lock); 788 return (DDI_SUCCESS); 789 } 790 791 static void 792 myri10ge_remove_tx_handles(struct myri10ge_slice_state *ss) 793 { 794 myri10ge_tx_ring_t *tx = &ss->tx; 795 struct myri10ge_tx_dma_handle *handle; 796 mutex_enter(&tx->handle_lock); 797 798 handle = tx->free_tx_handles; 799 while (handle != NULL) { 800 tx->free_tx_handles = handle->next; 801 ddi_dma_free_handle(&handle->h); 802 kmem_free(handle, sizeof (*handle)); 803 handle = tx->free_tx_handles; 804 MYRI10GE_SLICE_STAT_DEC(tx_handles_alloced); 805 } 806 mutex_exit(&tx->handle_lock); 807 if (MYRI10GE_SLICE_STAT(tx_handles_alloced) != 0) { 808 cmn_err(CE_WARN, "%s: %d tx dma handles allocated at close\n", 809 ss->mgp->name, 810 (int)MYRI10GE_SLICE_STAT(tx_handles_alloced)); 811 } 812 } 813 814 static void 815 myri10ge_free_tx_handles(myri10ge_tx_ring_t *tx, 816 struct myri10ge_tx_dma_handle_head *list) 817 { 818 mutex_enter(&tx->handle_lock); 819 list->tail->next = tx->free_tx_handles; 820 tx->free_tx_handles = list->head; 821 mutex_exit(&tx->handle_lock); 822 } 823 824 static void 825 myri10ge_free_tx_handle_slist(myri10ge_tx_ring_t *tx, 826 struct myri10ge_tx_dma_handle *handle) 827 { 828 struct myri10ge_tx_dma_handle_head list; 829 830 if (handle == NULL) 831 return; 832 list.head = handle; 833 list.tail = handle; 834 while (handle != NULL) { 835 list.tail = handle; 836 handle = handle->next; 837 } 838 myri10ge_free_tx_handles(tx, &list); 839 } 840 841 static int 842 myri10ge_alloc_tx_handles(struct myri10ge_slice_state *ss, int count, 843 struct myri10ge_tx_dma_handle **ret) 844 { 845 myri10ge_tx_ring_t *tx = &ss->tx; 846 struct myri10ge_tx_dma_handle *handle; 847 int err, i; 848 849 mutex_enter(&tx->handle_lock); 850 for (i = 0; i < count; i++) { 851 handle = tx->free_tx_handles; 852 while (handle == NULL) { 853 mutex_exit(&tx->handle_lock); 854 err = myri10ge_add_tx_handle(ss); 855 if (err != DDI_SUCCESS) { 856 goto abort_with_handles; 857 } 858 mutex_enter(&tx->handle_lock); 859 handle = tx->free_tx_handles; 860 } 861 tx->free_tx_handles = handle->next; 862 handle->next = *ret; 863 *ret = handle; 864 } 865 mutex_exit(&tx->handle_lock); 866 return (DDI_SUCCESS); 867 868 abort_with_handles: 869 myri10ge_free_tx_handle_slist(tx, *ret); 870 return (err); 871 } 872 873 874 /* 875 * Frees DMA resources associated with the send ring 876 */ 877 static void 878 myri10ge_unprepare_tx_ring(struct myri10ge_slice_state *ss) 879 { 880 myri10ge_tx_ring_t *tx; 881 struct myri10ge_tx_dma_handle_head handles; 882 size_t bytes; 883 int idx; 884 885 tx = &ss->tx; 886 handles.head = NULL; 887 handles.tail = NULL; 888 for (idx = 0; idx < ss->tx.mask + 1; idx++) { 889 if (tx->info[idx].m) { 890 (void) ddi_dma_unbind_handle(tx->info[idx].handle->h); 891 handles.head = tx->info[idx].handle; 892 if (handles.tail == NULL) 893 handles.tail = tx->info[idx].handle; 894 freeb(tx->info[idx].m); 895 tx->info[idx].m = 0; 896 tx->info[idx].handle = 0; 897 } 898 tx->cp[idx].va = NULL; 899 myri10ge_dma_free(&tx->cp[idx].dma); 900 } 901 bytes = sizeof (*tx->cp) * (tx->mask + 1); 902 kmem_free(tx->cp, bytes); 903 tx->cp = NULL; 904 if (handles.head != NULL) 905 myri10ge_free_tx_handles(tx, &handles); 906 myri10ge_remove_tx_handles(ss); 907 } 908 909 /* 910 * Allocates DMA handles associated with the send ring 911 */ 912 static inline int 913 myri10ge_prepare_tx_ring(struct myri10ge_slice_state *ss) 914 { 915 struct myri10ge_tx_dma_handle *handles; 916 int h; 917 size_t bytes; 918 919 bytes = sizeof (*ss->tx.cp) * (ss->tx.mask + 1); 920 ss->tx.cp = kmem_zalloc(bytes, KM_SLEEP); 921 if (ss->tx.cp == NULL) { 922 cmn_err(CE_WARN, 923 "%s: Failed to allocate tx copyblock storage\n", 924 ss->mgp->name); 925 return (DDI_FAILURE); 926 } 927 928 929 /* allocate the TX copyblocks */ 930 for (h = 0; h < ss->tx.mask + 1; h++) { 931 ss->tx.cp[h].va = myri10ge_dma_alloc(ss->mgp->dip, 932 4096, &myri10ge_rx_jumbo_dma_attr, 933 &myri10ge_dev_access_attr, DDI_DMA_STREAMING, 934 DDI_DMA_WRITE|DDI_DMA_STREAMING, &ss->tx.cp[h].dma, 1, 935 DDI_DMA_DONTWAIT); 936 if (ss->tx.cp[h].va == NULL) { 937 cmn_err(CE_WARN, "%s: Failed to allocate tx " 938 "copyblock %d\n", ss->mgp->name, h); 939 goto abort_with_copyblocks; 940 } 941 } 942 /* pre-allocate transmit handles */ 943 handles = NULL; 944 (void) myri10ge_alloc_tx_handles(ss, myri10ge_tx_handles_initial, 945 &handles); 946 if (handles != NULL) 947 myri10ge_free_tx_handle_slist(&ss->tx, handles); 948 949 return (DDI_SUCCESS); 950 951 abort_with_copyblocks: 952 while (h > 0) { 953 h--; 954 myri10ge_dma_free(&ss->tx.cp[h].dma); 955 } 956 957 bytes = sizeof (*ss->tx.cp) * (ss->tx.mask + 1); 958 kmem_free(ss->tx.cp, bytes); 959 ss->tx.cp = NULL; 960 return (DDI_FAILURE); 961 } 962 963 /* 964 * The eeprom strings on the lanaiX have the format 965 * SN=x\0 966 * MAC=x:x:x:x:x:x\0 967 * PT:ddd mmm xx xx:xx:xx xx\0 968 * PV:ddd mmm xx xx:xx:xx xx\0 969 */ 970 static int 971 myri10ge_read_mac_addr(struct myri10ge_priv *mgp) 972 { 973 #define MYRI10GE_NEXT_STRING(p) while (ptr < limit && *ptr++) 974 #define myri10ge_digit(c) (((c) >= '0' && (c) <= '9') ? ((c) - '0') : \ 975 (((c) >= 'A' && (c) <= 'F') ? (10 + (c) - 'A') : \ 976 (((c) >= 'a' && (c) <= 'f') ? (10 + (c) - 'a') : -1))) 977 978 char *ptr, *limit; 979 int i, hv, lv; 980 981 ptr = mgp->eeprom_strings; 982 limit = mgp->eeprom_strings + MYRI10GE_EEPROM_STRINGS_SIZE; 983 984 while (*ptr != '\0' && ptr < limit) { 985 if (memcmp(ptr, "MAC=", 4) == 0) { 986 ptr += 4; 987 if (myri10ge_verbose) 988 printf("%s: mac address = %s\n", mgp->name, 989 ptr); 990 mgp->mac_addr_string = ptr; 991 for (i = 0; i < 6; i++) { 992 if ((ptr + 2) > limit) 993 goto abort; 994 995 if (*(ptr+1) == ':') { 996 hv = 0; 997 lv = myri10ge_digit(*ptr); ptr++; 998 } else { 999 hv = myri10ge_digit(*ptr); ptr++; 1000 lv = myri10ge_digit(*ptr); ptr++; 1001 } 1002 mgp->mac_addr[i] = (hv << 4) | lv; 1003 ptr++; 1004 } 1005 } 1006 if (memcmp((const void *)ptr, "SN=", 3) == 0) { 1007 ptr += 3; 1008 mgp->sn_str = (char *)ptr; 1009 } 1010 if (memcmp((const void *)ptr, "PC=", 3) == 0) { 1011 ptr += 3; 1012 mgp->pc_str = (char *)ptr; 1013 } 1014 MYRI10GE_NEXT_STRING(ptr); 1015 } 1016 1017 return (0); 1018 1019 abort: 1020 cmn_err(CE_WARN, "%s: failed to parse eeprom_strings", mgp->name); 1021 return (ENXIO); 1022 } 1023 1024 1025 /* 1026 * Determine the register set containing the PCI resource we 1027 * want to map: the memory-mappable part of the interface. We do 1028 * this by scanning the DDI "reg" property of the interface, 1029 * which is an array of mx_ddi_reg_set structures. 1030 */ 1031 static int 1032 myri10ge_reg_set(dev_info_t *dip, int *reg_set, int *span, 1033 unsigned long *busno, unsigned long *devno, 1034 unsigned long *funcno) 1035 { 1036 1037 #define REGISTER_NUMBER(ip) (ip[0] >> 0 & 0xff) 1038 #define FUNCTION_NUMBER(ip) (ip[0] >> 8 & 0x07) 1039 #define DEVICE_NUMBER(ip) (ip[0] >> 11 & 0x1f) 1040 #define BUS_NUMBER(ip) (ip[0] >> 16 & 0xff) 1041 #define ADDRESS_SPACE(ip) (ip[0] >> 24 & 0x03) 1042 #define PCI_ADDR_HIGH(ip) (ip[1]) 1043 #define PCI_ADDR_LOW(ip) (ip[2]) 1044 #define PCI_SPAN_HIGH(ip) (ip[3]) 1045 #define PCI_SPAN_LOW(ip) (ip[4]) 1046 1047 #define MX_DDI_REG_SET_32_BIT_MEMORY_SPACE 2 1048 #define MX_DDI_REG_SET_64_BIT_MEMORY_SPACE 3 1049 1050 int *data, i, *rs; 1051 uint32_t nelementsp; 1052 1053 #ifdef MYRI10GE_REGSET_VERBOSE 1054 char *address_space_name[] = { "Configuration Space", 1055 "I/O Space", 1056 "32-bit Memory Space", 1057 "64-bit Memory Space" 1058 }; 1059 #endif 1060 1061 if (ddi_prop_lookup_int_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, 1062 "reg", &data, &nelementsp) != DDI_SUCCESS) { 1063 printf("Could not determine register set.\n"); 1064 return (ENXIO); 1065 } 1066 1067 #ifdef MYRI10GE_REGSET_VERBOSE 1068 printf("There are %d register sets.\n", nelementsp / 5); 1069 #endif 1070 if (!nelementsp) { 1071 printf("Didn't find any \"reg\" properties.\n"); 1072 ddi_prop_free(data); 1073 return (ENODEV); 1074 } 1075 1076 /* Scan for the register number. */ 1077 rs = &data[0]; 1078 *busno = BUS_NUMBER(rs); 1079 *devno = DEVICE_NUMBER(rs); 1080 *funcno = FUNCTION_NUMBER(rs); 1081 1082 #ifdef MYRI10GE_REGSET_VERBOSE 1083 printf("*** Scanning for register number.\n"); 1084 #endif 1085 for (i = 0; i < nelementsp / 5; i++) { 1086 rs = &data[5 * i]; 1087 #ifdef MYRI10GE_REGSET_VERBOSE 1088 printf("Examining register set %d:\n", i); 1089 printf(" Register number = %d.\n", REGISTER_NUMBER(rs)); 1090 printf(" Function number = %d.\n", FUNCTION_NUMBER(rs)); 1091 printf(" Device number = %d.\n", DEVICE_NUMBER(rs)); 1092 printf(" Bus number = %d.\n", BUS_NUMBER(rs)); 1093 printf(" Address space = %d (%s ).\n", ADDRESS_SPACE(rs), 1094 address_space_name[ADDRESS_SPACE(rs)]); 1095 printf(" pci address 0x%08x %08x\n", PCI_ADDR_HIGH(rs), 1096 PCI_ADDR_LOW(rs)); 1097 printf(" pci span 0x%08x %08x\n", PCI_SPAN_HIGH(rs), 1098 PCI_SPAN_LOW(rs)); 1099 #endif 1100 /* We are looking for a memory property. */ 1101 1102 if (ADDRESS_SPACE(rs) == MX_DDI_REG_SET_64_BIT_MEMORY_SPACE || 1103 ADDRESS_SPACE(rs) == MX_DDI_REG_SET_32_BIT_MEMORY_SPACE) { 1104 *reg_set = i; 1105 1106 #ifdef MYRI10GE_REGSET_VERBOSE 1107 printf("%s uses register set %d.\n", 1108 address_space_name[ADDRESS_SPACE(rs)], *reg_set); 1109 #endif 1110 1111 *span = (PCI_SPAN_LOW(rs)); 1112 #ifdef MYRI10GE_REGSET_VERBOSE 1113 printf("Board span is 0x%x\n", *span); 1114 #endif 1115 break; 1116 } 1117 } 1118 1119 ddi_prop_free(data); 1120 1121 /* If no match, fail. */ 1122 if (i >= nelementsp / 5) { 1123 return (EIO); 1124 } 1125 1126 return (0); 1127 } 1128 1129 1130 static int 1131 myri10ge_load_firmware_from_zlib(struct myri10ge_priv *mgp, uint32_t *limit) 1132 { 1133 void *inflate_buffer; 1134 int rv, status; 1135 size_t sram_size = mgp->sram_size - MYRI10GE_EEPROM_STRINGS_SIZE; 1136 size_t destlen; 1137 mcp_gen_header_t *hdr; 1138 unsigned hdr_offset, i; 1139 1140 1141 *limit = 0; /* -Wuninitialized */ 1142 status = 0; 1143 1144 inflate_buffer = kmem_zalloc(sram_size, KM_NOSLEEP); 1145 if (!inflate_buffer) { 1146 cmn_err(CE_WARN, 1147 "%s: Could not allocate buffer to inflate mcp\n", 1148 mgp->name); 1149 return (ENOMEM); 1150 } 1151 1152 destlen = sram_size; 1153 rv = z_uncompress(inflate_buffer, &destlen, mgp->eth_z8e, 1154 mgp->eth_z8e_length); 1155 1156 if (rv != Z_OK) { 1157 cmn_err(CE_WARN, "%s: Could not inflate mcp: %s\n", 1158 mgp->name, z_strerror(rv)); 1159 status = ENXIO; 1160 goto abort; 1161 } 1162 1163 *limit = (uint32_t)destlen; 1164 1165 hdr_offset = htonl(*(uint32_t *)(void *)((char *)inflate_buffer + 1166 MCP_HEADER_PTR_OFFSET)); 1167 hdr = (void *)((char *)inflate_buffer + hdr_offset); 1168 if (ntohl(hdr->mcp_type) != MCP_TYPE_ETH) { 1169 cmn_err(CE_WARN, "%s: Bad firmware type: 0x%x\n", mgp->name, 1170 ntohl(hdr->mcp_type)); 1171 status = EIO; 1172 goto abort; 1173 } 1174 1175 /* save firmware version for kstat */ 1176 (void) strncpy(mgp->fw_version, hdr->version, sizeof (mgp->fw_version)); 1177 if (myri10ge_verbose) 1178 printf("%s: firmware id: %s\n", mgp->name, hdr->version); 1179 1180 /* Copy the inflated firmware to NIC SRAM. */ 1181 for (i = 0; i < *limit; i += 256) { 1182 myri10ge_pio_copy((char *)mgp->sram + MYRI10GE_FW_OFFSET + i, 1183 (char *)inflate_buffer + i, 1184 min(256U, (unsigned)(*limit - i))); 1185 mb(); 1186 (void) *(int *)(void *)mgp->sram; 1187 mb(); 1188 } 1189 1190 abort: 1191 kmem_free(inflate_buffer, sram_size); 1192 1193 return (status); 1194 1195 } 1196 1197 1198 int 1199 myri10ge_send_cmd(struct myri10ge_priv *mgp, uint32_t cmd, 1200 myri10ge_cmd_t *data) 1201 { 1202 mcp_cmd_t *buf; 1203 char buf_bytes[sizeof (*buf) + 8]; 1204 volatile mcp_cmd_response_t *response = mgp->cmd; 1205 volatile char *cmd_addr = 1206 (volatile char *)mgp->sram + MXGEFW_ETH_CMD; 1207 int sleep_total = 0; 1208 1209 /* ensure buf is aligned to 8 bytes */ 1210 buf = (mcp_cmd_t *)((unsigned long)(buf_bytes + 7) & ~7UL); 1211 1212 buf->data0 = htonl(data->data0); 1213 buf->data1 = htonl(data->data1); 1214 buf->data2 = htonl(data->data2); 1215 buf->cmd = htonl(cmd); 1216 buf->response_addr.low = mgp->cmd_dma.low; 1217 buf->response_addr.high = mgp->cmd_dma.high; 1218 mutex_enter(&mgp->cmd_lock); 1219 response->result = 0xffffffff; 1220 mb(); 1221 1222 myri10ge_pio_copy((void *)cmd_addr, buf, sizeof (*buf)); 1223 1224 /* wait up to 20ms */ 1225 for (sleep_total = 0; sleep_total < 20; sleep_total++) { 1226 mb(); 1227 if (response->result != 0xffffffff) { 1228 if (response->result == 0) { 1229 data->data0 = ntohl(response->data); 1230 mutex_exit(&mgp->cmd_lock); 1231 return (0); 1232 } else if (ntohl(response->result) 1233 == MXGEFW_CMD_UNKNOWN) { 1234 mutex_exit(&mgp->cmd_lock); 1235 return (ENOSYS); 1236 } else if (ntohl(response->result) 1237 == MXGEFW_CMD_ERROR_UNALIGNED) { 1238 mutex_exit(&mgp->cmd_lock); 1239 return (E2BIG); 1240 } else { 1241 cmn_err(CE_WARN, 1242 "%s: command %d failed, result = %d\n", 1243 mgp->name, cmd, ntohl(response->result)); 1244 mutex_exit(&mgp->cmd_lock); 1245 return (ENXIO); 1246 } 1247 } 1248 drv_usecwait(1000); 1249 } 1250 mutex_exit(&mgp->cmd_lock); 1251 cmn_err(CE_WARN, "%s: command %d timed out, result = %d\n", 1252 mgp->name, cmd, ntohl(response->result)); 1253 return (EAGAIN); 1254 } 1255 1256 /* 1257 * Enable or disable periodic RDMAs from the host to make certain 1258 * chipsets resend dropped PCIe messages 1259 */ 1260 1261 static void 1262 myri10ge_dummy_rdma(struct myri10ge_priv *mgp, int enable) 1263 { 1264 char buf_bytes[72]; 1265 volatile uint32_t *confirm; 1266 volatile char *submit; 1267 uint32_t *buf; 1268 int i; 1269 1270 buf = (uint32_t *)((unsigned long)(buf_bytes + 7) & ~7UL); 1271 1272 /* clear confirmation addr */ 1273 confirm = (volatile uint32_t *)mgp->cmd; 1274 *confirm = 0; 1275 mb(); 1276 1277 /* 1278 * send an rdma command to the PCIe engine, and wait for the 1279 * response in the confirmation address. The firmware should 1280 * write a -1 there to indicate it is alive and well 1281 */ 1282 1283 buf[0] = mgp->cmd_dma.high; /* confirm addr MSW */ 1284 buf[1] = mgp->cmd_dma.low; /* confirm addr LSW */ 1285 buf[2] = htonl(0xffffffff); /* confirm data */ 1286 buf[3] = htonl(mgp->cmd_dma.high); /* dummy addr MSW */ 1287 buf[4] = htonl(mgp->cmd_dma.low); /* dummy addr LSW */ 1288 buf[5] = htonl(enable); /* enable? */ 1289 1290 1291 submit = (volatile char *)(mgp->sram + MXGEFW_BOOT_DUMMY_RDMA); 1292 1293 myri10ge_pio_copy((char *)submit, buf, 64); 1294 mb(); 1295 drv_usecwait(1000); 1296 mb(); 1297 i = 0; 1298 while (*confirm != 0xffffffff && i < 20) { 1299 drv_usecwait(1000); 1300 i++; 1301 } 1302 if (*confirm != 0xffffffff) { 1303 cmn_err(CE_WARN, "%s: dummy rdma %s failed (%p = 0x%x)", 1304 mgp->name, 1305 (enable ? "enable" : "disable"), (void*) confirm, *confirm); 1306 } 1307 } 1308 1309 static int 1310 myri10ge_load_firmware(struct myri10ge_priv *mgp) 1311 { 1312 myri10ge_cmd_t cmd; 1313 volatile uint32_t *confirm; 1314 volatile char *submit; 1315 char buf_bytes[72]; 1316 uint32_t *buf, size; 1317 int status, i; 1318 1319 buf = (uint32_t *)((unsigned long)(buf_bytes + 7) & ~7UL); 1320 1321 status = myri10ge_load_firmware_from_zlib(mgp, &size); 1322 if (status) { 1323 cmn_err(CE_WARN, "%s: firmware loading failed\n", mgp->name); 1324 return (status); 1325 } 1326 1327 /* clear confirmation addr */ 1328 confirm = (volatile uint32_t *)mgp->cmd; 1329 *confirm = 0; 1330 mb(); 1331 1332 /* 1333 * send a reload command to the bootstrap MCP, and wait for the 1334 * response in the confirmation address. The firmware should 1335 * write a -1 there to indicate it is alive and well 1336 */ 1337 1338 buf[0] = mgp->cmd_dma.high; /* confirm addr MSW */ 1339 buf[1] = mgp->cmd_dma.low; /* confirm addr LSW */ 1340 buf[2] = htonl(0xffffffff); /* confirm data */ 1341 1342 /* 1343 * FIX: All newest firmware should un-protect the bottom of 1344 * the sram before handoff. However, the very first interfaces 1345 * do not. Therefore the handoff copy must skip the first 8 bytes 1346 */ 1347 buf[3] = htonl(MYRI10GE_FW_OFFSET + 8); /* where the code starts */ 1348 buf[4] = htonl(size - 8); /* length of code */ 1349 buf[5] = htonl(8); /* where to copy to */ 1350 buf[6] = htonl(0); /* where to jump to */ 1351 1352 submit = (volatile char *)(mgp->sram + MXGEFW_BOOT_HANDOFF); 1353 1354 myri10ge_pio_copy((char *)submit, buf, 64); 1355 mb(); 1356 drv_usecwait(1000); 1357 mb(); 1358 i = 0; 1359 while (*confirm != 0xffffffff && i < 1000) { 1360 drv_usecwait(1000); 1361 i++; 1362 } 1363 if (*confirm != 0xffffffff) { 1364 cmn_err(CE_WARN, "%s: handoff failed (%p = 0x%x)", 1365 mgp->name, (void *) confirm, *confirm); 1366 1367 return (ENXIO); 1368 } 1369 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RX_RING_SIZE, &cmd); 1370 if (status != 0) { 1371 cmn_err(CE_WARN, "%s: failed MXGEFW_CMD_GET_RX_RING_SIZE\n", 1372 mgp->name); 1373 return (ENXIO); 1374 } 1375 1376 mgp->max_intr_slots = 2 * (cmd.data0 / sizeof (mcp_dma_addr_t)); 1377 myri10ge_dummy_rdma(mgp, 1); 1378 return (0); 1379 } 1380 1381 static int 1382 myri10ge_m_unicst(void *arg, const uint8_t *addr) 1383 { 1384 struct myri10ge_priv *mgp = arg; 1385 myri10ge_cmd_t cmd; 1386 int status; 1387 1388 cmd.data0 = ((addr[0] << 24) | (addr[1] << 16) 1389 | (addr[2] << 8) | addr[3]); 1390 1391 cmd.data1 = ((addr[4] << 8) | (addr[5])); 1392 1393 status = myri10ge_send_cmd(mgp, MXGEFW_SET_MAC_ADDRESS, &cmd); 1394 if (status == 0 && (addr != mgp->mac_addr)) 1395 (void) memcpy(mgp->mac_addr, addr, sizeof (mgp->mac_addr)); 1396 1397 return (status); 1398 } 1399 1400 static int 1401 myri10ge_change_pause(struct myri10ge_priv *mgp, int pause) 1402 { 1403 myri10ge_cmd_t cmd; 1404 int status; 1405 1406 if (pause) 1407 status = myri10ge_send_cmd(mgp, MXGEFW_ENABLE_FLOW_CONTROL, 1408 &cmd); 1409 else 1410 status = myri10ge_send_cmd(mgp, MXGEFW_DISABLE_FLOW_CONTROL, 1411 &cmd); 1412 1413 if (status) { 1414 cmn_err(CE_WARN, "%s: Failed to set flow control mode\n", 1415 mgp->name); 1416 return (ENXIO); 1417 } 1418 mgp->pause = pause; 1419 return (0); 1420 } 1421 1422 static void 1423 myri10ge_change_promisc(struct myri10ge_priv *mgp, int promisc) 1424 { 1425 myri10ge_cmd_t cmd; 1426 int status; 1427 1428 if (promisc) 1429 status = myri10ge_send_cmd(mgp, MXGEFW_ENABLE_PROMISC, &cmd); 1430 else 1431 status = myri10ge_send_cmd(mgp, MXGEFW_DISABLE_PROMISC, &cmd); 1432 1433 if (status) { 1434 cmn_err(CE_WARN, "%s: Failed to set promisc mode\n", 1435 mgp->name); 1436 } 1437 } 1438 1439 static int 1440 myri10ge_dma_test(struct myri10ge_priv *mgp, int test_type) 1441 { 1442 myri10ge_cmd_t cmd; 1443 int status; 1444 uint32_t len; 1445 void *dmabench; 1446 struct myri10ge_dma_stuff dmabench_dma; 1447 char *test = " "; 1448 1449 /* 1450 * Run a small DMA test. 1451 * The magic multipliers to the length tell the firmware 1452 * tp do DMA read, write, or read+write tests. The 1453 * results are returned in cmd.data0. The upper 16 1454 * bits or the return is the number of transfers completed. 1455 * The lower 16 bits is the time in 0.5us ticks that the 1456 * transfers took to complete 1457 */ 1458 1459 len = mgp->tx_boundary; 1460 1461 dmabench = myri10ge_dma_alloc(mgp->dip, len, 1462 &myri10ge_rx_jumbo_dma_attr, &myri10ge_dev_access_attr, 1463 DDI_DMA_STREAMING, DDI_DMA_RDWR|DDI_DMA_STREAMING, 1464 &dmabench_dma, 1, DDI_DMA_DONTWAIT); 1465 mgp->read_dma = mgp->write_dma = mgp->read_write_dma = 0; 1466 if (dmabench == NULL) { 1467 cmn_err(CE_WARN, "%s dma benchmark aborted\n", mgp->name); 1468 return (ENOMEM); 1469 } 1470 1471 cmd.data0 = ntohl(dmabench_dma.low); 1472 cmd.data1 = ntohl(dmabench_dma.high); 1473 cmd.data2 = len * 0x10000; 1474 status = myri10ge_send_cmd(mgp, test_type, &cmd); 1475 if (status != 0) { 1476 test = "read"; 1477 goto abort; 1478 } 1479 mgp->read_dma = ((cmd.data0>>16) * len * 2) / (cmd.data0 & 0xffff); 1480 1481 cmd.data0 = ntohl(dmabench_dma.low); 1482 cmd.data1 = ntohl(dmabench_dma.high); 1483 cmd.data2 = len * 0x1; 1484 status = myri10ge_send_cmd(mgp, test_type, &cmd); 1485 if (status != 0) { 1486 test = "write"; 1487 goto abort; 1488 } 1489 mgp->write_dma = ((cmd.data0>>16) * len * 2) / (cmd.data0 & 0xffff); 1490 1491 cmd.data0 = ntohl(dmabench_dma.low); 1492 cmd.data1 = ntohl(dmabench_dma.high); 1493 cmd.data2 = len * 0x10001; 1494 status = myri10ge_send_cmd(mgp, test_type, &cmd); 1495 if (status != 0) { 1496 test = "read/write"; 1497 goto abort; 1498 } 1499 mgp->read_write_dma = ((cmd.data0>>16) * len * 2 * 2) / 1500 (cmd.data0 & 0xffff); 1501 1502 1503 abort: 1504 myri10ge_dma_free(&dmabench_dma); 1505 if (status != 0 && test_type != MXGEFW_CMD_UNALIGNED_TEST) 1506 cmn_err(CE_WARN, "%s %s dma benchmark failed\n", mgp->name, 1507 test); 1508 return (status); 1509 } 1510 1511 static int 1512 myri10ge_reset(struct myri10ge_priv *mgp) 1513 { 1514 myri10ge_cmd_t cmd; 1515 struct myri10ge_nic_stat *ethstat; 1516 struct myri10ge_slice_state *ss; 1517 int i, status; 1518 size_t bytes; 1519 1520 /* send a reset command to the card to see if it is alive */ 1521 (void) memset(&cmd, 0, sizeof (cmd)); 1522 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_RESET, &cmd); 1523 if (status != 0) { 1524 cmn_err(CE_WARN, "%s: failed reset\n", mgp->name); 1525 return (ENXIO); 1526 } 1527 1528 /* Now exchange information about interrupts */ 1529 1530 bytes = mgp->max_intr_slots * sizeof (*mgp->ss[0].rx_done.entry); 1531 cmd.data0 = (uint32_t)bytes; 1532 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_SIZE, &cmd); 1533 1534 /* 1535 * Even though we already know how many slices are supported 1536 * via myri10ge_probe_slices() MXGEFW_CMD_GET_MAX_RSS_QUEUES 1537 * has magic side effects, and must be called after a reset. 1538 * It must be called prior to calling any RSS related cmds, 1539 * including assigning an interrupt queue for anything but 1540 * slice 0. It must also be called *after* 1541 * MXGEFW_CMD_SET_INTRQ_SIZE, since the intrq size is used by 1542 * the firmware to compute offsets. 1543 */ 1544 1545 if (mgp->num_slices > 1) { 1546 1547 /* ask the maximum number of slices it supports */ 1548 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_MAX_RSS_QUEUES, 1549 &cmd); 1550 if (status != 0) { 1551 cmn_err(CE_WARN, 1552 "%s: failed to get number of slices\n", 1553 mgp->name); 1554 return (status); 1555 } 1556 1557 /* 1558 * MXGEFW_CMD_ENABLE_RSS_QUEUES must be called prior 1559 * to setting up the interrupt queue DMA 1560 */ 1561 1562 cmd.data0 = mgp->num_slices; 1563 cmd.data1 = MXGEFW_SLICE_INTR_MODE_ONE_PER_SLICE | 1564 MXGEFW_SLICE_ENABLE_MULTIPLE_TX_QUEUES; 1565 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ENABLE_RSS_QUEUES, 1566 &cmd); 1567 if (status != 0) { 1568 cmn_err(CE_WARN, 1569 "%s: failed to set number of slices\n", 1570 mgp->name); 1571 return (status); 1572 } 1573 } 1574 for (i = 0; i < mgp->num_slices; i++) { 1575 ss = &mgp->ss[i]; 1576 cmd.data0 = ntohl(ss->rx_done.dma.low); 1577 cmd.data1 = ntohl(ss->rx_done.dma.high); 1578 cmd.data2 = i; 1579 status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_DMA, 1580 &cmd); 1581 }; 1582 1583 status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_IRQ_ACK_OFFSET, &cmd); 1584 for (i = 0; i < mgp->num_slices; i++) { 1585 ss = &mgp->ss[i]; 1586 ss->irq_claim = (volatile unsigned int *) 1587 (void *)(mgp->sram + cmd.data0 + 8 * i); 1588 } 1589 1590 if (mgp->ddi_intr_type == DDI_INTR_TYPE_FIXED) { 1591 status |= myri10ge_send_cmd(mgp, 1592 MXGEFW_CMD_GET_IRQ_DEASSERT_OFFSET, &cmd); 1593 mgp->irq_deassert = (uint32_t *)(void *)(mgp->sram + cmd.data0); 1594 } 1595 1596 status |= myri10ge_send_cmd(mgp, 1597 MXGEFW_CMD_GET_INTR_COAL_DELAY_OFFSET, &cmd); 1598 mgp->intr_coal_delay_ptr = (uint32_t *)(void *)(mgp->sram + cmd.data0); 1599 1600 if (status != 0) { 1601 cmn_err(CE_WARN, "%s: failed set interrupt parameters\n", 1602 mgp->name); 1603 return (status); 1604 } 1605 1606 *mgp->intr_coal_delay_ptr = htonl(mgp->intr_coal_delay); 1607 (void) myri10ge_dma_test(mgp, MXGEFW_DMA_TEST); 1608 1609 /* reset mcp/driver shared state back to 0 */ 1610 1611 for (i = 0; i < mgp->num_slices; i++) { 1612 ss = &mgp->ss[i]; 1613 bytes = mgp->max_intr_slots * 1614 sizeof (*mgp->ss[0].rx_done.entry); 1615 (void) memset(ss->rx_done.entry, 0, bytes); 1616 ss->tx.req = 0; 1617 ss->tx.done = 0; 1618 ss->tx.pkt_done = 0; 1619 ss->rx_big.cnt = 0; 1620 ss->rx_small.cnt = 0; 1621 ss->rx_done.idx = 0; 1622 ss->rx_done.cnt = 0; 1623 ss->rx_token = 0; 1624 ss->tx.watchdog_done = 0; 1625 ss->tx.watchdog_req = 0; 1626 ss->tx.active = 0; 1627 ss->tx.activate = 0; 1628 } 1629 mgp->watchdog_rx_pause = 0; 1630 if (mgp->ksp_stat != NULL) { 1631 ethstat = (struct myri10ge_nic_stat *)mgp->ksp_stat->ks_data; 1632 ethstat->link_changes.value.ul = 0; 1633 } 1634 status = myri10ge_m_unicst(mgp, mgp->mac_addr); 1635 myri10ge_change_promisc(mgp, 0); 1636 (void) myri10ge_change_pause(mgp, mgp->pause); 1637 return (status); 1638 } 1639 1640 static int 1641 myri10ge_init_toeplitz(struct myri10ge_priv *mgp) 1642 { 1643 myri10ge_cmd_t cmd; 1644 int i, b, s, t, j; 1645 int status; 1646 uint32_t k[8]; 1647 uint32_t tmp; 1648 uint8_t *key; 1649 1650 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RSS_KEY_OFFSET, 1651 &cmd); 1652 if (status != 0) { 1653 cmn_err(CE_WARN, "%s: failed to get rss key\n", 1654 mgp->name); 1655 return (EIO); 1656 } 1657 myri10ge_pio_copy32(mgp->rss_key, 1658 (uint32_t *)(void*)((char *)mgp->sram + cmd.data0), 1659 sizeof (mgp->rss_key)); 1660 1661 mgp->toeplitz_hash_table = kmem_alloc(sizeof (uint32_t) * 12 * 256, 1662 KM_SLEEP); 1663 key = (uint8_t *)mgp->rss_key; 1664 t = 0; 1665 for (b = 0; b < 12; b++) { 1666 for (s = 0; s < 8; s++) { 1667 /* Bits: b*8+s, ..., b*8+s+31 */ 1668 k[s] = 0; 1669 for (j = 0; j < 32; j++) { 1670 int bit = b*8+s+j; 1671 bit = 0x1 & (key[bit / 8] >> (7 -(bit & 0x7))); 1672 k[s] |= bit << (31 - j); 1673 } 1674 } 1675 1676 for (i = 0; i <= 0xff; i++) { 1677 tmp = 0; 1678 if (i & (1 << 7)) { tmp ^= k[0]; } 1679 if (i & (1 << 6)) { tmp ^= k[1]; } 1680 if (i & (1 << 5)) { tmp ^= k[2]; } 1681 if (i & (1 << 4)) { tmp ^= k[3]; } 1682 if (i & (1 << 3)) { tmp ^= k[4]; } 1683 if (i & (1 << 2)) { tmp ^= k[5]; } 1684 if (i & (1 << 1)) { tmp ^= k[6]; } 1685 if (i & (1 << 0)) { tmp ^= k[7]; } 1686 mgp->toeplitz_hash_table[t++] = tmp; 1687 } 1688 } 1689 return (0); 1690 } 1691 1692 static inline struct myri10ge_slice_state * 1693 myri10ge_toeplitz_send_hash(struct myri10ge_priv *mgp, struct ip *ip) 1694 { 1695 struct tcphdr *hdr; 1696 uint32_t saddr, daddr; 1697 uint32_t hash, slice; 1698 uint32_t *table = mgp->toeplitz_hash_table; 1699 uint16_t src, dst; 1700 1701 /* 1702 * Note hashing order is reversed from how it is done 1703 * in the NIC, so as to generate the same hash value 1704 * for the connection to try to keep connections CPU local 1705 */ 1706 1707 /* hash on IPv4 src/dst address */ 1708 saddr = ntohl(ip->ip_src.s_addr); 1709 daddr = ntohl(ip->ip_dst.s_addr); 1710 hash = table[(256 * 0) + ((daddr >> 24) & 0xff)]; 1711 hash ^= table[(256 * 1) + ((daddr >> 16) & 0xff)]; 1712 hash ^= table[(256 * 2) + ((daddr >> 8) & 0xff)]; 1713 hash ^= table[(256 * 3) + ((daddr) & 0xff)]; 1714 hash ^= table[(256 * 4) + ((saddr >> 24) & 0xff)]; 1715 hash ^= table[(256 * 5) + ((saddr >> 16) & 0xff)]; 1716 hash ^= table[(256 * 6) + ((saddr >> 8) & 0xff)]; 1717 hash ^= table[(256 * 7) + ((saddr) & 0xff)]; 1718 /* hash on TCP port, if required */ 1719 if ((myri10ge_rss_hash & MXGEFW_RSS_HASH_TYPE_TCP_IPV4) && 1720 ip->ip_p == IPPROTO_TCP) { 1721 hdr = (struct tcphdr *)(void *) 1722 (((uint8_t *)ip) + (ip->ip_hl << 2)); 1723 src = ntohs(hdr->th_sport); 1724 dst = ntohs(hdr->th_dport); 1725 1726 hash ^= table[(256 * 8) + ((dst >> 8) & 0xff)]; 1727 hash ^= table[(256 * 9) + ((dst) & 0xff)]; 1728 hash ^= table[(256 * 10) + ((src >> 8) & 0xff)]; 1729 hash ^= table[(256 * 11) + ((src) & 0xff)]; 1730 } 1731 slice = (mgp->num_slices - 1) & hash; 1732 return (&mgp->ss[slice]); 1733 1734 } 1735 1736 static inline struct myri10ge_slice_state * 1737 myri10ge_simple_send_hash(struct myri10ge_priv *mgp, struct ip *ip) 1738 { 1739 struct tcphdr *hdr; 1740 uint32_t slice, hash_val; 1741 1742 1743 if (ip->ip_p != IPPROTO_TCP && ip->ip_p != IPPROTO_UDP) { 1744 return (&mgp->ss[0]); 1745 } 1746 hdr = (struct tcphdr *)(void *)(((uint8_t *)ip) + (ip->ip_hl << 2)); 1747 1748 /* 1749 * Use the second byte of the *destination* address for 1750 * MXGEFW_RSS_HASH_TYPE_SRC_PORT, so as to match NIC's hashing 1751 */ 1752 hash_val = ntohs(hdr->th_dport) & 0xff; 1753 if (myri10ge_rss_hash == MXGEFW_RSS_HASH_TYPE_SRC_DST_PORT) 1754 hash_val += ntohs(hdr->th_sport) & 0xff; 1755 1756 slice = (mgp->num_slices - 1) & hash_val; 1757 return (&mgp->ss[slice]); 1758 } 1759 1760 static inline struct myri10ge_slice_state * 1761 myri10ge_send_hash(struct myri10ge_priv *mgp, mblk_t *mp) 1762 { 1763 unsigned int slice = 0; 1764 struct ether_header *eh; 1765 struct ether_vlan_header *vh; 1766 struct ip *ip; 1767 int ehl, ihl; 1768 1769 if (mgp->num_slices == 1) 1770 return (&mgp->ss[0]); 1771 1772 if (myri10ge_tx_hash == 0) { 1773 slice = CPU->cpu_id & (mgp->num_slices - 1); 1774 return (&mgp->ss[slice]); 1775 } 1776 1777 /* 1778 * ensure it is a TCP or UDP over IPv4 packet, and that the 1779 * headers are in the 1st mblk. Otherwise, punt 1780 */ 1781 ehl = sizeof (*eh); 1782 ihl = sizeof (*ip); 1783 if ((MBLKL(mp)) < (ehl + ihl + 8)) 1784 return (&mgp->ss[0]); 1785 eh = (struct ether_header *)(void *)mp->b_rptr; 1786 ip = (struct ip *)(void *)(eh + 1); 1787 if (eh->ether_type != BE_16(ETHERTYPE_IP)) { 1788 if (eh->ether_type != BE_16(ETHERTYPE_VLAN)) 1789 return (&mgp->ss[0]); 1790 vh = (struct ether_vlan_header *)(void *)mp->b_rptr; 1791 if (vh->ether_type != BE_16(ETHERTYPE_IP)) 1792 return (&mgp->ss[0]); 1793 ehl += 4; 1794 ip = (struct ip *)(void *)(vh + 1); 1795 } 1796 ihl = ip->ip_hl << 2; 1797 if (MBLKL(mp) < (ehl + ihl + 8)) 1798 return (&mgp->ss[0]); 1799 switch (myri10ge_rss_hash) { 1800 case MXGEFW_RSS_HASH_TYPE_IPV4: 1801 /* fallthru */ 1802 case MXGEFW_RSS_HASH_TYPE_TCP_IPV4: 1803 /* fallthru */ 1804 case (MXGEFW_RSS_HASH_TYPE_IPV4|MXGEFW_RSS_HASH_TYPE_TCP_IPV4): 1805 return (myri10ge_toeplitz_send_hash(mgp, ip)); 1806 case MXGEFW_RSS_HASH_TYPE_SRC_PORT: 1807 /* fallthru */ 1808 case MXGEFW_RSS_HASH_TYPE_SRC_DST_PORT: 1809 return (myri10ge_simple_send_hash(mgp, ip)); 1810 default: 1811 break; 1812 } 1813 return (&mgp->ss[0]); 1814 } 1815 1816 static int 1817 myri10ge_setup_slice(struct myri10ge_slice_state *ss) 1818 { 1819 struct myri10ge_priv *mgp = ss->mgp; 1820 myri10ge_cmd_t cmd; 1821 int tx_ring_size, rx_ring_size; 1822 int tx_ring_entries, rx_ring_entries; 1823 int slice, status; 1824 int allocated, idx; 1825 size_t bytes; 1826 1827 slice = ss - mgp->ss; 1828 cmd.data0 = slice; 1829 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_RING_SIZE, &cmd); 1830 tx_ring_size = cmd.data0; 1831 cmd.data0 = slice; 1832 status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_RX_RING_SIZE, &cmd); 1833 if (status != 0) 1834 return (status); 1835 rx_ring_size = cmd.data0; 1836 1837 tx_ring_entries = tx_ring_size / sizeof (struct mcp_kreq_ether_send); 1838 rx_ring_entries = rx_ring_size / sizeof (struct mcp_dma_addr); 1839 ss->tx.mask = tx_ring_entries - 1; 1840 ss->rx_small.mask = ss->rx_big.mask = rx_ring_entries - 1; 1841 1842 /* get the lanai pointers to the send and receive rings */ 1843 1844 cmd.data0 = slice; 1845 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SEND_OFFSET, &cmd); 1846 ss->tx.lanai = (mcp_kreq_ether_send_t *)(void *)(mgp->sram + cmd.data0); 1847 if (mgp->num_slices > 1) { 1848 ss->tx.go = (char *)mgp->sram + MXGEFW_ETH_SEND_GO + 64 * slice; 1849 ss->tx.stop = (char *)mgp->sram + MXGEFW_ETH_SEND_STOP + 1850 64 * slice; 1851 } else { 1852 ss->tx.go = NULL; 1853 ss->tx.stop = NULL; 1854 } 1855 1856 cmd.data0 = slice; 1857 status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_SMALL_RX_OFFSET, &cmd); 1858 ss->rx_small.lanai = (mcp_kreq_ether_recv_t *) 1859 (void *)(mgp->sram + cmd.data0); 1860 1861 cmd.data0 = slice; 1862 status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_BIG_RX_OFFSET, &cmd); 1863 ss->rx_big.lanai = (mcp_kreq_ether_recv_t *)(void *) 1864 (mgp->sram + cmd.data0); 1865 1866 if (status != 0) { 1867 cmn_err(CE_WARN, 1868 "%s: failed to get ring sizes or locations\n", mgp->name); 1869 return (status); 1870 } 1871 1872 status = ENOMEM; 1873 bytes = rx_ring_entries * sizeof (*ss->rx_small.shadow); 1874 ss->rx_small.shadow = kmem_zalloc(bytes, KM_SLEEP); 1875 if (ss->rx_small.shadow == NULL) 1876 goto abort; 1877 (void) memset(ss->rx_small.shadow, 0, bytes); 1878 1879 bytes = rx_ring_entries * sizeof (*ss->rx_big.shadow); 1880 ss->rx_big.shadow = kmem_zalloc(bytes, KM_SLEEP); 1881 if (ss->rx_big.shadow == NULL) 1882 goto abort_with_rx_small_shadow; 1883 (void) memset(ss->rx_big.shadow, 0, bytes); 1884 1885 /* allocate the host info rings */ 1886 1887 bytes = tx_ring_entries * sizeof (*ss->tx.info); 1888 ss->tx.info = kmem_zalloc(bytes, KM_SLEEP); 1889 if (ss->tx.info == NULL) 1890 goto abort_with_rx_big_shadow; 1891 (void) memset(ss->tx.info, 0, bytes); 1892 1893 bytes = rx_ring_entries * sizeof (*ss->rx_small.info); 1894 ss->rx_small.info = kmem_zalloc(bytes, KM_SLEEP); 1895 if (ss->rx_small.info == NULL) 1896 goto abort_with_tx_info; 1897 (void) memset(ss->rx_small.info, 0, bytes); 1898 1899 bytes = rx_ring_entries * sizeof (*ss->rx_big.info); 1900 ss->rx_big.info = kmem_zalloc(bytes, KM_SLEEP); 1901 if (ss->rx_big.info == NULL) 1902 goto abort_with_rx_small_info; 1903 (void) memset(ss->rx_big.info, 0, bytes); 1904 1905 ss->tx.stall = ss->tx.sched = 0; 1906 ss->tx.stall_early = ss->tx.stall_late = 0; 1907 1908 ss->jbufs_for_smalls = 1 + (1 + ss->rx_small.mask) / 1909 (myri10ge_mtu / (myri10ge_small_bytes + MXGEFW_PAD)); 1910 1911 allocated = myri10ge_add_jbufs(ss, 1912 myri10ge_bigbufs_initial + ss->jbufs_for_smalls, 1); 1913 if (allocated < ss->jbufs_for_smalls + myri10ge_bigbufs_initial) { 1914 cmn_err(CE_WARN, 1915 "%s: Could not allocate enough receive buffers (%d/%d)\n", 1916 mgp->name, allocated, 1917 myri10ge_bigbufs_initial + ss->jbufs_for_smalls); 1918 goto abort_with_jumbos; 1919 } 1920 1921 myri10ge_carve_up_jbufs_into_small_ring(ss); 1922 ss->j_rx_cnt = 0; 1923 1924 mutex_enter(&ss->jpool.mtx); 1925 if (allocated < rx_ring_entries) 1926 ss->jpool.low_water = allocated / 4; 1927 else 1928 ss->jpool.low_water = rx_ring_entries / 2; 1929 1930 /* 1931 * invalidate the big receive ring in case we do not 1932 * allocate sufficient jumbos to fill it 1933 */ 1934 (void) memset(ss->rx_big.shadow, 1, 1935 (ss->rx_big.mask + 1) * sizeof (ss->rx_big.shadow[0])); 1936 for (idx = 7; idx <= ss->rx_big.mask; idx += 8) { 1937 myri10ge_submit_8rx(&ss->rx_big.lanai[idx - 7], 1938 &ss->rx_big.shadow[idx - 7]); 1939 mb(); 1940 } 1941 1942 1943 myri10ge_restock_jumbos(ss); 1944 1945 for (idx = 7; idx <= ss->rx_small.mask; idx += 8) { 1946 myri10ge_submit_8rx(&ss->rx_small.lanai[idx - 7], 1947 &ss->rx_small.shadow[idx - 7]); 1948 mb(); 1949 } 1950 ss->rx_small.cnt = ss->rx_small.mask + 1; 1951 1952 mutex_exit(&ss->jpool.mtx); 1953 1954 status = myri10ge_prepare_tx_ring(ss); 1955 1956 if (status != 0) 1957 goto abort_with_small_jbufs; 1958 1959 cmd.data0 = ntohl(ss->fw_stats_dma.low); 1960 cmd.data1 = ntohl(ss->fw_stats_dma.high); 1961 cmd.data2 = sizeof (mcp_irq_data_t); 1962 cmd.data2 |= (slice << 16); 1963 bzero(ss->fw_stats, sizeof (*ss->fw_stats)); 1964 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_STATS_DMA_V2, &cmd); 1965 if (status == ENOSYS) { 1966 cmd.data0 = ntohl(ss->fw_stats_dma.low) + 1967 offsetof(mcp_irq_data_t, send_done_count); 1968 cmd.data1 = ntohl(ss->fw_stats_dma.high); 1969 status = myri10ge_send_cmd(mgp, 1970 MXGEFW_CMD_SET_STATS_DMA_OBSOLETE, &cmd); 1971 } 1972 if (status) { 1973 cmn_err(CE_WARN, "%s: Couldn't set stats DMA\n", mgp->name); 1974 goto abort_with_tx; 1975 } 1976 1977 return (0); 1978 1979 abort_with_tx: 1980 myri10ge_unprepare_tx_ring(ss); 1981 1982 abort_with_small_jbufs: 1983 myri10ge_release_small_jbufs(ss); 1984 1985 abort_with_jumbos: 1986 if (allocated != 0) { 1987 mutex_enter(&ss->jpool.mtx); 1988 ss->jpool.low_water = 0; 1989 mutex_exit(&ss->jpool.mtx); 1990 myri10ge_unstock_jumbos(ss); 1991 myri10ge_remove_jbufs(ss); 1992 } 1993 1994 bytes = rx_ring_entries * sizeof (*ss->rx_big.info); 1995 kmem_free(ss->rx_big.info, bytes); 1996 1997 abort_with_rx_small_info: 1998 bytes = rx_ring_entries * sizeof (*ss->rx_small.info); 1999 kmem_free(ss->rx_small.info, bytes); 2000 2001 abort_with_tx_info: 2002 bytes = tx_ring_entries * sizeof (*ss->tx.info); 2003 kmem_free(ss->tx.info, bytes); 2004 2005 abort_with_rx_big_shadow: 2006 bytes = rx_ring_entries * sizeof (*ss->rx_big.shadow); 2007 kmem_free(ss->rx_big.shadow, bytes); 2008 2009 abort_with_rx_small_shadow: 2010 bytes = rx_ring_entries * sizeof (*ss->rx_small.shadow); 2011 kmem_free(ss->rx_small.shadow, bytes); 2012 abort: 2013 return (status); 2014 2015 } 2016 2017 static void 2018 myri10ge_teardown_slice(struct myri10ge_slice_state *ss) 2019 { 2020 int tx_ring_entries, rx_ring_entries; 2021 size_t bytes; 2022 2023 /* ignore slices that have not been fully setup */ 2024 if (ss->tx.cp == NULL) 2025 return; 2026 /* Free the TX copy buffers */ 2027 myri10ge_unprepare_tx_ring(ss); 2028 2029 /* stop passing returned buffers to firmware */ 2030 2031 mutex_enter(&ss->jpool.mtx); 2032 ss->jpool.low_water = 0; 2033 mutex_exit(&ss->jpool.mtx); 2034 myri10ge_release_small_jbufs(ss); 2035 2036 /* Release the free jumbo frame pool */ 2037 myri10ge_unstock_jumbos(ss); 2038 myri10ge_remove_jbufs(ss); 2039 2040 rx_ring_entries = ss->rx_big.mask + 1; 2041 tx_ring_entries = ss->tx.mask + 1; 2042 2043 bytes = rx_ring_entries * sizeof (*ss->rx_big.info); 2044 kmem_free(ss->rx_big.info, bytes); 2045 2046 bytes = rx_ring_entries * sizeof (*ss->rx_small.info); 2047 kmem_free(ss->rx_small.info, bytes); 2048 2049 bytes = tx_ring_entries * sizeof (*ss->tx.info); 2050 kmem_free(ss->tx.info, bytes); 2051 2052 bytes = rx_ring_entries * sizeof (*ss->rx_big.shadow); 2053 kmem_free(ss->rx_big.shadow, bytes); 2054 2055 bytes = rx_ring_entries * sizeof (*ss->rx_small.shadow); 2056 kmem_free(ss->rx_small.shadow, bytes); 2057 2058 } 2059 static int 2060 myri10ge_start_locked(struct myri10ge_priv *mgp) 2061 { 2062 myri10ge_cmd_t cmd; 2063 int status, big_pow2, i; 2064 volatile uint8_t *itable; 2065 2066 status = DDI_SUCCESS; 2067 /* Allocate DMA resources and receive buffers */ 2068 2069 status = myri10ge_reset(mgp); 2070 if (status != 0) { 2071 cmn_err(CE_WARN, "%s: failed reset\n", mgp->name); 2072 return (DDI_FAILURE); 2073 } 2074 2075 if (mgp->num_slices > 1) { 2076 cmd.data0 = mgp->num_slices; 2077 cmd.data1 = 1; /* use MSI-X */ 2078 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ENABLE_RSS_QUEUES, 2079 &cmd); 2080 if (status != 0) { 2081 cmn_err(CE_WARN, 2082 "%s: failed to set number of slices\n", 2083 mgp->name); 2084 goto abort_with_nothing; 2085 } 2086 /* setup the indirection table */ 2087 cmd.data0 = mgp->num_slices; 2088 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_RSS_TABLE_SIZE, 2089 &cmd); 2090 2091 status |= myri10ge_send_cmd(mgp, 2092 MXGEFW_CMD_GET_RSS_TABLE_OFFSET, &cmd); 2093 if (status != 0) { 2094 cmn_err(CE_WARN, 2095 "%s: failed to setup rss tables\n", mgp->name); 2096 } 2097 2098 /* just enable an identity mapping */ 2099 itable = mgp->sram + cmd.data0; 2100 for (i = 0; i < mgp->num_slices; i++) 2101 itable[i] = (uint8_t)i; 2102 2103 if (myri10ge_rss_hash & MYRI10GE_TOEPLITZ_HASH) { 2104 status = myri10ge_init_toeplitz(mgp); 2105 if (status != 0) { 2106 cmn_err(CE_WARN, "%s: failed to setup " 2107 "toeplitz tx hash table", mgp->name); 2108 goto abort_with_nothing; 2109 } 2110 } 2111 cmd.data0 = 1; 2112 cmd.data1 = myri10ge_rss_hash; 2113 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_RSS_ENABLE, 2114 &cmd); 2115 if (status != 0) { 2116 cmn_err(CE_WARN, 2117 "%s: failed to enable slices\n", mgp->name); 2118 goto abort_with_toeplitz; 2119 } 2120 } 2121 2122 for (i = 0; i < mgp->num_slices; i++) { 2123 status = myri10ge_setup_slice(&mgp->ss[i]); 2124 if (status != 0) 2125 goto abort_with_slices; 2126 } 2127 2128 /* 2129 * Tell the MCP how many buffers he has, and to 2130 * bring the ethernet interface up 2131 * 2132 * Firmware needs the big buff size as a power of 2. Lie and 2133 * tell him the buffer is larger, because we only use 1 2134 * buffer/pkt, and the mtu will prevent overruns 2135 */ 2136 big_pow2 = myri10ge_mtu + MXGEFW_PAD; 2137 while ((big_pow2 & (big_pow2 - 1)) != 0) 2138 big_pow2++; 2139 2140 /* now give firmware buffers sizes, and MTU */ 2141 cmd.data0 = myri10ge_mtu; 2142 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_MTU, &cmd); 2143 cmd.data0 = myri10ge_small_bytes; 2144 status |= 2145 myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_SMALL_BUFFER_SIZE, &cmd); 2146 cmd.data0 = big_pow2; 2147 status |= myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_BIG_BUFFER_SIZE, &cmd); 2148 if (status) { 2149 cmn_err(CE_WARN, "%s: Couldn't set buffer sizes\n", mgp->name); 2150 goto abort_with_slices; 2151 } 2152 2153 2154 cmd.data0 = 1; 2155 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_TSO_MODE, &cmd); 2156 if (status) { 2157 cmn_err(CE_WARN, "%s: unable to setup TSO (%d)\n", 2158 mgp->name, status); 2159 } else { 2160 mgp->features |= MYRI10GE_TSO; 2161 } 2162 2163 mgp->link_state = -1; 2164 mgp->rdma_tags_available = 15; 2165 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_UP, &cmd); 2166 if (status) { 2167 cmn_err(CE_WARN, "%s: unable to start ethernet\n", mgp->name); 2168 goto abort_with_slices; 2169 } 2170 mgp->running = MYRI10GE_ETH_RUNNING; 2171 return (DDI_SUCCESS); 2172 2173 abort_with_slices: 2174 for (i = 0; i < mgp->num_slices; i++) 2175 myri10ge_teardown_slice(&mgp->ss[i]); 2176 2177 mgp->running = MYRI10GE_ETH_STOPPED; 2178 2179 abort_with_toeplitz: 2180 if (mgp->toeplitz_hash_table != NULL) { 2181 kmem_free(mgp->toeplitz_hash_table, 2182 sizeof (uint32_t) * 12 * 256); 2183 mgp->toeplitz_hash_table = NULL; 2184 } 2185 2186 abort_with_nothing: 2187 return (DDI_FAILURE); 2188 } 2189 2190 static void 2191 myri10ge_stop_locked(struct myri10ge_priv *mgp) 2192 { 2193 int status, old_down_cnt; 2194 myri10ge_cmd_t cmd; 2195 int wait_time = 10; 2196 int i, polling; 2197 2198 old_down_cnt = mgp->down_cnt; 2199 mb(); 2200 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd); 2201 if (status) { 2202 cmn_err(CE_WARN, "%s: Couldn't bring down link\n", mgp->name); 2203 } 2204 2205 while (old_down_cnt == *((volatile int *)&mgp->down_cnt)) { 2206 delay(1 * drv_usectohz(1000000)); 2207 wait_time--; 2208 if (wait_time == 0) 2209 break; 2210 } 2211 again: 2212 if (old_down_cnt == *((volatile int *)&mgp->down_cnt)) { 2213 cmn_err(CE_WARN, "%s: didn't get down irq\n", mgp->name); 2214 for (i = 0; i < mgp->num_slices; i++) { 2215 /* 2216 * take and release the rx lock to ensure 2217 * that no interrupt thread is blocked 2218 * elsewhere in the stack, preventing 2219 * completion 2220 */ 2221 2222 mutex_enter(&mgp->ss[i].rx_lock); 2223 printf("%s: slice %d rx irq idle\n", 2224 mgp->name, i); 2225 mutex_exit(&mgp->ss[i].rx_lock); 2226 2227 /* verify that the poll handler is inactive */ 2228 mutex_enter(&mgp->ss->poll_lock); 2229 polling = mgp->ss->rx_polling; 2230 mutex_exit(&mgp->ss->poll_lock); 2231 if (polling) { 2232 printf("%s: slice %d is polling\n", 2233 mgp->name, i); 2234 delay(1 * drv_usectohz(1000000)); 2235 goto again; 2236 } 2237 } 2238 delay(1 * drv_usectohz(1000000)); 2239 if (old_down_cnt == *((volatile int *)&mgp->down_cnt)) { 2240 cmn_err(CE_WARN, "%s: Never got down irq\n", mgp->name); 2241 } 2242 } 2243 2244 for (i = 0; i < mgp->num_slices; i++) 2245 myri10ge_teardown_slice(&mgp->ss[i]); 2246 2247 if (mgp->toeplitz_hash_table != NULL) { 2248 kmem_free(mgp->toeplitz_hash_table, 2249 sizeof (uint32_t) * 12 * 256); 2250 mgp->toeplitz_hash_table = NULL; 2251 } 2252 mgp->running = MYRI10GE_ETH_STOPPED; 2253 } 2254 2255 static int 2256 myri10ge_m_start(void *arg) 2257 { 2258 struct myri10ge_priv *mgp = arg; 2259 int status; 2260 2261 mutex_enter(&mgp->intrlock); 2262 2263 if (mgp->running != MYRI10GE_ETH_STOPPED) { 2264 mutex_exit(&mgp->intrlock); 2265 return (DDI_FAILURE); 2266 } 2267 status = myri10ge_start_locked(mgp); 2268 mutex_exit(&mgp->intrlock); 2269 2270 if (status != DDI_SUCCESS) 2271 return (status); 2272 2273 /* start the watchdog timer */ 2274 mgp->timer_id = timeout(myri10ge_watchdog, mgp, 2275 mgp->timer_ticks); 2276 return (DDI_SUCCESS); 2277 2278 } 2279 2280 static void 2281 myri10ge_m_stop(void *arg) 2282 { 2283 struct myri10ge_priv *mgp = arg; 2284 2285 mutex_enter(&mgp->intrlock); 2286 /* if the device not running give up */ 2287 if (mgp->running != MYRI10GE_ETH_RUNNING) { 2288 mutex_exit(&mgp->intrlock); 2289 return; 2290 } 2291 2292 mgp->running = MYRI10GE_ETH_STOPPING; 2293 mutex_exit(&mgp->intrlock); 2294 (void) untimeout(mgp->timer_id); 2295 mutex_enter(&mgp->intrlock); 2296 myri10ge_stop_locked(mgp); 2297 mutex_exit(&mgp->intrlock); 2298 2299 } 2300 2301 static inline void 2302 myri10ge_rx_csum(mblk_t *mp, struct myri10ge_rx_ring_stats *s, uint32_t csum) 2303 { 2304 struct ether_header *eh; 2305 struct ip *ip; 2306 struct ip6_hdr *ip6; 2307 uint32_t start, stuff, end, partial, hdrlen; 2308 2309 2310 csum = ntohs((uint16_t)csum); 2311 eh = (struct ether_header *)(void *)mp->b_rptr; 2312 hdrlen = sizeof (*eh); 2313 if (eh->ether_dhost.ether_addr_octet[0] & 1) { 2314 if (0 == (bcmp(eh->ether_dhost.ether_addr_octet, 2315 myri10ge_broadcastaddr, sizeof (eh->ether_dhost)))) 2316 s->brdcstrcv++; 2317 else 2318 s->multircv++; 2319 } 2320 2321 if (eh->ether_type == BE_16(ETHERTYPE_VLAN)) { 2322 /* 2323 * fix checksum by subtracting 4 bytes after what the 2324 * firmware thought was the end of the ether hdr 2325 */ 2326 partial = *(uint32_t *) 2327 (void *)(mp->b_rptr + ETHERNET_HEADER_SIZE); 2328 csum += ~partial; 2329 csum += (csum < ~partial); 2330 csum = (csum >> 16) + (csum & 0xFFFF); 2331 csum = (csum >> 16) + (csum & 0xFFFF); 2332 hdrlen += VLAN_TAGSZ; 2333 } 2334 2335 if (eh->ether_type == BE_16(ETHERTYPE_IP)) { 2336 ip = (struct ip *)(void *)(mp->b_rptr + hdrlen); 2337 start = ip->ip_hl << 2; 2338 2339 if (ip->ip_p == IPPROTO_TCP) 2340 stuff = start + offsetof(struct tcphdr, th_sum); 2341 else if (ip->ip_p == IPPROTO_UDP) 2342 stuff = start + offsetof(struct udphdr, uh_sum); 2343 else 2344 return; 2345 end = ntohs(ip->ip_len); 2346 } else if (eh->ether_type == BE_16(ETHERTYPE_IPV6)) { 2347 ip6 = (struct ip6_hdr *)(void *)(mp->b_rptr + hdrlen); 2348 start = sizeof (*ip6); 2349 if (ip6->ip6_nxt == IPPROTO_TCP) { 2350 stuff = start + offsetof(struct tcphdr, th_sum); 2351 } else if (ip6->ip6_nxt == IPPROTO_UDP) 2352 stuff = start + offsetof(struct udphdr, uh_sum); 2353 else 2354 return; 2355 end = start + ntohs(ip6->ip6_plen); 2356 /* 2357 * IPv6 headers do not contain a checksum, and hence 2358 * do not checksum to zero, so they don't "fall out" 2359 * of the partial checksum calculation like IPv4 2360 * headers do. We need to fix the partial checksum by 2361 * subtracting the checksum of the IPv6 header. 2362 */ 2363 2364 partial = myri10ge_csum_generic((uint16_t *)ip6, sizeof (*ip6)); 2365 csum += ~partial; 2366 csum += (csum < ~partial); 2367 csum = (csum >> 16) + (csum & 0xFFFF); 2368 csum = (csum >> 16) + (csum & 0xFFFF); 2369 } else { 2370 return; 2371 } 2372 2373 if (MBLKL(mp) > hdrlen + end) { 2374 /* padded frame, so hw csum may be invalid */ 2375 return; 2376 } 2377 2378 (void) hcksum_assoc(mp, NULL, NULL, start, stuff, end, 2379 csum, HCK_PARTIALCKSUM, 0); 2380 } 2381 2382 static mblk_t * 2383 myri10ge_rx_done_small(struct myri10ge_slice_state *ss, uint32_t len, 2384 uint32_t csum) 2385 { 2386 mblk_t *mp; 2387 myri10ge_rx_ring_t *rx; 2388 int idx; 2389 2390 rx = &ss->rx_small; 2391 idx = rx->cnt & rx->mask; 2392 ss->rx_small.cnt++; 2393 2394 /* allocate a new buffer to pass up the stack */ 2395 mp = allocb(len + MXGEFW_PAD, 0); 2396 if (mp == NULL) { 2397 MYRI10GE_ATOMIC_SLICE_STAT_INC(rx_small_nobuf); 2398 goto abort; 2399 } 2400 bcopy(ss->rx_small.info[idx].ptr, 2401 (caddr_t)mp->b_wptr, len + MXGEFW_PAD); 2402 mp->b_wptr += len + MXGEFW_PAD; 2403 mp->b_rptr += MXGEFW_PAD; 2404 2405 ss->rx_stats.ibytes += len; 2406 ss->rx_stats.ipackets += 1; 2407 myri10ge_rx_csum(mp, &ss->rx_stats, csum); 2408 2409 abort: 2410 if ((idx & 7) == 7) { 2411 myri10ge_submit_8rx(&rx->lanai[idx - 7], 2412 &rx->shadow[idx - 7]); 2413 } 2414 2415 return (mp); 2416 } 2417 2418 2419 static mblk_t * 2420 myri10ge_rx_done_big(struct myri10ge_slice_state *ss, uint32_t len, 2421 uint32_t csum) 2422 { 2423 struct myri10ge_jpool_stuff *jpool; 2424 struct myri10ge_jpool_entry *j; 2425 mblk_t *mp; 2426 int idx, num_owned_by_mcp; 2427 2428 jpool = &ss->jpool; 2429 idx = ss->j_rx_cnt & ss->rx_big.mask; 2430 j = ss->rx_big.info[idx].j; 2431 2432 if (j == NULL) { 2433 printf("%s: null j at idx=%d, rx_big.cnt = %d, j_rx_cnt=%d\n", 2434 ss->mgp->name, idx, ss->rx_big.cnt, ss->j_rx_cnt); 2435 return (NULL); 2436 } 2437 2438 2439 ss->rx_big.info[idx].j = NULL; 2440 ss->j_rx_cnt++; 2441 2442 2443 /* 2444 * Check to see if we are low on rx buffers. 2445 * Note that we must leave at least 8 free so there are 2446 * enough to free in a single 64-byte write. 2447 */ 2448 num_owned_by_mcp = ss->rx_big.cnt - ss->j_rx_cnt; 2449 if (num_owned_by_mcp < jpool->low_water) { 2450 mutex_enter(&jpool->mtx); 2451 myri10ge_restock_jumbos(ss); 2452 mutex_exit(&jpool->mtx); 2453 num_owned_by_mcp = ss->rx_big.cnt - ss->j_rx_cnt; 2454 /* if we are still low, then we have to copy */ 2455 if (num_owned_by_mcp < 16) { 2456 MYRI10GE_ATOMIC_SLICE_STAT_INC(rx_copy); 2457 /* allocate a new buffer to pass up the stack */ 2458 mp = allocb(len + MXGEFW_PAD, 0); 2459 if (mp == NULL) { 2460 goto abort; 2461 } 2462 bcopy(j->buf, 2463 (caddr_t)mp->b_wptr, len + MXGEFW_PAD); 2464 myri10ge_jfree_rtn(j); 2465 /* push buffer back to NIC */ 2466 mutex_enter(&jpool->mtx); 2467 myri10ge_restock_jumbos(ss); 2468 mutex_exit(&jpool->mtx); 2469 goto set_len; 2470 } 2471 } 2472 2473 /* loan our buffer to the stack */ 2474 mp = desballoc((unsigned char *)j->buf, myri10ge_mtu, 0, &j->free_func); 2475 if (mp == NULL) { 2476 goto abort; 2477 } 2478 2479 set_len: 2480 mp->b_rptr += MXGEFW_PAD; 2481 mp->b_wptr = ((unsigned char *) mp->b_rptr + len); 2482 2483 ss->rx_stats.ibytes += len; 2484 ss->rx_stats.ipackets += 1; 2485 myri10ge_rx_csum(mp, &ss->rx_stats, csum); 2486 2487 return (mp); 2488 2489 abort: 2490 myri10ge_jfree_rtn(j); 2491 MYRI10GE_ATOMIC_SLICE_STAT_INC(rx_big_nobuf); 2492 return (NULL); 2493 } 2494 2495 /* 2496 * Free all transmit buffers up until the specified index 2497 */ 2498 static inline void 2499 myri10ge_tx_done(struct myri10ge_slice_state *ss, uint32_t mcp_index) 2500 { 2501 myri10ge_tx_ring_t *tx; 2502 struct myri10ge_tx_dma_handle_head handles; 2503 int idx; 2504 int limit = 0; 2505 2506 tx = &ss->tx; 2507 handles.head = NULL; 2508 handles.tail = NULL; 2509 while (tx->pkt_done != (int)mcp_index) { 2510 idx = tx->done & tx->mask; 2511 2512 /* 2513 * mblk & DMA handle attached only to first slot 2514 * per buffer in the packet 2515 */ 2516 2517 if (tx->info[idx].m) { 2518 (void) ddi_dma_unbind_handle(tx->info[idx].handle->h); 2519 tx->info[idx].handle->next = handles.head; 2520 handles.head = tx->info[idx].handle; 2521 if (handles.tail == NULL) 2522 handles.tail = tx->info[idx].handle; 2523 freeb(tx->info[idx].m); 2524 tx->info[idx].m = 0; 2525 tx->info[idx].handle = 0; 2526 } 2527 if (tx->info[idx].ostat.opackets != 0) { 2528 tx->stats.multixmt += tx->info[idx].ostat.multixmt; 2529 tx->stats.brdcstxmt += tx->info[idx].ostat.brdcstxmt; 2530 tx->stats.obytes += tx->info[idx].ostat.obytes; 2531 tx->stats.opackets += tx->info[idx].ostat.opackets; 2532 tx->info[idx].stat.un.all = 0; 2533 tx->pkt_done++; 2534 } 2535 2536 tx->done++; 2537 /* 2538 * if we stalled the queue, wake it. But Wait until 2539 * we have at least 1/2 our slots free. 2540 */ 2541 if ((tx->req - tx->done) < (tx->mask >> 1) && 2542 tx->stall != tx->sched) { 2543 mutex_enter(&ss->tx.lock); 2544 tx->sched = tx->stall; 2545 mutex_exit(&ss->tx.lock); 2546 mac_tx_ring_update(ss->mgp->mh, tx->rh); 2547 } 2548 2549 /* limit potential for livelock */ 2550 if (unlikely(++limit > 2 * tx->mask)) 2551 break; 2552 } 2553 if (tx->req == tx->done && tx->stop != NULL) { 2554 /* 2555 * Nic has sent all pending requests, allow him 2556 * to stop polling this queue 2557 */ 2558 mutex_enter(&tx->lock); 2559 if (tx->req == tx->done && tx->active) { 2560 *(int *)(void *)tx->stop = 1; 2561 tx->active = 0; 2562 mb(); 2563 } 2564 mutex_exit(&tx->lock); 2565 } 2566 if (handles.head != NULL) 2567 myri10ge_free_tx_handles(tx, &handles); 2568 } 2569 2570 static void 2571 myri10ge_mbl_init(struct myri10ge_mblk_list *mbl) 2572 { 2573 mbl->head = NULL; 2574 mbl->tail = &mbl->head; 2575 mbl->cnt = 0; 2576 } 2577 2578 /*ARGSUSED*/ 2579 void 2580 myri10ge_mbl_append(struct myri10ge_slice_state *ss, 2581 struct myri10ge_mblk_list *mbl, mblk_t *mp) 2582 { 2583 *(mbl->tail) = mp; 2584 mbl->tail = &mp->b_next; 2585 mp->b_next = NULL; 2586 mbl->cnt++; 2587 } 2588 2589 2590 static inline void 2591 myri10ge_clean_rx_done(struct myri10ge_slice_state *ss, 2592 struct myri10ge_mblk_list *mbl, int limit, boolean_t *stop) 2593 { 2594 myri10ge_rx_done_t *rx_done = &ss->rx_done; 2595 struct myri10ge_priv *mgp = ss->mgp; 2596 mblk_t *mp; 2597 struct lro_entry *lro; 2598 uint16_t length; 2599 uint16_t checksum; 2600 2601 2602 while (rx_done->entry[rx_done->idx].length != 0) { 2603 if (unlikely (*stop)) { 2604 break; 2605 } 2606 length = ntohs(rx_done->entry[rx_done->idx].length); 2607 length &= (~MXGEFW_RSS_HASH_MASK); 2608 2609 /* limit potential for livelock */ 2610 limit -= length; 2611 if (unlikely(limit < 0)) 2612 break; 2613 2614 rx_done->entry[rx_done->idx].length = 0; 2615 checksum = ntohs(rx_done->entry[rx_done->idx].checksum); 2616 if (length <= myri10ge_small_bytes) 2617 mp = myri10ge_rx_done_small(ss, length, checksum); 2618 else 2619 mp = myri10ge_rx_done_big(ss, length, checksum); 2620 if (mp != NULL) { 2621 if (!myri10ge_lro || 2622 0 != myri10ge_lro_rx(ss, mp, checksum, mbl)) 2623 myri10ge_mbl_append(ss, mbl, mp); 2624 } 2625 rx_done->cnt++; 2626 rx_done->idx = rx_done->cnt & (mgp->max_intr_slots - 1); 2627 } 2628 while (ss->lro_active != NULL) { 2629 lro = ss->lro_active; 2630 ss->lro_active = lro->next; 2631 myri10ge_lro_flush(ss, lro, mbl); 2632 } 2633 } 2634 2635 static void 2636 myri10ge_intr_rx(struct myri10ge_slice_state *ss) 2637 { 2638 uint64_t gen; 2639 struct myri10ge_mblk_list mbl; 2640 2641 myri10ge_mbl_init(&mbl); 2642 if (mutex_tryenter(&ss->rx_lock) == 0) 2643 return; 2644 gen = ss->rx_gen_num; 2645 myri10ge_clean_rx_done(ss, &mbl, MYRI10GE_POLL_NULL, 2646 &ss->rx_polling); 2647 if (mbl.head != NULL) 2648 mac_rx_ring(ss->mgp->mh, ss->rx_rh, mbl.head, gen); 2649 mutex_exit(&ss->rx_lock); 2650 2651 } 2652 2653 static mblk_t * 2654 myri10ge_poll_rx(void *arg, int bytes) 2655 { 2656 struct myri10ge_slice_state *ss = arg; 2657 struct myri10ge_mblk_list mbl; 2658 boolean_t dummy = B_FALSE; 2659 2660 if (bytes == 0) 2661 return (NULL); 2662 2663 myri10ge_mbl_init(&mbl); 2664 mutex_enter(&ss->rx_lock); 2665 if (ss->rx_polling) 2666 myri10ge_clean_rx_done(ss, &mbl, bytes, &dummy); 2667 else 2668 printf("%d: poll_rx: token=%d, polling=%d\n", (int)(ss - 2669 ss->mgp->ss), ss->rx_token, ss->rx_polling); 2670 mutex_exit(&ss->rx_lock); 2671 return (mbl.head); 2672 } 2673 2674 /*ARGSUSED*/ 2675 static uint_t 2676 myri10ge_intr(caddr_t arg0, caddr_t arg1) 2677 { 2678 struct myri10ge_slice_state *ss = 2679 (struct myri10ge_slice_state *)(void *)arg0; 2680 struct myri10ge_priv *mgp = ss->mgp; 2681 mcp_irq_data_t *stats = ss->fw_stats; 2682 myri10ge_tx_ring_t *tx = &ss->tx; 2683 uint32_t send_done_count; 2684 uint8_t valid; 2685 2686 2687 /* make sure the DMA has finished */ 2688 if (!stats->valid) { 2689 return (DDI_INTR_UNCLAIMED); 2690 } 2691 valid = stats->valid; 2692 2693 /* low bit indicates receives are present */ 2694 if (valid & 1) 2695 myri10ge_intr_rx(ss); 2696 2697 if (mgp->ddi_intr_type == DDI_INTR_TYPE_FIXED) { 2698 /* lower legacy IRQ */ 2699 *mgp->irq_deassert = 0; 2700 if (!myri10ge_deassert_wait) 2701 /* don't wait for conf. that irq is low */ 2702 stats->valid = 0; 2703 mb(); 2704 } else { 2705 /* no need to wait for conf. that irq is low */ 2706 stats->valid = 0; 2707 } 2708 2709 do { 2710 /* check for transmit completes and receives */ 2711 send_done_count = ntohl(stats->send_done_count); 2712 if (send_done_count != tx->pkt_done) 2713 myri10ge_tx_done(ss, (int)send_done_count); 2714 } while (*((volatile uint8_t *) &stats->valid)); 2715 2716 if (stats->stats_updated) { 2717 if (mgp->link_state != stats->link_up || stats->link_down) { 2718 mgp->link_state = stats->link_up; 2719 if (stats->link_down) { 2720 mgp->down_cnt += stats->link_down; 2721 mgp->link_state = 0; 2722 } 2723 if (mgp->link_state) { 2724 if (myri10ge_verbose) 2725 printf("%s: link up\n", mgp->name); 2726 mac_link_update(mgp->mh, LINK_STATE_UP); 2727 } else { 2728 if (myri10ge_verbose) 2729 printf("%s: link down\n", mgp->name); 2730 mac_link_update(mgp->mh, LINK_STATE_DOWN); 2731 } 2732 MYRI10GE_NIC_STAT_INC(link_changes); 2733 } 2734 if (mgp->rdma_tags_available != 2735 ntohl(ss->fw_stats->rdma_tags_available)) { 2736 mgp->rdma_tags_available = 2737 ntohl(ss->fw_stats->rdma_tags_available); 2738 cmn_err(CE_NOTE, "%s: RDMA timed out! " 2739 "%d tags left\n", mgp->name, 2740 mgp->rdma_tags_available); 2741 } 2742 } 2743 2744 mb(); 2745 /* check to see if we have rx token to pass back */ 2746 if (valid & 0x1) { 2747 mutex_enter(&ss->poll_lock); 2748 if (ss->rx_polling) { 2749 ss->rx_token = 1; 2750 } else { 2751 *ss->irq_claim = BE_32(3); 2752 ss->rx_token = 0; 2753 } 2754 mutex_exit(&ss->poll_lock); 2755 } 2756 *(ss->irq_claim + 1) = BE_32(3); 2757 return (DDI_INTR_CLAIMED); 2758 } 2759 2760 /* 2761 * Add or remove a multicast address. This is called with our 2762 * macinfo's lock held by GLD, so we do not need to worry about 2763 * our own locking here. 2764 */ 2765 static int 2766 myri10ge_m_multicst(void *arg, boolean_t add, const uint8_t *multicastaddr) 2767 { 2768 myri10ge_cmd_t cmd; 2769 struct myri10ge_priv *mgp = arg; 2770 int status, join_leave; 2771 2772 if (add) 2773 join_leave = MXGEFW_JOIN_MULTICAST_GROUP; 2774 else 2775 join_leave = MXGEFW_LEAVE_MULTICAST_GROUP; 2776 (void) memcpy(&cmd.data0, multicastaddr, 4); 2777 (void) memcpy(&cmd.data1, multicastaddr + 4, 2); 2778 cmd.data0 = htonl(cmd.data0); 2779 cmd.data1 = htonl(cmd.data1); 2780 status = myri10ge_send_cmd(mgp, join_leave, &cmd); 2781 if (status == 0) 2782 return (0); 2783 2784 cmn_err(CE_WARN, "%s: failed to set multicast address\n", 2785 mgp->name); 2786 return (status); 2787 } 2788 2789 2790 static int 2791 myri10ge_m_promisc(void *arg, boolean_t on) 2792 { 2793 struct myri10ge_priv *mgp = arg; 2794 2795 myri10ge_change_promisc(mgp, on); 2796 return (0); 2797 } 2798 2799 /* 2800 * copy an array of mcp_kreq_ether_send_t's to the mcp. Copy 2801 * backwards one at a time and handle ring wraps 2802 */ 2803 2804 static inline void 2805 myri10ge_submit_req_backwards(myri10ge_tx_ring_t *tx, 2806 mcp_kreq_ether_send_t *src, int cnt) 2807 { 2808 int idx, starting_slot; 2809 starting_slot = tx->req; 2810 while (cnt > 1) { 2811 cnt--; 2812 idx = (starting_slot + cnt) & tx->mask; 2813 myri10ge_pio_copy(&tx->lanai[idx], 2814 &src[cnt], sizeof (*src)); 2815 mb(); 2816 } 2817 } 2818 2819 /* 2820 * copy an array of mcp_kreq_ether_send_t's to the mcp. Copy 2821 * at most 32 bytes at a time, so as to avoid involving the software 2822 * pio handler in the nic. We re-write the first segment's flags 2823 * to mark them valid only after writing the entire chain 2824 */ 2825 2826 static inline void 2827 myri10ge_submit_req(myri10ge_tx_ring_t *tx, mcp_kreq_ether_send_t *src, 2828 int cnt) 2829 { 2830 int idx, i; 2831 uint32_t *src_ints, *dst_ints; 2832 mcp_kreq_ether_send_t *srcp, *dstp, *dst; 2833 uint8_t last_flags; 2834 2835 idx = tx->req & tx->mask; 2836 2837 last_flags = src->flags; 2838 src->flags = 0; 2839 mb(); 2840 dst = dstp = &tx->lanai[idx]; 2841 srcp = src; 2842 2843 if ((idx + cnt) < tx->mask) { 2844 for (i = 0; i < (cnt - 1); i += 2) { 2845 myri10ge_pio_copy(dstp, srcp, 2 * sizeof (*src)); 2846 mb(); /* force write every 32 bytes */ 2847 srcp += 2; 2848 dstp += 2; 2849 } 2850 } else { 2851 /* 2852 * submit all but the first request, and ensure 2853 * that it is submitted below 2854 */ 2855 myri10ge_submit_req_backwards(tx, src, cnt); 2856 i = 0; 2857 } 2858 if (i < cnt) { 2859 /* submit the first request */ 2860 myri10ge_pio_copy(dstp, srcp, sizeof (*src)); 2861 mb(); /* barrier before setting valid flag */ 2862 } 2863 2864 /* re-write the last 32-bits with the valid flags */ 2865 src->flags |= last_flags; 2866 src_ints = (uint32_t *)src; 2867 src_ints += 3; 2868 dst_ints = (uint32_t *)dst; 2869 dst_ints += 3; 2870 *dst_ints = *src_ints; 2871 tx->req += cnt; 2872 mb(); 2873 /* notify NIC to poll this tx ring */ 2874 if (!tx->active && tx->go != NULL) { 2875 *(int *)(void *)tx->go = 1; 2876 tx->active = 1; 2877 tx->activate++; 2878 mb(); 2879 } 2880 } 2881 2882 /* ARGSUSED */ 2883 static inline void 2884 myri10ge_lso_info_get(mblk_t *mp, uint32_t *mss, uint32_t *flags) 2885 { 2886 uint32_t lso_flag; 2887 lso_info_get(mp, mss, &lso_flag); 2888 (*flags) |= lso_flag; 2889 } 2890 2891 2892 /* like pullupmsg, except preserve hcksum/LSO attributes */ 2893 static int 2894 myri10ge_pullup(struct myri10ge_slice_state *ss, mblk_t *mp) 2895 { 2896 uint32_t start, stuff, tx_offload_flags, mss; 2897 int ok; 2898 2899 mss = 0; 2900 hcksum_retrieve(mp, NULL, NULL, &start, &stuff, NULL, NULL, 2901 &tx_offload_flags); 2902 myri10ge_lso_info_get(mp, &mss, &tx_offload_flags); 2903 2904 ok = pullupmsg(mp, -1); 2905 if (!ok) { 2906 printf("pullupmsg failed"); 2907 return (DDI_FAILURE); 2908 } 2909 MYRI10GE_ATOMIC_SLICE_STAT_INC(xmit_pullup); 2910 (void) hcksum_assoc(mp, NULL, NULL, start, stuff, NULL, 2911 NULL, tx_offload_flags, 0); 2912 if (tx_offload_flags & HW_LSO) 2913 DB_LSOMSS(mp) = (uint16_t)mss; 2914 lso_info_set(mp, mss, tx_offload_flags); 2915 return (DDI_SUCCESS); 2916 } 2917 2918 static inline void 2919 myri10ge_tx_stat(struct myri10ge_tx_pkt_stats *s, struct ether_header *eh, 2920 int opackets, int obytes) 2921 { 2922 s->un.all = 0; 2923 if (eh->ether_dhost.ether_addr_octet[0] & 1) { 2924 if (0 == (bcmp(eh->ether_dhost.ether_addr_octet, 2925 myri10ge_broadcastaddr, sizeof (eh->ether_dhost)))) 2926 s->un.s.brdcstxmt = 1; 2927 else 2928 s->un.s.multixmt = 1; 2929 } 2930 s->un.s.opackets = (uint16_t)opackets; 2931 s->un.s.obytes = obytes; 2932 } 2933 2934 static int 2935 myri10ge_tx_copy(struct myri10ge_slice_state *ss, mblk_t *mp, 2936 mcp_kreq_ether_send_t *req) 2937 { 2938 myri10ge_tx_ring_t *tx = &ss->tx; 2939 caddr_t ptr; 2940 struct myri10ge_tx_copybuf *cp; 2941 mblk_t *bp; 2942 int idx, mblen, avail; 2943 uint16_t len; 2944 2945 mutex_enter(&tx->lock); 2946 avail = tx->mask - (tx->req - tx->done); 2947 if (avail <= 1) { 2948 mutex_exit(&tx->lock); 2949 return (EBUSY); 2950 } 2951 idx = tx->req & tx->mask; 2952 cp = &tx->cp[idx]; 2953 ptr = cp->va; 2954 for (len = 0, bp = mp; bp != NULL; bp = bp->b_cont) { 2955 mblen = MBLKL(bp); 2956 bcopy(bp->b_rptr, ptr, mblen); 2957 ptr += mblen; 2958 len += mblen; 2959 } 2960 /* ensure runts are padded to 60 bytes */ 2961 if (len < 60) { 2962 bzero(ptr, 64 - len); 2963 len = 60; 2964 } 2965 req->addr_low = cp->dma.low; 2966 req->addr_high = cp->dma.high; 2967 req->length = htons(len); 2968 req->pad = 0; 2969 req->rdma_count = 1; 2970 myri10ge_tx_stat(&tx->info[idx].stat, 2971 (struct ether_header *)(void *)cp->va, 1, len); 2972 (void) ddi_dma_sync(cp->dma.handle, 0, len, DDI_DMA_SYNC_FORDEV); 2973 myri10ge_submit_req(&ss->tx, req, 1); 2974 mutex_exit(&tx->lock); 2975 freemsg(mp); 2976 return (DDI_SUCCESS); 2977 } 2978 2979 2980 static void 2981 myri10ge_send_locked(myri10ge_tx_ring_t *tx, mcp_kreq_ether_send_t *req_list, 2982 struct myri10ge_tx_buffer_state *tx_info, 2983 int count) 2984 { 2985 int i, idx; 2986 2987 idx = 0; /* gcc -Wuninitialized */ 2988 /* store unmapping and bp info for tx irq handler */ 2989 for (i = 0; i < count; i++) { 2990 idx = (tx->req + i) & tx->mask; 2991 tx->info[idx].m = tx_info[i].m; 2992 tx->info[idx].handle = tx_info[i].handle; 2993 } 2994 tx->info[idx].stat.un.all = tx_info[0].stat.un.all; 2995 2996 /* submit the frame to the nic */ 2997 myri10ge_submit_req(tx, req_list, count); 2998 2999 3000 } 3001 3002 3003 3004 static void 3005 myri10ge_copydata(mblk_t *mp, int off, int len, caddr_t buf) 3006 { 3007 mblk_t *bp; 3008 int seglen; 3009 uint_t count; 3010 3011 bp = mp; 3012 3013 while (off > 0) { 3014 seglen = MBLKL(bp); 3015 if (off < seglen) 3016 break; 3017 off -= seglen; 3018 bp = bp->b_cont; 3019 } 3020 while (len > 0) { 3021 seglen = MBLKL(bp); 3022 count = min(seglen - off, len); 3023 bcopy(bp->b_rptr + off, buf, count); 3024 len -= count; 3025 buf += count; 3026 off = 0; 3027 bp = bp->b_cont; 3028 } 3029 } 3030 3031 static int 3032 myri10ge_ether_parse_header(mblk_t *mp) 3033 { 3034 struct ether_header eh_copy; 3035 struct ether_header *eh; 3036 int eth_hdr_len, seglen; 3037 3038 seglen = MBLKL(mp); 3039 eth_hdr_len = sizeof (*eh); 3040 if (seglen < eth_hdr_len) { 3041 myri10ge_copydata(mp, 0, eth_hdr_len, (caddr_t)&eh_copy); 3042 eh = &eh_copy; 3043 } else { 3044 eh = (struct ether_header *)(void *)mp->b_rptr; 3045 } 3046 if (eh->ether_type == BE_16(ETHERTYPE_VLAN)) { 3047 eth_hdr_len += 4; 3048 } 3049 3050 return (eth_hdr_len); 3051 } 3052 3053 static int 3054 myri10ge_lso_parse_header(mblk_t *mp, int off) 3055 { 3056 char buf[128]; 3057 int seglen; 3058 struct ip *ip; 3059 struct tcphdr *tcp; 3060 3061 seglen = MBLKL(mp); 3062 if (seglen < off + sizeof (*ip)) { 3063 myri10ge_copydata(mp, off, sizeof (*ip), buf); 3064 ip = (struct ip *)(void *)buf; 3065 } else { 3066 ip = (struct ip *)(void *)(mp->b_rptr + off); 3067 } 3068 if (seglen < off + (ip->ip_hl << 2) + sizeof (*tcp)) { 3069 myri10ge_copydata(mp, off, 3070 (ip->ip_hl << 2) + sizeof (*tcp), buf); 3071 ip = (struct ip *)(void *)buf; 3072 } 3073 tcp = (struct tcphdr *)(void *)((char *)ip + (ip->ip_hl << 2)); 3074 return (off + ((ip->ip_hl + tcp->th_off) << 2)); 3075 } 3076 3077 static int 3078 myri10ge_tx_tso_copy(struct myri10ge_slice_state *ss, mblk_t *mp, 3079 mcp_kreq_ether_send_t *req_list, int hdr_size, int pkt_size, 3080 uint16_t mss, uint8_t cksum_offset) 3081 { 3082 myri10ge_tx_ring_t *tx = &ss->tx; 3083 struct myri10ge_priv *mgp = ss->mgp; 3084 mblk_t *bp; 3085 mcp_kreq_ether_send_t *req; 3086 struct myri10ge_tx_copybuf *cp; 3087 caddr_t rptr, ptr; 3088 int mblen, count, cum_len, mss_resid, tx_req, pkt_size_tmp; 3089 int resid, avail, idx, hdr_size_tmp, tx_boundary; 3090 int rdma_count; 3091 uint32_t seglen, len, boundary, low, high_swapped; 3092 uint16_t pseudo_hdr_offset = htons(mss); 3093 uint8_t flags; 3094 3095 tx_boundary = mgp->tx_boundary; 3096 hdr_size_tmp = hdr_size; 3097 resid = tx_boundary; 3098 count = 1; 3099 mutex_enter(&tx->lock); 3100 3101 /* check to see if the slots are really there */ 3102 avail = tx->mask - (tx->req - tx->done); 3103 if (unlikely(avail <= MYRI10GE_MAX_SEND_DESC_TSO)) { 3104 atomic_add_32(&tx->stall, 1); 3105 mutex_exit(&tx->lock); 3106 return (EBUSY); 3107 } 3108 3109 /* copy */ 3110 cum_len = -hdr_size; 3111 count = 0; 3112 req = req_list; 3113 idx = tx->mask & tx->req; 3114 cp = &tx->cp[idx]; 3115 low = ntohl(cp->dma.low); 3116 ptr = cp->va; 3117 cp->len = 0; 3118 if (mss) { 3119 int payload = pkt_size - hdr_size; 3120 uint16_t opackets = (payload / mss) + ((payload % mss) != 0); 3121 tx->info[idx].ostat.opackets = opackets; 3122 tx->info[idx].ostat.obytes = (opackets - 1) * hdr_size 3123 + pkt_size; 3124 } 3125 hdr_size_tmp = hdr_size; 3126 mss_resid = mss; 3127 flags = (MXGEFW_FLAGS_TSO_HDR | MXGEFW_FLAGS_FIRST); 3128 tx_req = tx->req; 3129 for (bp = mp; bp != NULL; bp = bp->b_cont) { 3130 mblen = MBLKL(bp); 3131 rptr = (caddr_t)bp->b_rptr; 3132 len = min(hdr_size_tmp, mblen); 3133 if (len) { 3134 bcopy(rptr, ptr, len); 3135 rptr += len; 3136 ptr += len; 3137 resid -= len; 3138 mblen -= len; 3139 hdr_size_tmp -= len; 3140 cp->len += len; 3141 if (hdr_size_tmp) 3142 continue; 3143 if (resid < mss) { 3144 tx_req++; 3145 idx = tx->mask & tx_req; 3146 cp = &tx->cp[idx]; 3147 low = ntohl(cp->dma.low); 3148 ptr = cp->va; 3149 resid = tx_boundary; 3150 } 3151 } 3152 while (mblen) { 3153 len = min(mss_resid, mblen); 3154 bcopy(rptr, ptr, len); 3155 mss_resid -= len; 3156 resid -= len; 3157 mblen -= len; 3158 rptr += len; 3159 ptr += len; 3160 cp->len += len; 3161 if (mss_resid == 0) { 3162 mss_resid = mss; 3163 if (resid < mss) { 3164 tx_req++; 3165 idx = tx->mask & tx_req; 3166 cp = &tx->cp[idx]; 3167 cp->len = 0; 3168 low = ntohl(cp->dma.low); 3169 ptr = cp->va; 3170 resid = tx_boundary; 3171 } 3172 } 3173 } 3174 } 3175 3176 req = req_list; 3177 pkt_size_tmp = pkt_size; 3178 count = 0; 3179 rdma_count = 0; 3180 tx_req = tx->req; 3181 while (pkt_size_tmp) { 3182 idx = tx->mask & tx_req; 3183 cp = &tx->cp[idx]; 3184 high_swapped = cp->dma.high; 3185 low = ntohl(cp->dma.low); 3186 len = cp->len; 3187 if (len == 0) { 3188 printf("len=0! pkt_size_tmp=%d, pkt_size=%d\n", 3189 pkt_size_tmp, pkt_size); 3190 for (bp = mp; bp != NULL; bp = bp->b_cont) { 3191 mblen = MBLKL(bp); 3192 printf("mblen:%d\n", mblen); 3193 } 3194 pkt_size_tmp = pkt_size; 3195 tx_req = tx->req; 3196 while (pkt_size_tmp > 0) { 3197 idx = tx->mask & tx_req; 3198 cp = &tx->cp[idx]; 3199 printf("cp->len = %d\n", cp->len); 3200 pkt_size_tmp -= cp->len; 3201 tx_req++; 3202 } 3203 printf("dropped\n"); 3204 MYRI10GE_ATOMIC_SLICE_STAT_INC(xmit_err); 3205 goto done; 3206 } 3207 pkt_size_tmp -= len; 3208 while (len) { 3209 while (len) { 3210 uint8_t flags_next; 3211 int cum_len_next; 3212 3213 boundary = (low + mgp->tx_boundary) & 3214 ~(mgp->tx_boundary - 1); 3215 seglen = boundary - low; 3216 if (seglen > len) 3217 seglen = len; 3218 3219 flags_next = flags & ~MXGEFW_FLAGS_FIRST; 3220 cum_len_next = cum_len + seglen; 3221 (req-rdma_count)->rdma_count = rdma_count + 1; 3222 if (likely(cum_len >= 0)) { 3223 /* payload */ 3224 int next_is_first, chop; 3225 3226 chop = (cum_len_next > mss); 3227 cum_len_next = cum_len_next % mss; 3228 next_is_first = (cum_len_next == 0); 3229 flags |= chop * 3230 MXGEFW_FLAGS_TSO_CHOP; 3231 flags_next |= next_is_first * 3232 MXGEFW_FLAGS_FIRST; 3233 rdma_count |= -(chop | next_is_first); 3234 rdma_count += chop & !next_is_first; 3235 } else if (likely(cum_len_next >= 0)) { 3236 /* header ends */ 3237 int small; 3238 3239 rdma_count = -1; 3240 cum_len_next = 0; 3241 seglen = -cum_len; 3242 small = (mss <= MXGEFW_SEND_SMALL_SIZE); 3243 flags_next = MXGEFW_FLAGS_TSO_PLD | 3244 MXGEFW_FLAGS_FIRST | 3245 (small * MXGEFW_FLAGS_SMALL); 3246 } 3247 req->addr_high = high_swapped; 3248 req->addr_low = htonl(low); 3249 req->pseudo_hdr_offset = pseudo_hdr_offset; 3250 req->pad = 0; /* complete solid 16-byte block */ 3251 req->rdma_count = 1; 3252 req->cksum_offset = cksum_offset; 3253 req->length = htons(seglen); 3254 req->flags = flags | ((cum_len & 1) * 3255 MXGEFW_FLAGS_ALIGN_ODD); 3256 if (cksum_offset > seglen) 3257 cksum_offset -= seglen; 3258 else 3259 cksum_offset = 0; 3260 low += seglen; 3261 len -= seglen; 3262 cum_len = cum_len_next; 3263 req++; 3264 req->flags = 0; 3265 flags = flags_next; 3266 count++; 3267 rdma_count++; 3268 } 3269 } 3270 tx_req++; 3271 } 3272 (req-rdma_count)->rdma_count = (uint8_t)rdma_count; 3273 do { 3274 req--; 3275 req->flags |= MXGEFW_FLAGS_TSO_LAST; 3276 } while (!(req->flags & (MXGEFW_FLAGS_TSO_CHOP | 3277 MXGEFW_FLAGS_FIRST))); 3278 3279 myri10ge_submit_req(tx, req_list, count); 3280 done: 3281 mutex_exit(&tx->lock); 3282 freemsg(mp); 3283 return (DDI_SUCCESS); 3284 } 3285 3286 /* 3287 * Try to send the chain of buffers described by the mp. We must not 3288 * encapsulate more than eth->tx.req - eth->tx.done, or 3289 * MXGEFW_MAX_SEND_DESC, whichever is more. 3290 */ 3291 3292 static int 3293 myri10ge_send(struct myri10ge_slice_state *ss, mblk_t *mp, 3294 mcp_kreq_ether_send_t *req_list, struct myri10ge_tx_buffer_state *tx_info) 3295 { 3296 struct myri10ge_priv *mgp = ss->mgp; 3297 myri10ge_tx_ring_t *tx = &ss->tx; 3298 mcp_kreq_ether_send_t *req; 3299 struct myri10ge_tx_dma_handle *handles, *dma_handle = NULL; 3300 mblk_t *bp; 3301 ddi_dma_cookie_t cookie; 3302 int err, rv, count, avail, mblen, try_pullup, i, max_segs, maclen, 3303 rdma_count, cum_len, lso_hdr_size; 3304 uint32_t start, stuff, tx_offload_flags; 3305 uint32_t seglen, len, mss, boundary, low, high_swapped; 3306 uint_t ncookies; 3307 uint16_t pseudo_hdr_offset; 3308 uint8_t flags, cksum_offset, odd_flag; 3309 int pkt_size; 3310 int lso_copy = myri10ge_lso_copy; 3311 try_pullup = 1; 3312 3313 again: 3314 /* Setup checksum offloading, if needed */ 3315 hcksum_retrieve(mp, NULL, NULL, &start, &stuff, NULL, NULL, 3316 &tx_offload_flags); 3317 myri10ge_lso_info_get(mp, &mss, &tx_offload_flags); 3318 if (tx_offload_flags & HW_LSO) { 3319 max_segs = MYRI10GE_MAX_SEND_DESC_TSO; 3320 if ((tx_offload_flags & HCK_PARTIALCKSUM) == 0) { 3321 MYRI10GE_ATOMIC_SLICE_STAT_INC(xmit_lsobadflags); 3322 freemsg(mp); 3323 return (DDI_SUCCESS); 3324 } 3325 } else { 3326 max_segs = MXGEFW_MAX_SEND_DESC; 3327 mss = 0; 3328 } 3329 req = req_list; 3330 cksum_offset = 0; 3331 pseudo_hdr_offset = 0; 3332 3333 /* leave an extra slot keep the ring from wrapping */ 3334 avail = tx->mask - (tx->req - tx->done); 3335 3336 /* 3337 * If we have > MXGEFW_MAX_SEND_DESC, then any over-length 3338 * message will need to be pulled up in order to fit. 3339 * Otherwise, we are low on transmit descriptors, it is 3340 * probably better to stall and try again rather than pullup a 3341 * message to fit. 3342 */ 3343 3344 if (avail < max_segs) { 3345 err = EBUSY; 3346 atomic_add_32(&tx->stall_early, 1); 3347 goto stall; 3348 } 3349 3350 /* find out how long the frame is and how many segments it is */ 3351 count = 0; 3352 odd_flag = 0; 3353 pkt_size = 0; 3354 flags = (MXGEFW_FLAGS_NO_TSO | MXGEFW_FLAGS_FIRST); 3355 for (bp = mp; bp != NULL; bp = bp->b_cont) { 3356 dblk_t *dbp; 3357 mblen = MBLKL(bp); 3358 if (mblen == 0) { 3359 /* 3360 * we can't simply skip over 0-length mblks 3361 * because the hardware can't deal with them, 3362 * and we could leak them. 3363 */ 3364 MYRI10GE_ATOMIC_SLICE_STAT_INC(xmit_zero_len); 3365 err = EIO; 3366 goto pullup; 3367 } 3368 /* 3369 * There's no advantage to copying most gesballoc 3370 * attached blocks, so disable lso copy in that case 3371 */ 3372 if (mss && lso_copy == 1 && ((dbp = bp->b_datap) != NULL)) { 3373 if ((void *)dbp->db_lastfree != myri10ge_db_lastfree) { 3374 lso_copy = 0; 3375 } 3376 } 3377 pkt_size += mblen; 3378 count++; 3379 } 3380 3381 /* Try to pull up excessivly long chains */ 3382 if (count >= max_segs) { 3383 err = myri10ge_pullup(ss, mp); 3384 if (likely(err == DDI_SUCCESS)) { 3385 count = 1; 3386 } else { 3387 if (count < MYRI10GE_MAX_SEND_DESC_TSO) { 3388 /* 3389 * just let the h/w send it, it will be 3390 * inefficient, but us better than dropping 3391 */ 3392 max_segs = MYRI10GE_MAX_SEND_DESC_TSO; 3393 } else { 3394 /* drop it */ 3395 MYRI10GE_ATOMIC_SLICE_STAT_INC(xmit_err); 3396 freemsg(mp); 3397 return (0); 3398 } 3399 } 3400 } 3401 3402 cum_len = 0; 3403 maclen = myri10ge_ether_parse_header(mp); 3404 3405 if (tx_offload_flags & HCK_PARTIALCKSUM) { 3406 3407 cksum_offset = start + maclen; 3408 pseudo_hdr_offset = htons(stuff + maclen); 3409 odd_flag = MXGEFW_FLAGS_ALIGN_ODD; 3410 flags |= MXGEFW_FLAGS_CKSUM; 3411 } 3412 3413 lso_hdr_size = 0; /* -Wunitinialized */ 3414 if (mss) { /* LSO */ 3415 /* this removes any CKSUM flag from before */ 3416 flags = (MXGEFW_FLAGS_TSO_HDR | MXGEFW_FLAGS_FIRST); 3417 /* 3418 * parse the headers and set cum_len to a negative 3419 * value to reflect the offset of the TCP payload 3420 */ 3421 lso_hdr_size = myri10ge_lso_parse_header(mp, maclen); 3422 cum_len = -lso_hdr_size; 3423 if ((mss < mgp->tx_boundary) && lso_copy) { 3424 err = myri10ge_tx_tso_copy(ss, mp, req_list, 3425 lso_hdr_size, pkt_size, mss, cksum_offset); 3426 return (err); 3427 } 3428 3429 /* 3430 * for TSO, pseudo_hdr_offset holds mss. The firmware 3431 * figures out where to put the checksum by parsing 3432 * the header. 3433 */ 3434 3435 pseudo_hdr_offset = htons(mss); 3436 } else if (pkt_size <= MXGEFW_SEND_SMALL_SIZE) { 3437 flags |= MXGEFW_FLAGS_SMALL; 3438 if (pkt_size < myri10ge_tx_copylen) { 3439 req->cksum_offset = cksum_offset; 3440 req->pseudo_hdr_offset = pseudo_hdr_offset; 3441 req->flags = flags; 3442 err = myri10ge_tx_copy(ss, mp, req); 3443 return (err); 3444 } 3445 cum_len = 0; 3446 } 3447 3448 /* pull one DMA handle for each bp from our freelist */ 3449 handles = NULL; 3450 err = myri10ge_alloc_tx_handles(ss, count, &handles); 3451 if (err != DDI_SUCCESS) { 3452 err = DDI_FAILURE; 3453 goto stall; 3454 } 3455 count = 0; 3456 rdma_count = 0; 3457 for (bp = mp; bp != NULL; bp = bp->b_cont) { 3458 mblen = MBLKL(bp); 3459 dma_handle = handles; 3460 handles = handles->next; 3461 3462 rv = ddi_dma_addr_bind_handle(dma_handle->h, NULL, 3463 (caddr_t)bp->b_rptr, mblen, 3464 DDI_DMA_WRITE | DDI_DMA_STREAMING, DDI_DMA_SLEEP, NULL, 3465 &cookie, &ncookies); 3466 if (unlikely(rv != DDI_DMA_MAPPED)) { 3467 err = EIO; 3468 try_pullup = 0; 3469 dma_handle->next = handles; 3470 handles = dma_handle; 3471 goto abort_with_handles; 3472 } 3473 3474 /* reserve the slot */ 3475 tx_info[count].m = bp; 3476 tx_info[count].handle = dma_handle; 3477 3478 for (; ; ) { 3479 low = MYRI10GE_LOWPART_TO_U32(cookie.dmac_laddress); 3480 high_swapped = 3481 htonl(MYRI10GE_HIGHPART_TO_U32( 3482 cookie.dmac_laddress)); 3483 len = (uint32_t)cookie.dmac_size; 3484 while (len) { 3485 uint8_t flags_next; 3486 int cum_len_next; 3487 3488 boundary = (low + mgp->tx_boundary) & 3489 ~(mgp->tx_boundary - 1); 3490 seglen = boundary - low; 3491 if (seglen > len) 3492 seglen = len; 3493 3494 flags_next = flags & ~MXGEFW_FLAGS_FIRST; 3495 cum_len_next = cum_len + seglen; 3496 if (mss) { 3497 (req-rdma_count)->rdma_count = 3498 rdma_count + 1; 3499 if (likely(cum_len >= 0)) { 3500 /* payload */ 3501 int next_is_first, chop; 3502 3503 chop = (cum_len_next > mss); 3504 cum_len_next = 3505 cum_len_next % mss; 3506 next_is_first = 3507 (cum_len_next == 0); 3508 flags |= chop * 3509 MXGEFW_FLAGS_TSO_CHOP; 3510 flags_next |= next_is_first * 3511 MXGEFW_FLAGS_FIRST; 3512 rdma_count |= 3513 -(chop | next_is_first); 3514 rdma_count += 3515 chop & !next_is_first; 3516 } else if (likely(cum_len_next >= 0)) { 3517 /* header ends */ 3518 int small; 3519 3520 rdma_count = -1; 3521 cum_len_next = 0; 3522 seglen = -cum_len; 3523 small = (mss <= 3524 MXGEFW_SEND_SMALL_SIZE); 3525 flags_next = 3526 MXGEFW_FLAGS_TSO_PLD 3527 | MXGEFW_FLAGS_FIRST 3528 | (small * 3529 MXGEFW_FLAGS_SMALL); 3530 } 3531 } 3532 req->addr_high = high_swapped; 3533 req->addr_low = htonl(low); 3534 req->pseudo_hdr_offset = pseudo_hdr_offset; 3535 req->pad = 0; /* complete solid 16-byte block */ 3536 req->rdma_count = 1; 3537 req->cksum_offset = cksum_offset; 3538 req->length = htons(seglen); 3539 req->flags = flags | ((cum_len & 1) * odd_flag); 3540 if (cksum_offset > seglen) 3541 cksum_offset -= seglen; 3542 else 3543 cksum_offset = 0; 3544 low += seglen; 3545 len -= seglen; 3546 cum_len = cum_len_next; 3547 count++; 3548 rdma_count++; 3549 /* make sure all the segments will fit */ 3550 if (unlikely(count >= max_segs)) { 3551 MYRI10GE_ATOMIC_SLICE_STAT_INC( 3552 xmit_lowbuf); 3553 /* may try a pullup */ 3554 err = EBUSY; 3555 if (try_pullup) 3556 try_pullup = 2; 3557 goto abort_with_handles; 3558 } 3559 req++; 3560 req->flags = 0; 3561 flags = flags_next; 3562 tx_info[count].m = 0; 3563 } 3564 ncookies--; 3565 if (ncookies == 0) 3566 break; 3567 ddi_dma_nextcookie(dma_handle->h, &cookie); 3568 } 3569 } 3570 (req-rdma_count)->rdma_count = (uint8_t)rdma_count; 3571 3572 if (mss) { 3573 do { 3574 req--; 3575 req->flags |= MXGEFW_FLAGS_TSO_LAST; 3576 } while (!(req->flags & (MXGEFW_FLAGS_TSO_CHOP | 3577 MXGEFW_FLAGS_FIRST))); 3578 } 3579 3580 /* calculate tx stats */ 3581 if (mss) { 3582 uint16_t opackets; 3583 int payload; 3584 3585 payload = pkt_size - lso_hdr_size; 3586 opackets = (payload / mss) + ((payload % mss) != 0); 3587 tx_info[0].stat.un.all = 0; 3588 tx_info[0].ostat.opackets = opackets; 3589 tx_info[0].ostat.obytes = (opackets - 1) * lso_hdr_size 3590 + pkt_size; 3591 } else { 3592 myri10ge_tx_stat(&tx_info[0].stat, 3593 (struct ether_header *)(void *)mp->b_rptr, 1, pkt_size); 3594 } 3595 mutex_enter(&tx->lock); 3596 3597 /* check to see if the slots are really there */ 3598 avail = tx->mask - (tx->req - tx->done); 3599 if (unlikely(avail <= count)) { 3600 mutex_exit(&tx->lock); 3601 err = 0; 3602 goto late_stall; 3603 } 3604 3605 myri10ge_send_locked(tx, req_list, tx_info, count); 3606 mutex_exit(&tx->lock); 3607 return (DDI_SUCCESS); 3608 3609 late_stall: 3610 try_pullup = 0; 3611 atomic_add_32(&tx->stall_late, 1); 3612 3613 abort_with_handles: 3614 /* unbind and free handles from previous mblks */ 3615 for (i = 0; i < count; i++) { 3616 bp = tx_info[i].m; 3617 tx_info[i].m = 0; 3618 if (bp) { 3619 dma_handle = tx_info[i].handle; 3620 (void) ddi_dma_unbind_handle(dma_handle->h); 3621 dma_handle->next = handles; 3622 handles = dma_handle; 3623 tx_info[i].handle = NULL; 3624 tx_info[i].m = NULL; 3625 } 3626 } 3627 myri10ge_free_tx_handle_slist(tx, handles); 3628 pullup: 3629 if (try_pullup) { 3630 err = myri10ge_pullup(ss, mp); 3631 if (err != DDI_SUCCESS && try_pullup == 2) { 3632 /* drop */ 3633 MYRI10GE_ATOMIC_SLICE_STAT_INC(xmit_err); 3634 freemsg(mp); 3635 return (0); 3636 } 3637 try_pullup = 0; 3638 goto again; 3639 } 3640 3641 stall: 3642 if (err != 0) { 3643 if (err == EBUSY) { 3644 atomic_add_32(&tx->stall, 1); 3645 } else { 3646 MYRI10GE_ATOMIC_SLICE_STAT_INC(xmit_err); 3647 } 3648 } 3649 return (err); 3650 } 3651 3652 static mblk_t * 3653 myri10ge_send_wrapper(void *arg, mblk_t *mp) 3654 { 3655 struct myri10ge_slice_state *ss = arg; 3656 int err = 0; 3657 mcp_kreq_ether_send_t *req_list; 3658 #if defined(__i386) 3659 /* 3660 * We need about 2.5KB of scratch space to handle transmits. 3661 * i86pc has only 8KB of kernel stack space, so we malloc the 3662 * scratch space there rather than keeping it on the stack. 3663 */ 3664 size_t req_size, tx_info_size; 3665 struct myri10ge_tx_buffer_state *tx_info; 3666 caddr_t req_bytes; 3667 3668 req_size = sizeof (*req_list) * (MYRI10GE_MAX_SEND_DESC_TSO + 4) 3669 + 8; 3670 req_bytes = kmem_alloc(req_size, KM_SLEEP); 3671 tx_info_size = sizeof (*tx_info) * (MYRI10GE_MAX_SEND_DESC_TSO + 1); 3672 tx_info = kmem_alloc(tx_info_size, KM_SLEEP); 3673 #else 3674 char req_bytes[sizeof (*req_list) * (MYRI10GE_MAX_SEND_DESC_TSO + 4) 3675 + 8]; 3676 struct myri10ge_tx_buffer_state tx_info[MYRI10GE_MAX_SEND_DESC_TSO + 1]; 3677 #endif 3678 3679 /* ensure req_list entries are aligned to 8 bytes */ 3680 req_list = (struct mcp_kreq_ether_send *) 3681 (((unsigned long)req_bytes + 7UL) & ~7UL); 3682 3683 err = myri10ge_send(ss, mp, req_list, tx_info); 3684 3685 #if defined(__i386) 3686 kmem_free(tx_info, tx_info_size); 3687 kmem_free(req_bytes, req_size); 3688 #endif 3689 if (err) 3690 return (mp); 3691 else 3692 return (NULL); 3693 } 3694 3695 static int 3696 myri10ge_addmac(void *arg, const uint8_t *mac_addr) 3697 { 3698 struct myri10ge_priv *mgp = arg; 3699 int err; 3700 3701 if (mac_addr == NULL) 3702 return (EINVAL); 3703 3704 mutex_enter(&mgp->intrlock); 3705 if (mgp->macaddr_cnt) { 3706 mutex_exit(&mgp->intrlock); 3707 return (ENOSPC); 3708 } 3709 err = myri10ge_m_unicst(mgp, mac_addr); 3710 if (!err) 3711 mgp->macaddr_cnt++; 3712 3713 mutex_exit(&mgp->intrlock); 3714 if (err) 3715 return (err); 3716 3717 bcopy(mac_addr, mgp->mac_addr, sizeof (mgp->mac_addr)); 3718 return (0); 3719 } 3720 3721 /*ARGSUSED*/ 3722 static int 3723 myri10ge_remmac(void *arg, const uint8_t *mac_addr) 3724 { 3725 struct myri10ge_priv *mgp = arg; 3726 3727 mutex_enter(&mgp->intrlock); 3728 mgp->macaddr_cnt--; 3729 mutex_exit(&mgp->intrlock); 3730 3731 return (0); 3732 } 3733 3734 /*ARGSUSED*/ 3735 static void 3736 myri10ge_fill_group(void *arg, mac_ring_type_t rtype, const int index, 3737 mac_group_info_t *infop, mac_group_handle_t gh) 3738 { 3739 struct myri10ge_priv *mgp = arg; 3740 3741 if (rtype != MAC_RING_TYPE_RX) 3742 return; 3743 3744 infop->mgi_driver = (mac_group_driver_t)mgp; 3745 infop->mgi_start = NULL; 3746 infop->mgi_stop = NULL; 3747 infop->mgi_addmac = myri10ge_addmac; 3748 infop->mgi_remmac = myri10ge_remmac; 3749 infop->mgi_count = mgp->num_slices; 3750 } 3751 3752 static int 3753 myri10ge_ring_start(mac_ring_driver_t rh, uint64_t mr_gen_num) 3754 { 3755 struct myri10ge_slice_state *ss; 3756 3757 ss = (struct myri10ge_slice_state *)rh; 3758 mutex_enter(&ss->rx_lock); 3759 ss->rx_gen_num = mr_gen_num; 3760 mutex_exit(&ss->rx_lock); 3761 return (0); 3762 } 3763 3764 static int 3765 myri10ge_rx_ring_intr_disable(mac_intr_handle_t intrh) 3766 { 3767 struct myri10ge_slice_state *ss; 3768 3769 ss = (struct myri10ge_slice_state *)intrh; 3770 mutex_enter(&ss->poll_lock); 3771 ss->rx_polling = B_TRUE; 3772 mutex_exit(&ss->poll_lock); 3773 return (0); 3774 } 3775 3776 static int 3777 myri10ge_rx_ring_intr_enable(mac_intr_handle_t intrh) 3778 { 3779 struct myri10ge_slice_state *ss; 3780 3781 ss = (struct myri10ge_slice_state *)intrh; 3782 mutex_enter(&ss->poll_lock); 3783 ss->rx_polling = B_FALSE; 3784 if (ss->rx_token) { 3785 *ss->irq_claim = BE_32(3); 3786 ss->rx_token = 0; 3787 } 3788 mutex_exit(&ss->poll_lock); 3789 return (0); 3790 } 3791 3792 /*ARGSUSED*/ 3793 static void 3794 myri10ge_fill_ring(void *arg, mac_ring_type_t rtype, const int rg_index, 3795 const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh) 3796 { 3797 struct myri10ge_priv *mgp = arg; 3798 struct myri10ge_slice_state *ss; 3799 mac_intr_t *mintr = &infop->mri_intr; 3800 3801 ASSERT((unsigned int)ring_index < mgp->num_slices); 3802 3803 ss = &mgp->ss[ring_index]; 3804 switch (rtype) { 3805 case MAC_RING_TYPE_RX: 3806 ss->rx_rh = rh; 3807 infop->mri_driver = (mac_ring_driver_t)ss; 3808 infop->mri_start = myri10ge_ring_start; 3809 infop->mri_stop = NULL; 3810 infop->mri_poll = myri10ge_poll_rx; 3811 mintr->mi_handle = (mac_intr_handle_t)ss; 3812 mintr->mi_enable = myri10ge_rx_ring_intr_enable; 3813 mintr->mi_disable = myri10ge_rx_ring_intr_disable; 3814 break; 3815 case MAC_RING_TYPE_TX: 3816 ss->tx.rh = rh; 3817 infop->mri_driver = (mac_ring_driver_t)ss; 3818 infop->mri_start = NULL; 3819 infop->mri_stop = NULL; 3820 infop->mri_tx = myri10ge_send_wrapper; 3821 break; 3822 default: 3823 break; 3824 } 3825 } 3826 3827 static void 3828 myri10ge_nic_stat_destroy(struct myri10ge_priv *mgp) 3829 { 3830 if (mgp->ksp_stat == NULL) 3831 return; 3832 3833 kstat_delete(mgp->ksp_stat); 3834 mgp->ksp_stat = NULL; 3835 } 3836 3837 static void 3838 myri10ge_slice_stat_destroy(struct myri10ge_slice_state *ss) 3839 { 3840 if (ss->ksp_stat == NULL) 3841 return; 3842 3843 kstat_delete(ss->ksp_stat); 3844 ss->ksp_stat = NULL; 3845 } 3846 3847 static void 3848 myri10ge_info_destroy(struct myri10ge_priv *mgp) 3849 { 3850 if (mgp->ksp_info == NULL) 3851 return; 3852 3853 kstat_delete(mgp->ksp_info); 3854 mgp->ksp_info = NULL; 3855 } 3856 3857 static int 3858 myri10ge_nic_stat_kstat_update(kstat_t *ksp, int rw) 3859 { 3860 struct myri10ge_nic_stat *ethstat; 3861 struct myri10ge_priv *mgp; 3862 mcp_irq_data_t *fw_stats; 3863 3864 3865 if (rw == KSTAT_WRITE) 3866 return (EACCES); 3867 3868 ethstat = (struct myri10ge_nic_stat *)ksp->ks_data; 3869 mgp = (struct myri10ge_priv *)ksp->ks_private; 3870 fw_stats = mgp->ss[0].fw_stats; 3871 3872 ethstat->dma_read_bw_MBs.value.ul = mgp->read_dma; 3873 ethstat->dma_write_bw_MBs.value.ul = mgp->write_dma; 3874 ethstat->dma_read_write_bw_MBs.value.ul = mgp->read_write_dma; 3875 if (myri10ge_tx_dma_attr.dma_attr_flags & DDI_DMA_FORCE_PHYSICAL) 3876 ethstat->dma_force_physical.value.ul = 1; 3877 else 3878 ethstat->dma_force_physical.value.ul = 0; 3879 ethstat->lanes.value.ul = mgp->pcie_link_width; 3880 ethstat->dropped_bad_crc32.value.ul = 3881 ntohl(fw_stats->dropped_bad_crc32); 3882 ethstat->dropped_bad_phy.value.ul = 3883 ntohl(fw_stats->dropped_bad_phy); 3884 ethstat->dropped_link_error_or_filtered.value.ul = 3885 ntohl(fw_stats->dropped_link_error_or_filtered); 3886 ethstat->dropped_link_overflow.value.ul = 3887 ntohl(fw_stats->dropped_link_overflow); 3888 ethstat->dropped_multicast_filtered.value.ul = 3889 ntohl(fw_stats->dropped_multicast_filtered); 3890 ethstat->dropped_no_big_buffer.value.ul = 3891 ntohl(fw_stats->dropped_no_big_buffer); 3892 ethstat->dropped_no_small_buffer.value.ul = 3893 ntohl(fw_stats->dropped_no_small_buffer); 3894 ethstat->dropped_overrun.value.ul = 3895 ntohl(fw_stats->dropped_overrun); 3896 ethstat->dropped_pause.value.ul = 3897 ntohl(fw_stats->dropped_pause); 3898 ethstat->dropped_runt.value.ul = 3899 ntohl(fw_stats->dropped_runt); 3900 ethstat->link_up.value.ul = 3901 ntohl(fw_stats->link_up); 3902 ethstat->dropped_unicast_filtered.value.ul = 3903 ntohl(fw_stats->dropped_unicast_filtered); 3904 return (0); 3905 } 3906 3907 static int 3908 myri10ge_slice_stat_kstat_update(kstat_t *ksp, int rw) 3909 { 3910 struct myri10ge_slice_stat *ethstat; 3911 struct myri10ge_slice_state *ss; 3912 3913 if (rw == KSTAT_WRITE) 3914 return (EACCES); 3915 3916 ethstat = (struct myri10ge_slice_stat *)ksp->ks_data; 3917 ss = (struct myri10ge_slice_state *)ksp->ks_private; 3918 3919 ethstat->rx_big.value.ul = ss->j_rx_cnt; 3920 ethstat->rx_bigbuf_firmware.value.ul = ss->rx_big.cnt - ss->j_rx_cnt; 3921 ethstat->rx_bigbuf_pool.value.ul = 3922 ss->jpool.num_alloc - ss->jbufs_for_smalls; 3923 ethstat->rx_bigbuf_smalls.value.ul = ss->jbufs_for_smalls; 3924 ethstat->rx_small.value.ul = ss->rx_small.cnt - 3925 (ss->rx_small.mask + 1); 3926 ethstat->tx_done.value.ul = ss->tx.done; 3927 ethstat->tx_req.value.ul = ss->tx.req; 3928 ethstat->tx_activate.value.ul = ss->tx.activate; 3929 ethstat->xmit_sched.value.ul = ss->tx.sched; 3930 ethstat->xmit_stall.value.ul = ss->tx.stall; 3931 ethstat->xmit_stall_early.value.ul = ss->tx.stall_early; 3932 ethstat->xmit_stall_late.value.ul = ss->tx.stall_late; 3933 ethstat->xmit_err.value.ul = MYRI10GE_SLICE_STAT(xmit_err); 3934 return (0); 3935 } 3936 3937 static int 3938 myri10ge_info_kstat_update(kstat_t *ksp, int rw) 3939 { 3940 struct myri10ge_info *info; 3941 struct myri10ge_priv *mgp; 3942 3943 3944 if (rw == KSTAT_WRITE) 3945 return (EACCES); 3946 3947 info = (struct myri10ge_info *)ksp->ks_data; 3948 mgp = (struct myri10ge_priv *)ksp->ks_private; 3949 kstat_named_setstr(&info->driver_version, MYRI10GE_VERSION_STR); 3950 kstat_named_setstr(&info->firmware_version, mgp->fw_version); 3951 kstat_named_setstr(&info->firmware_name, mgp->fw_name); 3952 kstat_named_setstr(&info->interrupt_type, mgp->intr_type); 3953 kstat_named_setstr(&info->product_code, mgp->pc_str); 3954 kstat_named_setstr(&info->serial_number, mgp->sn_str); 3955 return (0); 3956 } 3957 3958 static struct myri10ge_info myri10ge_info_template = { 3959 { "driver_version", KSTAT_DATA_STRING }, 3960 { "firmware_version", KSTAT_DATA_STRING }, 3961 { "firmware_name", KSTAT_DATA_STRING }, 3962 { "interrupt_type", KSTAT_DATA_STRING }, 3963 { "product_code", KSTAT_DATA_STRING }, 3964 { "serial_number", KSTAT_DATA_STRING }, 3965 }; 3966 static kmutex_t myri10ge_info_template_lock; 3967 3968 3969 static int 3970 myri10ge_info_init(struct myri10ge_priv *mgp) 3971 { 3972 struct kstat *ksp; 3973 3974 ksp = kstat_create("myri10ge", ddi_get_instance(mgp->dip), 3975 "myri10ge_info", "net", KSTAT_TYPE_NAMED, 3976 sizeof (myri10ge_info_template) / 3977 sizeof (kstat_named_t), KSTAT_FLAG_VIRTUAL); 3978 if (ksp == NULL) { 3979 cmn_err(CE_WARN, 3980 "%s: myri10ge_info_init: kstat_create failed", mgp->name); 3981 return (DDI_FAILURE); 3982 } 3983 mgp->ksp_info = ksp; 3984 ksp->ks_update = myri10ge_info_kstat_update; 3985 ksp->ks_private = (void *) mgp; 3986 ksp->ks_data = &myri10ge_info_template; 3987 ksp->ks_lock = &myri10ge_info_template_lock; 3988 if (MYRI10GE_VERSION_STR != NULL) 3989 ksp->ks_data_size += strlen(MYRI10GE_VERSION_STR) + 1; 3990 if (mgp->fw_version != NULL) 3991 ksp->ks_data_size += strlen(mgp->fw_version) + 1; 3992 ksp->ks_data_size += strlen(mgp->fw_name) + 1; 3993 ksp->ks_data_size += strlen(mgp->intr_type) + 1; 3994 if (mgp->pc_str != NULL) 3995 ksp->ks_data_size += strlen(mgp->pc_str) + 1; 3996 if (mgp->sn_str != NULL) 3997 ksp->ks_data_size += strlen(mgp->sn_str) + 1; 3998 3999 kstat_install(ksp); 4000 return (DDI_SUCCESS); 4001 } 4002 4003 4004 static int 4005 myri10ge_nic_stat_init(struct myri10ge_priv *mgp) 4006 { 4007 struct kstat *ksp; 4008 struct myri10ge_nic_stat *ethstat; 4009 4010 ksp = kstat_create("myri10ge", ddi_get_instance(mgp->dip), 4011 "myri10ge_nic_stats", "net", KSTAT_TYPE_NAMED, 4012 sizeof (*ethstat) / sizeof (kstat_named_t), 0); 4013 if (ksp == NULL) { 4014 cmn_err(CE_WARN, 4015 "%s: myri10ge_stat_init: kstat_create failed", mgp->name); 4016 return (DDI_FAILURE); 4017 } 4018 mgp->ksp_stat = ksp; 4019 ethstat = (struct myri10ge_nic_stat *)(ksp->ks_data); 4020 4021 kstat_named_init(ðstat->dma_read_bw_MBs, 4022 "dma_read_bw_MBs", KSTAT_DATA_ULONG); 4023 kstat_named_init(ðstat->dma_write_bw_MBs, 4024 "dma_write_bw_MBs", KSTAT_DATA_ULONG); 4025 kstat_named_init(ðstat->dma_read_write_bw_MBs, 4026 "dma_read_write_bw_MBs", KSTAT_DATA_ULONG); 4027 kstat_named_init(ðstat->dma_force_physical, 4028 "dma_force_physical", KSTAT_DATA_ULONG); 4029 kstat_named_init(ðstat->lanes, 4030 "lanes", KSTAT_DATA_ULONG); 4031 kstat_named_init(ðstat->dropped_bad_crc32, 4032 "dropped_bad_crc32", KSTAT_DATA_ULONG); 4033 kstat_named_init(ðstat->dropped_bad_phy, 4034 "dropped_bad_phy", KSTAT_DATA_ULONG); 4035 kstat_named_init(ðstat->dropped_link_error_or_filtered, 4036 "dropped_link_error_or_filtered", KSTAT_DATA_ULONG); 4037 kstat_named_init(ðstat->dropped_link_overflow, 4038 "dropped_link_overflow", KSTAT_DATA_ULONG); 4039 kstat_named_init(ðstat->dropped_multicast_filtered, 4040 "dropped_multicast_filtered", KSTAT_DATA_ULONG); 4041 kstat_named_init(ðstat->dropped_no_big_buffer, 4042 "dropped_no_big_buffer", KSTAT_DATA_ULONG); 4043 kstat_named_init(ðstat->dropped_no_small_buffer, 4044 "dropped_no_small_buffer", KSTAT_DATA_ULONG); 4045 kstat_named_init(ðstat->dropped_overrun, 4046 "dropped_overrun", KSTAT_DATA_ULONG); 4047 kstat_named_init(ðstat->dropped_pause, 4048 "dropped_pause", KSTAT_DATA_ULONG); 4049 kstat_named_init(ðstat->dropped_runt, 4050 "dropped_runt", KSTAT_DATA_ULONG); 4051 kstat_named_init(ðstat->dropped_unicast_filtered, 4052 "dropped_unicast_filtered", KSTAT_DATA_ULONG); 4053 kstat_named_init(ðstat->dropped_runt, "dropped_runt", 4054 KSTAT_DATA_ULONG); 4055 kstat_named_init(ðstat->link_up, "link_up", KSTAT_DATA_ULONG); 4056 kstat_named_init(ðstat->link_changes, "link_changes", 4057 KSTAT_DATA_ULONG); 4058 ksp->ks_update = myri10ge_nic_stat_kstat_update; 4059 ksp->ks_private = (void *) mgp; 4060 kstat_install(ksp); 4061 return (DDI_SUCCESS); 4062 } 4063 4064 static int 4065 myri10ge_slice_stat_init(struct myri10ge_slice_state *ss) 4066 { 4067 struct myri10ge_priv *mgp = ss->mgp; 4068 struct kstat *ksp; 4069 struct myri10ge_slice_stat *ethstat; 4070 int instance; 4071 4072 /* 4073 * fake an instance so that the same slice numbers from 4074 * different instances do not collide 4075 */ 4076 instance = (ddi_get_instance(mgp->dip) * 1000) + (int)(ss - mgp->ss); 4077 ksp = kstat_create("myri10ge", instance, 4078 "myri10ge_slice_stats", "net", KSTAT_TYPE_NAMED, 4079 sizeof (*ethstat) / sizeof (kstat_named_t), 0); 4080 if (ksp == NULL) { 4081 cmn_err(CE_WARN, 4082 "%s: myri10ge_stat_init: kstat_create failed", mgp->name); 4083 return (DDI_FAILURE); 4084 } 4085 ss->ksp_stat = ksp; 4086 ethstat = (struct myri10ge_slice_stat *)(ksp->ks_data); 4087 kstat_named_init(ðstat->lro_bad_csum, "lro_bad_csum", 4088 KSTAT_DATA_ULONG); 4089 kstat_named_init(ðstat->lro_flushed, "lro_flushed", 4090 KSTAT_DATA_ULONG); 4091 kstat_named_init(ðstat->lro_queued, "lro_queued", 4092 KSTAT_DATA_ULONG); 4093 kstat_named_init(ðstat->rx_bigbuf_firmware, "rx_bigbuf_firmware", 4094 KSTAT_DATA_ULONG); 4095 kstat_named_init(ðstat->rx_bigbuf_pool, "rx_bigbuf_pool", 4096 KSTAT_DATA_ULONG); 4097 kstat_named_init(ðstat->rx_bigbuf_smalls, "rx_bigbuf_smalls", 4098 KSTAT_DATA_ULONG); 4099 kstat_named_init(ðstat->rx_copy, "rx_copy", 4100 KSTAT_DATA_ULONG); 4101 kstat_named_init(ðstat->rx_big_nobuf, "rx_big_nobuf", 4102 KSTAT_DATA_ULONG); 4103 kstat_named_init(ðstat->rx_small_nobuf, "rx_small_nobuf", 4104 KSTAT_DATA_ULONG); 4105 kstat_named_init(ðstat->xmit_zero_len, "xmit_zero_len", 4106 KSTAT_DATA_ULONG); 4107 kstat_named_init(ðstat->xmit_pullup, "xmit_pullup", 4108 KSTAT_DATA_ULONG); 4109 kstat_named_init(ðstat->xmit_pullup_first, "xmit_pullup_first", 4110 KSTAT_DATA_ULONG); 4111 kstat_named_init(ðstat->xmit_lowbuf, "xmit_lowbuf", 4112 KSTAT_DATA_ULONG); 4113 kstat_named_init(ðstat->xmit_lsobadflags, "xmit_lsobadflags", 4114 KSTAT_DATA_ULONG); 4115 kstat_named_init(ðstat->xmit_sched, "xmit_sched", 4116 KSTAT_DATA_ULONG); 4117 kstat_named_init(ðstat->xmit_stall, "xmit_stall", 4118 KSTAT_DATA_ULONG); 4119 kstat_named_init(ðstat->xmit_stall_early, "xmit_stall_early", 4120 KSTAT_DATA_ULONG); 4121 kstat_named_init(ðstat->xmit_stall_late, "xmit_stall_late", 4122 KSTAT_DATA_ULONG); 4123 kstat_named_init(ðstat->xmit_err, "xmit_err", 4124 KSTAT_DATA_ULONG); 4125 kstat_named_init(ðstat->tx_req, "tx_req", 4126 KSTAT_DATA_ULONG); 4127 kstat_named_init(ðstat->tx_activate, "tx_activate", 4128 KSTAT_DATA_ULONG); 4129 kstat_named_init(ðstat->tx_done, "tx_done", 4130 KSTAT_DATA_ULONG); 4131 kstat_named_init(ðstat->tx_handles_alloced, "tx_handles_alloced", 4132 KSTAT_DATA_ULONG); 4133 kstat_named_init(ðstat->rx_big, "rx_big", 4134 KSTAT_DATA_ULONG); 4135 kstat_named_init(ðstat->rx_small, "rx_small", 4136 KSTAT_DATA_ULONG); 4137 ksp->ks_update = myri10ge_slice_stat_kstat_update; 4138 ksp->ks_private = (void *) ss; 4139 kstat_install(ksp); 4140 return (DDI_SUCCESS); 4141 } 4142 4143 4144 4145 #if #cpu(i386) || defined __i386 || defined i386 || \ 4146 defined __i386__ || #cpu(x86_64) || defined __x86_64__ 4147 4148 #include <vm/hat.h> 4149 void *device_arena_alloc(size_t size, int vm_flag); 4150 void device_arena_free(void *vaddr, size_t size); 4151 4152 static void 4153 myri10ge_enable_nvidia_ecrc(struct myri10ge_priv *mgp) 4154 { 4155 dev_info_t *parent_dip; 4156 ddi_acc_handle_t handle; 4157 unsigned long bus_number, dev_number, func_number; 4158 unsigned long cfg_pa, paddr, base, pgoffset; 4159 char *cvaddr, *ptr; 4160 uint32_t *ptr32; 4161 int retval = DDI_FAILURE; 4162 int dontcare; 4163 uint16_t read_vid, read_did, vendor_id, device_id; 4164 4165 if (!myri10ge_nvidia_ecrc_enable) 4166 return; 4167 4168 parent_dip = ddi_get_parent(mgp->dip); 4169 if (parent_dip == NULL) { 4170 cmn_err(CE_WARN, "%s: I'm an orphan?", mgp->name); 4171 return; 4172 } 4173 4174 if (pci_config_setup(parent_dip, &handle) != DDI_SUCCESS) { 4175 cmn_err(CE_WARN, 4176 "%s: Could not access my parent's registers", mgp->name); 4177 return; 4178 } 4179 4180 vendor_id = pci_config_get16(handle, PCI_CONF_VENID); 4181 device_id = pci_config_get16(handle, PCI_CONF_DEVID); 4182 pci_config_teardown(&handle); 4183 4184 if (myri10ge_verbose) { 4185 unsigned long bus_number, dev_number, func_number; 4186 int reg_set, span; 4187 (void) myri10ge_reg_set(parent_dip, ®_set, &span, 4188 &bus_number, &dev_number, &func_number); 4189 if (myri10ge_verbose) 4190 printf("%s: parent at %ld:%ld:%ld\n", mgp->name, 4191 bus_number, dev_number, func_number); 4192 } 4193 4194 if (vendor_id != 0x10de) 4195 return; 4196 4197 if (device_id != 0x005d /* CK804 */ && 4198 (device_id < 0x374 || device_id > 0x378) /* MCP55 */) { 4199 return; 4200 } 4201 (void) myri10ge_reg_set(parent_dip, &dontcare, &dontcare, 4202 &bus_number, &dev_number, &func_number); 4203 4204 for (cfg_pa = 0xf0000000UL; 4205 retval != DDI_SUCCESS && cfg_pa >= 0xe0000000UL; 4206 cfg_pa -= 0x10000000UL) { 4207 /* find the config space address for the nvidia bridge */ 4208 paddr = (cfg_pa + bus_number * 0x00100000UL + 4209 (dev_number * 8 + func_number) * 0x00001000UL); 4210 4211 base = paddr & (~MMU_PAGEOFFSET); 4212 pgoffset = paddr & MMU_PAGEOFFSET; 4213 4214 /* map it into the kernel */ 4215 cvaddr = device_arena_alloc(ptob(1), VM_NOSLEEP); 4216 if (cvaddr == NULL) 4217 cmn_err(CE_WARN, "%s: failed to map nf4: cvaddr\n", 4218 mgp->name); 4219 4220 hat_devload(kas.a_hat, cvaddr, mmu_ptob(1), mmu_btop(base), 4221 PROT_WRITE|HAT_STRICTORDER, HAT_LOAD_LOCK); 4222 4223 ptr = cvaddr + pgoffset; 4224 read_vid = *(uint16_t *)(void *)(ptr + PCI_CONF_VENID); 4225 read_did = *(uint16_t *)(void *)(ptr + PCI_CONF_DEVID); 4226 if (vendor_id == read_did || device_id == read_did) { 4227 ptr32 = (uint32_t *)(void *)(ptr + 0x178); 4228 if (myri10ge_verbose) 4229 printf("%s: Enabling ECRC on upstream " 4230 "Nvidia bridge (0x%x:0x%x) " 4231 "at %ld:%ld:%ld\n", mgp->name, 4232 read_vid, read_did, bus_number, 4233 dev_number, func_number); 4234 *ptr32 |= 0x40; 4235 retval = DDI_SUCCESS; 4236 } 4237 hat_unload(kas.a_hat, cvaddr, ptob(1), HAT_UNLOAD_UNLOCK); 4238 device_arena_free(cvaddr, ptob(1)); 4239 } 4240 } 4241 4242 #else 4243 /*ARGSUSED*/ 4244 static void 4245 myri10ge_enable_nvidia_ecrc(struct myri10ge_priv *mgp) 4246 { 4247 } 4248 #endif /* i386 */ 4249 4250 4251 /* 4252 * The Lanai Z8E PCI-E interface achieves higher Read-DMA throughput 4253 * when the PCI-E Completion packets are aligned on an 8-byte 4254 * boundary. Some PCI-E chip sets always align Completion packets; on 4255 * the ones that do not, the alignment can be enforced by enabling 4256 * ECRC generation (if supported). 4257 * 4258 * When PCI-E Completion packets are not aligned, it is actually more 4259 * efficient to limit Read-DMA transactions to 2KB, rather than 4KB. 4260 * 4261 * If the driver can neither enable ECRC nor verify that it has 4262 * already been enabled, then it must use a firmware image which works 4263 * around unaligned completion packets (ethp_z8e.dat), and it should 4264 * also ensure that it never gives the device a Read-DMA which is 4265 * larger than 2KB by setting the tx.boundary to 2KB. If ECRC is 4266 * enabled, then the driver should use the aligned (eth_z8e.dat) 4267 * firmware image, and set tx.boundary to 4KB. 4268 */ 4269 4270 4271 static int 4272 myri10ge_firmware_probe(struct myri10ge_priv *mgp) 4273 { 4274 int status; 4275 4276 mgp->tx_boundary = 4096; 4277 /* 4278 * Verify the max read request size was set to 4KB 4279 * before trying the test with 4KB. 4280 */ 4281 if (mgp->max_read_request_4k == 0) 4282 mgp->tx_boundary = 2048; 4283 /* 4284 * load the optimized firmware which assumes aligned PCIe 4285 * completions in order to see if it works on this host. 4286 */ 4287 4288 mgp->fw_name = "rss_eth_z8e"; 4289 mgp->eth_z8e = (unsigned char *)rss_eth_z8e; 4290 mgp->eth_z8e_length = rss_eth_z8e_length; 4291 4292 status = myri10ge_load_firmware(mgp); 4293 if (status != 0) { 4294 return (status); 4295 } 4296 /* 4297 * Enable ECRC if possible 4298 */ 4299 myri10ge_enable_nvidia_ecrc(mgp); 4300 4301 /* 4302 * Run a DMA test which watches for unaligned completions and 4303 * aborts on the first one seen. 4304 */ 4305 status = myri10ge_dma_test(mgp, MXGEFW_CMD_UNALIGNED_TEST); 4306 if (status == 0) 4307 return (0); /* keep the aligned firmware */ 4308 4309 if (status != E2BIG) 4310 cmn_err(CE_WARN, "%s: DMA test failed: %d\n", 4311 mgp->name, status); 4312 if (status == ENOSYS) 4313 cmn_err(CE_WARN, "%s: Falling back to ethp! " 4314 "Please install up to date fw\n", mgp->name); 4315 return (status); 4316 } 4317 4318 static int 4319 myri10ge_select_firmware(struct myri10ge_priv *mgp) 4320 { 4321 int aligned; 4322 4323 aligned = 0; 4324 4325 if (myri10ge_force_firmware == 1) { 4326 if (myri10ge_verbose) 4327 printf("%s: Assuming aligned completions (forced)\n", 4328 mgp->name); 4329 aligned = 1; 4330 goto done; 4331 } 4332 4333 if (myri10ge_force_firmware == 2) { 4334 if (myri10ge_verbose) 4335 printf("%s: Assuming unaligned completions (forced)\n", 4336 mgp->name); 4337 aligned = 0; 4338 goto done; 4339 } 4340 4341 /* If the width is less than 8, we may used the aligned firmware */ 4342 if (mgp->pcie_link_width != 0 && mgp->pcie_link_width < 8) { 4343 cmn_err(CE_WARN, "!%s: PCIe link running at x%d\n", 4344 mgp->name, mgp->pcie_link_width); 4345 aligned = 1; 4346 goto done; 4347 } 4348 4349 if (0 == myri10ge_firmware_probe(mgp)) 4350 return (0); /* keep optimized firmware */ 4351 4352 done: 4353 if (aligned) { 4354 mgp->fw_name = "rss_eth_z8e"; 4355 mgp->eth_z8e = (unsigned char *)rss_eth_z8e; 4356 mgp->eth_z8e_length = rss_eth_z8e_length; 4357 mgp->tx_boundary = 4096; 4358 } else { 4359 mgp->fw_name = "rss_ethp_z8e"; 4360 mgp->eth_z8e = (unsigned char *)rss_ethp_z8e; 4361 mgp->eth_z8e_length = rss_ethp_z8e_length; 4362 mgp->tx_boundary = 2048; 4363 } 4364 4365 return (myri10ge_load_firmware(mgp)); 4366 } 4367 4368 static int 4369 myri10ge_add_intrs(struct myri10ge_priv *mgp, int add_handler) 4370 { 4371 dev_info_t *devinfo = mgp->dip; 4372 int count, avail, actual, intr_types; 4373 int x, y, rc, inum = 0; 4374 4375 4376 rc = ddi_intr_get_supported_types(devinfo, &intr_types); 4377 if (rc != DDI_SUCCESS) { 4378 cmn_err(CE_WARN, 4379 "!%s: ddi_intr_get_nintrs() failure, rc = %d\n", mgp->name, 4380 rc); 4381 return (DDI_FAILURE); 4382 } 4383 4384 if (!myri10ge_use_msi) 4385 intr_types &= ~DDI_INTR_TYPE_MSI; 4386 if (!myri10ge_use_msix) 4387 intr_types &= ~DDI_INTR_TYPE_MSIX; 4388 4389 if (intr_types & DDI_INTR_TYPE_MSIX) { 4390 mgp->ddi_intr_type = DDI_INTR_TYPE_MSIX; 4391 mgp->intr_type = "MSI-X"; 4392 } else if (intr_types & DDI_INTR_TYPE_MSI) { 4393 mgp->ddi_intr_type = DDI_INTR_TYPE_MSI; 4394 mgp->intr_type = "MSI"; 4395 } else { 4396 mgp->ddi_intr_type = DDI_INTR_TYPE_FIXED; 4397 mgp->intr_type = "Legacy"; 4398 } 4399 /* Get number of interrupts */ 4400 rc = ddi_intr_get_nintrs(devinfo, mgp->ddi_intr_type, &count); 4401 if ((rc != DDI_SUCCESS) || (count == 0)) { 4402 cmn_err(CE_WARN, "%s: ddi_intr_get_nintrs() failure, rc: %d, " 4403 "count: %d", mgp->name, rc, count); 4404 4405 return (DDI_FAILURE); 4406 } 4407 4408 /* Get number of available interrupts */ 4409 rc = ddi_intr_get_navail(devinfo, mgp->ddi_intr_type, &avail); 4410 if ((rc != DDI_SUCCESS) || (avail == 0)) { 4411 cmn_err(CE_WARN, "%s: ddi_intr_get_navail() failure, " 4412 "rc: %d, avail: %d\n", mgp->name, rc, avail); 4413 return (DDI_FAILURE); 4414 } 4415 if (avail < count) { 4416 cmn_err(CE_NOTE, 4417 "!%s: nintrs() returned %d, navail returned %d", 4418 mgp->name, count, avail); 4419 count = avail; 4420 } 4421 4422 if (count < mgp->num_slices) 4423 return (DDI_FAILURE); 4424 4425 if (count > mgp->num_slices) 4426 count = mgp->num_slices; 4427 4428 /* Allocate memory for MSI interrupts */ 4429 mgp->intr_size = count * sizeof (ddi_intr_handle_t); 4430 mgp->htable = kmem_alloc(mgp->intr_size, KM_SLEEP); 4431 4432 rc = ddi_intr_alloc(devinfo, mgp->htable, mgp->ddi_intr_type, inum, 4433 count, &actual, DDI_INTR_ALLOC_NORMAL); 4434 4435 if ((rc != DDI_SUCCESS) || (actual == 0)) { 4436 cmn_err(CE_WARN, "%s: ddi_intr_alloc() failed: %d", 4437 mgp->name, rc); 4438 4439 kmem_free(mgp->htable, mgp->intr_size); 4440 mgp->htable = NULL; 4441 return (DDI_FAILURE); 4442 } 4443 4444 if ((actual < count) && myri10ge_verbose) { 4445 cmn_err(CE_NOTE, "%s: got %d/%d slices", 4446 mgp->name, actual, count); 4447 } 4448 4449 mgp->intr_cnt = actual; 4450 4451 /* 4452 * Get priority for first irq, assume remaining are all the same 4453 */ 4454 if (ddi_intr_get_pri(mgp->htable[0], &mgp->intr_pri) 4455 != DDI_SUCCESS) { 4456 cmn_err(CE_WARN, "%s: ddi_intr_get_pri() failed", mgp->name); 4457 4458 /* Free already allocated intr */ 4459 for (y = 0; y < actual; y++) { 4460 (void) ddi_intr_free(mgp->htable[y]); 4461 } 4462 4463 kmem_free(mgp->htable, mgp->intr_size); 4464 mgp->htable = NULL; 4465 return (DDI_FAILURE); 4466 } 4467 4468 mgp->icookie = (void *)(uintptr_t)mgp->intr_pri; 4469 4470 if (!add_handler) 4471 return (DDI_SUCCESS); 4472 4473 /* Call ddi_intr_add_handler() */ 4474 for (x = 0; x < actual; x++) { 4475 if (ddi_intr_add_handler(mgp->htable[x], myri10ge_intr, 4476 (caddr_t)&mgp->ss[x], NULL) != DDI_SUCCESS) { 4477 cmn_err(CE_WARN, "%s: ddi_intr_add_handler() failed", 4478 mgp->name); 4479 4480 /* Free already allocated intr */ 4481 for (y = 0; y < actual; y++) { 4482 (void) ddi_intr_free(mgp->htable[y]); 4483 } 4484 4485 kmem_free(mgp->htable, mgp->intr_size); 4486 mgp->htable = NULL; 4487 return (DDI_FAILURE); 4488 } 4489 } 4490 4491 (void) ddi_intr_get_cap(mgp->htable[0], &mgp->intr_cap); 4492 if (mgp->intr_cap & DDI_INTR_FLAG_BLOCK) { 4493 /* Call ddi_intr_block_enable() for MSI */ 4494 (void) ddi_intr_block_enable(mgp->htable, mgp->intr_cnt); 4495 } else { 4496 /* Call ddi_intr_enable() for MSI non block enable */ 4497 for (x = 0; x < mgp->intr_cnt; x++) { 4498 (void) ddi_intr_enable(mgp->htable[x]); 4499 } 4500 } 4501 4502 return (DDI_SUCCESS); 4503 } 4504 4505 static void 4506 myri10ge_rem_intrs(struct myri10ge_priv *mgp, int handler_installed) 4507 { 4508 int x, err; 4509 4510 /* Disable all interrupts */ 4511 if (handler_installed) { 4512 if (mgp->intr_cap & DDI_INTR_FLAG_BLOCK) { 4513 /* Call ddi_intr_block_disable() */ 4514 (void) ddi_intr_block_disable(mgp->htable, 4515 mgp->intr_cnt); 4516 } else { 4517 for (x = 0; x < mgp->intr_cnt; x++) { 4518 (void) ddi_intr_disable(mgp->htable[x]); 4519 } 4520 } 4521 } 4522 4523 for (x = 0; x < mgp->intr_cnt; x++) { 4524 if (handler_installed) { 4525 /* Call ddi_intr_remove_handler() */ 4526 err = ddi_intr_remove_handler(mgp->htable[x]); 4527 if (err != DDI_SUCCESS) { 4528 cmn_err(CE_WARN, 4529 "%s: ddi_intr_remove_handler for" 4530 "vec %d returned %d\n", mgp->name, 4531 x, err); 4532 } 4533 } 4534 err = ddi_intr_free(mgp->htable[x]); 4535 if (err != DDI_SUCCESS) { 4536 cmn_err(CE_WARN, 4537 "%s: ddi_intr_free for vec %d returned %d\n", 4538 mgp->name, x, err); 4539 } 4540 } 4541 kmem_free(mgp->htable, mgp->intr_size); 4542 mgp->htable = NULL; 4543 } 4544 4545 static void 4546 myri10ge_test_physical(dev_info_t *dip) 4547 { 4548 ddi_dma_handle_t handle; 4549 struct myri10ge_dma_stuff dma; 4550 void *addr; 4551 int err; 4552 4553 /* test #1, sufficient for older sparc systems */ 4554 myri10ge_tx_dma_attr.dma_attr_flags = DDI_DMA_FORCE_PHYSICAL; 4555 err = ddi_dma_alloc_handle(dip, &myri10ge_tx_dma_attr, 4556 DDI_DMA_DONTWAIT, NULL, &handle); 4557 if (err == DDI_DMA_BADATTR) 4558 goto fail; 4559 ddi_dma_free_handle(&handle); 4560 4561 /* test #2, required on Olympis where the bind is what fails */ 4562 addr = myri10ge_dma_alloc(dip, 128, &myri10ge_tx_dma_attr, 4563 &myri10ge_dev_access_attr, DDI_DMA_STREAMING, 4564 DDI_DMA_WRITE|DDI_DMA_STREAMING, &dma, 0, DDI_DMA_DONTWAIT); 4565 if (addr == NULL) 4566 goto fail; 4567 myri10ge_dma_free(&dma); 4568 return; 4569 4570 fail: 4571 if (myri10ge_verbose) 4572 printf("myri10ge%d: DDI_DMA_FORCE_PHYSICAL failed, " 4573 "using IOMMU\n", ddi_get_instance(dip)); 4574 4575 myri10ge_tx_dma_attr.dma_attr_flags &= ~DDI_DMA_FORCE_PHYSICAL; 4576 } 4577 4578 static void 4579 myri10ge_get_props(dev_info_t *dip) 4580 { 4581 4582 myri10ge_flow_control = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4583 "myri10ge_flow_control", myri10ge_flow_control); 4584 4585 myri10ge_intr_coal_delay = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4586 "myri10ge_intr_coal_delay", myri10ge_intr_coal_delay); 4587 4588 #if #cpu(i386) || defined __i386 || defined i386 || \ 4589 defined __i386__ || #cpu(x86_64) || defined __x86_64__ 4590 myri10ge_nvidia_ecrc_enable = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4591 "myri10ge_nvidia_ecrc_enable", 1); 4592 #endif 4593 4594 4595 myri10ge_use_msi = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4596 "myri10ge_use_msi", myri10ge_use_msi); 4597 4598 myri10ge_deassert_wait = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4599 "myri10ge_deassert_wait", myri10ge_deassert_wait); 4600 4601 myri10ge_verbose = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4602 "myri10ge_verbose", myri10ge_verbose); 4603 4604 myri10ge_tx_copylen = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4605 "myri10ge_tx_copylen", myri10ge_tx_copylen); 4606 4607 if (myri10ge_tx_copylen < 60) { 4608 cmn_err(CE_WARN, 4609 "myri10ge_tx_copylen must be >= 60 bytes\n"); 4610 myri10ge_tx_copylen = 60; 4611 } 4612 4613 myri10ge_mtu_override = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4614 "myri10ge_mtu_override", myri10ge_mtu_override); 4615 4616 if (myri10ge_mtu_override >= 1500 && myri10ge_mtu_override <= 9000) 4617 myri10ge_mtu = myri10ge_mtu_override + 4618 sizeof (struct ether_header) + MXGEFW_PAD + VLAN_TAGSZ; 4619 else if (myri10ge_mtu_override != 0) { 4620 cmn_err(CE_WARN, 4621 "myri10ge_mtu_override must be between 1500 and " 4622 "9000 bytes\n"); 4623 } 4624 4625 myri10ge_bigbufs_initial = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4626 "myri10ge_bigbufs_initial", myri10ge_bigbufs_initial); 4627 myri10ge_bigbufs_max = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4628 "myri10ge_bigbufs_max", myri10ge_bigbufs_max); 4629 4630 myri10ge_watchdog_reset = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4631 "myri10ge_watchdog_reset", myri10ge_watchdog_reset); 4632 4633 if (myri10ge_bigbufs_initial < 128) { 4634 cmn_err(CE_WARN, 4635 "myri10ge_bigbufs_initial be at least 128\n"); 4636 myri10ge_bigbufs_initial = 128; 4637 } 4638 if (myri10ge_bigbufs_max < 128) { 4639 cmn_err(CE_WARN, 4640 "myri10ge_bigbufs_max be at least 128\n"); 4641 myri10ge_bigbufs_max = 128; 4642 } 4643 4644 if (myri10ge_bigbufs_max < myri10ge_bigbufs_initial) { 4645 cmn_err(CE_WARN, 4646 "myri10ge_bigbufs_max must be >= " 4647 "myri10ge_bigbufs_initial\n"); 4648 myri10ge_bigbufs_max = myri10ge_bigbufs_initial; 4649 } 4650 4651 myri10ge_force_firmware = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4652 "myri10ge_force_firmware", myri10ge_force_firmware); 4653 4654 myri10ge_max_slices = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4655 "myri10ge_max_slices", myri10ge_max_slices); 4656 4657 myri10ge_use_msix = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4658 "myri10ge_use_msix", myri10ge_use_msix); 4659 4660 myri10ge_rss_hash = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4661 "myri10ge_rss_hash", myri10ge_rss_hash); 4662 4663 if (myri10ge_rss_hash > MXGEFW_RSS_HASH_TYPE_MAX || 4664 myri10ge_rss_hash < MXGEFW_RSS_HASH_TYPE_IPV4) { 4665 cmn_err(CE_WARN, "myri10ge: Illegal rssh hash type %d\n", 4666 myri10ge_rss_hash); 4667 myri10ge_rss_hash = MXGEFW_RSS_HASH_TYPE_SRC_DST_PORT; 4668 } 4669 myri10ge_lro = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4670 "myri10ge_lro", myri10ge_lro); 4671 myri10ge_lro_cnt = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4672 "myri10ge_lro_cnt", myri10ge_lro_cnt); 4673 myri10ge_lro_max_aggr = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4674 "myri10ge_lro_max_aggr", myri10ge_lro_max_aggr); 4675 myri10ge_tx_hash = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4676 "myri10ge_tx_hash", myri10ge_tx_hash); 4677 myri10ge_use_lso = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4678 "myri10ge_use_lso", myri10ge_use_lso); 4679 myri10ge_lso_copy = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4680 "myri10ge_lso_copy", myri10ge_lso_copy); 4681 myri10ge_tx_handles_initial = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4682 "myri10ge_tx_handles_initial", myri10ge_tx_handles_initial); 4683 myri10ge_small_bytes = ddi_prop_get_int(DDI_DEV_T_ANY, dip, 0, 4684 "myri10ge_small_bytes", myri10ge_small_bytes); 4685 if ((myri10ge_small_bytes + MXGEFW_PAD) & (128 -1)) { 4686 cmn_err(CE_WARN, "myri10ge: myri10ge_small_bytes (%d)\n", 4687 myri10ge_small_bytes); 4688 cmn_err(CE_WARN, "must be aligned on 128b bndry -2\n"); 4689 myri10ge_small_bytes += 128; 4690 myri10ge_small_bytes &= ~(128 -1); 4691 myri10ge_small_bytes -= MXGEFW_PAD; 4692 cmn_err(CE_WARN, "rounded up to %d\n", 4693 myri10ge_small_bytes); 4694 4695 myri10ge_rss_hash = MXGEFW_RSS_HASH_TYPE_SRC_DST_PORT; 4696 } 4697 } 4698 4699 #ifndef PCI_EXP_LNKSTA 4700 #define PCI_EXP_LNKSTA 18 4701 #endif 4702 4703 static int 4704 myri10ge_find_cap(ddi_acc_handle_t handle, uint8_t *capptr, uint8_t capid) 4705 { 4706 uint16_t status; 4707 uint8_t ptr; 4708 4709 /* check to see if we have capabilities */ 4710 status = pci_config_get16(handle, PCI_CONF_STAT); 4711 if (!(status & PCI_STAT_CAP)) { 4712 cmn_err(CE_WARN, "PCI_STAT_CAP not found\n"); 4713 return (ENXIO); 4714 } 4715 4716 ptr = pci_config_get8(handle, PCI_CONF_CAP_PTR); 4717 4718 /* Walk the capabilities list, looking for a PCI Express cap */ 4719 while (ptr != PCI_CAP_NEXT_PTR_NULL) { 4720 if (pci_config_get8(handle, ptr + PCI_CAP_ID) == capid) 4721 break; 4722 ptr = pci_config_get8(handle, ptr + PCI_CAP_NEXT_PTR); 4723 } 4724 if (ptr < 64) { 4725 cmn_err(CE_WARN, "Bad capability offset %d\n", ptr); 4726 return (ENXIO); 4727 } 4728 *capptr = ptr; 4729 return (0); 4730 } 4731 4732 static int 4733 myri10ge_set_max_readreq(ddi_acc_handle_t handle) 4734 { 4735 int err; 4736 uint16_t val; 4737 uint8_t ptr; 4738 4739 err = myri10ge_find_cap(handle, &ptr, PCI_CAP_ID_PCI_E); 4740 if (err != 0) { 4741 cmn_err(CE_WARN, "could not find PCIe cap\n"); 4742 return (ENXIO); 4743 } 4744 4745 /* set max read req to 4096 */ 4746 val = pci_config_get16(handle, ptr + PCIE_DEVCTL); 4747 val = (val & ~PCIE_DEVCTL_MAX_READ_REQ_MASK) | 4748 PCIE_DEVCTL_MAX_READ_REQ_4096; 4749 pci_config_put16(handle, ptr + PCIE_DEVCTL, val); 4750 val = pci_config_get16(handle, ptr + PCIE_DEVCTL); 4751 if ((val & (PCIE_DEVCTL_MAX_READ_REQ_4096)) != 4752 PCIE_DEVCTL_MAX_READ_REQ_4096) { 4753 cmn_err(CE_WARN, "could not set max read req (%x)\n", val); 4754 return (EINVAL); 4755 } 4756 return (0); 4757 } 4758 4759 static int 4760 myri10ge_read_pcie_link_width(ddi_acc_handle_t handle, int *link) 4761 { 4762 int err; 4763 uint16_t val; 4764 uint8_t ptr; 4765 4766 err = myri10ge_find_cap(handle, &ptr, PCI_CAP_ID_PCI_E); 4767 if (err != 0) { 4768 cmn_err(CE_WARN, "could not set max read req\n"); 4769 return (ENXIO); 4770 } 4771 4772 /* read link width */ 4773 val = pci_config_get16(handle, ptr + PCIE_LINKSTS); 4774 val &= PCIE_LINKSTS_NEG_WIDTH_MASK; 4775 *link = (val >> 4); 4776 return (0); 4777 } 4778 4779 static int 4780 myri10ge_reset_nic(struct myri10ge_priv *mgp) 4781 { 4782 ddi_acc_handle_t handle = mgp->cfg_hdl; 4783 uint32_t reboot; 4784 uint16_t cmd; 4785 int err; 4786 4787 cmd = pci_config_get16(handle, PCI_CONF_COMM); 4788 if ((cmd & PCI_COMM_ME) == 0) { 4789 /* 4790 * Bus master DMA disabled? Check to see if the card 4791 * rebooted due to a parity error For now, just report 4792 * it 4793 */ 4794 4795 /* enter read32 mode */ 4796 pci_config_put8(handle, mgp->vso + 0x10, 0x3); 4797 /* read REBOOT_STATUS (0xfffffff0) */ 4798 pci_config_put32(handle, mgp->vso + 0x18, 0xfffffff0); 4799 reboot = pci_config_get16(handle, mgp->vso + 0x14); 4800 cmn_err(CE_WARN, "%s NIC rebooted 0x%x\n", mgp->name, reboot); 4801 return (0); 4802 } 4803 if (!myri10ge_watchdog_reset) { 4804 cmn_err(CE_WARN, "%s: not resetting\n", mgp->name); 4805 return (1); 4806 } 4807 4808 myri10ge_stop_locked(mgp); 4809 err = myri10ge_start_locked(mgp); 4810 if (err == DDI_FAILURE) { 4811 return (0); 4812 } 4813 mac_tx_update(mgp->mh); 4814 return (1); 4815 } 4816 4817 static inline int 4818 myri10ge_ring_stalled(myri10ge_tx_ring_t *tx) 4819 { 4820 if (tx->sched != tx->stall && 4821 tx->done == tx->watchdog_done && 4822 tx->watchdog_req != tx->watchdog_done) 4823 return (1); 4824 return (0); 4825 } 4826 4827 static void 4828 myri10ge_watchdog(void *arg) 4829 { 4830 struct myri10ge_priv *mgp; 4831 struct myri10ge_slice_state *ss; 4832 myri10ge_tx_ring_t *tx; 4833 int nic_ok = 1; 4834 int slices_stalled, rx_pause, i; 4835 int add_rx; 4836 4837 mgp = arg; 4838 mutex_enter(&mgp->intrlock); 4839 if (mgp->running != MYRI10GE_ETH_RUNNING) { 4840 cmn_err(CE_WARN, 4841 "%s not running, not rearming watchdog (%d)\n", 4842 mgp->name, mgp->running); 4843 mutex_exit(&mgp->intrlock); 4844 return; 4845 } 4846 4847 rx_pause = ntohl(mgp->ss[0].fw_stats->dropped_pause); 4848 4849 /* 4850 * make sure nic is stalled before we reset the nic, so as to 4851 * ensure we don't rip the transmit data structures out from 4852 * under a pending transmit 4853 */ 4854 4855 for (slices_stalled = 0, i = 0; i < mgp->num_slices; i++) { 4856 tx = &mgp->ss[i].tx; 4857 slices_stalled = myri10ge_ring_stalled(tx); 4858 if (slices_stalled) 4859 break; 4860 } 4861 4862 if (slices_stalled) { 4863 if (mgp->watchdog_rx_pause == rx_pause) { 4864 cmn_err(CE_WARN, 4865 "%s slice %d stalled:(%d, %d, %d, %d, %d %d %d\n)", 4866 mgp->name, i, tx->sched, tx->stall, 4867 tx->done, tx->watchdog_done, tx->req, tx->pkt_done, 4868 (int)ntohl(mgp->ss[i].fw_stats->send_done_count)); 4869 nic_ok = myri10ge_reset_nic(mgp); 4870 } else { 4871 cmn_err(CE_WARN, 4872 "%s Flow controlled, check link partner\n", 4873 mgp->name); 4874 } 4875 } 4876 4877 if (!nic_ok) { 4878 cmn_err(CE_WARN, 4879 "%s Nic dead, not rearming watchdog\n", mgp->name); 4880 mutex_exit(&mgp->intrlock); 4881 return; 4882 } 4883 for (i = 0; i < mgp->num_slices; i++) { 4884 ss = &mgp->ss[i]; 4885 tx = &ss->tx; 4886 tx->watchdog_done = tx->done; 4887 tx->watchdog_req = tx->req; 4888 if (ss->watchdog_rx_copy != MYRI10GE_SLICE_STAT(rx_copy)) { 4889 ss->watchdog_rx_copy = MYRI10GE_SLICE_STAT(rx_copy); 4890 add_rx = 4891 min(ss->jpool.num_alloc, 4892 myri10ge_bigbufs_max - 4893 (ss->jpool.num_alloc - 4894 ss->jbufs_for_smalls)); 4895 if (add_rx != 0) { 4896 (void) myri10ge_add_jbufs(ss, add_rx, 0); 4897 /* now feed them to the firmware */ 4898 mutex_enter(&ss->jpool.mtx); 4899 myri10ge_restock_jumbos(ss); 4900 mutex_exit(&ss->jpool.mtx); 4901 } 4902 } 4903 } 4904 mgp->watchdog_rx_pause = rx_pause; 4905 4906 mgp->timer_id = timeout(myri10ge_watchdog, mgp, 4907 mgp->timer_ticks); 4908 mutex_exit(&mgp->intrlock); 4909 } 4910 4911 /*ARGSUSED*/ 4912 static int 4913 myri10ge_get_coalesce(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp) 4914 4915 { 4916 struct myri10ge_priv *mgp = (struct myri10ge_priv *)(void *)cp; 4917 (void) mi_mpprintf(mp, "%d", mgp->intr_coal_delay); 4918 return (0); 4919 } 4920 4921 /*ARGSUSED*/ 4922 static int 4923 myri10ge_set_coalesce(queue_t *q, mblk_t *mp, char *value, 4924 caddr_t cp, cred_t *credp) 4925 4926 { 4927 struct myri10ge_priv *mgp = (struct myri10ge_priv *)(void *)cp; 4928 char *end; 4929 size_t new_value; 4930 4931 new_value = mi_strtol(value, &end, 10); 4932 if (end == value) 4933 return (EINVAL); 4934 4935 mutex_enter(&myri10ge_param_lock); 4936 mgp->intr_coal_delay = (int)new_value; 4937 *mgp->intr_coal_delay_ptr = htonl(mgp->intr_coal_delay); 4938 mutex_exit(&myri10ge_param_lock); 4939 return (0); 4940 } 4941 4942 /*ARGSUSED*/ 4943 static int 4944 myri10ge_get_pauseparam(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp) 4945 4946 { 4947 struct myri10ge_priv *mgp = (struct myri10ge_priv *)(void *)cp; 4948 (void) mi_mpprintf(mp, "%d", mgp->pause); 4949 return (0); 4950 } 4951 4952 /*ARGSUSED*/ 4953 static int 4954 myri10ge_set_pauseparam(queue_t *q, mblk_t *mp, char *value, 4955 caddr_t cp, cred_t *credp) 4956 4957 { 4958 struct myri10ge_priv *mgp = (struct myri10ge_priv *)(void *)cp; 4959 char *end; 4960 size_t new_value; 4961 int err = 0; 4962 4963 new_value = mi_strtol(value, &end, 10); 4964 if (end == value) 4965 return (EINVAL); 4966 if (new_value != 0) 4967 new_value = 1; 4968 4969 mutex_enter(&myri10ge_param_lock); 4970 if (new_value != mgp->pause) 4971 err = myri10ge_change_pause(mgp, new_value); 4972 mutex_exit(&myri10ge_param_lock); 4973 return (err); 4974 } 4975 4976 /*ARGSUSED*/ 4977 static int 4978 myri10ge_get_int(queue_t *q, mblk_t *mp, caddr_t cp, cred_t *credp) 4979 4980 { 4981 (void) mi_mpprintf(mp, "%d", *(int *)(void *)cp); 4982 return (0); 4983 } 4984 4985 /*ARGSUSED*/ 4986 static int 4987 myri10ge_set_int(queue_t *q, mblk_t *mp, char *value, 4988 caddr_t cp, cred_t *credp) 4989 4990 { 4991 char *end; 4992 size_t new_value; 4993 4994 new_value = mi_strtol(value, &end, 10); 4995 if (end == value) 4996 return (EINVAL); 4997 *(int *)(void *)cp = new_value; 4998 4999 return (0); 5000 } 5001 5002 static void 5003 myri10ge_ndd_init(struct myri10ge_priv *mgp) 5004 { 5005 mgp->nd_head = NULL; 5006 5007 (void) nd_load(&mgp->nd_head, "myri10ge_intr_coal_delay", 5008 myri10ge_get_coalesce, myri10ge_set_coalesce, (caddr_t)mgp); 5009 (void) nd_load(&mgp->nd_head, "myri10ge_flow_control", 5010 myri10ge_get_pauseparam, myri10ge_set_pauseparam, (caddr_t)mgp); 5011 (void) nd_load(&mgp->nd_head, "myri10ge_verbose", 5012 myri10ge_get_int, myri10ge_set_int, (caddr_t)&myri10ge_verbose); 5013 (void) nd_load(&mgp->nd_head, "myri10ge_deassert_wait", 5014 myri10ge_get_int, myri10ge_set_int, 5015 (caddr_t)&myri10ge_deassert_wait); 5016 (void) nd_load(&mgp->nd_head, "myri10ge_bigbufs_max", 5017 myri10ge_get_int, myri10ge_set_int, 5018 (caddr_t)&myri10ge_bigbufs_max); 5019 (void) nd_load(&mgp->nd_head, "myri10ge_lro", 5020 myri10ge_get_int, myri10ge_set_int, 5021 (caddr_t)&myri10ge_lro); 5022 (void) nd_load(&mgp->nd_head, "myri10ge_lro_max_aggr", 5023 myri10ge_get_int, myri10ge_set_int, 5024 (caddr_t)&myri10ge_lro_max_aggr); 5025 (void) nd_load(&mgp->nd_head, "myri10ge_tx_hash", 5026 myri10ge_get_int, myri10ge_set_int, 5027 (caddr_t)&myri10ge_tx_hash); 5028 (void) nd_load(&mgp->nd_head, "myri10ge_lso_copy", 5029 myri10ge_get_int, myri10ge_set_int, 5030 (caddr_t)&myri10ge_lso_copy); 5031 } 5032 5033 static void 5034 myri10ge_ndd_fini(struct myri10ge_priv *mgp) 5035 { 5036 nd_free(&mgp->nd_head); 5037 } 5038 5039 static void 5040 myri10ge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 5041 { 5042 struct iocblk *iocp; 5043 struct myri10ge_priv *mgp = arg; 5044 int cmd, ok, err; 5045 5046 iocp = (struct iocblk *)(void *)mp->b_rptr; 5047 cmd = iocp->ioc_cmd; 5048 5049 ok = 0; 5050 err = 0; 5051 5052 switch (cmd) { 5053 case ND_GET: 5054 case ND_SET: 5055 ok = nd_getset(wq, mgp->nd_head, mp); 5056 break; 5057 default: 5058 break; 5059 } 5060 if (!ok) 5061 err = EINVAL; 5062 else 5063 err = iocp->ioc_error; 5064 5065 if (!err) 5066 miocack(wq, mp, iocp->ioc_count, err); 5067 else 5068 miocnak(wq, mp, 0, err); 5069 } 5070 5071 static struct myri10ge_priv *mgp_list; 5072 5073 struct myri10ge_priv * 5074 myri10ge_get_instance(uint_t unit) 5075 { 5076 struct myri10ge_priv *mgp; 5077 5078 mutex_enter(&myri10ge_param_lock); 5079 for (mgp = mgp_list; mgp != NULL; mgp = mgp->next) { 5080 if (unit == ddi_get_instance(mgp->dip)) { 5081 mgp->refcnt++; 5082 break; 5083 } 5084 } 5085 mutex_exit(&myri10ge_param_lock); 5086 return (mgp); 5087 } 5088 5089 void 5090 myri10ge_put_instance(struct myri10ge_priv *mgp) 5091 { 5092 mutex_enter(&myri10ge_param_lock); 5093 mgp->refcnt--; 5094 mutex_exit(&myri10ge_param_lock); 5095 } 5096 5097 static boolean_t 5098 myri10ge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 5099 { 5100 struct myri10ge_priv *mgp = arg; 5101 uint32_t *cap_hcksum; 5102 mac_capab_lso_t *cap_lso; 5103 mac_capab_rings_t *cap_rings; 5104 5105 switch (cap) { 5106 case MAC_CAPAB_HCKSUM: 5107 cap_hcksum = cap_data; 5108 *cap_hcksum = HCKSUM_INET_PARTIAL; 5109 break; 5110 case MAC_CAPAB_RINGS: 5111 cap_rings = cap_data; 5112 switch (cap_rings->mr_type) { 5113 case MAC_RING_TYPE_RX: 5114 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 5115 cap_rings->mr_rnum = mgp->num_slices; 5116 cap_rings->mr_gnum = 1; 5117 cap_rings->mr_rget = myri10ge_fill_ring; 5118 cap_rings->mr_gget = myri10ge_fill_group; 5119 break; 5120 case MAC_RING_TYPE_TX: 5121 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 5122 cap_rings->mr_rnum = mgp->num_slices; 5123 cap_rings->mr_gnum = 0; 5124 cap_rings->mr_rget = myri10ge_fill_ring; 5125 cap_rings->mr_gget = NULL; 5126 break; 5127 default: 5128 return (B_FALSE); 5129 } 5130 break; 5131 case MAC_CAPAB_LSO: 5132 cap_lso = cap_data; 5133 if (!myri10ge_use_lso) 5134 return (B_FALSE); 5135 if (!(mgp->features & MYRI10GE_TSO)) 5136 return (B_FALSE); 5137 cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; 5138 cap_lso->lso_basic_tcp_ipv4.lso_max = (uint16_t)-1; 5139 break; 5140 5141 default: 5142 return (B_FALSE); 5143 } 5144 return (B_TRUE); 5145 } 5146 5147 5148 static int 5149 myri10ge_m_stat(void *arg, uint_t stat, uint64_t *val) 5150 { 5151 struct myri10ge_priv *mgp = arg; 5152 struct myri10ge_rx_ring_stats *rstat; 5153 struct myri10ge_tx_ring_stats *tstat; 5154 mcp_irq_data_t *fw_stats = mgp->ss[0].fw_stats; 5155 struct myri10ge_slice_state *ss; 5156 uint64_t tmp = 0; 5157 int i; 5158 5159 switch (stat) { 5160 case MAC_STAT_IFSPEED: 5161 *val = 10ull * 1000ull * 1000000ull; 5162 break; 5163 5164 case MAC_STAT_MULTIRCV: 5165 for (i = 0; i < mgp->num_slices; i++) { 5166 rstat = &mgp->ss[i].rx_stats; 5167 tmp += rstat->multircv; 5168 } 5169 *val = tmp; 5170 break; 5171 5172 case MAC_STAT_BRDCSTRCV: 5173 for (i = 0; i < mgp->num_slices; i++) { 5174 rstat = &mgp->ss[i].rx_stats; 5175 tmp += rstat->brdcstrcv; 5176 } 5177 *val = tmp; 5178 break; 5179 5180 case MAC_STAT_MULTIXMT: 5181 for (i = 0; i < mgp->num_slices; i++) { 5182 tstat = &mgp->ss[i].tx.stats; 5183 tmp += tstat->multixmt; 5184 } 5185 *val = tmp; 5186 break; 5187 5188 case MAC_STAT_BRDCSTXMT: 5189 for (i = 0; i < mgp->num_slices; i++) { 5190 tstat = &mgp->ss[i].tx.stats; 5191 tmp += tstat->brdcstxmt; 5192 } 5193 *val = tmp; 5194 break; 5195 5196 case MAC_STAT_NORCVBUF: 5197 tmp = ntohl(fw_stats->dropped_no_big_buffer); 5198 tmp += ntohl(fw_stats->dropped_no_small_buffer); 5199 tmp += ntohl(fw_stats->dropped_link_overflow); 5200 for (i = 0; i < mgp->num_slices; i++) { 5201 ss = &mgp->ss[i]; 5202 tmp += MYRI10GE_SLICE_STAT(rx_big_nobuf); 5203 tmp += MYRI10GE_SLICE_STAT(rx_small_nobuf); 5204 } 5205 *val = tmp; 5206 break; 5207 5208 case MAC_STAT_IERRORS: 5209 tmp += ntohl(fw_stats->dropped_bad_crc32); 5210 tmp += ntohl(fw_stats->dropped_bad_phy); 5211 tmp += ntohl(fw_stats->dropped_runt); 5212 tmp += ntohl(fw_stats->dropped_overrun); 5213 *val = tmp; 5214 break; 5215 5216 case MAC_STAT_OERRORS: 5217 for (i = 0; i < mgp->num_slices; i++) { 5218 ss = &mgp->ss[i]; 5219 tmp += MYRI10GE_SLICE_STAT(xmit_lsobadflags); 5220 tmp += MYRI10GE_SLICE_STAT(xmit_err); 5221 } 5222 *val = tmp; 5223 break; 5224 5225 case MAC_STAT_RBYTES: 5226 for (i = 0; i < mgp->num_slices; i++) { 5227 rstat = &mgp->ss[i].rx_stats; 5228 tmp += rstat->ibytes; 5229 } 5230 *val = tmp; 5231 break; 5232 5233 case MAC_STAT_IPACKETS: 5234 for (i = 0; i < mgp->num_slices; i++) { 5235 rstat = &mgp->ss[i].rx_stats; 5236 tmp += rstat->ipackets; 5237 } 5238 *val = tmp; 5239 break; 5240 5241 case MAC_STAT_OBYTES: 5242 for (i = 0; i < mgp->num_slices; i++) { 5243 tstat = &mgp->ss[i].tx.stats; 5244 tmp += tstat->obytes; 5245 } 5246 *val = tmp; 5247 break; 5248 5249 case MAC_STAT_OPACKETS: 5250 for (i = 0; i < mgp->num_slices; i++) { 5251 tstat = &mgp->ss[i].tx.stats; 5252 tmp += tstat->opackets; 5253 } 5254 *val = tmp; 5255 break; 5256 5257 case ETHER_STAT_TOOLONG_ERRORS: 5258 *val = ntohl(fw_stats->dropped_overrun); 5259 break; 5260 5261 #ifdef SOLARIS_S11 5262 case ETHER_STAT_TOOSHORT_ERRORS: 5263 *val = ntohl(fw_stats->dropped_runt); 5264 break; 5265 #endif 5266 5267 case ETHER_STAT_LINK_PAUSE: 5268 *val = mgp->pause; 5269 break; 5270 5271 case ETHER_STAT_LINK_AUTONEG: 5272 *val = 1; 5273 break; 5274 5275 case ETHER_STAT_LINK_DUPLEX: 5276 *val = LINK_DUPLEX_FULL; 5277 break; 5278 5279 default: 5280 return (ENOTSUP); 5281 } 5282 5283 return (0); 5284 } 5285 5286 static mac_callbacks_t myri10ge_m_callbacks = { 5287 (MC_IOCTL | MC_GETCAPAB), 5288 myri10ge_m_stat, 5289 myri10ge_m_start, 5290 myri10ge_m_stop, 5291 myri10ge_m_promisc, 5292 myri10ge_m_multicst, 5293 NULL, 5294 NULL, 5295 myri10ge_m_ioctl, 5296 myri10ge_m_getcapab 5297 }; 5298 5299 5300 static int 5301 myri10ge_probe_slices(struct myri10ge_priv *mgp) 5302 { 5303 myri10ge_cmd_t cmd; 5304 int status; 5305 5306 mgp->num_slices = 1; 5307 5308 /* hit the board with a reset to ensure it is alive */ 5309 (void) memset(&cmd, 0, sizeof (cmd)); 5310 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_RESET, &cmd); 5311 if (status != 0) { 5312 cmn_err(CE_WARN, "%s: failed reset\n", mgp->name); 5313 return (ENXIO); 5314 } 5315 5316 if (myri10ge_use_msix == 0) 5317 return (0); 5318 5319 /* tell it the size of the interrupt queues */ 5320 cmd.data0 = mgp->max_intr_slots * sizeof (struct mcp_slot); 5321 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_SET_INTRQ_SIZE, &cmd); 5322 if (status != 0) { 5323 cmn_err(CE_WARN, "%s: failed MXGEFW_CMD_SET_INTRQ_SIZE\n", 5324 mgp->name); 5325 return (ENXIO); 5326 } 5327 5328 /* ask the maximum number of slices it supports */ 5329 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_GET_MAX_RSS_QUEUES, 5330 &cmd); 5331 if (status != 0) 5332 return (0); 5333 5334 mgp->num_slices = cmd.data0; 5335 5336 /* 5337 * if the admin did not specify a limit to how many 5338 * slices we should use, cap it automatically to the 5339 * number of CPUs currently online 5340 */ 5341 if (myri10ge_max_slices == -1) 5342 myri10ge_max_slices = ncpus; 5343 5344 if (mgp->num_slices > myri10ge_max_slices) 5345 mgp->num_slices = myri10ge_max_slices; 5346 5347 5348 /* 5349 * Now try to allocate as many MSI-X vectors as we have 5350 * slices. We give up on MSI-X if we can only get a single 5351 * vector. 5352 */ 5353 while (mgp->num_slices > 1) { 5354 /* make sure it is a power of two */ 5355 while (mgp->num_slices & (mgp->num_slices - 1)) 5356 mgp->num_slices--; 5357 if (mgp->num_slices == 1) 5358 return (0); 5359 5360 status = myri10ge_add_intrs(mgp, 0); 5361 if (status == 0) { 5362 myri10ge_rem_intrs(mgp, 0); 5363 if (mgp->intr_cnt == mgp->num_slices) { 5364 if (myri10ge_verbose) 5365 printf("Got %d slices!\n", 5366 mgp->num_slices); 5367 return (0); 5368 } 5369 mgp->num_slices = mgp->intr_cnt; 5370 } else { 5371 mgp->num_slices = mgp->num_slices / 2; 5372 } 5373 } 5374 5375 if (myri10ge_verbose) 5376 printf("Got %d slices\n", mgp->num_slices); 5377 return (0); 5378 } 5379 5380 static void 5381 myri10ge_lro_free(struct myri10ge_slice_state *ss) 5382 { 5383 struct lro_entry *lro; 5384 5385 while (ss->lro_free != NULL) { 5386 lro = ss->lro_free; 5387 ss->lro_free = lro->next; 5388 kmem_free(lro, sizeof (*lro)); 5389 } 5390 } 5391 5392 static void 5393 myri10ge_lro_alloc(struct myri10ge_slice_state *ss) 5394 { 5395 struct lro_entry *lro; 5396 int idx; 5397 5398 ss->lro_free = NULL; 5399 ss->lro_active = NULL; 5400 5401 for (idx = 0; idx < myri10ge_lro_cnt; idx++) { 5402 lro = kmem_zalloc(sizeof (*lro), KM_SLEEP); 5403 if (lro == NULL) 5404 continue; 5405 lro->next = ss->lro_free; 5406 ss->lro_free = lro; 5407 } 5408 } 5409 5410 static void 5411 myri10ge_free_slices(struct myri10ge_priv *mgp) 5412 { 5413 struct myri10ge_slice_state *ss; 5414 size_t bytes; 5415 int i; 5416 5417 if (mgp->ss == NULL) 5418 return; 5419 5420 for (i = 0; i < mgp->num_slices; i++) { 5421 ss = &mgp->ss[i]; 5422 if (ss->rx_done.entry == NULL) 5423 continue; 5424 myri10ge_dma_free(&ss->rx_done.dma); 5425 ss->rx_done.entry = NULL; 5426 if (ss->fw_stats == NULL) 5427 continue; 5428 myri10ge_dma_free(&ss->fw_stats_dma); 5429 ss->fw_stats = NULL; 5430 mutex_destroy(&ss->rx_lock); 5431 mutex_destroy(&ss->tx.lock); 5432 mutex_destroy(&ss->tx.handle_lock); 5433 mutex_destroy(&ss->poll_lock); 5434 myri10ge_jpool_fini(ss); 5435 myri10ge_slice_stat_destroy(ss); 5436 myri10ge_lro_free(ss); 5437 } 5438 bytes = sizeof (*mgp->ss) * mgp->num_slices; 5439 kmem_free(mgp->ss, bytes); 5440 mgp->ss = NULL; 5441 } 5442 5443 5444 static int 5445 myri10ge_alloc_slices(struct myri10ge_priv *mgp) 5446 { 5447 struct myri10ge_slice_state *ss; 5448 size_t bytes; 5449 int i; 5450 5451 bytes = sizeof (*mgp->ss) * mgp->num_slices; 5452 mgp->ss = kmem_zalloc(bytes, KM_SLEEP); 5453 if (mgp->ss == NULL) 5454 return (ENOMEM); 5455 for (i = 0; i < mgp->num_slices; i++) { 5456 ss = &mgp->ss[i]; 5457 5458 ss->mgp = mgp; 5459 5460 /* allocate the per-slice firmware stats */ 5461 bytes = sizeof (*ss->fw_stats); 5462 ss->fw_stats = (mcp_irq_data_t *)(void *) 5463 myri10ge_dma_alloc(mgp->dip, bytes, 5464 &myri10ge_misc_dma_attr, &myri10ge_dev_access_attr, 5465 DDI_DMA_CONSISTENT, DDI_DMA_READ|DDI_DMA_CONSISTENT, 5466 &ss->fw_stats_dma, 1, DDI_DMA_DONTWAIT); 5467 if (ss->fw_stats == NULL) 5468 goto abort; 5469 (void) memset(ss->fw_stats, 0, bytes); 5470 5471 /* allocate rx done ring */ 5472 bytes = mgp->max_intr_slots * 5473 sizeof (*ss->rx_done.entry); 5474 ss->rx_done.entry = (mcp_slot_t *)(void *) 5475 myri10ge_dma_alloc(mgp->dip, bytes, 5476 &myri10ge_misc_dma_attr, &myri10ge_dev_access_attr, 5477 DDI_DMA_CONSISTENT, DDI_DMA_READ|DDI_DMA_CONSISTENT, 5478 &ss->rx_done.dma, 1, DDI_DMA_DONTWAIT); 5479 if (ss->rx_done.entry == NULL) { 5480 goto abort; 5481 } 5482 (void) memset(ss->rx_done.entry, 0, bytes); 5483 mutex_init(&ss->rx_lock, NULL, MUTEX_DEFAULT, mgp->icookie); 5484 mutex_init(&ss->tx.lock, NULL, MUTEX_DEFAULT, NULL); 5485 mutex_init(&ss->tx.handle_lock, NULL, MUTEX_DEFAULT, NULL); 5486 mutex_init(&ss->poll_lock, NULL, MUTEX_DEFAULT, NULL); 5487 myri10ge_jpool_init(ss); 5488 (void) myri10ge_slice_stat_init(ss); 5489 myri10ge_lro_alloc(ss); 5490 } 5491 5492 return (0); 5493 5494 abort: 5495 myri10ge_free_slices(mgp); 5496 return (ENOMEM); 5497 } 5498 5499 static int 5500 myri10ge_save_msi_state(struct myri10ge_priv *mgp, 5501 ddi_acc_handle_t handle) 5502 { 5503 uint8_t ptr; 5504 int err; 5505 5506 err = myri10ge_find_cap(handle, &ptr, PCI_CAP_ID_MSI); 5507 if (err != 0) { 5508 cmn_err(CE_WARN, "%s: could not find MSI cap\n", 5509 mgp->name); 5510 return (DDI_FAILURE); 5511 } 5512 mgp->pci_saved_state.msi_ctrl = 5513 pci_config_get16(handle, ptr + PCI_MSI_CTRL); 5514 mgp->pci_saved_state.msi_addr_low = 5515 pci_config_get32(handle, ptr + PCI_MSI_ADDR_OFFSET); 5516 mgp->pci_saved_state.msi_addr_high = 5517 pci_config_get32(handle, ptr + PCI_MSI_ADDR_OFFSET + 4); 5518 mgp->pci_saved_state.msi_data_32 = 5519 pci_config_get16(handle, ptr + PCI_MSI_32BIT_DATA); 5520 mgp->pci_saved_state.msi_data_64 = 5521 pci_config_get16(handle, ptr + PCI_MSI_64BIT_DATA); 5522 return (DDI_SUCCESS); 5523 } 5524 5525 static int 5526 myri10ge_restore_msi_state(struct myri10ge_priv *mgp, 5527 ddi_acc_handle_t handle) 5528 { 5529 uint8_t ptr; 5530 int err; 5531 5532 err = myri10ge_find_cap(handle, &ptr, PCI_CAP_ID_MSI); 5533 if (err != 0) { 5534 cmn_err(CE_WARN, "%s: could not find MSI cap\n", 5535 mgp->name); 5536 return (DDI_FAILURE); 5537 } 5538 5539 pci_config_put16(handle, ptr + PCI_MSI_CTRL, 5540 mgp->pci_saved_state.msi_ctrl); 5541 pci_config_put32(handle, ptr + PCI_MSI_ADDR_OFFSET, 5542 mgp->pci_saved_state.msi_addr_low); 5543 pci_config_put32(handle, ptr + PCI_MSI_ADDR_OFFSET + 4, 5544 mgp->pci_saved_state.msi_addr_high); 5545 pci_config_put16(handle, ptr + PCI_MSI_32BIT_DATA, 5546 mgp->pci_saved_state.msi_data_32); 5547 pci_config_put16(handle, ptr + PCI_MSI_64BIT_DATA, 5548 mgp->pci_saved_state.msi_data_64); 5549 5550 return (DDI_SUCCESS); 5551 } 5552 5553 static int 5554 myri10ge_save_pci_state(struct myri10ge_priv *mgp) 5555 { 5556 ddi_acc_handle_t handle = mgp->cfg_hdl; 5557 int i; 5558 int err = DDI_SUCCESS; 5559 5560 5561 /* Save the non-extended PCI config space 32-bits at a time */ 5562 for (i = 0; i < 16; i++) 5563 mgp->pci_saved_state.base[i] = 5564 pci_config_get32(handle, i*4); 5565 5566 /* now save MSI interrupt state *, if needed */ 5567 if (mgp->ddi_intr_type == DDI_INTR_TYPE_MSI) 5568 err = myri10ge_save_msi_state(mgp, handle); 5569 5570 return (err); 5571 } 5572 5573 static int 5574 myri10ge_restore_pci_state(struct myri10ge_priv *mgp) 5575 { 5576 ddi_acc_handle_t handle = mgp->cfg_hdl; 5577 int i; 5578 int err = DDI_SUCCESS; 5579 5580 5581 /* Restore the non-extended PCI config space 32-bits at a time */ 5582 for (i = 15; i >= 0; i--) 5583 pci_config_put32(handle, i*4, mgp->pci_saved_state.base[i]); 5584 5585 /* now restore MSI interrupt state *, if needed */ 5586 if (mgp->ddi_intr_type == DDI_INTR_TYPE_MSI) 5587 err = myri10ge_restore_msi_state(mgp, handle); 5588 5589 if (mgp->max_read_request_4k) 5590 (void) myri10ge_set_max_readreq(handle); 5591 return (err); 5592 } 5593 5594 5595 static int 5596 myri10ge_suspend(dev_info_t *dip) 5597 { 5598 struct myri10ge_priv *mgp = ddi_get_driver_private(dip); 5599 int status; 5600 5601 if (mgp == NULL) { 5602 cmn_err(CE_WARN, "null dip in myri10ge_suspend\n"); 5603 return (DDI_FAILURE); 5604 } 5605 if (mgp->dip != dip) { 5606 cmn_err(CE_WARN, "bad dip in myri10ge_suspend\n"); 5607 return (DDI_FAILURE); 5608 } 5609 mutex_enter(&mgp->intrlock); 5610 if (mgp->running == MYRI10GE_ETH_RUNNING) { 5611 mgp->running = MYRI10GE_ETH_STOPPING; 5612 mutex_exit(&mgp->intrlock); 5613 (void) untimeout(mgp->timer_id); 5614 mutex_enter(&mgp->intrlock); 5615 myri10ge_stop_locked(mgp); 5616 mgp->running = MYRI10GE_ETH_SUSPENDED_RUNNING; 5617 } 5618 status = myri10ge_save_pci_state(mgp); 5619 mutex_exit(&mgp->intrlock); 5620 return (status); 5621 } 5622 5623 static int 5624 myri10ge_resume(dev_info_t *dip) 5625 { 5626 struct myri10ge_priv *mgp = ddi_get_driver_private(dip); 5627 int status = DDI_SUCCESS; 5628 5629 if (mgp == NULL) { 5630 cmn_err(CE_WARN, "null dip in myri10ge_resume\n"); 5631 return (DDI_FAILURE); 5632 } 5633 if (mgp->dip != dip) { 5634 cmn_err(CE_WARN, "bad dip in myri10ge_resume\n"); 5635 return (DDI_FAILURE); 5636 } 5637 5638 mutex_enter(&mgp->intrlock); 5639 status = myri10ge_restore_pci_state(mgp); 5640 if (status == DDI_SUCCESS && 5641 mgp->running == MYRI10GE_ETH_SUSPENDED_RUNNING) { 5642 status = myri10ge_start_locked(mgp); 5643 } 5644 mutex_exit(&mgp->intrlock); 5645 if (status != DDI_SUCCESS) 5646 return (status); 5647 5648 /* start the watchdog timer */ 5649 mgp->timer_id = timeout(myri10ge_watchdog, mgp, 5650 mgp->timer_ticks); 5651 return (DDI_SUCCESS); 5652 } 5653 5654 static int 5655 myri10ge_attach(dev_info_t *dip, ddi_attach_cmd_t cmd) 5656 { 5657 5658 struct myri10ge_priv *mgp; 5659 mac_register_t *macp, *omacp; 5660 ddi_acc_handle_t handle; 5661 uint32_t csr, hdr_offset; 5662 int status, span, link_width, max_read_request_4k; 5663 unsigned long bus_number, dev_number, func_number; 5664 size_t bytes; 5665 offset_t ss_offset; 5666 uint8_t vso; 5667 5668 if (cmd == DDI_RESUME) { 5669 return (myri10ge_resume(dip)); 5670 } 5671 5672 if (cmd != DDI_ATTACH) 5673 return (DDI_FAILURE); 5674 if (pci_config_setup(dip, &handle) != DDI_SUCCESS) 5675 return (DDI_FAILURE); 5676 5677 /* enable busmater and io space access */ 5678 csr = pci_config_get32(handle, PCI_CONF_COMM); 5679 pci_config_put32(handle, PCI_CONF_COMM, 5680 (csr |PCI_COMM_ME|PCI_COMM_MAE)); 5681 status = myri10ge_read_pcie_link_width(handle, &link_width); 5682 if (status != 0) { 5683 cmn_err(CE_WARN, "could not read link width!\n"); 5684 link_width = 0; 5685 } 5686 max_read_request_4k = !myri10ge_set_max_readreq(handle); 5687 status = myri10ge_find_cap(handle, &vso, PCI_CAP_ID_VS); 5688 if (status != 0) 5689 goto abort_with_cfg_hdl; 5690 if ((omacp = mac_alloc(MAC_VERSION)) == NULL) 5691 goto abort_with_cfg_hdl; 5692 /* 5693 * XXXX Hack: mac_register_t grows in newer kernels. To be 5694 * able to write newer fields, such as m_margin, without 5695 * writing outside allocated memory, we allocate our own macp 5696 * and pass that to mac_register() 5697 */ 5698 macp = kmem_zalloc(sizeof (*macp) * 8, KM_SLEEP); 5699 macp->m_version = omacp->m_version; 5700 5701 if ((mgp = (struct myri10ge_priv *) 5702 kmem_zalloc(sizeof (*mgp), KM_SLEEP)) == NULL) { 5703 goto abort_with_macinfo; 5704 } 5705 ddi_set_driver_private(dip, mgp); 5706 5707 /* setup device name for log messages */ 5708 (void) sprintf(mgp->name, "myri10ge%d", ddi_get_instance(dip)); 5709 5710 mutex_enter(&myri10ge_param_lock); 5711 myri10ge_get_props(dip); 5712 mgp->intr_coal_delay = myri10ge_intr_coal_delay; 5713 mgp->pause = myri10ge_flow_control; 5714 mutex_exit(&myri10ge_param_lock); 5715 5716 mgp->max_read_request_4k = max_read_request_4k; 5717 mgp->pcie_link_width = link_width; 5718 mgp->running = MYRI10GE_ETH_STOPPED; 5719 mgp->vso = vso; 5720 mgp->dip = dip; 5721 mgp->cfg_hdl = handle; 5722 5723 mgp->timer_ticks = 5 * drv_usectohz(1000000); /* 5 seconds */ 5724 myri10ge_test_physical(dip); 5725 5726 /* allocate command page */ 5727 bytes = sizeof (*mgp->cmd); 5728 mgp->cmd = (mcp_cmd_response_t *) 5729 (void *)myri10ge_dma_alloc(dip, bytes, 5730 &myri10ge_misc_dma_attr, &myri10ge_dev_access_attr, 5731 DDI_DMA_CONSISTENT, DDI_DMA_RDWR|DDI_DMA_CONSISTENT, 5732 &mgp->cmd_dma, 1, DDI_DMA_DONTWAIT); 5733 if (mgp->cmd == NULL) 5734 goto abort_with_mgp; 5735 5736 (void) myri10ge_reg_set(dip, &mgp->reg_set, &span, &bus_number, 5737 &dev_number, &func_number); 5738 if (myri10ge_verbose) 5739 printf("%s at %ld:%ld:%ld attaching\n", mgp->name, 5740 bus_number, dev_number, func_number); 5741 status = ddi_regs_map_setup(dip, mgp->reg_set, (caddr_t *)&mgp->sram, 5742 (offset_t)0, (offset_t)span, &myri10ge_dev_access_attr, 5743 &mgp->io_handle); 5744 if (status != DDI_SUCCESS) { 5745 cmn_err(CE_WARN, "%s: couldn't map memory space", mgp->name); 5746 printf("%s: reg_set = %d, span = %d, status = %d", 5747 mgp->name, mgp->reg_set, span, status); 5748 goto abort_with_mgp; 5749 } 5750 5751 hdr_offset = *(uint32_t *)(void*)(mgp->sram + MCP_HEADER_PTR_OFFSET); 5752 hdr_offset = ntohl(hdr_offset) & 0xffffc; 5753 ss_offset = hdr_offset + 5754 offsetof(struct mcp_gen_header, string_specs); 5755 mgp->sram_size = ntohl(*(uint32_t *)(void*)(mgp->sram + ss_offset)); 5756 myri10ge_pio_copy32(mgp->eeprom_strings, 5757 (uint32_t *)(void*)((char *)mgp->sram + mgp->sram_size), 5758 MYRI10GE_EEPROM_STRINGS_SIZE); 5759 (void) memset(mgp->eeprom_strings + 5760 MYRI10GE_EEPROM_STRINGS_SIZE - 2, 0, 2); 5761 5762 status = myri10ge_read_mac_addr(mgp); 5763 if (status) { 5764 goto abort_with_mapped; 5765 } 5766 5767 status = myri10ge_select_firmware(mgp); 5768 if (status != 0) { 5769 cmn_err(CE_WARN, "%s: failed to load firmware\n", mgp->name); 5770 goto abort_with_mapped; 5771 } 5772 5773 status = myri10ge_probe_slices(mgp); 5774 if (status != 0) { 5775 cmn_err(CE_WARN, "%s: failed to probe slices\n", mgp->name); 5776 goto abort_with_dummy_rdma; 5777 } 5778 5779 status = myri10ge_alloc_slices(mgp); 5780 if (status != 0) { 5781 cmn_err(CE_WARN, "%s: failed to alloc slices\n", mgp->name); 5782 goto abort_with_dummy_rdma; 5783 } 5784 5785 /* add the interrupt handler */ 5786 status = myri10ge_add_intrs(mgp, 1); 5787 if (status != 0) { 5788 cmn_err(CE_WARN, "%s: Failed to add interrupt\n", 5789 mgp->name); 5790 goto abort_with_slices; 5791 } 5792 5793 /* now that we have an iblock_cookie, init the mutexes */ 5794 mutex_init(&mgp->cmd_lock, NULL, MUTEX_DRIVER, mgp->icookie); 5795 mutex_init(&mgp->intrlock, NULL, MUTEX_DRIVER, mgp->icookie); 5796 5797 5798 status = myri10ge_nic_stat_init(mgp); 5799 if (status != DDI_SUCCESS) 5800 goto abort_with_interrupts; 5801 status = myri10ge_info_init(mgp); 5802 if (status != DDI_SUCCESS) 5803 goto abort_with_stats; 5804 5805 /* 5806 * Initialize GLD state 5807 */ 5808 5809 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 5810 macp->m_driver = mgp; 5811 macp->m_dip = dip; 5812 macp->m_src_addr = mgp->mac_addr; 5813 macp->m_callbacks = &myri10ge_m_callbacks; 5814 macp->m_min_sdu = 0; 5815 macp->m_max_sdu = myri10ge_mtu - 5816 (sizeof (struct ether_header) + MXGEFW_PAD + VLAN_TAGSZ); 5817 #ifdef SOLARIS_S11 5818 macp->m_margin = VLAN_TAGSZ; 5819 #endif 5820 macp->m_v12n = MAC_VIRT_LEVEL1; 5821 status = mac_register(macp, &mgp->mh); 5822 if (status != 0) { 5823 cmn_err(CE_WARN, "%s: mac_register failed with %d\n", 5824 mgp->name, status); 5825 goto abort_with_info; 5826 } 5827 myri10ge_ndd_init(mgp); 5828 if (myri10ge_verbose) 5829 printf("%s: %s, tx bndry %d, fw %s\n", mgp->name, 5830 mgp->intr_type, mgp->tx_boundary, mgp->fw_name); 5831 mutex_enter(&myri10ge_param_lock); 5832 mgp->next = mgp_list; 5833 mgp_list = mgp; 5834 mutex_exit(&myri10ge_param_lock); 5835 kmem_free(macp, sizeof (*macp) * 8); 5836 mac_free(omacp); 5837 return (DDI_SUCCESS); 5838 5839 abort_with_info: 5840 myri10ge_info_destroy(mgp); 5841 5842 abort_with_stats: 5843 myri10ge_nic_stat_destroy(mgp); 5844 5845 abort_with_interrupts: 5846 mutex_destroy(&mgp->cmd_lock); 5847 mutex_destroy(&mgp->intrlock); 5848 myri10ge_rem_intrs(mgp, 1); 5849 5850 abort_with_slices: 5851 myri10ge_free_slices(mgp); 5852 5853 abort_with_dummy_rdma: 5854 myri10ge_dummy_rdma(mgp, 0); 5855 5856 abort_with_mapped: 5857 ddi_regs_map_free(&mgp->io_handle); 5858 5859 myri10ge_dma_free(&mgp->cmd_dma); 5860 5861 abort_with_mgp: 5862 kmem_free(mgp, sizeof (*mgp)); 5863 5864 abort_with_macinfo: 5865 kmem_free(macp, sizeof (*macp) * 8); 5866 mac_free(omacp); 5867 5868 abort_with_cfg_hdl: 5869 pci_config_teardown(&handle); 5870 return (DDI_FAILURE); 5871 5872 } 5873 5874 5875 static int 5876 myri10ge_detach(dev_info_t *dip, ddi_detach_cmd_t cmd) 5877 { 5878 struct myri10ge_priv *mgp, *tmp; 5879 int status, i, jbufs_alloced; 5880 5881 if (cmd == DDI_SUSPEND) { 5882 status = myri10ge_suspend(dip); 5883 return (status); 5884 } 5885 5886 if (cmd != DDI_DETACH) { 5887 return (DDI_FAILURE); 5888 } 5889 /* Get the driver private (gld_mac_info_t) structure */ 5890 mgp = ddi_get_driver_private(dip); 5891 5892 mutex_enter(&mgp->intrlock); 5893 jbufs_alloced = 0; 5894 for (i = 0; i < mgp->num_slices; i++) { 5895 myri10ge_remove_jbufs(&mgp->ss[i]); 5896 jbufs_alloced += mgp->ss[i].jpool.num_alloc; 5897 } 5898 mutex_exit(&mgp->intrlock); 5899 if (jbufs_alloced != 0) { 5900 cmn_err(CE_NOTE, "%s: %d loaned rx buffers remain\n", 5901 mgp->name, jbufs_alloced); 5902 return (DDI_FAILURE); 5903 } 5904 5905 mutex_enter(&myri10ge_param_lock); 5906 if (mgp->refcnt != 0) { 5907 mutex_exit(&myri10ge_param_lock); 5908 cmn_err(CE_NOTE, "%s: %d external refs remain\n", 5909 mgp->name, mgp->refcnt); 5910 return (DDI_FAILURE); 5911 } 5912 mutex_exit(&myri10ge_param_lock); 5913 5914 status = mac_unregister(mgp->mh); 5915 if (status != DDI_SUCCESS) 5916 return (status); 5917 5918 myri10ge_ndd_fini(mgp); 5919 myri10ge_dummy_rdma(mgp, 0); 5920 myri10ge_nic_stat_destroy(mgp); 5921 myri10ge_info_destroy(mgp); 5922 5923 mutex_destroy(&mgp->cmd_lock); 5924 mutex_destroy(&mgp->intrlock); 5925 5926 myri10ge_rem_intrs(mgp, 1); 5927 5928 myri10ge_free_slices(mgp); 5929 ddi_regs_map_free(&mgp->io_handle); 5930 myri10ge_dma_free(&mgp->cmd_dma); 5931 pci_config_teardown(&mgp->cfg_hdl); 5932 5933 mutex_enter(&myri10ge_param_lock); 5934 if (mgp_list == mgp) { 5935 mgp_list = mgp->next; 5936 } else { 5937 tmp = mgp_list; 5938 while (tmp->next != mgp && tmp->next != NULL) 5939 tmp = tmp->next; 5940 if (tmp->next != NULL) 5941 tmp->next = tmp->next->next; 5942 } 5943 kmem_free(mgp, sizeof (*mgp)); 5944 mutex_exit(&myri10ge_param_lock); 5945 return (DDI_SUCCESS); 5946 } 5947 5948 /* 5949 * Helper for quiesce entry point: Interrupt threads are not being 5950 * scheduled, so we must poll for the confirmation DMA to arrive in 5951 * the firmware stats block for slice 0. We're essentially running 5952 * the guts of the interrupt handler, and just cherry picking the 5953 * confirmation that the NIC is queuesced (stats->link_down) 5954 */ 5955 5956 static int 5957 myri10ge_poll_down(struct myri10ge_priv *mgp) 5958 { 5959 struct myri10ge_slice_state *ss = mgp->ss; 5960 mcp_irq_data_t *stats = ss->fw_stats; 5961 int valid; 5962 int found_down = 0; 5963 5964 5965 /* check for a pending IRQ */ 5966 5967 if (! *((volatile uint8_t *)& stats->valid)) 5968 return (0); 5969 valid = stats->valid; 5970 5971 /* 5972 * Make sure to tell the NIC to lower a legacy IRQ, else 5973 * it may have corrupt state after restarting 5974 */ 5975 5976 if (mgp->ddi_intr_type == DDI_INTR_TYPE_FIXED) { 5977 /* lower legacy IRQ */ 5978 *mgp->irq_deassert = 0; 5979 mb(); 5980 /* wait for irq conf DMA */ 5981 while (*((volatile uint8_t *)& stats->valid)) 5982 ; 5983 } 5984 if (stats->stats_updated && stats->link_down) 5985 found_down = 1; 5986 5987 if (valid & 0x1) 5988 *ss->irq_claim = BE_32(3); 5989 *(ss->irq_claim + 1) = BE_32(3); 5990 5991 return (found_down); 5992 } 5993 5994 static int 5995 myri10ge_quiesce(dev_info_t *dip) 5996 { 5997 struct myri10ge_priv *mgp; 5998 myri10ge_cmd_t cmd; 5999 int status, down, i; 6000 6001 mgp = ddi_get_driver_private(dip); 6002 if (mgp == NULL) 6003 return (DDI_FAILURE); 6004 6005 /* if devices was unplumbed, it is guaranteed to be quiescent */ 6006 if (mgp->running == MYRI10GE_ETH_STOPPED) 6007 return (DDI_SUCCESS); 6008 6009 /* send a down CMD to queuesce NIC */ 6010 status = myri10ge_send_cmd(mgp, MXGEFW_CMD_ETHERNET_DOWN, &cmd); 6011 if (status) { 6012 cmn_err(CE_WARN, "%s: Couldn't bring down link\n", mgp->name); 6013 return (DDI_FAILURE); 6014 } 6015 6016 for (i = 0; i < 20; i++) { 6017 down = myri10ge_poll_down(mgp); 6018 if (down) 6019 break; 6020 delay(drv_usectohz(100000)); 6021 mb(); 6022 } 6023 if (down) 6024 return (DDI_SUCCESS); 6025 return (DDI_FAILURE); 6026 } 6027 6028 /* 6029 * Distinguish between allocb'ed blocks, and gesballoc'ed attached 6030 * storage. 6031 */ 6032 static void 6033 myri10ge_find_lastfree(void) 6034 { 6035 mblk_t *mp = allocb(1024, 0); 6036 dblk_t *dbp; 6037 6038 if (mp == NULL) { 6039 cmn_err(CE_WARN, "myri10ge_find_lastfree failed\n"); 6040 return; 6041 } 6042 dbp = mp->b_datap; 6043 myri10ge_db_lastfree = (void *)dbp->db_lastfree; 6044 } 6045 6046 int 6047 _init(void) 6048 { 6049 int i; 6050 6051 if (myri10ge_verbose) 6052 cmn_err(CE_NOTE, 6053 "Myricom 10G driver (10GbE) version %s loading\n", 6054 MYRI10GE_VERSION_STR); 6055 myri10ge_find_lastfree(); 6056 mac_init_ops(&myri10ge_ops, "myri10ge"); 6057 mutex_init(&myri10ge_param_lock, NULL, MUTEX_DEFAULT, NULL); 6058 if ((i = mod_install(&modlinkage)) != 0) { 6059 cmn_err(CE_WARN, "mod_install returned %d\n", i); 6060 mac_fini_ops(&myri10ge_ops); 6061 mutex_destroy(&myri10ge_param_lock); 6062 } 6063 return (i); 6064 } 6065 6066 int 6067 _fini(void) 6068 { 6069 int i; 6070 i = mod_remove(&modlinkage); 6071 if (i != 0) { 6072 return (i); 6073 } 6074 mac_fini_ops(&myri10ge_ops); 6075 mutex_destroy(&myri10ge_param_lock); 6076 return (0); 6077 } 6078 6079 int 6080 _info(struct modinfo *modinfop) 6081 { 6082 return (mod_info(&modlinkage, modinfop)); 6083 } 6084 6085 6086 /* 6087 * This file uses MyriGE driver indentation. 6088 * 6089 * Local Variables: 6090 * c-file-style:"sun" 6091 * tab-width:8 6092 * End: 6093 */ 6094