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