2 * Copyright (C) 2015-2017 Netronome Systems, Inc.
4 * This software is dual licensed under the GNU General License Version 2,
5 * June 1991 as shown in the file COPYING in the top-level directory of this
6 * source tree or the BSD 2-Clause License provided below. You have the
7 * option to license this software under the complete terms of either license.
9 * The BSD 2-Clause License:
11 * Redistribution and use in source and binary forms, with or
12 * without modification, are permitted provided that the following
15 * 1. Redistributions of source code must retain the above
16 * copyright notice, this list of conditions and the following
19 * 2. Redistributions in binary form must reproduce the above
20 * copyright notice, this list of conditions and the following
21 * disclaimer in the documentation and/or other materials
22 * provided with the distribution.
24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
28 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
29 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
30 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
34 /* Authors: David Brunecz <david.brunecz@netronome.com>
35 * Jakub Kicinski <jakub.kicinski@netronome.com>
36 * Jason Mcmullan <jason.mcmullan@netronome.com>
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>
46 #include "nfp_nsp_eth.h"
47 #include "nfp6000/nfp6000.h"
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(struct eth_table_entry))
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)
59 #define NSP_ETH_PORT_LANES_MASK cpu_to_le64(NSP_ETH_PORT_LANES)
61 #define NSP_ETH_STATE_ENABLED BIT_ULL(1)
62 #define NSP_ETH_STATE_TX_ENABLED BIT_ULL(2)
63 #define NSP_ETH_STATE_RX_ENABLED BIT_ULL(3)
64 #define NSP_ETH_STATE_RATE GENMASK_ULL(11, 8)
66 #define NSP_ETH_CTRL_ENABLED BIT_ULL(1)
67 #define NSP_ETH_CTRL_TX_ENABLED BIT_ULL(2)
68 #define NSP_ETH_CTRL_RX_ENABLED BIT_ULL(3)
79 struct eth_table_entry {
87 static unsigned int nfp_eth_rate(enum nfp_eth_rate rate)
89 unsigned int rate_xlate[] = {
91 [RATE_10M] = SPEED_10,
92 [RATE_100M] = SPEED_100,
93 [RATE_1G] = SPEED_1000,
94 [RATE_10G] = SPEED_10000,
95 [RATE_25G] = SPEED_25000,
98 if (rate >= ARRAY_SIZE(rate_xlate))
101 return rate_xlate[rate];
104 static void nfp_eth_copy_mac_reverse(u8 *dst, const u8 *src)
108 for (i = 0; i < ETH_ALEN; i++)
109 dst[ETH_ALEN - i - 1] = src[i];
113 nfp_eth_port_translate(const struct eth_table_entry *src, unsigned int index,
114 struct nfp_eth_table_port *dst)
119 port = le64_to_cpu(src->port);
120 state = le64_to_cpu(src->state);
122 dst->eth_index = FIELD_GET(NSP_ETH_PORT_INDEX, port);
124 dst->nbi = index / NSP_ETH_NBI_PORT_COUNT;
125 dst->base = index % NSP_ETH_NBI_PORT_COUNT;
126 dst->lanes = FIELD_GET(NSP_ETH_PORT_LANES, port);
128 dst->enabled = FIELD_GET(NSP_ETH_STATE_ENABLED, state);
129 dst->tx_enabled = FIELD_GET(NSP_ETH_STATE_TX_ENABLED, state);
130 dst->rx_enabled = FIELD_GET(NSP_ETH_STATE_RX_ENABLED, state);
132 rate = nfp_eth_rate(FIELD_GET(NSP_ETH_STATE_RATE, state));
133 dst->speed = dst->lanes * rate;
135 nfp_eth_copy_mac_reverse(dst->mac_addr, src->mac_addr);
137 snprintf(dst->label, sizeof(dst->label) - 1, "%llu.%llu",
138 FIELD_GET(NSP_ETH_PORT_PHYLABEL, port),
139 FIELD_GET(NSP_ETH_PORT_LABEL, port));
143 * nfp_eth_read_ports() - retrieve port information
144 * @cpp: NFP CPP handle
146 * Read the port information from the device. Returned structure should
147 * be freed with kfree() once no longer needed.
149 * Return: populated ETH table or NULL on error.
151 struct nfp_eth_table *nfp_eth_read_ports(struct nfp_cpp *cpp)
153 struct nfp_eth_table *ret;
156 nsp = nfp_nsp_open(cpp);
160 ret = __nfp_eth_read_ports(cpp, nsp);
166 struct nfp_eth_table *
167 __nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp)
169 struct eth_table_entry *entries;
170 struct nfp_eth_table *table;
174 entries = kzalloc(NSP_ETH_TABLE_SIZE, GFP_KERNEL);
178 ret = nfp_nsp_read_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE);
180 nfp_err(cpp, "reading port table failed %d\n", ret);
185 /* Some versions of flash will give us 0 instead of port count */
188 for (i = 0; i < NSP_ETH_MAX_COUNT; i++)
189 if (entries[i].port & NSP_ETH_PORT_LANES_MASK)
193 table = kzalloc(sizeof(*table) +
194 sizeof(struct nfp_eth_table_port) * cnt, GFP_KERNEL);
201 for (i = 0, j = 0; i < NSP_ETH_MAX_COUNT; i++)
202 if (entries[i].port & NSP_ETH_PORT_LANES_MASK)
203 nfp_eth_port_translate(&entries[i], i,
212 * nfp_eth_set_mod_enable() - set PHY module enable control bit
213 * @cpp: NFP CPP handle
214 * @idx: NFP chip-wide port index
215 * @enable: Desired state
217 * Enable or disable PHY module (this usually means setting the TX lanes
220 * Return: 0 or -ERRNO.
222 int nfp_eth_set_mod_enable(struct nfp_cpp *cpp, unsigned int idx, bool enable)
224 struct eth_table_entry *entries;
229 entries = kzalloc(NSP_ETH_TABLE_SIZE, GFP_KERNEL);
233 nsp = nfp_nsp_open(cpp);
239 ret = nfp_nsp_read_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE);
241 nfp_err(cpp, "reading port table failed %d\n", ret);
245 if (!(entries[idx].port & NSP_ETH_PORT_LANES_MASK)) {
246 nfp_warn(cpp, "trying to set port state on disabled port %d\n",
252 /* Check if we are already in requested state */
253 reg = le64_to_cpu(entries[idx].state);
254 if (enable == FIELD_GET(NSP_ETH_CTRL_ENABLED, reg)) {
259 reg = le64_to_cpu(entries[idx].control);
260 reg &= ~NSP_ETH_CTRL_ENABLED;
261 reg |= FIELD_PREP(NSP_ETH_CTRL_ENABLED, enable);
262 entries[idx].control = cpu_to_le64(reg);
264 ret = nfp_nsp_write_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE);
269 return ret < 0 ? ret : 0;