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 * This file is part of the Chelsio T4 support code. 14 * 15 * Copyright (C) 2010-2013 Chelsio Communications. All rights reserved. 16 * 17 * This program is distributed in the hope that it will be useful, but WITHOUT 18 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 19 * FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file included in this 20 * release for licensing terms and conditions. 21 */ 22 23 #include <sys/ddi.h> 24 #include <sys/sunddi.h> 25 #include <sys/dlpi.h> 26 #include <sys/mac_provider.h> 27 #include <sys/mac_ether.h> 28 #include <sys/strsubr.h> 29 #include <sys/queue.h> 30 31 #include "common/common.h" 32 #include "common/t4_regs.h" 33 34 static int t4_mc_getstat(void *arg, uint_t stat, uint64_t *val); 35 static int t4_mc_start(void *arg); 36 static void t4_mc_stop(void *arg); 37 static int t4_mc_setpromisc(void *arg, boolean_t on); 38 static int t4_mc_multicst(void *arg, boolean_t add, const uint8_t *mcaddr); 39 static int t4_mc_unicst(void *arg, const uint8_t *ucaddr); 40 static boolean_t t4_mc_getcapab(void *arg, mac_capab_t cap, void *data); 41 static int t4_mc_setprop(void *arg, const char *name, mac_prop_id_t id, 42 uint_t size, const void *val); 43 static int t4_mc_getprop(void *arg, const char *name, mac_prop_id_t id, 44 uint_t size, void *val); 45 static void t4_mc_propinfo(void *arg, const char *name, mac_prop_id_t id, 46 mac_prop_info_handle_t ph); 47 48 static int begin_synchronized_op(struct port_info *pi, int hold, int waitok); 49 static void end_synchronized_op(struct port_info *pi, int held); 50 static int t4_init_synchronized(struct port_info *pi); 51 static int t4_uninit_synchronized(struct port_info *pi); 52 static void propinfo(struct port_info *pi, const char *name, 53 mac_prop_info_handle_t ph); 54 static int getprop(struct port_info *pi, const char *name, uint_t size, 55 void *val); 56 static int setprop(struct port_info *pi, const char *name, const void *val); 57 58 mac_callbacks_t t4_m_callbacks = { 59 .mc_callbacks = MC_GETCAPAB | MC_PROPERTIES, 60 .mc_getstat = t4_mc_getstat, 61 .mc_start = t4_mc_start, 62 .mc_stop = t4_mc_stop, 63 .mc_setpromisc = t4_mc_setpromisc, 64 .mc_multicst = t4_mc_multicst, 65 .mc_unicst = t4_mc_unicst, 66 .mc_tx = t4_mc_tx, 67 .mc_getcapab = t4_mc_getcapab, 68 .mc_setprop = t4_mc_setprop, 69 .mc_getprop = t4_mc_getprop, 70 .mc_propinfo = t4_mc_propinfo, 71 }; 72 73 /* I couldn't comeup with a better idea of not redefine 74 * another strcture and instead somehow reuse the earlier 75 * above structure and modify its members. 76 */ 77 mac_callbacks_t t4_m_ring_callbacks = { 78 .mc_callbacks = MC_GETCAPAB | MC_PROPERTIES, 79 .mc_getstat = t4_mc_getstat, 80 .mc_start = t4_mc_start, 81 .mc_stop = t4_mc_stop, 82 .mc_setpromisc =t4_mc_setpromisc, 83 .mc_multicst = t4_mc_multicst, 84 .mc_unicst = NULL, /* t4_addmac */ 85 .mc_tx = NULL, /* t4_eth_tx */ 86 .mc_getcapab = t4_mc_getcapab, 87 .mc_setprop = t4_mc_setprop, 88 .mc_getprop = t4_mc_getprop, 89 .mc_propinfo = t4_mc_propinfo, 90 }; 91 92 #define T4PROP_TMR_IDX "_holdoff_timer_idx" 93 #define T4PROP_PKTC_IDX "_holdoff_pktc_idx" 94 #define T4PROP_MTU "_mtu" 95 #define T4PROP_HW_CSUM "_hw_csum" 96 #define T4PROP_HW_LSO "_hw_lso" 97 #define T4PROP_TX_PAUSE "_tx_pause" 98 #define T4PROP_RX_PAUSE "_rx_pause" 99 100 char *t4_priv_props[] = { 101 T4PROP_TMR_IDX, 102 T4PROP_PKTC_IDX, 103 #if MAC_VERSION == 1 104 /* MAC_VERSION 1 doesn't seem to use MAC_PROP_MTU, hmmmm */ 105 T4PROP_MTU, 106 #endif 107 T4PROP_HW_CSUM, 108 T4PROP_HW_LSO, 109 T4PROP_TX_PAUSE, 110 T4PROP_RX_PAUSE, 111 NULL 112 }; 113 114 static int 115 t4_mc_getstat(void *arg, uint_t stat, uint64_t *val) 116 { 117 struct port_info *pi = arg; 118 struct adapter *sc = pi->adapter; 119 struct link_config *lc = &pi->link_cfg; 120 121 #define GET_STAT(name) \ 122 t4_read_reg64(sc, PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_##name##_L)) 123 124 switch (stat) { 125 case MAC_STAT_IFSPEED: 126 if (lc->link_ok != 0) { 127 *val = lc->speed; 128 *val *= 1000000; 129 } else 130 *val = 0; 131 break; 132 133 case MAC_STAT_MULTIRCV: 134 *val = GET_STAT(RX_PORT_MCAST); 135 break; 136 137 case MAC_STAT_BRDCSTRCV: 138 *val = GET_STAT(RX_PORT_BCAST); 139 break; 140 141 case MAC_STAT_MULTIXMT: 142 *val = GET_STAT(TX_PORT_MCAST); 143 break; 144 145 case MAC_STAT_BRDCSTXMT: 146 *val = GET_STAT(TX_PORT_BCAST); 147 break; 148 149 case MAC_STAT_NORCVBUF: 150 *val = 0; /* TODO should come from rxq->nomem */ 151 break; 152 153 case MAC_STAT_IERRORS: 154 *val = GET_STAT(RX_PORT_MTU_ERROR) + 155 GET_STAT(RX_PORT_MTU_CRC_ERROR) + 156 GET_STAT(RX_PORT_CRC_ERROR) + 157 GET_STAT(RX_PORT_LEN_ERROR) + 158 GET_STAT(RX_PORT_SYM_ERROR) + 159 GET_STAT(RX_PORT_LESS_64B); 160 break; 161 162 case MAC_STAT_UNKNOWNS: 163 return (ENOTSUP); 164 165 case MAC_STAT_NOXMTBUF: 166 *val = GET_STAT(TX_PORT_DROP); 167 break; 168 169 case MAC_STAT_OERRORS: 170 *val = GET_STAT(TX_PORT_ERROR); 171 break; 172 173 case MAC_STAT_COLLISIONS: 174 return (ENOTSUP); 175 176 case MAC_STAT_RBYTES: 177 *val = GET_STAT(RX_PORT_BYTES); 178 break; 179 180 case MAC_STAT_IPACKETS: 181 *val = GET_STAT(RX_PORT_FRAMES); 182 break; 183 184 case MAC_STAT_OBYTES: 185 *val = GET_STAT(TX_PORT_BYTES); 186 break; 187 188 case MAC_STAT_OPACKETS: 189 *val = GET_STAT(TX_PORT_FRAMES); 190 break; 191 192 case ETHER_STAT_ALIGN_ERRORS: 193 return (ENOTSUP); 194 195 case ETHER_STAT_FCS_ERRORS: 196 *val = GET_STAT(RX_PORT_CRC_ERROR); 197 break; 198 199 case ETHER_STAT_FIRST_COLLISIONS: 200 case ETHER_STAT_MULTI_COLLISIONS: 201 case ETHER_STAT_SQE_ERRORS: 202 case ETHER_STAT_DEFER_XMTS: 203 case ETHER_STAT_TX_LATE_COLLISIONS: 204 case ETHER_STAT_EX_COLLISIONS: 205 return (ENOTSUP); 206 207 case ETHER_STAT_MACXMT_ERRORS: 208 *val = GET_STAT(TX_PORT_ERROR); 209 break; 210 211 case ETHER_STAT_CARRIER_ERRORS: 212 return (ENOTSUP); 213 214 case ETHER_STAT_TOOLONG_ERRORS: 215 *val = GET_STAT(RX_PORT_MTU_ERROR); 216 break; 217 218 case ETHER_STAT_MACRCV_ERRORS: 219 *val = GET_STAT(RX_PORT_MTU_ERROR) + 220 GET_STAT(RX_PORT_MTU_CRC_ERROR) + 221 GET_STAT(RX_PORT_CRC_ERROR) + 222 GET_STAT(RX_PORT_LEN_ERROR) + 223 GET_STAT(RX_PORT_SYM_ERROR) + 224 GET_STAT(RX_PORT_LESS_64B); 225 break; 226 227 case ETHER_STAT_XCVR_ADDR: 228 case ETHER_STAT_XCVR_ID: 229 case ETHER_STAT_XCVR_INUSE: 230 return (ENOTSUP); 231 232 case ETHER_STAT_CAP_100GFDX: 233 *val = !!(lc->supported & FW_PORT_CAP_SPEED_100G); 234 break; 235 236 case ETHER_STAT_CAP_40GFDX: 237 *val = !!(lc->supported & FW_PORT_CAP_SPEED_40G); 238 break; 239 240 case ETHER_STAT_CAP_25GFDX: 241 *val = !!(lc->supported & FW_PORT_CAP_SPEED_25G); 242 break; 243 244 case ETHER_STAT_CAP_10GFDX: 245 *val = !!(lc->supported & FW_PORT_CAP_SPEED_10G); 246 break; 247 248 case ETHER_STAT_CAP_1000FDX: 249 *val = !!(lc->supported & FW_PORT_CAP_SPEED_1G); 250 break; 251 252 case ETHER_STAT_CAP_1000HDX: 253 return (ENOTSUP); 254 255 case ETHER_STAT_CAP_100FDX: 256 *val = !!(lc->supported & FW_PORT_CAP_SPEED_100M); 257 break; 258 259 case ETHER_STAT_CAP_100HDX: 260 return (ENOTSUP); 261 262 case ETHER_STAT_CAP_10FDX: 263 case ETHER_STAT_CAP_10HDX: 264 return (ENOTSUP); 265 266 case ETHER_STAT_CAP_ASMPAUSE: 267 *val = 0; 268 break; 269 270 case ETHER_STAT_CAP_PAUSE: 271 *val = 1; 272 break; 273 274 case ETHER_STAT_CAP_AUTONEG: 275 *val = !!(lc->supported & FW_PORT_CAP_ANEG); 276 break; 277 278 /* 279 * We have set flow control configuration based on tx_pause and rx_pause 280 * values supported through ndd. Now, we need to translate the settings 281 * we have in link_config structure to adv_cap_asmpause and 282 * adv_cap_pause. 283 * 284 * There are 4 combinations possible and the translation is as below: 285 * tx_pause = 0 => We don't send pause frames during Rx congestion 286 * tx_pause = 1 => We send pause frames during Rx congestion 287 * rx_pause = 0 => We ignore received pause frames 288 * rx_pause = 1 => We pause transmission when we receive pause frames 289 * 290 * +----------------------------+----------------------------------+ 291 * | tx_pause | rx_pause | adv_cap_asmpause | adv_cap_pause | 292 * +-------------------------+-------------------------------------+ 293 * | 0 | 0 | 0 | 0 | 294 * | 0 | 1 | 1 | 0 | 295 * | 1 | 0 | 1 | 1 | 296 * | 1 | 1 | 0 | 1 | 297 * +----------------------------+----------------------------------+ 298 */ 299 300 /* Advertised asymmetric pause capability */ 301 case ETHER_STAT_ADV_CAP_ASMPAUSE: 302 *val = (((lc->requested_fc & PAUSE_TX) ? 1 : 0) ^ 303 (lc->requested_fc & PAUSE_RX)); 304 break; 305 306 /* Advertised pause capability */ 307 case ETHER_STAT_ADV_CAP_PAUSE: 308 *val = (lc->requested_fc & PAUSE_TX) ? 1 : 0; 309 break; 310 311 case ETHER_STAT_ADV_CAP_100GFDX: 312 *val = !!(lc->advertising & FW_PORT_CAP_SPEED_100G); 313 break; 314 315 case ETHER_STAT_ADV_CAP_40GFDX: 316 *val = !!(lc->advertising & FW_PORT_CAP_SPEED_40G); 317 break; 318 319 case ETHER_STAT_ADV_CAP_25GFDX: 320 *val = !!(lc->advertising & FW_PORT_CAP_SPEED_25G); 321 break; 322 323 case ETHER_STAT_ADV_CAP_10GFDX: 324 *val = !!(lc->advertising & FW_PORT_CAP_SPEED_10G); 325 break; 326 327 case ETHER_STAT_ADV_CAP_1000FDX: 328 *val = !!(lc->advertising & FW_PORT_CAP_SPEED_1G); 329 break; 330 331 case ETHER_STAT_ADV_CAP_AUTONEG: 332 *val = !!(lc->advertising & FW_PORT_CAP_ANEG); 333 break; 334 335 case ETHER_STAT_ADV_CAP_1000HDX: 336 case ETHER_STAT_ADV_CAP_100FDX: 337 case ETHER_STAT_ADV_CAP_100HDX: 338 case ETHER_STAT_ADV_CAP_10FDX: 339 case ETHER_STAT_ADV_CAP_10HDX: 340 return (ENOTSUP); /* TODO */ 341 342 343 case ETHER_STAT_LP_CAP_100GFDX: 344 *val = !!(lc->lp_advertising & FW_PORT_CAP_SPEED_100G); 345 break; 346 347 case ETHER_STAT_LP_CAP_40GFDX: 348 *val = !!(lc->lp_advertising & FW_PORT_CAP_SPEED_40G); 349 break; 350 351 case ETHER_STAT_LP_CAP_25GFDX: 352 *val = !!(lc->lp_advertising & FW_PORT_CAP_SPEED_25G); 353 break; 354 355 case ETHER_STAT_LP_CAP_10GFDX: 356 *val = !!(lc->lp_advertising & FW_PORT_CAP_SPEED_10G); 357 break; 358 359 case ETHER_STAT_LP_CAP_1000FDX: 360 *val = !!(lc->lp_advertising & FW_PORT_CAP_SPEED_1G); 361 break; 362 363 case ETHER_STAT_LP_CAP_AUTONEG: 364 *val = !!(lc->lp_advertising & FW_PORT_CAP_ANEG); 365 break; 366 367 case ETHER_STAT_LP_CAP_1000HDX: 368 case ETHER_STAT_LP_CAP_100FDX: 369 case ETHER_STAT_LP_CAP_100HDX: 370 case ETHER_STAT_LP_CAP_10FDX: 371 case ETHER_STAT_LP_CAP_10HDX: 372 case ETHER_STAT_LP_CAP_ASMPAUSE: 373 case ETHER_STAT_LP_CAP_PAUSE: 374 return (ENOTSUP); 375 376 case ETHER_STAT_LINK_ASMPAUSE: 377 *val = 0; 378 break; 379 380 case ETHER_STAT_LINK_PAUSE: 381 *val = 1; 382 break; 383 384 case ETHER_STAT_LINK_AUTONEG: 385 *val = lc->autoneg == AUTONEG_ENABLE; 386 break; 387 388 case ETHER_STAT_LINK_DUPLEX: 389 if (lc->link_ok != 0) 390 *val = LINK_DUPLEX_FULL; 391 else 392 *val = LINK_DUPLEX_UNKNOWN; 393 break; 394 395 default: 396 #ifdef DEBUG 397 cxgb_printf(pi->dip, CE_NOTE, "stat %d not implemented.", stat); 398 #endif 399 return (ENOTSUP); 400 } 401 #undef GET_STAT 402 403 return (0); 404 } 405 406 static int 407 t4_mc_start(void *arg) 408 { 409 struct port_info *pi = arg; 410 int rc; 411 412 rc = begin_synchronized_op(pi, 0, 1); 413 if (rc != 0) 414 return (rc); 415 rc = t4_init_synchronized(pi); 416 end_synchronized_op(pi, 0); 417 418 return (rc); 419 } 420 421 static void 422 t4_mc_stop(void *arg) 423 { 424 struct port_info *pi = arg; 425 426 while (begin_synchronized_op(pi, 0, 1) != 0) 427 continue; 428 (void) t4_uninit_synchronized(pi); 429 end_synchronized_op(pi, 0); 430 } 431 432 static int 433 t4_mc_setpromisc(void *arg, boolean_t on) 434 { 435 struct port_info *pi = arg; 436 struct adapter *sc = pi->adapter; 437 int rc; 438 439 rc = begin_synchronized_op(pi, 1, 1); 440 if (rc != 0) 441 return (rc); 442 rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, -1, on ? 1 : 0, -1, -1, -1, 443 false); 444 end_synchronized_op(pi, 1); 445 446 return (rc); 447 } 448 449 /* 450 * TODO: Starts failing as soon as the 336 entry table fills up. Need to use 451 * hash in that case. 452 */ 453 static int 454 t4_mc_multicst(void *arg, boolean_t add, const uint8_t *mcaddr) 455 { 456 struct port_info *pi = arg; 457 struct adapter *sc = pi->adapter; 458 struct fw_vi_mac_cmd c; 459 int len16, rc; 460 461 len16 = howmany(sizeof (c.op_to_viid) + sizeof (c.freemacs_to_len16) + 462 sizeof (c.u.exact[0]), 16); 463 c.op_to_viid = htonl(V_FW_CMD_OP(FW_VI_MAC_CMD) | F_FW_CMD_REQUEST | 464 F_FW_CMD_WRITE | V_FW_VI_MAC_CMD_VIID(pi->viid)); 465 c.freemacs_to_len16 = htonl(V_FW_CMD_LEN16(len16)); 466 c.u.exact[0].valid_to_idx = htons(F_FW_VI_MAC_CMD_VALID | 467 V_FW_VI_MAC_CMD_IDX(add ? FW_VI_MAC_ADD_MAC : 468 FW_VI_MAC_MAC_BASED_FREE)); 469 bcopy(mcaddr, &c.u.exact[0].macaddr, ETHERADDRL); 470 471 rc = begin_synchronized_op(pi, 1, 1); 472 if (rc != 0) 473 return (rc); 474 rc = -t4_wr_mbox_meat(sc, sc->mbox, &c, len16 * 16, &c, true); 475 end_synchronized_op(pi, 1); 476 if (rc != 0) 477 return (rc); 478 #ifdef DEBUG 479 /* 480 * TODO: Firmware doesn't seem to return the correct index on removal 481 * (it gives back 0x3fd FW_VI_MAC_MAC_BASED_FREE unchanged. Remove this 482 * code once it is fixed. 483 */ 484 else { 485 uint16_t idx; 486 487 idx = G_FW_VI_MAC_CMD_IDX(ntohs(c.u.exact[0].valid_to_idx)); 488 cxgb_printf(pi->dip, CE_NOTE, 489 "%02x:%02x:%02x:%02x:%02x:%02x %s %d", mcaddr[0], 490 mcaddr[1], mcaddr[2], mcaddr[3], mcaddr[4], mcaddr[5], 491 add ? "added at index" : "removed from index", idx); 492 } 493 #endif 494 495 return (0); 496 } 497 498 int 499 t4_mc_unicst(void *arg, const uint8_t *ucaddr) 500 { 501 struct port_info *pi = arg; 502 struct adapter *sc = pi->adapter; 503 int rc; 504 505 if (ucaddr == NULL) 506 return (EINVAL); 507 508 rc = begin_synchronized_op(pi, 1, 1); 509 if (rc != 0) 510 return (rc); 511 512 /* We will support adding only one mac address */ 513 if (pi->adapter->props.multi_rings && pi->macaddr_cnt) { 514 end_synchronized_op(pi, 1); 515 return (ENOSPC); 516 } 517 rc = t4_change_mac(sc, sc->mbox, pi->viid, pi->xact_addr_filt, ucaddr, 518 true, true); 519 if (rc < 0) 520 rc = -rc; 521 else { 522 pi->macaddr_cnt++; 523 pi->xact_addr_filt = rc; 524 rc = 0; 525 } 526 end_synchronized_op(pi, 1); 527 528 return (rc); 529 } 530 531 int 532 t4_addmac(void *arg, const uint8_t *ucaddr) 533 { 534 return (t4_mc_unicst(arg, ucaddr)); 535 } 536 537 static int 538 t4_remmac(void *arg, const uint8_t *mac_addr) 539 { 540 struct port_info *pi = arg; 541 int rc; 542 543 rc = begin_synchronized_op(pi, 1, 1); 544 if (rc != 0) 545 return (rc); 546 547 pi->macaddr_cnt--; 548 end_synchronized_op(pi, 1); 549 550 return (0); 551 } 552 553 /* 554 * Callback funtion for MAC layer to register all groups. 555 */ 556 void 557 t4_fill_group(void *arg, mac_ring_type_t rtype, const int rg_index, 558 mac_group_info_t *infop, mac_group_handle_t gh) 559 { 560 struct port_info *pi = arg; 561 562 switch (rtype) { 563 case MAC_RING_TYPE_RX: { 564 infop->mgi_driver = (mac_group_driver_t)arg; 565 infop->mgi_start = NULL; 566 infop->mgi_stop = NULL; 567 infop->mgi_addmac = t4_addmac; 568 infop->mgi_remmac = t4_remmac; 569 infop->mgi_count = pi->nrxq; 570 break; 571 } 572 case MAC_RING_TYPE_TX: 573 default: 574 ASSERT(0); 575 break; 576 } 577 } 578 579 static int 580 t4_ring_start(mac_ring_driver_t rh, uint64_t mr_gen_num) 581 { 582 struct sge_rxq *rxq = (struct sge_rxq *)rh; 583 584 RXQ_LOCK(rxq); 585 rxq->ring_gen_num = mr_gen_num; 586 RXQ_UNLOCK(rxq); 587 return (0); 588 } 589 590 /* 591 * Enable interrupt on the specificed rx ring. 592 */ 593 int 594 t4_ring_intr_enable(mac_intr_handle_t intrh) 595 { 596 struct sge_rxq *rxq = (struct sge_rxq *)intrh; 597 struct adapter *sc = rxq->port->adapter; 598 struct sge_iq *iq; 599 600 iq = &rxq->iq; 601 RXQ_LOCK(rxq); 602 iq->polling = 0; 603 iq->state = IQS_IDLE; 604 t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS), 605 V_SEINTARM(iq->intr_params) | V_INGRESSQID(iq->cntxt_id)); 606 RXQ_UNLOCK(rxq); 607 return (0); 608 } 609 610 /* 611 * Disable interrupt on the specificed rx ring. 612 */ 613 int 614 t4_ring_intr_disable(mac_intr_handle_t intrh) 615 { 616 struct sge_rxq *rxq = (struct sge_rxq *)intrh; 617 struct sge_iq *iq; 618 619 /* Nothing to be done here wrt interrupt, as it 620 * will not fire, until we write back to 621 * A_SGE_PF_GTS.SEIntArm in t4_ring_intr_enable. 622 */ 623 624 iq = &rxq->iq; 625 RXQ_LOCK(rxq); 626 iq->polling = 1; 627 iq->state = IQS_BUSY; 628 RXQ_UNLOCK(rxq); 629 return (0); 630 } 631 632 mblk_t * 633 t4_poll_ring(void *arg, int n_bytes) 634 { 635 struct sge_rxq *rxq = (struct sge_rxq *)arg; 636 mblk_t *mp = NULL; 637 638 ASSERT(n_bytes >= 0); 639 if (n_bytes == 0) 640 return (NULL); 641 642 RXQ_LOCK(rxq); 643 mp = t4_ring_rx(rxq, n_bytes); 644 RXQ_UNLOCK(rxq); 645 646 return (mp); 647 } 648 649 /* 650 * Retrieve a value for one of the statistics for a particular rx ring 651 */ 652 int 653 t4_rx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val) 654 { 655 struct sge_rxq *rxq = (struct sge_rxq *)rh; 656 657 switch (stat) { 658 case MAC_STAT_RBYTES: 659 *val = rxq->rxbytes; 660 break; 661 662 case MAC_STAT_IPACKETS: 663 *val = rxq->rxpkts; 664 break; 665 666 default: 667 *val = 0; 668 return (ENOTSUP); 669 } 670 671 return (0); 672 } 673 674 /* 675 * Retrieve a value for one of the statistics for a particular tx ring 676 */ 677 int 678 t4_tx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val) 679 { 680 struct sge_txq *txq = (struct sge_txq *)rh; 681 682 switch (stat) { 683 case MAC_STAT_RBYTES: 684 *val = txq->txbytes; 685 break; 686 687 case MAC_STAT_IPACKETS: 688 *val = txq->txpkts; 689 break; 690 691 default: 692 *val = 0; 693 return (ENOTSUP); 694 } 695 696 return (0); 697 } 698 699 /* 700 * Callback funtion for MAC layer to register all rings 701 * for given ring_group, noted by group_index. 702 * Since we have only one group, ring index becomes 703 * absolute index. 704 */ 705 void 706 t4_fill_ring(void *arg, mac_ring_type_t rtype, const int group_index, 707 const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh) 708 { 709 struct port_info *pi = arg; 710 mac_intr_t *mintr; 711 712 switch (rtype) { 713 case MAC_RING_TYPE_RX: { 714 struct sge_rxq *rxq; 715 716 rxq = &pi->adapter->sge.rxq[pi->first_rxq + ring_index]; 717 rxq->ring_handle = rh; 718 719 infop->mri_driver = (mac_ring_driver_t)rxq; 720 infop->mri_start = t4_ring_start; 721 infop->mri_stop = NULL; 722 infop->mri_poll = t4_poll_ring; 723 infop->mri_stat = t4_rx_stat; 724 725 mintr = &infop->mri_intr; 726 mintr->mi_handle = (mac_intr_handle_t)rxq; 727 mintr->mi_enable = t4_ring_intr_enable; 728 mintr->mi_disable = t4_ring_intr_disable; 729 730 break; 731 } 732 case MAC_RING_TYPE_TX: { 733 struct sge_txq *txq = &pi->adapter->sge.txq[pi->first_txq + ring_index]; 734 txq->ring_handle = rh; 735 infop->mri_driver = (mac_ring_driver_t)txq; 736 infop->mri_start = NULL; 737 infop->mri_stop = NULL; 738 infop->mri_tx = t4_eth_tx; 739 infop->mri_stat = t4_tx_stat; 740 break; 741 } 742 default: 743 ASSERT(0); 744 break; 745 } 746 } 747 748 mblk_t * 749 t4_mc_tx(void *arg, mblk_t *m) 750 { 751 struct port_info *pi = arg; 752 struct adapter *sc = pi->adapter; 753 struct sge_txq *txq = &sc->sge.txq[pi->first_txq]; 754 755 return (t4_eth_tx(txq, m)); 756 } 757 758 static int 759 t4_mc_transceiver_info(void *arg, uint_t id, mac_transceiver_info_t *infop) 760 { 761 struct port_info *pi = arg; 762 763 if (id != 0 || infop == NULL) 764 return (EINVAL); 765 766 switch (pi->mod_type) { 767 case FW_PORT_MOD_TYPE_NONE: 768 mac_transceiver_info_set_present(infop, B_FALSE); 769 break; 770 case FW_PORT_MOD_TYPE_NOTSUPPORTED: 771 mac_transceiver_info_set_present(infop, B_TRUE); 772 mac_transceiver_info_set_usable(infop, B_FALSE); 773 break; 774 default: 775 mac_transceiver_info_set_present(infop, B_TRUE); 776 mac_transceiver_info_set_usable(infop, B_TRUE); 777 break; 778 } 779 780 return (0); 781 } 782 783 static int 784 t4_mc_transceiver_read(void *arg, uint_t id, uint_t page, void *bp, 785 size_t nbytes, off_t offset, size_t *nread) 786 { 787 struct port_info *pi = arg; 788 struct adapter *sc = pi->adapter; 789 int rc; 790 size_t i, maxread; 791 /* LINTED: E_FUNC_VAR_UNUSED */ 792 struct fw_ldst_cmd ldst __unused; 793 794 if (id != 0 || bp == NULL || nbytes == 0 || nread == NULL || 795 (page != 0xa0 && page != 0xa2) || offset < 0) 796 return (EINVAL); 797 798 if (nbytes > 256 || offset >= 256 || (offset + nbytes > 256)) 799 return (EINVAL); 800 801 rc = begin_synchronized_op(pi, 0, 1); 802 if (rc != 0) 803 return (rc); 804 805 /* 806 * Firmware has a maximum size that we can read. Don't read more than it 807 * allows. 808 */ 809 maxread = sizeof (ldst.u.i2c.data); 810 for (i = 0; i < nbytes; i += maxread) { 811 size_t toread = MIN(maxread, nbytes - i); 812 rc = -t4_i2c_rd(sc, sc->mbox, pi->port_id, page, offset, toread, 813 bp); 814 if (rc != 0) 815 break; 816 offset += toread; 817 bp = (void *)((uintptr_t)bp + toread); 818 } 819 end_synchronized_op(pi, 0); 820 if (rc == 0) 821 *nread = nbytes; 822 return (rc); 823 } 824 825 static int 826 t4_port_led_set(void *arg, mac_led_mode_t mode, uint_t flags) 827 { 828 struct port_info *pi = arg; 829 struct adapter *sc = pi->adapter; 830 int val, rc; 831 832 if (flags != 0) 833 return (EINVAL); 834 835 switch (mode) { 836 case MAC_LED_DEFAULT: 837 val = 0; 838 break; 839 case MAC_LED_IDENT: 840 val = 0xffff; 841 break; 842 843 default: 844 return (ENOTSUP); 845 } 846 847 rc = begin_synchronized_op(pi, 1, 1); 848 if (rc != 0) 849 return (rc); 850 rc = -t4_identify_port(sc, sc->mbox, pi->viid, val); 851 end_synchronized_op(pi, 1); 852 853 return (rc); 854 } 855 856 static boolean_t 857 t4_mc_getcapab(void *arg, mac_capab_t cap, void *data) 858 { 859 struct port_info *pi = arg; 860 boolean_t status = B_TRUE; 861 mac_capab_transceiver_t *mct; 862 mac_capab_led_t *mcl; 863 864 switch (cap) { 865 case MAC_CAPAB_HCKSUM: 866 if (pi->features & CXGBE_HW_CSUM) { 867 uint32_t *d = data; 868 *d = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM; 869 } else 870 status = B_FALSE; 871 break; 872 873 case MAC_CAPAB_LSO: 874 /* Enabling LSO requires Checksum offloading */ 875 if (pi->features & CXGBE_HW_LSO && 876 pi->features & CXGBE_HW_CSUM) { 877 mac_capab_lso_t *d = data; 878 879 d->lso_flags = LSO_TX_BASIC_TCP_IPV4; 880 d->lso_basic_tcp_ipv4.lso_max = 65535; 881 } else 882 status = B_FALSE; 883 break; 884 885 case MAC_CAPAB_RINGS: { 886 mac_capab_rings_t *cap_rings = data; 887 888 if (!pi->adapter->props.multi_rings) { 889 status = B_FALSE; 890 break; 891 } 892 switch (cap_rings->mr_type) { 893 case MAC_RING_TYPE_RX: 894 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 895 cap_rings->mr_rnum = pi->nrxq; 896 cap_rings->mr_gnum = 1; 897 cap_rings->mr_rget = t4_fill_ring; 898 cap_rings->mr_gget = t4_fill_group; 899 cap_rings->mr_gaddring = NULL; 900 cap_rings->mr_gremring = NULL; 901 break; 902 case MAC_RING_TYPE_TX: 903 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 904 cap_rings->mr_rnum = pi->ntxq; 905 cap_rings->mr_gnum = 0; 906 cap_rings->mr_rget = t4_fill_ring; 907 cap_rings->mr_gget = NULL; 908 break; 909 } 910 break; 911 } 912 913 case MAC_CAPAB_TRANSCEIVER: 914 mct = data; 915 916 mct->mct_flags = 0; 917 mct->mct_ntransceivers = 1; 918 mct->mct_info = t4_mc_transceiver_info; 919 mct->mct_read = t4_mc_transceiver_read; 920 break; 921 case MAC_CAPAB_LED: 922 mcl = data; 923 mcl->mcl_flags = 0; 924 mcl->mcl_modes = MAC_LED_DEFAULT | MAC_LED_IDENT; 925 mcl->mcl_set = t4_port_led_set; 926 break; 927 928 default: 929 status = B_FALSE; /* cap not supported */ 930 } 931 932 return (status); 933 } 934 935 /* ARGSUSED */ 936 static int 937 t4_mc_setprop(void *arg, const char *name, mac_prop_id_t id, uint_t size, 938 const void *val) 939 { 940 struct port_info *pi = arg; 941 struct adapter *sc = pi->adapter; 942 struct link_config lc_copy, *lc = &pi->link_cfg; 943 uint8_t v8 = *(uint8_t *)val; 944 uint32_t v32 = *(uint32_t *)val; 945 int old, new = 0, relink = 0, rx_mode = 0, rc = 0; 946 link_flowctrl_t fc; 947 948 /* 949 * Save a copy of link_config. This can be used to restore link_config 950 * if t4_link_l1cfg() fails. 951 */ 952 bcopy(lc, &lc_copy, sizeof (struct link_config)); 953 954 switch (id) { 955 case MAC_PROP_AUTONEG: 956 if (lc->supported & FW_PORT_CAP_ANEG) { 957 old = lc->autoneg; 958 new = v8 ? AUTONEG_ENABLE : AUTONEG_DISABLE; 959 if (old != new) { 960 /* LINTED: E_CONSTANT_CONDITION */ 961 lc->autoneg = new; 962 relink = 1; 963 if (new == AUTONEG_DISABLE) { 964 /* Only 100M is available */ 965 lc->requested_speed = 966 FW_PORT_CAP_SPEED_100M; 967 lc->advertising = 968 FW_PORT_CAP_SPEED_100M; 969 } else { 970 /* 971 * Advertise autonegotiation capability 972 * along with supported speeds 973 */ 974 lc->advertising |= (FW_PORT_CAP_ANEG | 975 (lc->supported & 976 (FW_PORT_CAP_SPEED_100M | 977 FW_PORT_CAP_SPEED_1G))); 978 lc->requested_speed = 0; 979 } 980 } 981 } else 982 rc = ENOTSUP; 983 break; 984 985 case MAC_PROP_MTU: 986 if (v32 < 46 || v32 > MAX_MTU) { 987 rc = EINVAL; 988 } else if (v32 != pi->mtu) { 989 pi->mtu = v32; 990 (void) mac_maxsdu_update(pi->mh, v32); 991 rx_mode = 1; 992 } 993 994 break; 995 996 case MAC_PROP_FLOWCTRL: 997 fc = *(link_flowctrl_t *)val; 998 old = lc->requested_fc & (PAUSE_TX | PAUSE_RX); 999 1000 if (fc == LINK_FLOWCTRL_BI) 1001 new = (PAUSE_TX | PAUSE_RX); 1002 else if (fc == LINK_FLOWCTRL_TX) 1003 new = PAUSE_TX; 1004 else if (fc == LINK_FLOWCTRL_RX) 1005 new = PAUSE_RX; 1006 1007 if (new != old) { 1008 lc->requested_fc &= ~(PAUSE_TX | PAUSE_RX); 1009 lc->requested_fc |= new; 1010 relink = 1; 1011 } 1012 break; 1013 1014 case MAC_PROP_EN_10GFDX_CAP: 1015 if (lc->supported & FW_PORT_CAP_ANEG && is_10G_port(pi)) { 1016 old = lc->advertising & FW_PORT_CAP_SPEED_10G; 1017 new = v8 ? FW_PORT_CAP_SPEED_10G : 0; 1018 if (new != old) { 1019 lc->advertising &= ~FW_PORT_CAP_SPEED_10G; 1020 lc->advertising |= new; 1021 relink = 1; 1022 } 1023 } else 1024 rc = ENOTSUP; 1025 1026 break; 1027 1028 case MAC_PROP_EN_1000FDX_CAP: 1029 /* Forced 1G */ 1030 if (lc->autoneg == AUTONEG_ENABLE) { 1031 old = lc->advertising & FW_PORT_CAP_SPEED_1G; 1032 new = v8 ? FW_PORT_CAP_SPEED_1G : 0; 1033 1034 if (old != new) { 1035 lc->advertising &= ~FW_PORT_CAP_SPEED_1G; 1036 lc->advertising |= new; 1037 relink = 1; 1038 } 1039 } else 1040 rc = ENOTSUP; 1041 break; 1042 1043 case MAC_PROP_EN_100FDX_CAP: 1044 /* Forced 100M */ 1045 if (lc->autoneg == AUTONEG_ENABLE) { 1046 old = lc->advertising & FW_PORT_CAP_SPEED_100M; 1047 new = v8 ? FW_PORT_CAP_SPEED_100M : 0; 1048 if (old != new) { 1049 lc->advertising &= ~FW_PORT_CAP_SPEED_100M; 1050 lc->advertising |= new; 1051 relink = 1; 1052 } 1053 } else 1054 rc = ENOTSUP; 1055 break; 1056 1057 case MAC_PROP_PRIVATE: 1058 rc = setprop(pi, name, val); 1059 break; 1060 1061 default: 1062 rc = ENOTSUP; 1063 } 1064 1065 if (isset(&sc->open_device_map, pi->port_id) != 0) { 1066 if (relink != 0) { 1067 t4_os_link_changed(pi->adapter, pi->port_id, 0); 1068 rc = begin_synchronized_op(pi, 1, 1); 1069 if (rc != 0) 1070 return (rc); 1071 rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, 1072 &pi->link_cfg); 1073 end_synchronized_op(pi, 1); 1074 if (rc != 0) { 1075 cxgb_printf(pi->dip, CE_WARN, 1076 "start_link failed:%d", rc); 1077 1078 /* Restore link_config */ 1079 bcopy(&lc_copy, lc, 1080 sizeof (struct link_config)); 1081 } 1082 } 1083 1084 if (rx_mode != 0) { 1085 rc = begin_synchronized_op(pi, 1, 1); 1086 if (rc != 0) 1087 return (rc); 1088 rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, v32, -1, 1089 -1, -1, -1, false); 1090 end_synchronized_op(pi, 1); 1091 if (rc != 0) { 1092 cxgb_printf(pi->dip, CE_WARN, 1093 "set_rxmode failed: %d", rc); 1094 } 1095 } 1096 } 1097 1098 return (rc); 1099 } 1100 1101 static int 1102 t4_mc_getprop(void *arg, const char *name, mac_prop_id_t id, uint_t size, 1103 void *val) 1104 { 1105 struct port_info *pi = arg; 1106 struct link_config *lc = &pi->link_cfg; 1107 uint8_t *u = val; 1108 1109 switch (id) { 1110 case MAC_PROP_DUPLEX: 1111 *(link_duplex_t *)val = lc->link_ok ? LINK_DUPLEX_FULL : 1112 LINK_DUPLEX_UNKNOWN; 1113 break; 1114 1115 case MAC_PROP_SPEED: 1116 if (lc->link_ok != 0) { 1117 *(uint64_t *)val = lc->speed; 1118 *(uint64_t *)val *= 1000000; 1119 } else 1120 *(uint64_t *)val = 0; 1121 break; 1122 1123 case MAC_PROP_STATUS: 1124 *(link_state_t *)val = lc->link_ok ? LINK_STATE_UP : 1125 LINK_STATE_DOWN; 1126 break; 1127 1128 case MAC_PROP_AUTONEG: 1129 *u = lc->autoneg == AUTONEG_ENABLE; 1130 break; 1131 1132 case MAC_PROP_MTU: 1133 *(uint32_t *)val = pi->mtu; 1134 break; 1135 1136 case MAC_PROP_FLOWCTRL: 1137 if ((lc->requested_fc & (PAUSE_TX | PAUSE_RX)) == 1138 (PAUSE_TX | PAUSE_RX)) 1139 *(link_flowctrl_t *)val = LINK_FLOWCTRL_BI; 1140 else if (lc->requested_fc & PAUSE_TX) 1141 *(link_flowctrl_t *)val = LINK_FLOWCTRL_TX; 1142 else if (lc->requested_fc & PAUSE_RX) 1143 *(link_flowctrl_t *)val = LINK_FLOWCTRL_RX; 1144 else 1145 *(link_flowctrl_t *)val = LINK_FLOWCTRL_NONE; 1146 break; 1147 1148 case MAC_PROP_ADV_100GFDX_CAP: 1149 case MAC_PROP_EN_100GFDX_CAP: 1150 *u = !!(lc->advertising & FW_PORT_CAP_SPEED_100G); 1151 break; 1152 1153 case MAC_PROP_ADV_40GFDX_CAP: 1154 case MAC_PROP_EN_40GFDX_CAP: 1155 *u = !!(lc->advertising & FW_PORT_CAP_SPEED_40G); 1156 break; 1157 1158 case MAC_PROP_ADV_25GFDX_CAP: 1159 case MAC_PROP_EN_25GFDX_CAP: 1160 *u = !!(lc->advertising & FW_PORT_CAP_SPEED_25G); 1161 break; 1162 1163 case MAC_PROP_ADV_10GFDX_CAP: 1164 case MAC_PROP_EN_10GFDX_CAP: 1165 *u = !!(lc->advertising & FW_PORT_CAP_SPEED_10G); 1166 break; 1167 1168 case MAC_PROP_ADV_1000FDX_CAP: 1169 case MAC_PROP_EN_1000FDX_CAP: 1170 *u = !!(lc->advertising & FW_PORT_CAP_SPEED_1G); 1171 break; 1172 1173 case MAC_PROP_ADV_100FDX_CAP: 1174 case MAC_PROP_EN_100FDX_CAP: 1175 *u = !!(lc->advertising & FW_PORT_CAP_SPEED_100M); 1176 break; 1177 1178 case MAC_PROP_PRIVATE: 1179 return (getprop(pi, name, size, val)); 1180 1181 default: 1182 return (ENOTSUP); 1183 } 1184 1185 return (0); 1186 } 1187 1188 static void 1189 t4_mc_propinfo(void *arg, const char *name, mac_prop_id_t id, 1190 mac_prop_info_handle_t ph) 1191 { 1192 struct port_info *pi = arg; 1193 struct link_config *lc = &pi->link_cfg; 1194 1195 switch (id) { 1196 case MAC_PROP_DUPLEX: 1197 case MAC_PROP_SPEED: 1198 case MAC_PROP_STATUS: 1199 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1200 break; 1201 1202 case MAC_PROP_AUTONEG: 1203 if (lc->supported & FW_PORT_CAP_ANEG) 1204 mac_prop_info_set_default_uint8(ph, 1); 1205 else 1206 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1207 break; 1208 1209 case MAC_PROP_MTU: 1210 mac_prop_info_set_range_uint32(ph, 46, MAX_MTU); 1211 break; 1212 1213 case MAC_PROP_FLOWCTRL: 1214 mac_prop_info_set_default_link_flowctrl(ph, LINK_FLOWCTRL_BI); 1215 break; 1216 1217 case MAC_PROP_EN_10GFDX_CAP: 1218 if (lc->supported & FW_PORT_CAP_ANEG && 1219 lc->supported & FW_PORT_CAP_SPEED_10G) 1220 mac_prop_info_set_default_uint8(ph, 1); 1221 else 1222 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1223 break; 1224 1225 case MAC_PROP_EN_1000FDX_CAP: 1226 if (lc->supported & FW_PORT_CAP_ANEG && 1227 lc->supported & FW_PORT_CAP_SPEED_1G) 1228 mac_prop_info_set_default_uint8(ph, 1); 1229 else 1230 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1231 break; 1232 1233 case MAC_PROP_EN_100FDX_CAP: 1234 if (lc->supported & FW_PORT_CAP_ANEG && 1235 lc->supported & FW_PORT_CAP_SPEED_100M) 1236 mac_prop_info_set_default_uint8(ph, 1); 1237 else 1238 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1239 break; 1240 1241 case MAC_PROP_ADV_10GFDX_CAP: 1242 case MAC_PROP_ADV_1000FDX_CAP: 1243 case MAC_PROP_ADV_100FDX_CAP: 1244 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1245 break; 1246 1247 case MAC_PROP_PRIVATE: 1248 propinfo(pi, name, ph); 1249 break; 1250 1251 default: 1252 break; 1253 } 1254 } 1255 1256 static int 1257 begin_synchronized_op(struct port_info *pi, int hold, int waitok) 1258 { 1259 struct adapter *sc = pi->adapter; 1260 int rc = 0; 1261 1262 ADAPTER_LOCK(sc); 1263 while (!IS_DOOMED(pi) && IS_BUSY(sc)) { 1264 if (!waitok) { 1265 rc = EBUSY; 1266 goto failed; 1267 } else if (cv_wait_sig(&sc->cv, &sc->lock) == 0) { 1268 rc = EINTR; 1269 goto failed; 1270 } 1271 } 1272 if (IS_DOOMED(pi) != 0) { /* shouldn't happen on Solaris */ 1273 rc = ENXIO; 1274 goto failed; 1275 } 1276 ASSERT(!IS_BUSY(sc)); 1277 /* LINTED: E_CONSTANT_CONDITION */ 1278 SET_BUSY(sc); 1279 1280 if (!hold) 1281 ADAPTER_UNLOCK(sc); 1282 1283 return (0); 1284 failed: 1285 ADAPTER_UNLOCK(sc); 1286 return (rc); 1287 } 1288 1289 static void 1290 end_synchronized_op(struct port_info *pi, int held) 1291 { 1292 struct adapter *sc = pi->adapter; 1293 1294 if (!held) 1295 ADAPTER_LOCK(sc); 1296 1297 ADAPTER_LOCK_ASSERT_OWNED(sc); 1298 ASSERT(IS_BUSY(sc)); 1299 /* LINTED: E_CONSTANT_CONDITION */ 1300 CLR_BUSY(sc); 1301 cv_signal(&sc->cv); 1302 ADAPTER_UNLOCK(sc); 1303 } 1304 1305 static int 1306 t4_init_synchronized(struct port_info *pi) 1307 { 1308 struct adapter *sc = pi->adapter; 1309 int rc = 0; 1310 1311 ADAPTER_LOCK_ASSERT_NOTOWNED(sc); 1312 1313 if (isset(&sc->open_device_map, pi->port_id) != 0) 1314 return (0); /* already running */ 1315 1316 if (!(sc->flags & FULL_INIT_DONE) && 1317 ((rc = adapter_full_init(sc)) != 0)) 1318 return (rc); /* error message displayed already */ 1319 1320 if (!(pi->flags & PORT_INIT_DONE)) { 1321 rc = port_full_init(pi); 1322 if (rc != 0) 1323 return (rc); /* error message displayed already */ 1324 } else 1325 enable_port_queues(pi); 1326 1327 rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, pi->mtu, 0, 0, 1, 0, false); 1328 if (rc != 0) { 1329 cxgb_printf(pi->dip, CE_WARN, "set_rxmode failed: %d", rc); 1330 goto done; 1331 } 1332 rc = t4_change_mac(sc, sc->mbox, pi->viid, pi->xact_addr_filt, 1333 pi->hw_addr, true, true); 1334 if (rc < 0) { 1335 cxgb_printf(pi->dip, CE_WARN, "change_mac failed: %d", rc); 1336 rc = -rc; 1337 goto done; 1338 } else 1339 /* LINTED: E_ASSIGN_NARROW_CONV */ 1340 pi->xact_addr_filt = rc; 1341 1342 rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, &pi->link_cfg); 1343 if (rc != 0) { 1344 cxgb_printf(pi->dip, CE_WARN, "start_link failed: %d", rc); 1345 goto done; 1346 } 1347 1348 rc = -t4_enable_vi(sc, sc->mbox, pi->viid, true, true); 1349 if (rc != 0) { 1350 cxgb_printf(pi->dip, CE_WARN, "enable_vi failed: %d", rc); 1351 goto done; 1352 } 1353 1354 /* all ok */ 1355 setbit(&sc->open_device_map, pi->port_id); 1356 done: 1357 if (rc != 0) 1358 (void) t4_uninit_synchronized(pi); 1359 1360 return (rc); 1361 } 1362 1363 /* 1364 * Idempotent. 1365 */ 1366 static int 1367 t4_uninit_synchronized(struct port_info *pi) 1368 { 1369 struct adapter *sc = pi->adapter; 1370 int rc; 1371 1372 ADAPTER_LOCK_ASSERT_NOTOWNED(sc); 1373 1374 /* 1375 * Disable the VI so that all its data in either direction is discarded 1376 * by the MPS. Leave everything else (the queues, interrupts, and 1Hz 1377 * tick) intact as the TP can deliver negative advice or data that it's 1378 * holding in its RAM (for an offloaded connection) even after the VI is 1379 * disabled. 1380 */ 1381 rc = -t4_enable_vi(sc, sc->mbox, pi->viid, false, false); 1382 if (rc != 0) { 1383 cxgb_printf(pi->dip, CE_WARN, "disable_vi failed: %d", rc); 1384 return (rc); 1385 } 1386 1387 disable_port_queues(pi); 1388 1389 clrbit(&sc->open_device_map, pi->port_id); 1390 1391 pi->link_cfg.link_ok = 0; 1392 pi->link_cfg.speed = 0; 1393 mac_link_update(pi->mh, LINK_STATE_UNKNOWN); 1394 1395 return (0); 1396 } 1397 1398 static void 1399 propinfo(struct port_info *pi, const char *name, mac_prop_info_handle_t ph) 1400 { 1401 struct adapter *sc = pi->adapter; 1402 struct driver_properties *p = &sc->props; 1403 struct link_config *lc = &pi->link_cfg; 1404 int v; 1405 char str[16]; 1406 1407 if (strcmp(name, T4PROP_TMR_IDX) == 0) 1408 v = is_10G_port(pi) ? p->tmr_idx_10g : p->tmr_idx_1g; 1409 else if (strcmp(name, T4PROP_PKTC_IDX) == 0) 1410 v = is_10G_port(pi) ? p->pktc_idx_10g : p->pktc_idx_1g; 1411 else if (strcmp(name, T4PROP_HW_CSUM) == 0) 1412 v = (pi->features & CXGBE_HW_CSUM) ? 1 : 0; 1413 else if (strcmp(name, T4PROP_HW_LSO) == 0) 1414 v = (pi->features & CXGBE_HW_LSO) ? 1 : 0; 1415 else if (strcmp(name, T4PROP_TX_PAUSE) == 0) 1416 v = (lc->fc & PAUSE_TX) ? 1 : 0; 1417 else if (strcmp(name, T4PROP_RX_PAUSE) == 0) 1418 v = (lc->fc & PAUSE_RX) ? 1 : 0; 1419 #if MAC_VERSION == 1 1420 else if (strcmp(name, T4PROP_MTU) == 0) 1421 v = ETHERMTU; 1422 #endif 1423 else 1424 return; 1425 1426 (void) snprintf(str, sizeof (str), "%d", v); 1427 mac_prop_info_set_default_str(ph, str); 1428 } 1429 1430 static int 1431 getprop(struct port_info *pi, const char *name, uint_t size, void *val) 1432 { 1433 struct link_config *lc = &pi->link_cfg; 1434 int v; 1435 1436 if (strcmp(name, T4PROP_TMR_IDX) == 0) 1437 v = pi->tmr_idx; 1438 else if (strcmp(name, T4PROP_PKTC_IDX) == 0) 1439 v = pi->pktc_idx; 1440 else if (strcmp(name, T4PROP_HW_CSUM) == 0) 1441 v = (pi->features & CXGBE_HW_CSUM) ? 1 : 0; 1442 else if (strcmp(name, T4PROP_HW_LSO) == 0) 1443 v = (pi->features & CXGBE_HW_LSO) ? 1 : 0; 1444 else if (strcmp(name, T4PROP_TX_PAUSE) == 0) 1445 v = (lc->fc & PAUSE_TX) ? 1 : 0; 1446 else if (strcmp(name, T4PROP_RX_PAUSE) == 0) 1447 v = (lc->fc & PAUSE_RX) ? 1 : 0; 1448 #if MAC_VERSION == 1 1449 else if (strcmp(name, T4PROP_MTU) == 0) 1450 v = pi->mtu; 1451 #endif 1452 else 1453 return (ENOTSUP); 1454 1455 (void) snprintf(val, size, "%d", v); 1456 return (0); 1457 } 1458 1459 static int 1460 setprop(struct port_info *pi, const char *name, const void *val) 1461 { 1462 struct adapter *sc = pi->adapter; 1463 long v; 1464 int i, rc = 0, relink = 0, rx_mode = 0; 1465 struct sge_rxq *rxq; 1466 struct link_config lc_old, *lc = &pi->link_cfg; 1467 1468 /* 1469 * Save a copy of link_config. This can be used to restore link_config 1470 * if t4_link_l1cfg() fails. 1471 */ 1472 bcopy(lc, &lc_old, sizeof (struct link_config)); 1473 1474 (void) ddi_strtol(val, NULL, 0, &v); 1475 1476 if (strcmp(name, T4PROP_TMR_IDX) == 0) { 1477 if (v < 0 || v >= SGE_NTIMERS) 1478 return (EINVAL); 1479 if (v == pi->tmr_idx) 1480 return (0); 1481 1482 /* LINTED: E_ASSIGN_NARROW_CONV */ 1483 pi->tmr_idx = v; 1484 for_each_rxq(pi, i, rxq) { 1485 rxq->iq.intr_params = V_QINTR_TIMER_IDX(v) | 1486 V_QINTR_CNT_EN(pi->pktc_idx >= 0); 1487 } 1488 1489 } else if (strcmp(name, T4PROP_PKTC_IDX) == 0) { 1490 if (v >= SGE_NCOUNTERS) 1491 return (EINVAL); 1492 if (v == pi->pktc_idx || (v < 0 && pi->pktc_idx == -1)) 1493 return (0); 1494 1495 /* LINTED: E_ASSIGN_NARROW_CONV */ 1496 pi->pktc_idx = v < 0 ? -1 : v; 1497 for_each_rxq(pi, i, rxq) { 1498 rxq->iq.intr_params = V_QINTR_TIMER_IDX(pi->tmr_idx) | 1499 /* takes effect right away */ 1500 V_QINTR_CNT_EN(v >= 0); 1501 /* LINTED: E_ASSIGN_NARROW_CONV */ 1502 rxq->iq.intr_pktc_idx = v; /* this needs fresh plumb */ 1503 } 1504 } else if (strcmp(name, T4PROP_HW_CSUM) == 0) { 1505 if (v != 0 && v != 1) 1506 return (EINVAL); 1507 if (v == 1) 1508 pi->features |= CXGBE_HW_CSUM; 1509 else 1510 pi->features &= ~CXGBE_HW_CSUM; 1511 } else if (strcmp(name, T4PROP_HW_LSO) == 0) { 1512 if (v != 0 && v != 1) 1513 return (EINVAL); 1514 if (v == 1) 1515 pi->features |= CXGBE_HW_LSO; 1516 else 1517 pi->features &= ~CXGBE_HW_LSO; 1518 } else if (strcmp(name, T4PROP_TX_PAUSE) == 0) { 1519 if (v != 0 && v != 1) 1520 return (EINVAL); 1521 1522 if (v != 0) 1523 lc->requested_fc |= PAUSE_TX; 1524 else 1525 lc->requested_fc &= ~PAUSE_TX; 1526 1527 relink = 1; 1528 1529 } else if (strcmp(name, T4PROP_RX_PAUSE) == 0) { 1530 if (v != 0 && v != 1) 1531 return (EINVAL); 1532 1533 if (v != 0) 1534 lc->requested_fc |= PAUSE_RX; 1535 else 1536 lc->requested_fc &= ~PAUSE_RX; 1537 1538 relink = 1; 1539 } 1540 #if MAC_VERSION == 1 1541 else if (strcmp(name, T4PROP_MTU) == 0) { 1542 if (v < 46 || v > MAX_MTU) 1543 return (EINVAL); 1544 if (v == pi->mtu) 1545 return (0); 1546 1547 pi->mtu = (int)v; 1548 (void) mac_maxsdu_update(pi->mh, v); 1549 rx_mode = 1; 1550 } 1551 #endif 1552 else 1553 return (ENOTSUP); 1554 1555 if (!(relink || rx_mode)) 1556 return (0); 1557 1558 /* If we are here, either relink or rx_mode is 1 */ 1559 if (isset(&sc->open_device_map, pi->port_id) != 0) { 1560 if (relink != 0) { 1561 rc = begin_synchronized_op(pi, 1, 1); 1562 if (rc != 0) 1563 return (rc); 1564 rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, lc); 1565 end_synchronized_op(pi, 1); 1566 if (rc != 0) { 1567 cxgb_printf(pi->dip, CE_WARN, 1568 "start_link failed:%d", rc); 1569 /* Restore link_config */ 1570 bcopy(&lc_old, lc, sizeof (struct link_config)); 1571 } 1572 } else if (rx_mode != 0) { 1573 rc = begin_synchronized_op(pi, 1, 1); 1574 if (rc != 0) 1575 return (rc); 1576 rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, v, -1, -1, 1577 -1, -1, false); 1578 end_synchronized_op(pi, 1); 1579 if (rc != 0) { 1580 cxgb_printf(pi->dip, CE_WARN, 1581 "set_rxmode failed: %d", rc); 1582 } 1583 } 1584 return (rc); 1585 } 1586 1587 return (0); 1588 } 1589 1590 void 1591 t4_mc_init(struct port_info *pi) 1592 { 1593 pi->props = t4_priv_props; 1594 } 1595 1596 void 1597 t4_mc_cb_init(struct port_info *pi) 1598 { 1599 if (pi->adapter->props.multi_rings) 1600 pi->mc = &t4_m_ring_callbacks; 1601 else 1602 pi->mc = &t4_m_callbacks; 1603 } 1604 1605 void 1606 t4_os_link_changed(struct adapter *sc, int idx, int link_stat) 1607 { 1608 struct port_info *pi = sc->port[idx]; 1609 1610 mac_link_update(pi->mh, link_stat ? LINK_STATE_UP : LINK_STATE_DOWN); 1611 } 1612 1613 /* ARGSUSED */ 1614 void 1615 t4_mac_rx(struct port_info *pi, struct sge_rxq *rxq, mblk_t *m) 1616 { 1617 mac_rx(pi->mh, NULL, m); 1618 } 1619 1620 void 1621 t4_mac_tx_update(struct port_info *pi, struct sge_txq *txq) 1622 { 1623 if (pi->adapter->props.multi_rings) 1624 mac_tx_ring_update(pi->mh, txq->ring_handle); 1625 else 1626 mac_tx_update(pi->mh); 1627 } 1628