1 // SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) 2 /* Copyright (C) 2015-2017 Netronome Systems, Inc. */ 3 4 /* Authors: David Brunecz <david.brunecz@netronome.com> 5 * Jakub Kicinski <jakub.kicinski@netronome.com> 6 * Jason Mcmullan <jason.mcmullan@netronome.com> 7 */ 8 9 #include <linux/bitfield.h> 10 #include <linux/ethtool.h> 11 #include <linux/if_ether.h> 12 #include <linux/kernel.h> 13 #include <linux/module.h> 14 15 #include "nfp.h" 16 #include "nfp_nsp.h" 17 #include "nfp6000/nfp6000.h" 18 19 #define NSP_ETH_NBI_PORT_COUNT 24 20 #define NSP_ETH_MAX_COUNT (2 * NSP_ETH_NBI_PORT_COUNT) 21 #define NSP_ETH_TABLE_SIZE (NSP_ETH_MAX_COUNT * \ 22 sizeof(union eth_table_entry)) 23 24 #define NSP_ETH_PORT_LANES GENMASK_ULL(3, 0) 25 #define NSP_ETH_PORT_INDEX GENMASK_ULL(15, 8) 26 #define NSP_ETH_PORT_LABEL GENMASK_ULL(53, 48) 27 #define NSP_ETH_PORT_PHYLABEL GENMASK_ULL(59, 54) 28 #define NSP_ETH_PORT_FEC_SUPP_BASER BIT_ULL(60) 29 #define NSP_ETH_PORT_FEC_SUPP_RS BIT_ULL(61) 30 #define NSP_ETH_PORT_SUPP_ANEG BIT_ULL(63) 31 32 #define NSP_ETH_PORT_LANES_MASK cpu_to_le64(NSP_ETH_PORT_LANES) 33 34 #define NSP_ETH_STATE_CONFIGURED BIT_ULL(0) 35 #define NSP_ETH_STATE_ENABLED BIT_ULL(1) 36 #define NSP_ETH_STATE_TX_ENABLED BIT_ULL(2) 37 #define NSP_ETH_STATE_RX_ENABLED BIT_ULL(3) 38 #define NSP_ETH_STATE_RATE GENMASK_ULL(11, 8) 39 #define NSP_ETH_STATE_INTERFACE GENMASK_ULL(19, 12) 40 #define NSP_ETH_STATE_MEDIA GENMASK_ULL(21, 20) 41 #define NSP_ETH_STATE_OVRD_CHNG BIT_ULL(22) 42 #define NSP_ETH_STATE_ANEG GENMASK_ULL(25, 23) 43 #define NSP_ETH_STATE_FEC GENMASK_ULL(27, 26) 44 #define NSP_ETH_STATE_ACT_FEC GENMASK_ULL(29, 28) 45 46 #define NSP_ETH_CTRL_CONFIGURED BIT_ULL(0) 47 #define NSP_ETH_CTRL_ENABLED BIT_ULL(1) 48 #define NSP_ETH_CTRL_TX_ENABLED BIT_ULL(2) 49 #define NSP_ETH_CTRL_RX_ENABLED BIT_ULL(3) 50 #define NSP_ETH_CTRL_SET_RATE BIT_ULL(4) 51 #define NSP_ETH_CTRL_SET_LANES BIT_ULL(5) 52 #define NSP_ETH_CTRL_SET_ANEG BIT_ULL(6) 53 #define NSP_ETH_CTRL_SET_FEC BIT_ULL(7) 54 #define NSP_ETH_CTRL_SET_IDMODE BIT_ULL(8) 55 56 enum nfp_eth_raw { 57 NSP_ETH_RAW_PORT = 0, 58 NSP_ETH_RAW_STATE, 59 NSP_ETH_RAW_MAC, 60 NSP_ETH_RAW_CONTROL, 61 62 NSP_ETH_NUM_RAW 63 }; 64 65 enum nfp_eth_rate { 66 RATE_INVALID = 0, 67 RATE_10M, 68 RATE_100M, 69 RATE_1G, 70 RATE_10G, 71 RATE_25G, 72 }; 73 74 union eth_table_entry { 75 struct { 76 __le64 port; 77 __le64 state; 78 u8 mac_addr[6]; 79 u8 resv[2]; 80 __le64 control; 81 }; 82 __le64 raw[NSP_ETH_NUM_RAW]; 83 }; 84 85 static const struct { 86 enum nfp_eth_rate rate; 87 unsigned int speed; 88 } nsp_eth_rate_tbl[] = { 89 { RATE_INVALID, 0, }, 90 { RATE_10M, SPEED_10, }, 91 { RATE_100M, SPEED_100, }, 92 { RATE_1G, SPEED_1000, }, 93 { RATE_10G, SPEED_10000, }, 94 { RATE_25G, SPEED_25000, }, 95 }; 96 97 static unsigned int nfp_eth_rate2speed(enum nfp_eth_rate rate) 98 { 99 int i; 100 101 for (i = 0; i < ARRAY_SIZE(nsp_eth_rate_tbl); i++) 102 if (nsp_eth_rate_tbl[i].rate == rate) 103 return nsp_eth_rate_tbl[i].speed; 104 105 return 0; 106 } 107 108 static unsigned int nfp_eth_speed2rate(unsigned int speed) 109 { 110 int i; 111 112 for (i = 0; i < ARRAY_SIZE(nsp_eth_rate_tbl); i++) 113 if (nsp_eth_rate_tbl[i].speed == speed) 114 return nsp_eth_rate_tbl[i].rate; 115 116 return RATE_INVALID; 117 } 118 119 static void nfp_eth_copy_mac_reverse(u8 *dst, const u8 *src) 120 { 121 int i; 122 123 for (i = 0; i < ETH_ALEN; i++) 124 dst[ETH_ALEN - i - 1] = src[i]; 125 } 126 127 static void 128 nfp_eth_port_translate(struct nfp_nsp *nsp, const union eth_table_entry *src, 129 unsigned int index, struct nfp_eth_table_port *dst) 130 { 131 unsigned int rate; 132 unsigned int fec; 133 u64 port, state; 134 135 port = le64_to_cpu(src->port); 136 state = le64_to_cpu(src->state); 137 138 dst->eth_index = FIELD_GET(NSP_ETH_PORT_INDEX, port); 139 dst->index = index; 140 dst->nbi = index / NSP_ETH_NBI_PORT_COUNT; 141 dst->base = index % NSP_ETH_NBI_PORT_COUNT; 142 dst->lanes = FIELD_GET(NSP_ETH_PORT_LANES, port); 143 144 dst->enabled = FIELD_GET(NSP_ETH_STATE_ENABLED, state); 145 dst->tx_enabled = FIELD_GET(NSP_ETH_STATE_TX_ENABLED, state); 146 dst->rx_enabled = FIELD_GET(NSP_ETH_STATE_RX_ENABLED, state); 147 148 rate = nfp_eth_rate2speed(FIELD_GET(NSP_ETH_STATE_RATE, state)); 149 dst->speed = dst->lanes * rate; 150 151 dst->interface = FIELD_GET(NSP_ETH_STATE_INTERFACE, state); 152 dst->media = FIELD_GET(NSP_ETH_STATE_MEDIA, state); 153 154 nfp_eth_copy_mac_reverse(dst->mac_addr, src->mac_addr); 155 156 dst->label_port = FIELD_GET(NSP_ETH_PORT_PHYLABEL, port); 157 dst->label_subport = FIELD_GET(NSP_ETH_PORT_LABEL, port); 158 159 if (nfp_nsp_get_abi_ver_minor(nsp) < 17) 160 return; 161 162 dst->override_changed = FIELD_GET(NSP_ETH_STATE_OVRD_CHNG, state); 163 dst->aneg = FIELD_GET(NSP_ETH_STATE_ANEG, state); 164 165 if (nfp_nsp_get_abi_ver_minor(nsp) < 22) 166 return; 167 168 fec = FIELD_GET(NSP_ETH_PORT_FEC_SUPP_BASER, port); 169 dst->fec_modes_supported |= fec << NFP_FEC_BASER_BIT; 170 fec = FIELD_GET(NSP_ETH_PORT_FEC_SUPP_RS, port); 171 dst->fec_modes_supported |= fec << NFP_FEC_REED_SOLOMON_BIT; 172 if (dst->fec_modes_supported) 173 dst->fec_modes_supported |= NFP_FEC_AUTO | NFP_FEC_DISABLED; 174 175 dst->fec = FIELD_GET(NSP_ETH_STATE_FEC, state); 176 dst->act_fec = dst->fec; 177 178 if (nfp_nsp_get_abi_ver_minor(nsp) < 33) 179 return; 180 181 dst->act_fec = FIELD_GET(NSP_ETH_STATE_ACT_FEC, state); 182 dst->supp_aneg = FIELD_GET(NSP_ETH_PORT_SUPP_ANEG, port); 183 } 184 185 static void 186 nfp_eth_calc_port_geometry(struct nfp_cpp *cpp, struct nfp_eth_table *table) 187 { 188 unsigned int i, j; 189 190 for (i = 0; i < table->count; i++) { 191 table->max_index = max(table->max_index, table->ports[i].index); 192 193 for (j = 0; j < table->count; j++) { 194 if (table->ports[i].label_port != 195 table->ports[j].label_port) 196 continue; 197 table->ports[i].port_lanes += table->ports[j].lanes; 198 199 if (i == j) 200 continue; 201 if (table->ports[i].label_subport == 202 table->ports[j].label_subport) 203 nfp_warn(cpp, 204 "Port %d subport %d is a duplicate\n", 205 table->ports[i].label_port, 206 table->ports[i].label_subport); 207 208 table->ports[i].is_split = true; 209 } 210 } 211 } 212 213 static void 214 nfp_eth_calc_port_type(struct nfp_cpp *cpp, struct nfp_eth_table_port *entry) 215 { 216 if (entry->interface == NFP_INTERFACE_NONE) { 217 entry->port_type = PORT_NONE; 218 return; 219 } else if (entry->interface == NFP_INTERFACE_RJ45) { 220 entry->port_type = PORT_TP; 221 return; 222 } 223 224 if (entry->media == NFP_MEDIA_FIBRE) 225 entry->port_type = PORT_FIBRE; 226 else 227 entry->port_type = PORT_DA; 228 } 229 230 static void 231 nfp_eth_read_media(struct nfp_cpp *cpp, struct nfp_nsp *nsp, struct nfp_eth_table_port *entry) 232 { 233 struct nfp_eth_media_buf ethm = { 234 .eth_index = entry->eth_index, 235 }; 236 unsigned int i; 237 int ret; 238 239 if (!nfp_nsp_has_read_media(nsp)) 240 return; 241 242 ret = nfp_nsp_read_media(nsp, ðm, sizeof(ethm)); 243 if (ret) { 244 nfp_err(cpp, "Reading media link modes failed: %d\n", ret); 245 return; 246 } 247 248 for (i = 0; i < 2; i++) { 249 entry->link_modes_supp[i] = le64_to_cpu(ethm.supported_modes[i]); 250 entry->link_modes_ad[i] = le64_to_cpu(ethm.advertised_modes[i]); 251 } 252 } 253 254 /** 255 * nfp_eth_read_ports() - retrieve port information 256 * @cpp: NFP CPP handle 257 * 258 * Read the port information from the device. Returned structure should 259 * be freed with kfree() once no longer needed. 260 * 261 * Return: populated ETH table or NULL on error. 262 */ 263 struct nfp_eth_table *nfp_eth_read_ports(struct nfp_cpp *cpp) 264 { 265 struct nfp_eth_table *ret; 266 struct nfp_nsp *nsp; 267 268 nsp = nfp_nsp_open(cpp); 269 if (IS_ERR(nsp)) 270 return NULL; 271 272 ret = __nfp_eth_read_ports(cpp, nsp); 273 nfp_nsp_close(nsp); 274 275 return ret; 276 } 277 278 struct nfp_eth_table * 279 __nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp) 280 { 281 union eth_table_entry *entries; 282 struct nfp_eth_table *table; 283 int i, j, ret, cnt = 0; 284 285 entries = kzalloc(NSP_ETH_TABLE_SIZE, GFP_KERNEL); 286 if (!entries) 287 return NULL; 288 289 ret = nfp_nsp_read_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE); 290 if (ret < 0) { 291 nfp_err(cpp, "reading port table failed %d\n", ret); 292 goto err; 293 } 294 295 for (i = 0; i < NSP_ETH_MAX_COUNT; i++) 296 if (entries[i].port & NSP_ETH_PORT_LANES_MASK) 297 cnt++; 298 299 /* Some versions of flash will give us 0 instead of port count. 300 * For those that give a port count, verify it against the value 301 * calculated above. 302 */ 303 if (ret && ret != cnt) { 304 nfp_err(cpp, "table entry count reported (%d) does not match entries present (%d)\n", 305 ret, cnt); 306 goto err; 307 } 308 309 table = kzalloc(struct_size(table, ports, cnt), GFP_KERNEL); 310 if (!table) 311 goto err; 312 313 table->count = cnt; 314 for (i = 0, j = 0; i < NSP_ETH_MAX_COUNT; i++) 315 if (entries[i].port & NSP_ETH_PORT_LANES_MASK) 316 nfp_eth_port_translate(nsp, &entries[i], i, 317 &table->ports[j++]); 318 319 nfp_eth_calc_port_geometry(cpp, table); 320 for (i = 0; i < table->count; i++) { 321 nfp_eth_calc_port_type(cpp, &table->ports[i]); 322 nfp_eth_read_media(cpp, nsp, &table->ports[i]); 323 } 324 325 kfree(entries); 326 327 return table; 328 329 err: 330 kfree(entries); 331 return NULL; 332 } 333 334 struct nfp_nsp *nfp_eth_config_start(struct nfp_cpp *cpp, unsigned int idx) 335 { 336 union eth_table_entry *entries; 337 struct nfp_nsp *nsp; 338 int ret; 339 340 entries = kzalloc(NSP_ETH_TABLE_SIZE, GFP_KERNEL); 341 if (!entries) 342 return ERR_PTR(-ENOMEM); 343 344 nsp = nfp_nsp_open(cpp); 345 if (IS_ERR(nsp)) { 346 kfree(entries); 347 return nsp; 348 } 349 350 ret = nfp_nsp_read_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE); 351 if (ret < 0) { 352 nfp_err(cpp, "reading port table failed %d\n", ret); 353 goto err; 354 } 355 356 if (!(entries[idx].port & NSP_ETH_PORT_LANES_MASK)) { 357 nfp_warn(cpp, "trying to set port state on disabled port %d\n", 358 idx); 359 goto err; 360 } 361 362 nfp_nsp_config_set_state(nsp, entries, idx); 363 return nsp; 364 365 err: 366 nfp_nsp_close(nsp); 367 kfree(entries); 368 return ERR_PTR(-EIO); 369 } 370 371 void nfp_eth_config_cleanup_end(struct nfp_nsp *nsp) 372 { 373 union eth_table_entry *entries = nfp_nsp_config_entries(nsp); 374 375 nfp_nsp_config_set_modified(nsp, false); 376 nfp_nsp_config_clear_state(nsp); 377 nfp_nsp_close(nsp); 378 kfree(entries); 379 } 380 381 /** 382 * nfp_eth_config_commit_end() - perform recorded configuration changes 383 * @nsp: NFP NSP handle returned from nfp_eth_config_start() 384 * 385 * Perform the configuration which was requested with __nfp_eth_set_*() 386 * helpers and recorded in @nsp state. If device was already configured 387 * as requested or no __nfp_eth_set_*() operations were made no NSP command 388 * will be performed. 389 * 390 * Return: 391 * 0 - configuration successful; 392 * 1 - no changes were needed; 393 * -ERRNO - configuration failed. 394 */ 395 int nfp_eth_config_commit_end(struct nfp_nsp *nsp) 396 { 397 union eth_table_entry *entries = nfp_nsp_config_entries(nsp); 398 int ret = 1; 399 400 if (nfp_nsp_config_modified(nsp)) { 401 ret = nfp_nsp_write_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE); 402 ret = ret < 0 ? ret : 0; 403 } 404 405 nfp_eth_config_cleanup_end(nsp); 406 407 return ret; 408 } 409 410 /** 411 * nfp_eth_set_mod_enable() - set PHY module enable control bit 412 * @cpp: NFP CPP handle 413 * @idx: NFP chip-wide port index 414 * @enable: Desired state 415 * 416 * Enable or disable PHY module (this usually means setting the TX lanes 417 * disable bits). 418 * 419 * Return: 420 * 0 - configuration successful; 421 * 1 - no changes were needed; 422 * -ERRNO - configuration failed. 423 */ 424 int nfp_eth_set_mod_enable(struct nfp_cpp *cpp, unsigned int idx, bool enable) 425 { 426 union eth_table_entry *entries; 427 struct nfp_nsp *nsp; 428 u64 reg; 429 430 nsp = nfp_eth_config_start(cpp, idx); 431 if (IS_ERR(nsp)) 432 return PTR_ERR(nsp); 433 434 entries = nfp_nsp_config_entries(nsp); 435 436 /* Check if we are already in requested state */ 437 reg = le64_to_cpu(entries[idx].state); 438 if (enable != FIELD_GET(NSP_ETH_CTRL_ENABLED, reg)) { 439 reg = le64_to_cpu(entries[idx].control); 440 reg &= ~NSP_ETH_CTRL_ENABLED; 441 reg |= FIELD_PREP(NSP_ETH_CTRL_ENABLED, enable); 442 entries[idx].control = cpu_to_le64(reg); 443 444 nfp_nsp_config_set_modified(nsp, true); 445 } 446 447 return nfp_eth_config_commit_end(nsp); 448 } 449 450 /** 451 * nfp_eth_set_configured() - set PHY module configured control bit 452 * @cpp: NFP CPP handle 453 * @idx: NFP chip-wide port index 454 * @configed: Desired state 455 * 456 * Set the ifup/ifdown state on the PHY. 457 * 458 * Return: 459 * 0 - configuration successful; 460 * 1 - no changes were needed; 461 * -ERRNO - configuration failed. 462 */ 463 int nfp_eth_set_configured(struct nfp_cpp *cpp, unsigned int idx, bool configed) 464 { 465 union eth_table_entry *entries; 466 struct nfp_nsp *nsp; 467 u64 reg; 468 469 nsp = nfp_eth_config_start(cpp, idx); 470 if (IS_ERR(nsp)) 471 return PTR_ERR(nsp); 472 473 /* Older ABI versions did support this feature, however this has only 474 * been reliable since ABI 20. 475 */ 476 if (nfp_nsp_get_abi_ver_minor(nsp) < 20) { 477 nfp_eth_config_cleanup_end(nsp); 478 return -EOPNOTSUPP; 479 } 480 481 entries = nfp_nsp_config_entries(nsp); 482 483 /* Check if we are already in requested state */ 484 reg = le64_to_cpu(entries[idx].state); 485 if (configed != FIELD_GET(NSP_ETH_STATE_CONFIGURED, reg)) { 486 reg = le64_to_cpu(entries[idx].control); 487 reg &= ~NSP_ETH_CTRL_CONFIGURED; 488 reg |= FIELD_PREP(NSP_ETH_CTRL_CONFIGURED, configed); 489 entries[idx].control = cpu_to_le64(reg); 490 491 nfp_nsp_config_set_modified(nsp, true); 492 } 493 494 return nfp_eth_config_commit_end(nsp); 495 } 496 497 static int 498 nfp_eth_set_bit_config(struct nfp_nsp *nsp, unsigned int raw_idx, 499 const u64 mask, const unsigned int shift, 500 unsigned int val, const u64 ctrl_bit) 501 { 502 union eth_table_entry *entries = nfp_nsp_config_entries(nsp); 503 unsigned int idx = nfp_nsp_config_idx(nsp); 504 u64 reg; 505 506 /* Note: set features were added in ABI 0.14 but the error 507 * codes were initially not populated correctly. 508 */ 509 if (nfp_nsp_get_abi_ver_minor(nsp) < 17) { 510 nfp_err(nfp_nsp_cpp(nsp), 511 "set operations not supported, please update flash\n"); 512 return -EOPNOTSUPP; 513 } 514 515 /* Check if we are already in requested state */ 516 reg = le64_to_cpu(entries[idx].raw[raw_idx]); 517 if (val == (reg & mask) >> shift) 518 return 0; 519 520 reg &= ~mask; 521 reg |= (val << shift) & mask; 522 entries[idx].raw[raw_idx] = cpu_to_le64(reg); 523 524 entries[idx].control |= cpu_to_le64(ctrl_bit); 525 526 nfp_nsp_config_set_modified(nsp, true); 527 528 return 0; 529 } 530 531 int nfp_eth_set_idmode(struct nfp_cpp *cpp, unsigned int idx, bool state) 532 { 533 union eth_table_entry *entries; 534 struct nfp_nsp *nsp; 535 u64 reg; 536 537 nsp = nfp_eth_config_start(cpp, idx); 538 if (IS_ERR(nsp)) 539 return PTR_ERR(nsp); 540 541 /* Set this features were added in ABI 0.32 */ 542 if (nfp_nsp_get_abi_ver_minor(nsp) < 32) { 543 nfp_err(nfp_nsp_cpp(nsp), 544 "set id mode operation not supported, please update flash\n"); 545 nfp_eth_config_cleanup_end(nsp); 546 return -EOPNOTSUPP; 547 } 548 549 entries = nfp_nsp_config_entries(nsp); 550 551 reg = le64_to_cpu(entries[idx].control); 552 reg &= ~NSP_ETH_CTRL_SET_IDMODE; 553 reg |= FIELD_PREP(NSP_ETH_CTRL_SET_IDMODE, state); 554 entries[idx].control = cpu_to_le64(reg); 555 556 nfp_nsp_config_set_modified(nsp, true); 557 558 return nfp_eth_config_commit_end(nsp); 559 } 560 561 #define NFP_ETH_SET_BIT_CONFIG(nsp, raw_idx, mask, val, ctrl_bit) \ 562 ({ \ 563 __BF_FIELD_CHECK(mask, 0ULL, val, "NFP_ETH_SET_BIT_CONFIG: "); \ 564 nfp_eth_set_bit_config(nsp, raw_idx, mask, __bf_shf(mask), \ 565 val, ctrl_bit); \ 566 }) 567 568 /** 569 * __nfp_eth_set_aneg() - set PHY autonegotiation control bit 570 * @nsp: NFP NSP handle returned from nfp_eth_config_start() 571 * @mode: Desired autonegotiation mode 572 * 573 * Allow/disallow PHY module to advertise/perform autonegotiation. 574 * Will write to hwinfo overrides in the flash (persistent config). 575 * 576 * Return: 0 or -ERRNO. 577 */ 578 int __nfp_eth_set_aneg(struct nfp_nsp *nsp, enum nfp_eth_aneg mode) 579 { 580 return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_STATE, 581 NSP_ETH_STATE_ANEG, mode, 582 NSP_ETH_CTRL_SET_ANEG); 583 } 584 585 /** 586 * __nfp_eth_set_fec() - set PHY forward error correction control bit 587 * @nsp: NFP NSP handle returned from nfp_eth_config_start() 588 * @mode: Desired fec mode 589 * 590 * Set the PHY module forward error correction mode. 591 * Will write to hwinfo overrides in the flash (persistent config). 592 * 593 * Return: 0 or -ERRNO. 594 */ 595 static int __nfp_eth_set_fec(struct nfp_nsp *nsp, enum nfp_eth_fec mode) 596 { 597 return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_STATE, 598 NSP_ETH_STATE_FEC, mode, 599 NSP_ETH_CTRL_SET_FEC); 600 } 601 602 /** 603 * nfp_eth_set_fec() - set PHY forward error correction control mode 604 * @cpp: NFP CPP handle 605 * @idx: NFP chip-wide port index 606 * @mode: Desired fec mode 607 * 608 * Return: 609 * 0 - configuration successful; 610 * 1 - no changes were needed; 611 * -ERRNO - configuration failed. 612 */ 613 int 614 nfp_eth_set_fec(struct nfp_cpp *cpp, unsigned int idx, enum nfp_eth_fec mode) 615 { 616 struct nfp_nsp *nsp; 617 int err; 618 619 nsp = nfp_eth_config_start(cpp, idx); 620 if (IS_ERR(nsp)) 621 return PTR_ERR(nsp); 622 623 err = __nfp_eth_set_fec(nsp, mode); 624 if (err) { 625 nfp_eth_config_cleanup_end(nsp); 626 return err; 627 } 628 629 return nfp_eth_config_commit_end(nsp); 630 } 631 632 /** 633 * __nfp_eth_set_speed() - set interface speed/rate 634 * @nsp: NFP NSP handle returned from nfp_eth_config_start() 635 * @speed: Desired speed (per lane) 636 * 637 * Set lane speed. Provided @speed value should be subport speed divided 638 * by number of lanes this subport is spanning (i.e. 10000 for 40G, 25000 for 639 * 50G, etc.) 640 * Will write to hwinfo overrides in the flash (persistent config). 641 * 642 * Return: 0 or -ERRNO. 643 */ 644 int __nfp_eth_set_speed(struct nfp_nsp *nsp, unsigned int speed) 645 { 646 enum nfp_eth_rate rate; 647 648 rate = nfp_eth_speed2rate(speed); 649 if (rate == RATE_INVALID) { 650 nfp_warn(nfp_nsp_cpp(nsp), 651 "could not find matching lane rate for speed %u\n", 652 speed); 653 return -EINVAL; 654 } 655 656 return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_STATE, 657 NSP_ETH_STATE_RATE, rate, 658 NSP_ETH_CTRL_SET_RATE); 659 } 660 661 /** 662 * __nfp_eth_set_split() - set interface lane split 663 * @nsp: NFP NSP handle returned from nfp_eth_config_start() 664 * @lanes: Desired lanes per port 665 * 666 * Set number of lanes in the port. 667 * Will write to hwinfo overrides in the flash (persistent config). 668 * 669 * Return: 0 or -ERRNO. 670 */ 671 int __nfp_eth_set_split(struct nfp_nsp *nsp, unsigned int lanes) 672 { 673 return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_PORT, NSP_ETH_PORT_LANES, 674 lanes, NSP_ETH_CTRL_SET_LANES); 675 } 676