1 /* 2 * CDDL HEADER START 3 * 4 * Copyright(c) 2007-2008 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: 10 * 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 using or redistributing this file, you may do so under the 15 * License only. No other modification of this header is permitted. 16 * 17 * If applicable, add the following below this CDDL HEADER, with the 18 * fields enclosed by brackets "[]" replaced with your own identifying 19 * information: Portions Copyright [yyyy] [name of copyright owner] 20 * 21 * CDDL HEADER END 22 */ 23 24 /* 25 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms of the CDDL. 27 */ 28 29 #pragma ident "%Z%%M% %I% %E% SMI" 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 for (i = 0; i < 16; i++) 107 ixgbe_ks->tor.value.ui64 += 108 IXGBE_READ_REG(hw, IXGBE_QBRC(i)); 109 *val = ixgbe_ks->tor.value.ui64; 110 break; 111 112 case MAC_STAT_OBYTES: 113 for (i = 0; i < 16; i++) 114 ixgbe_ks->tot.value.ui64 += 115 IXGBE_READ_REG(hw, IXGBE_QBTC(i)); 116 *val = ixgbe_ks->tot.value.ui64; 117 break; 118 119 case MAC_STAT_IPACKETS: 120 ixgbe_ks->tpr.value.ui64 += 121 IXGBE_READ_REG(hw, IXGBE_TPR); 122 *val = ixgbe_ks->tpr.value.ui64; 123 break; 124 125 case MAC_STAT_OPACKETS: 126 ixgbe_ks->tpt.value.ui64 += 127 IXGBE_READ_REG(hw, IXGBE_TPT); 128 *val = ixgbe_ks->tpt.value.ui64; 129 break; 130 131 /* RFC 1643 stats */ 132 case ETHER_STAT_FCS_ERRORS: 133 ixgbe_ks->crcerrs.value.ui64 += 134 IXGBE_READ_REG(hw, IXGBE_CRCERRS); 135 *val = ixgbe_ks->crcerrs.value.ui64; 136 break; 137 138 case ETHER_STAT_TOOLONG_ERRORS: 139 ixgbe_ks->roc.value.ui64 += 140 IXGBE_READ_REG(hw, IXGBE_ROC); 141 *val = ixgbe_ks->roc.value.ui64; 142 break; 143 144 case ETHER_STAT_MACRCV_ERRORS: 145 ixgbe_ks->crcerrs.value.ui64 += 146 IXGBE_READ_REG(hw, IXGBE_CRCERRS); 147 ixgbe_ks->illerrc.value.ui64 += 148 IXGBE_READ_REG(hw, IXGBE_ILLERRC); 149 ixgbe_ks->errbc.value.ui64 += 150 IXGBE_READ_REG(hw, IXGBE_ERRBC); 151 ixgbe_ks->rlec.value.ui64 += 152 IXGBE_READ_REG(hw, IXGBE_RLEC); 153 *val = ixgbe_ks->crcerrs.value.ui64 + 154 ixgbe_ks->illerrc.value.ui64 + 155 ixgbe_ks->errbc.value.ui64 + 156 ixgbe_ks->rlec.value.ui64; 157 break; 158 159 /* MII/GMII stats */ 160 case ETHER_STAT_XCVR_ADDR: 161 /* The Internal PHY's MDI address for each MAC is 1 */ 162 *val = 1; 163 break; 164 165 case ETHER_STAT_XCVR_ID: 166 *val = hw->phy.id; 167 break; 168 169 case ETHER_STAT_XCVR_INUSE: 170 switch (ixgbe->link_speed) { 171 case IXGBE_LINK_SPEED_1GB_FULL: 172 *val = 173 (hw->phy.media_type == ixgbe_media_type_copper) ? 174 XCVR_1000T : XCVR_1000X; 175 break; 176 case IXGBE_LINK_SPEED_100_FULL: 177 *val = (hw->phy.media_type == ixgbe_media_type_copper) ? 178 XCVR_100T2 : XCVR_100X; 179 break; 180 default: 181 *val = XCVR_NONE; 182 break; 183 } 184 break; 185 186 case ETHER_STAT_CAP_1000FDX: 187 *val = ixgbe->param_1000fdx_cap; 188 break; 189 190 case ETHER_STAT_CAP_100FDX: 191 *val = ixgbe->param_100fdx_cap; 192 break; 193 194 case ETHER_STAT_CAP_ASMPAUSE: 195 *val = ixgbe->param_asym_pause_cap; 196 break; 197 198 case ETHER_STAT_CAP_PAUSE: 199 *val = ixgbe->param_pause_cap; 200 break; 201 202 case ETHER_STAT_CAP_AUTONEG: 203 *val = ixgbe->param_autoneg_cap; 204 break; 205 206 case ETHER_STAT_ADV_CAP_1000FDX: 207 *val = ixgbe->param_adv_1000fdx_cap; 208 break; 209 210 case ETHER_STAT_ADV_CAP_100FDX: 211 *val = ixgbe->param_adv_100fdx_cap; 212 break; 213 214 case ETHER_STAT_ADV_CAP_ASMPAUSE: 215 *val = ixgbe->param_adv_asym_pause_cap; 216 break; 217 218 case ETHER_STAT_ADV_CAP_PAUSE: 219 *val = ixgbe->param_adv_pause_cap; 220 break; 221 222 case ETHER_STAT_ADV_CAP_AUTONEG: 223 *val = hw->mac.autoneg; 224 break; 225 226 case ETHER_STAT_LP_CAP_1000FDX: 227 *val = ixgbe->param_lp_1000fdx_cap; 228 break; 229 230 case ETHER_STAT_LP_CAP_100FDX: 231 *val = ixgbe->param_lp_100fdx_cap; 232 break; 233 234 case ETHER_STAT_LP_CAP_ASMPAUSE: 235 *val = ixgbe->param_lp_asym_pause_cap; 236 break; 237 238 case ETHER_STAT_LP_CAP_PAUSE: 239 *val = ixgbe->param_lp_pause_cap; 240 break; 241 242 case ETHER_STAT_LP_CAP_AUTONEG: 243 *val = ixgbe->param_lp_autoneg_cap; 244 break; 245 246 case ETHER_STAT_LINK_ASMPAUSE: 247 *val = ixgbe->param_asym_pause_cap; 248 break; 249 250 case ETHER_STAT_LINK_PAUSE: 251 *val = ixgbe->param_pause_cap; 252 break; 253 254 case ETHER_STAT_LINK_AUTONEG: 255 *val = hw->mac.autoneg; 256 break; 257 case ETHER_STAT_LINK_DUPLEX: 258 *val = LINK_DUPLEX_FULL; 259 break; 260 261 case ETHER_STAT_TOOSHORT_ERRORS: 262 ixgbe_ks->ruc.value.ui64 += 263 IXGBE_READ_REG(hw, IXGBE_RUC); 264 *val = ixgbe_ks->ruc.value.ui64; 265 break; 266 267 case ETHER_STAT_CAP_REMFAULT: 268 *val = ixgbe->param_rem_fault; 269 break; 270 271 case ETHER_STAT_ADV_REMFAULT: 272 *val = ixgbe->param_adv_rem_fault; 273 break; 274 275 case ETHER_STAT_LP_REMFAULT: 276 *val = ixgbe->param_lp_rem_fault; 277 break; 278 279 case ETHER_STAT_JABBER_ERRORS: 280 ixgbe_ks->rjc.value.ui64 += 281 IXGBE_READ_REG(hw, IXGBE_RJC); 282 *val = ixgbe_ks->rjc.value.ui64; 283 break; 284 285 default: 286 mutex_exit(&ixgbe->gen_lock); 287 return (ENOTSUP); 288 } 289 290 mutex_exit(&ixgbe->gen_lock); 291 292 if (ixgbe_check_acc_handle(ixgbe->osdep.reg_handle) != DDI_FM_OK) 293 ddi_fm_service_impact(ixgbe->dip, DDI_SERVICE_UNAFFECTED); 294 295 return (0); 296 } 297 298 /* 299 * Bring the device out of the reset/quiesced state that it 300 * was in when the interface was registered. 301 */ 302 int 303 ixgbe_m_start(void *arg) 304 { 305 ixgbe_t *ixgbe = (ixgbe_t *)arg; 306 307 mutex_enter(&ixgbe->gen_lock); 308 309 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 310 mutex_exit(&ixgbe->gen_lock); 311 return (ECANCELED); 312 } 313 314 if (ixgbe_start(ixgbe) != IXGBE_SUCCESS) { 315 mutex_exit(&ixgbe->gen_lock); 316 return (EIO); 317 } 318 319 ixgbe->ixgbe_state |= IXGBE_STARTED; 320 321 mutex_exit(&ixgbe->gen_lock); 322 323 /* 324 * Enable and start the watchdog timer 325 */ 326 ixgbe_enable_watchdog_timer(ixgbe); 327 328 return (0); 329 } 330 331 /* 332 * Stop the device and put it in a reset/quiesced state such 333 * that the interface can be unregistered. 334 */ 335 void 336 ixgbe_m_stop(void *arg) 337 { 338 ixgbe_t *ixgbe = (ixgbe_t *)arg; 339 340 mutex_enter(&ixgbe->gen_lock); 341 342 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 343 mutex_exit(&ixgbe->gen_lock); 344 return; 345 } 346 347 ixgbe->ixgbe_state &= ~IXGBE_STARTED; 348 349 ixgbe_stop(ixgbe); 350 351 mutex_exit(&ixgbe->gen_lock); 352 353 /* 354 * Disable and stop the watchdog timer 355 */ 356 ixgbe_disable_watchdog_timer(ixgbe); 357 } 358 359 /* 360 * Set the promiscuity of the device. 361 */ 362 int 363 ixgbe_m_promisc(void *arg, boolean_t on) 364 { 365 ixgbe_t *ixgbe = (ixgbe_t *)arg; 366 uint32_t reg_val; 367 struct ixgbe_hw *hw = &ixgbe->hw; 368 369 mutex_enter(&ixgbe->gen_lock); 370 371 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 372 mutex_exit(&ixgbe->gen_lock); 373 return (ECANCELED); 374 } 375 reg_val = IXGBE_READ_REG(hw, IXGBE_FCTRL); 376 377 if (on) 378 reg_val |= (IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE); 379 else 380 reg_val &= (~(IXGBE_FCTRL_UPE | IXGBE_FCTRL_MPE)); 381 382 IXGBE_WRITE_REG(&ixgbe->hw, IXGBE_FCTRL, reg_val); 383 384 mutex_exit(&ixgbe->gen_lock); 385 386 return (0); 387 } 388 389 /* 390 * Add/remove the addresses to/from the set of multicast 391 * addresses for which the device will receive packets. 392 */ 393 int 394 ixgbe_m_multicst(void *arg, boolean_t add, const uint8_t *mcst_addr) 395 { 396 ixgbe_t *ixgbe = (ixgbe_t *)arg; 397 int result; 398 399 mutex_enter(&ixgbe->gen_lock); 400 401 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 402 mutex_exit(&ixgbe->gen_lock); 403 return (ECANCELED); 404 } 405 406 result = (add) ? ixgbe_multicst_add(ixgbe, mcst_addr) 407 : ixgbe_multicst_remove(ixgbe, mcst_addr); 408 409 mutex_exit(&ixgbe->gen_lock); 410 411 return (result); 412 } 413 414 /* 415 * Set a new device unicast address. 416 */ 417 int 418 ixgbe_m_unicst(void *arg, const uint8_t *mac_addr) 419 { 420 ixgbe_t *ixgbe = (ixgbe_t *)arg; 421 int result; 422 423 mutex_enter(&ixgbe->gen_lock); 424 425 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 426 mutex_exit(&ixgbe->gen_lock); 427 return (ECANCELED); 428 } 429 430 /* 431 * Store the new MAC address. 432 */ 433 bcopy(mac_addr, ixgbe->hw.mac.addr, ETHERADDRL); 434 435 /* 436 * Set MAC address in address slot 0, which is the default address. 437 */ 438 result = ixgbe_unicst_set(ixgbe, mac_addr, 0); 439 440 mutex_exit(&ixgbe->gen_lock); 441 442 return (result); 443 } 444 445 /* 446 * Pass on M_IOCTL messages passed to the DLD, and support 447 * private IOCTLs for debugging and ndd. 448 */ 449 void 450 ixgbe_m_ioctl(void *arg, queue_t *q, mblk_t *mp) 451 { 452 ixgbe_t *ixgbe = (ixgbe_t *)arg; 453 struct iocblk *iocp; 454 enum ioc_reply status; 455 456 iocp = (struct iocblk *)(uintptr_t)mp->b_rptr; 457 iocp->ioc_error = 0; 458 459 switch (iocp->ioc_cmd) { 460 case LB_GET_INFO_SIZE: 461 case LB_GET_INFO: 462 case LB_GET_MODE: 463 case LB_SET_MODE: 464 status = ixgbe_loopback_ioctl(ixgbe, iocp, mp); 465 break; 466 467 case ND_GET: 468 case ND_SET: 469 status = ixgbe_nd_ioctl(ixgbe, q, mp, iocp); 470 break; 471 472 default: 473 status = IOC_INVAL; 474 break; 475 } 476 477 /* 478 * Decide how to reply 479 */ 480 switch (status) { 481 default: 482 case IOC_INVAL: 483 /* 484 * Error, reply with a NAK and EINVAL or the specified error 485 */ 486 miocnak(q, mp, 0, iocp->ioc_error == 0 ? 487 EINVAL : iocp->ioc_error); 488 break; 489 490 case IOC_DONE: 491 /* 492 * OK, reply already sent 493 */ 494 break; 495 496 case IOC_ACK: 497 /* 498 * OK, reply with an ACK 499 */ 500 miocack(q, mp, 0, 0); 501 break; 502 503 case IOC_REPLY: 504 /* 505 * OK, send prepared reply as ACK or NAK 506 */ 507 mp->b_datap->db_type = iocp->ioc_error == 0 ? 508 M_IOCACK : M_IOCNAK; 509 qreply(q, mp); 510 break; 511 } 512 } 513 514 515 /* 516 * Find an unused address slot, set the address to it, reserve 517 * this slot and enable the device to start filtering on the 518 * new address. 519 */ 520 int 521 ixgbe_m_unicst_add(void *arg, mac_multi_addr_t *maddr) 522 { 523 ixgbe_t *ixgbe = (ixgbe_t *)arg; 524 mac_addr_slot_t slot; 525 int err; 526 527 mutex_enter(&ixgbe->gen_lock); 528 529 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 530 mutex_exit(&ixgbe->gen_lock); 531 return (ECANCELED); 532 } 533 534 if (mac_unicst_verify(ixgbe->mac_hdl, 535 maddr->mma_addr, maddr->mma_addrlen) == B_FALSE) { 536 mutex_exit(&ixgbe->gen_lock); 537 return (EINVAL); 538 } 539 540 if (ixgbe->unicst_avail == 0) { 541 /* no slots available */ 542 mutex_exit(&ixgbe->gen_lock); 543 return (ENOSPC); 544 } 545 546 /* 547 * Primary/default address is in slot 0. The next addresses 548 * are the multiple MAC addresses. So multiple MAC address 0 549 * is in slot 1, 1 in slot 2, and so on. So the first multiple 550 * MAC address resides in slot 1. 551 */ 552 for (slot = 1; slot < ixgbe->unicst_total; slot++) { 553 if (ixgbe->unicst_addr[slot].mac.set == 0) 554 break; 555 } 556 557 ASSERT((slot > 0) && (slot < ixgbe->unicst_total)); 558 559 maddr->mma_slot = slot; 560 561 if ((err = ixgbe_unicst_set(ixgbe, maddr->mma_addr, slot)) == 0) { 562 ixgbe->unicst_addr[slot].mac.set = 1; 563 ixgbe->unicst_avail--; 564 } 565 566 mutex_exit(&ixgbe->gen_lock); 567 568 return (err); 569 } 570 571 /* 572 * Removes a MAC address that was added before. 573 */ 574 int 575 ixgbe_m_unicst_remove(void *arg, mac_addr_slot_t slot) 576 { 577 ixgbe_t *ixgbe = (ixgbe_t *)arg; 578 int err; 579 580 mutex_enter(&ixgbe->gen_lock); 581 582 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 583 mutex_exit(&ixgbe->gen_lock); 584 return (ECANCELED); 585 } 586 587 if ((slot <= 0) || (slot >= ixgbe->unicst_total)) { 588 mutex_exit(&ixgbe->gen_lock); 589 return (EINVAL); 590 } 591 592 if (ixgbe->unicst_addr[slot].mac.set == 1) { 593 /* 594 * Copy the default address to the passed slot 595 */ 596 if ((err = ixgbe_unicst_set(ixgbe, 597 ixgbe->unicst_addr[0].mac.addr, slot)) == 0) { 598 ixgbe->unicst_addr[slot].mac.set = 0; 599 ixgbe->unicst_avail++; 600 } 601 602 mutex_exit(&ixgbe->gen_lock); 603 604 return (err); 605 } 606 607 mutex_exit(&ixgbe->gen_lock); 608 609 return (EINVAL); 610 } 611 612 /* 613 * Modifies the value of an address that has been added before. 614 * The new address length and the slot number that was returned 615 * in the call to add should be passed in. mma_flags should be 616 * set to 0. 617 * Returns 0 on success. 618 */ 619 int 620 ixgbe_m_unicst_modify(void *arg, mac_multi_addr_t *maddr) 621 { 622 ixgbe_t *ixgbe = (ixgbe_t *)arg; 623 mac_addr_slot_t slot; 624 int err; 625 626 mutex_enter(&ixgbe->gen_lock); 627 628 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 629 mutex_exit(&ixgbe->gen_lock); 630 return (ECANCELED); 631 } 632 633 if (mac_unicst_verify(ixgbe->mac_hdl, 634 maddr->mma_addr, maddr->mma_addrlen) == B_FALSE) { 635 mutex_exit(&ixgbe->gen_lock); 636 return (EINVAL); 637 } 638 639 slot = maddr->mma_slot; 640 641 if ((slot <= 0) || (slot >= ixgbe->unicst_total)) { 642 mutex_exit(&ixgbe->gen_lock); 643 return (EINVAL); 644 } 645 646 if (ixgbe->unicst_addr[slot].mac.set == 1) { 647 err = ixgbe_unicst_set(ixgbe, maddr->mma_addr, slot); 648 mutex_exit(&ixgbe->gen_lock); 649 return (err); 650 } 651 652 mutex_exit(&ixgbe->gen_lock); 653 654 return (EINVAL); 655 } 656 657 /* 658 * Get the MAC address and all other information related to 659 * the address slot passed in mac_multi_addr_t. 660 * mma_flags should be set to 0 in the call. 661 * On return, mma_flags can take the following values: 662 * 1) MMAC_SLOT_UNUSED 663 * 2) MMAC_SLOT_USED | MMAC_VENDOR_ADDR 664 * 3) MMAC_SLOT_UNUSED | MMAC_VENDOR_ADDR 665 * 4) MMAC_SLOT_USED 666 */ 667 int 668 ixgbe_m_unicst_get(void *arg, mac_multi_addr_t *maddr) 669 { 670 ixgbe_t *ixgbe = (ixgbe_t *)arg; 671 mac_addr_slot_t slot; 672 673 mutex_enter(&ixgbe->gen_lock); 674 675 if (ixgbe->ixgbe_state & IXGBE_SUSPENDED) { 676 mutex_exit(&ixgbe->gen_lock); 677 return (ECANCELED); 678 } 679 680 slot = maddr->mma_slot; 681 682 if ((slot <= 0) || (slot >= ixgbe->unicst_total)) { 683 mutex_exit(&ixgbe->gen_lock); 684 return (EINVAL); 685 } 686 if (ixgbe->unicst_addr[slot].mac.set == 1) { 687 bcopy(ixgbe->unicst_addr[slot].mac.addr, 688 maddr->mma_addr, ETHERADDRL); 689 maddr->mma_flags = MMAC_SLOT_USED; 690 } else { 691 maddr->mma_flags = MMAC_SLOT_UNUSED; 692 } 693 694 mutex_exit(&ixgbe->gen_lock); 695 696 return (0); 697 } 698 699 /* 700 * Obtain the MAC's capabilities and associated data from 701 * the driver. 702 */ 703 boolean_t 704 ixgbe_m_getcapab(void *arg, mac_capab_t cap, void *cap_data) 705 { 706 ixgbe_t *ixgbe = (ixgbe_t *)arg; 707 708 switch (cap) { 709 case MAC_CAPAB_HCKSUM: { 710 uint32_t *tx_hcksum_flags = cap_data; 711 712 /* 713 * We advertise our capabilities only if tx hcksum offload is 714 * enabled. On receive, the stack will accept checksummed 715 * packets anyway, even if we haven't said we can deliver 716 * them. 717 */ 718 if (!ixgbe->tx_hcksum_enable) 719 return (B_FALSE); 720 721 *tx_hcksum_flags = HCKSUM_INET_PARTIAL | HCKSUM_IPHDRCKSUM; 722 break; 723 } 724 case MAC_CAPAB_LSO: { 725 mac_capab_lso_t *cap_lso = cap_data; 726 727 if (ixgbe->lso_enable) { 728 cap_lso->lso_flags = LSO_TX_BASIC_TCP_IPV4; 729 cap_lso->lso_basic_tcp_ipv4.lso_max = IXGBE_LSO_MAXLEN; 730 break; 731 } else { 732 return (B_FALSE); 733 } 734 } 735 case MAC_CAPAB_MULTIADDRESS: { 736 multiaddress_capab_t *mmacp = cap_data; 737 738 /* 739 * The number of MAC addresses made available by 740 * this capability is one less than the total as 741 * the primary address in slot 0 is counted in 742 * the total. 743 */ 744 mmacp->maddr_naddr = ixgbe->unicst_total - 1; 745 mmacp->maddr_naddrfree = ixgbe->unicst_avail; 746 /* No multiple factory addresses, set mma_flag to 0 */ 747 mmacp->maddr_flag = 0; 748 mmacp->maddr_handle = ixgbe; 749 mmacp->maddr_add = ixgbe_m_unicst_add; 750 mmacp->maddr_remove = ixgbe_m_unicst_remove; 751 mmacp->maddr_modify = ixgbe_m_unicst_modify; 752 mmacp->maddr_get = ixgbe_m_unicst_get; 753 mmacp->maddr_reserve = NULL; 754 break; 755 } 756 default: 757 return (B_FALSE); 758 } 759 return (B_TRUE); 760 } 761