1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright(c) 2007-2008 Intel Corporation. All rights reserved. 24 */ 25 26 /* 27 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 28 * Use is subject to license terms. 29 */ 30 31 #include "ixgbe_sw.h" 32 33 /* 34 * Retrieve a value for one of the statistics. 35 */ 36 int 37 ixgbe_m_stat(void *arg, uint_t stat, uint64_t *val) 38 { 39 ixgbe_t *ixgbe = (ixgbe_t *)arg; 40 struct ixgbe_hw *hw = &ixgbe->hw; 41 ixgbe_stat_t *ixgbe_ks; 42 int i; 43 44 ixgbe_ks = (ixgbe_stat_t *)ixgbe->ixgbe_ks->ks_data; 45 46 mutex_enter(&ixgbe->gen_lock); 47 48 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 49 mutex_exit(&ixgbe->gen_lock); 50 return (ECANCELED); 51 } 52 53 switch (stat) { 54 case MAC_STAT_IFSPEED: 55 *val = ixgbe->link_speed * 1000000ull; 56 break; 57 58 case MAC_STAT_MULTIRCV: 59 ixgbe_ks->mprc.value.ui64 += 60 IXGBE_READ_REG(hw, IXGBE_MPRC); 61 *val = ixgbe_ks->mprc.value.ui64; 62 break; 63 64 case MAC_STAT_BRDCSTRCV: 65 ixgbe_ks->bprc.value.ui64 += 66 IXGBE_READ_REG(hw, IXGBE_BPRC); 67 *val = ixgbe_ks->bprc.value.ui64; 68 break; 69 70 case MAC_STAT_MULTIXMT: 71 ixgbe_ks->mptc.value.ui64 += 72 IXGBE_READ_REG(hw, IXGBE_MPTC); 73 *val = ixgbe_ks->mptc.value.ui64; 74 break; 75 76 case MAC_STAT_BRDCSTXMT: 77 ixgbe_ks->bptc.value.ui64 += 78 IXGBE_READ_REG(hw, IXGBE_BPTC); 79 *val = ixgbe_ks->bptc.value.ui64; 80 break; 81 82 case MAC_STAT_NORCVBUF: 83 for (i = 0; i < 8; i++) { 84 ixgbe_ks->rnbc.value.ui64 += 85 IXGBE_READ_REG(hw, IXGBE_RNBC(i)); 86 } 87 *val = ixgbe_ks->rnbc.value.ui64; 88 break; 89 90 case MAC_STAT_IERRORS: 91 ixgbe_ks->crcerrs.value.ui64 += 92 IXGBE_READ_REG(hw, IXGBE_CRCERRS); 93 ixgbe_ks->illerrc.value.ui64 += 94 IXGBE_READ_REG(hw, IXGBE_ILLERRC); 95 ixgbe_ks->errbc.value.ui64 += 96 IXGBE_READ_REG(hw, IXGBE_ERRBC); 97 ixgbe_ks->rlec.value.ui64 += 98 IXGBE_READ_REG(hw, IXGBE_RLEC); 99 *val = ixgbe_ks->crcerrs.value.ui64 + 100 ixgbe_ks->illerrc.value.ui64 + 101 ixgbe_ks->errbc.value.ui64 + 102 ixgbe_ks->rlec.value.ui64; 103 break; 104 105 case MAC_STAT_RBYTES: 106 ixgbe_ks->tor.value.ui64 = 0; 107 for (i = 0; i < 16; i++) { 108 ixgbe_ks->qbrc[i].value.ui64 += 109 IXGBE_READ_REG(hw, IXGBE_QBRC(i)); 110 ixgbe_ks->tor.value.ui64 += 111 ixgbe_ks->qbrc[i].value.ui64; 112 } 113 *val = ixgbe_ks->tor.value.ui64; 114 break; 115 116 case MAC_STAT_OBYTES: 117 ixgbe_ks->tot.value.ui64 = 0; 118 for (i = 0; i < 16; i++) { 119 ixgbe_ks->qbtc[i].value.ui64 += 120 IXGBE_READ_REG(hw, IXGBE_QBTC(i)); 121 ixgbe_ks->tot.value.ui64 += 122 ixgbe_ks->qbtc[i].value.ui64; 123 } 124 *val = ixgbe_ks->tot.value.ui64; 125 break; 126 127 case MAC_STAT_IPACKETS: 128 ixgbe_ks->tpr.value.ui64 += 129 IXGBE_READ_REG(hw, IXGBE_TPR); 130 *val = ixgbe_ks->tpr.value.ui64; 131 break; 132 133 case MAC_STAT_OPACKETS: 134 ixgbe_ks->tpt.value.ui64 += 135 IXGBE_READ_REG(hw, IXGBE_TPT); 136 *val = ixgbe_ks->tpt.value.ui64; 137 break; 138 139 /* RFC 1643 stats */ 140 case ETHER_STAT_FCS_ERRORS: 141 ixgbe_ks->crcerrs.value.ui64 += 142 IXGBE_READ_REG(hw, IXGBE_CRCERRS); 143 *val = ixgbe_ks->crcerrs.value.ui64; 144 break; 145 146 case ETHER_STAT_TOOLONG_ERRORS: 147 ixgbe_ks->roc.value.ui64 += 148 IXGBE_READ_REG(hw, IXGBE_ROC); 149 *val = ixgbe_ks->roc.value.ui64; 150 break; 151 152 case ETHER_STAT_MACRCV_ERRORS: 153 ixgbe_ks->crcerrs.value.ui64 += 154 IXGBE_READ_REG(hw, IXGBE_CRCERRS); 155 ixgbe_ks->illerrc.value.ui64 += 156 IXGBE_READ_REG(hw, IXGBE_ILLERRC); 157 ixgbe_ks->errbc.value.ui64 += 158 IXGBE_READ_REG(hw, IXGBE_ERRBC); 159 ixgbe_ks->rlec.value.ui64 += 160 IXGBE_READ_REG(hw, IXGBE_RLEC); 161 *val = ixgbe_ks->crcerrs.value.ui64 + 162 ixgbe_ks->illerrc.value.ui64 + 163 ixgbe_ks->errbc.value.ui64 + 164 ixgbe_ks->rlec.value.ui64; 165 break; 166 167 /* MII/GMII stats */ 168 case ETHER_STAT_XCVR_ADDR: 169 /* The Internal PHY's MDI address for each MAC is 1 */ 170 *val = 1; 171 break; 172 173 case ETHER_STAT_XCVR_ID: 174 *val = hw->phy.id; 175 break; 176 177 case ETHER_STAT_XCVR_INUSE: 178 switch (ixgbe->link_speed) { 179 case IXGBE_LINK_SPEED_1GB_FULL: 180 *val = 181 (hw->phy.media_type == ixgbe_media_type_copper) ? 182 XCVR_1000T : XCVR_1000X; 183 break; 184 case IXGBE_LINK_SPEED_100_FULL: 185 *val = (hw->phy.media_type == ixgbe_media_type_copper) ? 186 XCVR_100T2 : XCVR_100X; 187 break; 188 default: 189 *val = XCVR_NONE; 190 break; 191 } 192 break; 193 194 case ETHER_STAT_CAP_1000FDX: 195 *val = ixgbe->param_1000fdx_cap; 196 break; 197 198 case ETHER_STAT_CAP_100FDX: 199 *val = ixgbe->param_100fdx_cap; 200 break; 201 202 case ETHER_STAT_CAP_ASMPAUSE: 203 *val = ixgbe->param_asym_pause_cap; 204 break; 205 206 case ETHER_STAT_CAP_PAUSE: 207 *val = ixgbe->param_pause_cap; 208 break; 209 210 case ETHER_STAT_CAP_AUTONEG: 211 *val = ixgbe->param_autoneg_cap; 212 break; 213 214 case ETHER_STAT_ADV_CAP_1000FDX: 215 *val = ixgbe->param_adv_1000fdx_cap; 216 break; 217 218 case ETHER_STAT_ADV_CAP_100FDX: 219 *val = ixgbe->param_adv_100fdx_cap; 220 break; 221 222 case ETHER_STAT_ADV_CAP_ASMPAUSE: 223 *val = ixgbe->param_adv_asym_pause_cap; 224 break; 225 226 case ETHER_STAT_ADV_CAP_PAUSE: 227 *val = ixgbe->param_adv_pause_cap; 228 break; 229 230 case ETHER_STAT_ADV_CAP_AUTONEG: 231 *val = hw->mac.autoneg; 232 break; 233 234 case ETHER_STAT_LP_CAP_1000FDX: 235 *val = ixgbe->param_lp_1000fdx_cap; 236 break; 237 238 case ETHER_STAT_LP_CAP_100FDX: 239 *val = ixgbe->param_lp_100fdx_cap; 240 break; 241 242 case ETHER_STAT_LP_CAP_ASMPAUSE: 243 *val = ixgbe->param_lp_asym_pause_cap; 244 break; 245 246 case ETHER_STAT_LP_CAP_PAUSE: 247 *val = ixgbe->param_lp_pause_cap; 248 break; 249 250 case ETHER_STAT_LP_CAP_AUTONEG: 251 *val = ixgbe->param_lp_autoneg_cap; 252 break; 253 254 case ETHER_STAT_LINK_ASMPAUSE: 255 *val = ixgbe->param_asym_pause_cap; 256 break; 257 258 case ETHER_STAT_LINK_PAUSE: 259 *val = ixgbe->param_pause_cap; 260 break; 261 262 case ETHER_STAT_LINK_AUTONEG: 263 *val = hw->mac.autoneg; 264 break; 265 case ETHER_STAT_LINK_DUPLEX: 266 *val = LINK_DUPLEX_FULL; 267 break; 268 269 case ETHER_STAT_TOOSHORT_ERRORS: 270 ixgbe_ks->ruc.value.ui64 += 271 IXGBE_READ_REG(hw, IXGBE_RUC); 272 *val = ixgbe_ks->ruc.value.ui64; 273 break; 274 275 case ETHER_STAT_CAP_REMFAULT: 276 *val = ixgbe->param_rem_fault; 277 break; 278 279 case ETHER_STAT_ADV_REMFAULT: 280 *val = ixgbe->param_adv_rem_fault; 281 break; 282 283 case ETHER_STAT_LP_REMFAULT: 284 *val = ixgbe->param_lp_rem_fault; 285 break; 286 287 case ETHER_STAT_JABBER_ERRORS: 288 ixgbe_ks->rjc.value.ui64 += 289 IXGBE_READ_REG(hw, IXGBE_RJC); 290 *val = ixgbe_ks->rjc.value.ui64; 291 break; 292 293 default: 294 mutex_exit(&ixgbe->gen_lock); 295 return (ENOTSUP); 296 } 297 298 mutex_exit(&ixgbe->gen_lock); 299 300 if (ixgbe_check_acc_handle(ixgbe->osdep.reg_handle) != DDI_FM_OK) 301 ddi_fm_service_impact(ixgbe->dip, DDI_SERVICE_UNAFFECTED); 302 303 return (0); 304 } 305 306 /* 307 * Bring the device out of the reset/quiesced state that it 308 * was in when the interface was registered. 309 */ 310 int 311 ixgbe_m_start(void *arg) 312 { 313 ixgbe_t *ixgbe = (ixgbe_t *)arg; 314 315 mutex_enter(&ixgbe->gen_lock); 316 317 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 318 mutex_exit(&ixgbe->gen_lock); 319 return (ECANCELED); 320 } 321 322 if (ixgbe_start(ixgbe) != IXGBE_SUCCESS) { 323 mutex_exit(&ixgbe->gen_lock); 324 return (EIO); 325 } 326 327 ixgbe->ixgbe_state |= IXGBE_STARTED; 328 329 mutex_exit(&ixgbe->gen_lock); 330 331 /* 332 * Enable and start the watchdog timer 333 */ 334 ixgbe_enable_watchdog_timer(ixgbe); 335 336 return (0); 337 } 338 339 /* 340 * Stop the device and put it in a reset/quiesced state such 341 * that the interface can be unregistered. 342 */ 343 void 344 ixgbe_m_stop(void *arg) 345 { 346 ixgbe_t *ixgbe = (ixgbe_t *)arg; 347 348 mutex_enter(&ixgbe->gen_lock); 349 350 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 351 mutex_exit(&ixgbe->gen_lock); 352 return; 353 } 354 355 ixgbe->ixgbe_state &= ~IXGBE_STARTED; 356 357 ixgbe_stop(ixgbe); 358 359 mutex_exit(&ixgbe->gen_lock); 360 361 /* 362 * Disable and stop the watchdog timer 363 */ 364 ixgbe_disable_watchdog_timer(ixgbe); 365 } 366 367 /* 368 * Set the promiscuity of the device. 369 */ 370 int 371 ixgbe_m_promisc(void *arg, boolean_t on) 372 { 373 ixgbe_t *ixgbe = (ixgbe_t *)arg; 374 uint32_t reg_val; 375 struct ixgbe_hw *hw = &ixgbe->hw; 376 377 mutex_enter(&ixgbe->gen_lock); 378 379 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 380 mutex_exit(&ixgbe->gen_lock); 381 return (ECANCELED); 382 } 383 reg_val = IXGBE_READ_REG(hw, IXGBE_FCTRL); 384 385 if (on) 386 reg_val |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 387 else 388 reg_val &= (~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE)); 389 390 IXGBE_WRITE_REG(&ixgbe->hw, IXGBE_FCTRL, reg_val); 391 392 mutex_exit(&ixgbe->gen_lock); 393 394 return (0); 395 } 396 397 /* 398 * Add/remove the addresses to/from the set of multicast 399 * addresses for which the device will receive packets. 400 */ 401 int 402 ixgbe_m_multicst(void *arg, boolean_t add, const uint8_t *mcst_addr) 403 { 404 ixgbe_t *ixgbe = (ixgbe_t *)arg; 405 int result; 406 407 mutex_enter(&ixgbe->gen_lock); 408 409 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 410 mutex_exit(&ixgbe->gen_lock); 411 return (ECANCELED); 412 } 413 414 result = (add) ? ixgbe_multicst_add(ixgbe, mcst_addr) 415 : ixgbe_multicst_remove(ixgbe, mcst_addr); 416 417 mutex_exit(&ixgbe->gen_lock); 418 419 return (result); 420 } 421 422 /* 423 * Pass on M_IOCTL messages passed to the DLD, and support 424 * private IOCTLs for debugging and ndd. 425 */ 426 void 427 ixgbe_m_ioctl(void *arg, queue_t *q, mblk_t *mp) 428 { 429 ixgbe_t *ixgbe = (ixgbe_t *)arg; 430 struct iocblk *iocp; 431 enum ioc_reply status; 432 433 iocp = (struct iocblk *)(uintptr_t)mp->b_rptr; 434 iocp->ioc_error = 0; 435 436 switch (iocp->ioc_cmd) { 437 case LB_GET_INFO_SIZE: 438 case LB_GET_INFO: 439 case LB_GET_MODE: 440 case LB_SET_MODE: 441 status = ixgbe_loopback_ioctl(ixgbe, iocp, mp); 442 break; 443 444 case ND_GET: 445 case ND_SET: 446 status = ixgbe_nd_ioctl(ixgbe, q, mp, iocp); 447 break; 448 449 default: 450 status = IOC_INVAL; 451 break; 452 } 453 454 /* 455 * Decide how to reply 456 */ 457 switch (status) { 458 default: 459 case IOC_INVAL: 460 /* 461 * Error, reply with a NAK and EINVAL or the specified error 462 */ 463 miocnak(q, mp, 0, iocp->ioc_error == 0 ? 464 EINVAL : iocp->ioc_error); 465 break; 466 467 case IOC_DONE: 468 /* 469 * OK, reply already sent 470 */ 471 break; 472 473 case IOC_ACK: 474 /* 475 * OK, reply with an ACK 476 */ 477 miocack(q, mp, 0, 0); 478 break; 479 480 case IOC_REPLY: 481 /* 482 * OK, send prepared reply as ACK or NAK 483 */ 484 mp->b_datap->db_type = iocp->ioc_error == 0 ? 485 M_IOCACK : M_IOCNAK; 486 qreply(q, mp); 487 break; 488 } 489 } 490 491 /* 492 * Obtain the MAC's capabilities and associated data from 493 * the driver. 494 */ 495 boolean_t 496 ixgbe_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 497 { 498 ixgbe_t *ixgbe = (ixgbe_t *)arg; 499 500 switch (cap) { 501 case MAC_CAPAB_HCKSUM: { 502 uint32_t *tx_hcksum_flags = cap_data; 503 504 /* 505 * We advertise our capabilities only if tx hcksum offload is 506 * enabled. On receive, the stack will accept checksummed 507 * packets anyway, even if we haven't said we can deliver 508 * them. 509 */ 510 if (!ixgbe->tx_hcksum_enable) 511 return (B_FALSE); 512 513 *tx_hcksum_flags = HCKSUM_INET_PARTIAL | HCKSUM_IPHDRCKSUM; 514 break; 515 } 516 case MAC_CAPAB_LSO: { 517 mac_capab_lso_t *cap_lso = cap_data; 518 519 if (ixgbe->lso_enable) { 520 cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; 521 cap_lso->lso_basic_tcp_ipv4.lso_max = IXGBE_LSO_MAXLEN; 522 break; 523 } else { 524 return (B_FALSE); 525 } 526 } 527 case MAC_CAPAB_RINGS: { 528 mac_capab_rings_t *cap_rings = cap_data; 529 530 switch (cap_rings->mr_type) { 531 case MAC_RING_TYPE_RX: 532 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 533 cap_rings->mr_rnum = ixgbe->num_rx_rings; 534 cap_rings->mr_gnum = ixgbe->num_rx_groups; 535 cap_rings->mr_rget = ixgbe_fill_ring; 536 cap_rings->mr_gget = ixgbe_fill_group; 537 cap_rings->mr_gaddring = NULL; 538 cap_rings->mr_gremring = NULL; 539 break; 540 case MAC_RING_TYPE_TX: 541 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 542 cap_rings->mr_rnum = ixgbe->num_tx_rings; 543 cap_rings->mr_gnum = 0; 544 cap_rings->mr_rget = ixgbe_fill_ring; 545 cap_rings->mr_gget = NULL; 546 break; 547 default: 548 break; 549 } 550 break; 551 } 552 default: 553 return (B_FALSE); 554 } 555 return (B_TRUE); 556 } 557