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