|
58 | 58 |
|
59 | 59 | #define NSP_ETH_PORT_LANES_MASK cpu_to_le64(NSP_ETH_PORT_LANES) |
60 | 60 |
|
| 61 | +#define NSP_ETH_STATE_CONFIGURED BIT_ULL(0) |
61 | 62 | #define NSP_ETH_STATE_ENABLED BIT_ULL(1) |
62 | 63 | #define NSP_ETH_STATE_TX_ENABLED BIT_ULL(2) |
63 | 64 | #define NSP_ETH_STATE_RX_ENABLED BIT_ULL(3) |
|
67 | 68 | #define NSP_ETH_STATE_OVRD_CHNG BIT_ULL(22) |
68 | 69 | #define NSP_ETH_STATE_ANEG GENMASK_ULL(25, 23) |
69 | 70 |
|
| 71 | +#define NSP_ETH_CTRL_CONFIGURED BIT_ULL(0) |
70 | 72 | #define NSP_ETH_CTRL_ENABLED BIT_ULL(1) |
71 | 73 | #define NSP_ETH_CTRL_TX_ENABLED BIT_ULL(2) |
72 | 74 | #define NSP_ETH_CTRL_RX_ENABLED BIT_ULL(3) |
| 75 | +#define NSP_ETH_CTRL_SET_RATE BIT_ULL(4) |
| 76 | +#define NSP_ETH_CTRL_SET_LANES BIT_ULL(5) |
| 77 | +#define NSP_ETH_CTRL_SET_ANEG BIT_ULL(6) |
73 | 78 |
|
74 | 79 | enum nfp_eth_raw { |
75 | 80 | NSP_ETH_RAW_PORT = 0, |
@@ -100,21 +105,38 @@ union eth_table_entry { |
100 | 105 | __le64 raw[NSP_ETH_NUM_RAW]; |
101 | 106 | }; |
102 | 107 |
|
103 | | -static unsigned int nfp_eth_rate(enum nfp_eth_rate rate) |
| 108 | +static const struct { |
| 109 | + enum nfp_eth_rate rate; |
| 110 | + unsigned int speed; |
| 111 | +} nsp_eth_rate_tbl[] = { |
| 112 | + { RATE_INVALID, 0, }, |
| 113 | + { RATE_10M, SPEED_10, }, |
| 114 | + { RATE_100M, SPEED_100, }, |
| 115 | + { RATE_1G, SPEED_1000, }, |
| 116 | + { RATE_10G, SPEED_10000, }, |
| 117 | + { RATE_25G, SPEED_25000, }, |
| 118 | +}; |
| 119 | + |
| 120 | +static unsigned int nfp_eth_rate2speed(enum nfp_eth_rate rate) |
104 | 121 | { |
105 | | - unsigned int rate_xlate[] = { |
106 | | - [RATE_INVALID] = 0, |
107 | | - [RATE_10M] = SPEED_10, |
108 | | - [RATE_100M] = SPEED_100, |
109 | | - [RATE_1G] = SPEED_1000, |
110 | | - [RATE_10G] = SPEED_10000, |
111 | | - [RATE_25G] = SPEED_25000, |
112 | | - }; |
| 122 | + int i; |
113 | 123 |
|
114 | | - if (rate >= ARRAY_SIZE(rate_xlate)) |
115 | | - return 0; |
| 124 | + for (i = 0; i < ARRAY_SIZE(nsp_eth_rate_tbl); i++) |
| 125 | + if (nsp_eth_rate_tbl[i].rate == rate) |
| 126 | + return nsp_eth_rate_tbl[i].speed; |
| 127 | + |
| 128 | + return 0; |
| 129 | +} |
| 130 | + |
| 131 | +static unsigned int nfp_eth_speed2rate(unsigned int speed) |
| 132 | +{ |
| 133 | + int i; |
| 134 | + |
| 135 | + for (i = 0; i < ARRAY_SIZE(nsp_eth_rate_tbl); i++) |
| 136 | + if (nsp_eth_rate_tbl[i].speed == speed) |
| 137 | + return nsp_eth_rate_tbl[i].rate; |
116 | 138 |
|
117 | | - return rate_xlate[rate]; |
| 139 | + return RATE_INVALID; |
118 | 140 | } |
119 | 141 |
|
120 | 142 | static void nfp_eth_copy_mac_reverse(u8 *dst, const u8 *src) |
@@ -145,7 +167,7 @@ nfp_eth_port_translate(struct nfp_nsp *nsp, const union eth_table_entry *src, |
145 | 167 | dst->tx_enabled = FIELD_GET(NSP_ETH_STATE_TX_ENABLED, state); |
146 | 168 | dst->rx_enabled = FIELD_GET(NSP_ETH_STATE_RX_ENABLED, state); |
147 | 169 |
|
148 | | - rate = nfp_eth_rate(FIELD_GET(NSP_ETH_STATE_RATE, state)); |
| 170 | + rate = nfp_eth_rate2speed(FIELD_GET(NSP_ETH_STATE_RATE, state)); |
149 | 171 | dst->speed = dst->lanes * rate; |
150 | 172 |
|
151 | 173 | dst->interface = FIELD_GET(NSP_ETH_STATE_INTERFACE, state); |
@@ -392,3 +414,135 @@ int nfp_eth_set_mod_enable(struct nfp_cpp *cpp, unsigned int idx, bool enable) |
392 | 414 |
|
393 | 415 | return nfp_eth_config_commit_end(nsp); |
394 | 416 | } |
| 417 | + |
| 418 | +/** |
| 419 | + * nfp_eth_set_configured() - set PHY module configured control bit |
| 420 | + * @cpp: NFP CPP handle |
| 421 | + * @idx: NFP chip-wide port index |
| 422 | + * @configed: Desired state |
| 423 | + * |
| 424 | + * Set the ifup/ifdown state on the PHY. |
| 425 | + * |
| 426 | + * Return: 0 or -ERRNO. |
| 427 | + */ |
| 428 | +int nfp_eth_set_configured(struct nfp_cpp *cpp, unsigned int idx, bool configed) |
| 429 | +{ |
| 430 | + union eth_table_entry *entries; |
| 431 | + struct nfp_nsp *nsp; |
| 432 | + u64 reg; |
| 433 | + |
| 434 | + nsp = nfp_eth_config_start(cpp, idx); |
| 435 | + if (IS_ERR(nsp)) |
| 436 | + return PTR_ERR(nsp); |
| 437 | + |
| 438 | + entries = nfp_nsp_config_entries(nsp); |
| 439 | + |
| 440 | + /* Check if we are already in requested state */ |
| 441 | + reg = le64_to_cpu(entries[idx].state); |
| 442 | + if (configed != FIELD_GET(NSP_ETH_STATE_CONFIGURED, reg)) { |
| 443 | + reg = le64_to_cpu(entries[idx].control); |
| 444 | + reg &= ~NSP_ETH_CTRL_CONFIGURED; |
| 445 | + reg |= FIELD_PREP(NSP_ETH_CTRL_CONFIGURED, configed); |
| 446 | + entries[idx].control = cpu_to_le64(reg); |
| 447 | + |
| 448 | + nfp_nsp_config_set_modified(nsp, true); |
| 449 | + } |
| 450 | + |
| 451 | + return nfp_eth_config_commit_end(nsp); |
| 452 | +} |
| 453 | + |
| 454 | +/* Force inline, FIELD_* macroes require masks to be compilation-time known */ |
| 455 | +static __always_inline int |
| 456 | +nfp_eth_set_bit_config(struct nfp_nsp *nsp, unsigned int raw_idx, |
| 457 | + const u64 mask, unsigned int val, const u64 ctrl_bit) |
| 458 | +{ |
| 459 | + union eth_table_entry *entries = nfp_nsp_config_entries(nsp); |
| 460 | + unsigned int idx = nfp_nsp_config_idx(nsp); |
| 461 | + u64 reg; |
| 462 | + |
| 463 | + /* Note: set features were added in ABI 0.14 but the error |
| 464 | + * codes were initially not populated correctly. |
| 465 | + */ |
| 466 | + if (nfp_nsp_get_abi_ver_minor(nsp) < 17) { |
| 467 | + nfp_err(nfp_nsp_cpp(nsp), |
| 468 | + "set operations not supported, please update flash\n"); |
| 469 | + return -EOPNOTSUPP; |
| 470 | + } |
| 471 | + |
| 472 | + /* Check if we are already in requested state */ |
| 473 | + reg = le64_to_cpu(entries[idx].raw[raw_idx]); |
| 474 | + if (val == FIELD_GET(mask, reg)) |
| 475 | + return 0; |
| 476 | + |
| 477 | + reg &= ~mask; |
| 478 | + reg |= FIELD_PREP(mask, val); |
| 479 | + entries[idx].raw[raw_idx] = cpu_to_le64(reg); |
| 480 | + |
| 481 | + entries[idx].control |= cpu_to_le64(ctrl_bit); |
| 482 | + |
| 483 | + nfp_nsp_config_set_modified(nsp, true); |
| 484 | + |
| 485 | + return 0; |
| 486 | +} |
| 487 | + |
| 488 | +/** |
| 489 | + * __nfp_eth_set_aneg() - set PHY autonegotiation control bit |
| 490 | + * @nsp: NFP NSP handle returned from nfp_eth_config_start() |
| 491 | + * @mode: Desired autonegotiation mode |
| 492 | + * |
| 493 | + * Allow/disallow PHY module to advertise/perform autonegotiation. |
| 494 | + * Will write to hwinfo overrides in the flash (persistent config). |
| 495 | + * |
| 496 | + * Return: 0 or -ERRNO. |
| 497 | + */ |
| 498 | +int __nfp_eth_set_aneg(struct nfp_nsp *nsp, enum nfp_eth_aneg mode) |
| 499 | +{ |
| 500 | + return nfp_eth_set_bit_config(nsp, NSP_ETH_RAW_STATE, |
| 501 | + NSP_ETH_STATE_ANEG, mode, |
| 502 | + NSP_ETH_CTRL_SET_ANEG); |
| 503 | +} |
| 504 | + |
| 505 | +/** |
| 506 | + * __nfp_eth_set_speed() - set interface speed/rate |
| 507 | + * @nsp: NFP NSP handle returned from nfp_eth_config_start() |
| 508 | + * @speed: Desired speed (per lane) |
| 509 | + * |
| 510 | + * Set lane speed. Provided @speed value should be subport speed divided |
| 511 | + * by number of lanes this subport is spanning (i.e. 10000 for 40G, 25000 for |
| 512 | + * 50G, etc.) |
| 513 | + * Will write to hwinfo overrides in the flash (persistent config). |
| 514 | + * |
| 515 | + * Return: 0 or -ERRNO. |
| 516 | + */ |
| 517 | +int __nfp_eth_set_speed(struct nfp_nsp *nsp, unsigned int speed) |
| 518 | +{ |
| 519 | + enum nfp_eth_rate rate; |
| 520 | + |
| 521 | + rate = nfp_eth_speed2rate(speed); |
| 522 | + if (rate == RATE_INVALID) { |
| 523 | + nfp_warn(nfp_nsp_cpp(nsp), |
| 524 | + "could not find matching lane rate for speed %u\n", |
| 525 | + speed); |
| 526 | + return -EINVAL; |
| 527 | + } |
| 528 | + |
| 529 | + return nfp_eth_set_bit_config(nsp, NSP_ETH_RAW_STATE, |
| 530 | + NSP_ETH_STATE_RATE, rate, |
| 531 | + NSP_ETH_CTRL_SET_RATE); |
| 532 | +} |
| 533 | + |
| 534 | +/** |
| 535 | + * __nfp_eth_set_split() - set interface lane split |
| 536 | + * @nsp: NFP NSP handle returned from nfp_eth_config_start() |
| 537 | + * @lanes: Desired lanes per port |
| 538 | + * |
| 539 | + * Set number of lanes in the port. |
| 540 | + * Will write to hwinfo overrides in the flash (persistent config). |
| 541 | + * |
| 542 | + * Return: 0 or -ERRNO. |
| 543 | + */ |
| 544 | +int __nfp_eth_set_split(struct nfp_nsp *nsp, unsigned int lanes) |
| 545 | +{ |
| 546 | + return nfp_eth_set_bit_config(nsp, NSP_ETH_RAW_PORT, NSP_ETH_PORT_LANES, |
| 547 | + lanes, NSP_ETH_CTRL_SET_LANES); |
| 548 | +} |
0 commit comments