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