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 static void
nfp_eth_read_media(struct nfp_cpp * cpp,struct nfp_nsp * nsp,struct nfp_eth_table_port * entry)231 nfp_eth_read_media(struct nfp_cpp *cpp, struct nfp_nsp *nsp, struct nfp_eth_table_port *entry)
232 {
233 struct nfp_eth_media_buf ethm = {
234 .eth_index = entry->eth_index,
235 };
236 unsigned int i;
237 int ret;
238
239 if (!nfp_nsp_has_read_media(nsp))
240 return;
241
242 ret = nfp_nsp_read_media(nsp, ðm, sizeof(ethm));
243 if (ret) {
244 nfp_err(cpp, "Reading media link modes failed: %d\n", ret);
245 return;
246 }
247
248 for (i = 0; i < 2; i++) {
249 entry->link_modes_supp[i] = le64_to_cpu(ethm.supported_modes[i]);
250 entry->link_modes_ad[i] = le64_to_cpu(ethm.advertised_modes[i]);
251 }
252 }
253
254 /**
255 * nfp_eth_read_ports() - retrieve port information
256 * @cpp: NFP CPP handle
257 *
258 * Read the port information from the device. Returned structure should
259 * be freed with kfree() once no longer needed.
260 *
261 * Return: populated ETH table or NULL on error.
262 */
nfp_eth_read_ports(struct nfp_cpp * cpp)263 struct nfp_eth_table *nfp_eth_read_ports(struct nfp_cpp *cpp)
264 {
265 struct nfp_eth_table *ret;
266 struct nfp_nsp *nsp;
267
268 nsp = nfp_nsp_open(cpp);
269 if (IS_ERR(nsp))
270 return NULL;
271
272 ret = __nfp_eth_read_ports(cpp, nsp);
273 nfp_nsp_close(nsp);
274
275 return ret;
276 }
277
278 struct nfp_eth_table *
__nfp_eth_read_ports(struct nfp_cpp * cpp,struct nfp_nsp * nsp)279 __nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp)
280 {
281 union eth_table_entry *entries;
282 struct nfp_eth_table *table;
283 int i, j, ret, cnt = 0;
284
285 entries = kzalloc(NSP_ETH_TABLE_SIZE, GFP_KERNEL);
286 if (!entries)
287 return NULL;
288
289 ret = nfp_nsp_read_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE);
290 if (ret < 0) {
291 nfp_err(cpp, "reading port table failed %d\n", ret);
292 goto err;
293 }
294
295 for (i = 0; i < NSP_ETH_MAX_COUNT; i++)
296 if (entries[i].port & NSP_ETH_PORT_LANES_MASK)
297 cnt++;
298
299 /* Some versions of flash will give us 0 instead of port count.
300 * For those that give a port count, verify it against the value
301 * calculated above.
302 */
303 if (ret && ret != cnt) {
304 nfp_err(cpp, "table entry count reported (%d) does not match entries present (%d)\n",
305 ret, cnt);
306 goto err;
307 }
308
309 table = kzalloc(struct_size(table, ports, cnt), GFP_KERNEL);
310 if (!table)
311 goto err;
312
313 table->count = cnt;
314 for (i = 0, j = 0; i < NSP_ETH_MAX_COUNT; i++)
315 if (entries[i].port & NSP_ETH_PORT_LANES_MASK)
316 nfp_eth_port_translate(nsp, &entries[i], i,
317 &table->ports[j++]);
318
319 nfp_eth_calc_port_geometry(cpp, table);
320 for (i = 0; i < table->count; i++) {
321 nfp_eth_calc_port_type(cpp, &table->ports[i]);
322 nfp_eth_read_media(cpp, nsp, &table->ports[i]);
323 }
324
325 kfree(entries);
326
327 return table;
328
329 err:
330 kfree(entries);
331 return NULL;
332 }
333
nfp_eth_config_start(struct nfp_cpp * cpp,unsigned int idx)334 struct nfp_nsp *nfp_eth_config_start(struct nfp_cpp *cpp, unsigned int idx)
335 {
336 union eth_table_entry *entries;
337 struct nfp_nsp *nsp;
338 int ret;
339
340 entries = kzalloc(NSP_ETH_TABLE_SIZE, GFP_KERNEL);
341 if (!entries)
342 return ERR_PTR(-ENOMEM);
343
344 nsp = nfp_nsp_open(cpp);
345 if (IS_ERR(nsp)) {
346 kfree(entries);
347 return nsp;
348 }
349
350 ret = nfp_nsp_read_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE);
351 if (ret < 0) {
352 nfp_err(cpp, "reading port table failed %d\n", ret);
353 goto err;
354 }
355
356 if (!(entries[idx].port & NSP_ETH_PORT_LANES_MASK)) {
357 nfp_warn(cpp, "trying to set port state on disabled port %d\n",
358 idx);
359 goto err;
360 }
361
362 nfp_nsp_config_set_state(nsp, entries, idx);
363 return nsp;
364
365 err:
366 nfp_nsp_close(nsp);
367 kfree(entries);
368 return ERR_PTR(-EIO);
369 }
370
nfp_eth_config_cleanup_end(struct nfp_nsp * nsp)371 void nfp_eth_config_cleanup_end(struct nfp_nsp *nsp)
372 {
373 union eth_table_entry *entries = nfp_nsp_config_entries(nsp);
374
375 nfp_nsp_config_set_modified(nsp, false);
376 nfp_nsp_config_clear_state(nsp);
377 nfp_nsp_close(nsp);
378 kfree(entries);
379 }
380
381 /**
382 * nfp_eth_config_commit_end() - perform recorded configuration changes
383 * @nsp: NFP NSP handle returned from nfp_eth_config_start()
384 *
385 * Perform the configuration which was requested with __nfp_eth_set_*()
386 * helpers and recorded in @nsp state. If device was already configured
387 * as requested or no __nfp_eth_set_*() operations were made no NSP command
388 * will be performed.
389 *
390 * Return:
391 * 0 - configuration successful;
392 * 1 - no changes were needed;
393 * -ERRNO - configuration failed.
394 */
nfp_eth_config_commit_end(struct nfp_nsp * nsp)395 int nfp_eth_config_commit_end(struct nfp_nsp *nsp)
396 {
397 union eth_table_entry *entries = nfp_nsp_config_entries(nsp);
398 int ret = 1;
399
400 if (nfp_nsp_config_modified(nsp)) {
401 ret = nfp_nsp_write_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE);
402 ret = ret < 0 ? ret : 0;
403 }
404
405 nfp_eth_config_cleanup_end(nsp);
406
407 return ret;
408 }
409
410 /**
411 * nfp_eth_set_mod_enable() - set PHY module enable control bit
412 * @cpp: NFP CPP handle
413 * @idx: NFP chip-wide port index
414 * @enable: Desired state
415 *
416 * Enable or disable PHY module (this usually means setting the TX lanes
417 * disable bits).
418 *
419 * Return:
420 * 0 - configuration successful;
421 * 1 - no changes were needed;
422 * -ERRNO - configuration failed.
423 */
nfp_eth_set_mod_enable(struct nfp_cpp * cpp,unsigned int idx,bool enable)424 int nfp_eth_set_mod_enable(struct nfp_cpp *cpp, unsigned int idx, bool enable)
425 {
426 union eth_table_entry *entries;
427 struct nfp_nsp *nsp;
428 u64 reg;
429
430 nsp = nfp_eth_config_start(cpp, idx);
431 if (IS_ERR(nsp))
432 return PTR_ERR(nsp);
433
434 entries = nfp_nsp_config_entries(nsp);
435
436 /* Check if we are already in requested state */
437 reg = le64_to_cpu(entries[idx].state);
438 if (enable != FIELD_GET(NSP_ETH_CTRL_ENABLED, reg)) {
439 reg = le64_to_cpu(entries[idx].control);
440 reg &= ~NSP_ETH_CTRL_ENABLED;
441 reg |= FIELD_PREP(NSP_ETH_CTRL_ENABLED, enable);
442 entries[idx].control = cpu_to_le64(reg);
443
444 nfp_nsp_config_set_modified(nsp, true);
445 }
446
447 return nfp_eth_config_commit_end(nsp);
448 }
449
450 /**
451 * nfp_eth_set_configured() - set PHY module configured control bit
452 * @cpp: NFP CPP handle
453 * @idx: NFP chip-wide port index
454 * @configed: Desired state
455 *
456 * Set the ifup/ifdown state on the PHY.
457 *
458 * Return:
459 * 0 - configuration successful;
460 * 1 - no changes were needed;
461 * -ERRNO - configuration failed.
462 */
nfp_eth_set_configured(struct nfp_cpp * cpp,unsigned int idx,bool configed)463 int nfp_eth_set_configured(struct nfp_cpp *cpp, unsigned int idx, bool configed)
464 {
465 union eth_table_entry *entries;
466 struct nfp_nsp *nsp;
467 u64 reg;
468
469 nsp = nfp_eth_config_start(cpp, idx);
470 if (IS_ERR(nsp))
471 return PTR_ERR(nsp);
472
473 /* Older ABI versions did support this feature, however this has only
474 * been reliable since ABI 20.
475 */
476 if (nfp_nsp_get_abi_ver_minor(nsp) < 20) {
477 nfp_eth_config_cleanup_end(nsp);
478 return -EOPNOTSUPP;
479 }
480
481 entries = nfp_nsp_config_entries(nsp);
482
483 /* Check if we are already in requested state */
484 reg = le64_to_cpu(entries[idx].state);
485 if (configed != FIELD_GET(NSP_ETH_STATE_CONFIGURED, reg)) {
486 reg = le64_to_cpu(entries[idx].control);
487 reg &= ~NSP_ETH_CTRL_CONFIGURED;
488 reg |= FIELD_PREP(NSP_ETH_CTRL_CONFIGURED, configed);
489 entries[idx].control = cpu_to_le64(reg);
490
491 nfp_nsp_config_set_modified(nsp, true);
492 }
493
494 return nfp_eth_config_commit_end(nsp);
495 }
496
497 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)498 nfp_eth_set_bit_config(struct nfp_nsp *nsp, unsigned int raw_idx,
499 const u64 mask, const unsigned int shift,
500 unsigned int val, const u64 ctrl_bit)
501 {
502 union eth_table_entry *entries = nfp_nsp_config_entries(nsp);
503 unsigned int idx = nfp_nsp_config_idx(nsp);
504 u64 reg;
505
506 /* Note: set features were added in ABI 0.14 but the error
507 * codes were initially not populated correctly.
508 */
509 if (nfp_nsp_get_abi_ver_minor(nsp) < 17) {
510 nfp_err(nfp_nsp_cpp(nsp),
511 "set operations not supported, please update flash\n");
512 return -EOPNOTSUPP;
513 }
514
515 /* Check if we are already in requested state */
516 reg = le64_to_cpu(entries[idx].raw[raw_idx]);
517 if (val == (reg & mask) >> shift)
518 return 0;
519
520 reg &= ~mask;
521 reg |= (val << shift) & mask;
522 entries[idx].raw[raw_idx] = cpu_to_le64(reg);
523
524 entries[idx].control |= cpu_to_le64(ctrl_bit);
525
526 nfp_nsp_config_set_modified(nsp, true);
527
528 return 0;
529 }
530
nfp_eth_set_idmode(struct nfp_cpp * cpp,unsigned int idx,bool state)531 int nfp_eth_set_idmode(struct nfp_cpp *cpp, unsigned int idx, bool state)
532 {
533 union eth_table_entry *entries;
534 struct nfp_nsp *nsp;
535 u64 reg;
536
537 nsp = nfp_eth_config_start(cpp, idx);
538 if (IS_ERR(nsp))
539 return PTR_ERR(nsp);
540
541 /* Set this features were added in ABI 0.32 */
542 if (nfp_nsp_get_abi_ver_minor(nsp) < 32) {
543 nfp_err(nfp_nsp_cpp(nsp),
544 "set id mode operation not supported, please update flash\n");
545 nfp_eth_config_cleanup_end(nsp);
546 return -EOPNOTSUPP;
547 }
548
549 entries = nfp_nsp_config_entries(nsp);
550
551 reg = le64_to_cpu(entries[idx].control);
552 reg &= ~NSP_ETH_CTRL_SET_IDMODE;
553 reg |= FIELD_PREP(NSP_ETH_CTRL_SET_IDMODE, state);
554 entries[idx].control = cpu_to_le64(reg);
555
556 nfp_nsp_config_set_modified(nsp, true);
557
558 return nfp_eth_config_commit_end(nsp);
559 }
560
561 #define NFP_ETH_SET_BIT_CONFIG(nsp, raw_idx, mask, val, ctrl_bit) \
562 ({ \
563 __BF_FIELD_CHECK(mask, 0ULL, val, "NFP_ETH_SET_BIT_CONFIG: "); \
564 nfp_eth_set_bit_config(nsp, raw_idx, mask, __bf_shf(mask), \
565 val, ctrl_bit); \
566 })
567
568 /**
569 * __nfp_eth_set_aneg() - set PHY autonegotiation control bit
570 * @nsp: NFP NSP handle returned from nfp_eth_config_start()
571 * @mode: Desired autonegotiation mode
572 *
573 * Allow/disallow PHY module to advertise/perform autonegotiation.
574 * Will write to hwinfo overrides in the flash (persistent config).
575 *
576 * Return: 0 or -ERRNO.
577 */
__nfp_eth_set_aneg(struct nfp_nsp * nsp,enum nfp_eth_aneg mode)578 int __nfp_eth_set_aneg(struct nfp_nsp *nsp, enum nfp_eth_aneg mode)
579 {
580 return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_STATE,
581 NSP_ETH_STATE_ANEG, mode,
582 NSP_ETH_CTRL_SET_ANEG);
583 }
584
585 /**
586 * __nfp_eth_set_fec() - set PHY forward error correction control bit
587 * @nsp: NFP NSP handle returned from nfp_eth_config_start()
588 * @mode: Desired fec mode
589 *
590 * Set the PHY module forward error correction mode.
591 * Will write to hwinfo overrides in the flash (persistent config).
592 *
593 * Return: 0 or -ERRNO.
594 */
__nfp_eth_set_fec(struct nfp_nsp * nsp,enum nfp_eth_fec mode)595 static int __nfp_eth_set_fec(struct nfp_nsp *nsp, enum nfp_eth_fec mode)
596 {
597 return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_STATE,
598 NSP_ETH_STATE_FEC, mode,
599 NSP_ETH_CTRL_SET_FEC);
600 }
601
602 /**
603 * nfp_eth_set_fec() - set PHY forward error correction control mode
604 * @cpp: NFP CPP handle
605 * @idx: NFP chip-wide port index
606 * @mode: Desired fec mode
607 *
608 * Return:
609 * 0 - configuration successful;
610 * 1 - no changes were needed;
611 * -ERRNO - configuration failed.
612 */
613 int
nfp_eth_set_fec(struct nfp_cpp * cpp,unsigned int idx,enum nfp_eth_fec mode)614 nfp_eth_set_fec(struct nfp_cpp *cpp, unsigned int idx, enum nfp_eth_fec mode)
615 {
616 struct nfp_nsp *nsp;
617 int err;
618
619 nsp = nfp_eth_config_start(cpp, idx);
620 if (IS_ERR(nsp))
621 return PTR_ERR(nsp);
622
623 err = __nfp_eth_set_fec(nsp, mode);
624 if (err) {
625 nfp_eth_config_cleanup_end(nsp);
626 return err;
627 }
628
629 return nfp_eth_config_commit_end(nsp);
630 }
631
632 /**
633 * __nfp_eth_set_speed() - set interface speed/rate
634 * @nsp: NFP NSP handle returned from nfp_eth_config_start()
635 * @speed: Desired speed (per lane)
636 *
637 * Set lane speed. Provided @speed value should be subport speed divided
638 * by number of lanes this subport is spanning (i.e. 10000 for 40G, 25000 for
639 * 50G, etc.)
640 * Will write to hwinfo overrides in the flash (persistent config).
641 *
642 * Return: 0 or -ERRNO.
643 */
__nfp_eth_set_speed(struct nfp_nsp * nsp,unsigned int speed)644 int __nfp_eth_set_speed(struct nfp_nsp *nsp, unsigned int speed)
645 {
646 enum nfp_eth_rate rate;
647
648 rate = nfp_eth_speed2rate(speed);
649 if (rate == RATE_INVALID) {
650 nfp_warn(nfp_nsp_cpp(nsp),
651 "could not find matching lane rate for speed %u\n",
652 speed);
653 return -EINVAL;
654 }
655
656 return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_STATE,
657 NSP_ETH_STATE_RATE, rate,
658 NSP_ETH_CTRL_SET_RATE);
659 }
660
661 /**
662 * __nfp_eth_set_split() - set interface lane split
663 * @nsp: NFP NSP handle returned from nfp_eth_config_start()
664 * @lanes: Desired lanes per port
665 *
666 * Set number of lanes in the port.
667 * Will write to hwinfo overrides in the flash (persistent config).
668 *
669 * Return: 0 or -ERRNO.
670 */
__nfp_eth_set_split(struct nfp_nsp * nsp,unsigned int lanes)671 int __nfp_eth_set_split(struct nfp_nsp *nsp, unsigned int lanes)
672 {
673 return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_PORT, NSP_ETH_PORT_LANES,
674 lanes, NSP_ETH_CTRL_SET_LANES);
675 }
676