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