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