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