GNU Linux-libre 4.19.281-gnu1
[releases.git] / drivers / net / ethernet / netronome / nfp / nfpcore / nfp_nsp_eth.c
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 }