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
53 enum 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
62 enum nfp_eth_rate {
63 RATE_INVALID = 0,
64 RATE_10M,
65 RATE_100M,
66 RATE_1G,
67 RATE_10G,
68 RATE_25G,
69 };
70
71 union 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
82 static 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
nfp_eth_rate2speed(enum nfp_eth_rate rate)94 static 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
nfp_eth_speed2rate(unsigned int speed)105 static 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
nfp_eth_copy_mac_reverse(u8 * dst,const u8 * src)116 static 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
124 static void
nfp_eth_port_translate(struct nfp_nsp * nsp,const union eth_table_entry * src,unsigned int index,struct nfp_eth_table_port * dst)125 nfp_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
175 static void
nfp_eth_calc_port_geometry(struct nfp_cpp * cpp,struct nfp_eth_table * table)176 nfp_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
203 static void
nfp_eth_calc_port_type(struct nfp_cpp * cpp,struct nfp_eth_table_port * entry)204 nfp_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 */
nfp_eth_read_ports(struct nfp_cpp * cpp)229 struct 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
244 struct nfp_eth_table *
__nfp_eth_read_ports(struct nfp_cpp * cpp,struct nfp_nsp * nsp)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
293 err:
294 kfree(entries);
295 return NULL;
296 }
297
nfp_eth_config_start(struct nfp_cpp * cpp,unsigned int idx)298 struct 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
329 err:
330 nfp_nsp_close(nsp);
331 kfree(entries);
332 return ERR_PTR(-EIO);
333 }
334
nfp_eth_config_cleanup_end(struct nfp_nsp * nsp)335 void 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 */
nfp_eth_config_commit_end(struct nfp_nsp * nsp)359 int 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 */
nfp_eth_set_mod_enable(struct nfp_cpp * cpp,unsigned int idx,bool enable)388 int 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 */
nfp_eth_set_configured(struct nfp_cpp * cpp,unsigned int idx,bool configed)427 int 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
461 static int
nfp_eth_set_bit_config(struct nfp_nsp * nsp,unsigned int raw_idx,const u64 mask,const unsigned int shift,unsigned int val,const u64 ctrl_bit)462 nfp_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 */
__nfp_eth_set_aneg(struct nfp_nsp * nsp,enum nfp_eth_aneg mode)512 int __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 */
__nfp_eth_set_fec(struct nfp_nsp * nsp,enum nfp_eth_fec mode)529 static 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 */
547 int
nfp_eth_set_fec(struct nfp_cpp * cpp,unsigned int idx,enum nfp_eth_fec mode)548 nfp_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 */
__nfp_eth_set_speed(struct nfp_nsp * nsp,unsigned int speed)578 int __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 */
__nfp_eth_set_split(struct nfp_nsp * nsp,unsigned int lanes)605 int __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