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