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