1 /* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2018 Netronome Systems, Inc.
7 #include <rte_common.h>
8 #include <rte_byteorder.h>
11 #include "nfp6000/nfp6000.h"
13 #define GENMASK_ULL(h, l) \
14 (((~0ULL) - (1ULL << (l)) + 1) & \
15 (~0ULL >> (64 - 1 - (h))))
17 #define __bf_shf(x) (__builtin_ffsll(x) - 1)
19 #define FIELD_GET(_mask, _reg) \
21 typeof(_mask) _x = (_mask); \
22 (typeof(_x))(((_reg) & (_x)) >> __bf_shf(_x)); \
25 #define FIELD_FIT(_mask, _val) \
27 typeof(_mask) _x = (_mask); \
28 !((((typeof(_x))_val) << __bf_shf(_x)) & ~(_x)); \
31 #define FIELD_PREP(_mask, _val) \
33 typeof(_mask) _x = (_mask); \
34 ((typeof(_x))(_val) << __bf_shf(_x)) & (_x); \
37 #define NSP_ETH_NBI_PORT_COUNT 24
38 #define NSP_ETH_MAX_COUNT (2 * NSP_ETH_NBI_PORT_COUNT)
39 #define NSP_ETH_TABLE_SIZE (NSP_ETH_MAX_COUNT * \
40 sizeof(union eth_table_entry))
42 #define NSP_ETH_PORT_LANES GENMASK_ULL(3, 0)
43 #define NSP_ETH_PORT_INDEX GENMASK_ULL(15, 8)
44 #define NSP_ETH_PORT_LABEL GENMASK_ULL(53, 48)
45 #define NSP_ETH_PORT_PHYLABEL GENMASK_ULL(59, 54)
46 #define NSP_ETH_PORT_FEC_SUPP_BASER BIT_ULL(60)
47 #define NSP_ETH_PORT_FEC_SUPP_RS BIT_ULL(61)
49 #define NSP_ETH_PORT_LANES_MASK rte_cpu_to_le_64(NSP_ETH_PORT_LANES)
51 #define NSP_ETH_STATE_CONFIGURED BIT_ULL(0)
52 #define NSP_ETH_STATE_ENABLED BIT_ULL(1)
53 #define NSP_ETH_STATE_TX_ENABLED BIT_ULL(2)
54 #define NSP_ETH_STATE_RX_ENABLED BIT_ULL(3)
55 #define NSP_ETH_STATE_RATE GENMASK_ULL(11, 8)
56 #define NSP_ETH_STATE_INTERFACE GENMASK_ULL(19, 12)
57 #define NSP_ETH_STATE_MEDIA GENMASK_ULL(21, 20)
58 #define NSP_ETH_STATE_OVRD_CHNG BIT_ULL(22)
59 #define NSP_ETH_STATE_ANEG GENMASK_ULL(25, 23)
60 #define NSP_ETH_STATE_FEC GENMASK_ULL(27, 26)
62 #define NSP_ETH_CTRL_CONFIGURED BIT_ULL(0)
63 #define NSP_ETH_CTRL_ENABLED BIT_ULL(1)
64 #define NSP_ETH_CTRL_TX_ENABLED BIT_ULL(2)
65 #define NSP_ETH_CTRL_RX_ENABLED BIT_ULL(3)
66 #define NSP_ETH_CTRL_SET_RATE BIT_ULL(4)
67 #define NSP_ETH_CTRL_SET_LANES BIT_ULL(5)
68 #define NSP_ETH_CTRL_SET_ANEG BIT_ULL(6)
69 #define NSP_ETH_CTRL_SET_FEC BIT_ULL(7)
71 /* Which connector port. */
75 #define PORT_FIBRE 0x03
78 #define PORT_NONE 0xef
79 #define PORT_OTHER 0xff
83 #define SPEED_1000 1000
84 #define SPEED_2500 2500
85 #define SPEED_5000 5000
86 #define SPEED_10000 10000
87 #define SPEED_14000 14000
88 #define SPEED_20000 20000
89 #define SPEED_25000 25000
90 #define SPEED_40000 40000
91 #define SPEED_50000 50000
92 #define SPEED_56000 56000
93 #define SPEED_100000 100000
113 union eth_table_entry {
121 uint64_t raw[NSP_ETH_NUM_RAW];
124 static const struct {
125 enum nfp_eth_rate rate;
127 } nsp_eth_rate_tbl[] = {
128 { RATE_INVALID, 0, },
129 { RATE_10M, SPEED_10, },
130 { RATE_100M, SPEED_100, },
131 { RATE_1G, SPEED_1000, },
132 { RATE_10G, SPEED_10000, },
133 { RATE_25G, SPEED_25000, },
137 nfp_eth_rate2speed(enum nfp_eth_rate rate)
141 for (i = 0; i < (int)ARRAY_SIZE(nsp_eth_rate_tbl); i++)
142 if (nsp_eth_rate_tbl[i].rate == rate)
143 return nsp_eth_rate_tbl[i].speed;
149 nfp_eth_speed2rate(unsigned int speed)
153 for (i = 0; i < (int)ARRAY_SIZE(nsp_eth_rate_tbl); i++)
154 if (nsp_eth_rate_tbl[i].speed == speed)
155 return nsp_eth_rate_tbl[i].rate;
161 nfp_eth_copy_mac_reverse(uint8_t *dst, const uint8_t *src)
165 for (i = 0; i < (int)ETH_ALEN; i++)
166 dst[ETH_ALEN - i - 1] = src[i];
170 nfp_eth_port_translate(struct nfp_nsp *nsp, const union eth_table_entry *src,
171 unsigned int index, struct nfp_eth_table_port *dst)
175 uint64_t port, state;
177 port = rte_le_to_cpu_64(src->port);
178 state = rte_le_to_cpu_64(src->state);
180 dst->eth_index = FIELD_GET(NSP_ETH_PORT_INDEX, port);
182 dst->nbi = index / NSP_ETH_NBI_PORT_COUNT;
183 dst->base = index % NSP_ETH_NBI_PORT_COUNT;
184 dst->lanes = FIELD_GET(NSP_ETH_PORT_LANES, port);
186 dst->enabled = FIELD_GET(NSP_ETH_STATE_ENABLED, state);
187 dst->tx_enabled = FIELD_GET(NSP_ETH_STATE_TX_ENABLED, state);
188 dst->rx_enabled = FIELD_GET(NSP_ETH_STATE_RX_ENABLED, state);
190 rate = nfp_eth_rate2speed(FIELD_GET(NSP_ETH_STATE_RATE, state));
191 dst->speed = dst->lanes * rate;
193 dst->interface = FIELD_GET(NSP_ETH_STATE_INTERFACE, state);
194 dst->media = FIELD_GET(NSP_ETH_STATE_MEDIA, state);
196 nfp_eth_copy_mac_reverse(dst->mac_addr, src->mac_addr);
198 dst->label_port = FIELD_GET(NSP_ETH_PORT_PHYLABEL, port);
199 dst->label_subport = FIELD_GET(NSP_ETH_PORT_LABEL, port);
201 if (nfp_nsp_get_abi_ver_minor(nsp) < 17)
204 dst->override_changed = FIELD_GET(NSP_ETH_STATE_OVRD_CHNG, state);
205 dst->aneg = FIELD_GET(NSP_ETH_STATE_ANEG, state);
207 if (nfp_nsp_get_abi_ver_minor(nsp) < 22)
210 fec = FIELD_GET(NSP_ETH_PORT_FEC_SUPP_BASER, port);
211 dst->fec_modes_supported |= fec << NFP_FEC_BASER_BIT;
212 fec = FIELD_GET(NSP_ETH_PORT_FEC_SUPP_RS, port);
213 dst->fec_modes_supported |= fec << NFP_FEC_REED_SOLOMON_BIT;
214 if (dst->fec_modes_supported)
215 dst->fec_modes_supported |= NFP_FEC_AUTO | NFP_FEC_DISABLED;
217 dst->fec = 1 << FIELD_GET(NSP_ETH_STATE_FEC, state);
221 nfp_eth_calc_port_geometry(struct nfp_eth_table *table)
225 for (i = 0; i < table->count; i++) {
226 table->max_index = RTE_MAX(table->max_index,
227 table->ports[i].index);
229 for (j = 0; j < table->count; j++) {
230 if (table->ports[i].label_port !=
231 table->ports[j].label_port)
233 table->ports[i].port_lanes += table->ports[j].lanes;
237 if (table->ports[i].label_subport ==
238 table->ports[j].label_subport)
239 printf("Port %d subport %d is a duplicate\n",
240 table->ports[i].label_port,
241 table->ports[i].label_subport);
243 table->ports[i].is_split = 1;
249 nfp_eth_calc_port_type(struct nfp_eth_table_port *entry)
251 if (entry->interface == NFP_INTERFACE_NONE) {
252 entry->port_type = PORT_NONE;
256 if (entry->media == NFP_MEDIA_FIBRE)
257 entry->port_type = PORT_FIBRE;
259 entry->port_type = PORT_DA;
262 static struct nfp_eth_table *
263 __nfp_eth_read_ports(struct nfp_nsp *nsp)
265 union eth_table_entry *entries;
266 struct nfp_eth_table *table;
268 int i, j, ret, cnt = 0;
270 entries = malloc(NSP_ETH_TABLE_SIZE);
274 memset(entries, 0, NSP_ETH_TABLE_SIZE);
275 ret = nfp_nsp_read_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE);
277 printf("reading port table failed %d\n", ret);
281 for (i = 0; i < NSP_ETH_MAX_COUNT; i++)
282 if (entries[i].port & NSP_ETH_PORT_LANES_MASK)
285 /* Some versions of flash will give us 0 instead of port count. For
286 * those that give a port count, verify it against the value calculated
289 if (ret && ret != cnt) {
290 printf("table entry count (%d) unmatch entries present (%d)\n",
295 table_sz = sizeof(*table) + sizeof(struct nfp_eth_table_port) * cnt;
296 table = malloc(table_sz);
300 memset(table, 0, table_sz);
302 for (i = 0, j = 0; i < NSP_ETH_MAX_COUNT; i++)
303 if (entries[i].port & NSP_ETH_PORT_LANES_MASK)
304 nfp_eth_port_translate(nsp, &entries[i], i,
307 nfp_eth_calc_port_geometry(table);
308 for (i = 0; i < (int)table->count; i++)
309 nfp_eth_calc_port_type(&table->ports[i]);
321 * nfp_eth_read_ports() - retrieve port information
322 * @cpp: NFP CPP handle
324 * Read the port information from the device. Returned structure should
325 * be freed with kfree() once no longer needed.
327 * Return: populated ETH table or NULL on error.
329 struct nfp_eth_table *
330 nfp_eth_read_ports(struct nfp_cpp *cpp)
332 struct nfp_eth_table *ret;
335 nsp = nfp_nsp_open(cpp);
339 ret = __nfp_eth_read_ports(nsp);
346 nfp_eth_config_start(struct nfp_cpp *cpp, unsigned int idx)
348 union eth_table_entry *entries;
352 entries = malloc(NSP_ETH_TABLE_SIZE);
356 memset(entries, 0, NSP_ETH_TABLE_SIZE);
357 nsp = nfp_nsp_open(cpp);
363 ret = nfp_nsp_read_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE);
365 printf("reading port table failed %d\n", ret);
369 if (!(entries[idx].port & NSP_ETH_PORT_LANES_MASK)) {
370 printf("trying to set port state on disabled port %d\n", idx);
374 nfp_nsp_config_set_state(nsp, entries, idx);
384 nfp_eth_config_cleanup_end(struct nfp_nsp *nsp)
386 union eth_table_entry *entries = nfp_nsp_config_entries(nsp);
388 nfp_nsp_config_set_modified(nsp, 0);
389 nfp_nsp_config_clear_state(nsp);
395 * nfp_eth_config_commit_end() - perform recorded configuration changes
396 * @nsp: NFP NSP handle returned from nfp_eth_config_start()
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
404 * 0 - configuration successful;
405 * 1 - no changes were needed;
406 * -ERRNO - configuration failed.
409 nfp_eth_config_commit_end(struct nfp_nsp *nsp)
411 union eth_table_entry *entries = nfp_nsp_config_entries(nsp);
414 if (nfp_nsp_config_modified(nsp)) {
415 ret = nfp_nsp_write_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE);
416 ret = ret < 0 ? ret : 0;
419 nfp_eth_config_cleanup_end(nsp);
425 * nfp_eth_set_mod_enable() - set PHY module enable control bit
426 * @cpp: NFP CPP handle
427 * @idx: NFP chip-wide port index
428 * @enable: Desired state
430 * Enable or disable PHY module (this usually means setting the TX lanes
434 * 0 - configuration successful;
435 * 1 - no changes were needed;
436 * -ERRNO - configuration failed.
439 nfp_eth_set_mod_enable(struct nfp_cpp *cpp, unsigned int idx, int enable)
441 union eth_table_entry *entries;
445 nsp = nfp_eth_config_start(cpp, idx);
449 entries = nfp_nsp_config_entries(nsp);
451 /* Check if we are already in requested state */
452 reg = rte_le_to_cpu_64(entries[idx].state);
453 if (enable != (int)FIELD_GET(NSP_ETH_CTRL_ENABLED, reg)) {
454 reg = rte_le_to_cpu_64(entries[idx].control);
455 reg &= ~NSP_ETH_CTRL_ENABLED;
456 reg |= FIELD_PREP(NSP_ETH_CTRL_ENABLED, enable);
457 entries[idx].control = rte_cpu_to_le_64(reg);
459 nfp_nsp_config_set_modified(nsp, 1);
462 return nfp_eth_config_commit_end(nsp);
466 * nfp_eth_set_configured() - set PHY module configured control bit
467 * @cpp: NFP CPP handle
468 * @idx: NFP chip-wide port index
469 * @configed: Desired state
471 * Set the ifup/ifdown state on the PHY.
474 * 0 - configuration successful;
475 * 1 - no changes were needed;
476 * -ERRNO - configuration failed.
479 nfp_eth_set_configured(struct nfp_cpp *cpp, unsigned int idx, int configed)
481 union eth_table_entry *entries;
485 nsp = nfp_eth_config_start(cpp, idx);
490 * Older ABI versions did support this feature, however this has only
491 * been reliable since ABI 20.
493 if (nfp_nsp_get_abi_ver_minor(nsp) < 20) {
494 nfp_eth_config_cleanup_end(nsp);
498 entries = nfp_nsp_config_entries(nsp);
500 /* Check if we are already in requested state */
501 reg = rte_le_to_cpu_64(entries[idx].state);
502 if (configed != (int)FIELD_GET(NSP_ETH_STATE_CONFIGURED, reg)) {
503 reg = rte_le_to_cpu_64(entries[idx].control);
504 reg &= ~NSP_ETH_CTRL_CONFIGURED;
505 reg |= FIELD_PREP(NSP_ETH_CTRL_CONFIGURED, configed);
506 entries[idx].control = rte_cpu_to_le_64(reg);
508 nfp_nsp_config_set_modified(nsp, 1);
511 return nfp_eth_config_commit_end(nsp);
515 nfp_eth_set_bit_config(struct nfp_nsp *nsp, unsigned int raw_idx,
516 const uint64_t mask, const unsigned int shift,
517 unsigned int val, const uint64_t ctrl_bit)
519 union eth_table_entry *entries = nfp_nsp_config_entries(nsp);
520 unsigned int idx = nfp_nsp_config_idx(nsp);
524 * Note: set features were added in ABI 0.14 but the error
525 * codes were initially not populated correctly.
527 if (nfp_nsp_get_abi_ver_minor(nsp) < 17) {
528 printf("set operations not supported, please update flash\n");
532 /* Check if we are already in requested state */
533 reg = rte_le_to_cpu_64(entries[idx].raw[raw_idx]);
534 if (val == (reg & mask) >> shift)
538 reg |= (val << shift) & mask;
539 entries[idx].raw[raw_idx] = rte_cpu_to_le_64(reg);
541 entries[idx].control |= rte_cpu_to_le_64(ctrl_bit);
543 nfp_nsp_config_set_modified(nsp, 1);
548 #define NFP_ETH_SET_BIT_CONFIG(nsp, raw_idx, mask, val, ctrl_bit) \
550 typeof(mask) _x = (mask); \
551 nfp_eth_set_bit_config(nsp, raw_idx, _x, __bf_shf(_x), \
556 * __nfp_eth_set_aneg() - set PHY autonegotiation control bit
557 * @nsp: NFP NSP handle returned from nfp_eth_config_start()
558 * @mode: Desired autonegotiation mode
560 * Allow/disallow PHY module to advertise/perform autonegotiation.
561 * Will write to hwinfo overrides in the flash (persistent config).
563 * Return: 0 or -ERRNO.
566 __nfp_eth_set_aneg(struct nfp_nsp *nsp, enum nfp_eth_aneg mode)
568 return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_STATE,
569 NSP_ETH_STATE_ANEG, mode,
570 NSP_ETH_CTRL_SET_ANEG);
574 * __nfp_eth_set_fec() - set PHY forward error correction control bit
575 * @nsp: NFP NSP handle returned from nfp_eth_config_start()
576 * @mode: Desired fec mode
578 * Set the PHY module forward error correction mode.
579 * Will write to hwinfo overrides in the flash (persistent config).
581 * Return: 0 or -ERRNO.
584 __nfp_eth_set_fec(struct nfp_nsp *nsp, enum nfp_eth_fec mode)
586 return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_STATE,
587 NSP_ETH_STATE_FEC, mode,
588 NSP_ETH_CTRL_SET_FEC);
592 * nfp_eth_set_fec() - set PHY forward error correction control mode
593 * @cpp: NFP CPP handle
594 * @idx: NFP chip-wide port index
595 * @mode: Desired fec mode
598 * 0 - configuration successful;
599 * 1 - no changes were needed;
600 * -ERRNO - configuration failed.
603 nfp_eth_set_fec(struct nfp_cpp *cpp, unsigned int idx, enum nfp_eth_fec mode)
608 nsp = nfp_eth_config_start(cpp, idx);
612 err = __nfp_eth_set_fec(nsp, mode);
614 nfp_eth_config_cleanup_end(nsp);
618 return nfp_eth_config_commit_end(nsp);
622 * __nfp_eth_set_speed() - set interface speed/rate
623 * @nsp: NFP NSP handle returned from nfp_eth_config_start()
624 * @speed: Desired speed (per lane)
626 * Set lane speed. Provided @speed value should be subport speed divided
627 * by number of lanes this subport is spanning (i.e. 10000 for 40G, 25000 for
629 * Will write to hwinfo overrides in the flash (persistent config).
631 * Return: 0 or -ERRNO.
634 __nfp_eth_set_speed(struct nfp_nsp *nsp, unsigned int speed)
636 enum nfp_eth_rate rate;
638 rate = nfp_eth_speed2rate(speed);
639 if (rate == RATE_INVALID) {
640 printf("could not find matching lane rate for speed %u\n",
645 return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_STATE,
646 NSP_ETH_STATE_RATE, rate,
647 NSP_ETH_CTRL_SET_RATE);
651 * __nfp_eth_set_split() - set interface lane split
652 * @nsp: NFP NSP handle returned from nfp_eth_config_start()
653 * @lanes: Desired lanes per port
655 * Set number of lanes in the port.
656 * Will write to hwinfo overrides in the flash (persistent config).
658 * Return: 0 or -ERRNO.
661 __nfp_eth_set_split(struct nfp_nsp *nsp, unsigned int lanes)
663 return NFP_ETH_SET_BIT_CONFIG(nsp, NSP_ETH_RAW_PORT, NSP_ETH_PORT_LANES,
664 lanes, NSP_ETH_CTRL_SET_LANES);