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