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