xref: /linux/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c (revision 06d07429858317ded2db7986113a9e0129cd599b)
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 
60 enum 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 
69 enum nfp_eth_rate {
70 	RATE_INVALID = 0,
71 	RATE_10M,
72 	RATE_100M,
73 	RATE_1G,
74 	RATE_10G,
75 	RATE_25G,
76 };
77 
78 union 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 
89 static 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 
nfp_eth_rate2speed(enum nfp_eth_rate rate)101 static 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 
nfp_eth_speed2rate(unsigned int speed)112 static 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 
nfp_eth_copy_mac_reverse(u8 * dst,const u8 * src)123 static 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 
131 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)132 nfp_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 
198 static void
nfp_eth_calc_port_geometry(struct nfp_cpp * cpp,struct nfp_eth_table * table)199 nfp_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 
226 static void
nfp_eth_calc_port_type(struct nfp_cpp * cpp,struct nfp_eth_table_port * entry)227 nfp_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 
243 static void
nfp_eth_read_media(struct nfp_cpp * cpp,struct nfp_nsp * nsp,struct nfp_eth_table_port * entry)244 nfp_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  */
nfp_eth_read_ports(struct nfp_cpp * cpp)276 struct 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 
291 struct nfp_eth_table *
__nfp_eth_read_ports(struct nfp_cpp * cpp,struct nfp_nsp * nsp)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 
342 err:
343 	kfree(entries);
344 	return NULL;
345 }
346 
nfp_eth_config_start(struct nfp_cpp * cpp,unsigned int idx)347 struct 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 
378 err:
379 	nfp_nsp_close(nsp);
380 	kfree(entries);
381 	return ERR_PTR(-EIO);
382 }
383 
nfp_eth_config_cleanup_end(struct nfp_nsp * nsp)384 void 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  */
nfp_eth_config_commit_end(struct nfp_nsp * nsp)408 int 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  */
nfp_eth_set_mod_enable(struct nfp_cpp * cpp,unsigned int idx,bool enable)437 int 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  */
nfp_eth_set_configured(struct nfp_cpp * cpp,unsigned int idx,bool configed)476 int 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 
510 static int
nfp_eth_set_bit_config(struct nfp_nsp * nsp,unsigned int raw_idx,const u64 mask,const unsigned int shift,u64 val,const u64 ctrl_bit)511 nfp_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 
nfp_eth_set_idmode(struct nfp_cpp * cpp,unsigned int idx,bool state)544 int 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  */
__nfp_eth_set_aneg(struct nfp_nsp * nsp,enum nfp_eth_aneg mode)591 int __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  */
__nfp_eth_set_fec(struct nfp_nsp * nsp,enum nfp_eth_fec mode)608 static 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  */
626 int
nfp_eth_set_fec(struct nfp_cpp * cpp,unsigned int idx,enum nfp_eth_fec mode)627 nfp_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  */
__nfp_eth_set_txpause(struct nfp_nsp * nsp,unsigned int tx_pause)654 static 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  */
__nfp_eth_set_rxpause(struct nfp_nsp * nsp,unsigned int rx_pause)669 static 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  */
687 int
nfp_eth_set_pauseparam(struct nfp_cpp * cpp,unsigned int idx,unsigned int tx_pause,unsigned int rx_pause)688 nfp_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  */
__nfp_eth_set_speed(struct nfp_nsp * nsp,unsigned int speed)732 int __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  */
__nfp_eth_set_split(struct nfp_nsp * nsp,unsigned int lanes)759 int __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 }
764