1 /* 2 * This file and its contents are supplied under the terms of the 3 * Common Development and Distribution License ("CDDL"), version 1.0. 4 * You may only use this file in accordance with the terms of version 5 * 1.0 of the CDDL. 6 * 7 * A full copy of the text of the CDDL should have accompanied this 8 * source. A copy of the CDDL is also available via the Internet at 9 * http://www.illumos.org/license/CDDL. 10 */ 11 12 /* 13 * Copyright 2024 Oxide Computer Company 14 */ 15 16 /* 17 * Intel I225/226 Ethernet Driver. This is the same MAC that is found in the 18 * e1000 and igb drivers, but Intel decided it would be a different driver and 19 * so here we are. 20 */ 21 22 #include <sys/sysmacros.h> 23 24 #include "igc.h" 25 26 typedef struct { 27 enum igc_media_type imm_phy; 28 uint16_t imm_speed; 29 mac_ether_media_t imm_media; 30 } igc_media_map_t; 31 32 static const igc_media_map_t igc_media_map[] = { 33 { igc_media_type_copper, SPEED_10, ETHER_MEDIA_10BASE_T }, 34 { igc_media_type_copper, SPEED_100, ETHER_MEDIA_100BASE_TX }, 35 { igc_media_type_copper, SPEED_1000, ETHER_MEDIA_1000BASE_T }, 36 { igc_media_type_copper, SPEED_2500, ETHER_MEDIA_2500BASE_T }, 37 }; 38 39 static mac_ether_media_t 40 igc_link_to_media(igc_t *igc) 41 { 42 switch (igc->igc_link_state) { 43 case LINK_STATE_UP: 44 break; 45 case LINK_STATE_DOWN: 46 return (ETHER_MEDIA_NONE); 47 default: 48 return (ETHER_MEDIA_UNKNOWN); 49 } 50 51 for (size_t i = 0; i < ARRAY_SIZE(igc_media_map); i++) { 52 const igc_media_map_t *map = &igc_media_map[i]; 53 if (igc->igc_hw.phy.media_type == map->imm_phy && 54 igc->igc_link_speed == map->imm_speed) { 55 return (map->imm_media); 56 } 57 } 58 59 return (ETHER_MEDIA_UNKNOWN); 60 } 61 62 /* 63 * The following stats are skipped because there is no good way to get it from 64 * hardware or we don't know how to perform such a mapping: 65 * 66 * - MAC_STAT_UNKNOWNS 67 * - MAC_STAT_UNDERFLOWS 68 * - MAC_STAT_OVERFLOWS 69 * - ETHER_STAT_SQE_ERRORS 70 * - ETHER_STAT_MACRCV_ERRORS 71 */ 72 static int 73 igc_m_getstat(void *drv, uint_t stat, uint64_t *valp) 74 { 75 igc_t *igc = drv; 76 igc_stats_t *stats = &igc->igc_stats; 77 int ret = 0; 78 uint32_t an_adv; 79 80 mutex_enter(&igc->igc_lock); 81 an_adv = igc->igc_hw.phy.autoneg_advertised; 82 83 switch (stat) { 84 /* MIB-II stats (RFC 1213 and RFC 1573) */ 85 case MAC_STAT_IFSPEED: 86 *valp = (uint64_t)igc->igc_link_speed * 1000000; 87 break; 88 case MAC_STAT_MULTIRCV: 89 stats->is_mprc.value.ui64 += igc_read32(igc, IGC_MPRC); 90 *valp = stats->is_mprc.value.ui64; 91 break; 92 case MAC_STAT_BRDCSTRCV: 93 stats->is_bprc.value.ui64 += igc_read32(igc, IGC_BPRC); 94 *valp = stats->is_bprc.value.ui64; 95 break; 96 case MAC_STAT_MULTIXMT: 97 stats->is_mptc.value.ui64 += igc_read32(igc, IGC_MPTC); 98 *valp = stats->is_mptc.value.ui64; 99 break; 100 case MAC_STAT_BRDCSTXMT: 101 stats->is_bptc.value.ui64 += igc_read32(igc, IGC_BPTC); 102 *valp = stats->is_bptc.value.ui64; 103 break; 104 case MAC_STAT_NORCVBUF: 105 stats->is_rnbc.value.ui64 += igc_read32(igc, IGC_RNBC); 106 *valp = stats->is_rnbc.value.ui64; 107 break; 108 case MAC_STAT_IERRORS: 109 stats->is_crcerrs.value.ui64 += igc_read32(igc, IGC_CRCERRS); 110 stats->is_rlec.value.ui64 += igc_read32(igc, IGC_RLEC); 111 stats->is_algnerrc.value.ui64 += igc_read32(igc, IGC_ALGNERRC); 112 113 *valp = stats->is_crcerrs.value.ui64 + 114 stats->is_rlec.value.ui64 + stats->is_algnerrc.value.ui64; 115 break; 116 case MAC_STAT_OERRORS: 117 stats->is_ecol.value.ui64 += igc_read32(igc, IGC_ECOL); 118 stats->is_latecol.value.ui64 += igc_read32(igc, IGC_LATECOL); 119 120 *valp = stats->is_ecol.value.ui64 + 121 stats->is_latecol.value.ui64; 122 break; 123 case MAC_STAT_COLLISIONS: 124 stats->is_colc.value.ui64 += igc_read32(igc, IGC_COLC); 125 *valp = stats->is_colc.value.ui64; 126 break; 127 case MAC_STAT_RBYTES: 128 igc_stats_update_u64(igc, &stats->is_tor, IGC_TORL); 129 *valp = stats->is_tor.value.ui64; 130 break; 131 case MAC_STAT_IPACKETS: 132 stats->is_tpr.value.ui64 += igc_read32(igc, IGC_TPR); 133 *valp = stats->is_tpr.value.ui64; 134 break; 135 case MAC_STAT_OBYTES: 136 igc_stats_update_u64(igc, &stats->is_tor, IGC_TOTL); 137 *valp = stats->is_tot.value.ui64; 138 break; 139 case MAC_STAT_OPACKETS: 140 stats->is_tpt.value.ui64 += igc_read32(igc, IGC_TPT); 141 *valp = stats->is_tpt.value.ui64; 142 break; 143 case MAC_STAT_UNDERFLOWS: 144 stats->is_ruc.value.ui64 += igc_read32(igc, IGC_RUC); 145 *valp = stats->is_ruc.value.ui64; 146 break; 147 case MAC_STAT_OVERFLOWS: 148 stats->is_roc.value.ui64 += igc_read32(igc, IGC_ROC); 149 *valp = stats->is_roc.value.ui64; 150 break; 151 /* RFC 1643 stats */ 152 case ETHER_STAT_ALIGN_ERRORS: 153 stats->is_algnerrc.value.ui64 += igc_read32(igc, IGC_ALGNERRC); 154 *valp = stats->is_algnerrc.value.ui64; 155 break; 156 case ETHER_STAT_FCS_ERRORS: 157 stats->is_crcerrs.value.ui64 += igc_read32(igc, IGC_CRCERRS); 158 *valp = stats->is_crcerrs.value.ui64; 159 break; 160 case ETHER_STAT_FIRST_COLLISIONS: 161 stats->is_scc.value.ui64 += igc_read32(igc, IGC_SCC); 162 *valp = stats->is_scc.value.ui64; 163 break; 164 case ETHER_STAT_MULTI_COLLISIONS: 165 stats->is_mcc.value.ui64 += igc_read32(igc, IGC_MCC); 166 *valp = stats->is_mcc.value.ui64; 167 break; 168 case ETHER_STAT_DEFER_XMTS: 169 stats->is_dc.value.ui64 += igc_read32(igc, IGC_DC); 170 *valp = stats->is_dc.value.ui64; 171 break; 172 case ETHER_STAT_TX_LATE_COLLISIONS: 173 stats->is_latecol.value.ui64 += igc_read32(igc, IGC_LATECOL); 174 *valp = stats->is_latecol.value.ui64; 175 break; 176 case ETHER_STAT_EX_COLLISIONS: 177 stats->is_ecol.value.ui64 += igc_read32(igc, IGC_ECOL); 178 *valp = stats->is_ecol.value.ui64; 179 break; 180 case ETHER_STAT_MACXMT_ERRORS: 181 stats->is_ecol.value.ui64 += igc_read32(igc, IGC_ECOL); 182 *valp = stats->is_ecol.value.ui64; 183 break; 184 case ETHER_STAT_CARRIER_ERRORS: 185 stats->is_htdpmc.value.ui64 += igc_read32(igc, IGC_HTDPMC); 186 *valp = stats->is_htdpmc.value.ui64; 187 break; 188 case ETHER_STAT_TOOLONG_ERRORS: 189 stats->is_roc.value.ui64 += igc_read32(igc, IGC_ROC); 190 *valp = stats->is_roc.value.ui64; 191 break; 192 /* MII/GMII stats */ 193 case ETHER_STAT_XCVR_ADDR: 194 *valp = igc->igc_hw.phy.addr; 195 break; 196 case ETHER_STAT_XCVR_ID: 197 *valp = igc->igc_hw.phy.id | igc->igc_hw.phy.revision; 198 break; 199 case ETHER_STAT_XCVR_INUSE: 200 *valp = igc_link_to_media(igc); 201 break; 202 case ETHER_STAT_CAP_2500FDX: 203 case ETHER_STAT_CAP_1000FDX: 204 case ETHER_STAT_CAP_100FDX: 205 case ETHER_STAT_CAP_100HDX: 206 case ETHER_STAT_CAP_10FDX: 207 case ETHER_STAT_CAP_10HDX: 208 case ETHER_STAT_CAP_ASMPAUSE: 209 case ETHER_STAT_CAP_PAUSE: 210 case ETHER_STAT_CAP_AUTONEG: 211 /* 212 * These are all about what the device is capable of and every 213 * device is capable of this that we support right now. 214 */ 215 *valp = 1; 216 break; 217 case ETHER_STAT_ADV_CAP_2500FDX: 218 *valp = (an_adv & ADVERTISE_2500_FULL) != 0; 219 break; 220 case ETHER_STAT_ADV_CAP_1000FDX: 221 *valp = (an_adv & ADVERTISE_1000_FULL) != 0; 222 break; 223 case ETHER_STAT_ADV_CAP_100FDX: 224 *valp = (an_adv & ADVERTISE_100_FULL) != 0; 225 break; 226 case ETHER_STAT_ADV_CAP_100HDX: 227 *valp = (an_adv & ADVERTISE_100_HALF) != 0; 228 break; 229 case ETHER_STAT_ADV_CAP_10FDX: 230 *valp = (an_adv & ADVERTISE_10_FULL) != 0; 231 break; 232 case ETHER_STAT_ADV_CAP_10HDX: 233 *valp = (an_adv & ADVERTISE_10_HALF) != 0; 234 break; 235 case ETHER_STAT_ADV_CAP_ASMPAUSE: 236 *valp = (igc->igc_phy_an_adv & NWAY_AR_ASM_DIR) != 0; 237 break; 238 case ETHER_STAT_ADV_CAP_PAUSE: 239 *valp = (igc->igc_phy_an_adv & NWAY_AR_PAUSE) != 0; 240 break; 241 case ETHER_STAT_ADV_CAP_AUTONEG: 242 *valp = igc->igc_hw.mac.autoneg; 243 break; 244 case ETHER_STAT_LP_CAP_2500FDX: 245 *valp = (igc->igc_phy_mmd_sts & MMD_AN_STS1_LP_2P5T_CAP) != 0; 246 break; 247 case ETHER_STAT_LP_CAP_1000FDX: 248 *valp = (igc->igc_phy_1000t_status & SR_1000T_LP_FD_CAPS) != 0; 249 break; 250 case ETHER_STAT_LP_CAP_100FDX: 251 *valp = (igc->igc_phy_lp & NWAY_LPAR_100TX_FD_CAPS) != 0; 252 break; 253 case ETHER_STAT_LP_CAP_100HDX: 254 *valp = (igc->igc_phy_lp & NWAY_LPAR_100TX_HD_CAPS) != 0; 255 break; 256 case ETHER_STAT_LP_CAP_10FDX: 257 *valp = (igc->igc_phy_lp & NWAY_LPAR_10T_FD_CAPS) != 0; 258 break; 259 case ETHER_STAT_LP_CAP_10HDX: 260 *valp = (igc->igc_phy_lp & NWAY_LPAR_10T_HD_CAPS) != 0; 261 break; 262 case ETHER_STAT_LP_CAP_ASMPAUSE: 263 *valp = (igc->igc_phy_lp & NWAY_AR_ASM_DIR) != 0; 264 break; 265 case ETHER_STAT_LP_CAP_PAUSE: 266 *valp = (igc->igc_phy_lp & NWAY_LPAR_PAUSE) != 0; 267 break; 268 case ETHER_STAT_LP_CAP_AUTONEG: 269 *valp = (igc->igc_phy_ext_status & NWAY_ER_LP_NWAY_CAPS) != 0; 270 break; 271 case ETHER_STAT_LINK_ASMPAUSE: 272 *valp = (igc->igc_hw.fc.current_mode == igc_fc_full || 273 igc->igc_hw.fc.current_mode == igc_fc_rx_pause); 274 break; 275 case ETHER_STAT_LINK_PAUSE: 276 *valp = (igc->igc_hw.fc.current_mode == igc_fc_full || 277 igc->igc_hw.fc.current_mode == igc_fc_tx_pause); 278 break; 279 case ETHER_STAT_LINK_AUTONEG: 280 *valp = igc->igc_hw.mac.autoneg; 281 break; 282 case ETHER_STAT_LINK_DUPLEX: 283 *valp = igc->igc_link_duplex; 284 break; 285 case ETHER_STAT_CAP_REMFAULT: 286 *valp = 1; 287 break; 288 case ETHER_STAT_ADV_REMFAULT: 289 *valp = (igc->igc_phy_an_adv & NWAY_AR_REMOTE_FAULT) != 0; 290 break; 291 case ETHER_STAT_LP_REMFAULT: 292 *valp = (igc->igc_phy_lp & NWAY_LPAR_REMOTE_FAULT) != 0; 293 break; 294 295 case ETHER_STAT_TOOSHORT_ERRORS: 296 stats->is_ruc.value.ui64 += igc_read32(igc, IGC_RUC); 297 *valp = stats->is_ruc.value.ui64; 298 break; 299 300 case ETHER_STAT_JABBER_ERRORS: 301 stats->is_rjc.value.ui64 += igc_read32(igc, IGC_RJC); 302 *valp = stats->is_rjc.value.ui64; 303 break; 304 305 /* 306 * Unsupported speeds. 307 */ 308 case ETHER_STAT_CAP_100T4: 309 case ETHER_STAT_CAP_1000HDX: 310 case ETHER_STAT_CAP_10GFDX: 311 case ETHER_STAT_CAP_40GFDX: 312 case ETHER_STAT_CAP_100GFDX: 313 case ETHER_STAT_CAP_5000FDX: 314 case ETHER_STAT_CAP_25GFDX: 315 case ETHER_STAT_CAP_50GFDX: 316 case ETHER_STAT_CAP_200GFDX: 317 case ETHER_STAT_CAP_400GFDX: 318 case ETHER_STAT_ADV_CAP_100T4: 319 case ETHER_STAT_ADV_CAP_1000HDX: 320 case ETHER_STAT_ADV_CAP_10GFDX: 321 case ETHER_STAT_ADV_CAP_40GFDX: 322 case ETHER_STAT_ADV_CAP_100GFDX: 323 case ETHER_STAT_ADV_CAP_5000FDX: 324 case ETHER_STAT_ADV_CAP_25GFDX: 325 case ETHER_STAT_ADV_CAP_50GFDX: 326 case ETHER_STAT_ADV_CAP_200GFDX: 327 case ETHER_STAT_ADV_CAP_400GFDX: 328 *valp = 0; 329 break; 330 331 /* 332 * These are values that aren't supported by igc(4D); however, some of 333 * the MII registers can be used to answer this based on the 334 * MultiGBASE-T spec (and others). 335 */ 336 case ETHER_STAT_LP_CAP_1000HDX: 337 *valp = (igc->igc_phy_1000t_status & SR_1000T_LP_HD_CAPS) != 0; 338 break; 339 case ETHER_STAT_LP_CAP_100T4: 340 *valp = (igc->igc_phy_lp & NWAY_LPAR_100T4_CAPS) != 0; 341 break; 342 case ETHER_STAT_LP_CAP_10GFDX: 343 *valp = (igc->igc_phy_mmd_sts & MMD_AN_STS1_LP_10T_CAP) != 0; 344 break; 345 case ETHER_STAT_LP_CAP_40GFDX: 346 *valp = (igc->igc_phy_mmd_sts & MMD_AN_STS1_LP_40T_CAP) != 0; 347 break; 348 case ETHER_STAT_LP_CAP_5000FDX: 349 *valp = (igc->igc_phy_mmd_sts & MMD_AN_STS1_LP_5T_CAP) != 0; 350 break; 351 case ETHER_STAT_LP_CAP_25GFDX: 352 *valp = (igc->igc_phy_mmd_sts & MMD_AN_STS1_LP_25T_CAP) != 0; 353 break; 354 case ETHER_STAT_LP_CAP_50GFDX: 355 case ETHER_STAT_LP_CAP_100GFDX: 356 case ETHER_STAT_LP_CAP_200GFDX: 357 case ETHER_STAT_LP_CAP_400GFDX: 358 *valp = 0; 359 break; 360 default: 361 ret = ENOTSUP; 362 } 363 mutex_exit(&igc->igc_lock); 364 365 return (ret); 366 } 367 368 static void 369 igc_m_stop(void *drv) 370 { 371 igc_t *igc = drv; 372 373 igc_hw_intr_disable(igc); 374 (void) igc_reset_hw(&igc->igc_hw); 375 igc_rx_drain(igc); 376 igc_rx_data_free(igc); 377 igc_tx_data_free(igc); 378 379 /* 380 * Now that we're fully stopped, remove all of our state tracking. 381 */ 382 mutex_enter(&igc->igc_lock); 383 igc->igc_attach &= ~IGC_ATTACH_TX_DATA; 384 igc->igc_attach &= ~IGC_ATTACH_RX_DATA; 385 igc->igc_attach &= ~IGC_ATTACH_MAC_START; 386 mutex_exit(&igc->igc_lock); 387 } 388 389 static int 390 igc_m_start(void *drv) 391 { 392 int ret; 393 igc_t *igc = drv; 394 395 mutex_enter(&igc->igc_lock); 396 igc->igc_attach |= IGC_ATTACH_MAC_START; 397 mutex_exit(&igc->igc_lock); 398 399 /* 400 * Ensure that the phy is powerd on. 401 */ 402 igc_power_up_phy(&igc->igc_hw); 403 404 if (!igc_rx_data_alloc(igc)) { 405 ret = ENOMEM; 406 goto cleanup; 407 } 408 mutex_enter(&igc->igc_lock); 409 igc->igc_attach |= IGC_ATTACH_RX_DATA; 410 mutex_exit(&igc->igc_lock); 411 412 if (!igc_tx_data_alloc(igc)) { 413 ret = ENOMEM; 414 goto cleanup; 415 } 416 mutex_enter(&igc->igc_lock); 417 igc->igc_attach |= IGC_ATTACH_TX_DATA; 418 mutex_exit(&igc->igc_lock); 419 420 if (!igc_hw_common_init(igc)) { 421 ret = EIO; 422 goto cleanup; 423 } 424 425 /* 426 * The above hardware reset ensures that the latest requested link 427 * properties are set and that the packet sizes and related are 428 * programmed. Now we must go through and program the ring information 429 * into the hardware and enable interrupts. Once that's done we're good 430 * to go. 431 */ 432 igc_rx_hw_init(igc); 433 igc_tx_hw_init(igc); 434 igc_hw_intr_enable(igc); 435 436 return (0); 437 438 cleanup: 439 mutex_enter(&igc->igc_lock); 440 if ((igc->igc_attach & IGC_ATTACH_TX_DATA) != 0) { 441 igc_tx_data_free(igc); 442 igc->igc_attach &= ~IGC_ATTACH_TX_DATA; 443 } 444 445 if ((igc->igc_attach & IGC_ATTACH_RX_DATA) != 0) { 446 igc_rx_data_free(igc); 447 igc->igc_attach &= ~IGC_ATTACH_RX_DATA; 448 } 449 450 igc->igc_attach &= ~IGC_ATTACH_MAC_START; 451 mutex_exit(&igc->igc_lock); 452 453 return (ret); 454 } 455 456 static int 457 igc_m_setpromisc(void *drv, boolean_t en) 458 { 459 igc_t *igc = drv; 460 uint32_t reg; 461 462 mutex_enter(&igc->igc_lock); 463 464 reg = igc_read32(igc, IGC_RCTL); 465 if (en) { 466 reg |= IGC_RCTL_UPE | IGC_RCTL_MPE; 467 igc->igc_promisc = true; 468 } else { 469 reg &= ~(IGC_RCTL_UPE | IGC_RCTL_MPE); 470 igc->igc_promisc = false; 471 } 472 igc_write32(igc, IGC_RCTL, reg); 473 mutex_exit(&igc->igc_lock); 474 475 return (0); 476 } 477 478 static int 479 igc_m_multicast(void *drv, boolean_t add, const uint8_t *mac) 480 { 481 int ret = 0; 482 igc_t *igc = drv; 483 484 if ((mac[0] & 0x01) == 0) { 485 return (EINVAL); 486 } 487 488 mutex_enter(&igc->igc_lock); 489 if (add) { 490 bool space = false; 491 492 for (uint16_t i = 0; i < igc->igc_nmcast; i++) { 493 if (igc->igc_mcast[i].ia_valid) 494 continue; 495 496 bcopy(mac, igc->igc_mcast[i].ia_mac, ETHERADDRL); 497 igc->igc_mcast[i].ia_valid = true; 498 space = true; 499 break; 500 } 501 502 if (!space) { 503 ret = ENOSPC; 504 } 505 } else { 506 bool found = false; 507 508 for (uint16_t i = 0; i < igc->igc_nmcast; i++) { 509 if (!igc->igc_mcast[i].ia_valid || bcmp(mac, 510 igc->igc_mcast[i].ia_mac, ETHERADDRL) != 0) { 511 continue; 512 } 513 514 bzero(igc->igc_mcast[i].ia_mac, ETHERADDRL); 515 igc->igc_mcast[i].ia_valid = false; 516 found = true; 517 break; 518 } 519 520 if (!found) { 521 ret = ENOENT; 522 } 523 } 524 igc_multicast_sync(igc); 525 mutex_exit(&igc->igc_lock); 526 527 return (ret); 528 } 529 530 static int 531 igc_group_add_mac(void *gr_drv, const uint8_t *mac) 532 { 533 igc_t *igc = gr_drv; 534 535 ASSERT3U(mac[0] & 0x01, ==, 0); 536 537 mutex_enter(&igc->igc_lock); 538 for (uint16_t i = 0; i < igc->igc_nucast; i++) { 539 int ret; 540 541 if (igc->igc_ucast[i].ia_valid) 542 continue; 543 544 bcopy(mac, igc->igc_ucast[i].ia_mac, ETHERADDRL); 545 igc->igc_ucast[i].ia_valid = true; 546 ret = igc_rar_set(&igc->igc_hw, igc->igc_ucast[i].ia_mac, i); 547 VERIFY3S(ret, ==, IGC_SUCCESS); 548 mutex_exit(&igc->igc_lock); 549 return (0); 550 } 551 mutex_exit(&igc->igc_lock); 552 553 return (ENOSPC); 554 } 555 556 static int 557 igc_group_rem_mac(void *gr_drv, const uint8_t *mac) 558 { 559 igc_t *igc = gr_drv; 560 561 ASSERT3U(mac[0] & 0x01, ==, 0); 562 563 mutex_enter(&igc->igc_lock); 564 for (uint16_t i = 0; i < igc->igc_nucast; i++) { 565 int ret; 566 567 if (!igc->igc_ucast[i].ia_valid || bcmp(mac, 568 igc->igc_ucast[i].ia_mac, ETHERADDRL) != 0) { 569 continue; 570 } 571 572 bzero(igc->igc_ucast[i].ia_mac, ETHERADDRL); 573 igc->igc_ucast[i].ia_valid = false; 574 ret = igc_rar_set(&igc->igc_hw, igc->igc_ucast[i].ia_mac, i); 575 VERIFY3S(ret, ==, IGC_SUCCESS); 576 mutex_exit(&igc->igc_lock); 577 return (0); 578 } 579 mutex_exit(&igc->igc_lock); 580 581 return (ENOENT); 582 } 583 584 int 585 igc_tx_ring_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val) 586 { 587 igc_tx_ring_t *tx_ring = (igc_tx_ring_t *)rh; 588 589 switch (stat) { 590 case MAC_STAT_OBYTES: 591 *val = tx_ring->itr_stat.its_obytes.value.ui64; 592 break; 593 case MAC_STAT_OPACKETS: 594 *val = tx_ring->itr_stat.its_opackets.value.ui64; 595 break; 596 default: 597 *val = 0; 598 return (ENOTSUP); 599 } 600 601 return (0); 602 } 603 604 int 605 igc_rx_ring_start(mac_ring_driver_t rh, uint64_t gen) 606 { 607 igc_rx_ring_t *rx_ring = (igc_rx_ring_t *)rh; 608 609 mutex_enter(&rx_ring->irr_lock); 610 rx_ring->irr_gen = gen; 611 mutex_exit(&rx_ring->irr_lock); 612 613 return (0); 614 } 615 616 mblk_t * 617 igc_rx_ring_poll(void *drv, int nbytes) 618 { 619 mblk_t *mp; 620 igc_rx_ring_t *ring = drv; 621 622 ASSERT3S(nbytes, >, 0); 623 if (nbytes == 0) { 624 return (NULL); 625 } 626 627 mutex_enter(&ring->irr_lock); 628 mp = igc_ring_rx(ring, nbytes); 629 mutex_exit(&ring->irr_lock); 630 631 return (mp); 632 } 633 634 int 635 igc_rx_ring_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val) 636 { 637 igc_rx_ring_t *rx_ring = (igc_rx_ring_t *)rh; 638 639 switch (stat) { 640 case MAC_STAT_RBYTES: 641 *val = rx_ring->irr_stat.irs_rbytes.value.ui64; 642 break; 643 case MAC_STAT_IPACKETS: 644 *val = rx_ring->irr_stat.irs_ipackets.value.ui64; 645 break; 646 default: 647 *val = 0; 648 return (ENOTSUP); 649 } 650 651 return (0); 652 } 653 654 int 655 igc_rx_ring_intr_enable(mac_intr_handle_t ih) 656 { 657 igc_rx_ring_t *ring = (igc_rx_ring_t *)ih; 658 igc_t *igc = ring->irr_igc; 659 660 /* 661 * Disabling a ring requires us updating shared device registers. So we 662 * use the igc_lock to protect that. We also grab the irr_lock, so we 663 * can synchronize with the I/O path. 664 */ 665 mutex_enter(&igc->igc_lock); 666 mutex_enter(&ring->irr_lock); 667 ring->irr_flags &= ~IGC_RXR_F_POLL; 668 mutex_exit(&ring->irr_lock); 669 670 /* 671 * Re-enable interrupts. We update our EIMS value and then update both 672 * the EIMS and EIAC. We update the whole set with the EIMS just to 673 * simplify things. 674 */ 675 igc->igc_eims |= 1 << ring->irr_intr_idx; 676 igc_write32(igc, IGC_EIMS, igc->igc_eims); 677 igc_write32(igc, IGC_EIAC, igc->igc_eims); 678 mutex_exit(&igc->igc_lock); 679 return (0); 680 } 681 682 int 683 igc_rx_ring_intr_disable(mac_intr_handle_t ih) 684 { 685 igc_rx_ring_t *ring = (igc_rx_ring_t *)ih; 686 igc_t *igc = ring->irr_igc; 687 688 /* 689 * Disabling a ring requires us updating shared device registers. So we 690 * use the igc_lock to protect that. We also grab the irr_lock, so we 691 * can synchronize with the I/O path. 692 */ 693 mutex_enter(&igc->igc_lock); 694 mutex_enter(&ring->irr_lock); 695 ring->irr_flags |= IGC_RXR_F_POLL; 696 mutex_exit(&ring->irr_lock); 697 698 /* 699 * Writing to the EIMC register masks off interrupts for this. We also 700 * clear this from EIAC as a means of making sure it also won't 701 * retrigger. We remove this queue from our global tracking set of what 702 * the eims value should be to simplify tracking. 703 */ 704 igc_write32(igc, IGC_EIMC, 1 << ring->irr_intr_idx); 705 igc->igc_eims &= ~ (1 << ring->irr_intr_idx); 706 igc_write32(igc, IGC_EIAC, igc->igc_eims); 707 mutex_exit(&igc->igc_lock); 708 709 return (0); 710 } 711 712 static void 713 igc_fill_tx_ring(void *arg, mac_ring_type_t rtype, const int group_idx, 714 const int ring_idx, mac_ring_info_t *infop, mac_ring_handle_t rh) 715 { 716 igc_t *igc = arg; 717 igc_tx_ring_t *ring; 718 719 ASSERT3S(group_idx, ==, -1); 720 ASSERT3S(ring_idx, <, igc->igc_ntx_rings); 721 722 ring = &igc->igc_tx_rings[ring_idx]; 723 ring->itr_rh = rh; 724 725 infop->mri_driver = (mac_ring_driver_t)ring; 726 infop->mri_start = NULL; 727 infop->mri_stop = NULL; 728 infop->mri_tx = igc_ring_tx; 729 infop->mri_stat = igc_tx_ring_stat; 730 731 if (igc->igc_intr_type == DDI_INTR_TYPE_MSIX) { 732 infop->mri_intr.mi_ddi_handle = 733 igc->igc_intr_handles[ring->itr_intr_idx]; 734 } 735 } 736 737 static void 738 igc_fill_rx_ring(void *arg, mac_ring_type_t rtype, const int group_idx, 739 const int ring_idx, mac_ring_info_t *infop, mac_ring_handle_t rh) 740 { 741 igc_t *igc = arg; 742 igc_rx_ring_t *ring; 743 744 ASSERT3S(group_idx, ==, 0); 745 ASSERT3S(ring_idx, <, igc->igc_nrx_rings); 746 747 ring = &igc->igc_rx_rings[ring_idx]; 748 ring->irr_rh = rh; 749 750 infop->mri_driver = (mac_ring_driver_t)ring; 751 infop->mri_start = igc_rx_ring_start; 752 infop->mri_stop = NULL; 753 infop->mri_poll = igc_rx_ring_poll; 754 infop->mri_stat = igc_rx_ring_stat; 755 infop->mri_intr.mi_handle = (mac_intr_handle_t)ring; 756 infop->mri_intr.mi_enable = igc_rx_ring_intr_enable; 757 infop->mri_intr.mi_disable = igc_rx_ring_intr_disable; 758 759 if (igc->igc_intr_type == DDI_INTR_TYPE_MSIX) { 760 infop->mri_intr.mi_ddi_handle = 761 igc->igc_intr_handles[ring->irr_intr_idx]; 762 } 763 } 764 765 static void 766 igc_fill_rx_group(void *arg, mac_ring_type_t rtype, const int idx, 767 mac_group_info_t *infop, mac_group_handle_t gh) 768 { 769 igc_t *igc = arg; 770 771 if (rtype != MAC_RING_TYPE_RX) { 772 return; 773 } 774 775 igc->igc_rxg_hdl = gh; 776 infop->mgi_driver = (mac_group_driver_t)igc; 777 infop->mgi_start = NULL; 778 infop->mgi_stop = NULL; 779 infop->mgi_addmac = igc_group_add_mac; 780 infop->mgi_remmac = igc_group_rem_mac; 781 infop->mgi_count = igc->igc_nrx_rings; 782 } 783 784 static int 785 igc_led_set(void *drv, mac_led_mode_t mode, uint_t flags) 786 { 787 igc_t *igc = drv; 788 uint32_t led; 789 790 if (flags != 0) { 791 return (EINVAL); 792 } 793 794 switch (mode) { 795 case MAC_LED_DEFAULT: 796 led = igc->igc_ledctl; 797 break; 798 case MAC_LED_IDENT: 799 led = igc->igc_ledctl_blink; 800 break; 801 case MAC_LED_OFF: 802 led = igc->igc_ledctl_off; 803 break; 804 case MAC_LED_ON: 805 led = igc->igc_ledctl_on; 806 break; 807 default: 808 return (ENOTSUP); 809 } 810 811 mutex_enter(&igc->igc_lock); 812 igc_write32(igc, IGC_LEDCTL, led); 813 igc->igc_led_mode = mode; 814 mutex_exit(&igc->igc_lock); 815 816 return (0); 817 } 818 819 static boolean_t 820 igc_m_getcapab(void *drv, mac_capab_t capab, void *data) 821 { 822 igc_t *igc = drv; 823 mac_capab_rings_t *rings; 824 mac_capab_led_t *led; 825 uint32_t *cksump; 826 827 switch (capab) { 828 case MAC_CAPAB_RINGS: 829 rings = data; 830 rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 831 switch (rings->mr_type) { 832 case MAC_RING_TYPE_TX: 833 rings->mr_gnum = 0; 834 rings->mr_rnum = igc->igc_ntx_rings; 835 rings->mr_rget = igc_fill_tx_ring; 836 rings->mr_gget = NULL; 837 rings->mr_gaddring = NULL; 838 rings->mr_gremring = NULL; 839 break; 840 case MAC_RING_TYPE_RX: 841 rings->mr_gnum = 1; 842 rings->mr_rnum = igc->igc_nrx_rings; 843 rings->mr_rget = igc_fill_rx_ring; 844 rings->mr_gget = igc_fill_rx_group; 845 rings->mr_gaddring = NULL; 846 rings->mr_gremring = NULL; 847 break; 848 default: 849 return (B_FALSE); 850 } 851 break; 852 case MAC_CAPAB_HCKSUM: 853 cksump = data; 854 855 /* 856 * The hardware supports computing the full checksum on receive, 857 * but on transmit needs the partial checksum pre-computed. 858 */ 859 *cksump = HCKSUM_INET_PARTIAL | HCKSUM_IPHDRCKSUM; 860 break; 861 case MAC_CAPAB_LED: 862 led = data; 863 led->mcl_flags = 0; 864 led->mcl_modes = MAC_LED_DEFAULT | MAC_LED_OFF | MAC_LED_ON | 865 MAC_LED_IDENT; 866 led->mcl_set = igc_led_set; 867 return (B_TRUE); 868 default: 869 return (B_FALSE); 870 } 871 return (B_TRUE); 872 } 873 874 void 875 igc_m_propinfo(void *drv, const char *name, mac_prop_id_t prop, 876 mac_prop_info_handle_t prh) 877 { 878 igc_t *igc = drv; 879 880 switch (prop) { 881 case MAC_PROP_DUPLEX: 882 case MAC_PROP_SPEED: 883 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 884 break; 885 case MAC_PROP_AUTONEG: 886 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 887 mac_prop_info_set_default_uint8(prh, 1); 888 break; 889 case MAC_PROP_MTU: 890 mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW); 891 mac_prop_info_set_range_uint32(prh, ETHERMIN, 892 igc->igc_limits.il_max_mtu); 893 mac_prop_info_set_default_uint32(prh, ETHERMTU); 894 break; 895 case MAC_PROP_FLOWCTRL: 896 mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW); 897 mac_prop_info_set_default_link_flowctrl(prh, LINK_FLOWCTRL_BI); 898 break; 899 /* 900 * Right now, all igc devices support the same set of speeds and we 901 * attempt to advertise them all. 902 */ 903 case MAC_PROP_ADV_10HDX_CAP: 904 case MAC_PROP_ADV_10FDX_CAP: 905 case MAC_PROP_ADV_100HDX_CAP: 906 case MAC_PROP_ADV_100FDX_CAP: 907 case MAC_PROP_ADV_1000FDX_CAP: 908 case MAC_PROP_ADV_2500FDX_CAP: 909 mac_prop_info_set_perm(prh, MAC_PROP_PERM_READ); 910 mac_prop_info_set_default_uint8(prh, 1); 911 break; 912 case MAC_PROP_EN_10HDX_CAP: 913 case MAC_PROP_EN_10FDX_CAP: 914 case MAC_PROP_EN_100HDX_CAP: 915 case MAC_PROP_EN_100FDX_CAP: 916 case MAC_PROP_EN_1000FDX_CAP: 917 case MAC_PROP_EN_2500FDX_CAP: 918 mac_prop_info_set_perm(prh, MAC_PROP_PERM_RW); 919 mac_prop_info_set_default_uint8(prh, 1); 920 break; 921 default: 922 break; 923 } 924 } 925 926 int 927 igc_m_getprop(void *drv, const char *name, mac_prop_id_t prop, 928 uint_t pr_valsize, void *pr_val) 929 { 930 igc_t *igc = drv; 931 int ret = 0; 932 uint8_t *u8p; 933 uint64_t u64; 934 link_flowctrl_t flow; 935 mac_ether_media_t media; 936 937 mutex_enter(&igc->igc_lock); 938 939 switch (prop) { 940 case MAC_PROP_DUPLEX: 941 if (pr_valsize < sizeof (link_duplex_t)) { 942 ret = EOVERFLOW; 943 break; 944 } 945 bcopy(&igc->igc_link_duplex, pr_val, sizeof (link_duplex_t)); 946 break; 947 case MAC_PROP_SPEED: 948 if (pr_valsize < sizeof (uint64_t)) { 949 ret = EOVERFLOW; 950 break; 951 } 952 u64 = (uint64_t)igc->igc_link_speed * 1000000; 953 bcopy(&u64, pr_val, sizeof (uint64_t)); 954 break; 955 case MAC_PROP_STATUS: 956 if (pr_valsize < sizeof (link_state_t)) { 957 ret = EOVERFLOW; 958 break; 959 } 960 bcopy(&igc->igc_link_state, pr_val, sizeof (link_state_t)); 961 break; 962 case MAC_PROP_MEDIA: 963 if (pr_valsize < sizeof (mac_ether_media_t)) { 964 ret = EOVERFLOW; 965 break; 966 } 967 media = igc_link_to_media(igc); 968 bcopy(&media, pr_val, sizeof (mac_ether_media_t)); 969 break; 970 case MAC_PROP_AUTONEG: 971 if (pr_valsize < sizeof (uint8_t)) { 972 ret = EOVERFLOW; 973 break; 974 } 975 u8p = pr_val; 976 *u8p = igc->igc_hw.mac.autoneg; 977 break; 978 case MAC_PROP_MTU: 979 if (pr_valsize < sizeof (uint32_t)) { 980 ret = EOVERFLOW; 981 break; 982 } 983 bcopy(&igc->igc_mtu, pr_val, sizeof (uint32_t)); 984 break; 985 case MAC_PROP_FLOWCTRL: 986 switch (igc->igc_hw.fc.requested_mode) { 987 case igc_fc_none: 988 flow = LINK_FLOWCTRL_NONE; 989 break; 990 case igc_fc_rx_pause: 991 flow = LINK_FLOWCTRL_RX; 992 break; 993 case igc_fc_tx_pause: 994 flow = LINK_FLOWCTRL_TX; 995 break; 996 case igc_fc_full: 997 flow = LINK_FLOWCTRL_BI; 998 break; 999 /* 1000 * We don't expect to get this value here; however, for 1001 * completeness of the switch's valid options we include it and 1002 * set it to the common firmware default of enabling 1003 * bi-direcitonal pause frames. 1004 */ 1005 case igc_fc_default: 1006 flow = LINK_FLOWCTRL_BI; 1007 break; 1008 } 1009 bcopy(&flow, pr_val, sizeof (link_flowctrl_t)); 1010 break; 1011 case MAC_PROP_ADV_10HDX_CAP: 1012 case MAC_PROP_ADV_10FDX_CAP: 1013 case MAC_PROP_ADV_100HDX_CAP: 1014 case MAC_PROP_ADV_100FDX_CAP: 1015 case MAC_PROP_ADV_1000FDX_CAP: 1016 case MAC_PROP_ADV_2500FDX_CAP: 1017 ret = ENOTSUP; 1018 break; 1019 case MAC_PROP_EN_10HDX_CAP: 1020 if (pr_valsize < sizeof (uint8_t)) { 1021 ret = EOVERFLOW; 1022 break; 1023 } 1024 u8p = pr_val; 1025 *u8p = (igc->igc_hw.phy.autoneg_advertised & 1026 ADVERTISE_10_HALF) != 0; 1027 break; 1028 case MAC_PROP_EN_10FDX_CAP: 1029 if (pr_valsize < sizeof (uint8_t)) { 1030 ret = EOVERFLOW; 1031 break; 1032 } 1033 u8p = pr_val; 1034 *u8p = (igc->igc_hw.phy.autoneg_advertised & 1035 ADVERTISE_10_FULL) != 0; 1036 break; 1037 case MAC_PROP_EN_100HDX_CAP: 1038 if (pr_valsize < sizeof (uint8_t)) { 1039 ret = EOVERFLOW; 1040 break; 1041 } 1042 u8p = pr_val; 1043 *u8p = (igc->igc_hw.phy.autoneg_advertised & 1044 ADVERTISE_100_HALF) != 0; 1045 break; 1046 case MAC_PROP_EN_100FDX_CAP: 1047 if (pr_valsize < sizeof (uint8_t)) { 1048 ret = EOVERFLOW; 1049 break; 1050 } 1051 u8p = pr_val; 1052 *u8p = (igc->igc_hw.phy.autoneg_advertised & 1053 ADVERTISE_100_FULL) != 0; 1054 break; 1055 case MAC_PROP_EN_1000FDX_CAP: 1056 if (pr_valsize < sizeof (uint8_t)) { 1057 ret = EOVERFLOW; 1058 break; 1059 } 1060 u8p = pr_val; 1061 *u8p = (igc->igc_hw.phy.autoneg_advertised & 1062 ADVERTISE_1000_FULL) != 0; 1063 break; 1064 case MAC_PROP_EN_2500FDX_CAP: 1065 if (pr_valsize < sizeof (uint8_t)) { 1066 ret = EOVERFLOW; 1067 break; 1068 } 1069 u8p = pr_val; 1070 *u8p = (igc->igc_hw.phy.autoneg_advertised & 1071 ADVERTISE_2500_FULL) != 0; 1072 break; 1073 default: 1074 ret = ENOTSUP; 1075 break; 1076 } 1077 1078 mutex_exit(&igc->igc_lock); 1079 return (ret); 1080 } 1081 1082 int 1083 igc_m_setprop(void *drv, const char *name, mac_prop_id_t prop, uint_t size, 1084 const void *val) 1085 { 1086 int ret = 0; 1087 bool update_link = true; 1088 igc_t *igc = drv; 1089 uint32_t fc, mtu; 1090 uint8_t en; 1091 1092 mutex_enter(&igc->igc_lock); 1093 switch (prop) { 1094 /* 1095 * The following properties are always read-only. Note, auto-negotiation 1096 * is here because we don't support turning it off right now. We leave 1097 * out unsupported speeds. 1098 */ 1099 case MAC_PROP_DUPLEX: 1100 case MAC_PROP_SPEED: 1101 case MAC_PROP_STATUS: 1102 case MAC_PROP_AUTONEG: 1103 case MAC_PROP_ADV_2500FDX_CAP: 1104 case MAC_PROP_ADV_1000FDX_CAP: 1105 case MAC_PROP_ADV_1000HDX_CAP: 1106 case MAC_PROP_ADV_100FDX_CAP: 1107 case MAC_PROP_ADV_100HDX_CAP: 1108 case MAC_PROP_ADV_10HDX_CAP: 1109 case MAC_PROP_ADV_10FDX_CAP: 1110 case MAC_PROP_MEDIA: 1111 ret = ENOTSUP; 1112 break; 1113 /* 1114 * This is a property that we should support, but don't today. 1115 */ 1116 case MAC_PROP_MTU: 1117 /* 1118 * Unfortunately, like our siblings igb and e1000g, we do not 1119 * currently support changing the MTU dynamically. 1120 */ 1121 if ((igc->igc_attach & IGC_ATTACH_MAC_START) != 0) { 1122 ret = EBUSY; 1123 break; 1124 } 1125 1126 /* 1127 * Changing the MTU does not require us to update the link right 1128 * now as this can only be done while the device is stopped. 1129 */ 1130 update_link = false; 1131 1132 bcopy(val, &mtu, sizeof (mtu)); 1133 if (mtu < ETHERMIN || mtu > igc->igc_limits.il_max_mtu) { 1134 ret = EINVAL; 1135 break; 1136 } 1137 1138 /* 1139 * Verify that MAC will let us perform this operation. Once we 1140 * have confirmed that we will need to update our various buffer 1141 * sizes. Right now the driver requires that we increase the rx 1142 * buffer size to match the MTU. The tx buffer size is capped at 1143 * a page size and will be chained together if required. See the 1144 * theory statement for more information. 1145 */ 1146 ret = mac_maxsdu_update(igc->igc_mac_hdl, mtu); 1147 if (ret == 0) { 1148 igc->igc_mtu = mtu; 1149 igc_hw_buf_update(igc); 1150 } 1151 break; 1152 case MAC_PROP_FLOWCTRL: 1153 bcopy(val, &fc, sizeof (uint32_t)); 1154 1155 switch (fc) { 1156 case LINK_FLOWCTRL_NONE: 1157 igc->igc_hw.fc.requested_mode = igc_fc_none; 1158 break; 1159 case LINK_FLOWCTRL_RX: 1160 igc->igc_hw.fc.requested_mode = igc_fc_rx_pause; 1161 break; 1162 case LINK_FLOWCTRL_TX: 1163 igc->igc_hw.fc.requested_mode = igc_fc_tx_pause; 1164 break; 1165 case LINK_FLOWCTRL_BI: 1166 igc->igc_hw.fc.requested_mode = igc_fc_full; 1167 break; 1168 default: 1169 ret = EINVAL; 1170 break; 1171 } 1172 break; 1173 case MAC_PROP_EN_2500FDX_CAP: 1174 bcopy(val, &en, sizeof (uint8_t)); 1175 if (en != 0) { 1176 igc->igc_hw.phy.autoneg_advertised |= 1177 ADVERTISE_2500_FULL; 1178 } else { 1179 igc->igc_hw.phy.autoneg_advertised &= 1180 ~ADVERTISE_2500_FULL; 1181 } 1182 break; 1183 case MAC_PROP_EN_1000FDX_CAP: 1184 bcopy(val, &en, sizeof (uint8_t)); 1185 if (en != 0) { 1186 igc->igc_hw.phy.autoneg_advertised |= 1187 ADVERTISE_1000_FULL; 1188 } else { 1189 igc->igc_hw.phy.autoneg_advertised &= 1190 ~ADVERTISE_1000_FULL; 1191 } 1192 break; 1193 case MAC_PROP_EN_100FDX_CAP: 1194 bcopy(val, &en, sizeof (uint8_t)); 1195 if (en != 0) { 1196 igc->igc_hw.phy.autoneg_advertised |= 1197 ADVERTISE_100_FULL; 1198 } else { 1199 igc->igc_hw.phy.autoneg_advertised &= 1200 ~ADVERTISE_100_FULL; 1201 } 1202 break; 1203 case MAC_PROP_EN_100HDX_CAP: 1204 bcopy(val, &en, sizeof (uint8_t)); 1205 if (en != 0) { 1206 igc->igc_hw.phy.autoneg_advertised |= 1207 ADVERTISE_100_HALF; 1208 } else { 1209 igc->igc_hw.phy.autoneg_advertised &= 1210 ~ADVERTISE_100_HALF; 1211 } 1212 break; 1213 case MAC_PROP_EN_10FDX_CAP: 1214 bcopy(val, &en, sizeof (uint8_t)); 1215 if (en != 0) { 1216 igc->igc_hw.phy.autoneg_advertised |= 1217 ADVERTISE_10_FULL; 1218 } else { 1219 igc->igc_hw.phy.autoneg_advertised &= 1220 ~ADVERTISE_10_FULL; 1221 } 1222 break; 1223 case MAC_PROP_EN_10HDX_CAP: 1224 bcopy(val, &en, sizeof (uint8_t)); 1225 if (en != 0) { 1226 igc->igc_hw.phy.autoneg_advertised |= 1227 ADVERTISE_10_HALF; 1228 } else { 1229 igc->igc_hw.phy.autoneg_advertised &= 1230 ~ADVERTISE_10_HALF; 1231 } 1232 break; 1233 default: 1234 ret = ENOTSUP; 1235 break; 1236 } 1237 1238 if (ret == 0 && update_link) { 1239 if (igc_setup_link(&igc->igc_hw) != IGC_SUCCESS) { 1240 ret = EIO; 1241 } 1242 } 1243 mutex_exit(&igc->igc_lock); 1244 1245 return (ret); 1246 } 1247 1248 static mac_callbacks_t igc_mac_callbacks = { 1249 .mc_callbacks = MC_GETCAPAB | MC_GETPROP | MC_SETPROP | MC_PROPINFO, 1250 .mc_getstat = igc_m_getstat, 1251 .mc_start = igc_m_start, 1252 .mc_stop = igc_m_stop, 1253 .mc_setpromisc = igc_m_setpromisc, 1254 .mc_multicst = igc_m_multicast, 1255 .mc_getcapab = igc_m_getcapab, 1256 .mc_setprop = igc_m_setprop, 1257 .mc_getprop = igc_m_getprop, 1258 .mc_propinfo = igc_m_propinfo 1259 }; 1260 1261 bool 1262 igc_mac_register(igc_t *igc) 1263 { 1264 int ret; 1265 mac_register_t *mac = mac_alloc(MAC_VERSION); 1266 1267 if (mac == NULL) { 1268 dev_err(igc->igc_dip, CE_WARN, "failed to allocate mac " 1269 "registration handle"); 1270 return (false); 1271 } 1272 1273 mac->m_type_ident = MAC_PLUGIN_IDENT_ETHER; 1274 mac->m_driver = igc; 1275 mac->m_dip = igc->igc_dip; 1276 mac->m_src_addr = igc->igc_hw.mac.addr; 1277 mac->m_callbacks = &igc_mac_callbacks; 1278 mac->m_min_sdu = 0; 1279 mac->m_max_sdu = igc->igc_mtu; 1280 mac->m_margin = VLAN_TAGSZ; 1281 mac->m_priv_props = NULL; 1282 mac->m_v12n = MAC_VIRT_LEVEL1; 1283 1284 ret = mac_register(mac, &igc->igc_mac_hdl); 1285 mac_free(mac); 1286 if (ret != 0) { 1287 dev_err(igc->igc_dip, CE_WARN, "failed to register with MAC: " 1288 "%d", ret); 1289 return (false); 1290 } 1291 1292 return (true); 1293 } 1294