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