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