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 return (ENOTSUP); 463 } 464 #undef GET_STAT 465 466 return (0); 467 } 468 469 static int 470 t4_mc_start(void *arg) 471 { 472 struct port_info *pi = arg; 473 int rc; 474 475 rc = begin_synchronized_op(pi, 0, 1); 476 if (rc != 0) 477 return (rc); 478 rc = t4_init_synchronized(pi); 479 end_synchronized_op(pi, 0); 480 481 return (rc); 482 } 483 484 static void 485 t4_mc_stop(void *arg) 486 { 487 struct port_info *pi = arg; 488 489 while (begin_synchronized_op(pi, 0, 1) != 0) 490 continue; 491 (void) t4_uninit_synchronized(pi); 492 end_synchronized_op(pi, 0); 493 } 494 495 static int 496 t4_mc_setpromisc(void *arg, boolean_t on) 497 { 498 struct port_info *pi = arg; 499 struct adapter *sc = pi->adapter; 500 int rc; 501 502 rc = begin_synchronized_op(pi, 1, 1); 503 if (rc != 0) 504 return (rc); 505 rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, -1, on ? 1 : 0, -1, -1, -1, 506 false); 507 end_synchronized_op(pi, 1); 508 509 return (rc); 510 } 511 512 /* 513 * TODO: Starts failing as soon as the 336 entry table fills up. Need to use 514 * hash in that case. 515 */ 516 static int 517 t4_mc_multicst(void *arg, boolean_t add, const uint8_t *mcaddr) 518 { 519 struct port_info *pi = arg; 520 struct adapter *sc = pi->adapter; 521 struct fw_vi_mac_cmd c; 522 int len16, rc; 523 524 len16 = howmany(sizeof (c.op_to_viid) + sizeof (c.freemacs_to_len16) + 525 sizeof (c.u.exact[0]), 16); 526 c.op_to_viid = htonl(V_FW_CMD_OP(FW_VI_MAC_CMD) | F_FW_CMD_REQUEST | 527 F_FW_CMD_WRITE | V_FW_VI_MAC_CMD_VIID(pi->viid)); 528 c.freemacs_to_len16 = htonl(V_FW_CMD_LEN16(len16)); 529 c.u.exact[0].valid_to_idx = htons(F_FW_VI_MAC_CMD_VALID | 530 V_FW_VI_MAC_CMD_IDX(add ? FW_VI_MAC_ADD_MAC : 531 FW_VI_MAC_MAC_BASED_FREE)); 532 bcopy(mcaddr, &c.u.exact[0].macaddr, ETHERADDRL); 533 534 rc = begin_synchronized_op(pi, 1, 1); 535 if (rc != 0) 536 return (rc); 537 rc = -t4_wr_mbox_meat(sc, sc->mbox, &c, len16 * 16, &c, true); 538 end_synchronized_op(pi, 1); 539 if (rc != 0) 540 return (rc); 541 #ifdef DEBUG 542 /* 543 * TODO: Firmware doesn't seem to return the correct index on removal 544 * (it gives back 0x3fd FW_VI_MAC_MAC_BASED_FREE unchanged. Remove this 545 * code once it is fixed. 546 */ 547 else { 548 uint16_t idx; 549 550 idx = G_FW_VI_MAC_CMD_IDX(ntohs(c.u.exact[0].valid_to_idx)); 551 cxgb_printf(pi->dip, CE_NOTE, 552 "%02x:%02x:%02x:%02x:%02x:%02x %s %d", mcaddr[0], 553 mcaddr[1], mcaddr[2], mcaddr[3], mcaddr[4], mcaddr[5], 554 add ? "added at index" : "removed from index", idx); 555 } 556 #endif 557 558 return (0); 559 } 560 561 int 562 t4_mc_unicst(void *arg, const uint8_t *ucaddr) 563 { 564 struct port_info *pi = arg; 565 struct adapter *sc = pi->adapter; 566 int rc; 567 568 if (ucaddr == NULL) 569 return (EINVAL); 570 571 rc = begin_synchronized_op(pi, 1, 1); 572 if (rc != 0) 573 return (rc); 574 575 /* We will support adding only one mac address */ 576 if (pi->adapter->props.multi_rings && pi->macaddr_cnt) { 577 end_synchronized_op(pi, 1); 578 return (ENOSPC); 579 } 580 rc = t4_change_mac(sc, sc->mbox, pi->viid, pi->xact_addr_filt, ucaddr, 581 true, &pi->smt_idx); 582 if (rc < 0) 583 rc = -rc; 584 else { 585 pi->macaddr_cnt++; 586 pi->xact_addr_filt = rc; 587 rc = 0; 588 } 589 end_synchronized_op(pi, 1); 590 591 return (rc); 592 } 593 594 int 595 t4_addmac(void *arg, const uint8_t *ucaddr) 596 { 597 return (t4_mc_unicst(arg, ucaddr)); 598 } 599 600 static int 601 t4_remmac(void *arg, const uint8_t *mac_addr) 602 { 603 struct port_info *pi = arg; 604 int rc; 605 606 rc = begin_synchronized_op(pi, 1, 1); 607 if (rc != 0) 608 return (rc); 609 610 pi->macaddr_cnt--; 611 end_synchronized_op(pi, 1); 612 613 return (0); 614 } 615 616 /* 617 * Callback funtion for MAC layer to register all groups. 618 */ 619 void 620 t4_fill_group(void *arg, mac_ring_type_t rtype, const int rg_index, 621 mac_group_info_t *infop, mac_group_handle_t gh) 622 { 623 struct port_info *pi = arg; 624 625 switch (rtype) { 626 case MAC_RING_TYPE_RX: { 627 infop->mgi_driver = (mac_group_driver_t)arg; 628 infop->mgi_start = NULL; 629 infop->mgi_stop = NULL; 630 infop->mgi_addmac = t4_addmac; 631 infop->mgi_remmac = t4_remmac; 632 infop->mgi_count = pi->nrxq; 633 break; 634 } 635 case MAC_RING_TYPE_TX: 636 default: 637 ASSERT(0); 638 break; 639 } 640 } 641 642 static int 643 t4_ring_start(mac_ring_driver_t rh, uint64_t mr_gen_num) 644 { 645 struct sge_rxq *rxq = (struct sge_rxq *)rh; 646 647 RXQ_LOCK(rxq); 648 rxq->ring_gen_num = mr_gen_num; 649 RXQ_UNLOCK(rxq); 650 return (0); 651 } 652 653 /* 654 * Enable interrupt on the specificed rx ring. 655 */ 656 int 657 t4_ring_intr_enable(mac_intr_handle_t intrh) 658 { 659 struct sge_rxq *rxq = (struct sge_rxq *)intrh; 660 struct adapter *sc = rxq->port->adapter; 661 struct sge_iq *iq; 662 663 iq = &rxq->iq; 664 RXQ_LOCK(rxq); 665 iq->polling = 0; 666 iq->state = IQS_IDLE; 667 t4_write_reg(sc, MYPF_REG(A_SGE_PF_GTS), 668 V_SEINTARM(iq->intr_params) | V_INGRESSQID(iq->cntxt_id)); 669 RXQ_UNLOCK(rxq); 670 return (0); 671 } 672 673 /* 674 * Disable interrupt on the specificed rx ring. 675 */ 676 int 677 t4_ring_intr_disable(mac_intr_handle_t intrh) 678 { 679 struct sge_rxq *rxq = (struct sge_rxq *)intrh; 680 struct sge_iq *iq; 681 682 /* Nothing to be done here wrt interrupt, as it 683 * will not fire, until we write back to 684 * A_SGE_PF_GTS.SEIntArm in t4_ring_intr_enable. 685 */ 686 687 iq = &rxq->iq; 688 RXQ_LOCK(rxq); 689 iq->polling = 1; 690 iq->state = IQS_BUSY; 691 RXQ_UNLOCK(rxq); 692 return (0); 693 } 694 695 mblk_t * 696 t4_poll_ring(void *arg, int n_bytes) 697 { 698 struct sge_rxq *rxq = (struct sge_rxq *)arg; 699 mblk_t *mp = NULL; 700 701 ASSERT(n_bytes >= 0); 702 if (n_bytes == 0) 703 return (NULL); 704 705 RXQ_LOCK(rxq); 706 mp = t4_ring_rx(rxq, n_bytes); 707 RXQ_UNLOCK(rxq); 708 709 return (mp); 710 } 711 712 /* 713 * Retrieve a value for one of the statistics for a particular rx ring 714 */ 715 int 716 t4_rx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val) 717 { 718 struct sge_rxq *rxq = (struct sge_rxq *)rh; 719 720 switch (stat) { 721 case MAC_STAT_RBYTES: 722 *val = rxq->rxbytes; 723 break; 724 725 case MAC_STAT_IPACKETS: 726 *val = rxq->rxpkts; 727 break; 728 729 default: 730 *val = 0; 731 return (ENOTSUP); 732 } 733 734 return (0); 735 } 736 737 /* 738 * Retrieve a value for one of the statistics for a particular tx ring 739 */ 740 int 741 t4_tx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val) 742 { 743 struct sge_txq *txq = (struct sge_txq *)rh; 744 745 switch (stat) { 746 case MAC_STAT_RBYTES: 747 *val = txq->txbytes; 748 break; 749 750 case MAC_STAT_IPACKETS: 751 *val = txq->txpkts; 752 break; 753 754 default: 755 *val = 0; 756 return (ENOTSUP); 757 } 758 759 return (0); 760 } 761 762 /* 763 * Callback funtion for MAC layer to register all rings 764 * for given ring_group, noted by group_index. 765 * Since we have only one group, ring index becomes 766 * absolute index. 767 */ 768 void 769 t4_fill_ring(void *arg, mac_ring_type_t rtype, const int group_index, 770 const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh) 771 { 772 struct port_info *pi = arg; 773 mac_intr_t *mintr; 774 775 switch (rtype) { 776 case MAC_RING_TYPE_RX: { 777 struct sge_rxq *rxq; 778 779 rxq = &pi->adapter->sge.rxq[pi->first_rxq + ring_index]; 780 rxq->ring_handle = rh; 781 782 infop->mri_driver = (mac_ring_driver_t)rxq; 783 infop->mri_start = t4_ring_start; 784 infop->mri_stop = NULL; 785 infop->mri_poll = t4_poll_ring; 786 infop->mri_stat = t4_rx_stat; 787 788 mintr = &infop->mri_intr; 789 mintr->mi_handle = (mac_intr_handle_t)rxq; 790 mintr->mi_enable = t4_ring_intr_enable; 791 mintr->mi_disable = t4_ring_intr_disable; 792 793 break; 794 } 795 case MAC_RING_TYPE_TX: { 796 struct sge_txq *txq = &pi->adapter->sge.txq[pi->first_txq + ring_index]; 797 txq->ring_handle = rh; 798 infop->mri_driver = (mac_ring_driver_t)txq; 799 infop->mri_start = NULL; 800 infop->mri_stop = NULL; 801 infop->mri_tx = t4_eth_tx; 802 infop->mri_stat = t4_tx_stat; 803 break; 804 } 805 default: 806 ASSERT(0); 807 break; 808 } 809 } 810 811 mblk_t * 812 t4_mc_tx(void *arg, mblk_t *m) 813 { 814 struct port_info *pi = arg; 815 struct adapter *sc = pi->adapter; 816 struct sge_txq *txq = &sc->sge.txq[pi->first_txq]; 817 818 return (t4_eth_tx(txq, m)); 819 } 820 821 static int 822 t4_mc_transceiver_info(void *arg, uint_t id, mac_transceiver_info_t *infop) 823 { 824 struct port_info *pi = arg; 825 826 if (id != 0 || infop == NULL) 827 return (EINVAL); 828 829 switch (pi->mod_type) { 830 case FW_PORT_MOD_TYPE_NONE: 831 mac_transceiver_info_set_present(infop, B_FALSE); 832 break; 833 case FW_PORT_MOD_TYPE_NOTSUPPORTED: 834 mac_transceiver_info_set_present(infop, B_TRUE); 835 mac_transceiver_info_set_usable(infop, B_FALSE); 836 break; 837 default: 838 mac_transceiver_info_set_present(infop, B_TRUE); 839 mac_transceiver_info_set_usable(infop, B_TRUE); 840 break; 841 } 842 843 return (0); 844 } 845 846 static int 847 t4_mc_transceiver_read(void *arg, uint_t id, uint_t page, void *bp, 848 size_t nbytes, off_t offset, size_t *nread) 849 { 850 struct port_info *pi = arg; 851 struct adapter *sc = pi->adapter; 852 int rc; 853 size_t i, maxread; 854 /* LINTED: E_FUNC_VAR_UNUSED */ 855 struct fw_ldst_cmd ldst __unused; 856 857 if (id != 0 || bp == NULL || nbytes == 0 || nread == NULL || 858 (page != 0xa0 && page != 0xa2) || offset < 0) 859 return (EINVAL); 860 861 if (nbytes > 256 || offset >= 256 || (offset + nbytes > 256)) 862 return (EINVAL); 863 864 rc = begin_synchronized_op(pi, 0, 1); 865 if (rc != 0) 866 return (rc); 867 868 /* 869 * Firmware has a maximum size that we can read. Don't read more than it 870 * allows. 871 */ 872 maxread = sizeof (ldst.u.i2c.data); 873 for (i = 0; i < nbytes; i += maxread) { 874 size_t toread = MIN(maxread, nbytes - i); 875 rc = -t4_i2c_rd(sc, sc->mbox, pi->port_id, page, offset, toread, 876 bp); 877 if (rc != 0) 878 break; 879 offset += toread; 880 bp = (void *)((uintptr_t)bp + toread); 881 } 882 end_synchronized_op(pi, 0); 883 if (rc == 0) 884 *nread = nbytes; 885 return (rc); 886 } 887 888 static int 889 t4_port_led_set(void *arg, mac_led_mode_t mode, uint_t flags) 890 { 891 struct port_info *pi = arg; 892 struct adapter *sc = pi->adapter; 893 int val, rc; 894 895 if (flags != 0) 896 return (EINVAL); 897 898 switch (mode) { 899 case MAC_LED_DEFAULT: 900 val = 0; 901 break; 902 case MAC_LED_IDENT: 903 val = 0xffff; 904 break; 905 906 default: 907 return (ENOTSUP); 908 } 909 910 rc = begin_synchronized_op(pi, 1, 1); 911 if (rc != 0) 912 return (rc); 913 rc = -t4_identify_port(sc, sc->mbox, pi->viid, val); 914 end_synchronized_op(pi, 1); 915 916 return (rc); 917 } 918 919 static boolean_t 920 t4_mc_getcapab(void *arg, mac_capab_t cap, void *data) 921 { 922 struct port_info *pi = arg; 923 boolean_t status = B_TRUE; 924 mac_capab_transceiver_t *mct; 925 mac_capab_led_t *mcl; 926 927 switch (cap) { 928 case MAC_CAPAB_HCKSUM: 929 if (pi->features & CXGBE_HW_CSUM) { 930 uint32_t *d = data; 931 *d = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM | 932 HCKSUM_INET_FULL_V6; 933 } else 934 status = B_FALSE; 935 break; 936 937 case MAC_CAPAB_LSO: 938 /* Enabling LSO requires Checksum offloading */ 939 if (pi->features & CXGBE_HW_LSO && 940 pi->features & CXGBE_HW_CSUM) { 941 mac_capab_lso_t *d = data; 942 943 d->lso_flags = LSO_TX_BASIC_TCP_IPV4 | 944 LSO_TX_BASIC_TCP_IPV6; 945 d->lso_basic_tcp_ipv4.lso_max = 65535; 946 d->lso_basic_tcp_ipv6.lso_max = 65535; 947 } else 948 status = B_FALSE; 949 break; 950 951 case MAC_CAPAB_RINGS: { 952 mac_capab_rings_t *cap_rings = data; 953 954 if (!pi->adapter->props.multi_rings) { 955 status = B_FALSE; 956 break; 957 } 958 switch (cap_rings->mr_type) { 959 case MAC_RING_TYPE_RX: 960 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 961 cap_rings->mr_rnum = pi->nrxq; 962 cap_rings->mr_gnum = 1; 963 cap_rings->mr_rget = t4_fill_ring; 964 cap_rings->mr_gget = t4_fill_group; 965 cap_rings->mr_gaddring = NULL; 966 cap_rings->mr_gremring = NULL; 967 break; 968 case MAC_RING_TYPE_TX: 969 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 970 cap_rings->mr_rnum = pi->ntxq; 971 cap_rings->mr_gnum = 0; 972 cap_rings->mr_rget = t4_fill_ring; 973 cap_rings->mr_gget = NULL; 974 break; 975 } 976 break; 977 } 978 979 case MAC_CAPAB_TRANSCEIVER: 980 mct = data; 981 982 mct->mct_flags = 0; 983 mct->mct_ntransceivers = 1; 984 mct->mct_info = t4_mc_transceiver_info; 985 mct->mct_read = t4_mc_transceiver_read; 986 break; 987 case MAC_CAPAB_LED: 988 mcl = data; 989 mcl->mcl_flags = 0; 990 mcl->mcl_modes = MAC_LED_DEFAULT | MAC_LED_IDENT; 991 mcl->mcl_set = t4_port_led_set; 992 break; 993 994 default: 995 status = B_FALSE; /* cap not supported */ 996 } 997 998 return (status); 999 } 1000 1001 static void t4_mac_link_caps_to_flowctrl(fw_port_cap32_t caps, 1002 link_flowctrl_t *fc) 1003 { 1004 u8 pause_tx = 0, pause_rx = 0; 1005 1006 if (caps & FW_PORT_CAP32_FC_TX) 1007 pause_tx = 1; 1008 1009 if (caps & FW_PORT_CAP32_FC_RX) 1010 pause_rx = 1; 1011 1012 if (pause_rx & pause_tx) 1013 *fc = LINK_FLOWCTRL_BI; 1014 else if (pause_tx) 1015 *fc = LINK_FLOWCTRL_TX; 1016 else if (pause_rx) 1017 *fc = LINK_FLOWCTRL_RX; 1018 else 1019 *fc = LINK_FLOWCTRL_NONE; 1020 } 1021 1022 static int t4_mac_flowctrl_to_link_caps(struct port_info *pi, 1023 link_flowctrl_t fc, 1024 fw_port_cap32_t *new_caps) 1025 { 1026 cc_pause_t pause = 0; 1027 1028 switch (fc) { 1029 case LINK_FLOWCTRL_BI: 1030 pause |= PAUSE_TX | PAUSE_RX; 1031 break; 1032 case LINK_FLOWCTRL_TX: 1033 pause |= PAUSE_TX; 1034 break; 1035 case LINK_FLOWCTRL_RX: 1036 pause |= PAUSE_RX; 1037 break; 1038 default: 1039 break; 1040 } 1041 1042 if (pi->link_cfg.admin_caps & FW_PORT_CAP32_ANEG) 1043 pause |= PAUSE_AUTONEG; 1044 1045 return t4_link_set_pause(pi, pause, new_caps); 1046 } 1047 1048 static link_fec_t t4_mac_port_caps_to_fec_cap(fw_port_cap32_t caps) 1049 { 1050 link_fec_t link_fec = 0; 1051 1052 if (caps & FW_PORT_CAP32_FEC_RS) 1053 link_fec |= LINK_FEC_RS; 1054 1055 if (caps & FW_PORT_CAP32_FEC_BASER_RS) 1056 link_fec |= LINK_FEC_BASE_R; 1057 1058 if (caps & FW_PORT_CAP32_FEC_NO_FEC) 1059 link_fec |= LINK_FEC_NONE; 1060 1061 if ((link_fec & (link_fec - 1)) && 1062 !(caps & FW_PORT_CAP32_FORCE_FEC)) 1063 return LINK_FEC_AUTO; 1064 1065 return link_fec; 1066 } 1067 1068 static void t4_mac_admin_caps_to_fec_cap(fw_port_cap32_t caps, 1069 link_fec_t *fec) 1070 { 1071 *fec = t4_mac_port_caps_to_fec_cap(caps); 1072 } 1073 1074 static void t4_mac_link_caps_to_fec_cap(fw_port_cap32_t caps, 1075 link_fec_t *fec) 1076 { 1077 link_fec_t link_fec; 1078 1079 caps &= ~FW_PORT_CAP32_FEC_NO_FEC; 1080 link_fec = t4_mac_port_caps_to_fec_cap(caps); 1081 *fec = link_fec ? link_fec : LINK_FEC_NONE; 1082 } 1083 1084 static int t4_mac_fec_cap_to_link_caps(struct port_info *pi, link_fec_t v, 1085 fw_port_cap32_t *new_caps) 1086 { 1087 cc_fec_t fec = 0; 1088 1089 if (v == LINK_FEC_AUTO) { 1090 fec = FEC_AUTO; 1091 goto out; 1092 } 1093 1094 if (v & LINK_FEC_NONE) { 1095 v &= ~LINK_FEC_NONE; 1096 fec |= FEC_NONE; 1097 } 1098 1099 if (v & LINK_FEC_RS) { 1100 v &= ~LINK_FEC_RS; 1101 fec |= FEC_RS; 1102 } 1103 1104 if (v & LINK_FEC_BASE_R) { 1105 v &= ~LINK_FEC_BASE_R; 1106 fec |= FEC_BASER_RS; 1107 } 1108 1109 if (v != 0) 1110 return (-1); 1111 1112 ASSERT3S(fec, !=, 0); 1113 1114 fec |= FEC_FORCE; 1115 1116 out: 1117 return t4_link_set_fec(pi, fec, new_caps); 1118 } 1119 1120 /* ARGSUSED */ 1121 static int 1122 t4_mc_setprop(void *arg, const char *name, mac_prop_id_t id, uint_t size, 1123 const void *val) 1124 { 1125 struct port_info *pi = arg; 1126 struct adapter *sc = pi->adapter; 1127 struct link_config *lc = &pi->link_cfg; 1128 fw_port_cap32_t new_caps = lc->admin_caps; 1129 int relink = 0, rx_mode = 0, rc = 0; 1130 uint32_t v32 = *(uint32_t *)val; 1131 uint8_t v8 = *(uint8_t *)val; 1132 link_flowctrl_t fc; 1133 link_fec_t fec; 1134 1135 switch (id) { 1136 case MAC_PROP_AUTONEG: 1137 rc = t4_link_set_autoneg(pi, v8, &new_caps); 1138 relink = 1; 1139 break; 1140 1141 case MAC_PROP_MTU: 1142 if (v32 < 46 || v32 > MAX_MTU) { 1143 rc = EINVAL; 1144 } else if (v32 != pi->mtu) { 1145 pi->mtu = v32; 1146 (void) mac_maxsdu_update(pi->mh, v32); 1147 rx_mode = 1; 1148 } 1149 1150 break; 1151 1152 case MAC_PROP_FLOWCTRL: 1153 fc = *(link_flowctrl_t *)val; 1154 rc = t4_mac_flowctrl_to_link_caps(pi, fc, &new_caps); 1155 relink = 1; 1156 break; 1157 1158 case MAC_PROP_EN_FEC_CAP: 1159 fec = *(link_fec_t *)val; 1160 rc = t4_mac_fec_cap_to_link_caps(pi, fec, &new_caps); 1161 relink = 1; 1162 break; 1163 1164 case MAC_PROP_EN_100GFDX_CAP: 1165 rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_100G, v8, 1166 &new_caps); 1167 relink = 1; 1168 break; 1169 1170 case MAC_PROP_EN_50GFDX_CAP: 1171 rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_50G, v8, 1172 &new_caps); 1173 relink = 1; 1174 break; 1175 1176 case MAC_PROP_EN_40GFDX_CAP: 1177 rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_40G, v8, 1178 &new_caps); 1179 relink = 1; 1180 break; 1181 1182 case MAC_PROP_EN_25GFDX_CAP: 1183 rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_25G, v8, 1184 &new_caps); 1185 relink = 1; 1186 break; 1187 1188 case MAC_PROP_EN_10GFDX_CAP: 1189 rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_10G, v8, 1190 &new_caps); 1191 relink = 1; 1192 break; 1193 1194 case MAC_PROP_EN_1000FDX_CAP: 1195 rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_1G, v8, 1196 &new_caps); 1197 relink = 1; 1198 break; 1199 1200 case MAC_PROP_EN_100FDX_CAP: 1201 rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_100M, v8, 1202 &new_caps); 1203 relink = 1; 1204 break; 1205 1206 case MAC_PROP_PRIVATE: 1207 rc = setprop(pi, name, val); 1208 break; 1209 1210 default: 1211 rc = ENOTSUP; 1212 break; 1213 } 1214 1215 if (rc != 0) 1216 return (rc); 1217 1218 if (isset(&sc->open_device_map, pi->port_id) != 0) { 1219 if (relink != 0) { 1220 rc = begin_synchronized_op(pi, 1, 1); 1221 if (rc != 0) 1222 return (rc); 1223 rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, lc, 1224 new_caps); 1225 end_synchronized_op(pi, 1); 1226 if (rc != 0) { 1227 cxgb_printf(pi->dip, CE_WARN, 1228 "%s link config failed: %d", 1229 __func__, rc); 1230 return (rc); 1231 } 1232 } 1233 1234 if (rx_mode != 0) { 1235 rc = begin_synchronized_op(pi, 1, 1); 1236 if (rc != 0) 1237 return (rc); 1238 rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, v32, -1, 1239 -1, -1, -1, false); 1240 end_synchronized_op(pi, 1); 1241 if (rc != 0) { 1242 cxgb_printf(pi->dip, CE_WARN, 1243 "set_rxmode failed: %d", rc); 1244 return (rc); 1245 } 1246 } 1247 } 1248 1249 if (relink != 0) 1250 lc->admin_caps = new_caps; 1251 1252 return (0); 1253 } 1254 1255 static int 1256 t4_mc_getprop(void *arg, const char *name, mac_prop_id_t id, uint_t size, 1257 void *val) 1258 { 1259 struct port_info *pi = arg; 1260 struct link_config *lc = &pi->link_cfg; 1261 uint8_t *u = val; 1262 int rc = 0; 1263 1264 switch (id) { 1265 case MAC_PROP_DUPLEX: 1266 *(link_duplex_t *)val = lc->link_ok ? LINK_DUPLEX_FULL : 1267 LINK_DUPLEX_UNKNOWN; 1268 break; 1269 1270 case MAC_PROP_SPEED: 1271 if (lc->link_ok != 0) { 1272 *(uint64_t *)val = t4_link_fwcap_to_speed(lc->link_caps); 1273 *(uint64_t *)val *= 1000000; 1274 } else { 1275 *(uint64_t *)val = 0; 1276 } 1277 break; 1278 1279 case MAC_PROP_STATUS: 1280 *(link_state_t *)val = lc->link_ok ? LINK_STATE_UP : 1281 LINK_STATE_DOWN; 1282 break; 1283 1284 case MAC_PROP_AUTONEG: 1285 *u = !!(lc->link_caps & FW_PORT_CAP32_ANEG); 1286 break; 1287 1288 case MAC_PROP_MTU: 1289 *(uint32_t *)val = pi->mtu; 1290 break; 1291 1292 case MAC_PROP_FLOWCTRL: 1293 t4_mac_link_caps_to_flowctrl(lc->link_caps, val); 1294 break; 1295 1296 case MAC_PROP_ADV_FEC_CAP: 1297 t4_mac_link_caps_to_fec_cap(lc->link_caps, val); 1298 break; 1299 1300 case MAC_PROP_EN_FEC_CAP: 1301 t4_mac_admin_caps_to_fec_cap(lc->admin_caps, val); 1302 break; 1303 1304 case MAC_PROP_ADV_100GFDX_CAP: 1305 *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_100G); 1306 break; 1307 1308 case MAC_PROP_EN_100GFDX_CAP: 1309 *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100G); 1310 break; 1311 1312 case MAC_PROP_ADV_50GFDX_CAP: 1313 *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_50G); 1314 break; 1315 1316 case MAC_PROP_EN_50GFDX_CAP: 1317 *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_50G); 1318 break; 1319 1320 case MAC_PROP_ADV_40GFDX_CAP: 1321 *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_40G); 1322 break; 1323 1324 case MAC_PROP_EN_40GFDX_CAP: 1325 *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_40G); 1326 break; 1327 1328 case MAC_PROP_ADV_25GFDX_CAP: 1329 *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_25G); 1330 break; 1331 1332 case MAC_PROP_EN_25GFDX_CAP: 1333 *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_25G); 1334 break; 1335 1336 case MAC_PROP_ADV_10GFDX_CAP: 1337 *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_10G); 1338 break; 1339 1340 case MAC_PROP_EN_10GFDX_CAP: 1341 *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_10G); 1342 break; 1343 1344 case MAC_PROP_ADV_1000FDX_CAP: 1345 *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_1G); 1346 break; 1347 1348 case MAC_PROP_EN_1000FDX_CAP: 1349 *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_1G); 1350 break; 1351 1352 case MAC_PROP_ADV_100FDX_CAP: 1353 *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_100M); 1354 break; 1355 1356 case MAC_PROP_EN_100FDX_CAP: 1357 *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100M); 1358 break; 1359 1360 case MAC_PROP_PRIVATE: 1361 return (getprop(pi, name, size, val)); 1362 1363 default: 1364 return (ENOTSUP); 1365 } 1366 1367 return (rc); 1368 } 1369 1370 static void 1371 t4_mc_propinfo(void *arg, const char *name, mac_prop_id_t id, 1372 mac_prop_info_handle_t ph) 1373 { 1374 struct port_info *pi = arg; 1375 struct link_config *lc = &pi->link_cfg; 1376 1377 switch (id) { 1378 case MAC_PROP_DUPLEX: 1379 case MAC_PROP_SPEED: 1380 case MAC_PROP_STATUS: 1381 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1382 break; 1383 1384 case MAC_PROP_AUTONEG: 1385 if (lc->pcaps & FW_PORT_CAP32_ANEG) 1386 mac_prop_info_set_default_uint8(ph, 1); 1387 else 1388 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1389 break; 1390 1391 case MAC_PROP_MTU: 1392 mac_prop_info_set_range_uint32(ph, 46, MAX_MTU); 1393 break; 1394 1395 case MAC_PROP_FLOWCTRL: 1396 mac_prop_info_set_default_link_flowctrl(ph, LINK_FLOWCTRL_BI); 1397 break; 1398 1399 case MAC_PROP_EN_FEC_CAP: 1400 mac_prop_info_set_default_fec(ph, LINK_FEC_AUTO); 1401 break; 1402 1403 case MAC_PROP_ADV_FEC_CAP: 1404 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1405 mac_prop_info_set_default_fec(ph, LINK_FEC_AUTO); 1406 break; 1407 1408 case MAC_PROP_EN_100GFDX_CAP: 1409 if (lc->pcaps & FW_PORT_CAP32_SPEED_100G) 1410 mac_prop_info_set_default_uint8(ph, 1); 1411 else 1412 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1413 break; 1414 1415 case MAC_PROP_EN_50GFDX_CAP: 1416 if (lc->pcaps & FW_PORT_CAP32_SPEED_50G) 1417 mac_prop_info_set_default_uint8(ph, 1); 1418 else 1419 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1420 break; 1421 1422 case MAC_PROP_EN_40GFDX_CAP: 1423 if (lc->pcaps & FW_PORT_CAP32_SPEED_40G) 1424 mac_prop_info_set_default_uint8(ph, 1); 1425 else 1426 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1427 break; 1428 1429 case MAC_PROP_EN_25GFDX_CAP: 1430 if (lc->pcaps & FW_PORT_CAP32_SPEED_25G) 1431 mac_prop_info_set_default_uint8(ph, 1); 1432 else 1433 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1434 break; 1435 1436 case MAC_PROP_EN_10GFDX_CAP: 1437 if (lc->pcaps & FW_PORT_CAP32_SPEED_10G) 1438 mac_prop_info_set_default_uint8(ph, 1); 1439 else 1440 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1441 break; 1442 1443 case MAC_PROP_EN_1000FDX_CAP: 1444 if (lc->pcaps & FW_PORT_CAP32_SPEED_1G) 1445 mac_prop_info_set_default_uint8(ph, 1); 1446 else 1447 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1448 break; 1449 1450 case MAC_PROP_EN_100FDX_CAP: 1451 if (lc->pcaps & FW_PORT_CAP32_SPEED_100M) 1452 mac_prop_info_set_default_uint8(ph, 1); 1453 else 1454 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1455 break; 1456 1457 case MAC_PROP_ADV_100GFDX_CAP: 1458 case MAC_PROP_ADV_50GFDX_CAP: 1459 case MAC_PROP_ADV_40GFDX_CAP: 1460 case MAC_PROP_ADV_25GFDX_CAP: 1461 case MAC_PROP_ADV_10GFDX_CAP: 1462 case MAC_PROP_ADV_1000FDX_CAP: 1463 case MAC_PROP_ADV_100FDX_CAP: 1464 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1465 break; 1466 1467 case MAC_PROP_PRIVATE: 1468 propinfo(pi, name, ph); 1469 break; 1470 1471 default: 1472 break; 1473 } 1474 } 1475 1476 int 1477 begin_synchronized_op(struct port_info *pi, int hold, int waitok) 1478 { 1479 struct adapter *sc = pi->adapter; 1480 int rc = 0; 1481 1482 ADAPTER_LOCK(sc); 1483 while (!IS_DOOMED(pi) && IS_BUSY(sc)) { 1484 if (!waitok) { 1485 rc = EBUSY; 1486 goto failed; 1487 } else if (cv_wait_sig(&sc->cv, &sc->lock) == 0) { 1488 rc = EINTR; 1489 goto failed; 1490 } 1491 } 1492 if (IS_DOOMED(pi) != 0) { /* shouldn't happen on Solaris */ 1493 rc = ENXIO; 1494 goto failed; 1495 } 1496 ASSERT(!IS_BUSY(sc)); 1497 /* LINTED: E_CONSTANT_CONDITION */ 1498 SET_BUSY(sc); 1499 1500 if (!hold) 1501 ADAPTER_UNLOCK(sc); 1502 1503 return (0); 1504 failed: 1505 ADAPTER_UNLOCK(sc); 1506 return (rc); 1507 } 1508 1509 void 1510 end_synchronized_op(struct port_info *pi, int held) 1511 { 1512 struct adapter *sc = pi->adapter; 1513 1514 if (!held) 1515 ADAPTER_LOCK(sc); 1516 1517 ADAPTER_LOCK_ASSERT_OWNED(sc); 1518 ASSERT(IS_BUSY(sc)); 1519 /* LINTED: E_CONSTANT_CONDITION */ 1520 CLR_BUSY(sc); 1521 cv_signal(&sc->cv); 1522 ADAPTER_UNLOCK(sc); 1523 } 1524 1525 static int 1526 t4_init_synchronized(struct port_info *pi) 1527 { 1528 struct adapter *sc = pi->adapter; 1529 int rc = 0; 1530 1531 ADAPTER_LOCK_ASSERT_NOTOWNED(sc); 1532 1533 if (isset(&sc->open_device_map, pi->port_id) != 0) 1534 return (0); /* already running */ 1535 1536 if (!(sc->flags & FULL_INIT_DONE) && 1537 ((rc = adapter_full_init(sc)) != 0)) 1538 return (rc); /* error message displayed already */ 1539 1540 if (!(pi->flags & PORT_INIT_DONE)) { 1541 rc = port_full_init(pi); 1542 if (rc != 0) 1543 return (rc); /* error message displayed already */ 1544 } else 1545 enable_port_queues(pi); 1546 1547 rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, pi->mtu, 0, 0, 1, 0, false); 1548 if (rc != 0) { 1549 cxgb_printf(pi->dip, CE_WARN, "set_rxmode failed: %d", rc); 1550 goto done; 1551 } 1552 rc = t4_change_mac(sc, sc->mbox, pi->viid, pi->xact_addr_filt, 1553 pi->hw_addr, true, &pi->smt_idx); 1554 if (rc < 0) { 1555 cxgb_printf(pi->dip, CE_WARN, "change_mac failed: %d", rc); 1556 rc = -rc; 1557 goto done; 1558 } else 1559 /* LINTED: E_ASSIGN_NARROW_CONV */ 1560 pi->xact_addr_filt = rc; 1561 1562 rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, &pi->link_cfg, 1563 pi->link_cfg.admin_caps); 1564 if (rc != 0) { 1565 cxgb_printf(pi->dip, CE_WARN, "start_link failed: %d", rc); 1566 goto done; 1567 } 1568 1569 rc = -t4_enable_vi(sc, sc->mbox, pi->viid, true, true); 1570 if (rc != 0) { 1571 cxgb_printf(pi->dip, CE_WARN, "enable_vi failed: %d", rc); 1572 goto done; 1573 } 1574 1575 /* all ok */ 1576 setbit(&sc->open_device_map, pi->port_id); 1577 done: 1578 if (rc != 0) 1579 (void) t4_uninit_synchronized(pi); 1580 1581 return (rc); 1582 } 1583 1584 /* 1585 * Idempotent. 1586 */ 1587 static int 1588 t4_uninit_synchronized(struct port_info *pi) 1589 { 1590 struct adapter *sc = pi->adapter; 1591 int rc; 1592 1593 ADAPTER_LOCK_ASSERT_NOTOWNED(sc); 1594 1595 /* 1596 * Disable the VI so that all its data in either direction is discarded 1597 * by the MPS. Leave everything else (the queues, interrupts, and 1Hz 1598 * tick) intact as the TP can deliver negative advice or data that it's 1599 * holding in its RAM (for an offloaded connection) even after the VI is 1600 * disabled. 1601 */ 1602 rc = -t4_enable_vi(sc, sc->mbox, pi->viid, false, false); 1603 if (rc != 0) { 1604 cxgb_printf(pi->dip, CE_WARN, "disable_vi failed: %d", rc); 1605 return (rc); 1606 } 1607 1608 disable_port_queues(pi); 1609 1610 clrbit(&sc->open_device_map, pi->port_id); 1611 1612 pi->link_cfg.link_ok = 0; 1613 mac_link_update(pi->mh, LINK_STATE_UNKNOWN); 1614 1615 return (0); 1616 } 1617 1618 static void 1619 propinfo(struct port_info *pi, const char *name, mac_prop_info_handle_t ph) 1620 { 1621 struct adapter *sc = pi->adapter; 1622 struct driver_properties *p = &sc->props; 1623 struct link_config *lc = &pi->link_cfg; 1624 int v; 1625 char str[16]; 1626 1627 if (strcmp(name, T4PROP_TMR_IDX) == 0) 1628 v = is_10G_port(pi) ? p->tmr_idx_10g : p->tmr_idx_1g; 1629 else if (strcmp(name, T4PROP_PKTC_IDX) == 0) 1630 v = is_10G_port(pi) ? p->pktc_idx_10g : p->pktc_idx_1g; 1631 else if (strcmp(name, T4PROP_HW_CSUM) == 0) 1632 v = (pi->features & CXGBE_HW_CSUM) ? 1 : 0; 1633 else if (strcmp(name, T4PROP_HW_LSO) == 0) 1634 v = (pi->features & CXGBE_HW_LSO) ? 1 : 0; 1635 else if (strcmp(name, T4PROP_TX_PAUSE) == 0) 1636 v = (lc->pcaps & FW_PORT_CAP32_FC_TX) ? 1 : 0; 1637 else if (strcmp(name, T4PROP_RX_PAUSE) == 0) 1638 v = (lc->pcaps & FW_PORT_CAP32_FC_RX) ? 1 : 0; 1639 #if MAC_VERSION == 1 1640 else if (strcmp(name, T4PROP_MTU) == 0) 1641 v = ETHERMTU; 1642 #endif 1643 else 1644 return; 1645 1646 (void) snprintf(str, sizeof (str), "%d", v); 1647 mac_prop_info_set_default_str(ph, str); 1648 } 1649 1650 static int 1651 getprop(struct port_info *pi, const char *name, uint_t size, void *val) 1652 { 1653 struct link_config *lc = &pi->link_cfg; 1654 int v; 1655 1656 if (strcmp(name, T4PROP_TMR_IDX) == 0) 1657 v = pi->tmr_idx; 1658 else if (strcmp(name, T4PROP_PKTC_IDX) == 0) 1659 v = pi->pktc_idx; 1660 else if (strcmp(name, T4PROP_HW_CSUM) == 0) 1661 v = (pi->features & CXGBE_HW_CSUM) ? 1 : 0; 1662 else if (strcmp(name, T4PROP_HW_LSO) == 0) 1663 v = (pi->features & CXGBE_HW_LSO) ? 1 : 0; 1664 else if (strcmp(name, T4PROP_TX_PAUSE) == 0) 1665 v = (lc->link_caps & FW_PORT_CAP32_FC_TX) ? 1 : 0; 1666 else if (strcmp(name, T4PROP_RX_PAUSE) == 0) 1667 v = (lc->link_caps & FW_PORT_CAP32_FC_RX) ? 1 : 0; 1668 #if MAC_VERSION == 1 1669 else if (strcmp(name, T4PROP_MTU) == 0) 1670 v = pi->mtu; 1671 #endif 1672 else 1673 return (ENOTSUP); 1674 1675 (void) snprintf(val, size, "%d", v); 1676 return (0); 1677 } 1678 1679 static int 1680 setprop(struct port_info *pi, const char *name, const void *val) 1681 { 1682 struct link_config *lc = &pi->link_cfg; 1683 fw_port_cap32_t new_caps = lc->admin_caps; 1684 int i, rc = 0, relink = 0, rx_mode = 0; 1685 struct adapter *sc = pi->adapter; 1686 struct sge_rxq *rxq; 1687 cc_pause_t fc = 0; 1688 long v; 1689 1690 (void) ddi_strtol(val, NULL, 0, &v); 1691 1692 if (strcmp(name, T4PROP_TMR_IDX) == 0) { 1693 if (v < 0 || v >= SGE_NTIMERS) 1694 return (EINVAL); 1695 if (v == pi->tmr_idx) 1696 return (0); 1697 1698 /* LINTED: E_ASSIGN_NARROW_CONV */ 1699 pi->tmr_idx = v; 1700 for_each_rxq(pi, i, rxq) { 1701 rxq->iq.intr_params = V_QINTR_TIMER_IDX(v) | 1702 V_QINTR_CNT_EN(pi->pktc_idx >= 0); 1703 } 1704 1705 } else if (strcmp(name, T4PROP_PKTC_IDX) == 0) { 1706 if (v >= SGE_NCOUNTERS) 1707 return (EINVAL); 1708 if (v == pi->pktc_idx || (v < 0 && pi->pktc_idx == -1)) 1709 return (0); 1710 1711 /* LINTED: E_ASSIGN_NARROW_CONV */ 1712 pi->pktc_idx = v < 0 ? -1 : v; 1713 for_each_rxq(pi, i, rxq) { 1714 rxq->iq.intr_params = V_QINTR_TIMER_IDX(pi->tmr_idx) | 1715 /* takes effect right away */ 1716 V_QINTR_CNT_EN(v >= 0); 1717 /* LINTED: E_ASSIGN_NARROW_CONV */ 1718 rxq->iq.intr_pktc_idx = v; /* this needs fresh plumb */ 1719 } 1720 } else if (strcmp(name, T4PROP_HW_CSUM) == 0) { 1721 if (v != 0 && v != 1) 1722 return (EINVAL); 1723 if (v == 1) 1724 pi->features |= CXGBE_HW_CSUM; 1725 else 1726 pi->features &= ~CXGBE_HW_CSUM; 1727 } else if (strcmp(name, T4PROP_HW_LSO) == 0) { 1728 if (v != 0 && v != 1) 1729 return (EINVAL); 1730 if (v == 1) 1731 pi->features |= CXGBE_HW_LSO; 1732 else 1733 pi->features &= ~CXGBE_HW_LSO; 1734 } else if (strcmp(name, T4PROP_TX_PAUSE) == 0) { 1735 if (v != 0 && v != 1) 1736 return (EINVAL); 1737 1738 if ((new_caps & FW_PORT_CAP32_FC_TX) && (v == 1)) 1739 fc |= PAUSE_TX; 1740 if (new_caps & FW_PORT_CAP32_FC_RX) 1741 fc |= PAUSE_RX; 1742 if (lc->admin_caps & FW_PORT_CAP32_ANEG) 1743 fc |= PAUSE_AUTONEG; 1744 1745 t4_link_set_pause(pi, fc, &new_caps); 1746 relink = 1; 1747 1748 } else if (strcmp(name, T4PROP_RX_PAUSE) == 0) { 1749 if (v != 0 && v != 1) 1750 return (EINVAL); 1751 1752 if (new_caps & FW_PORT_CAP32_FC_TX) 1753 fc |= PAUSE_TX; 1754 if ((new_caps & FW_PORT_CAP32_FC_RX) && (v == 1)) 1755 fc |= PAUSE_RX; 1756 if (lc->admin_caps & FW_PORT_CAP32_ANEG) 1757 fc |= PAUSE_AUTONEG; 1758 1759 t4_link_set_pause(pi, fc, &new_caps); 1760 relink = 1; 1761 } 1762 #if MAC_VERSION == 1 1763 else if (strcmp(name, T4PROP_MTU) == 0) { 1764 if (v < 46 || v > MAX_MTU) 1765 return (EINVAL); 1766 if (v == pi->mtu) 1767 return (0); 1768 1769 pi->mtu = (int)v; 1770 (void) mac_maxsdu_update(pi->mh, v); 1771 rx_mode = 1; 1772 } 1773 #endif 1774 else 1775 return (ENOTSUP); 1776 1777 if (!(relink || rx_mode)) 1778 return (0); 1779 1780 /* If we are here, either relink or rx_mode is 1 */ 1781 if (isset(&sc->open_device_map, pi->port_id) != 0) { 1782 if (relink != 0) { 1783 rc = begin_synchronized_op(pi, 1, 1); 1784 if (rc != 0) 1785 return (rc); 1786 rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, lc, 1787 new_caps); 1788 end_synchronized_op(pi, 1); 1789 if (rc != 0) { 1790 cxgb_printf(pi->dip, CE_WARN, 1791 "%s link config failed: %d", 1792 __func__, rc); 1793 return (rc); 1794 } 1795 } else if (rx_mode != 0) { 1796 rc = begin_synchronized_op(pi, 1, 1); 1797 if (rc != 0) 1798 return (rc); 1799 rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, v, -1, -1, 1800 -1, -1, false); 1801 end_synchronized_op(pi, 1); 1802 if (rc != 0) { 1803 cxgb_printf(pi->dip, CE_WARN, 1804 "set_rxmode failed: %d", rc); 1805 return (rc); 1806 } 1807 } 1808 } 1809 1810 if (relink != 0) 1811 lc->admin_caps = new_caps; 1812 1813 return (0); 1814 } 1815 1816 void 1817 t4_mc_init(struct port_info *pi) 1818 { 1819 pi->props = t4_priv_props; 1820 } 1821 1822 void 1823 t4_mc_cb_init(struct port_info *pi) 1824 { 1825 if (pi->adapter->props.multi_rings) 1826 pi->mc = &t4_m_ring_callbacks; 1827 else 1828 pi->mc = &t4_m_callbacks; 1829 } 1830 1831 void 1832 t4_os_link_changed(struct adapter *sc, int idx, int link_stat) 1833 { 1834 struct port_info *pi = sc->port[idx]; 1835 1836 mac_link_update(pi->mh, link_stat ? LINK_STATE_UP : LINK_STATE_DOWN); 1837 } 1838 1839 /* ARGSUSED */ 1840 void 1841 t4_mac_rx(struct port_info *pi, struct sge_rxq *rxq, mblk_t *m) 1842 { 1843 mac_rx(pi->mh, NULL, m); 1844 } 1845 1846 void 1847 t4_mac_tx_update(struct port_info *pi, struct sge_txq *txq) 1848 { 1849 if (pi->adapter->props.multi_rings) 1850 mac_tx_ring_update(pi->mh, txq->ring_handle); 1851 else 1852 mac_tx_update(pi->mh); 1853 } 1854