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