1 5578 mx205022 /* 2 5578 mx205022 * CDDL HEADER START 3 5578 mx205022 * 4 5578 mx205022 * The contents of this file are subject to the terms of the 5 5578 mx205022 * Common Development and Distribution License (the "License"). 6 5578 mx205022 * You may not use this file except in compliance with the License. 7 5578 mx205022 * 8 5578 mx205022 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 5578 mx205022 * or http://www.opensolaris.org/os/licensing. 10 5578 mx205022 * See the License for the specific language governing permissions 11 5578 mx205022 * and limitations under the License. 12 5578 mx205022 * 13 5578 mx205022 * When distributing Covered Code, include this CDDL HEADER in each 14 5578 mx205022 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 5578 mx205022 * If applicable, add the following below this CDDL HEADER, with the 16 5578 mx205022 * fields enclosed by brackets "[]" replaced with your own identifying 17 5578 mx205022 * information: Portions Copyright [yyyy] [name of copyright owner] 18 5578 mx205022 * 19 5578 mx205022 * CDDL HEADER END 20 5578 mx205022 */ 21 5578 mx205022 22 5574 mx205022 /* 23 9514 Girish * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 24 5574 mx205022 * Use is subject to license terms. 25 5574 mx205022 */ 26 5574 mx205022 27 5574 mx205022 28 5574 mx205022 #include "nge.h" 29 5574 mx205022 30 5574 mx205022 /* 31 5574 mx205022 * Describes the chip's DMA engine 32 5574 mx205022 */ 33 5574 mx205022 34 5574 mx205022 static ddi_dma_attr_t hot_dma_attr = { 35 5574 mx205022 DMA_ATTR_V0, /* dma_attr version */ 36 5574 mx205022 0x0000000000000000ull, /* dma_attr_addr_lo */ 37 5574 mx205022 0x000000FFFFFFFFFFull, /* dma_attr_addr_hi */ 38 5574 mx205022 0x000000007FFFFFFFull, /* dma_attr_count_max */ 39 5574 mx205022 0x0000000000000010ull, /* dma_attr_align */ 40 5574 mx205022 0x00000FFF, /* dma_attr_burstsizes */ 41 5574 mx205022 0x00000001, /* dma_attr_minxfer */ 42 5574 mx205022 0x000000000000FFFFull, /* dma_attr_maxxfer */ 43 5574 mx205022 0x000000FFFFFFFFFFull, /* dma_attr_seg */ 44 5574 mx205022 1, /* dma_attr_sgllen */ 45 5574 mx205022 0x00000001, /* dma_attr_granular */ 46 5574 mx205022 0 47 5574 mx205022 }; 48 5574 mx205022 49 5574 mx205022 static ddi_dma_attr_t hot_tx_dma_attr = { 50 5574 mx205022 DMA_ATTR_V0, /* dma_attr version */ 51 5574 mx205022 0x0000000000000000ull, /* dma_attr_addr_lo */ 52 5574 mx205022 0x000000FFFFFFFFFFull, /* dma_attr_addr_hi */ 53 5574 mx205022 0x0000000000003FFFull, /* dma_attr_count_max */ 54 5574 mx205022 0x0000000000000010ull, /* dma_attr_align */ 55 5574 mx205022 0x00000FFF, /* dma_attr_burstsizes */ 56 5574 mx205022 0x00000001, /* dma_attr_minxfer */ 57 5574 mx205022 0x0000000000003FFFull, /* dma_attr_maxxfer */ 58 5574 mx205022 0x000000FFFFFFFFFFull, /* dma_attr_seg */ 59 5574 mx205022 NGE_MAX_COOKIES, /* dma_attr_sgllen */ 60 5574 mx205022 1, /* dma_attr_granular */ 61 5574 mx205022 0 62 5574 mx205022 }; 63 5574 mx205022 64 5574 mx205022 static ddi_dma_attr_t sum_dma_attr = { 65 5574 mx205022 DMA_ATTR_V0, /* dma_attr version */ 66 5574 mx205022 0x0000000000000000ull, /* dma_attr_addr_lo */ 67 5574 mx205022 0x00000000FFFFFFFFull, /* dma_attr_addr_hi */ 68 5574 mx205022 0x000000007FFFFFFFull, /* dma_attr_count_max */ 69 5574 mx205022 0x0000000000000010ull, /* dma_attr_align */ 70 5574 mx205022 0x00000FFF, /* dma_attr_burstsizes */ 71 5574 mx205022 0x00000001, /* dma_attr_minxfer */ 72 5574 mx205022 0x000000000000FFFFull, /* dma_attr_maxxfer */ 73 5574 mx205022 0x00000000FFFFFFFFull, /* dma_attr_seg */ 74 5574 mx205022 1, /* dma_attr_sgllen */ 75 5574 mx205022 0x00000001, /* dma_attr_granular */ 76 5574 mx205022 0 77 5574 mx205022 }; 78 5574 mx205022 79 5574 mx205022 static ddi_dma_attr_t sum_tx_dma_attr = { 80 5574 mx205022 DMA_ATTR_V0, /* dma_attr version */ 81 5574 mx205022 0x0000000000000000ull, /* dma_attr_addr_lo */ 82 5574 mx205022 0x00000000FFFFFFFFull, /* dma_attr_addr_hi */ 83 5574 mx205022 0x0000000000003FFFull, /* dma_attr_count_max */ 84 5574 mx205022 0x0000000000000010ull, /* dma_attr_align */ 85 5574 mx205022 0x00000FFF, /* dma_attr_burstsizes */ 86 5574 mx205022 0x00000001, /* dma_attr_minxfer */ 87 5574 mx205022 0x0000000000003FFFull, /* dma_attr_maxxfer */ 88 5574 mx205022 0x00000000FFFFFFFFull, /* dma_attr_seg */ 89 5574 mx205022 NGE_MAX_COOKIES, /* dma_attr_sgllen */ 90 5574 mx205022 1, /* dma_attr_granular */ 91 5574 mx205022 0 92 5574 mx205022 }; 93 5574 mx205022 94 5574 mx205022 /* 95 5574 mx205022 * DMA access attributes for data. 96 5574 mx205022 */ 97 5574 mx205022 ddi_device_acc_attr_t nge_data_accattr = { 98 5574 mx205022 DDI_DEVICE_ATTR_V0, 99 5574 mx205022 DDI_STRUCTURE_LE_ACC, 100 5574 mx205022 DDI_STRICTORDER_ACC, 101 5574 mx205022 DDI_DEFAULT_ACC 102 5574 mx205022 }; 103 5574 mx205022 104 5574 mx205022 /* 105 5574 mx205022 * DMA access attributes for descriptors. 106 5574 mx205022 */ 107 5574 mx205022 static ddi_device_acc_attr_t nge_desc_accattr = { 108 5574 mx205022 DDI_DEVICE_ATTR_V0, 109 5574 mx205022 DDI_STRUCTURE_LE_ACC, 110 5574 mx205022 DDI_STRICTORDER_ACC, 111 5574 mx205022 DDI_DEFAULT_ACC 112 5574 mx205022 }; 113 5574 mx205022 114 5574 mx205022 /* 115 5574 mx205022 * PIO access attributes for registers 116 5574 mx205022 */ 117 5574 mx205022 static ddi_device_acc_attr_t nge_reg_accattr = { 118 5574 mx205022 DDI_DEVICE_ATTR_V0, 119 5574 mx205022 DDI_STRUCTURE_LE_ACC, 120 5574 mx205022 DDI_STRICTORDER_ACC, 121 5574 mx205022 DDI_DEFAULT_ACC 122 5574 mx205022 }; 123 5574 mx205022 124 5574 mx205022 /* 125 5574 mx205022 * NIC DESC MODE 2 126 5574 mx205022 */ 127 5574 mx205022 128 5574 mx205022 static const nge_desc_attr_t nge_sum_desc = { 129 5574 mx205022 130 5574 mx205022 sizeof (sum_rx_bd), 131 5574 mx205022 sizeof (sum_tx_bd), 132 5574 mx205022 &sum_dma_attr, 133 5574 mx205022 &sum_tx_dma_attr, 134 5574 mx205022 nge_sum_rxd_fill, 135 5574 mx205022 nge_sum_rxd_check, 136 5574 mx205022 nge_sum_txd_fill, 137 5574 mx205022 nge_sum_txd_check, 138 5574 mx205022 }; 139 5574 mx205022 140 5574 mx205022 /* 141 5574 mx205022 * NIC DESC MODE 3 142 5574 mx205022 */ 143 5574 mx205022 144 5574 mx205022 static const nge_desc_attr_t nge_hot_desc = { 145 5574 mx205022 146 5574 mx205022 sizeof (hot_rx_bd), 147 5574 mx205022 sizeof (hot_tx_bd), 148 5574 mx205022 &hot_dma_attr, 149 5574 mx205022 &hot_tx_dma_attr, 150 5574 mx205022 nge_hot_rxd_fill, 151 5574 mx205022 nge_hot_rxd_check, 152 5574 mx205022 nge_hot_txd_fill, 153 5574 mx205022 nge_hot_txd_check, 154 5574 mx205022 }; 155 5574 mx205022 156 6512 sowmini static char nge_ident[] = "nVidia 1Gb Ethernet"; 157 5574 mx205022 static char clsize_propname[] = "cache-line-size"; 158 5574 mx205022 static char latency_propname[] = "latency-timer"; 159 5574 mx205022 static char debug_propname[] = "nge-debug-flags"; 160 5659 jj146644 static char intr_moderation[] = "intr-moderation"; 161 5574 mx205022 static char rx_data_hw[] = "rx-data-hw"; 162 5574 mx205022 static char rx_prd_lw[] = "rx-prd-lw"; 163 5574 mx205022 static char rx_prd_hw[] = "rx-prd-hw"; 164 5574 mx205022 static char sw_intr_intv[] = "sw-intr-intvl"; 165 5574 mx205022 static char nge_desc_mode[] = "desc-mode"; 166 5574 mx205022 static char default_mtu[] = "default_mtu"; 167 5574 mx205022 static char low_memory_mode[] = "minimal-memory-usage"; 168 5574 mx205022 extern kmutex_t nge_log_mutex[1]; 169 5574 mx205022 170 5574 mx205022 static int nge_m_start(void *); 171 5574 mx205022 static void nge_m_stop(void *); 172 5574 mx205022 static int nge_m_promisc(void *, boolean_t); 173 5574 mx205022 static int nge_m_multicst(void *, boolean_t, const uint8_t *); 174 5574 mx205022 static int nge_m_unicst(void *, const uint8_t *); 175 5574 mx205022 static void nge_m_ioctl(void *, queue_t *, mblk_t *); 176 5574 mx205022 static boolean_t nge_m_getcapab(void *, mac_capab_t, void *); 177 6200 mx205022 static int nge_m_setprop(void *, const char *, mac_prop_id_t, 178 6200 mx205022 uint_t, const void *); 179 6200 mx205022 static int nge_m_getprop(void *, const char *, mac_prop_id_t, 180 8118 Vasumathi uint_t, uint_t, void *, uint_t *); 181 6200 mx205022 static int nge_set_priv_prop(nge_t *, const char *, uint_t, 182 6200 mx205022 const void *); 183 6200 mx205022 static int nge_get_priv_prop(nge_t *, const char *, uint_t, 184 6512 sowmini uint_t, void *); 185 5574 mx205022 186 6200 mx205022 #define NGE_M_CALLBACK_FLAGS\ 187 6200 mx205022 (MC_IOCTL | MC_GETCAPAB | MC_SETPROP | MC_GETPROP) 188 5574 mx205022 189 5574 mx205022 static mac_callbacks_t nge_m_callbacks = { 190 5574 mx205022 NGE_M_CALLBACK_FLAGS, 191 5574 mx205022 nge_m_stat, 192 5574 mx205022 nge_m_start, 193 5574 mx205022 nge_m_stop, 194 5574 mx205022 nge_m_promisc, 195 5574 mx205022 nge_m_multicst, 196 5574 mx205022 nge_m_unicst, 197 5574 mx205022 nge_m_tx, 198 5574 mx205022 nge_m_ioctl, 199 6200 mx205022 nge_m_getcapab, 200 6200 mx205022 NULL, 201 6200 mx205022 NULL, 202 6200 mx205022 nge_m_setprop, 203 6200 mx205022 nge_m_getprop 204 5574 mx205022 }; 205 6512 sowmini 206 6512 sowmini mac_priv_prop_t nge_priv_props[] = { 207 6512 sowmini {"_tx_bcopy_threshold", MAC_PROP_PERM_RW}, 208 6512 sowmini {"_rx_bcopy_threshold", MAC_PROP_PERM_RW}, 209 6512 sowmini {"_recv_max_packet", MAC_PROP_PERM_RW}, 210 6512 sowmini {"_poll_quiet_time", MAC_PROP_PERM_RW}, 211 6512 sowmini {"_poll_busy_time", MAC_PROP_PERM_RW}, 212 6512 sowmini {"_rx_intr_hwater", MAC_PROP_PERM_RW}, 213 6512 sowmini {"_rx_intr_lwater", MAC_PROP_PERM_RW}, 214 6512 sowmini }; 215 6512 sowmini 216 6512 sowmini #define NGE_MAX_PRIV_PROPS \ 217 6512 sowmini (sizeof (nge_priv_props)/sizeof (mac_priv_prop_t)) 218 5574 mx205022 219 5574 mx205022 static int nge_add_intrs(nge_t *, int); 220 5574 mx205022 static void nge_rem_intrs(nge_t *); 221 5574 mx205022 static int nge_register_intrs_and_init_locks(nge_t *); 222 5574 mx205022 223 5574 mx205022 /* 224 5574 mx205022 * NGE MSI tunable: 225 5574 mx205022 */ 226 5574 mx205022 boolean_t nge_enable_msi = B_FALSE; 227 5574 mx205022 228 5574 mx205022 static enum ioc_reply 229 5574 mx205022 nge_set_loop_mode(nge_t *ngep, uint32_t mode) 230 5574 mx205022 { 231 5574 mx205022 /* 232 5574 mx205022 * If the mode isn't being changed, there's nothing to do ... 233 5574 mx205022 */ 234 5574 mx205022 if (mode == ngep->param_loop_mode) 235 5574 mx205022 return (IOC_ACK); 236 5574 mx205022 237 5574 mx205022 /* 238 5574 mx205022 * Validate the requested mode and prepare a suitable message 239 5574 mx205022 * to explain the link down/up cycle that the change will 240 5574 mx205022 * probably induce ... 241 5574 mx205022 */ 242 5574 mx205022 switch (mode) { 243 5574 mx205022 default: 244 5574 mx205022 return (IOC_INVAL); 245 5574 mx205022 246 5574 mx205022 case NGE_LOOP_NONE: 247 5574 mx205022 case NGE_LOOP_EXTERNAL_100: 248 5574 mx205022 case NGE_LOOP_EXTERNAL_10: 249 5574 mx205022 case NGE_LOOP_INTERNAL_PHY: 250 5574 mx205022 break; 251 5574 mx205022 } 252 5574 mx205022 253 5574 mx205022 /* 254 5574 mx205022 * All OK; tell the caller to reprogram 255 5574 mx205022 * the PHY and/or MAC for the new mode ... 256 5574 mx205022 */ 257 5574 mx205022 ngep->param_loop_mode = mode; 258 5574 mx205022 return (IOC_RESTART_ACK); 259 5574 mx205022 } 260 5574 mx205022 261 5574 mx205022 #undef NGE_DBG 262 5574 mx205022 #define NGE_DBG NGE_DBG_INIT 263 5574 mx205022 264 5574 mx205022 /* 265 5574 mx205022 * Utility routine to carve a slice off a chunk of allocated memory, 266 5574 mx205022 * updating the chunk descriptor accordingly. The size of the slice 267 5574 mx205022 * is given by the product of the <qty> and <size> parameters. 268 5574 mx205022 */ 269 5574 mx205022 void 270 5574 mx205022 nge_slice_chunk(dma_area_t *slice, dma_area_t *chunk, 271 5574 mx205022 uint32_t qty, uint32_t size) 272 5574 mx205022 { 273 5574 mx205022 size_t totsize; 274 5574 mx205022 275 5574 mx205022 totsize = qty*size; 276 5574 mx205022 ASSERT(size > 0); 277 5574 mx205022 ASSERT(totsize <= chunk->alength); 278 5574 mx205022 279 5574 mx205022 *slice = *chunk; 280 5574 mx205022 slice->nslots = qty; 281 5574 mx205022 slice->size = size; 282 5574 mx205022 slice->alength = totsize; 283 5574 mx205022 284 5574 mx205022 chunk->mem_va = (caddr_t)chunk->mem_va + totsize; 285 5574 mx205022 chunk->alength -= totsize; 286 5574 mx205022 chunk->offset += totsize; 287 5574 mx205022 chunk->cookie.dmac_laddress += totsize; 288 5574 mx205022 chunk->cookie.dmac_size -= totsize; 289 5574 mx205022 } 290 5574 mx205022 291 5574 mx205022 /* 292 5574 mx205022 * Allocate an area of memory and a DMA handle for accessing it 293 5574 mx205022 */ 294 5574 mx205022 int 295 5574 mx205022 nge_alloc_dma_mem(nge_t *ngep, size_t memsize, ddi_device_acc_attr_t *attr_p, 296 5574 mx205022 uint_t dma_flags, dma_area_t *dma_p) 297 5574 mx205022 { 298 5574 mx205022 int err; 299 5574 mx205022 caddr_t va; 300 5574 mx205022 301 5574 mx205022 NGE_TRACE(("nge_alloc_dma_mem($%p, %ld, $%p, 0x%x, $%p)", 302 5574 mx205022 (void *)ngep, memsize, attr_p, dma_flags, dma_p)); 303 5574 mx205022 /* 304 5574 mx205022 * Allocate handle 305 5574 mx205022 */ 306 5574 mx205022 err = ddi_dma_alloc_handle(ngep->devinfo, ngep->desc_attr.dma_attr, 307 5574 mx205022 DDI_DMA_DONTWAIT, NULL, &dma_p->dma_hdl); 308 5574 mx205022 if (err != DDI_SUCCESS) 309 5574 mx205022 goto fail; 310 5574 mx205022 311 5574 mx205022 /* 312 5574 mx205022 * Allocate memory 313 5574 mx205022 */ 314 5574 mx205022 err = ddi_dma_mem_alloc(dma_p->dma_hdl, memsize, attr_p, 315 5574 mx205022 dma_flags & (DDI_DMA_CONSISTENT | DDI_DMA_STREAMING), 316 5574 mx205022 DDI_DMA_DONTWAIT, NULL, &va, &dma_p->alength, &dma_p->acc_hdl); 317 5574 mx205022 if (err != DDI_SUCCESS) 318 5574 mx205022 goto fail; 319 5574 mx205022 320 5574 mx205022 /* 321 5574 mx205022 * Bind the two together 322 5574 mx205022 */ 323 5574 mx205022 dma_p->mem_va = va; 324 5574 mx205022 err = ddi_dma_addr_bind_handle(dma_p->dma_hdl, NULL, 325 5574 mx205022 va, dma_p->alength, dma_flags, DDI_DMA_DONTWAIT, NULL, 326 5574 mx205022 &dma_p->cookie, &dma_p->ncookies); 327 5574 mx205022 328 5574 mx205022 if (err != DDI_DMA_MAPPED || dma_p->ncookies != 1) 329 5574 mx205022 goto fail; 330 5574 mx205022 331 5574 mx205022 dma_p->nslots = ~0U; 332 5574 mx205022 dma_p->size = ~0U; 333 5574 mx205022 dma_p->offset = 0; 334 5574 mx205022 335 5574 mx205022 return (DDI_SUCCESS); 336 5574 mx205022 337 5574 mx205022 fail: 338 5574 mx205022 nge_free_dma_mem(dma_p); 339 5574 mx205022 NGE_DEBUG(("nge_alloc_dma_mem: fail to alloc dma memory!")); 340 5574 mx205022 341 5574 mx205022 return (DDI_FAILURE); 342 5574 mx205022 } 343 5574 mx205022 344 5574 mx205022 /* 345 5574 mx205022 * Free one allocated area of DMAable memory 346 5574 mx205022 */ 347 5574 mx205022 void 348 5574 mx205022 nge_free_dma_mem(dma_area_t *dma_p) 349 5574 mx205022 { 350 5574 mx205022 if (dma_p->dma_hdl != NULL) { 351 5574 mx205022 if (dma_p->ncookies) { 352 5574 mx205022 (void) ddi_dma_unbind_handle(dma_p->dma_hdl); 353 5574 mx205022 dma_p->ncookies = 0; 354 5574 mx205022 } 355 5574 mx205022 } 356 5574 mx205022 if (dma_p->acc_hdl != NULL) { 357 5574 mx205022 ddi_dma_mem_free(&dma_p->acc_hdl); 358 5574 mx205022 dma_p->acc_hdl = NULL; 359 5574 mx205022 } 360 5574 mx205022 if (dma_p->dma_hdl != NULL) { 361 5574 mx205022 ddi_dma_free_handle(&dma_p->dma_hdl); 362 5574 mx205022 dma_p->dma_hdl = NULL; 363 5574 mx205022 } 364 5574 mx205022 } 365 5574 mx205022 366 5574 mx205022 #define ALLOC_TX_BUF 0x1 367 5574 mx205022 #define ALLOC_TX_DESC 0x2 368 5574 mx205022 #define ALLOC_RX_DESC 0x4 369 5574 mx205022 370 5574 mx205022 int 371 5574 mx205022 nge_alloc_bufs(nge_t *ngep) 372 5574 mx205022 { 373 5574 mx205022 int err; 374 5574 mx205022 int split; 375 5574 mx205022 int progress; 376 5574 mx205022 size_t txbuffsize; 377 5574 mx205022 size_t rxdescsize; 378 5574 mx205022 size_t txdescsize; 379 5574 mx205022 380 5574 mx205022 txbuffsize = ngep->tx_desc * ngep->buf_size; 381 5574 mx205022 rxdescsize = ngep->rx_desc; 382 5574 mx205022 txdescsize = ngep->tx_desc; 383 5574 mx205022 rxdescsize *= ngep->desc_attr.rxd_size; 384 5574 mx205022 txdescsize *= ngep->desc_attr.txd_size; 385 5574 mx205022 progress = 0; 386 5574 mx205022 387 5574 mx205022 NGE_TRACE(("nge_alloc_bufs($%p)", (void *)ngep)); 388 5574 mx205022 /* 389 5574 mx205022 * Allocate memory & handles for TX buffers 390 5574 mx205022 */ 391 5574 mx205022 ASSERT((txbuffsize % ngep->nge_split) == 0); 392 5574 mx205022 for (split = 0; split < ngep->nge_split; ++split) { 393 5574 mx205022 err = nge_alloc_dma_mem(ngep, txbuffsize/ngep->nge_split, 394 5574 mx205022 &nge_data_accattr, DDI_DMA_WRITE | NGE_DMA_MODE, 395 5574 mx205022 &ngep->send->buf[split]); 396 5574 mx205022 if (err != DDI_SUCCESS) 397 5574 mx205022 goto fail; 398 5574 mx205022 } 399 5574 mx205022 400 5574 mx205022 progress |= ALLOC_TX_BUF; 401 5574 mx205022 402 5574 mx205022 /* 403 5574 mx205022 * Allocate memory & handles for receive return rings and 404 5574 mx205022 * buffer (producer) descriptor rings 405 5574 mx205022 */ 406 5574 mx205022 err = nge_alloc_dma_mem(ngep, rxdescsize, &nge_desc_accattr, 407 5574 mx205022 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, &ngep->recv->desc); 408 5574 mx205022 if (err != DDI_SUCCESS) 409 5574 mx205022 goto fail; 410 5574 mx205022 progress |= ALLOC_RX_DESC; 411 5574 mx205022 412 5574 mx205022 /* 413 5574 mx205022 * Allocate memory & handles for TX descriptor rings, 414 5574 mx205022 */ 415 5574 mx205022 err = nge_alloc_dma_mem(ngep, txdescsize, &nge_desc_accattr, 416 5574 mx205022 DDI_DMA_RDWR | DDI_DMA_CONSISTENT, &ngep->send->desc); 417 5574 mx205022 if (err != DDI_SUCCESS) 418 5574 mx205022 goto fail; 419 5574 mx205022 return (DDI_SUCCESS); 420 5574 mx205022 421 5574 mx205022 fail: 422 5574 mx205022 if (progress & ALLOC_RX_DESC) 423 5574 mx205022 nge_free_dma_mem(&ngep->recv->desc); 424 5574 mx205022 if (progress & ALLOC_TX_BUF) { 425 5574 mx205022 for (split = 0; split < ngep->nge_split; ++split) 426 5574 mx205022 nge_free_dma_mem(&ngep->send->buf[split]); 427 5574 mx205022 } 428 5574 mx205022 429 5574 mx205022 return (DDI_FAILURE); 430 5574 mx205022 } 431 5574 mx205022 432 5574 mx205022 /* 433 5574 mx205022 * This routine frees the transmit and receive buffers and descriptors. 434 5574 mx205022 * Make sure the chip is stopped before calling it! 435 5574 mx205022 */ 436 5574 mx205022 void 437 5574 mx205022 nge_free_bufs(nge_t *ngep) 438 5574 mx205022 { 439 5574 mx205022 int split; 440 5574 mx205022 441 5574 mx205022 NGE_TRACE(("nge_free_bufs($%p)", (void *)ngep)); 442 5574 mx205022 443 5574 mx205022 nge_free_dma_mem(&ngep->recv->desc); 444 5574 mx205022 nge_free_dma_mem(&ngep->send->desc); 445 5574 mx205022 446 5574 mx205022 for (split = 0; split < ngep->nge_split; ++split) 447 5574 mx205022 nge_free_dma_mem(&ngep->send->buf[split]); 448 5574 mx205022 } 449 5574 mx205022 450 5574 mx205022 /* 451 5574 mx205022 * Clean up initialisation done above before the memory is freed 452 5574 mx205022 */ 453 5574 mx205022 static void 454 5574 mx205022 nge_fini_send_ring(nge_t *ngep) 455 5574 mx205022 { 456 5574 mx205022 uint32_t slot; 457 5574 mx205022 size_t dmah_num; 458 5574 mx205022 send_ring_t *srp; 459 5574 mx205022 sw_tx_sbd_t *ssbdp; 460 5574 mx205022 461 5574 mx205022 srp = ngep->send; 462 5574 mx205022 ssbdp = srp->sw_sbds; 463 5574 mx205022 464 5574 mx205022 NGE_TRACE(("nge_fini_send_ring($%p)", (void *)ngep)); 465 5574 mx205022 466 5574 mx205022 dmah_num = sizeof (srp->dmahndl) / sizeof (srp->dmahndl[0]); 467 5574 mx205022 468 5574 mx205022 for (slot = 0; slot < dmah_num; ++slot) { 469 5574 mx205022 if (srp->dmahndl[slot].hndl) { 470 5574 mx205022 (void) ddi_dma_unbind_handle(srp->dmahndl[slot].hndl); 471 5574 mx205022 ddi_dma_free_handle(&srp->dmahndl[slot].hndl); 472 5574 mx205022 srp->dmahndl[slot].hndl = NULL; 473 5574 mx205022 srp->dmahndl[slot].next = NULL; 474 5574 mx205022 } 475 5574 mx205022 } 476 5574 mx205022 477 5574 mx205022 srp->dmah_free.head = NULL; 478 5574 mx205022 srp->dmah_free.tail = NULL; 479 5574 mx205022 480 5574 mx205022 kmem_free(ssbdp, srp->desc.nslots*sizeof (*ssbdp)); 481 5574 mx205022 482 5574 mx205022 } 483 5574 mx205022 484 5574 mx205022 /* 485 5574 mx205022 * Initialise the specified Send Ring, using the information in the 486 5574 mx205022 * <dma_area> descriptors that it contains to set up all the other 487 5574 mx205022 * fields. This routine should be called only once for each ring. 488 5574 mx205022 */ 489 5574 mx205022 static int 490 5574 mx205022 nge_init_send_ring(nge_t *ngep) 491 5574 mx205022 { 492 5574 mx205022 size_t dmah_num; 493 5574 mx205022 uint32_t nslots; 494 5574 mx205022 uint32_t err; 495 5574 mx205022 uint32_t slot; 496 5574 mx205022 uint32_t split; 497 5574 mx205022 send_ring_t *srp; 498 5574 mx205022 sw_tx_sbd_t *ssbdp; 499 5574 mx205022 dma_area_t desc; 500 5574 mx205022 dma_area_t pbuf; 501 5574 mx205022 502 5574 mx205022 srp = ngep->send; 503 5574 mx205022 srp->desc.nslots = ngep->tx_desc; 504 5574 mx205022 nslots = srp->desc.nslots; 505 5574 mx205022 506 5574 mx205022 NGE_TRACE(("nge_init_send_ring($%p)", (void *)ngep)); 507 5574 mx205022 /* 508 5574 mx205022 * Other one-off initialisation of per-ring data 509 5574 mx205022 */ 510 5574 mx205022 srp->ngep = ngep; 511 5574 mx205022 512 5574 mx205022 /* 513 5574 mx205022 * Allocate the array of s/w Send Buffer Descriptors 514 5574 mx205022 */ 515 5574 mx205022 ssbdp = kmem_zalloc(nslots*sizeof (*ssbdp), KM_SLEEP); 516 5574 mx205022 srp->sw_sbds = ssbdp; 517 5574 mx205022 518 5574 mx205022 /* 519 5574 mx205022 * Now initialise each array element once and for all 520 5574 mx205022 */ 521 5574 mx205022 desc = srp->desc; 522 5574 mx205022 for (split = 0; split < ngep->nge_split; ++split) { 523 5574 mx205022 pbuf = srp->buf[split]; 524 5574 mx205022 for (slot = 0; slot < nslots/ngep->nge_split; ++ssbdp, ++slot) { 525 5574 mx205022 nge_slice_chunk(&ssbdp->desc, &desc, 1, 526 5574 mx205022 ngep->desc_attr.txd_size); 527 5574 mx205022 nge_slice_chunk(&ssbdp->pbuf, &pbuf, 1, 528 5574 mx205022 ngep->buf_size); 529 5574 mx205022 } 530 5574 mx205022 ASSERT(pbuf.alength == 0); 531 5574 mx205022 } 532 5574 mx205022 ASSERT(desc.alength == 0); 533 5574 mx205022 534 5574 mx205022 dmah_num = sizeof (srp->dmahndl) / sizeof (srp->dmahndl[0]); 535 5574 mx205022 536 5574 mx205022 /* preallocate dma handles for tx buffer */ 537 5574 mx205022 for (slot = 0; slot < dmah_num; ++slot) { 538 5574 mx205022 539 5574 mx205022 err = ddi_dma_alloc_handle(ngep->devinfo, 540 5574 mx205022 ngep->desc_attr.tx_dma_attr, DDI_DMA_DONTWAIT, 541 5574 mx205022 NULL, &srp->dmahndl[slot].hndl); 542 5574 mx205022 543 5574 mx205022 if (err != DDI_SUCCESS) { 544 5574 mx205022 nge_fini_send_ring(ngep); 545 5574 mx205022 nge_error(ngep, 546 5574 mx205022 "nge_init_send_ring: alloc dma handle fails"); 547 5574 mx205022 return (DDI_FAILURE); 548 5574 mx205022 } 549 5574 mx205022 srp->dmahndl[slot].next = srp->dmahndl + slot + 1; 550 5574 mx205022 } 551 5574 mx205022 552 5574 mx205022 srp->dmah_free.head = srp->dmahndl; 553 5574 mx205022 srp->dmah_free.tail = srp->dmahndl + dmah_num - 1; 554 5574 mx205022 srp->dmah_free.tail->next = NULL; 555 5574 mx205022 556 5574 mx205022 return (DDI_SUCCESS); 557 5574 mx205022 } 558 5574 mx205022 559 5574 mx205022 /* 560 5574 mx205022 * Intialize the tx recycle pointer and tx sending pointer of tx ring 561 5574 mx205022 * and set the type of tx's data descriptor by default. 562 5574 mx205022 */ 563 5574 mx205022 static void 564 5574 mx205022 nge_reinit_send_ring(nge_t *ngep) 565 5574 mx205022 { 566 5574 mx205022 size_t dmah_num; 567 5574 mx205022 uint32_t slot; 568 5574 mx205022 send_ring_t *srp; 569 5574 mx205022 sw_tx_sbd_t *ssbdp; 570 5574 mx205022 571 5574 mx205022 srp = ngep->send; 572 5574 mx205022 573 5574 mx205022 /* 574 5574 mx205022 * Reinitialise control variables ... 575 5574 mx205022 */ 576 5574 mx205022 577 5574 mx205022 srp->tx_hwmark = NGE_DESC_MIN; 578 5574 mx205022 srp->tx_lwmark = NGE_DESC_MIN; 579 5574 mx205022 580 5574 mx205022 srp->tx_next = 0; 581 5574 mx205022 srp->tx_free = srp->desc.nslots; 582 5574 mx205022 srp->tc_next = 0; 583 5574 mx205022 584 5574 mx205022 dmah_num = sizeof (srp->dmahndl) / sizeof (srp->dmahndl[0]); 585 5574 mx205022 586 5574 mx205022 for (slot = 0; slot - dmah_num != 0; ++slot) 587 5574 mx205022 srp->dmahndl[slot].next = srp->dmahndl + slot + 1; 588 5574 mx205022 589 5574 mx205022 srp->dmah_free.head = srp->dmahndl; 590 5574 mx205022 srp->dmah_free.tail = srp->dmahndl + dmah_num - 1; 591 5574 mx205022 srp->dmah_free.tail->next = NULL; 592 5574 mx205022 593 5574 mx205022 /* 594 5574 mx205022 * Zero and sync all the h/w Send Buffer Descriptors 595 5574 mx205022 */ 596 5574 mx205022 for (slot = 0; slot < srp->desc.nslots; ++slot) { 597 5574 mx205022 ssbdp = &srp->sw_sbds[slot]; 598 5574 mx205022 ssbdp->flags = HOST_OWN; 599 5574 mx205022 } 600 5574 mx205022 601 5574 mx205022 DMA_ZERO(srp->desc); 602 5574 mx205022 DMA_SYNC(srp->desc, DDI_DMA_SYNC_FORDEV); 603 5574 mx205022 } 604 5574 mx205022 605 5574 mx205022 /* 606 5574 mx205022 * Initialize the slot number of rx's ring 607 5574 mx205022 */ 608 5574 mx205022 static void 609 5574 mx205022 nge_init_recv_ring(nge_t *ngep) 610 5574 mx205022 { 611 5574 mx205022 recv_ring_t *rrp; 612 5574 mx205022 613 5574 mx205022 rrp = ngep->recv; 614 5574 mx205022 rrp->desc.nslots = ngep->rx_desc; 615 5574 mx205022 rrp->ngep = ngep; 616 5574 mx205022 } 617 5574 mx205022 618 5574 mx205022 /* 619 5574 mx205022 * Intialize the rx recycle pointer and rx sending pointer of rx ring 620 5574 mx205022 */ 621 5574 mx205022 static void 622 5574 mx205022 nge_reinit_recv_ring(nge_t *ngep) 623 5574 mx205022 { 624 5574 mx205022 recv_ring_t *rrp; 625 5574 mx205022 626 5574 mx205022 rrp = ngep->recv; 627 5574 mx205022 628 5574 mx205022 /* 629 5574 mx205022 * Reinitialise control variables ... 630 5574 mx205022 */ 631 5574 mx205022 rrp->prod_index = 0; 632 5574 mx205022 /* 633 5574 mx205022 * Zero and sync all the h/w Send Buffer Descriptors 634 5574 mx205022 */ 635 5574 mx205022 DMA_ZERO(rrp->desc); 636 5574 mx205022 DMA_SYNC(rrp->desc, DDI_DMA_SYNC_FORDEV); 637 5574 mx205022 } 638 5574 mx205022 639 5574 mx205022 /* 640 5574 mx205022 * Clean up initialisation done above before the memory is freed 641 5574 mx205022 */ 642 5574 mx205022 static void 643 5574 mx205022 nge_fini_buff_ring(nge_t *ngep) 644 5574 mx205022 { 645 5574 mx205022 uint32_t i; 646 5574 mx205022 buff_ring_t *brp; 647 5574 mx205022 dma_area_t *bufp; 648 5574 mx205022 sw_rx_sbd_t *bsbdp; 649 5574 mx205022 650 5574 mx205022 brp = ngep->buff; 651 5574 mx205022 bsbdp = brp->sw_rbds; 652 5574 mx205022 653 5574 mx205022 NGE_DEBUG(("nge_fini_buff_ring($%p)", (void *)ngep)); 654 5574 mx205022 655 5574 mx205022 mutex_enter(brp->recycle_lock); 656 5574 mx205022 brp->buf_sign++; 657 5574 mx205022 mutex_exit(brp->recycle_lock); 658 5574 mx205022 for (i = 0; i < ngep->rx_desc; i++, ++bsbdp) { 659 5574 mx205022 if (bsbdp->bufp) { 660 5574 mx205022 if (bsbdp->bufp->mp) 661 5574 mx205022 freemsg(bsbdp->bufp->mp); 662 5574 mx205022 nge_free_dma_mem(bsbdp->bufp); 663 5574 mx205022 kmem_free(bsbdp->bufp, sizeof (dma_area_t)); 664 5574 mx205022 bsbdp->bufp = NULL; 665 5574 mx205022 } 666 5574 mx205022 } 667 5574 mx205022 while (brp->free_list != NULL) { 668 5574 mx205022 bufp = brp->free_list; 669 5574 mx205022 brp->free_list = bufp->next; 670 5574 mx205022 bufp->next = NULL; 671 5574 mx205022 if (bufp->mp) 672 5574 mx205022 freemsg(bufp->mp); 673 5574 mx205022 nge_free_dma_mem(bufp); 674 5574 mx205022 kmem_free(bufp, sizeof (dma_area_t)); 675 5574 mx205022 } 676 5574 mx205022 while (brp->recycle_list != NULL) { 677 5574 mx205022 bufp = brp->recycle_list; 678 5574 mx205022 brp->recycle_list = bufp->next; 679 5574 mx205022 bufp->next = NULL; 680 5574 mx205022 if (bufp->mp) 681 5574 mx205022 freemsg(bufp->mp); 682 5574 mx205022 nge_free_dma_mem(bufp); 683 5574 mx205022 kmem_free(bufp, sizeof (dma_area_t)); 684 5574 mx205022 } 685 5574 mx205022 686 5574 mx205022 687 5574 mx205022 kmem_free(brp->sw_rbds, (ngep->rx_desc * sizeof (*bsbdp))); 688 5574 mx205022 brp->sw_rbds = NULL; 689 5574 mx205022 } 690 5574 mx205022 691 5574 mx205022 /* 692 5574 mx205022 * Intialize the Rx's data ring and free ring 693 5574 mx205022 */ 694 5574 mx205022 static int 695 5574 mx205022 nge_init_buff_ring(nge_t *ngep) 696 5574 mx205022 { 697 5574 mx205022 uint32_t err; 698 5574 mx205022 uint32_t slot; 699 5574 mx205022 uint32_t nslots_buff; 700 5574 mx205022 uint32_t nslots_recv; 701 5574 mx205022 buff_ring_t *brp; 702 5574 mx205022 recv_ring_t *rrp; 703 5574 mx205022 dma_area_t desc; 704 5574 mx205022 dma_area_t *bufp; 705 5574 mx205022 sw_rx_sbd_t *bsbdp; 706 5574 mx205022 707 5574 mx205022 rrp = ngep->recv; 708 5574 mx205022 brp = ngep->buff; 709 5574 mx205022 brp->nslots = ngep->rx_buf; 710 5574 mx205022 brp->rx_bcopy = B_FALSE; 711 5574 mx205022 nslots_recv = rrp->desc.nslots; 712 5574 mx205022 nslots_buff = brp->nslots; 713 5574 mx205022 brp->ngep = ngep; 714 5574 mx205022 715 5574 mx205022 NGE_TRACE(("nge_init_buff_ring($%p)", (void *)ngep)); 716 5574 mx205022 717 5574 mx205022 /* 718 5574 mx205022 * Allocate the array of s/w Recv Buffer Descriptors 719 5574 mx205022 */ 720 5574 mx205022 bsbdp = kmem_zalloc(nslots_recv *sizeof (*bsbdp), KM_SLEEP); 721 5574 mx205022 brp->sw_rbds = bsbdp; 722 5574 mx205022 brp->free_list = NULL; 723 5574 mx205022 brp->recycle_list = NULL; 724 5574 mx205022 for (slot = 0; slot < nslots_buff; ++slot) { 725 5574 mx205022 bufp = kmem_zalloc(sizeof (dma_area_t), KM_SLEEP); 726 5574 mx205022 err = nge_alloc_dma_mem(ngep, (ngep->buf_size 727 5574 mx205022 + NGE_HEADROOM), 728 5574 mx205022 &nge_data_accattr, DDI_DMA_READ | NGE_DMA_MODE, bufp); 729 5574 mx205022 if (err != DDI_SUCCESS) { 730 5574 mx205022 kmem_free(bufp, sizeof (dma_area_t)); 731 5574 mx205022 return (DDI_FAILURE); 732 5574 mx205022 } 733 5574 mx205022 734 5574 mx205022 bufp->alength -= NGE_HEADROOM; 735 5574 mx205022 bufp->offset += NGE_HEADROOM; 736 5574 mx205022 bufp->private = (caddr_t)ngep; 737 5574 mx205022 bufp->rx_recycle.free_func = nge_recv_recycle; 738 5574 mx205022 bufp->rx_recycle.free_arg = (caddr_t)bufp; 739 5574 mx205022 bufp->signature = brp->buf_sign; 740 5574 mx205022 bufp->rx_delivered = B_FALSE; 741 5574 mx205022 bufp->mp = desballoc(DMA_VPTR(*bufp), 742 5574 mx205022 ngep->buf_size + NGE_HEADROOM, 743 5574 mx205022 0, &bufp->rx_recycle); 744 5574 mx205022 745 5574 mx205022 if (bufp->mp == NULL) { 746 5574 mx205022 return (DDI_FAILURE); 747 5574 mx205022 } 748 5574 mx205022 bufp->next = brp->free_list; 749 5574 mx205022 brp->free_list = bufp; 750 5574 mx205022 } 751 5574 mx205022 752 5574 mx205022 /* 753 5574 mx205022 * Now initialise each array element once and for all 754 5574 mx205022 */ 755 5574 mx205022 desc = rrp->desc; 756 5574 mx205022 for (slot = 0; slot < nslots_recv; ++slot, ++bsbdp) { 757 5574 mx205022 nge_slice_chunk(&bsbdp->desc, &desc, 1, 758 5574 mx205022 ngep->desc_attr.rxd_size); 759 5574 mx205022 bufp = brp->free_list; 760 5574 mx205022 brp->free_list = bufp->next; 761 5574 mx205022 bsbdp->bufp = bufp; 762 5574 mx205022 bsbdp->flags = CONTROLER_OWN; 763 5574 mx205022 bufp->next = NULL; 764 5574 mx205022 } 765 5574 mx205022 766 5574 mx205022 ASSERT(desc.alength == 0); 767 5574 mx205022 return (DDI_SUCCESS); 768 5574 mx205022 } 769 5574 mx205022 770 5574 mx205022 /* 771 5574 mx205022 * Fill the host address of data in rx' descriptor 772 5574 mx205022 * and initialize free pointers of rx free ring 773 5574 mx205022 */ 774 5574 mx205022 static int 775 5574 mx205022 nge_reinit_buff_ring(nge_t *ngep) 776 5574 mx205022 { 777 5574 mx205022 uint32_t slot; 778 5574 mx205022 uint32_t nslots_recv; 779 5574 mx205022 buff_ring_t *brp; 780 5574 mx205022 recv_ring_t *rrp; 781 5574 mx205022 sw_rx_sbd_t *bsbdp; 782 5574 mx205022 void *hw_bd_p; 783 5574 mx205022 784 5574 mx205022 brp = ngep->buff; 785 5574 mx205022 rrp = ngep->recv; 786 5574 mx205022 bsbdp = brp->sw_rbds; 787 5574 mx205022 nslots_recv = rrp->desc.nslots; 788 5574 mx205022 for (slot = 0; slot < nslots_recv; ++bsbdp, ++slot) { 789 5574 mx205022 hw_bd_p = DMA_VPTR(bsbdp->desc); 790 5574 mx205022 /* 791 5574 mx205022 * There is a scenario: When the traffic of small tcp 792 5574 mx205022 * packet is heavy, suspending the tcp traffic will 793 5574 mx205022 * cause the preallocated buffers for rx not to be 794 5574 mx205022 * released in time by tcp taffic and cause rx's buffer 795 5574 mx205022 * pointers not to be refilled in time. 796 5574 mx205022 * 797 5574 mx205022 * At this point, if we reinitialize the driver, the bufp 798 5574 mx205022 * pointer for rx's traffic will be NULL. 799 5574 mx205022 * So the result of the reinitializion fails. 800 5574 mx205022 */ 801 5574 mx205022 if (bsbdp->bufp == NULL) 802 5574 mx205022 return (DDI_FAILURE); 803 5574 mx205022 804 5574 mx205022 ngep->desc_attr.rxd_fill(hw_bd_p, &bsbdp->bufp->cookie, 805 5574 mx205022 bsbdp->bufp->alength); 806 5574 mx205022 } 807 5574 mx205022 return (DDI_SUCCESS); 808 5574 mx205022 } 809 5574 mx205022 810 5574 mx205022 static void 811 5574 mx205022 nge_init_ring_param_lock(nge_t *ngep) 812 5574 mx205022 { 813 5574 mx205022 buff_ring_t *brp; 814 5574 mx205022 send_ring_t *srp; 815 5574 mx205022 816 5574 mx205022 srp = ngep->send; 817 5574 mx205022 brp = ngep->buff; 818 5574 mx205022 819 5574 mx205022 /* Init the locks for send ring */ 820 5574 mx205022 mutex_init(srp->tx_lock, NULL, MUTEX_DRIVER, 821 5574 mx205022 DDI_INTR_PRI(ngep->intr_pri)); 822 5574 mx205022 mutex_init(srp->tc_lock, NULL, MUTEX_DRIVER, 823 5574 mx205022 DDI_INTR_PRI(ngep->intr_pri)); 824 5574 mx205022 mutex_init(&srp->dmah_lock, NULL, MUTEX_DRIVER, 825 5574 mx205022 DDI_INTR_PRI(ngep->intr_pri)); 826 5574 mx205022 827 5574 mx205022 /* Init parameters of buffer ring */ 828 5574 mx205022 brp->free_list = NULL; 829 5574 mx205022 brp->recycle_list = NULL; 830 5574 mx205022 brp->rx_hold = 0; 831 5574 mx205022 brp->buf_sign = 0; 832 5574 mx205022 833 5574 mx205022 /* Init recycle list lock */ 834 5574 mx205022 mutex_init(brp->recycle_lock, NULL, MUTEX_DRIVER, 835 5574 mx205022 DDI_INTR_PRI(ngep->intr_pri)); 836 5574 mx205022 } 837 5574 mx205022 838 5574 mx205022 int 839 5574 mx205022 nge_init_rings(nge_t *ngep) 840 5574 mx205022 { 841 5574 mx205022 uint32_t err; 842 5574 mx205022 843 5574 mx205022 err = nge_init_send_ring(ngep); 844 5574 mx205022 if (err != DDI_SUCCESS) { 845 5574 mx205022 return (err); 846 5574 mx205022 } 847 5574 mx205022 nge_init_recv_ring(ngep); 848 5574 mx205022 849 5574 mx205022 err = nge_init_buff_ring(ngep); 850 5574 mx205022 if (err != DDI_SUCCESS) { 851 5574 mx205022 nge_fini_send_ring(ngep); 852 5574 mx205022 return (DDI_FAILURE); 853 5574 mx205022 } 854 5574 mx205022 855 5574 mx205022 return (err); 856 5574 mx205022 } 857 5574 mx205022 858 5574 mx205022 static int 859 5574 mx205022 nge_reinit_ring(nge_t *ngep) 860 5574 mx205022 { 861 5574 mx205022 int err; 862 5574 mx205022 863 5574 mx205022 nge_reinit_recv_ring(ngep); 864 5574 mx205022 nge_reinit_send_ring(ngep); 865 5574 mx205022 err = nge_reinit_buff_ring(ngep); 866 5574 mx205022 return (err); 867 5574 mx205022 } 868 5574 mx205022 869 5574 mx205022 870 5574 mx205022 void 871 5574 mx205022 nge_fini_rings(nge_t *ngep) 872 5574 mx205022 { 873 5574 mx205022 /* 874 5574 mx205022 * For receive ring, nothing need to be finished. 875 5574 mx205022 * So only finish buffer ring and send ring here. 876 5574 mx205022 */ 877 5574 mx205022 nge_fini_buff_ring(ngep); 878 5574 mx205022 nge_fini_send_ring(ngep); 879 5574 mx205022 } 880 5574 mx205022 881 5574 mx205022 /* 882 5574 mx205022 * Loopback ioctl code 883 5574 mx205022 */ 884 5574 mx205022 885 5574 mx205022 static lb_property_t loopmodes[] = { 886 5574 mx205022 { normal, "normal", NGE_LOOP_NONE }, 887 5574 mx205022 { external, "100Mbps", NGE_LOOP_EXTERNAL_100 }, 888 5574 mx205022 { external, "10Mbps", NGE_LOOP_EXTERNAL_10 }, 889 5574 mx205022 { internal, "PHY", NGE_LOOP_INTERNAL_PHY }, 890 5574 mx205022 }; 891 5574 mx205022 892 5574 mx205022 enum ioc_reply 893 5574 mx205022 nge_loop_ioctl(nge_t *ngep, mblk_t *mp, struct iocblk *iocp) 894 5574 mx205022 { 895 5574 mx205022 int cmd; 896 5574 mx205022 uint32_t *lbmp; 897 5574 mx205022 lb_info_sz_t *lbsp; 898 5574 mx205022 lb_property_t *lbpp; 899 5574 mx205022 900 5574 mx205022 /* 901 5574 mx205022 * Validate format of ioctl 902 5574 mx205022 */ 903 5574 mx205022 if (mp->b_cont == NULL) 904 5574 mx205022 return (IOC_INVAL); 905 5574 mx205022 906 5574 mx205022 cmd = iocp->ioc_cmd; 907 5574 mx205022 908 5574 mx205022 switch (cmd) { 909 5574 mx205022 default: 910 5574 mx205022 return (IOC_INVAL); 911 5574 mx205022 912 5574 mx205022 case LB_GET_INFO_SIZE: 913 5574 mx205022 if (iocp->ioc_count != sizeof (lb_info_sz_t)) 914 5574 mx205022 return (IOC_INVAL); 915 5574 mx205022 lbsp = (lb_info_sz_t *)mp->b_cont->b_rptr; 916 5574 mx205022 *lbsp = sizeof (loopmodes); 917 5574 mx205022 return (IOC_REPLY); 918 5574 mx205022 919 5574 mx205022 case LB_GET_INFO: 920 5574 mx205022 if (iocp->ioc_count != sizeof (loopmodes)) 921 5574 mx205022 return (IOC_INVAL); 922 5574 mx205022 lbpp = (lb_property_t *)mp->b_cont->b_rptr; 923 5574 mx205022 bcopy(loopmodes, lbpp, sizeof (loopmodes)); 924 5574 mx205022 return (IOC_REPLY); 925 5574 mx205022 926 5574 mx205022 case LB_GET_MODE: 927 5574 mx205022 if (iocp->ioc_count != sizeof (uint32_t)) 928 5574 mx205022 return (IOC_INVAL); 929 5574 mx205022 lbmp = (uint32_t *)mp->b_cont->b_rptr; 930 5574 mx205022 *lbmp = ngep->param_loop_mode; 931 5574 mx205022 return (IOC_REPLY); 932 5574 mx205022 933 5574 mx205022 case LB_SET_MODE: 934 5574 mx205022 if (iocp->ioc_count != sizeof (uint32_t)) 935 5574 mx205022 return (IOC_INVAL); 936 5574 mx205022 lbmp = (uint32_t *)mp->b_cont->b_rptr; 937 5574 mx205022 return (nge_set_loop_mode(ngep, *lbmp)); 938 5574 mx205022 } 939 5574 mx205022 } 940 5574 mx205022 941 5574 mx205022 #undef NGE_DBG 942 5574 mx205022 #define NGE_DBG NGE_DBG_NEMO 943 5574 mx205022 944 5574 mx205022 945 5574 mx205022 static void 946 5574 mx205022 nge_check_desc_prop(nge_t *ngep) 947 5574 mx205022 { 948 5574 mx205022 if (ngep->desc_mode != DESC_HOT && ngep->desc_mode != DESC_OFFLOAD) 949 5574 mx205022 ngep->desc_mode = DESC_HOT; 950 5574 mx205022 951 5574 mx205022 if (ngep->desc_mode == DESC_OFFLOAD) { 952 5574 mx205022 953 5574 mx205022 ngep->desc_attr = nge_sum_desc; 954 5574 mx205022 955 5574 mx205022 } else if (ngep->desc_mode == DESC_HOT) { 956 5574 mx205022 957 5574 mx205022 ngep->desc_attr = nge_hot_desc; 958 5574 mx205022 } 959 5574 mx205022 } 960 5574 mx205022 961 5574 mx205022 /* 962 5574 mx205022 * nge_get_props -- get the parameters to tune the driver 963 5574 mx205022 */ 964 5574 mx205022 static void 965 5574 mx205022 nge_get_props(nge_t *ngep) 966 5574 mx205022 { 967 5574 mx205022 chip_info_t *infop; 968 5574 mx205022 dev_info_t *devinfo; 969 5574 mx205022 nge_dev_spec_param_t *dev_param_p; 970 5574 mx205022 971 5574 mx205022 devinfo = ngep->devinfo; 972 5574 mx205022 infop = (chip_info_t *)&ngep->chipinfo; 973 5574 mx205022 dev_param_p = &ngep->dev_spec_param; 974 5574 mx205022 975 5574 mx205022 infop->clsize = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 976 5574 mx205022 DDI_PROP_DONTPASS, clsize_propname, 32); 977 5574 mx205022 978 5574 mx205022 infop->latency = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 979 5574 mx205022 DDI_PROP_DONTPASS, latency_propname, 64); 980 5659 jj146644 ngep->intr_moderation = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 981 5659 jj146644 DDI_PROP_DONTPASS, intr_moderation, NGE_SET); 982 5574 mx205022 ngep->rx_datahwm = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 983 5574 mx205022 DDI_PROP_DONTPASS, rx_data_hw, 0x20); 984 5574 mx205022 ngep->rx_prdlwm = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 985 5574 mx205022 DDI_PROP_DONTPASS, rx_prd_lw, 0x4); 986 5574 mx205022 ngep->rx_prdhwm = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 987 5574 mx205022 DDI_PROP_DONTPASS, rx_prd_hw, 0xc); 988 5574 mx205022 989 5574 mx205022 ngep->sw_intr_intv = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 990 5574 mx205022 DDI_PROP_DONTPASS, sw_intr_intv, SWTR_ITC); 991 5574 mx205022 ngep->debug = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 992 5574 mx205022 DDI_PROP_DONTPASS, debug_propname, NGE_DBG_CHIP); 993 5574 mx205022 ngep->desc_mode = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 994 5574 mx205022 DDI_PROP_DONTPASS, nge_desc_mode, dev_param_p->desc_type); 995 5574 mx205022 ngep->lowmem_mode = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 996 5574 mx205022 DDI_PROP_DONTPASS, low_memory_mode, 0); 997 5574 mx205022 998 5574 mx205022 if (dev_param_p->jumbo) { 999 5574 mx205022 ngep->default_mtu = ddi_prop_get_int(DDI_DEV_T_ANY, devinfo, 1000 5574 mx205022 DDI_PROP_DONTPASS, default_mtu, ETHERMTU); 1001 5574 mx205022 } else 1002 5574 mx205022 ngep->default_mtu = ETHERMTU; 1003 10496 Li-Zhen if (dev_param_p->tx_pause_frame) 1004 10496 Li-Zhen ngep->param_link_tx_pause = B_TRUE; 1005 10496 Li-Zhen else 1006 10496 Li-Zhen ngep->param_link_tx_pause = B_FALSE; 1007 10496 Li-Zhen 1008 10496 Li-Zhen if (dev_param_p->rx_pause_frame) 1009 10496 Li-Zhen ngep->param_link_rx_pause = B_TRUE; 1010 10496 Li-Zhen else 1011 10496 Li-Zhen ngep->param_link_rx_pause = B_FALSE; 1012 5574 mx205022 1013 5574 mx205022 if (ngep->default_mtu > ETHERMTU && 1014 5574 mx205022 ngep->default_mtu <= NGE_MTU_2500) { 1015 5574 mx205022 ngep->buf_size = NGE_JB2500_BUFSZ; 1016 5574 mx205022 ngep->tx_desc = NGE_SEND_JB2500_SLOTS_DESC; 1017 5574 mx205022 ngep->rx_desc = NGE_RECV_JB2500_SLOTS_DESC; 1018 5574 mx205022 ngep->rx_buf = NGE_RECV_JB2500_SLOTS_DESC * 2; 1019 5574 mx205022 ngep->nge_split = NGE_SPLIT_256; 1020 5574 mx205022 } else if (ngep->default_mtu > NGE_MTU_2500 && 1021 5574 mx205022 ngep->default_mtu <= NGE_MTU_4500) { 1022 5574 mx205022 ngep->buf_size = NGE_JB4500_BUFSZ; 1023 5574 mx205022 ngep->tx_desc = NGE_SEND_JB4500_SLOTS_DESC; 1024 5574 mx205022 ngep->rx_desc = NGE_RECV_JB4500_SLOTS_DESC; 1025 5574 mx205022 ngep->rx_buf = NGE_RECV_JB4500_SLOTS_DESC * 2; 1026 5574 mx205022 ngep->nge_split = NGE_SPLIT_256; 1027 5574 mx205022 } else if (ngep->default_mtu > NGE_MTU_4500 && 1028 5574 mx205022 ngep->default_mtu <= NGE_MAX_MTU) { 1029 5574 mx205022 ngep->buf_size = NGE_JB9000_BUFSZ; 1030 5574 mx205022 ngep->tx_desc = NGE_SEND_JB9000_SLOTS_DESC; 1031 5574 mx205022 ngep->rx_desc = NGE_RECV_JB9000_SLOTS_DESC; 1032 5574 mx205022 ngep->rx_buf = NGE_RECV_JB9000_SLOTS_DESC * 2; 1033 5574 mx205022 ngep->nge_split = NGE_SPLIT_256; 1034 5574 mx205022 } else if (ngep->default_mtu > NGE_MAX_MTU) { 1035 5574 mx205022 ngep->default_mtu = NGE_MAX_MTU; 1036 5574 mx205022 ngep->buf_size = NGE_JB9000_BUFSZ; 1037 5574 mx205022 ngep->tx_desc = NGE_SEND_JB9000_SLOTS_DESC; 1038 5574 mx205022 ngep->rx_desc = NGE_RECV_JB9000_SLOTS_DESC; 1039 5574 mx205022 ngep->rx_buf = NGE_RECV_JB9000_SLOTS_DESC * 2; 1040 5574 mx205022 ngep->nge_split = NGE_SPLIT_256; 1041 5574 mx205022 } else if (ngep->lowmem_mode != 0) { 1042 5574 mx205022 ngep->default_mtu = ETHERMTU; 1043 5574 mx205022 ngep->buf_size = NGE_STD_BUFSZ; 1044 5574 mx205022 ngep->tx_desc = NGE_SEND_LOWMEM_SLOTS_DESC; 1045 5574 mx205022 ngep->rx_desc = NGE_RECV_LOWMEM_SLOTS_DESC; 1046 5574 mx205022 ngep->rx_buf = NGE_RECV_LOWMEM_SLOTS_DESC * 2; 1047 5574 mx205022 ngep->nge_split = NGE_SPLIT_32; 1048 5574 mx205022 } else { 1049 5574 mx205022 ngep->default_mtu = ETHERMTU; 1050 5574 mx205022 ngep->buf_size = NGE_STD_BUFSZ; 1051 5574 mx205022 ngep->tx_desc = dev_param_p->tx_desc_num; 1052 5574 mx205022 ngep->rx_desc = dev_param_p->rx_desc_num; 1053 5574 mx205022 ngep->rx_buf = dev_param_p->rx_desc_num * 2; 1054 5574 mx205022 ngep->nge_split = dev_param_p->nge_split; 1055 5574 mx205022 } 1056 5574 mx205022 1057 5574 mx205022 nge_check_desc_prop(ngep); 1058 5574 mx205022 } 1059 5574 mx205022 1060 5574 mx205022 1061 5574 mx205022 static int 1062 7656 Sherry nge_reset_dev(nge_t *ngep) 1063 5574 mx205022 { 1064 5574 mx205022 int err; 1065 5869 mx205022 nge_mul_addr1 maddr1; 1066 5869 mx205022 nge_sw_statistics_t *sw_stp; 1067 5869 mx205022 sw_stp = &ngep->statistics.sw_statistics; 1068 5574 mx205022 send_ring_t *srp = ngep->send; 1069 5574 mx205022 1070 5574 mx205022 ASSERT(mutex_owned(ngep->genlock)); 1071 5574 mx205022 mutex_enter(srp->tc_lock); 1072 5574 mx205022 mutex_enter(srp->tx_lock); 1073 5574 mx205022 1074 5574 mx205022 nge_tx_recycle_all(ngep); 1075 5574 mx205022 err = nge_reinit_ring(ngep); 1076 5574 mx205022 if (err == DDI_FAILURE) { 1077 5574 mx205022 mutex_exit(srp->tx_lock); 1078 5574 mx205022 mutex_exit(srp->tc_lock); 1079 5574 mx205022 return (err); 1080 5574 mx205022 } 1081 5574 mx205022 err = nge_chip_reset(ngep); 1082 5869 mx205022 /* 1083 5869 mx205022 * Clear the Multicast mac address table 1084 5869 mx205022 */ 1085 5869 mx205022 nge_reg_put32(ngep, NGE_MUL_ADDR0, 0); 1086 5869 mx205022 maddr1.addr_val = nge_reg_get32(ngep, NGE_MUL_ADDR1); 1087 5869 mx205022 maddr1.addr_bits.addr = 0; 1088 5869 mx205022 nge_reg_put32(ngep, NGE_MUL_ADDR1, maddr1.addr_val); 1089 5869 mx205022 1090 5574 mx205022 mutex_exit(srp->tx_lock); 1091 5574 mx205022 mutex_exit(srp->tc_lock); 1092 5574 mx205022 if (err == DDI_FAILURE) 1093 5574 mx205022 return (err); 1094 5574 mx205022 ngep->watchdog = 0; 1095 5574 mx205022 ngep->resched_needed = B_FALSE; 1096 5574 mx205022 ngep->promisc = B_FALSE; 1097 5574 mx205022 ngep->param_loop_mode = NGE_LOOP_NONE; 1098 5574 mx205022 ngep->factotum_flag = 0; 1099 5574 mx205022 ngep->resched_needed = 0; 1100 5574 mx205022 ngep->nge_mac_state = NGE_MAC_RESET; 1101 5574 mx205022 ngep->max_sdu = ngep->default_mtu + ETHER_HEAD_LEN + ETHERFCSL; 1102 5574 mx205022 ngep->max_sdu += VTAG_SIZE; 1103 5574 mx205022 ngep->rx_def = 0x16; 1104 5869 mx205022 1105 5869 mx205022 /* Clear the software statistics */ 1106 5869 mx205022 sw_stp->recv_count = 0; 1107 5869 mx205022 sw_stp->xmit_count = 0; 1108 5869 mx205022 sw_stp->rbytes = 0; 1109 5869 mx205022 sw_stp->obytes = 0; 1110 5869 mx205022 1111 5574 mx205022 return (DDI_SUCCESS); 1112 5574 mx205022 } 1113 5574 mx205022 1114 5574 mx205022 static void 1115 5574 mx205022 nge_m_stop(void *arg) 1116 5574 mx205022 { 1117 5574 mx205022 nge_t *ngep = arg; /* private device info */ 1118 9708 Zhen int err; 1119 5574 mx205022 1120 5574 mx205022 NGE_TRACE(("nge_m_stop($%p)", arg)); 1121 5574 mx205022 1122 5574 mx205022 /* 1123 5574 mx205022 * Just stop processing, then record new MAC state 1124 5574 mx205022 */ 1125 5574 mx205022 mutex_enter(ngep->genlock); 1126 5869 mx205022 /* If suspended, the adapter is already stopped, just return. */ 1127 5869 mx205022 if (ngep->suspended) { 1128 5869 mx205022 ASSERT(ngep->nge_mac_state == NGE_MAC_STOPPED); 1129 5869 mx205022 mutex_exit(ngep->genlock); 1130 5869 mx205022 return; 1131 5869 mx205022 } 1132 5574 mx205022 rw_enter(ngep->rwlock, RW_WRITER); 1133 5574 mx205022 1134 9708 Zhen err = nge_chip_stop(ngep, B_FALSE); 1135 9708 Zhen if (err == DDI_FAILURE) 1136 9708 Zhen err = nge_chip_reset(ngep); 1137 9708 Zhen if (err == DDI_FAILURE) 1138 9708 Zhen nge_problem(ngep, "nge_m_stop: stop chip failed"); 1139 5574 mx205022 ngep->nge_mac_state = NGE_MAC_STOPPED; 1140 5574 mx205022 1141 5574 mx205022 /* Recycle all the TX BD */ 1142 5574 mx205022 nge_tx_recycle_all(ngep); 1143 5574 mx205022 nge_fini_rings(ngep); 1144 5574 mx205022 nge_free_bufs(ngep); 1145 5574 mx205022 1146 5574 mx205022 NGE_DEBUG(("nge_m_stop($%p) done", arg)); 1147 5574 mx205022 1148 5574 mx205022 rw_exit(ngep->rwlock); 1149 5574 mx205022 mutex_exit(ngep->genlock); 1150 5574 mx205022 } 1151 5574 mx205022 1152 5574 mx205022 static int 1153 5574 mx205022 nge_m_start(void *arg) 1154 5574 mx205022 { 1155 5574 mx205022 int err; 1156 5574 mx205022 nge_t *ngep = arg; 1157 5574 mx205022 1158 5574 mx205022 NGE_TRACE(("nge_m_start($%p)", arg)); 1159 5869 mx205022 1160 5869 mx205022 /* 1161 5869 mx205022 * Start processing and record new MAC state 1162 5869 mx205022 */ 1163 5869 mx205022 mutex_enter(ngep->genlock); 1164 5574 mx205022 /* 1165 5574 mx205022 * If suspended, don't start, as the resume processing 1166 5574 mx205022 * will recall this function with the suspended flag off. 1167 5574 mx205022 */ 1168 5869 mx205022 if (ngep->suspended) { 1169 5869 mx205022 mutex_exit(ngep->genlock); 1170 5988 vb160487 return (EIO); 1171 5869 mx205022 } 1172 5574 mx205022 rw_enter(ngep->rwlock, RW_WRITER); 1173 5574 mx205022 err = nge_alloc_bufs(ngep); 1174 5574 mx205022 if (err != DDI_SUCCESS) { 1175 5574 mx205022 nge_problem(ngep, "nge_m_start: DMA buffer allocation failed"); 1176 5574 mx205022 goto finish; 1177 5574 mx205022 } 1178 5574 mx205022 err = nge_init_rings(ngep); 1179 5574 mx205022 if (err != DDI_SUCCESS) { 1180 5574 mx205022 nge_free_bufs(ngep); 1181 5988 vb160487 nge_problem(ngep, "nge_init_rings() failed,err=%x", err); 1182 5574 mx205022 goto finish; 1183 5574 mx205022 } 1184 5574 mx205022 err = nge_restart(ngep); 1185 5574 mx205022 1186 5574 mx205022 NGE_DEBUG(("nge_m_start($%p) done", arg)); 1187 5988 vb160487 finish: 1188 5988 vb160487 rw_exit(ngep->rwlock); 1189 5988 vb160487 mutex_exit(ngep->genlock); 1190 5574 mx205022 1191 5988 vb160487 return (err == DDI_SUCCESS ? 0 : EIO); 1192 5574 mx205022 } 1193 5574 mx205022 1194 5574 mx205022 static int 1195 5574 mx205022 nge_m_unicst(void *arg, const uint8_t *macaddr) 1196 5574 mx205022 { 1197 5574 mx205022 nge_t *ngep = arg; 1198 5574 mx205022 1199 5574 mx205022 NGE_TRACE(("nge_m_unicst($%p)", arg)); 1200 5574 mx205022 /* 1201 5574 mx205022 * Remember the new current address in the driver state 1202 5574 mx205022 * Sync the chip's idea of the address too ... 1203 5574 mx205022 */ 1204 5574 mx205022 mutex_enter(ngep->genlock); 1205 5574 mx205022 1206 5574 mx205022 ethaddr_copy(macaddr, ngep->cur_uni_addr.addr); 1207 5574 mx205022 ngep->cur_uni_addr.set = 1; 1208 5574 mx205022 1209 5574 mx205022 /* 1210 5574 mx205022 * If we are suspended, we want to quit now, and not update 1211 5574 mx205022 * the chip. Doing so might put it in a bad state, but the 1212 5574 mx205022 * resume will get the unicast address installed. 1213 5574 mx205022 */ 1214 5869 mx205022 if (ngep->suspended) { 1215 5869 mx205022 mutex_exit(ngep->genlock); 1216 5574 mx205022 return (DDI_SUCCESS); 1217 5869 mx205022 } 1218 5574 mx205022 nge_chip_sync(ngep); 1219 5574 mx205022 1220 5574 mx205022 NGE_DEBUG(("nge_m_unicst($%p) done", arg)); 1221 5574 mx205022 mutex_exit(ngep->genlock); 1222 5574 mx205022 1223 5574 mx205022 return (0); 1224 5574 mx205022 } 1225 5574 mx205022 1226 5574 mx205022 static int 1227 5574 mx205022 nge_m_promisc(void *arg, boolean_t on) 1228 5574 mx205022 { 1229 5574 mx205022 nge_t *ngep = arg; 1230 5574 mx205022 1231 5574 mx205022 NGE_TRACE(("nge_m_promisc($%p)", arg)); 1232 5574 mx205022 1233 5574 mx205022 /* 1234 5574 mx205022 * Store specified mode and pass to chip layer to update h/w 1235 5574 mx205022 */ 1236 5574 mx205022 mutex_enter(ngep->genlock); 1237 5869 mx205022 /* 1238 5869 mx205022 * If suspended, there is no need to do anything, even 1239 5869 mx205022 * recording the promiscuious mode is not neccessary, as 1240 5869 mx205022 * it won't be properly set on resume. Just return failing. 1241 5869 mx205022 */ 1242 5869 mx205022 if (ngep->suspended) { 1243 5869 mx205022 mutex_exit(ngep->genlock); 1244 5869 mx205022 return (DDI_FAILURE); 1245 5869 mx205022 } 1246 5574 mx205022 if (ngep->promisc == on) { 1247 5574 mx205022 mutex_exit(ngep->genlock); 1248 5574 mx205022 NGE_DEBUG(("nge_m_promisc($%p) done", arg)); 1249 5574 mx205022 return (0); 1250 5574 mx205022 } 1251 5574 mx205022 ngep->promisc = on; 1252 7155 mx205022 ngep->record_promisc = ngep->promisc; 1253 5574 mx205022 nge_chip_sync(ngep); 1254 5574 mx205022 NGE_DEBUG(("nge_m_promisc($%p) done", arg)); 1255 5574 mx205022 mutex_exit(ngep->genlock); 1256 5574 mx205022 1257 5574 mx205022 return (0); 1258 5574 mx205022 } 1259 5574 mx205022 1260 5574 mx205022 static void nge_mulparam(nge_t *ngep) 1261 5574 mx205022 { 1262 5574 mx205022 uint8_t number; 1263 5574 mx205022 ether_addr_t pand; 1264 5574 mx205022 ether_addr_t por; 1265 5574 mx205022 mul_item *plist; 1266 5574 mx205022 1267 5574 mx205022 for (number = 0; number < ETHERADDRL; number++) { 1268 5574 mx205022 pand[number] = 0x00; 1269 5574 mx205022 por[number] = 0x00; 1270 5574 mx205022 } 1271 5574 mx205022 for (plist = ngep->pcur_mulist; plist != NULL; plist = plist->next) { 1272 5574 mx205022 for (number = 0; number < ETHERADDRL; number++) { 1273 5574 mx205022 pand[number] &= plist->mul_addr[number]; 1274 5574 mx205022 por[number] |= plist->mul_addr[number]; 1275 5574 mx205022 } 1276 5574 mx205022 } 1277 5574 mx205022 for (number = 0; number < ETHERADDRL; number++) { 1278 5574 mx205022 ngep->cur_mul_addr.addr[number] 1279 5574 mx205022 = pand[number] & por[number]; 1280 5574 mx205022 ngep->cur_mul_mask.addr[number] 1281 5574 mx205022 = pand [number] | (~por[number]); 1282 5574 mx205022 } 1283 5574 mx205022 } 1284 5574 mx205022 static int 1285 5574 mx205022 nge_m_multicst(void *arg, boolean_t add, const uint8_t *mca) 1286 5574 mx205022 { 1287 5574 mx205022 boolean_t update; 1288 5574 mx205022 boolean_t b_eq; 1289 5574 mx205022 nge_t *ngep = arg; 1290 5574 mx205022 mul_item *plist; 1291 5574 mx205022 mul_item *plist_prev; 1292 5574 mx205022 mul_item *pitem; 1293 5574 mx205022 1294 5574 mx205022 NGE_TRACE(("nge_m_multicst($%p, %s, %s)", arg, 1295 5574 mx205022 (add) ? "add" : "remove", ether_sprintf((void *)mca))); 1296 5574 mx205022 1297 5574 mx205022 update = B_FALSE; 1298 5574 mx205022 plist = plist_prev = NULL; 1299 5574 mx205022 mutex_enter(ngep->genlock); 1300 5574 mx205022 if (add) { 1301 5574 mx205022 if (ngep->pcur_mulist != NULL) { 1302 5574 mx205022 for (plist = ngep->pcur_mulist; plist != NULL; 1303 5574 mx205022 plist = plist->next) { 1304 5574 mx205022 b_eq = ether_eq(plist->mul_addr, mca); 1305 5574 mx205022 if (b_eq) { 1306 5574 mx205022 plist->ref_cnt++; 1307 5574 mx205022 break; 1308 5574 mx205022 } 1309 5574 mx205022 plist_prev = plist; 1310 5574 mx205022 } 1311 5574 mx205022 } 1312 5574 mx205022 1313 5574 mx205022 if (plist == NULL) { 1314 5574 mx205022 pitem = kmem_zalloc(sizeof (mul_item), KM_SLEEP); 1315 5574 mx205022 ether_copy(mca, pitem->mul_addr); 1316 5574 mx205022 pitem ->ref_cnt++; 1317 5574 mx205022 pitem ->next = NULL; 1318 5574 mx205022 if (plist_prev == NULL) 1319 5574 mx205022 ngep->pcur_mulist = pitem; 1320 5574 mx205022 else 1321 5574 mx205022 plist_prev->next = pitem; 1322 5574 mx205022 update = B_TRUE; 1323 5574 mx205022 } 1324 5574 mx205022 } else { 1325 5574 mx205022 if (ngep->pcur_mulist != NULL) { 1326 5574 mx205022 for (plist = ngep->pcur_mulist; plist != NULL; 1327 5574 mx205022 plist = plist->next) { 1328 5574 mx205022 b_eq = ether_eq(plist->mul_addr, mca); 1329 5574 mx205022 if (b_eq) { 1330 5574 mx205022 update = B_TRUE; 1331 5574 mx205022 break; 1332 5574 mx205022 } 1333 5574 mx205022 plist_prev = plist; 1334 5574 mx205022 } 1335 5574 mx205022 1336 5574 mx205022 if (update) { 1337 5574 mx205022 if ((plist_prev == NULL) && 1338 5574 mx205022 (plist->next == NULL)) 1339 5574 mx205022 ngep->pcur_mulist = NULL; 1340 5574 mx205022 else if ((plist_prev == NULL) && 1341 5574 mx205022 (plist->next != NULL)) 1342 5574 mx205022 ngep->pcur_mulist = plist->next; 1343 5574 mx205022 else 1344 5574 mx205022 plist_prev->next = plist->next; 1345 5574 mx205022 kmem_free(plist, sizeof (mul_item)); 1346 5574 mx205022 } 1347 5574 mx205022 } 1348 5574 mx205022 } 1349 5574 mx205022 1350 5869 mx205022 if (update && !ngep->suspended) { 1351 5574 mx205022 nge_mulparam(ngep); 1352 5574 mx205022 nge_chip_sync(ngep); 1353 5574 mx205022 } 1354 5574 mx205022 NGE_DEBUG(("nge_m_multicst($%p) done", arg)); 1355 5574 mx205022 mutex_exit(ngep->genlock); 1356 5574 mx205022 1357 5574 mx205022 return (0); 1358 5574 mx205022 } 1359 5574 mx205022 1360 5574 mx205022 static void 1361 5574 mx205022 nge_m_ioctl(void *arg, queue_t *wq, mblk_t *mp) 1362 5574 mx205022 { 1363 5574 mx205022 int err; 1364 5574 mx205022 int cmd; 1365 5574 mx205022 nge_t *ngep = arg; 1366 5574 mx205022 struct iocblk *iocp; 1367 5574 mx205022 enum ioc_reply status; 1368 5574 mx205022 boolean_t need_privilege; 1369 5574 mx205022 1370 5574 mx205022 /* 1371 5574 mx205022 * If suspended, we might actually be able to do some of 1372 5574 mx205022 * these ioctls, but it is harder to make sure they occur 1373 5574 mx205022 * without actually putting the hardware in an undesireable 1374 5574 mx205022 * state. So just NAK it. 1375 5574 mx205022 */ 1376 5869 mx205022 mutex_enter(ngep->genlock); 1377 5574 mx205022 if (ngep->suspended) { 1378 5574 mx205022 miocnak(wq, mp, 0, EINVAL); 1379 5869 mx205022 mutex_exit(ngep->genlock); 1380 5574 mx205022 return; 1381 5574 mx205022 } 1382 5869 mx205022 mutex_exit(ngep->genlock); 1383 5574 mx205022 1384 5574 mx205022 /* 1385 5574 mx205022 * Validate the command before bothering with the mutex ... 1386 5574 mx205022 */ 1387 5574 mx205022 iocp = (struct iocblk *)mp->b_rptr; 1388 5574 mx205022 iocp->ioc_error = 0; 1389 5574 mx205022 need_privilege = B_TRUE; 1390 5574 mx205022 cmd = iocp->ioc_cmd; 1391 5574 mx205022 1392 5574 mx205022 NGE_DEBUG(("nge_m_ioctl: cmd 0x%x", cmd)); 1393 5574 mx205022 switch (cmd) { 1394 5574 mx205022 default: 1395 5574 mx205022 NGE_LDB(NGE_DBG_BADIOC, 1396 5574 mx205022 ("nge_m_ioctl: unknown cmd 0x%x", cmd)); 1397 5574 mx205022 1398 5574 mx205022 miocnak(wq, mp, 0, EINVAL); 1399 5574 mx205022 return; 1400 5574 mx205022 1401 5574 mx205022 case NGE_MII_READ: 1402 5574 mx205022 case NGE_MII_WRITE: 1403 5574 mx205022 case NGE_SEE_READ: 1404 5574 mx205022 case NGE_SEE_WRITE: 1405 5574 mx205022 case NGE_DIAG: 1406 5574 mx205022 case NGE_PEEK: 1407 5574 mx205022 case NGE_POKE: 1408 5574 mx205022 case NGE_PHY_RESET: 1409 5574 mx205022 case NGE_SOFT_RESET: 1410 5574 mx205022 case NGE_HARD_RESET: 1411 5574 mx205022 break; 1412 5574 mx205022 1413 5574 mx205022 case LB_GET_INFO_SIZE: 1414 5574 mx205022 case LB_GET_INFO: 1415 5574 mx205022 case LB_GET_MODE: 1416 5574 mx205022 need_privilege = B_FALSE; 1417 5574 mx205022 break; 1418 5574 mx205022 case LB_SET_MODE: 1419 5574 mx205022 break; 1420 5574 mx205022 } 1421 5574 mx205022 1422 5574 mx205022 if (need_privilege) { 1423 5574 mx205022 /* 1424 5574 mx205022 * Check for specific net_config privilege. 1425 5574 mx205022 */ 1426 5574 mx205022 err = secpolicy_net_config(iocp->ioc_cr, B_FALSE); 1427 5574 mx205022 if (err != 0) { 1428 5574 mx205022 NGE_DEBUG(("nge_m_ioctl: rejected cmd 0x%x, err %d", 1429 5574 mx205022 cmd, err)); 1430 5574 mx205022 miocnak(wq, mp, 0, err); 1431 5574 mx205022 return; 1432 5574 mx205022 } 1433 5574 mx205022 } 1434 5574 mx205022 1435 5574 mx205022 mutex_enter(ngep->genlock); 1436 5574 mx205022 1437 5574 mx205022 switch (cmd) { 1438 5574 mx205022 default: 1439 5574 mx205022 _NOTE(NOTREACHED) 1440 5574 mx205022 status = IOC_INVAL; 1441 5574 mx205022 break; 1442 5574 mx205022 1443 5574 mx205022 case NGE_MII_READ: 1444 5574 mx205022 case NGE_MII_WRITE: 1445 5574 mx205022 case NGE_SEE_READ: 1446 5574 mx205022 case NGE_SEE_WRITE: 1447 5574 mx205022 case NGE_DIAG: 1448 5574 mx205022 case NGE_PEEK: 1449 5574 mx205022 case NGE_POKE: 1450 5574 mx205022 case NGE_PHY_RESET: 1451 5574 mx205022 case NGE_SOFT_RESET: 1452 5574 mx205022 case NGE_HARD_RESET: 1453 5574 mx205022 status = nge_chip_ioctl(ngep, mp, iocp); 1454 5574 mx205022 break; 1455 5574 mx205022 1456 5574 mx205022 case LB_GET_INFO_SIZE: 1457 5574 mx205022 case LB_GET_INFO: 1458 5574 mx205022 case LB_GET_MODE: 1459 5574 mx205022 case LB_SET_MODE: 1460 5574 mx205022 status = nge_loop_ioctl(ngep, mp, iocp); 1461 5574 mx205022 break; 1462 5574 mx205022 1463 5574 mx205022 } 1464 5574 mx205022 1465 5574 mx205022 /* 1466 5574 mx205022 * Do we need to reprogram the PHY and/or the MAC? 1467 5574 mx205022 * Do it now, while we still have the mutex. 1468 5574 mx205022 * 1469 5574 mx205022 * Note: update the PHY first, 'cos it controls the 1470 5574 mx205022 * speed/duplex parameters that the MAC code uses. 1471 5574 mx205022 */ 1472 5574 mx205022 1473 5574 mx205022 NGE_DEBUG(("nge_m_ioctl: cmd 0x%x status %d", cmd, status)); 1474 5574 mx205022 1475 5574 mx205022 switch (status) { 1476 5574 mx205022 case IOC_RESTART_REPLY: 1477 5574 mx205022 case IOC_RESTART_ACK: 1478 5574 mx205022 (*ngep->physops->phys_update)(ngep); 1479 5574 mx205022 nge_chip_sync(ngep); 1480 5574 mx205022 break; 1481 5574 mx205022 1482 5574 mx205022 default: 1483 5574 mx205022 break; 1484 5574 mx205022 } 1485 5574 mx205022 1486 5574 mx205022 mutex_exit(ngep->genlock); 1487 5574 mx205022 1488 5574 mx205022 /* 1489 5574 mx205022 * Finally, decide how to reply 1490 5574 mx205022 */ 1491 5574 mx205022 switch (status) { 1492 5574 mx205022 1493 5574 mx205022 default: 1494 5574 mx205022 case IOC_INVAL: 1495 5574 mx205022 miocnak(wq, mp, 0, iocp->ioc_error == 0 ? 1496 5574 mx205022 EINVAL : iocp->ioc_error); 1497 5574 mx205022 break; 1498 5574 mx205022 1499 5574 mx205022 case IOC_DONE: 1500 5574 mx205022 break; 1501 5574 mx205022 1502 5574 mx205022 case IOC_RESTART_ACK: 1503 5574 mx205022 case IOC_ACK: 1504 5574 mx205022 miocack(wq, mp, 0, 0); 1505 5574 mx205022 break; 1506 5574 mx205022 1507 5574 mx205022 case IOC_RESTART_REPLY: 1508 5574 mx205022 case IOC_REPLY: 1509 5574 mx205022 mp->b_datap->db_type = iocp->ioc_error == 0 ? 1510 5574 mx205022 M_IOCACK : M_IOCNAK; 1511 5574 mx205022 qreply(wq, mp); 1512 5574 mx205022 break; 1513 5574 mx205022 } 1514 5574 mx205022 } 1515 5574 mx205022 1516 6200 mx205022 static boolean_t 1517 6200 mx205022 nge_param_locked(mac_prop_id_t pr_num) 1518 6200 mx205022 { 1519 6200 mx205022 /* 1520 6200 mx205022 * All adv_* parameters are locked (read-only) while 1521 6200 mx205022 * the device is in any sort of loopback mode ... 1522 6200 mx205022 */ 1523 6200 mx205022 switch (pr_num) { 1524 6789 am223141 case MAC_PROP_ADV_1000FDX_CAP: 1525 6789 am223141 case MAC_PROP_EN_1000FDX_CAP: 1526 6789 am223141 case MAC_PROP_ADV_1000HDX_CAP: 1527 6789 am223141 case MAC_PROP_EN_1000HDX_CAP: 1528 6789 am223141 case MAC_PROP_ADV_100FDX_CAP: 1529 6789 am223141 case MAC_PROP_EN_100FDX_CAP: 1530 6789 am223141 case MAC_PROP_ADV_100HDX_CAP: 1531 6789 am223141 case MAC_PROP_EN_100HDX_CAP: 1532 6789 am223141 case MAC_PROP_ADV_10FDX_CAP: 1533 6789 am223141 case MAC_PROP_EN_10FDX_CAP: 1534 6789 am223141 case MAC_PROP_ADV_10HDX_CAP: 1535 6789 am223141 case MAC_PROP_EN_10HDX_CAP: 1536 6789 am223141 case MAC_PROP_AUTONEG: 1537 6789 am223141 case MAC_PROP_FLOWCTRL: 1538 6200 mx205022 return (B_TRUE); 1539 6200 mx205022 } 1540 6200 mx205022 return (B_FALSE); 1541 6200 mx205022 } 1542 6200 mx205022 1543 6200 mx205022 /* 1544 6200 mx205022 * callback functions for set/get of properties 1545 6200 mx205022 */ 1546 6200 mx205022 static int 1547 6200 mx205022 nge_m_setprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 1548 6200 mx205022 uint_t pr_valsize, const void *pr_val) 1549 6200 mx205022 { 1550 6200 mx205022 nge_t *ngep = barg; 1551 6200 mx205022 int err = 0; 1552 6512 sowmini uint32_t cur_mtu, new_mtu; 1553 6200 mx205022 link_flowctrl_t fl; 1554 6200 mx205022 1555 6200 mx205022 mutex_enter(ngep->genlock); 1556 6200 mx205022 if (ngep->param_loop_mode != NGE_LOOP_NONE && 1557 6200 mx205022 nge_param_locked(pr_num)) { 1558 6200 mx205022 /* 1559 6200 mx205022 * All adv_* parameters are locked (read-only) 1560 6200 mx205022 * while the device is in any sort of loopback mode. 1561 6200 mx205022 */ 1562 6200 mx205022 mutex_exit(ngep->genlock); 1563 6200 mx205022 return (EBUSY); 1564 6200 mx205022 } 1565 6200 mx205022 switch (pr_num) { 1566 6789 am223141 case MAC_PROP_EN_1000FDX_CAP: 1567 6200 mx205022 ngep->param_en_1000fdx = *(uint8_t *)pr_val; 1568 6200 mx205022 ngep->param_adv_1000fdx = *(uint8_t *)pr_val; 1569 6200 mx205022 goto reprogram; 1570 6789 am223141 case MAC_PROP_EN_100FDX_CAP: 1571 6200 mx205022 ngep->param_en_100fdx = *(uint8_t *)pr_val; 1572 6200 mx205022 ngep->param_adv_100fdx = *(uint8_t *)pr_val; 1573 6200 mx205022 goto reprogram; 1574 6789 am223141 case MAC_PROP_EN_100HDX_CAP: 1575 6200 mx205022 ngep->param_en_100hdx = *(uint8_t *)pr_val; 1576 6200 mx205022 ngep->param_adv_100hdx = *(uint8_t *)pr_val; 1577 6200 mx205022 goto reprogram; 1578 6789 am223141 case MAC_PROP_EN_10FDX_CAP: 1579 6200 mx205022 ngep->param_en_10fdx = *(uint8_t *)pr_val; 1580 6200 mx205022 ngep->param_adv_10fdx = *(uint8_t *)pr_val; 1581 6200 mx205022 goto reprogram; 1582 6789 am223141 case MAC_PROP_EN_10HDX_CAP: 1583 6200 mx205022 ngep->param_en_10hdx = *(uint8_t *)pr_val; 1584 6200 mx205022 ngep->param_adv_10hdx = *(uint8_t *)pr_val; 1585 6200 mx205022 reprogram: 1586 6200 mx205022 (*ngep->physops->phys_update)(ngep); 1587 6200 mx205022 nge_chip_sync(ngep); 1588 6200 mx205022 break; 1589 6200 mx205022 1590 6789 am223141 case MAC_PROP_ADV_1000FDX_CAP: 1591 6789 am223141 case MAC_PROP_ADV_1000HDX_CAP: 1592 6789 am223141 case MAC_PROP_ADV_100FDX_CAP: 1593 6789 am223141 case MAC_PROP_ADV_100HDX_CAP: 1594 6789 am223141 case MAC_PROP_ADV_10FDX_CAP: 1595 6789 am223141 case MAC_PROP_ADV_10HDX_CAP: 1596 6789 am223141 case MAC_PROP_STATUS: 1597 6789 am223141 case MAC_PROP_SPEED: 1598 6789 am223141 case MAC_PROP_DUPLEX: 1599 6789 am223141 case MAC_PROP_EN_1000HDX_CAP: 1600 6200 mx205022 err = ENOTSUP; /* read-only prop. Can't set this */ 1601 6200 mx205022 break; 1602 6789 am223141 case MAC_PROP_AUTONEG: 1603 6200 mx205022 ngep->param_adv_autoneg = *(uint8_t *)pr_val; 1604 6200 mx205022 (*ngep->physops->phys_update)(ngep); 1605 6200 mx205022 nge_chip_sync(ngep); 1606 6200 mx205022 break; 1607 6789 am223141 case MAC_PROP_MTU: 1608 6200 mx205022 cur_mtu = ngep->default_mtu; 1609 6200 mx205022 bcopy(pr_val, &new_mtu, sizeof (new_mtu)); 1610 6200 mx205022 if (new_mtu == cur_mtu) { 1611 6200 mx205022 err = 0; 1612 6200 mx205022 break; 1613 6200 mx205022 } 1614 6200 mx205022 if (new_mtu < ETHERMTU || 1615 6200 mx205022 new_mtu > NGE_MAX_MTU) { 1616 6200 mx205022 err = EINVAL; 1617 6200 mx205022 break; 1618 6200 mx205022 } 1619 6200 mx205022 if ((new_mtu > ETHERMTU) && 1620 6200 mx205022 (!ngep->dev_spec_param.jumbo)) { 1621 6200 mx205022 err = EINVAL; 1622 6200 mx205022 break; 1623 6200 mx205022 } 1624 6200 mx205022 if (ngep->nge_mac_state == NGE_MAC_STARTED) { 1625 6200 mx205022 err = EBUSY; 1626 6200 mx205022 break; 1627 6200 mx205022 } 1628 6200 mx205022 1629 6200 mx205022 ngep->default_mtu = new_mtu; 1630 6200 mx205022 if (ngep->default_mtu > ETHERMTU && 1631 6200 mx205022 ngep->default_mtu <= NGE_MTU_2500) { 1632 6200 mx205022 ngep->buf_size = NGE_JB2500_BUFSZ; 1633 6200 mx205022 ngep->tx_desc = NGE_SEND_JB2500_SLOTS_DESC; 1634 6200 mx205022 ngep->rx_desc = NGE_RECV_JB2500_SLOTS_DESC; 1635 6200 mx205022 ngep->rx_buf = NGE_RECV_JB2500_SLOTS_DESC * 2; 1636 6200 mx205022 ngep->nge_split = NGE_SPLIT_256; 1637 6200 mx205022 } else if (ngep->default_mtu > NGE_MTU_2500 && 1638 6200 mx205022 ngep->default_mtu <= NGE_MTU_4500) { 1639 6200 mx205022 ngep->buf_size = NGE_JB4500_BUFSZ; 1640 6200 mx205022 ngep->tx_desc = NGE_SEND_JB4500_SLOTS_DESC; 1641 6200 mx205022 ngep->rx_desc = NGE_RECV_JB4500_SLOTS_DESC; 1642 6200 mx205022 ngep->rx_buf = NGE_RECV_JB4500_SLOTS_DESC * 2; 1643 6200 mx205022 ngep->nge_split = NGE_SPLIT_256; 1644 6200 mx205022 } else if (ngep->default_mtu > NGE_MTU_4500 && 1645 6200 mx205022 ngep->default_mtu <= NGE_MAX_MTU) { 1646 6200 mx205022 ngep->buf_size = NGE_JB9000_BUFSZ; 1647 6200 mx205022 ngep->tx_desc = NGE_SEND_JB9000_SLOTS_DESC; 1648 6200 mx205022 ngep->rx_desc = NGE_RECV_JB9000_SLOTS_DESC; 1649 6200 mx205022 ngep->rx_buf = NGE_RECV_JB9000_SLOTS_DESC * 2; 1650 6200 mx205022 ngep->nge_split = NGE_SPLIT_256; 1651 6200 mx205022 } else if (ngep->default_mtu > NGE_MAX_MTU) { 1652 6200 mx205022 ngep->default_mtu = NGE_MAX_MTU; 1653 6200 mx205022 ngep->buf_size = NGE_JB9000_BUFSZ; 1654 6200 mx205022 ngep->tx_desc = NGE_SEND_JB9000_SLOTS_DESC; 1655 6200 mx205022 ngep->rx_desc = NGE_RECV_JB9000_SLOTS_DESC; 1656 6200 mx205022 ngep->rx_buf = NGE_RECV_JB9000_SLOTS_DESC * 2; 1657 6200 mx205022 ngep->nge_split = NGE_SPLIT_256; 1658 6200 mx205022 } else if (ngep->lowmem_mode != 0) { 1659 6200 mx205022 ngep->default_mtu = ETHERMTU; 1660 6200 mx205022 ngep->buf_size = NGE_STD_BUFSZ; 1661 6200 mx205022 ngep->tx_desc = NGE_SEND_LOWMEM_SLOTS_DESC; 1662 6200 mx205022 ngep->rx_desc = NGE_RECV_LOWMEM_SLOTS_DESC; 1663 6200 mx205022 ngep->rx_buf = NGE_RECV_LOWMEM_SLOTS_DESC * 2; 1664 6200 mx205022 ngep->nge_split = NGE_SPLIT_32; 1665 6200 mx205022 } else { 1666 6200 mx205022 ngep->default_mtu = ETHERMTU; 1667 6200 mx205022 ngep->buf_size = NGE_STD_BUFSZ; 1668 6200 mx205022 ngep->tx_desc = 1669 6200 mx205022 ngep->dev_spec_param.tx_desc_num; 1670 6200 mx205022 ngep->rx_desc = 1671 6200 mx205022 ngep->dev_spec_param.rx_desc_num; 1672 6200 mx205022 ngep->rx_buf = 1673 6200 mx205022 ngep->dev_spec_param.rx_desc_num * 2; 1674 6200 mx205022 ngep->nge_split = 1675 6200 mx205022 ngep->dev_spec_param.nge_split; 1676 6200 mx205022 } 1677 6200 mx205022 1678 6200 mx205022 err = mac_maxsdu_update(ngep->mh, ngep->default_mtu); 1679 6200 mx205022 1680 6200 mx205022 break; 1681 6789 am223141 case MAC_PROP_FLOWCTRL: 1682 6200 mx205022 bcopy(pr_val, &fl, sizeof (fl)); 1683 6200 mx205022 switch (fl) { 1684 6200 mx205022 default: 1685 6200 mx205022 err = ENOTSUP; 1686 6200 mx205022 break; 1687 6200 mx205022 case LINK_FLOWCTRL_NONE: 1688 6200 mx205022 ngep->param_adv_pause = 0; 1689 6200 mx205022 ngep->param_adv_asym_pause = 0; 1690 6200 mx205022 1691 6200 mx205022 ngep->param_link_rx_pause = B_FALSE; 1692 6200 mx205022 ngep->param_link_tx_pause = B_FALSE; 1693 6200 mx205022 break; 1694 6200 mx205022 case LINK_FLOWCTRL_RX: 1695 6200 mx205022 if (!((ngep->param_lp_pause == 0) && 1696 6200 mx205022 (ngep->param_lp_asym_pause == 1))) { 1697 6200 mx205022 err = EINVAL; 1698 6200 mx205022 break; 1699 6200 mx205022 } 1700 6200 mx205022 ngep->param_adv_pause = 1; 1701 6200 mx205022 ngep->param_adv_asym_pause = 1; 1702 6200 mx205022 1703 6200 mx205022 ngep->param_link_rx_pause = B_TRUE; 1704 6200 mx205022 ngep->param_link_tx_pause = B_FALSE; 1705 6200 mx205022 break; 1706 6200 mx205022 case LINK_FLOWCTRL_TX: 1707 6200 mx205022 if (!((ngep->param_lp_pause == 1) && 1708 6200 mx205022 (ngep->param_lp_asym_pause == 1))) { 1709 6200 mx205022 err = EINVAL; 1710 6200 mx205022 break; 1711 6200 mx205022 } 1712 6200 mx205022 ngep->param_adv_pause = 0; 1713 6200 mx205022 ngep->param_adv_asym_pause = 1; 1714 6200 mx205022 1715 6200 mx205022 ngep->param_link_rx_pause = B_FALSE; 1716 6200 mx205022 ngep->param_link_tx_pause = B_TRUE; 1717 6200 mx205022 break; 1718 6200 mx205022 case LINK_FLOWCTRL_BI: 1719 6200 mx205022 if (ngep->param_lp_pause != 1) { 1720 6200 mx205022 err = EINVAL; 1721 6200 mx205022 break; 1722 6200 mx205022 } 1723 6200 mx205022 ngep->param_adv_pause = 1; 1724 6200 mx205022 1725 6200 mx205022 ngep->param_link_rx_pause = B_TRUE; 1726 6200 mx205022 ngep->param_link_tx_pause = B_TRUE; 1727 6200 mx205022 break; 1728 6200 mx205022 } 1729 6200 mx205022 1730 6200 mx205022 if (err == 0) { 1731 6200 mx205022 (*ngep->physops->phys_update)(ngep); 1732 6200 mx205022 nge_chip_sync(ngep); 1733 6200 mx205022 } 1734 6200 mx205022 1735 6200 mx205022 break; 1736 6789 am223141 case MAC_PROP_PRIVATE: 1737 6200 mx205022 err = nge_set_priv_prop(ngep, pr_name, pr_valsize, 1738 6200 mx205022 pr_val); 1739 6200 mx205022 if (err == 0) { 1740 6200 mx205022 (*ngep->physops->phys_update)(ngep); 1741 6200 mx205022 nge_chip_sync(ngep); 1742 6200 mx205022 } 1743 6200 mx205022 break; 1744 6200 mx205022 default: 1745 6200 mx205022 err = ENOTSUP; 1746 6200 mx205022 } 1747 6200 mx205022 mutex_exit(ngep->genlock); 1748 6200 mx205022 return (err); 1749 6200 mx205022 } 1750 6200 mx205022 1751 6200 mx205022 static int 1752 6200 mx205022 nge_m_getprop(void *barg, const char *pr_name, mac_prop_id_t pr_num, 1753 8118 Vasumathi uint_t pr_flags, uint_t pr_valsize, void *pr_val, uint_t *perm) 1754 6200 mx205022 { 1755 6200 mx205022 nge_t *ngep = barg; 1756 6512 sowmini int err = 0; 1757 6200 mx205022 link_flowctrl_t fl; 1758 6512 sowmini uint64_t speed; 1759 6789 am223141 boolean_t is_default = (pr_flags & MAC_PROP_DEFAULT); 1760 6512 sowmini 1761 6512 sowmini if (pr_valsize == 0) 1762 6512 sowmini return (EINVAL); 1763 6200 mx205022 1764 8118 Vasumathi *perm = MAC_PROP_PERM_RW; 1765 8118 Vasumathi 1766 6200 mx205022 bzero(pr_val, pr_valsize); 1767 8118 Vasumathi 1768 6200 mx205022 switch (pr_num) { 1769 6789 am223141 case MAC_PROP_DUPLEX: 1770 8118 Vasumathi *perm = MAC_PROP_PERM_READ; 1771 6512 sowmini if (pr_valsize >= sizeof (link_duplex_t)) { 1772 6512 sowmini bcopy(&ngep->param_link_duplex, pr_val, 1773 6512 sowmini sizeof (link_duplex_t)); 1774 6512 sowmini } else 1775 6512 sowmini err = EINVAL; 1776 6200 mx205022 break; 1777 6789 am223141 case MAC_PROP_SPEED: 1778 8118 Vasumathi *perm = MAC_PROP_PERM_READ; 1779 6200 mx205022 if (pr_valsize >= sizeof (uint64_t)) { 1780 6512 sowmini speed = ngep->param_link_speed * 1000000ull; 1781 6512 sowmini bcopy(&speed, pr_val, sizeof (speed)); 1782 6512 sowmini } else 1783 6512 sowmini err = EINVAL; 1784 6512 sowmini break; 1785 6789 am223141 case MAC_PROP_AUTONEG: 1786 6512 sowmini if (is_default) { 1787 6512 sowmini *(uint8_t *)pr_val = 1; 1788 6512 sowmini } else { 1789 6512 sowmini *(uint8_t *)pr_val = ngep->param_adv_autoneg; 1790 6200 mx205022 } 1791 6200 mx205022 break; 1792 6789 am223141 case MAC_PROP_FLOWCTRL: 1793 6200 mx205022 if (pr_valsize >= sizeof (link_flowctrl_t)) { 1794 6789 am223141 if (pr_flags & MAC_PROP_DEFAULT) { 1795 6512 sowmini fl = LINK_FLOWCTRL_BI; 1796 6512 sowmini bcopy(&fl, pr_val, sizeof (fl)); 1797 6512 sowmini break; 1798 6512 sowmini } 1799 6200 mx205022 if (ngep->param_link_rx_pause && 1800 6200 mx205022 !ngep->param_link_tx_pause) 1801 6200 mx205022 fl = LINK_FLOWCTRL_RX; 1802 6200 mx205022 1803 6200 mx205022 if (!ngep->param_link_rx_pause && 1804 6200 mx205022 !ngep->param_link_tx_pause) 1805 6200 mx205022 fl = LINK_FLOWCTRL_NONE; 1806 6200 mx205022 1807 6200 mx205022 if (!ngep->param_link_rx_pause && 1808 6200 mx205022 ngep->param_link_tx_pause) 1809 6200 mx205022 fl = LINK_FLOWCTRL_TX; 1810 6200 mx205022 1811 6200 mx205022 if (ngep->param_link_rx_pause && 1812 6200 mx205022 ngep->param_link_tx_pause) 1813 6200 mx205022 fl = LINK_FLOWCTRL_BI; 1814 6200 mx205022 bcopy(&fl, pr_val, sizeof (fl)); 1815 6512 sowmini } else 1816 6512 sowmini err = EINVAL; 1817 6200 mx205022 break; 1818 6789 am223141 case MAC_PROP_ADV_1000FDX_CAP: 1819 8118 Vasumathi *perm = MAC_PROP_PERM_READ; 1820 6512 sowmini if (is_default) { 1821 6512 sowmini *(uint8_t *)pr_val = 1; 1822 6512 sowmini } else { 1823 6200 mx205022 *(uint8_t *)pr_val = ngep->param_adv_1000fdx; 1824 6200 mx205022 } 1825 6200 mx205022 break; 1826 6789 am223141 case MAC_PROP_EN_1000FDX_CAP: 1827 6512 sowmini if (is_default) { 1828 6512 sowmini *(uint8_t *)pr_val = 1; 1829 6512 sowmini } else { 1830 6200 mx205022 *(uint8_t *)pr_val = ngep->param_en_1000fdx; 1831 6200 mx205022 } 1832 6200 mx205022 break; 1833 6789 am223141 case MAC_PROP_ADV_1000HDX_CAP: 1834 8118 Vasumathi *perm = MAC_PROP_PERM_READ; 1835 6512 sowmini if (is_default) { 1836 6512 sowmini *(uint8_t *)pr_val = 0; 1837 6512 sowmini } else { 1838 6200 mx205022 *(uint8_t *)pr_val = ngep->param_adv_1000hdx; 1839 6200 mx205022 } 1840 6200 mx205022 break; 1841 6789 am223141 case MAC_PROP_EN_1000HDX_CAP: 1842 8118 Vasumathi *perm = MAC_PROP_PERM_READ; 1843 6512 sowmini if (is_default) { 1844 6512 sowmini *(uint8_t *)pr_val = 0; 1845 6512 sowmini } else { 1846 6200 mx205022 *(uint8_t *)pr_val = ngep->param_en_1000hdx; 1847 6200 mx205022 } 1848 6200 mx205022 break; 1849 6789 am223141 case MAC_PROP_ADV_100FDX_CAP: 1850 8118 Vasumathi *perm = MAC_PROP_PERM_READ; 1851 6512 sowmini if (is_default) { 1852 6512 sowmini *(uint8_t *)pr_val = 1; 1853 6512 sowmini } else { 1854 6200 mx205022 *(uint8_t *)pr_val = ngep->param_adv_100fdx; 1855 6200 mx205022 } 1856 6200 mx205022 break; 1857 6789 am223141 case MAC_PROP_EN_100FDX_CAP: 1858 6512 sowmini if (is_default) { 1859 6512 sowmini *(uint8_t *)pr_val = 1; 1860 6512 sowmini } else { 1861 6200 mx205022 *(uint8_t *)pr_val = ngep->param_en_100fdx; 1862 6200 mx205022 } 1863 6200 mx205022 break; 1864 6789 am223141 case MAC_PROP_ADV_100HDX_CAP: 1865 8118 Vasumathi *perm = MAC_PROP_PERM_READ; 1866 6512 sowmini if (is_default) { 1867 6512 sowmini *(uint8_t *)pr_val = 1; 1868 6512 sowmini } else { 1869 6200 mx205022 *(uint8_t *)pr_val = ngep->param_adv_100hdx; 1870 6200 mx205022 } 1871 6200 mx205022 break; 1872 6789 am223141 case MAC_PROP_EN_100HDX_CAP: 1873 6512 sowmini if (is_default) { 1874 6512 sowmini *(uint8_t *)pr_val = 1; 1875 6512 sowmini } else { 1876 6200 mx205022 *(uint8_t *)pr_val = ngep->param_en_100hdx; 1877 6200 mx205022 } 1878 6200 mx205022 break; 1879 6789 am223141 case MAC_PROP_ADV_10FDX_CAP: 1880 8118 Vasumathi *perm = MAC_PROP_PERM_READ; 1881 6512 sowmini if (is_default) { 1882 6512 sowmini *(uint8_t *)pr_val = 1; 1883 6512 sowmini } else { 1884 6200 mx205022 *(uint8_t *)pr_val = ngep->param_adv_10fdx; 1885 6200 mx205022 } 1886 6200 mx205022 break; 1887 6789 am223141 case MAC_PROP_EN_10FDX_CAP: 1888 6512 sowmini if (is_default) { 1889 6512 sowmini *(uint8_t *)pr_val = 1; 1890 6512 sowmini } else { 1891 6200 mx205022 *(uint8_t *)pr_val = ngep->param_en_10fdx; 1892 6200 mx205022 } 1893 6200 mx205022 break; 1894 6789 am223141 case MAC_PROP_ADV_10HDX_CAP: 1895 8118 Vasumathi *perm = MAC_PROP_PERM_READ; 1896 6512 sowmini if (is_default) { 1897 6512 sowmini *(uint8_t *)pr_val = 1; 1898 6512 sowmini } else { 1899 6200 mx205022 *(uint8_t *)pr_val = ngep->param_adv_10hdx; 1900 6200 mx205022 } 1901 6200 mx205022 break; 1902 6789 am223141 case MAC_PROP_EN_10HDX_CAP: 1903 6512 sowmini if (is_default) { 1904 6512 sowmini *(uint8_t *)pr_val = 1; 1905 6512 sowmini } else { 1906 6200 mx205022 *(uint8_t *)pr_val = ngep->param_en_10hdx; 1907 6200 mx205022 } 1908 6200 mx205022 break; 1909 6789 am223141 case MAC_PROP_ADV_100T4_CAP: 1910 6789 am223141 case MAC_PROP_EN_100T4_CAP: 1911 8118 Vasumathi *perm = MAC_PROP_PERM_READ; 1912 6512 sowmini *(uint8_t *)pr_val = 0; 1913 6512 sowmini break; 1914 6789 am223141 case MAC_PROP_PRIVATE: 1915 6512 sowmini err = nge_get_priv_prop(ngep, pr_name, pr_flags, 1916 6512 sowmini pr_valsize, pr_val); 1917 6200 mx205022 break; 1918 9514 Girish case MAC_PROP_MTU: { 1919 9514 Girish mac_propval_range_t range; 1920 9514 Girish 1921 9514 Girish if (!(pr_flags & MAC_PROP_POSSIBLE)) 1922 9514 Girish return (ENOTSUP); 1923 9514 Girish if (pr_valsize < sizeof (mac_propval_range_t)) 1924 9514 Girish return (EINVAL); 1925 9514 Girish range.mpr_count = 1; 1926 9514 Girish range.mpr_type = MAC_PROPVAL_UINT32; 1927 9514 Girish range.range_uint32[0].mpur_min = 1928 9514 Girish range.range_uint32[0].mpur_max = ETHERMTU; 1929 9514 Girish if (ngep->dev_spec_param.jumbo) 1930 9514 Girish range.range_uint32[0].mpur_max = NGE_MAX_MTU; 1931 9514 Girish bcopy(&range, pr_val, sizeof (range)); 1932 9514 Girish break; 1933 9514 Girish } 1934 6200 mx205022 default: 1935 6200 mx205022 err = ENOTSUP; 1936 6200 mx205022 } 1937 6200 mx205022 return (err); 1938 6200 mx205022 } 1939 6200 mx205022 1940 6200 mx205022 /* ARGSUSED */ 1941 6200 mx205022 static int 1942 6200 mx205022 nge_set_priv_prop(nge_t *ngep, const char *pr_name, uint_t pr_valsize, 1943 6200 mx205022 const void *pr_val) 1944 6200 mx205022 { 1945 6200 mx205022 int err = 0; 1946 6200 mx205022 long result; 1947 6200 mx205022 1948 6200 mx205022 if (strcmp(pr_name, "_tx_bcopy_threshold") == 0) { 1949 6200 mx205022 if (pr_val == NULL) { 1950 6200 mx205022 err = EINVAL; 1951 6200 mx205022 return (err); 1952 6200 mx205022 } 1953 6200 mx205022 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 1954 6200 mx205022 if (result < 0 || result > NGE_MAX_SDU) { 1955 6200 mx205022 err = EINVAL; 1956 6200 mx205022 } else { 1957 6200 mx205022 ngep->param_txbcopy_threshold = (uint32_t)result; 1958 6200 mx205022 goto reprogram; 1959 6200 mx205022 } 1960 6200 mx205022 return (err); 1961 6200 mx205022 } 1962 6200 mx205022 if (strcmp(pr_name, "_rx_bcopy_threshold") == 0) { 1963 6200 mx205022 if (pr_val == NULL) { 1964 6200 mx205022 err = EINVAL; 1965 6200 mx205022 return (err); 1966 6200 mx205022 } 1967 6200 mx205022 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 1968 6200 mx205022 if (result < 0 || result > NGE_MAX_SDU) { 1969 6200 mx205022 err = EINVAL; 1970 6200 mx205022 } else { 1971 6200 mx205022 ngep->param_rxbcopy_threshold = (uint32_t)result; 1972 6200 mx205022 goto reprogram; 1973 6200 mx205022 } 1974 6200 mx205022 return (err); 1975 6200 mx205022 } 1976 6200 mx205022 if (strcmp(pr_name, "_recv_max_packet") == 0) { 1977 6200 mx205022 if (pr_val == NULL) { 1978 6200 mx205022 err = EINVAL; 1979 6200 mx205022 return (err); 1980 6200 mx205022 } 1981 6200 mx205022 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 1982 6200 mx205022 if (result < 0 || result > NGE_RECV_SLOTS_DESC_1024) { 1983 6200 mx205022 err = EINVAL; 1984 6200 mx205022 } else { 1985 6200 mx205022 ngep->param_recv_max_packet = (uint32_t)result; 1986 6200 mx205022 goto reprogram; 1987 6200 mx205022 } 1988 6200 mx205022 return (err); 1989 6200 mx205022 } 1990 6200 mx205022 if (strcmp(pr_name, "_poll_quiet_time") == 0) { 1991 6200 mx205022 if (pr_val == NULL) { 1992 6200 mx205022 err = EINVAL; 1993 6200 mx205022 return (err); 1994 6200 mx205022 } 1995 6200 mx205022 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 1996 6200 mx205022 if (result < 0 || result > 10000) { 1997 6200 mx205022 err = EINVAL; 1998 6200 mx205022 } else { 1999 6200 mx205022 ngep->param_poll_quiet_time = (uint32_t)result; 2000 6200 mx205022 goto reprogram; 2001 6200 mx205022 } 2002 6200 mx205022 return (err); 2003 6200 mx205022 } 2004 6200 mx205022 if (strcmp(pr_name, "_poll_busy_time") == 0) { 2005 6200 mx205022 if (pr_val == NULL) { 2006 6200 mx205022 err = EINVAL; 2007 6200 mx205022 return (err); 2008 6200 mx205022 } 2009 6200 mx205022 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 2010 6200 mx205022 if (result < 0 || result > 10000) { 2011 6200 mx205022 err = EINVAL; 2012 6200 mx205022 } else { 2013 6200 mx205022 ngep->param_poll_busy_time = (uint32_t)result; 2014 6200 mx205022 goto reprogram; 2015 6200 mx205022 } 2016 6200 mx205022 return (err); 2017 6200 mx205022 } 2018 6200 mx205022 if (strcmp(pr_name, "_rx_intr_hwater") == 0) { 2019 6200 mx205022 if (pr_val == NULL) { 2020 6200 mx205022 err = EINVAL; 2021 6200 mx205022 return (err); 2022 6200 mx205022 } 2023 6200 mx205022 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 2024 6512 sowmini if (result < 0 || result > NGE_RECV_SLOTS_DESC_1024) { 2025 6200 mx205022 err = EINVAL; 2026 6200 mx205022 } else { 2027 6200 mx205022 ngep->param_rx_intr_hwater = (uint32_t)result; 2028 6200 mx205022 goto reprogram; 2029 6200 mx205022 } 2030 6200 mx205022 return (err); 2031 6200 mx205022 } 2032 6200 mx205022 if (strcmp(pr_name, "_rx_intr_lwater") == 0) { 2033 6200 mx205022 if (pr_val == NULL) { 2034 6200 mx205022 err = EINVAL; 2035 6200 mx205022 return (err); 2036 6200 mx205022 } 2037 6200 mx205022 (void) ddi_strtol(pr_val, (char **)NULL, 0, &result); 2038 6512 sowmini if (result < 0 || result > NGE_RECV_SLOTS_DESC_1024) { 2039 6200 mx205022 err = EINVAL; 2040 6200 mx205022 } else { 2041 6200 mx205022 ngep->param_rx_intr_lwater = (uint32_t)result; 2042 6200 mx205022 goto reprogram; 2043 6200 mx205022 } 2044 6200 mx205022 return (err); 2045 6200 mx205022 } 2046 6200 mx205022 err = ENOTSUP; 2047 6200 mx205022 return (err); 2048 6200 mx205022 2049 6200 mx205022 reprogram: 2050 6200 mx205022 if (err == 0) { 2051 6200 mx205022 (*ngep->physops->phys_update)(ngep); 2052 6200 mx205022 nge_chip_sync(ngep); 2053 6200 mx205022 } 2054 6200 mx205022 2055 6200 mx205022 return (err); 2056 6200 mx205022 } 2057 6200 mx205022 2058 6200 mx205022 static int 2059 6512 sowmini nge_get_priv_prop(nge_t *ngep, const char *pr_name, uint_t pr_flags, 2060 6512 sowmini uint_t pr_valsize, void *pr_val) 2061 6200 mx205022 { 2062 6200 mx205022 int err = ENOTSUP; 2063 6789 am223141 boolean_t is_default = (pr_flags & MAC_PROP_DEFAULT); 2064 6512 sowmini int value; 2065 6200 mx205022 2066 6200 mx205022 if (strcmp(pr_name, "_tx_bcopy_threshold") == 0) { 2067 6512 sowmini value = (is_default ? NGE_TX_COPY_SIZE : 2068 6512 sowmini ngep->param_txbcopy_threshold); 2069 6200 mx205022 err = 0; 2070 6200 mx205022 goto done; 2071 6200 mx205022 } 2072 6200 mx205022 if (strcmp(pr_name, "_rx_bcopy_threshold") == 0) { 2073 6512 sowmini value = (is_default ? NGE_RX_COPY_SIZE : 2074 6512 sowmini ngep->param_rxbcopy_threshold); 2075 6200 mx205022 err = 0; 2076 6200 mx205022 goto done; 2077 6200 mx205022 } 2078 6200 mx205022 if (strcmp(pr_name, "_recv_max_packet") == 0) { 2079 6512 sowmini value = (is_default ? 128 : ngep->param_recv_max_packet); 2080 6200 mx205022 err = 0; 2081 6200 mx205022 goto done; 2082 6200 mx205022 } 2083 6200 mx205022 if (strcmp(pr_name, "_poll_quiet_time") == 0) { 2084 6512 sowmini value = (is_default ? NGE_POLL_QUIET_TIME : 2085 6512 sowmini ngep->param_poll_quiet_time); 2086 6200 mx205022 err = 0; 2087 6200 mx205022 goto done; 2088 6200 mx205022 } 2089 6200 mx205022 if (strcmp(pr_name, "_poll_busy_time") == 0) { 2090 6512 sowmini value = (is_default ? NGE_POLL_BUSY_TIME : 2091 6512 sowmini ngep->param_poll_busy_time); 2092 6200 mx205022 err = 0; 2093 6200 mx205022 goto done; 2094 6200 mx205022 } 2095 6200 mx205022 if (strcmp(pr_name, "_rx_intr_hwater") == 0) { 2096 6512 sowmini value = (is_default ? 1 : ngep->param_rx_intr_hwater); 2097 6200 mx205022 err = 0; 2098 6200 mx205022 goto done; 2099 6200 mx205022 } 2100 6200 mx205022 if (strcmp(pr_name, "_rx_intr_lwater") == 0) { 2101 6512 sowmini value = (is_default ? 8 : ngep->param_rx_intr_lwater); 2102 6200 mx205022 err = 0; 2103 6200 mx205022 goto done; 2104 6200 mx205022 } 2105 6200 mx205022 2106 6200 mx205022 done: 2107 6200 mx205022 if (err == 0) { 2108 6512 sowmini (void) snprintf(pr_val, pr_valsize, "%d", value); 2109 6200 mx205022 } 2110 6200 mx205022 return (err); 2111 6200 mx205022 } 2112 6200 mx205022 2113 5574 mx205022 /* ARGSUSED */ 2114 5574 mx205022 static boolean_t 2115 5574 mx205022 nge_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 2116 5574 mx205022 { 2117 5574 mx205022 nge_t *ngep = arg; 2118 5574 mx205022 nge_dev_spec_param_t *dev_param_p; 2119 5574 mx205022 2120 5574 mx205022 dev_param_p = &ngep->dev_spec_param; 2121 5574 mx205022 2122 5574 mx205022 switch (cap) { 2123 5574 mx205022 case MAC_CAPAB_HCKSUM: { 2124 5574 mx205022 uint32_t *hcksum_txflags = cap_data; 2125 5574 mx205022 2126 5574 mx205022 if (dev_param_p->tx_hw_checksum) { 2127 5574 mx205022 *hcksum_txflags = dev_param_p->tx_hw_checksum; 2128 5574 mx205022 } else 2129 5574 mx205022 return (B_FALSE); 2130 5574 mx205022 break; 2131 5574 mx205022 } 2132 5574 mx205022 default: 2133 5574 mx205022 return (B_FALSE); 2134 5574 mx205022 } 2135 5574 mx205022 return (B_TRUE); 2136 5574 mx205022 } 2137 5574 mx205022 2138 5574 mx205022 #undef NGE_DBG 2139 5574 mx205022 #define NGE_DBG NGE_DBG_INIT /* debug flag for this code */ 2140 5574 mx205022 int 2141 5574 mx205022 nge_restart(nge_t *ngep) 2142 5574 mx205022 { 2143 5574 mx205022 int err = 0; 2144 7656 Sherry err = nge_reset_dev(ngep); 2145 7155 mx205022 /* write back the promisc setting */ 2146 7155 mx205022 ngep->promisc = ngep->record_promisc; 2147 6366 mx205022 nge_chip_sync(ngep); 2148 5869 mx205022 if (!err) 2149 5869 mx205022 err = nge_chip_start(ngep); 2150 5574 mx205022 2151 5574 mx205022 if (err) { 2152 5574 mx205022 ngep->nge_mac_state = NGE_MAC_STOPPED; 2153 5574 mx205022 return (DDI_FAILURE); 2154 5574 mx205022 } else { 2155 5574 mx205022 ngep->nge_mac_state = NGE_MAC_STARTED; 2156 5574 mx205022 return (DDI_SUCCESS); 2157 5574 mx205022 } 2158 5574 mx205022 } 2159 5574 mx205022 2160 5574 mx205022 void 2161 5574 mx205022 nge_wake_factotum(nge_t *ngep) 2162 5574 mx205022 { 2163 5574 mx205022 mutex_enter(ngep->softlock); 2164 5574 mx205022 if (ngep->factotum_flag == 0) { 2165 5574 mx205022 ngep->factotum_flag = 1; 2166 5574 mx205022 (void) ddi_intr_trigger_softint(ngep->factotum_hdl, NULL); 2167 5574 mx205022 } 2168 5574 mx205022 mutex_exit(ngep->softlock); 2169 5574 mx205022 } 2170 5574 mx205022 2171 10615 Zhen void 2172 10615 Zhen nge_interrupt_optimize(nge_t *ngep) 2173 10615 Zhen { 2174 10615 Zhen uint32_t tx_pkts; 2175 10615 Zhen tx_pkts = ngep->statistics.sw_statistics.xmit_count - ngep->tpkts_last; 2176 10615 Zhen ngep->tpkts_last = ngep->statistics.sw_statistics.xmit_count; 2177 10615 Zhen if ((tx_pkts > NGE_POLL_TUNE) && 2178 10615 Zhen (tx_pkts <= NGE_POLL_MAX)) 2179 10615 Zhen ngep->tfint_threshold = (tx_pkts / NGE_POLL_ENTER); 2180 10615 Zhen else 2181 10615 Zhen ngep->tfint_threshold = NGE_TFINT_DEFAULT; 2182 10615 Zhen } 2183 10615 Zhen 2184 5574 mx205022 /* 2185 5574 mx205022 * High-level cyclic handler 2186 5574 mx205022 * 2187 5574 mx205022 * This routine schedules a (low-level) softint callback to the 2188 5574 mx205022 * factotum. 2189 5574 mx205022 */ 2190 5574 mx205022 2191 5574 mx205022 static void 2192 5574 mx205022 nge_chip_cyclic(void *arg) 2193 5574 mx205022 { 2194 5574 mx205022 nge_t *ngep; 2195 5574 mx205022 2196 5574 mx205022 ngep = (nge_t *)arg; 2197 5574 mx205022 2198 5574 mx205022 switch (ngep->nge_chip_state) { 2199 5574 mx205022 default: 2200 5574 mx205022 return; 2201 5574 mx205022 2202 5574 mx205022 case NGE_CHIP_RUNNING: 2203 10615 Zhen nge_interrupt_optimize(ngep); 2204 5574 mx205022 break; 2205 5574 mx205022 2206 5574 mx205022 case NGE_CHIP_FAULT: 2207 5574 mx205022 case NGE_CHIP_ERROR: 2208 5574 mx205022 break; 2209 5574 mx205022 } 2210 5574 mx205022 2211 5574 mx205022 nge_wake_factotum(ngep); 2212 5574 mx205022 } 2213 5574 mx205022 2214 9604 Zhen /* 2215 9604 Zhen * Get/Release semaphore of SMU 2216 9604 Zhen * For SMU enabled chipset 2217 9604 Zhen * When nge driver is attached, driver should acquire 2218 9604 Zhen * semaphore before PHY init and accessing MAC registers. 2219 9604 Zhen * When nge driver is unattached, driver should release 2220 9604 Zhen * semaphore. 2221 9604 Zhen */ 2222 9604 Zhen 2223 9604 Zhen static int 2224 9604 Zhen nge_smu_sema(nge_t *ngep, boolean_t acquire) 2225 9604 Zhen { 2226 9604 Zhen nge_tx_en tx_en; 2227 9604 Zhen uint32_t tries; 2228 9604 Zhen 2229 9604 Zhen if (acquire) { 2230 9604 Zhen for (tries = 0; tries < 5; tries++) { 2231 9604 Zhen tx_en.val = nge_reg_get32(ngep, NGE_TX_EN); 2232 9604 Zhen if (tx_en.bits.smu2mac == NGE_SMU_FREE) 2233 9604 Zhen break; 2234 9604 Zhen delay(drv_usectohz(1000000)); 2235 9604 Zhen } 2236 9604 Zhen if (tx_en.bits.smu2mac != NGE_SMU_FREE) 2237 9604 Zhen return (DDI_FAILURE); 2238 9604 Zhen for (tries = 0; tries < 5; tries++) { 2239 9604 Zhen tx_en.val = nge_reg_get32(ngep, NGE_TX_EN); 2240 9604 Zhen tx_en.bits.mac2smu = NGE_SMU_GET; 2241 9604 Zhen nge_reg_put32(ngep, NGE_TX_EN, tx_en.val); 2242 9604 Zhen tx_en.val = nge_reg_get32(ngep, NGE_TX_EN); 2243 9604 Zhen 2244 9604 Zhen if (tx_en.bits.mac2smu == NGE_SMU_GET && 2245 9604 Zhen tx_en.bits.smu2mac == NGE_SMU_FREE) 2246 9604 Zhen return (DDI_SUCCESS); 2247 9604 Zhen drv_usecwait(10); 2248 9604 Zhen } 2249 9604 Zhen return (DDI_FAILURE); 2250 9604 Zhen } else 2251 9604 Zhen nge_reg_put32(ngep, NGE_TX_EN, 0x0); 2252 9604 Zhen 2253 9604 Zhen return (DDI_SUCCESS); 2254 9604 Zhen 2255 9604 Zhen } 2256 5574 mx205022 static void 2257 5574 mx205022 nge_unattach(nge_t *ngep) 2258 5574 mx205022 { 2259 5574 mx205022 send_ring_t *srp; 2260 5574 mx205022 buff_ring_t *brp; 2261 5574 mx205022 2262 5574 mx205022 srp = ngep->send; 2263 5574 mx205022 brp = ngep->buff; 2264 5574 mx205022 NGE_TRACE(("nge_unattach($%p)", (void *)ngep)); 2265 5574 mx205022 2266 5574 mx205022 /* 2267 5574 mx205022 * Flag that no more activity may be initiated 2268 5574 mx205022 */ 2269 5574 mx205022 ngep->progress &= ~PROGRESS_READY; 2270 5574 mx205022 ngep->nge_mac_state = NGE_MAC_UNATTACH; 2271 5574 mx205022 2272 5574 mx205022 /* 2273 5574 mx205022 * Quiesce the PHY and MAC (leave it reset but still powered). 2274 5574 mx205022 * Clean up and free all NGE data structures 2275 5574 mx205022 */ 2276 5574 mx205022 if (ngep->periodic_id != NULL) { 2277 5574 mx205022 ddi_periodic_delete(ngep->periodic_id); 2278 5574 mx205022 ngep->periodic_id = NULL; 2279 5574 mx205022 } 2280 5574 mx205022 2281 5574 mx205022 if (ngep->progress & PROGRESS_KSTATS) 2282 5574 mx205022 nge_fini_kstats(ngep); 2283 5574 mx205022 2284 5574 mx205022 if (ngep->progress & PROGRESS_HWINT) { 2285 5574 mx205022 mutex_enter(ngep->genlock); 2286 5574 mx205022 nge_restore_mac_addr(ngep); 2287 5574 mx205022 (void) nge_chip_stop(ngep, B_FALSE); 2288 9604 Zhen if (ngep->chipinfo.device == DEVICE_ID_MCP55_373 || 2289 9604 Zhen ngep->chipinfo.device == DEVICE_ID_MCP55_372) { 2290 9604 Zhen (void) nge_smu_sema(ngep, B_FALSE); 2291 9604 Zhen } 2292 5574 mx205022 mutex_exit(ngep->genlock); 2293 5574 mx205022 } 2294 5574 mx205022 2295 5574 mx205022 if (ngep->progress & PROGRESS_SWINT) 2296 5574 mx205022 nge_rem_intrs(ngep); 2297 5574 mx205022 2298 5574 mx205022 if (ngep->progress & PROGRESS_FACTOTUM) 2299 5574 mx205022 (void) ddi_intr_remove_softint(ngep->factotum_hdl); 2300 5574 mx205022 2301 5574 mx205022 if (ngep->progress & PROGRESS_RESCHED) 2302 5574 mx205022 (void) ddi_intr_remove_softint(ngep->resched_hdl); 2303 5574 mx205022 2304 5574 mx205022 if (ngep->progress & PROGRESS_INTR) { 2305 5574 mx205022 mutex_destroy(srp->tx_lock); 2306 5574 mx205022 mutex_destroy(srp->tc_lock); 2307 5574 mx205022 mutex_destroy(&srp->dmah_lock); 2308 5574 mx205022 mutex_destroy(brp->recycle_lock); 2309 5574 mx205022 2310 5574 mx205022 mutex_destroy(ngep->genlock); 2311 5574 mx205022 mutex_destroy(ngep->softlock); 2312 5574 mx205022 rw_destroy(ngep->rwlock); 2313 5574 mx205022 } 2314 5574 mx205022 2315 5574 mx205022 if (ngep->progress & PROGRESS_REGS) 2316 5574 mx205022 ddi_regs_map_free(&ngep->io_handle); 2317 5574 mx205022 2318 5574 mx205022 if (ngep->progress & PROGRESS_CFG) 2319 5574 mx205022 pci_config_teardown(&ngep->cfg_handle); 2320 5574 mx205022 2321 5574 mx205022 ddi_remove_minor_node(ngep->devinfo, NULL); 2322 5574 mx205022 2323 5574 mx205022 kmem_free(ngep, sizeof (*ngep)); 2324 5574 mx205022 } 2325 5574 mx205022 2326 5574 mx205022 static int 2327 5574 mx205022 nge_resume(dev_info_t *devinfo) 2328 5574 mx205022 { 2329 5574 mx205022 nge_t *ngep; 2330 5574 mx205022 chip_info_t *infop; 2331 5869 mx205022 int err; 2332 5574 mx205022 2333 5574 mx205022 ASSERT(devinfo != NULL); 2334 5574 mx205022 2335 5574 mx205022 ngep = ddi_get_driver_private(devinfo); 2336 5869 mx205022 err = 0; 2337 5869 mx205022 2338 5574 mx205022 /* 2339 5574 mx205022 * If there are state inconsistancies, this is bad. Returning 2340 5574 mx205022 * DDI_FAILURE here will eventually cause the machine to panic, 2341 5574 mx205022 * so it is best done here so that there is a possibility of 2342 5574 mx205022 * debugging the problem. 2343 5574 mx205022 */ 2344 5574 mx205022 if (ngep == NULL) 2345 5574 mx205022 cmn_err(CE_PANIC, 2346 5574 mx205022 "nge: ngep returned from ddi_get_driver_private was NULL"); 2347 5574 mx205022 infop = (chip_info_t *)&ngep->chipinfo; 2348 5574 mx205022 2349 5574 mx205022 if (ngep->devinfo != devinfo) 2350 5574 mx205022 cmn_err(CE_PANIC, 2351 5869 mx205022 "nge: passed devinfo not the same as saved devinfo"); 2352 5574 mx205022 2353 5869 mx205022 mutex_enter(ngep->genlock); 2354 5869 mx205022 rw_enter(ngep->rwlock, RW_WRITER); 2355 5574 mx205022 2356 5574 mx205022 /* 2357 5574 mx205022 * Fetch the config space. Even though we have most of it cached, 2358 5574 mx205022 * some values *might* change across a suspend/resume. 2359 5574 mx205022 */ 2360 5574 mx205022 nge_chip_cfg_init(ngep, infop, B_FALSE); 2361 5574 mx205022 2362 5574 mx205022 /* 2363 5869 mx205022 * Only in one case, this conditional branch can be executed: the port 2364 5869 mx205022 * hasn't been plumbed. 2365 5574 mx205022 */ 2366 5869 mx205022 if (ngep->suspended == B_FALSE) { 2367 5869 mx205022 rw_exit(ngep->rwlock); 2368 5869 mx205022 mutex_exit(ngep->genlock); 2369 5869 mx205022 return (DDI_SUCCESS); 2370 5869 mx205022 } 2371 5869 mx205022 2372 5869 mx205022 nge_tx_recycle_all(ngep); 2373 5869 mx205022 err = nge_reinit_ring(ngep); 2374 5869 mx205022 if (!err) { 2375 5869 mx205022 err = nge_chip_reset(ngep); 2376 5869 mx205022 if (!err) 2377 5869 mx205022 err = nge_chip_start(ngep); 2378 5869 mx205022 } 2379 5869 mx205022 2380 5869 mx205022 if (err) { 2381 5574 mx205022 /* 2382 5574 mx205022 * We note the failure, but return success, as the 2383 5574 mx205022 * system is still usable without this controller. 2384 5574 mx205022 */ 2385 5574 mx205022 cmn_err(CE_WARN, "nge: resume: failed to restart controller"); 2386 5869 mx205022 } else { 2387 5869 mx205022 ngep->nge_mac_state = NGE_MAC_STARTED; 2388 5574 mx205022 } 2389 5869 mx205022 ngep->suspended = B_FALSE; 2390 5869 mx205022 2391 5869 mx205022 rw_exit(ngep->rwlock); 2392 5869 mx205022 mutex_exit(ngep->genlock); 2393 5869 mx205022 2394 5574 mx205022 return (DDI_SUCCESS); 2395 5574 mx205022 } 2396 5574 mx205022 2397 5574 mx205022 /* 2398 5574 mx205022 * attach(9E) -- Attach a device to the system 2399 5574 mx205022 * 2400 5574 mx205022 * Called once for each board successfully probed. 2401 5574 mx205022 */ 2402 5574 mx205022 static int 2403 5574 mx205022 nge_attach(dev_info_t *devinfo, ddi_attach_cmd_t cmd) 2404 5574 mx205022 { 2405 5574 mx205022 int err; 2406 5574 mx205022 int i; 2407 5574 mx205022 int instance; 2408 5574 mx205022 caddr_t regs; 2409 5574 mx205022 nge_t *ngep; 2410 5574 mx205022 chip_info_t *infop; 2411 5574 mx205022 mac_register_t *macp; 2412 5574 mx205022 2413 5574 mx205022 switch (cmd) { 2414 5574 mx205022 default: 2415 5574 mx205022 return (DDI_FAILURE); 2416 5574 mx205022 2417 5574 mx205022 case DDI_RESUME: 2418 5574 mx205022 return (nge_resume(devinfo)); 2419 5574 mx205022 2420 5574 mx205022 case DDI_ATTACH: 2421 5574 mx205022 break; 2422 5574 mx205022 } 2423 5574 mx205022 2424 5574 mx205022 ngep = kmem_zalloc(sizeof (*ngep), KM_SLEEP); 2425 5574 mx205022 instance = ddi_get_instance(devinfo); 2426 5574 mx205022 ddi_set_driver_private(devinfo, ngep); 2427 5574 mx205022 ngep->devinfo = devinfo; 2428 5574 mx205022 2429 5574 mx205022 (void) snprintf(ngep->ifname, sizeof (ngep->ifname), "%s%d", 2430 5574 mx205022 NGE_DRIVER_NAME, instance); 2431 5574 mx205022 err = pci_config_setup(devinfo, &ngep->cfg_handle); 2432 5574 mx205022 if (err != DDI_SUCCESS) { 2433 5574 mx205022 nge_problem(ngep, "nge_attach: pci_config_setup() failed"); 2434 5574 mx205022 goto attach_fail; 2435 5574 mx205022 } 2436 6512 sowmini /* 2437 6512 sowmini * param_txbcopy_threshold and param_rxbcopy_threshold are tx/rx bcopy 2438 6512 sowmini * thresholds. Bounds: min 0, max NGE_MAX_SDU 2439 6512 sowmini */ 2440 6512 sowmini ngep->param_txbcopy_threshold = NGE_TX_COPY_SIZE; 2441 6512 sowmini ngep->param_rxbcopy_threshold = NGE_RX_COPY_SIZE; 2442 6512 sowmini 2443 6512 sowmini /* 2444 6512 sowmini * param_recv_max_packet is max packet received per interupt. 2445 6512 sowmini * Bounds: min 0, max NGE_RECV_SLOTS_DESC_1024 2446 6512 sowmini */ 2447 6512 sowmini ngep->param_recv_max_packet = 128; 2448 6512 sowmini 2449 6512 sowmini /* 2450 6512 sowmini * param_poll_quiet_time and param_poll_busy_time are quiet/busy time 2451 6512 sowmini * switch from per packet interrupt to polling interrupt. 2452 6512 sowmini * Bounds: min 0, max 10000 2453 6512 sowmini */ 2454 6512 sowmini ngep->param_poll_quiet_time = NGE_POLL_QUIET_TIME; 2455 6512 sowmini ngep->param_poll_busy_time = NGE_POLL_BUSY_TIME; 2456 10615 Zhen ngep->tfint_threshold = NGE_TFINT_DEFAULT; 2457 10615 Zhen ngep->poll = B_FALSE; 2458 10615 Zhen ngep->ch_intr_mode = B_FALSE; 2459 6512 sowmini 2460 6512 sowmini /* 2461 6512 sowmini * param_rx_intr_hwater/param_rx_intr_lwater: ackets received 2462 6512 sowmini * to trigger the poll_quiet_time/poll_busy_time counter. 2463 6512 sowmini * Bounds: min 0, max NGE_RECV_SLOTS_DESC_1024. 2464 6512 sowmini */ 2465 6512 sowmini ngep->param_rx_intr_hwater = 1; 2466 6512 sowmini ngep->param_rx_intr_lwater = 8; 2467 6512 sowmini 2468 6512 sowmini 2469 5574 mx205022 infop = (chip_info_t *)&ngep->chipinfo; 2470 5574 mx205022 nge_chip_cfg_init(ngep, infop, B_FALSE); 2471 5574 mx205022 nge_init_dev_spec_param(ngep); 2472 5574 mx205022 nge_get_props(ngep); 2473 5574 mx205022 ngep->progress |= PROGRESS_CFG; 2474 5574 mx205022 2475 5574 mx205022 err = ddi_regs_map_setup(devinfo, NGE_PCI_OPREGS_RNUMBER, 2476 5574 mx205022 ®s, 0, 0, &nge_reg_accattr, &ngep->io_handle); 2477 5574 mx205022 if (err != DDI_SUCCESS) { 2478 5574 mx205022 nge_problem(ngep, "nge_attach: ddi_regs_map_setup() failed"); 2479 5574 mx205022 goto attach_fail; 2480 5574 mx205022 } 2481 5574 mx205022 ngep->io_regs = regs; 2482 5574 mx205022 ngep->progress |= PROGRESS_REGS; 2483 5574 mx205022 2484 5574 mx205022 err = nge_register_intrs_and_init_locks(ngep); 2485 5574 mx205022 if (err != DDI_SUCCESS) { 2486 5574 mx205022 nge_problem(ngep, "nge_attach:" 2487 5574 mx205022 " register intrs and init locks failed"); 2488 5574 mx205022 goto attach_fail; 2489 5574 mx205022 } 2490 5574 mx205022 nge_init_ring_param_lock(ngep); 2491 5574 mx205022 ngep->progress |= PROGRESS_INTR; 2492 5574 mx205022 2493 5574 mx205022 mutex_enter(ngep->genlock); 2494 5574 mx205022 2495 9604 Zhen if (ngep->chipinfo.device == DEVICE_ID_MCP55_373 || 2496 9604 Zhen ngep->chipinfo.device == DEVICE_ID_MCP55_372) { 2497 9604 Zhen err = nge_smu_sema(ngep, B_TRUE); 2498 9604 Zhen if (err != DDI_SUCCESS) { 2499 9604 Zhen nge_problem(ngep, "nge_attach: nge_smu_sema() failed"); 2500 9604 Zhen goto attach_fail; 2501 9604 Zhen } 2502 9604 Zhen } 2503 5574 mx205022 /* 2504 5574 mx205022 * Initialise link state variables 2505 5574 mx205022 * Stop, reset & reinitialise the chip. 2506 5574 mx205022 * Initialise the (internal) PHY. 2507 5574 mx205022 */ 2508 5574 mx205022 nge_phys_init(ngep); 2509 8218 Min ngep->nge_chip_state = NGE_CHIP_INITIAL; 2510 5574 mx205022 err = nge_chip_reset(ngep); 2511 5574 mx205022 if (err != DDI_SUCCESS) { 2512 5574 mx205022 nge_problem(ngep, "nge_attach: nge_chip_reset() failed"); 2513 5574 mx205022 mutex_exit(ngep->genlock); 2514 5574 mx205022 goto attach_fail; 2515 5574 mx205022 } 2516 5574 mx205022 nge_chip_sync(ngep); 2517 5574 mx205022 2518 5574 mx205022 /* 2519 5574 mx205022 * Now that mutex locks are initialized, enable interrupts. 2520 5574 mx205022 */ 2521 5574 mx205022 if (ngep->intr_cap & DDI_INTR_FLAG_BLOCK) { 2522 5574 mx205022 /* Call ddi_intr_block_enable() for MSI interrupts */ 2523 5574 mx205022 (void) ddi_intr_block_enable(ngep->htable, 2524 5574 mx205022 ngep->intr_actual_cnt); 2525 5574 mx205022 } else { 2526 5574 mx205022 /* Call ddi_intr_enable for MSI or FIXED interrupts */ 2527 5574 mx205022 for (i = 0; i < ngep->intr_actual_cnt; i++) { 2528 5574 mx205022 (void) ddi_intr_enable(ngep->htable[i]); 2529 5574 mx205022 } 2530 5574 mx205022 } 2531 5574 mx205022 2532 5574 mx205022 ngep->link_state = LINK_STATE_UNKNOWN; 2533 5574 mx205022 ngep->progress |= PROGRESS_HWINT; 2534 5574 mx205022 2535 5574 mx205022 /* 2536 5574 mx205022 * Register NDD-tweakable parameters 2537 5574 mx205022 */ 2538 5574 mx205022 if (nge_nd_init(ngep)) { 2539 5574 mx205022 nge_problem(ngep, "nge_attach: nge_nd_init() failed"); 2540 5574 mx205022 mutex_exit(ngep->genlock); 2541 5574 mx205022 goto attach_fail; 2542 5574 mx205022 } 2543 5574 mx205022 ngep->progress |= PROGRESS_NDD; 2544 5574 mx205022 2545 5574 mx205022 /* 2546 5574 mx205022 * Create & initialise named kstats 2547 5574 mx205022 */ 2548 5574 mx205022 nge_init_kstats(ngep, instance); 2549 5574 mx205022 ngep->progress |= PROGRESS_KSTATS; 2550 5574 mx205022 2551 5574 mx205022 mutex_exit(ngep->genlock); 2552 5574 mx205022 2553 5574 mx205022 if ((macp = mac_alloc(MAC_VERSION)) == NULL) 2554 5574 mx205022 goto attach_fail; 2555 5574 mx205022 macp->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 2556 5574 mx205022 macp->m_driver = ngep; 2557 5574 mx205022 macp->m_dip = devinfo; 2558 5574 mx205022 macp->m_src_addr = infop->vendor_addr.addr; 2559 5574 mx205022 macp->m_callbacks = &nge_m_callbacks; 2560 5574 mx205022 macp->m_min_sdu = 0; 2561 5574 mx205022 macp->m_max_sdu = ngep->default_mtu; 2562 5895 yz147064 macp->m_margin = VTAG_SIZE; 2563 6512 sowmini macp->m_priv_props = nge_priv_props; 2564 6512 sowmini macp->m_priv_prop_count = NGE_MAX_PRIV_PROPS; 2565 5574 mx205022 /* 2566 5574 mx205022 * Finally, we're ready to register ourselves with the mac 2567 5574 mx205022 * interface; if this succeeds, we're all ready to start() 2568 5574 mx205022 */ 2569 5574 mx205022 err = mac_register(macp, &ngep->mh); 2570 5574 mx205022 mac_free(macp); 2571 5574 mx205022 if (err != 0) 2572 5574 mx205022 goto attach_fail; 2573 5574 mx205022 2574 5574 mx205022 /* 2575 5574 mx205022 * Register a periodical handler. 2576 5574 mx205022 * nge_chip_cyclic() is invoked in kernel context. 2577 5574 mx205022 */ 2578 5574 mx205022 ngep->periodic_id = ddi_periodic_add(nge_chip_cyclic, ngep, 2579 5574 mx205022 NGE_CYCLIC_PERIOD, DDI_IPL_0); 2580 5574 mx205022 2581 5574 mx205022 ngep->progress |= PROGRESS_READY; 2582 5574 mx205022 return (DDI_SUCCESS); 2583 5574 mx205022 2584 5574 mx205022 attach_fail: 2585 5574 mx205022 nge_unattach(ngep); 2586 5574 mx205022 return (DDI_FAILURE); 2587 5574 mx205022 } 2588 5574 mx205022 2589 5869 mx205022 static int 2590 5869 mx205022 nge_suspend(nge_t *ngep) 2591 5869 mx205022 { 2592 5869 mx205022 mutex_enter(ngep->genlock); 2593 5869 mx205022 rw_enter(ngep->rwlock, RW_WRITER); 2594 5869 mx205022 2595 5869 mx205022 /* if the port hasn't been plumbed, just return */ 2596 5869 mx205022 if (ngep->nge_mac_state != NGE_MAC_STARTED) { 2597 5869 mx205022 rw_exit(ngep->rwlock); 2598 5869 mx205022 mutex_exit(ngep->genlock); 2599 5869 mx205022 return (DDI_SUCCESS); 2600 5869 mx205022 } 2601 5869 mx205022 ngep->suspended = B_TRUE; 2602 5869 mx205022 (void) nge_chip_stop(ngep, B_FALSE); 2603 5869 mx205022 ngep->nge_mac_state = NGE_MAC_STOPPED; 2604 5869 mx205022 2605 5869 mx205022 rw_exit(ngep->rwlock); 2606 5869 mx205022 mutex_exit(ngep->genlock); 2607 5869 mx205022 return (DDI_SUCCESS); 2608 5869 mx205022 } 2609 5869 mx205022 2610 5574 mx205022 /* 2611 5574 mx205022 * detach(9E) -- Detach a device from the system 2612 5574 mx205022 */ 2613 5574 mx205022 static int 2614 5574 mx205022 nge_detach(dev_info_t *devinfo, ddi_detach_cmd_t cmd) 2615 5574 mx205022 { 2616 5574 mx205022 int i; 2617 5574 mx205022 nge_t *ngep; 2618 5574 mx205022 mul_item *p, *nextp; 2619 5574 mx205022 buff_ring_t *brp; 2620 5574 mx205022 2621 5574 mx205022 NGE_GTRACE(("nge_detach($%p, %d)", (void *)devinfo, cmd)); 2622 5574 mx205022 2623 5574 mx205022 ngep = ddi_get_driver_private(devinfo); 2624 5574 mx205022 brp = ngep->buff; 2625 5574 mx205022 2626 5574 mx205022 switch (cmd) { 2627 5574 mx205022 default: 2628 5574 mx205022 return (DDI_FAILURE); 2629 5574 mx205022 2630 5574 mx205022 case DDI_SUSPEND: 2631 5574 mx205022 /* 2632 5574 mx205022 * Stop the NIC 2633 5574 mx205022 * Note: This driver doesn't currently support WOL, but 2634 5574 mx205022 * should it in the future, it is important to 2635 5574 mx205022 * make sure the PHY remains powered so that the 2636 5574 mx205022 * wakeup packet can actually be recieved. 2637 5574 mx205022 */ 2638 5869 mx205022 return (nge_suspend(ngep)); 2639 5574 mx205022 2640 5574 mx205022 case DDI_DETACH: 2641 5574 mx205022 break; 2642 5574 mx205022 } 2643 5574 mx205022 2644 5574 mx205022 /* Try to wait all the buffer post to upper layer be released */ 2645 5574 mx205022 for (i = 0; i < 1000; i++) { 2646 5574 mx205022 if (brp->rx_hold == 0) 2647 5574 mx205022 break; 2648 5574 mx205022 drv_usecwait(1000); 2649 5574 mx205022 } 2650 5574 mx205022 2651 5574 mx205022 /* If there is any posted buffer, reject to detach */ 2652 5574 mx205022 if (brp->rx_hold != 0) 2653 5574 mx205022 return (DDI_FAILURE); 2654 5574 mx205022 2655 5574 mx205022 /* 2656 5574 mx205022 * Unregister from the GLD subsystem. This can fail, in 2657 5574 mx205022 * particular if there are DLPI style-2 streams still open - 2658 5574 mx205022 * in which case we just return failure without shutting 2659 5574 mx205022 * down chip operations. 2660 5574 mx205022 */ 2661 5574 mx205022 if (mac_unregister(ngep->mh) != DDI_SUCCESS) 2662 5574 mx205022 return (DDI_FAILURE); 2663 6366 mx205022 2664 6366 mx205022 /* 2665 6366 mx205022 * Recycle the multicast table. mac_unregister() should be called 2666 6366 mx205022 * before it to ensure the multicast table can be used even if 2667 6366 mx205022 * mac_unregister() fails. 2668 6366 mx205022 */ 2669 6366 mx205022 for (p = ngep->pcur_mulist; p != NULL; p = nextp) { 2670 6366 mx205022 nextp = p->next; 2671 6366 mx205022 kmem_free(p, sizeof (mul_item)); 2672 6366 mx205022 } 2673 6366 mx205022 ngep->pcur_mulist = NULL; 2674 5574 mx205022 2675 5574 mx205022 /* 2676 5574 mx205022 * All activity stopped, so we can clean up & exit 2677 5574 mx205022 */ 2678 5574 mx205022 nge_unattach(ngep); 2679 5574 mx205022 return (DDI_SUCCESS); 2680 5574 mx205022 } 2681 5574 mx205022 2682 7656 Sherry /* 2683 7656 Sherry * quiesce(9E) entry point. 2684 7656 Sherry * 2685 7656 Sherry * This function is called when the system is single-threaded at high 2686 7656 Sherry * PIL with preemption disabled. Therefore, this function must not be 2687 7656 Sherry * blocked. 2688 7656 Sherry * 2689 7656 Sherry * This function returns DDI_SUCCESS on success, or DDI_FAILURE on failure. 2690 7656 Sherry * DDI_FAILURE indicates an error condition and should almost never happen. 2691 7656 Sherry */ 2692 7656 Sherry static int 2693 7656 Sherry nge_quiesce(dev_info_t *devinfo) 2694 7656 Sherry { 2695 7656 Sherry nge_t *ngep; 2696 7656 Sherry 2697 7656 Sherry ngep = ddi_get_driver_private(devinfo); 2698 7656 Sherry 2699 7656 Sherry if (ngep == NULL) 2700 7656 Sherry return (DDI_FAILURE); 2701 7656 Sherry 2702 7656 Sherry /* 2703 7656 Sherry * Turn off debug tracing 2704 7656 Sherry */ 2705 7656 Sherry nge_debug = 0; 2706 7656 Sherry ngep->debug = 0; 2707 7656 Sherry 2708 7656 Sherry nge_restore_mac_addr(ngep); 2709 7656 Sherry (void) nge_chip_stop(ngep, B_FALSE); 2710 7656 Sherry 2711 7656 Sherry return (DDI_SUCCESS); 2712 7656 Sherry } 2713 7656 Sherry 2714 7656 Sherry 2715 5574 mx205022 2716 5574 mx205022 /* 2717 5574 mx205022 * ========== Module Loading Data & Entry Points ========== 2718 5574 mx205022 */ 2719 5574 mx205022 2720 5574 mx205022 DDI_DEFINE_STREAM_OPS(nge_dev_ops, nulldev, nulldev, nge_attach, nge_detach, 2721 7656 Sherry NULL, NULL, D_MP, NULL, nge_quiesce); 2722 5574 mx205022 2723 5574 mx205022 2724 5574 mx205022 static struct modldrv nge_modldrv = { 2725 5574 mx205022 &mod_driverops, /* Type of module. This one is a driver */ 2726 5574 mx205022 nge_ident, /* short description */ 2727 5574 mx205022 &nge_dev_ops /* driver specific ops */ 2728 5574 mx205022 }; 2729 5574 mx205022 2730 5574 mx205022 static struct modlinkage modlinkage = { 2731 5574 mx205022 MODREV_1, (void *)&nge_modldrv, NULL 2732 5574 mx205022 }; 2733 5574 mx205022 2734 5574 mx205022 2735 5574 mx205022 int 2736 5574 mx205022 _info(struct modinfo *modinfop) 2737 5574 mx205022 { 2738 5574 mx205022 return (mod_info(&modlinkage, modinfop)); 2739 5574 mx205022 } 2740 5574 mx205022 2741 5574 mx205022 int 2742 5574 mx205022 _init(void) 2743 5574 mx205022 { 2744 5574 mx205022 int status; 2745 5574 mx205022 2746 5574 mx205022 mac_init_ops(&nge_dev_ops, "nge"); 2747 5574 mx205022 status = mod_install(&modlinkage); 2748 5574 mx205022 if (status != DDI_SUCCESS) 2749 5574 mx205022 mac_fini_ops(&nge_dev_ops); 2750 5574 mx205022 else 2751 5574 mx205022 mutex_init(nge_log_mutex, NULL, MUTEX_DRIVER, NULL); 2752 5574 mx205022 2753 5574 mx205022 return (status); 2754 5574 mx205022 } 2755 5574 mx205022 2756 5574 mx205022 int 2757 5574 mx205022 _fini(void) 2758 5574 mx205022 { 2759 5574 mx205022 int status; 2760 5574 mx205022 2761 5574 mx205022 status = mod_remove(&modlinkage); 2762 5574 mx205022 if (status == DDI_SUCCESS) { 2763 5574 mx205022 mac_fini_ops(&nge_dev_ops); 2764 5574 mx205022 mutex_destroy(nge_log_mutex); 2765 5574 mx205022 } 2766 5574 mx205022 2767 5574 mx205022 return (status); 2768 5574 mx205022 } 2769 5574 mx205022 2770 5574 mx205022 /* 2771 5574 mx205022 * ============ Init MSI/Fixed/SoftInterrupt routines ============== 2772 5574 mx205022 */ 2773 5574 mx205022 2774 5574 mx205022 /* 2775 5574 mx205022 * Register interrupts and initialize each mutex and condition variables 2776 5574 mx205022 */ 2777 5574 mx205022 2778 5574 mx205022 static int 2779 5574 mx205022 nge_register_intrs_and_init_locks(nge_t *ngep) 2780 5574 mx205022 { 2781 5574 mx205022 int err; 2782 5574 mx205022 int intr_types; 2783 5574 mx205022 uint_t soft_prip; 2784 5574 mx205022 nge_msi_mask msi_mask; 2785 5574 mx205022 nge_msi_map0_vec map0_vec; 2786 5574 mx205022 nge_msi_map1_vec map1_vec; 2787 5574 mx205022 2788 5574 mx205022 /* 2789 5574 mx205022 * Add the softint handlers: 2790 5574 mx205022 * 2791 5574 mx205022 * Both of these handlers are used to avoid restrictions on the 2792 5574 mx205022 * context and/or mutexes required for some operations. In 2793 5574 mx205022 * particular, the hardware interrupt handler and its subfunctions 2794 5574 mx205022 * can detect a number of conditions that we don't want to handle 2795 5574 mx205022 * in that context or with that set of mutexes held. So, these 2796 5574 mx205022 * softints are triggered instead: 2797 5574 mx205022 * 2798 5574 mx205022 * the <resched> softint is triggered if if we have previously 2799 5574 mx205022 * had to refuse to send a packet because of resource shortage 2800 5574 mx205022 * (we've run out of transmit buffers), but the send completion 2801 5574 mx205022 * interrupt handler has now detected that more buffers have 2802 5574 mx205022 * become available. Its only purpose is to call gld_sched() 2803 5574 mx205022 * to retry the pending transmits (we're not allowed to hold 2804 5574 mx205022 * driver-defined mutexes across gld_sched()). 2805 5574 mx205022 * 2806 5574 mx205022 * the <factotum> is triggered if the h/w interrupt handler 2807 5574 mx205022 * sees the <link state changed> or <error> bits in the status 2808 5574 mx205022 * block. It's also triggered periodically to poll the link 2809 5574 mx205022 * state, just in case we aren't getting link status change 2810 5574 mx205022 * interrupts ... 2811 5574 mx205022 */ 2812 5574 mx205022 err = ddi_intr_add_softint(ngep->devinfo, &ngep->resched_hdl, 2813 5574 mx205022 DDI_INTR_SOFTPRI_MIN, nge_reschedule, (caddr_t)ngep); 2814 5574 mx205022 if (err != DDI_SUCCESS) { 2815 5574 mx205022 nge_problem(ngep, 2816 5574 mx205022 "nge_attach: add nge_reschedule softintr failed"); 2817 5574 mx205022 2818 5574 mx205022 return (DDI_FAILURE); 2819 5574 mx205022 } 2820 5574 mx205022 ngep->progress |= PROGRESS_RESCHED; 2821 5574 mx205022 err = ddi_intr_add_softint(ngep->devinfo, &ngep->factotum_hdl, 2822 5574 mx205022 DDI_INTR_SOFTPRI_MIN, nge_chip_factotum, (caddr_t)ngep); 2823 5574 mx205022 if (err != DDI_SUCCESS) { 2824 5574 mx205022 nge_problem(ngep, 2825 5574 mx205022 "nge_attach: add nge_chip_factotum softintr failed!"); 2826 5574 mx205022 2827 5574 mx205022 return (DDI_FAILURE); 2828 5574 mx205022 } 2829 5574 mx205022 if (ddi_intr_get_softint_pri(ngep->factotum_hdl, &soft_prip) 2830 5574 mx205022 != DDI_SUCCESS) { 2831 5574 mx205022 nge_problem(ngep, "nge_attach: get softintr priority failed\n"); 2832 5574 mx205022 2833 5574 mx205022 return (DDI_FAILURE); 2834 5574 mx205022 } 2835 5574 mx205022 ngep->soft_pri = soft_prip; 2836 5574 mx205022 2837 5574 mx205022 ngep->progress |= PROGRESS_FACTOTUM; 2838 5574 mx205022 /* Get supported interrupt types */ 2839 5574 mx205022 if (ddi_intr_get_supported_types(ngep->devinfo, &intr_types) 2840 5574 mx205022 != DDI_SUCCESS) { 2841 5574 mx205022 nge_error(ngep, "ddi_intr_get_supported_types failed\n"); 2842 5574 mx205022 2843 5574 mx205022 return (DDI_FAILURE); 2844 5574 mx205022 } 2845 5574 mx205022 2846 5574 mx205022 NGE_DEBUG(("ddi_intr_get_supported_types() returned: %x", 2847 5574 mx205022 intr_types)); 2848 5574 mx205022 2849 5574 mx205022 if ((intr_types & DDI_INTR_TYPE_MSI) && nge_enable_msi) { 2850 5574 mx205022 2851 5574 mx205022 /* MSI Configurations for mcp55 chipset */ 2852 5574 mx205022 if (ngep->chipinfo.device == DEVICE_ID_MCP55_373 || 2853 5574 mx205022 ngep->chipinfo.device == DEVICE_ID_MCP55_372) { 2854 5574 mx205022 2855 5574 mx205022 2856 5574 mx205022 /* Enable the 8 vectors */ 2857 5574 mx205022 msi_mask.msi_mask_val = 2858 5574 mx205022 nge_reg_get32(ngep, NGE_MSI_MASK); 2859 5574 mx205022 msi_mask.msi_msk_bits.vec0 = NGE_SET; 2860 5574 mx205022 msi_mask.msi_msk_bits.vec1 = NGE_SET; 2861 5574 mx205022 msi_mask.msi_msk_bits.vec2 = NGE_SET; 2862 5574 mx205022 msi_mask.msi_msk_bits.vec3 = NGE_SET; 2863 5574 mx205022 msi_mask.msi_msk_bits.vec4 = NGE_SET; 2864 5574 mx205022 msi_mask.msi_msk_bits.vec5 = NGE_SET; 2865 5574 mx205022 msi_mask.msi_msk_bits.vec6 = NGE_SET; 2866 5574 mx205022 msi_mask.msi_msk_bits.vec7 = NGE_SET; 2867 5574 mx205022 nge_reg_put32(ngep, NGE_MSI_MASK, 2868 5574 mx205022 msi_mask.msi_mask_val); 2869 5574 mx205022 2870 5574 mx205022 /* 2871 5574 mx205022 * Remapping the MSI MAP0 and MAP1. MCP55 2872 5574 mx205022 * is default mapping all the interrupt to 0 vector. 2873 5574 mx205022 * Software needs to remapping this. 2874 5574 mx205022 * This mapping is same as CK804. 2875 5574 mx205022 */ 2876 5574 mx205022 map0_vec.msi_map0_val = 2877 5574 mx205022 nge_reg_get32(ngep, NGE_MSI_MAP0); 2878 5574 mx205022 map1_vec.msi_map1_val = 2879 5574 mx205022 nge_reg_get32(ngep, NGE_MSI_MAP1); 2880 5574 mx205022 map0_vec.vecs_bits.reint_vec = 0; 2881 5574 mx205022 map0_vec.vecs_bits.rcint_vec = 0; 2882 5574 mx205022 map0_vec.vecs_bits.miss_vec = 3; 2883 5574 mx205022 map0_vec.vecs_bits.teint_vec = 5; 2884 5574 mx205022 map0_vec.vecs_bits.tcint_vec = 5; 2885 5574 mx205022 map0_vec.vecs_bits.stint_vec = 2; 2886 5574 mx205022 map0_vec.vecs_bits.mint_vec = 6; 2887 5574 mx205022 map0_vec.vecs_bits.rfint_vec = 0; 2888 5574 mx205022 map1_vec.vecs_bits.tfint_vec = 5; 2889 5574 mx205022 map1_vec.vecs_bits.feint_vec = 6; 2890 5574 mx205022 map1_vec.vecs_bits.resv8_11 = 3; 2891 5574 mx205022 map1_vec.vecs_bits.resv12_15 = 1; 2892 5574 mx205022 map1_vec.vecs_bits.resv16_19 = 0; 2893 5574 mx205022 map1_vec.vecs_bits.resv20_23 = 7; 2894 5574 mx205022 map1_vec.vecs_bits.resv24_31 = 0xff; 2895 5574 mx205022 nge_reg_put32(ngep, NGE_MSI_MAP0, 2896 5574 mx205022 map0_vec.msi_map0_val); 2897 5574 mx205022 nge_reg_put32(ngep, NGE_MSI_MAP1, 2898 5574 mx205022 map1_vec.msi_map1_val); 2899 5574 mx205022 } 2900 5574 mx205022 if (nge_add_intrs(ngep, DDI_INTR_TYPE_MSI) != DDI_SUCCESS) { 2901 5574 mx205022 NGE_DEBUG(("MSI registration failed, " 2902 5574 mx205022 "trying FIXED interrupt type\n")); 2903 5574 mx205022 } else { 2904 5574 mx205022 nge_log(ngep, "Using MSI interrupt type\n"); 2905 5574 mx205022 2906 5574 mx205022 ngep->intr_type = DDI_INTR_TYPE_MSI; 2907 5574 mx205022 ngep->progress |= PROGRESS_SWINT; 2908 5574 mx205022 } 2909 5574 mx205022 } 2910 5574 mx205022 2911 5574 mx205022 if (!(ngep->progress & PROGRESS_SWINT) && 2912 5574 mx205022 (intr_types & DDI_INTR_TYPE_FIXED)) { 2913 5574 mx205022 if (nge_add_intrs(ngep, DDI_INTR_TYPE_FIXED) != DDI_SUCCESS) { 2914 5574 mx205022 nge_error(ngep, "FIXED interrupt " 2915 5574 mx205022 "registration failed\n"); 2916 5574 mx205022 2917 5574 mx205022 return (DDI_FAILURE); 2918 5574 mx205022 } 2919 5574 mx205022 2920 5574 mx205022 nge_log(ngep, "Using FIXED interrupt type\n"); 2921 5574 mx205022 2922 5574 mx205022 ngep->intr_type = DDI_INTR_TYPE_FIXED; 2923 5574 mx205022 ngep->progress |= PROGRESS_SWINT; 2924 5574 mx205022 } 2925 5574 mx205022 2926 5574 mx205022 2927 5574 mx205022 if (!(ngep->progress & PROGRESS_SWINT)) { 2928 5574 mx205022 nge_error(ngep, "No interrupts registered\n"); 2929 5574 mx205022 2930 5574 mx205022 return (DDI_FAILURE); 2931 5574 mx205022 } 2932 5574 mx205022 mutex_init(ngep->genlock, NULL, MUTEX_DRIVER, 2933 5574 mx205022 DDI_INTR_PRI(ngep->intr_pri)); 2934 5574 mx205022 mutex_init(ngep->softlock, NULL, MUTEX_DRIVER, 2935 5574 mx205022 DDI_INTR_PRI(ngep->soft_pri)); 2936 5574 mx205022 rw_init(ngep->rwlock, NULL, RW_DRIVER, 2937 5574 mx205022 DDI_INTR_PRI(ngep->intr_pri)); 2938 5574 mx205022 2939 5574 mx205022 return (DDI_SUCCESS); 2940 5574 mx205022 } 2941 5574 mx205022 2942 5574 mx205022 /* 2943 5574 mx205022 * nge_add_intrs: 2944 5574 mx205022 * 2945 5574 mx205022 * Register FIXED or MSI interrupts. 2946 5574 mx205022 */ 2947 5574 mx205022 static int 2948 5574 mx205022 nge_add_intrs(nge_t *ngep, int intr_type) 2949 5574 mx205022 { 2950 5574 mx205022 dev_info_t *dip = ngep->devinfo; 2951 5574 mx205022 int avail, actual, intr_size, count = 0; 2952 5574 mx205022 int i, flag, ret; 2953 5574 mx205022 2954 5574 mx205022 NGE_DEBUG(("nge_add_intrs: interrupt type 0x%x\n", intr_type)); 2955 5574 mx205022 2956 5574 mx205022 /* Get number of interrupts */ 2957 5574 mx205022 ret = ddi_intr_get_nintrs(dip, intr_type, &count); 2958 5574 mx205022 if ((ret != DDI_SUCCESS) || (count == 0)) { 2959 5574 mx205022 nge_error(ngep, "ddi_intr_get_nintrs() failure, ret: %d, " 2960 5574 mx205022 "count: %d", ret, count); 2961 5574 mx205022 2962 5574 mx205022 return (DDI_FAILURE); 2963 5574 mx205022 } 2964 5574 mx205022 2965 5574 mx205022 /* Get number of available interrupts */ 2966 5574 mx205022 ret = ddi_intr_get_navail(dip, intr_type, &avail); 2967 5574 mx205022 if ((ret != DDI_SUCCESS) || (avail == 0)) { 2968 5574 mx205022 nge_error(ngep, "ddi_intr_get_navail() failure, " 2969 5574 mx205022 "ret: %d, avail: %d\n", ret, avail); 2970 5574 mx205022 2971 5574 mx205022 return (DDI_FAILURE); 2972 5574 mx205022 } 2973 5574 mx205022 2974 5574 mx205022 if (avail < count) { 2975 5574 mx205022 NGE_DEBUG(("nitrs() returned %d, navail returned %d\n", 2976 5574 mx205022 count, avail)); 2977 5574 mx205022 } 2978 5574 mx205022 flag = DDI_INTR_ALLOC_NORMAL; 2979 5574 mx205022 2980 5574 mx205022 /* Allocate an array of interrupt handles */ 2981 5574 mx205022 intr_size = count * sizeof (ddi_intr_handle_t); 2982 5574 mx205022 ngep->htable = kmem_alloc(intr_size, KM_SLEEP); 2983 5574 mx205022 2984 5574 mx205022 /* Call ddi_intr_alloc() */ 2985 5574 mx205022 ret = ddi_intr_alloc(dip, ngep->htable, intr_type, 0, 2986 5574 mx205022 count, &actual, flag); 2987 5574 mx205022 2988 5574 mx205022 if ((ret != DDI_SUCCESS) || (actual == 0)) { 2989 5574 mx205022 nge_error(ngep, "ddi_intr_alloc() failed %d\n", ret); 2990 5574 mx205022 2991 5574 mx205022 kmem_free(ngep->htable, intr_size); 2992 5574 mx205022 return (DDI_FAILURE); 2993 5574 mx205022 } 2994 5574 mx205022 2995 5574 mx205022 if (actual < count) { 2996 5574