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: dst->mac_addr, src: 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(state: 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(state: 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(state: 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(state: 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(state: nsp))
253 return;
254
255 ret = nfp_nsp_read_media(state: nsp, buf: &ethm, size: 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(ptr: nsp))
283 return NULL;
284
285 ret = __nfp_eth_read_ports(cpp, nsp);
286 nfp_nsp_close(state: 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(state: nsp, buf: 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, src: &entries[i], index: i,
330 dst: &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, entry: &table->ports[i]);
335 nfp_eth_read_media(cpp, nsp, entry: &table->ports[i]);
336 }
337
338 kfree(objp: entries);
339
340 return table;
341
342err:
343 kfree(objp: 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(error: -ENOMEM);
356
357 nsp = nfp_nsp_open(cpp);
358 if (IS_ERR(ptr: nsp)) {
359 kfree(objp: entries);
360 return nsp;
361 }
362
363 ret = nfp_nsp_read_eth_table(state: nsp, buf: 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(state: nsp, entries, idx);
376 return nsp;
377
378err:
379 nfp_nsp_close(state: nsp);
380 kfree(objp: entries);
381 return ERR_PTR(error: -EIO);
382}
383
384void nfp_eth_config_cleanup_end(struct nfp_nsp *nsp)
385{
386 union eth_table_entry *entries = nfp_nsp_config_entries(state: nsp);
387
388 nfp_nsp_config_set_modified(state: nsp, modified: false);
389 nfp_nsp_config_clear_state(state: nsp);
390 nfp_nsp_close(state: nsp);
391 kfree(objp: 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(state: nsp);
411 int ret = 1;
412
413 if (nfp_nsp_config_modified(state: nsp)) {
414 ret = nfp_nsp_write_eth_table(state: nsp, buf: 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(ptr: nsp))
445 return PTR_ERR(ptr: nsp);
446
447 entries = nfp_nsp_config_entries(state: 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(state: nsp, modified: 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(ptr: nsp))
484 return PTR_ERR(ptr: 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(state: nsp) < 20) {
490 nfp_eth_config_cleanup_end(nsp);
491 return -EOPNOTSUPP;
492 }
493
494 entries = nfp_nsp_config_entries(state: 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(state: nsp, modified: 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(state: nsp);
516 unsigned int idx = nfp_nsp_config_idx(state: 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(state: 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(state: nsp, modified: 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(ptr: nsp))
552 return PTR_ERR(ptr: nsp);
553
554 /* Set this features were added in ABI 0.32 */
555 if (nfp_nsp_get_abi_ver_minor(state: 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(state: 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(state: nsp, modified: 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(ptr: nsp))
634 return PTR_ERR(ptr: 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(ptr: nsp))
696 return PTR_ERR(ptr: nsp);
697
698 if (nfp_nsp_get_abi_ver_minor(state: 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}
764

source code of linux/drivers/net/ethernet/netronome/nfp/nfpcore/nfp_nsp_eth.c