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 2025 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 t4_propinfo_priv(struct port_info *, const char *, 56 mac_prop_info_handle_t); 57 static int t4_getprop_priv(struct port_info *, const char *, uint_t, void *); 58 static int t4_setprop_priv(struct port_info *, const char *, const void *); 59 60 mac_callbacks_t t4_m_callbacks = { 61 .mc_callbacks = MC_GETCAPAB | MC_PROPERTIES, 62 .mc_getstat = t4_mc_getstat, 63 .mc_start = t4_mc_start, 64 .mc_stop = t4_mc_stop, 65 .mc_setpromisc = t4_mc_setpromisc, 66 .mc_multicst = t4_mc_multicst, 67 .mc_unicst = t4_mc_unicst, 68 .mc_tx = t4_mc_tx, 69 .mc_getcapab = t4_mc_getcapab, 70 .mc_setprop = t4_mc_setprop, 71 .mc_getprop = t4_mc_getprop, 72 .mc_propinfo = t4_mc_propinfo, 73 }; 74 75 mac_callbacks_t t4_m_ring_callbacks = { 76 .mc_callbacks = MC_GETCAPAB | MC_PROPERTIES, 77 .mc_getstat = t4_mc_getstat, 78 .mc_start = t4_mc_start, 79 .mc_stop = t4_mc_stop, 80 .mc_setpromisc = t4_mc_setpromisc, 81 .mc_multicst = t4_mc_multicst, 82 .mc_unicst = NULL, /* t4_addmac */ 83 .mc_tx = NULL, /* t4_eth_tx */ 84 .mc_getcapab = t4_mc_getcapab, 85 .mc_setprop = t4_mc_setprop, 86 .mc_getprop = t4_mc_getprop, 87 .mc_propinfo = t4_mc_propinfo, 88 }; 89 90 typedef enum t4_prop_id { 91 T4PROP_FW_TMR, 92 T4PROP_FW_PKTC, 93 T4PROP_RX_TMR, 94 T4PROP_RX_PKTC, 95 T4PROP_TX_TMR, 96 T4PROP_HW_CSUM, 97 T4PROP_HW_LSO, 98 T4PROP_RX_PAUSE, 99 T4PROP_TX_PAUSE, 100 } t4_prop_id_t; 101 102 typedef struct t4_priv_prop { 103 const char *tpp_name; 104 t4_prop_id_t tpp_id; 105 bool tpp_is_bool; 106 } t4_priv_prop_t; 107 108 static const t4_priv_prop_t t4_priv_props[] = { 109 /* 110 * Because there is a single FWQ for the entire NIC, all ports will be 111 * impacted by changes to these properties. 112 */ 113 { "_fw_coalesce_timer_us", T4PROP_FW_TMR }, 114 { "_fw_coalesce_count", T4PROP_FW_PKTC }, 115 116 { "_rx_coalesce_timer_us", T4PROP_RX_TMR }, 117 { "_rx_coalesce_count", T4PROP_RX_PKTC }, 118 { "_tx_reclaim_timer_us", T4PROP_TX_TMR }, 119 { "_hw_csum", T4PROP_HW_CSUM, true }, 120 { "_hw_lso", T4PROP_HW_LSO, true }, 121 { "_rx_pause", T4PROP_RX_PAUSE, true }, 122 { "_tx_pause", T4PROP_TX_PAUSE, true }, 123 }; 124 125 static const t4_priv_prop_t * 126 t4_priv_prop_match(const char *name) 127 { 128 for (uint_t i = 0; i < ARRAY_SIZE(t4_priv_props); i++) { 129 const t4_priv_prop_t *prop = &t4_priv_props[i]; 130 if (strcmp(prop->tpp_name, name) == 0) { 131 return (prop); 132 } 133 } 134 return (NULL); 135 } 136 137 static bool 138 t4_priv_prop_supported(struct port_info *pi, const t4_priv_prop_t *prop) 139 { 140 struct adapter *sc = pi->adapter; 141 142 switch (prop->tpp_id) { 143 case T4PROP_TX_TMR: 144 return ((sc->flags & TAF_DBQ_TIMER) != 0); 145 146 default: 147 return (true); 148 } 149 } 150 151 const char ** 152 t4_get_priv_props(struct port_info *pi, size_t *alloc_sz) 153 { 154 /* 155 * Just alloc for all possible options, skipping those which are not 156 * supported (and appending extra NULLs). 157 */ 158 const size_t sz = (ARRAY_SIZE(t4_priv_props) + 1) * sizeof (char *); 159 const char **out = kmem_zalloc(sz, KM_SLEEP); 160 161 uint_t filled = 0; 162 for (uint_t i = 0; i < ARRAY_SIZE(t4_priv_props); i++) { 163 if (t4_priv_prop_supported(pi, &t4_priv_props[i])) { 164 out[filled++] = t4_priv_props[i].tpp_name; 165 } 166 } 167 168 *alloc_sz = sz; 169 return (out); 170 } 171 172 /* 173 * To determine the actual Ethernet mode that we're in we need to look at the 174 * port type. That will tell us whether we're using a BASE-T PHY, have an 175 * external SFP connection whose module type we also need to use to qualify 176 * this, and then the link speed itself. Combining that tuple we can then get 177 * the current media. 178 * 179 * Our tables below assume we have gotten it down so the last thing we need to 180 * consider is a single speed. If port types end up supporting the same class of 181 * transceiver at a given speed, then this will need to be changed to use 182 * additional information to disambiguate that (which will require additional 183 * logic from the firmware). 184 */ 185 typedef struct { 186 fw_port_cap32_t tmm_speed; 187 mac_ether_media_t tmm_ether; 188 } t4nex_media_map_t; 189 190 static const t4nex_media_map_t t4nex_map_baset[] = { 191 /* 192 * We're assuming that the 100 Mb/s mode is 100BASE-TX. It's hard to say 193 * for certain what the phy would have done, but given the rest of the 194 * market, that seems the most likely one. 195 */ 196 { FW_PORT_CAP32_SPEED_100M, ETHER_MEDIA_100BASE_TX }, 197 { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_T }, 198 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_T } 199 }; 200 201 static const t4nex_media_map_t t4nex_map_kx[] = { 202 { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_KX }, 203 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_KX4 } 204 }; 205 206 static const t4nex_media_map_t t4nex_map_cx[] = { 207 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_CX4 } 208 }; 209 210 static const t4nex_media_map_t t4nex_map_kr[] = { 211 { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_KX }, 212 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_KR }, 213 { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_KR }, 214 { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_KR4 }, 215 { FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_KR2 }, 216 { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_KR4 }, 217 }; 218 219 static const t4nex_media_map_t t4nex_map_lr[] = { 220 { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_LX }, 221 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_LR }, 222 { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_LR }, 223 { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_LR4 }, 224 { FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_LR2 }, 225 { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_LR4 }, 226 }; 227 228 static const t4nex_media_map_t t4nex_map_sr[] = { 229 { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_SX }, 230 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_SR }, 231 { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_SR }, 232 { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_SR4 }, 233 { FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_SR2 }, 234 { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_SR4 }, 235 }; 236 237 static const t4nex_media_map_t t4nex_map_er[] = { 238 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_ER }, 239 { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_ER }, 240 { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_ER4 }, 241 { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_ER4 }, 242 }; 243 244 static const t4nex_media_map_t t4nex_map_cr[] = { 245 { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_CX }, 246 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_CR }, 247 { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_CR }, 248 { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_CR4 }, 249 { FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_CR2 }, 250 { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_CR4 }, 251 }; 252 253 static const t4nex_media_map_t t4nex_map_acc[] = { 254 { FW_PORT_CAP32_SPEED_1G, ETHER_MEDIA_1000BASE_CX }, 255 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_ACC }, 256 { FW_PORT_CAP32_SPEED_25G, ETHER_MEDIA_25GBASE_ACC }, 257 { FW_PORT_CAP32_SPEED_40G, ETHER_MEDIA_40GBASE_ACC4 }, 258 { FW_PORT_CAP32_SPEED_50G, ETHER_MEDIA_50GBASE_ACC2 }, 259 { FW_PORT_CAP32_SPEED_100G, ETHER_MEDIA_100GBASE_ACC4 }, 260 }; 261 262 static const t4nex_media_map_t t4nex_map_lrm[] = { 263 { FW_PORT_CAP32_SPEED_10G, ETHER_MEDIA_10GBASE_LRM }, 264 }; 265 266 static mac_ether_media_t 267 t4_port_to_media(struct port_info *pi) 268 { 269 fw_port_cap32_t speed; 270 struct link_config *lc = &pi->link_cfg; 271 const t4nex_media_map_t *map = NULL; 272 size_t count = 0; 273 274 if (lc->link_ok != 0) { 275 speed = t4_link_fwcap_to_fwspeed(lc->link_caps); 276 } else { 277 return (ETHER_MEDIA_UNKNOWN); 278 } 279 280 switch (pi->port_type) { 281 case FW_PORT_TYPE_FIBER_XFI: 282 case FW_PORT_TYPE_FIBER_XAUI: 283 case FW_PORT_TYPE_SFP: 284 case FW_PORT_TYPE_QSFP_10G: 285 case FW_PORT_TYPE_QSA: 286 case FW_PORT_TYPE_QSFP: 287 case FW_PORT_TYPE_CR4_QSFP: 288 case FW_PORT_TYPE_CR_QSFP: 289 case FW_PORT_TYPE_CR2_QSFP: 290 case FW_PORT_TYPE_SFP28: 291 switch (pi->mod_type) { 292 case FW_PORT_MOD_TYPE_LR: 293 map = t4nex_map_lr; 294 count = ARRAY_SIZE(t4nex_map_lr); 295 break; 296 case FW_PORT_MOD_TYPE_SR: 297 map = t4nex_map_sr; 298 count = ARRAY_SIZE(t4nex_map_sr); 299 break; 300 case FW_PORT_MOD_TYPE_ER: 301 map = t4nex_map_er; 302 count = ARRAY_SIZE(t4nex_map_er); 303 break; 304 case FW_PORT_MOD_TYPE_TWINAX_PASSIVE: 305 map = t4nex_map_cr; 306 count = ARRAY_SIZE(t4nex_map_cr); 307 break; 308 case FW_PORT_MOD_TYPE_TWINAX_ACTIVE: 309 map = t4nex_map_acc; 310 count = ARRAY_SIZE(t4nex_map_acc); 311 break; 312 case FW_PORT_MOD_TYPE_LRM: 313 map = t4nex_map_lrm; 314 count = ARRAY_SIZE(t4nex_map_lrm); 315 break; 316 case FW_PORT_MOD_TYPE_ERROR: 317 case FW_PORT_MOD_TYPE_UNKNOWN: 318 case FW_PORT_MOD_TYPE_NOTSUPPORTED: 319 case FW_PORT_MOD_TYPE_NONE: 320 case FW_PORT_MOD_TYPE_NA: 321 default: 322 break; 323 } 324 break; 325 case FW_PORT_TYPE_KX4: 326 case FW_PORT_TYPE_KX: 327 map = t4nex_map_kx; 328 count = ARRAY_SIZE(t4nex_map_kx); 329 break; 330 case FW_PORT_TYPE_CX4: 331 map = t4nex_map_cx; 332 count = ARRAY_SIZE(t4nex_map_cx); 333 break; 334 case FW_PORT_TYPE_KR: 335 case FW_PORT_TYPE_BP_AP: 336 case FW_PORT_TYPE_BP4_AP: 337 case FW_PORT_TYPE_BP40_BA: 338 case FW_PORT_TYPE_KR4_100G: 339 case FW_PORT_TYPE_KR_SFP28: 340 case FW_PORT_TYPE_KR_XLAUI: 341 map = t4nex_map_kr; 342 count = ARRAY_SIZE(t4nex_map_kr); 343 break; 344 case FW_PORT_TYPE_BT_SGMII: 345 case FW_PORT_TYPE_BT_XFI: 346 case FW_PORT_TYPE_BT_XAUI: 347 map = t4nex_map_baset; 348 count = ARRAY_SIZE(t4nex_map_baset); 349 break; 350 case FW_PORT_TYPE_NONE: 351 default: 352 break; 353 } 354 355 for (size_t i = 0; i < count; i++) { 356 if (map[i].tmm_speed == speed) { 357 return (map[i].tmm_ether); 358 } 359 } 360 361 /* 362 * At this point we return unknown as we already checked for a down link 363 * earlier. 364 */ 365 return (ETHER_MEDIA_UNKNOWN); 366 } 367 368 static int 369 t4_mc_getstat(void *arg, uint_t stat, uint64_t *val) 370 { 371 struct port_info *pi = arg; 372 struct adapter *sc = pi->adapter; 373 struct link_config *lc = &pi->link_cfg; 374 375 #define GET_STAT(name) \ 376 t4_read_reg64(sc, PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_##name##_L)) 377 378 switch (stat) { 379 case MAC_STAT_IFSPEED: 380 if (lc->link_ok != 0) { 381 *val = t4_link_fwcap_to_speed(lc->link_caps); 382 *val *= 1000000; 383 } else 384 *val = 0; 385 break; 386 387 case MAC_STAT_MULTIRCV: 388 *val = GET_STAT(RX_PORT_MCAST); 389 break; 390 391 case MAC_STAT_BRDCSTRCV: 392 *val = GET_STAT(RX_PORT_BCAST); 393 break; 394 395 case MAC_STAT_MULTIXMT: 396 *val = GET_STAT(TX_PORT_MCAST); 397 break; 398 399 case MAC_STAT_BRDCSTXMT: 400 *val = GET_STAT(TX_PORT_BCAST); 401 break; 402 403 case MAC_STAT_NORCVBUF: 404 *val = 0; /* TODO should come from rxq->nomem */ 405 break; 406 407 case MAC_STAT_IERRORS: 408 *val = GET_STAT(RX_PORT_MTU_ERROR) + 409 GET_STAT(RX_PORT_MTU_CRC_ERROR) + 410 GET_STAT(RX_PORT_CRC_ERROR) + 411 GET_STAT(RX_PORT_LEN_ERROR) + 412 GET_STAT(RX_PORT_SYM_ERROR) + 413 GET_STAT(RX_PORT_LESS_64B); 414 break; 415 416 case MAC_STAT_UNKNOWNS: 417 return (ENOTSUP); 418 419 case MAC_STAT_NOXMTBUF: 420 *val = GET_STAT(TX_PORT_DROP); 421 break; 422 423 case MAC_STAT_OERRORS: 424 *val = GET_STAT(TX_PORT_ERROR); 425 break; 426 427 case MAC_STAT_COLLISIONS: 428 return (ENOTSUP); 429 430 case MAC_STAT_RBYTES: 431 *val = GET_STAT(RX_PORT_BYTES); 432 break; 433 434 case MAC_STAT_IPACKETS: 435 *val = GET_STAT(RX_PORT_FRAMES); 436 break; 437 438 case MAC_STAT_OBYTES: 439 *val = GET_STAT(TX_PORT_BYTES); 440 break; 441 442 case MAC_STAT_OPACKETS: 443 *val = GET_STAT(TX_PORT_FRAMES); 444 break; 445 446 case ETHER_STAT_ALIGN_ERRORS: 447 return (ENOTSUP); 448 449 case ETHER_STAT_FCS_ERRORS: 450 *val = GET_STAT(RX_PORT_CRC_ERROR); 451 break; 452 453 case ETHER_STAT_FIRST_COLLISIONS: 454 case ETHER_STAT_MULTI_COLLISIONS: 455 case ETHER_STAT_SQE_ERRORS: 456 case ETHER_STAT_DEFER_XMTS: 457 case ETHER_STAT_TX_LATE_COLLISIONS: 458 case ETHER_STAT_EX_COLLISIONS: 459 return (ENOTSUP); 460 461 case ETHER_STAT_MACXMT_ERRORS: 462 *val = GET_STAT(TX_PORT_ERROR); 463 break; 464 465 case ETHER_STAT_CARRIER_ERRORS: 466 return (ENOTSUP); 467 468 case ETHER_STAT_TOOLONG_ERRORS: 469 *val = GET_STAT(RX_PORT_MTU_ERROR); 470 break; 471 472 case ETHER_STAT_MACRCV_ERRORS: 473 *val = GET_STAT(RX_PORT_MTU_ERROR) + 474 GET_STAT(RX_PORT_MTU_CRC_ERROR) + 475 GET_STAT(RX_PORT_CRC_ERROR) + 476 GET_STAT(RX_PORT_LEN_ERROR) + 477 GET_STAT(RX_PORT_SYM_ERROR) + 478 GET_STAT(RX_PORT_LESS_64B); 479 break; 480 481 case ETHER_STAT_XCVR_ADDR: 482 case ETHER_STAT_XCVR_ID: 483 return (ENOTSUP); 484 case ETHER_STAT_XCVR_INUSE: 485 *val = t4_port_to_media(pi); 486 break; 487 488 case ETHER_STAT_CAP_100GFDX: 489 *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_100G); 490 break; 491 492 case ETHER_STAT_CAP_50GFDX: 493 *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_50G); 494 break; 495 496 case ETHER_STAT_CAP_40GFDX: 497 *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_40G); 498 break; 499 500 case ETHER_STAT_CAP_25GFDX: 501 *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_25G); 502 break; 503 504 case ETHER_STAT_CAP_10GFDX: 505 *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_10G); 506 break; 507 508 case ETHER_STAT_CAP_1000FDX: 509 *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_1G); 510 break; 511 512 case ETHER_STAT_CAP_100FDX: 513 *val = !!(lc->pcaps & FW_PORT_CAP32_SPEED_100M); 514 break; 515 516 case ETHER_STAT_CAP_1000HDX: 517 case ETHER_STAT_CAP_100HDX: 518 case ETHER_STAT_CAP_10FDX: 519 case ETHER_STAT_CAP_10HDX: 520 return (ENOTSUP); 521 522 case ETHER_STAT_CAP_ASMPAUSE: 523 *val = !!(lc->pcaps & FW_PORT_CAP32_FC_RX); 524 break; 525 526 case ETHER_STAT_CAP_PAUSE: 527 *val = !!(lc->pcaps & FW_PORT_CAP32_FC_TX); 528 break; 529 530 case ETHER_STAT_CAP_AUTONEG: 531 *val = !!(lc->pcaps & FW_PORT_CAP32_ANEG); 532 break; 533 534 /* 535 * We have set flow control configuration based on tx_pause and rx_pause 536 * values supported through ndd. Now, we need to translate the settings 537 * we have in link_config structure to adv_cap_asmpause and 538 * adv_cap_pause. 539 * 540 * There are 4 combinations possible and the translation is as below: 541 * tx_pause = 0 => We don't send pause frames during Rx congestion 542 * tx_pause = 1 => We send pause frames during Rx congestion 543 * rx_pause = 0 => We ignore received pause frames 544 * rx_pause = 1 => We pause transmission when we receive pause frames 545 * 546 * +----------------------------+----------------------------------+ 547 * | tx_pause | rx_pause | adv_cap_asmpause | adv_cap_pause | 548 * +-------------------------+-------------------------------------+ 549 * | 0 | 0 | 0 | 0 | 550 * | 0 | 1 | 1 | 0 | 551 * | 1 | 0 | 1 | 1 | 552 * | 1 | 1 | 0 | 1 | 553 * +----------------------------+----------------------------------+ 554 */ 555 556 /* Advertised asymmetric pause capability */ 557 case ETHER_STAT_ADV_CAP_ASMPAUSE: 558 if (lc->pcaps & FW_PORT_CAP32_802_3_ASM_DIR) 559 *val = !!(lc->admin_caps & FW_PORT_CAP32_802_3_ASM_DIR); 560 else 561 *val = (!!(lc->admin_caps & FW_PORT_CAP32_FC_TX)) ^ 562 (!!(lc->admin_caps & FW_PORT_CAP32_FC_RX)); 563 break; 564 565 /* Advertised pause capability */ 566 case ETHER_STAT_ADV_CAP_PAUSE: 567 if (lc->pcaps & FW_PORT_CAP32_802_3_PAUSE) 568 *val = !!(lc->admin_caps & FW_PORT_CAP32_802_3_PAUSE); 569 else 570 *val = !!(lc->admin_caps & FW_PORT_CAP32_FC_TX); 571 break; 572 573 case ETHER_STAT_ADV_CAP_100GFDX: 574 *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100G); 575 break; 576 577 case ETHER_STAT_ADV_CAP_50GFDX: 578 *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_50G); 579 break; 580 581 case ETHER_STAT_ADV_CAP_40GFDX: 582 *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_40G); 583 break; 584 585 case ETHER_STAT_ADV_CAP_25GFDX: 586 *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_25G); 587 break; 588 589 case ETHER_STAT_ADV_CAP_10GFDX: 590 *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_10G); 591 break; 592 593 case ETHER_STAT_ADV_CAP_1000FDX: 594 *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_1G); 595 break; 596 597 case ETHER_STAT_ADV_CAP_100FDX: 598 *val = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100M); 599 break; 600 601 case ETHER_STAT_ADV_CAP_AUTONEG: 602 *val = !!(lc->admin_caps & FW_PORT_CAP32_ANEG); 603 break; 604 605 case ETHER_STAT_ADV_CAP_1000HDX: 606 case ETHER_STAT_ADV_CAP_100HDX: 607 case ETHER_STAT_ADV_CAP_10FDX: 608 case ETHER_STAT_ADV_CAP_10HDX: 609 return (ENOTSUP); /* TODO */ 610 611 case ETHER_STAT_LP_CAP_ASMPAUSE: 612 if (!(lc->acaps & FW_PORT_CAP32_ANEG)) 613 return (ENOTSUP); 614 615 if (lc->pcaps & FW_PORT_CAP32_802_3_ASM_DIR) 616 *val = !!(lc->lpacaps & FW_PORT_CAP32_802_3_ASM_DIR); 617 else 618 *val = (!!(lc->lpacaps & FW_PORT_CAP32_FC_TX)) ^ 619 (!!(lc->lpacaps & FW_PORT_CAP32_FC_RX)); 620 break; 621 622 case ETHER_STAT_LP_CAP_PAUSE: 623 if (!(lc->acaps & FW_PORT_CAP32_ANEG)) 624 return (ENOTSUP); 625 626 if (lc->pcaps & FW_PORT_CAP32_802_3_PAUSE) 627 *val = !!(lc->lpacaps & FW_PORT_CAP32_802_3_PAUSE); 628 else 629 *val = !!(lc->lpacaps & FW_PORT_CAP32_FC_TX); 630 break; 631 632 case ETHER_STAT_LP_CAP_100GFDX: 633 if (!(lc->acaps & FW_PORT_CAP32_ANEG)) 634 return (ENOTSUP); 635 636 *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_100G); 637 break; 638 639 case ETHER_STAT_LP_CAP_50GFDX: 640 if (!(lc->acaps & FW_PORT_CAP32_ANEG)) 641 return (ENOTSUP); 642 643 *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_50G); 644 break; 645 646 case ETHER_STAT_LP_CAP_40GFDX: 647 if (!(lc->acaps & FW_PORT_CAP32_ANEG)) 648 return (ENOTSUP); 649 650 *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_40G); 651 break; 652 653 case ETHER_STAT_LP_CAP_25GFDX: 654 if (!(lc->acaps & FW_PORT_CAP32_ANEG)) 655 return (ENOTSUP); 656 657 *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_25G); 658 break; 659 660 case ETHER_STAT_LP_CAP_10GFDX: 661 if (!(lc->acaps & FW_PORT_CAP32_ANEG)) 662 return (ENOTSUP); 663 664 *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_10G); 665 break; 666 667 case ETHER_STAT_LP_CAP_1000FDX: 668 if (!(lc->acaps & FW_PORT_CAP32_ANEG)) 669 return (ENOTSUP); 670 671 *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_1G); 672 break; 673 674 case ETHER_STAT_LP_CAP_100FDX: 675 if (!(lc->acaps & FW_PORT_CAP32_ANEG)) 676 return (ENOTSUP); 677 678 *val = !!(lc->lpacaps & FW_PORT_CAP32_SPEED_100M); 679 break; 680 681 case ETHER_STAT_LP_CAP_AUTONEG: 682 if (!(lc->acaps & FW_PORT_CAP32_ANEG)) 683 return (ENOTSUP); 684 685 *val = !!(lc->lpacaps & FW_PORT_CAP32_ANEG); 686 break; 687 688 case ETHER_STAT_LP_CAP_1000HDX: 689 case ETHER_STAT_LP_CAP_100HDX: 690 case ETHER_STAT_LP_CAP_10FDX: 691 case ETHER_STAT_LP_CAP_10HDX: 692 return (ENOTSUP); 693 694 case ETHER_STAT_LINK_ASMPAUSE: 695 *val = (!!(lc->link_caps & FW_PORT_CAP32_FC_TX)) ^ 696 (!!(lc->link_caps & FW_PORT_CAP32_FC_RX)); 697 break; 698 699 case ETHER_STAT_LINK_PAUSE: 700 *val = !!(lc->link_caps & FW_PORT_CAP32_FC_TX); 701 break; 702 703 case ETHER_STAT_LINK_AUTONEG: 704 *val = !!(lc->link_caps & FW_PORT_CAP32_ANEG); 705 break; 706 707 case ETHER_STAT_LINK_DUPLEX: 708 if (lc->link_ok != 0) 709 *val = LINK_DUPLEX_FULL; 710 else 711 *val = LINK_DUPLEX_UNKNOWN; 712 break; 713 714 default: 715 return (ENOTSUP); 716 } 717 #undef GET_STAT 718 719 return (0); 720 } 721 722 static int 723 t4_mc_start(void *arg) 724 { 725 struct port_info *pi = arg; 726 727 ADAPTER_LOCK(pi->adapter); 728 const int rc = t4_init_synchronized(pi); 729 ADAPTER_UNLOCK(pi->adapter); 730 731 return (rc); 732 } 733 734 static void 735 t4_mc_stop(void *arg) 736 { 737 struct port_info *pi = arg; 738 739 ADAPTER_LOCK(pi->adapter); 740 (void) t4_uninit_synchronized(pi); 741 ADAPTER_UNLOCK(pi->adapter); 742 } 743 744 static int 745 t4_mc_setpromisc(void *arg, boolean_t on) 746 { 747 struct port_info *pi = arg; 748 struct adapter *sc = pi->adapter; 749 int rc; 750 751 ADAPTER_LOCK(sc); 752 rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, -1, on ? 1 : 0, -1, -1, -1, 753 false); 754 ADAPTER_UNLOCK(sc); 755 756 return (rc); 757 } 758 759 /* 760 * TODO: Starts failing as soon as the 336 entry table fills up. Need to use 761 * hash in that case. 762 */ 763 static int 764 t4_mc_multicst(void *arg, boolean_t add, const uint8_t *mcaddr) 765 { 766 struct port_info *pi = arg; 767 struct adapter *sc = pi->adapter; 768 struct fw_vi_mac_cmd c; 769 int len16, rc; 770 771 len16 = howmany(sizeof (c.op_to_viid) + sizeof (c.freemacs_to_len16) + 772 sizeof (c.u.exact[0]), 16); 773 c.op_to_viid = htonl(V_FW_CMD_OP(FW_VI_MAC_CMD) | F_FW_CMD_REQUEST | 774 F_FW_CMD_WRITE | V_FW_VI_MAC_CMD_VIID(pi->viid)); 775 c.freemacs_to_len16 = htonl(V_FW_CMD_LEN16(len16)); 776 c.u.exact[0].valid_to_idx = htons(F_FW_VI_MAC_CMD_VALID | 777 V_FW_VI_MAC_CMD_IDX(add ? FW_VI_MAC_ADD_MAC : 778 FW_VI_MAC_MAC_BASED_FREE)); 779 bcopy(mcaddr, &c.u.exact[0].macaddr, ETHERADDRL); 780 781 ADAPTER_LOCK(sc); 782 rc = -t4_wr_mbox_meat(sc, sc->mbox, &c, len16 * 16, &c, true); 783 ADAPTER_UNLOCK(sc); 784 if (rc != 0) 785 return (rc); 786 #ifdef DEBUG 787 /* 788 * TODO: Firmware doesn't seem to return the correct index on removal 789 * (it gives back 0x3fd FW_VI_MAC_MAC_BASED_FREE unchanged. Remove this 790 * code once it is fixed. 791 */ 792 else { 793 uint16_t idx; 794 795 idx = G_FW_VI_MAC_CMD_IDX(ntohs(c.u.exact[0].valid_to_idx)); 796 cxgb_printf(pi->dip, CE_NOTE, 797 "%02x:%02x:%02x:%02x:%02x:%02x %s %d", mcaddr[0], 798 mcaddr[1], mcaddr[2], mcaddr[3], mcaddr[4], mcaddr[5], 799 add ? "added at index" : "removed from index", idx); 800 } 801 #endif 802 803 return (0); 804 } 805 806 int 807 t4_mc_unicst(void *arg, const uint8_t *ucaddr) 808 { 809 struct port_info *pi = arg; 810 struct adapter *sc = pi->adapter; 811 int rc; 812 813 if (ucaddr == NULL) 814 return (EINVAL); 815 816 ADAPTER_LOCK(sc); 817 818 /* We will support adding only one mac address */ 819 if (pi->adapter->props.multi_rings && pi->macaddr_cnt) { 820 ADAPTER_UNLOCK(sc); 821 return (ENOSPC); 822 } 823 rc = t4_change_mac(sc, sc->mbox, pi->viid, pi->xact_addr_filt, ucaddr, 824 true, &pi->smt_idx); 825 if (rc < 0) { 826 rc = -rc; 827 } else { 828 pi->macaddr_cnt++; 829 pi->xact_addr_filt = rc; 830 rc = 0; 831 } 832 ADAPTER_UNLOCK(sc); 833 834 return (rc); 835 } 836 837 int 838 t4_addmac(void *arg, const uint8_t *ucaddr) 839 { 840 return (t4_mc_unicst(arg, ucaddr)); 841 } 842 843 static int 844 t4_remmac(void *arg, const uint8_t *mac_addr) 845 { 846 struct port_info *pi = arg; 847 848 ADAPTER_LOCK(pi->adapter); 849 pi->macaddr_cnt--; 850 ADAPTER_UNLOCK(pi->adapter); 851 852 return (0); 853 } 854 855 /* 856 * Callback funtion for MAC layer to register all groups. 857 */ 858 void 859 t4_fill_group(void *arg, mac_ring_type_t rtype, const int rg_index, 860 mac_group_info_t *infop, mac_group_handle_t gh) 861 { 862 struct port_info *pi = arg; 863 864 switch (rtype) { 865 case MAC_RING_TYPE_RX: { 866 infop->mgi_driver = (mac_group_driver_t)arg; 867 infop->mgi_start = NULL; 868 infop->mgi_stop = NULL; 869 infop->mgi_addmac = t4_addmac; 870 infop->mgi_remmac = t4_remmac; 871 infop->mgi_count = pi->nrxq; 872 break; 873 } 874 case MAC_RING_TYPE_TX: 875 default: 876 ASSERT(0); 877 break; 878 } 879 } 880 881 static int 882 t4_ring_start(mac_ring_driver_t rh, uint64_t mr_gen_num) 883 { 884 struct sge_rxq *rxq = (struct sge_rxq *)rh; 885 886 RXQ_LOCK(rxq); 887 rxq->ring_gen_num = mr_gen_num; 888 RXQ_UNLOCK(rxq); 889 return (0); 890 } 891 892 /* 893 * Enable interrupt on the specificed rx ring. 894 */ 895 int 896 t4_ring_intr_enable(mac_intr_handle_t intrh) 897 { 898 struct sge_rxq *rxq = (struct sge_rxq *)intrh; 899 struct sge_iq *iq = &rxq->iq; 900 901 RXQ_LOCK(rxq); 902 iq->polling = 0; 903 iq->state = IQS_IDLE; 904 t4_iq_gts_update(iq, iq->intr_params, 0); 905 RXQ_UNLOCK(rxq); 906 return (0); 907 } 908 909 /* 910 * Disable interrupt on the specificed rx ring. 911 */ 912 int 913 t4_ring_intr_disable(mac_intr_handle_t intrh) 914 { 915 struct sge_rxq *rxq = (struct sge_rxq *)intrh; 916 struct sge_iq *iq; 917 918 /* 919 * Nothing to be done here WRT the interrupt, as it will not fire until 920 * re-enabled through the t4_iq_gts_update() in t4_ring_intr_enable(). 921 */ 922 923 iq = &rxq->iq; 924 RXQ_LOCK(rxq); 925 iq->polling = 1; 926 iq->state = IQS_BUSY; 927 RXQ_UNLOCK(rxq); 928 929 return (0); 930 } 931 932 mblk_t * 933 t4_poll_ring(void *arg, int n_bytes) 934 { 935 struct sge_rxq *rxq = (struct sge_rxq *)arg; 936 mblk_t *mp = NULL; 937 938 ASSERT(n_bytes >= 0); 939 if (n_bytes == 0) 940 return (NULL); 941 942 RXQ_LOCK(rxq); 943 mp = t4_ring_rx(rxq, n_bytes); 944 RXQ_UNLOCK(rxq); 945 946 return (mp); 947 } 948 949 /* 950 * Retrieve a value for one of the statistics for a particular rx ring 951 */ 952 int 953 t4_rx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val) 954 { 955 struct sge_rxq *rxq = (struct sge_rxq *)rh; 956 957 switch (stat) { 958 case MAC_STAT_RBYTES: 959 *val = rxq->rxbytes; 960 break; 961 962 case MAC_STAT_IPACKETS: 963 *val = rxq->rxpkts; 964 break; 965 966 default: 967 *val = 0; 968 return (ENOTSUP); 969 } 970 971 return (0); 972 } 973 974 /* 975 * Retrieve a value for one of the statistics for a particular tx ring 976 */ 977 int 978 t4_tx_stat(mac_ring_driver_t rh, uint_t stat, uint64_t *val) 979 { 980 struct sge_txq *txq = (struct sge_txq *)rh; 981 982 switch (stat) { 983 case MAC_STAT_RBYTES: 984 *val = txq->txbytes; 985 break; 986 987 case MAC_STAT_IPACKETS: 988 *val = txq->txpkts; 989 break; 990 991 default: 992 *val = 0; 993 return (ENOTSUP); 994 } 995 996 return (0); 997 } 998 999 /* 1000 * Callback funtion for MAC layer to register all rings 1001 * for given ring_group, noted by group_index. 1002 * Since we have only one group, ring index becomes 1003 * absolute index. 1004 */ 1005 void 1006 t4_fill_ring(void *arg, mac_ring_type_t rtype, const int group_index, 1007 const int ring_index, mac_ring_info_t *infop, mac_ring_handle_t rh) 1008 { 1009 struct port_info *pi = arg; 1010 mac_intr_t *mintr; 1011 1012 switch (rtype) { 1013 case MAC_RING_TYPE_RX: { 1014 struct sge_rxq *rxq; 1015 1016 rxq = &pi->adapter->sge.rxq[pi->first_rxq + ring_index]; 1017 rxq->ring_handle = rh; 1018 1019 infop->mri_driver = (mac_ring_driver_t)rxq; 1020 infop->mri_start = t4_ring_start; 1021 infop->mri_stop = NULL; 1022 infop->mri_poll = t4_poll_ring; 1023 infop->mri_stat = t4_rx_stat; 1024 1025 mintr = &infop->mri_intr; 1026 mintr->mi_handle = (mac_intr_handle_t)rxq; 1027 mintr->mi_enable = t4_ring_intr_enable; 1028 mintr->mi_disable = t4_ring_intr_disable; 1029 1030 break; 1031 } 1032 case MAC_RING_TYPE_TX: { 1033 struct sge_txq *txq = 1034 &pi->adapter->sge.txq[pi->first_txq + ring_index]; 1035 txq->ring_handle = rh; 1036 infop->mri_driver = (mac_ring_driver_t)txq; 1037 infop->mri_start = NULL; 1038 infop->mri_stop = NULL; 1039 infop->mri_tx = t4_eth_tx; 1040 infop->mri_stat = t4_tx_stat; 1041 break; 1042 } 1043 default: 1044 ASSERT(0); 1045 break; 1046 } 1047 } 1048 1049 mblk_t * 1050 t4_mc_tx(void *arg, mblk_t *m) 1051 { 1052 struct port_info *pi = arg; 1053 struct adapter *sc = pi->adapter; 1054 struct sge_txq *txq = &sc->sge.txq[pi->first_txq]; 1055 1056 return (t4_eth_tx(txq, m)); 1057 } 1058 1059 static int 1060 t4_mc_transceiver_info(void *arg, uint_t id, mac_transceiver_info_t *infop) 1061 { 1062 struct port_info *pi = arg; 1063 1064 if (id != 0 || infop == NULL) 1065 return (EINVAL); 1066 1067 switch (pi->mod_type) { 1068 case FW_PORT_MOD_TYPE_NONE: 1069 mac_transceiver_info_set_present(infop, B_FALSE); 1070 break; 1071 case FW_PORT_MOD_TYPE_NOTSUPPORTED: 1072 mac_transceiver_info_set_present(infop, B_TRUE); 1073 mac_transceiver_info_set_usable(infop, B_FALSE); 1074 break; 1075 default: 1076 mac_transceiver_info_set_present(infop, B_TRUE); 1077 mac_transceiver_info_set_usable(infop, B_TRUE); 1078 break; 1079 } 1080 1081 return (0); 1082 } 1083 1084 static int 1085 t4_mc_transceiver_read(void *arg, uint_t id, uint_t page, void *bp, 1086 size_t nbytes, off_t offset, size_t *nread) 1087 { 1088 struct port_info *pi = arg; 1089 struct adapter *sc = pi->adapter; 1090 int rc; 1091 1092 if (id != 0 || bp == NULL || nbytes == 0 || nread == NULL || 1093 (page != 0xa0 && page != 0xa2) || offset < 0) 1094 return (EINVAL); 1095 1096 if (nbytes > 256 || offset >= 256 || (offset + nbytes > 256)) 1097 return (EINVAL); 1098 1099 ADAPTER_LOCK(sc); 1100 /* 1101 * Firmware has a maximum size that we can read. Don't read more than it 1102 * allows. 1103 */ 1104 const size_t maxread = sizeof (((struct fw_ldst_cmd *)0)->u.i2c.data); 1105 for (size_t i = 0; i < nbytes; i += maxread) { 1106 size_t toread = MIN(maxread, nbytes - i); 1107 rc = -t4_i2c_rd(sc, sc->mbox, pi->port_id, page, offset, toread, 1108 bp); 1109 if (rc != 0) 1110 break; 1111 offset += toread; 1112 bp = (void *)((uintptr_t)bp + toread); 1113 } 1114 ADAPTER_UNLOCK(sc); 1115 1116 if (rc == 0) 1117 *nread = nbytes; 1118 return (rc); 1119 } 1120 1121 static int 1122 t4_port_led_set(void *arg, mac_led_mode_t mode, uint_t flags) 1123 { 1124 struct port_info *pi = arg; 1125 struct adapter *sc = pi->adapter; 1126 int val, rc; 1127 1128 if (flags != 0) 1129 return (EINVAL); 1130 1131 switch (mode) { 1132 case MAC_LED_DEFAULT: 1133 val = 0; 1134 break; 1135 case MAC_LED_IDENT: 1136 val = 0xffff; 1137 break; 1138 1139 default: 1140 return (ENOTSUP); 1141 } 1142 1143 ADAPTER_LOCK(sc); 1144 rc = -t4_identify_port(sc, sc->mbox, pi->viid, val); 1145 ADAPTER_UNLOCK(sc); 1146 1147 return (rc); 1148 } 1149 1150 static boolean_t 1151 t4_mc_getcapab(void *arg, mac_capab_t cap, void *data) 1152 { 1153 struct port_info *pi = arg; 1154 boolean_t status = B_TRUE; 1155 mac_capab_transceiver_t *mct; 1156 mac_capab_led_t *mcl; 1157 1158 switch (cap) { 1159 case MAC_CAPAB_HCKSUM: 1160 if (pi->features & CXGBE_HW_CSUM) { 1161 uint32_t *d = data; 1162 *d = HCKSUM_INET_FULL_V4 | HCKSUM_IPHDRCKSUM | 1163 HCKSUM_INET_FULL_V6; 1164 } else 1165 status = B_FALSE; 1166 break; 1167 1168 case MAC_CAPAB_LSO: 1169 /* Enabling LSO requires Checksum offloading */ 1170 if (pi->features & CXGBE_HW_LSO && 1171 pi->features & CXGBE_HW_CSUM) { 1172 mac_capab_lso_t *d = data; 1173 1174 d->lso_flags = LSO_TX_BASIC_TCP_IPV4 | 1175 LSO_TX_BASIC_TCP_IPV6; 1176 d->lso_basic_tcp_ipv4.lso_max = 65535; 1177 d->lso_basic_tcp_ipv6.lso_max = 65535; 1178 } else 1179 status = B_FALSE; 1180 break; 1181 1182 case MAC_CAPAB_RINGS: { 1183 mac_capab_rings_t *cap_rings = data; 1184 1185 if (!pi->adapter->props.multi_rings) { 1186 status = B_FALSE; 1187 break; 1188 } 1189 switch (cap_rings->mr_type) { 1190 case MAC_RING_TYPE_RX: 1191 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 1192 cap_rings->mr_rnum = pi->nrxq; 1193 cap_rings->mr_gnum = 1; 1194 cap_rings->mr_rget = t4_fill_ring; 1195 cap_rings->mr_gget = t4_fill_group; 1196 cap_rings->mr_gaddring = NULL; 1197 cap_rings->mr_gremring = NULL; 1198 break; 1199 case MAC_RING_TYPE_TX: 1200 cap_rings->mr_group_type = MAC_GROUP_TYPE_STATIC; 1201 cap_rings->mr_rnum = pi->ntxq; 1202 cap_rings->mr_gnum = 0; 1203 cap_rings->mr_rget = t4_fill_ring; 1204 cap_rings->mr_gget = NULL; 1205 break; 1206 } 1207 break; 1208 } 1209 1210 case MAC_CAPAB_TRANSCEIVER: 1211 mct = data; 1212 1213 mct->mct_flags = 0; 1214 mct->mct_ntransceivers = 1; 1215 mct->mct_info = t4_mc_transceiver_info; 1216 mct->mct_read = t4_mc_transceiver_read; 1217 break; 1218 case MAC_CAPAB_LED: 1219 mcl = data; 1220 mcl->mcl_flags = 0; 1221 mcl->mcl_modes = MAC_LED_DEFAULT | MAC_LED_IDENT; 1222 mcl->mcl_set = t4_port_led_set; 1223 break; 1224 1225 default: 1226 status = B_FALSE; /* cap not supported */ 1227 } 1228 1229 return (status); 1230 } 1231 1232 static void 1233 t4_mac_link_caps_to_flowctrl(fw_port_cap32_t caps, link_flowctrl_t *fc) 1234 { 1235 u8 pause_tx = 0, pause_rx = 0; 1236 1237 if (caps & FW_PORT_CAP32_FC_TX) 1238 pause_tx = 1; 1239 1240 if (caps & FW_PORT_CAP32_FC_RX) 1241 pause_rx = 1; 1242 1243 if (pause_rx & pause_tx) 1244 *fc = LINK_FLOWCTRL_BI; 1245 else if (pause_tx) 1246 *fc = LINK_FLOWCTRL_TX; 1247 else if (pause_rx) 1248 *fc = LINK_FLOWCTRL_RX; 1249 else 1250 *fc = LINK_FLOWCTRL_NONE; 1251 } 1252 1253 static int 1254 t4_mac_flowctrl_to_link_caps(struct port_info *pi, link_flowctrl_t fc, 1255 fw_port_cap32_t *new_caps) 1256 { 1257 cc_pause_t pause = 0; 1258 1259 switch (fc) { 1260 case LINK_FLOWCTRL_BI: 1261 pause |= PAUSE_TX | PAUSE_RX; 1262 break; 1263 case LINK_FLOWCTRL_TX: 1264 pause |= PAUSE_TX; 1265 break; 1266 case LINK_FLOWCTRL_RX: 1267 pause |= PAUSE_RX; 1268 break; 1269 default: 1270 break; 1271 } 1272 1273 if (pi->link_cfg.admin_caps & FW_PORT_CAP32_ANEG) 1274 pause |= PAUSE_AUTONEG; 1275 1276 return (t4_link_set_pause(pi, pause, new_caps)); 1277 } 1278 1279 static link_fec_t 1280 t4_mac_port_caps_to_fec_cap(fw_port_cap32_t caps) 1281 { 1282 link_fec_t link_fec = 0; 1283 1284 if (caps & FW_PORT_CAP32_FEC_RS) 1285 link_fec |= LINK_FEC_RS; 1286 1287 if (caps & FW_PORT_CAP32_FEC_BASER_RS) 1288 link_fec |= LINK_FEC_BASE_R; 1289 1290 if (caps & FW_PORT_CAP32_FEC_NO_FEC) 1291 link_fec |= LINK_FEC_NONE; 1292 1293 if ((link_fec & (link_fec - 1)) && 1294 !(caps & FW_PORT_CAP32_FORCE_FEC)) 1295 return (LINK_FEC_AUTO); 1296 1297 return (link_fec); 1298 } 1299 1300 static void 1301 t4_mac_admin_caps_to_fec_cap(fw_port_cap32_t caps, link_fec_t *fec) 1302 { 1303 *fec = t4_mac_port_caps_to_fec_cap(caps); 1304 } 1305 1306 static void 1307 t4_mac_link_caps_to_fec_cap(fw_port_cap32_t caps, link_fec_t *fec) 1308 { 1309 link_fec_t link_fec; 1310 1311 caps &= ~FW_PORT_CAP32_FEC_NO_FEC; 1312 link_fec = t4_mac_port_caps_to_fec_cap(caps); 1313 *fec = link_fec ? link_fec : LINK_FEC_NONE; 1314 } 1315 1316 static int 1317 t4_mac_fec_cap_to_link_caps(struct port_info *pi, link_fec_t v, 1318 fw_port_cap32_t *new_caps) 1319 { 1320 cc_fec_t fec = 0; 1321 1322 if (v == LINK_FEC_AUTO) { 1323 fec = FEC_AUTO; 1324 goto out; 1325 } 1326 1327 if (v & LINK_FEC_NONE) { 1328 v &= ~LINK_FEC_NONE; 1329 fec |= FEC_NONE; 1330 } 1331 1332 if (v & LINK_FEC_RS) { 1333 v &= ~LINK_FEC_RS; 1334 fec |= FEC_RS; 1335 } 1336 1337 if (v & LINK_FEC_BASE_R) { 1338 v &= ~LINK_FEC_BASE_R; 1339 fec |= FEC_BASER_RS; 1340 } 1341 1342 if (v != 0) 1343 return (-1); 1344 1345 ASSERT3S(fec, !=, 0); 1346 1347 fec |= FEC_FORCE; 1348 1349 out: 1350 return (t4_link_set_fec(pi, fec, new_caps)); 1351 } 1352 1353 /* ARGSUSED */ 1354 static int 1355 t4_mc_setprop(void *arg, const char *name, mac_prop_id_t id, uint_t size, 1356 const void *val) 1357 { 1358 struct port_info *pi = arg; 1359 struct adapter *sc = pi->adapter; 1360 struct link_config *lc = &pi->link_cfg; 1361 fw_port_cap32_t new_caps = lc->admin_caps; 1362 int relink = 0, rx_mode = 0, rc = 0; 1363 uint32_t v32 = *(uint32_t *)val; 1364 uint8_t v8 = *(uint8_t *)val; 1365 1366 switch (id) { 1367 case MAC_PROP_AUTONEG: 1368 rc = t4_link_set_autoneg(pi, v8, &new_caps); 1369 relink = 1; 1370 break; 1371 1372 case MAC_PROP_MTU: 1373 if (v32 < 46 || v32 > MAX_MTU) { 1374 rc = EINVAL; 1375 } else if (v32 != pi->mtu) { 1376 pi->mtu = v32; 1377 (void) mac_maxsdu_update(pi->mh, v32); 1378 rx_mode = 1; 1379 } 1380 break; 1381 1382 case MAC_PROP_FLOWCTRL: 1383 rc = t4_mac_flowctrl_to_link_caps(pi, 1384 *(const link_flowctrl_t *)val, &new_caps); 1385 relink = 1; 1386 break; 1387 1388 case MAC_PROP_EN_FEC_CAP: 1389 rc = t4_mac_fec_cap_to_link_caps(pi, 1390 *(const link_fec_t *)val, &new_caps); 1391 relink = 1; 1392 break; 1393 1394 case MAC_PROP_EN_100GFDX_CAP: 1395 rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_100G, v8, 1396 &new_caps); 1397 relink = 1; 1398 break; 1399 1400 case MAC_PROP_EN_50GFDX_CAP: 1401 rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_50G, v8, 1402 &new_caps); 1403 relink = 1; 1404 break; 1405 1406 case MAC_PROP_EN_40GFDX_CAP: 1407 rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_40G, v8, 1408 &new_caps); 1409 relink = 1; 1410 break; 1411 1412 case MAC_PROP_EN_25GFDX_CAP: 1413 rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_25G, v8, 1414 &new_caps); 1415 relink = 1; 1416 break; 1417 1418 case MAC_PROP_EN_10GFDX_CAP: 1419 rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_10G, v8, 1420 &new_caps); 1421 relink = 1; 1422 break; 1423 1424 case MAC_PROP_EN_1000FDX_CAP: 1425 rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_1G, v8, 1426 &new_caps); 1427 relink = 1; 1428 break; 1429 1430 case MAC_PROP_EN_100FDX_CAP: 1431 rc = t4_link_set_speed(pi, FW_PORT_CAP32_SPEED_100M, v8, 1432 &new_caps); 1433 relink = 1; 1434 break; 1435 1436 case MAC_PROP_PRIVATE: 1437 return (t4_setprop_priv(pi, name, val)); 1438 1439 default: 1440 rc = ENOTSUP; 1441 break; 1442 } 1443 1444 if (rc != 0) 1445 return (rc); 1446 1447 if ((pi->flags & TPF_OPEN) != 0) { 1448 if (relink != 0) { 1449 ADAPTER_LOCK(sc); 1450 rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, lc, 1451 new_caps); 1452 ADAPTER_UNLOCK(sc); 1453 if (rc != 0) { 1454 cxgb_printf(pi->dip, CE_WARN, 1455 "%s link config failed: %d", __func__, rc); 1456 return (rc); 1457 } 1458 } 1459 1460 if (rx_mode != 0) { 1461 ADAPTER_LOCK(sc); 1462 rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, v32, -1, 1463 -1, -1, -1, false); 1464 ADAPTER_UNLOCK(sc); 1465 if (rc != 0) { 1466 cxgb_printf(pi->dip, CE_WARN, 1467 "set_rxmode failed: %d", rc); 1468 return (rc); 1469 } 1470 } 1471 } 1472 1473 if (relink != 0) 1474 lc->admin_caps = new_caps; 1475 1476 return (0); 1477 } 1478 1479 static int 1480 t4_mc_getprop(void *arg, const char *name, mac_prop_id_t id, uint_t size, 1481 void *val) 1482 { 1483 struct port_info *pi = arg; 1484 struct link_config *lc = &pi->link_cfg; 1485 uint8_t *u = val; 1486 int rc = 0; 1487 1488 switch (id) { 1489 case MAC_PROP_DUPLEX: 1490 *(link_duplex_t *)val = lc->link_ok ? LINK_DUPLEX_FULL : 1491 LINK_DUPLEX_UNKNOWN; 1492 break; 1493 1494 case MAC_PROP_SPEED: 1495 if (lc->link_ok != 0) { 1496 *(uint64_t *)val = 1497 t4_link_fwcap_to_speed(lc->link_caps); 1498 *(uint64_t *)val *= 1000000; 1499 } else { 1500 *(uint64_t *)val = 0; 1501 } 1502 break; 1503 1504 case MAC_PROP_STATUS: 1505 *(link_state_t *)val = lc->link_ok ? LINK_STATE_UP : 1506 LINK_STATE_DOWN; 1507 break; 1508 1509 case MAC_PROP_MEDIA: 1510 *(mac_ether_media_t *)val = t4_port_to_media(pi); 1511 break; 1512 1513 case MAC_PROP_AUTONEG: 1514 *u = !!(lc->link_caps & FW_PORT_CAP32_ANEG); 1515 break; 1516 1517 case MAC_PROP_MTU: 1518 *(uint32_t *)val = pi->mtu; 1519 break; 1520 1521 case MAC_PROP_FLOWCTRL: 1522 t4_mac_link_caps_to_flowctrl(lc->link_caps, val); 1523 break; 1524 1525 case MAC_PROP_ADV_FEC_CAP: 1526 t4_mac_link_caps_to_fec_cap(lc->link_caps, val); 1527 break; 1528 1529 case MAC_PROP_EN_FEC_CAP: 1530 t4_mac_admin_caps_to_fec_cap(lc->admin_caps, val); 1531 break; 1532 1533 case MAC_PROP_ADV_100GFDX_CAP: 1534 *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_100G); 1535 break; 1536 1537 case MAC_PROP_EN_100GFDX_CAP: 1538 *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100G); 1539 break; 1540 1541 case MAC_PROP_ADV_50GFDX_CAP: 1542 *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_50G); 1543 break; 1544 1545 case MAC_PROP_EN_50GFDX_CAP: 1546 *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_50G); 1547 break; 1548 1549 case MAC_PROP_ADV_40GFDX_CAP: 1550 *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_40G); 1551 break; 1552 1553 case MAC_PROP_EN_40GFDX_CAP: 1554 *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_40G); 1555 break; 1556 1557 case MAC_PROP_ADV_25GFDX_CAP: 1558 *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_25G); 1559 break; 1560 1561 case MAC_PROP_EN_25GFDX_CAP: 1562 *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_25G); 1563 break; 1564 1565 case MAC_PROP_ADV_10GFDX_CAP: 1566 *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_10G); 1567 break; 1568 1569 case MAC_PROP_EN_10GFDX_CAP: 1570 *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_10G); 1571 break; 1572 1573 case MAC_PROP_ADV_1000FDX_CAP: 1574 *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_1G); 1575 break; 1576 1577 case MAC_PROP_EN_1000FDX_CAP: 1578 *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_1G); 1579 break; 1580 1581 case MAC_PROP_ADV_100FDX_CAP: 1582 *u = !!(lc->link_caps & FW_PORT_CAP32_SPEED_100M); 1583 break; 1584 1585 case MAC_PROP_EN_100FDX_CAP: 1586 *u = !!(lc->admin_caps & FW_PORT_CAP32_SPEED_100M); 1587 break; 1588 1589 case MAC_PROP_PRIVATE: 1590 return (t4_getprop_priv(pi, name, size, val)); 1591 1592 default: 1593 return (ENOTSUP); 1594 } 1595 1596 return (rc); 1597 } 1598 1599 static void 1600 t4_mc_propinfo(void *arg, const char *name, mac_prop_id_t id, 1601 mac_prop_info_handle_t ph) 1602 { 1603 struct port_info *pi = arg; 1604 struct link_config *lc = &pi->link_cfg; 1605 1606 switch (id) { 1607 case MAC_PROP_DUPLEX: 1608 case MAC_PROP_SPEED: 1609 case MAC_PROP_STATUS: 1610 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1611 break; 1612 1613 case MAC_PROP_AUTONEG: 1614 if (lc->pcaps & FW_PORT_CAP32_ANEG) 1615 mac_prop_info_set_default_uint8(ph, 1); 1616 else 1617 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1618 break; 1619 1620 case MAC_PROP_MTU: 1621 mac_prop_info_set_range_uint32(ph, 46, MAX_MTU); 1622 break; 1623 1624 case MAC_PROP_FLOWCTRL: 1625 mac_prop_info_set_default_link_flowctrl(ph, LINK_FLOWCTRL_BI); 1626 break; 1627 1628 case MAC_PROP_EN_FEC_CAP: 1629 mac_prop_info_set_default_fec(ph, LINK_FEC_AUTO); 1630 break; 1631 1632 case MAC_PROP_ADV_FEC_CAP: 1633 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1634 mac_prop_info_set_default_fec(ph, LINK_FEC_AUTO); 1635 break; 1636 1637 case MAC_PROP_EN_100GFDX_CAP: 1638 if (lc->pcaps & FW_PORT_CAP32_SPEED_100G) 1639 mac_prop_info_set_default_uint8(ph, 1); 1640 else 1641 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1642 break; 1643 1644 case MAC_PROP_EN_50GFDX_CAP: 1645 if (lc->pcaps & FW_PORT_CAP32_SPEED_50G) 1646 mac_prop_info_set_default_uint8(ph, 1); 1647 else 1648 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1649 break; 1650 1651 case MAC_PROP_EN_40GFDX_CAP: 1652 if (lc->pcaps & FW_PORT_CAP32_SPEED_40G) 1653 mac_prop_info_set_default_uint8(ph, 1); 1654 else 1655 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1656 break; 1657 1658 case MAC_PROP_EN_25GFDX_CAP: 1659 if (lc->pcaps & FW_PORT_CAP32_SPEED_25G) 1660 mac_prop_info_set_default_uint8(ph, 1); 1661 else 1662 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1663 break; 1664 1665 case MAC_PROP_EN_10GFDX_CAP: 1666 if (lc->pcaps & FW_PORT_CAP32_SPEED_10G) 1667 mac_prop_info_set_default_uint8(ph, 1); 1668 else 1669 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1670 break; 1671 1672 case MAC_PROP_EN_1000FDX_CAP: 1673 if (lc->pcaps & FW_PORT_CAP32_SPEED_1G) 1674 mac_prop_info_set_default_uint8(ph, 1); 1675 else 1676 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1677 break; 1678 1679 case MAC_PROP_EN_100FDX_CAP: 1680 if (lc->pcaps & FW_PORT_CAP32_SPEED_100M) 1681 mac_prop_info_set_default_uint8(ph, 1); 1682 else 1683 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1684 break; 1685 1686 case MAC_PROP_ADV_100GFDX_CAP: 1687 case MAC_PROP_ADV_50GFDX_CAP: 1688 case MAC_PROP_ADV_40GFDX_CAP: 1689 case MAC_PROP_ADV_25GFDX_CAP: 1690 case MAC_PROP_ADV_10GFDX_CAP: 1691 case MAC_PROP_ADV_1000FDX_CAP: 1692 case MAC_PROP_ADV_100FDX_CAP: 1693 mac_prop_info_set_perm(ph, MAC_PROP_PERM_READ); 1694 break; 1695 1696 case MAC_PROP_PRIVATE: 1697 t4_propinfo_priv(pi, name, ph); 1698 break; 1699 1700 default: 1701 break; 1702 } 1703 } 1704 1705 static int 1706 t4_init_synchronized(struct port_info *pi) 1707 { 1708 struct adapter *sc = pi->adapter; 1709 int rc = 0; 1710 1711 ADAPTER_LOCK_ASSERT_OWNED(pi->adapter); 1712 ASSERT(sc->flags & TAF_INIT_DONE); 1713 1714 PORT_LOCK(pi); 1715 1716 if ((pi->flags & TPF_OPEN) != 0) { 1717 PORT_UNLOCK(pi); 1718 return (0); /* already running */ 1719 } 1720 1721 if (!(pi->flags & TPF_INIT_DONE)) { 1722 rc = t4_port_full_init(pi); 1723 if (rc != 0) { 1724 PORT_UNLOCK(pi); 1725 return (rc); /* error message displayed already */ 1726 } 1727 } else { 1728 t4_port_queues_enable(pi); 1729 } 1730 1731 rc = -t4_set_rxmode(sc, sc->mbox, pi->viid, pi->mtu, 0, 0, 1, 0, false); 1732 if (rc != 0) { 1733 cxgb_printf(pi->dip, CE_WARN, "set_rxmode failed: %d", rc); 1734 goto done; 1735 } 1736 rc = t4_change_mac(sc, sc->mbox, pi->viid, pi->xact_addr_filt, 1737 pi->hw_addr, true, &pi->smt_idx); 1738 if (rc < 0) { 1739 cxgb_printf(pi->dip, CE_WARN, "change_mac failed: %d", rc); 1740 rc = -rc; 1741 goto done; 1742 } else { 1743 pi->xact_addr_filt = rc; 1744 } 1745 1746 rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, &pi->link_cfg, 1747 pi->link_cfg.admin_caps); 1748 if (rc != 0) { 1749 cxgb_printf(pi->dip, CE_WARN, "start_link failed: %d", rc); 1750 goto done; 1751 } 1752 1753 rc = -t4_enable_vi(sc, sc->mbox, pi->viid, true, true); 1754 if (rc != 0) { 1755 cxgb_printf(pi->dip, CE_WARN, "enable_vi failed: %d", rc); 1756 goto done; 1757 } 1758 1759 /* all ok */ 1760 pi->flags |= TPF_OPEN; 1761 done: 1762 PORT_UNLOCK(pi); 1763 if (rc != 0) 1764 (void) t4_uninit_synchronized(pi); 1765 1766 return (rc); 1767 } 1768 1769 /* 1770 * Idempotent. 1771 */ 1772 static int 1773 t4_uninit_synchronized(struct port_info *pi) 1774 { 1775 struct adapter *sc = pi->adapter; 1776 int rc; 1777 1778 ADAPTER_LOCK_ASSERT_OWNED(pi->adapter); 1779 1780 PORT_LOCK(pi); 1781 /* 1782 * Disable the VI so that all its data in either direction is discarded 1783 * by the MPS. Leave everything else (the queues, interrupts, and 1Hz 1784 * tick) intact as the TP can deliver negative advice or data that it's 1785 * holding in its RAM (for an offloaded connection) even after the VI is 1786 * disabled. 1787 */ 1788 rc = -t4_enable_vi(sc, sc->mbox, pi->viid, false, false); 1789 if (rc != 0) { 1790 cxgb_printf(pi->dip, CE_WARN, "disable_vi failed: %d", rc); 1791 PORT_UNLOCK(pi); 1792 return (rc); 1793 } 1794 1795 t4_port_queues_disable(pi); 1796 1797 pi->flags &= ~TPF_OPEN; 1798 pi->link_cfg.link_ok = 0; 1799 PORT_UNLOCK(pi); 1800 1801 mac_link_update(pi->mh, LINK_STATE_UNKNOWN); 1802 1803 return (0); 1804 } 1805 1806 static uint_t 1807 t4_convert_holdoff_timer(struct adapter *sc, uint_t idx) 1808 { 1809 ASSERT(idx < SGE_NTIMERS); 1810 return (sc->props.holdoff_timer_us[idx]); 1811 } 1812 1813 static int 1814 t4_convert_holdoff_pktcnt(struct adapter *sc, int idx) 1815 { 1816 if (idx < 0) { 1817 return (-1); 1818 } else { 1819 ASSERT(idx < SGE_NCOUNTERS); 1820 return (sc->props.holdoff_pktcnt[idx]); 1821 } 1822 } 1823 1824 static uint_t 1825 t4_convert_dbq_timer(struct adapter *sc, uint_t idx) 1826 { 1827 ASSERT(idx < SGE_NDBQTIMERS); 1828 return (sc->sge.dbq_timers[idx]); 1829 } 1830 1831 static void 1832 t4_propinfo_priv(struct port_info *pi, const char *name, 1833 mac_prop_info_handle_t ph) 1834 { 1835 struct adapter *sc = pi->adapter; 1836 struct driver_properties *dp = &sc->props; 1837 struct link_config *lc = &pi->link_cfg; 1838 1839 const t4_priv_prop_t *prop = t4_priv_prop_match(name); 1840 if (prop == NULL || !t4_priv_prop_supported(pi, prop)) { 1841 return; 1842 } 1843 1844 int v = 0; 1845 switch (prop->tpp_id) { 1846 case T4PROP_FW_TMR: 1847 v = t4_convert_holdoff_timer(sc, sc->props.fwq_tmr_idx); 1848 break; 1849 case T4PROP_FW_PKTC: 1850 v = t4_convert_holdoff_pktcnt(sc, sc->props.fwq_pktc_idx); 1851 break; 1852 case T4PROP_RX_TMR: 1853 v = t4_convert_holdoff_timer(sc, t4_port_is_10xg(pi) ? 1854 dp->tmr_idx_10g : dp->tmr_idx_1g); 1855 break; 1856 case T4PROP_RX_PKTC: 1857 v = t4_convert_holdoff_pktcnt(sc, t4_port_is_10xg(pi) ? 1858 dp->pktc_idx_10g : dp->pktc_idx_1g); 1859 break; 1860 case T4PROP_TX_TMR: 1861 v = t4_convert_dbq_timer(sc, dp->dbq_timer_idx); 1862 break; 1863 case T4PROP_HW_CSUM: 1864 v = (pi->features & CXGBE_HW_CSUM) ? 1 : 0; 1865 break; 1866 case T4PROP_HW_LSO: 1867 v = (pi->features & CXGBE_HW_LSO) ? 1 : 0; 1868 break; 1869 case T4PROP_TX_PAUSE: 1870 v = (lc->pcaps & FW_PORT_CAP32_FC_TX) ? 1 : 0; 1871 break; 1872 case T4PROP_RX_PAUSE: 1873 v = (lc->pcaps & FW_PORT_CAP32_FC_RX) ? 1 : 0; 1874 break; 1875 default: 1876 return; 1877 } 1878 1879 char str[16]; 1880 (void) snprintf(str, sizeof (str), "%d", v); 1881 mac_prop_info_set_default_str(ph, str); 1882 } 1883 1884 static int 1885 t4_getprop_priv(struct port_info *pi, const char *name, uint_t size, void *val) 1886 { 1887 struct adapter *sc = pi->adapter; 1888 struct link_config *lc = &pi->link_cfg; 1889 1890 const t4_priv_prop_t *prop = t4_priv_prop_match(name); 1891 if (prop == NULL || !t4_priv_prop_supported(pi, prop)) { 1892 return (ENOTSUP); 1893 } 1894 1895 PORT_LOCK(pi); 1896 int v = 0; 1897 switch (prop->tpp_id) { 1898 case T4PROP_FW_TMR: 1899 v = t4_convert_holdoff_timer(sc, sc->sge.fwq_tmr_idx); 1900 break; 1901 case T4PROP_FW_PKTC: 1902 v = t4_convert_holdoff_pktcnt(sc, sc->sge.fwq_pktc_idx); 1903 break; 1904 case T4PROP_RX_TMR: 1905 v = t4_convert_holdoff_timer(sc, pi->tmr_idx); 1906 break; 1907 case T4PROP_RX_PKTC: 1908 v = t4_convert_holdoff_pktcnt(sc, pi->pktc_idx); 1909 break; 1910 case T4PROP_TX_TMR: 1911 v = t4_convert_dbq_timer(sc, pi->dbq_timer_idx); 1912 break; 1913 case T4PROP_HW_CSUM: 1914 v = (pi->features & CXGBE_HW_CSUM) ? 1 : 0; 1915 break; 1916 case T4PROP_HW_LSO: 1917 v = (pi->features & CXGBE_HW_LSO) ? 1 : 0; 1918 break; 1919 case T4PROP_TX_PAUSE: 1920 v = (lc->link_caps & FW_PORT_CAP32_FC_TX) ? 1 : 0; 1921 break; 1922 case T4PROP_RX_PAUSE: 1923 v = (lc->link_caps & FW_PORT_CAP32_FC_RX) ? 1 : 0; 1924 break; 1925 default: 1926 PORT_UNLOCK(pi); 1927 return (ENOTSUP); 1928 } 1929 PORT_UNLOCK(pi); 1930 1931 (void) snprintf(val, size, "%d", v); 1932 return (0); 1933 } 1934 1935 #define ABS_DELTA(left, right) \ 1936 (((left) > (right)) ? (left) - (right) : (right) - (left)) 1937 1938 uint8_t 1939 t4_choose_holdoff_timer(struct adapter *sc, uint_t target_us) 1940 { 1941 const uint_t *timer_us = sc->props.holdoff_timer_us; 1942 1943 uint_t delta = UINT_MAX; 1944 uint_t chosen_idx = 0; 1945 for (uint_t i = 0; i < SGE_NTIMERS; i++) { 1946 const uint_t next_delta = ABS_DELTA(target_us, timer_us[i]); 1947 1948 if (next_delta < delta) { 1949 chosen_idx = i; 1950 delta = next_delta; 1951 } 1952 } 1953 1954 ASSERT3U(chosen_idx, <, SGE_NTIMERS); 1955 return (chosen_idx); 1956 } 1957 1958 int8_t 1959 t4_choose_holdoff_pktcnt(struct adapter *sc, int target_cnt) 1960 { 1961 const uint_t *pkt_cnt = sc->props.holdoff_pktcnt; 1962 1963 if (target_cnt <= 0) { 1964 /* -1 is sentinel value for do-not-use */ 1965 return (-1); 1966 } 1967 1968 uint_t delta = UINT_MAX; 1969 uint_t chosen_idx = 0; 1970 for (uint_t i = 0; i < SGE_NCOUNTERS; i++) { 1971 const uint_t next_delta = ABS_DELTA(target_cnt, pkt_cnt[i]); 1972 1973 if (next_delta < delta) { 1974 chosen_idx = i; 1975 delta = next_delta; 1976 } 1977 } 1978 1979 ASSERT3U(chosen_idx, <, SGE_NCOUNTERS); 1980 return (chosen_idx); 1981 } 1982 1983 uint_t 1984 t4_choose_dbq_timer(struct adapter *sc, uint_t target_us) 1985 { 1986 const uint16_t *dbq_us = sc->sge.dbq_timers; 1987 1988 uint_t delta = UINT_MAX; 1989 uint_t chosen_idx = 0; 1990 for (uint_t i = 0; i < SGE_NDBQTIMERS; i++) { 1991 const uint_t next_delta = ABS_DELTA(target_us, dbq_us[i]); 1992 1993 if (next_delta < delta) { 1994 chosen_idx = i; 1995 delta = next_delta; 1996 } 1997 } 1998 1999 ASSERT3U(chosen_idx, <, SGE_NDBQTIMERS); 2000 return (chosen_idx); 2001 } 2002 2003 2004 static int 2005 t4_setprop_priv(struct port_info *pi, const char *name, const void *val) 2006 { 2007 struct adapter *sc = pi->adapter; 2008 long v; 2009 2010 const t4_priv_prop_t *prop = t4_priv_prop_match(name); 2011 if (prop == NULL || !t4_priv_prop_supported(pi, prop)) { 2012 return (ENOTSUP); 2013 } 2014 2015 (void) ddi_strtol(val, NULL, 0, &v); 2016 if (prop->tpp_is_bool && v != 0 && v != 1) { 2017 return (EINVAL); 2018 } 2019 const bool vbool = (v != 0); 2020 2021 /* XXX: this needs better locking to deal with adapter init */ 2022 2023 bool update_rx_intr_cfg = false; 2024 bool update_link_cfg = false; 2025 struct link_config *lc = &pi->link_cfg; 2026 fw_port_cap32_t new_caps = lc->admin_caps; 2027 cc_pause_t fc = 0; 2028 2029 switch (prop->tpp_id) { 2030 case T4PROP_FW_TMR: { 2031 struct sge_iq *fwq = &sc->sge.fwq; 2032 const uint8_t idx = t4_choose_holdoff_timer(sc, MAX(0, v)); 2033 2034 IQ_LOCK(fwq); 2035 sc->sge.fwq_tmr_idx = idx; 2036 t4_iq_update_intr_cfg(fwq, sc->sge.fwq_tmr_idx, 2037 sc->sge.fwq_pktc_idx); 2038 IQ_UNLOCK(fwq); 2039 break; 2040 } 2041 case T4PROP_FW_PKTC: { 2042 struct sge_iq *fwq = &sc->sge.fwq; 2043 const int8_t idx = t4_choose_holdoff_pktcnt(sc, (int)v); 2044 2045 IQ_LOCK(fwq); 2046 sc->sge.fwq_pktc_idx = idx; 2047 t4_iq_update_intr_cfg(fwq, sc->sge.fwq_tmr_idx, 2048 sc->sge.fwq_pktc_idx); 2049 IQ_UNLOCK(fwq); 2050 break; 2051 } 2052 case T4PROP_RX_TMR: { 2053 const uint8_t idx = t4_choose_holdoff_timer(sc, MAX(0, v)); 2054 if (idx != pi->tmr_idx) { 2055 pi->tmr_idx = idx; 2056 update_rx_intr_cfg = true; 2057 } 2058 break; 2059 } 2060 case T4PROP_RX_PKTC: { 2061 const int8_t idx = t4_choose_holdoff_pktcnt(sc, (int)v); 2062 if (idx != pi->pktc_idx) { 2063 pi->pktc_idx = idx; 2064 update_rx_intr_cfg = true; 2065 } 2066 break; 2067 } 2068 case T4PROP_TX_TMR: { 2069 ASSERT(sc->flags & TAF_DBQ_TIMER); 2070 if (v <= 0) { 2071 return (EINVAL); 2072 } 2073 const uint_t idx = t4_choose_dbq_timer(sc, (uint_t)v); 2074 PORT_LOCK(pi); 2075 if ((pi->flags & TPF_OPEN) != 0 && 2076 idx != pi->dbq_timer_idx) { 2077 pi->dbq_timer_idx = idx; 2078 2079 int i; 2080 struct sge_txq *txq; 2081 for_each_txq(pi, i, txq) { 2082 struct sge_eq *eq = &txq->eq; 2083 2084 EQ_LOCK(eq); 2085 t4_eq_update_dbq_timer(eq, pi); 2086 EQ_UNLOCK(eq); 2087 } 2088 } 2089 PORT_UNLOCK(pi); 2090 return (0); 2091 } 2092 case T4PROP_HW_CSUM: 2093 if (vbool) 2094 pi->features |= CXGBE_HW_CSUM; 2095 else 2096 pi->features &= ~CXGBE_HW_CSUM; 2097 break; 2098 case T4PROP_HW_LSO: 2099 if (vbool) 2100 pi->features |= CXGBE_HW_LSO; 2101 else 2102 pi->features &= ~CXGBE_HW_LSO; 2103 break; 2104 case T4PROP_TX_PAUSE: 2105 case T4PROP_RX_PAUSE: 2106 if (new_caps & FW_PORT_CAP32_FC_TX) { 2107 if (prop->tpp_id == T4PROP_TX_PAUSE) { 2108 fc |= vbool ? PAUSE_TX : 0; 2109 } else { 2110 fc |= PAUSE_TX; 2111 } 2112 } 2113 if (new_caps & FW_PORT_CAP32_FC_RX) { 2114 if (prop->tpp_id == T4PROP_RX_PAUSE) { 2115 fc |= vbool ? PAUSE_RX : 0; 2116 } else { 2117 fc |= PAUSE_RX; 2118 } 2119 } 2120 if (new_caps & FW_PORT_CAP32_ANEG) { 2121 fc |= PAUSE_AUTONEG; 2122 } 2123 update_link_cfg = true; 2124 break; 2125 default: 2126 return (ENOTSUP); 2127 } 2128 2129 if (update_rx_intr_cfg) { 2130 struct sge_rxq *rxq; 2131 int i; 2132 2133 PORT_LOCK(pi); 2134 if ((pi->flags & TPF_OPEN) != 0) { 2135 for_each_rxq(pi, i, rxq) { 2136 struct sge_iq *iq = &rxq->iq; 2137 2138 IQ_LOCK(iq); 2139 t4_iq_update_intr_cfg(iq, pi->tmr_idx, 2140 pi->pktc_idx); 2141 IQ_UNLOCK(iq); 2142 } 2143 } 2144 PORT_UNLOCK(pi); 2145 } 2146 if (update_link_cfg) { 2147 int rc = 0; 2148 2149 ADAPTER_LOCK(pi->adapter); 2150 PORT_LOCK(pi); 2151 t4_link_set_pause(pi, fc, &new_caps); 2152 if ((pi->flags & TPF_OPEN) != 0) { 2153 rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, lc, 2154 new_caps); 2155 if (rc != 0) { 2156 cxgb_printf(pi->dip, CE_WARN, 2157 "%s link config failed: %d", 2158 __func__, rc); 2159 } 2160 } 2161 2162 if (rc == 0) { 2163 lc->admin_caps = new_caps; 2164 } 2165 PORT_UNLOCK(pi); 2166 ADAPTER_UNLOCK(pi->adapter); 2167 return (rc); 2168 } 2169 2170 return (0); 2171 } 2172 2173 void 2174 t4_mc_cb_init(struct port_info *pi) 2175 { 2176 if (pi->adapter->props.multi_rings) 2177 pi->mc = &t4_m_ring_callbacks; 2178 else 2179 pi->mc = &t4_m_callbacks; 2180 } 2181 2182 void 2183 t4_os_link_changed(struct adapter *sc, int idx, int link_stat) 2184 { 2185 struct port_info *pi = sc->port[idx]; 2186 2187 mac_link_update(pi->mh, link_stat ? LINK_STATE_UP : LINK_STATE_DOWN); 2188 } 2189 2190 /* ARGSUSED */ 2191 void 2192 t4_mac_rx(struct port_info *pi, struct sge_rxq *rxq, mblk_t *m) 2193 { 2194 mac_rx(pi->mh, NULL, m); 2195 } 2196 2197 void 2198 t4_mac_tx_update(struct port_info *pi, struct sge_txq *txq) 2199 { 2200 if (pi->adapter->props.multi_rings) 2201 mac_tx_ring_update(pi->mh, txq->ring_handle); 2202 else 2203 mac_tx_update(pi->mh); 2204 } 2205