xref: /linux/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c (revision 3ad0876554cafa368f574d4d408468510543e9ff)
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 }
638