File Index
Files and directories
Sign in
FILE

nfp_nsp_eth.c

File preview with syntax highlighting.

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