brcmfmac: use local iftype avoiding use-after-free of virtual interface
[linux-2.6-block.git] / drivers / net / ethernet / netronome / nfp / nfpcore / nfp_nsp_eth.c
1 /*
2  * Copyright (C) 2015-2017 Netronome Systems, Inc.
3  *
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.
8  *
9  * The BSD 2-Clause License:
10  *
11  *     Redistribution and use in source and binary forms, with or
12  *     without modification, are permitted provided that the following
13  *     conditions are met:
14  *
15  *      1. Redistributions of source code must retain the above
16  *         copyright notice, this list of conditions and the following
17  *         disclaimer.
18  *
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.
23  *
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
31  * SOFTWARE.
32  */
33
34 /* Authors: David Brunecz <david.brunecz@netronome.com>
35  *          Jakub Kicinski <jakub.kicinski@netronome.com>
36  *          Jason Mcmullan <jason.mcmullan@netronome.com>
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_eth.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(struct 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
59 #define NSP_ETH_PORT_LANES_MASK         cpu_to_le64(NSP_ETH_PORT_LANES)
60
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)
65
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)
69
70 enum nfp_eth_rate {
71         RATE_INVALID = 0,
72         RATE_10M,
73         RATE_100M,
74         RATE_1G,
75         RATE_10G,
76         RATE_25G,
77 };
78
79 struct eth_table_entry {
80         __le64 port;
81         __le64 state;
82         u8 mac_addr[6];
83         u8 resv[2];
84         __le64 control;
85 };
86
87 static unsigned int nfp_eth_rate(enum nfp_eth_rate rate)
88 {
89         unsigned int rate_xlate[] = {
90                 [RATE_INVALID]          = 0,
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,
96         };
97
98         if (rate >= ARRAY_SIZE(rate_xlate))
99                 return 0;
100
101         return rate_xlate[rate];
102 }
103
104 static void nfp_eth_copy_mac_reverse(u8 *dst, const u8 *src)
105 {
106         int i;
107
108         for (i = 0; i < ETH_ALEN; i++)
109                 dst[ETH_ALEN - i - 1] = src[i];
110 }
111
112 static void
113 nfp_eth_port_translate(const struct eth_table_entry *src, unsigned int index,
114                        struct nfp_eth_table_port *dst)
115 {
116         unsigned int rate;
117         u64 port, state;
118
119         port = le64_to_cpu(src->port);
120         state = le64_to_cpu(src->state);
121
122         dst->eth_index = FIELD_GET(NSP_ETH_PORT_INDEX, port);
123         dst->index = index;
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);
127
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);
131
132         rate = nfp_eth_rate(FIELD_GET(NSP_ETH_STATE_RATE, state));
133         dst->speed = dst->lanes * rate;
134
135         nfp_eth_copy_mac_reverse(dst->mac_addr, src->mac_addr);
136
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));
140 }
141
142 /**
143  * nfp_eth_read_ports() - retrieve port information
144  * @cpp:        NFP CPP handle
145  *
146  * Read the port information from the device.  Returned structure should
147  * be freed with kfree() once no longer needed.
148  *
149  * Return: populated ETH table or NULL on error.
150  */
151 struct nfp_eth_table *nfp_eth_read_ports(struct nfp_cpp *cpp)
152 {
153         struct nfp_eth_table *ret;
154         struct nfp_nsp *nsp;
155
156         nsp = nfp_nsp_open(cpp);
157         if (IS_ERR(nsp))
158                 return NULL;
159
160         ret = __nfp_eth_read_ports(cpp, nsp);
161         nfp_nsp_close(nsp);
162
163         return ret;
164 }
165
166 struct nfp_eth_table *
167 __nfp_eth_read_ports(struct nfp_cpp *cpp, struct nfp_nsp *nsp)
168 {
169         struct eth_table_entry *entries;
170         struct nfp_eth_table *table;
171         unsigned int cnt;
172         int i, j, ret;
173
174         entries = kzalloc(NSP_ETH_TABLE_SIZE, GFP_KERNEL);
175         if (!entries)
176                 return NULL;
177
178         ret = nfp_nsp_read_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE);
179         if (ret < 0) {
180                 nfp_err(cpp, "reading port table failed %d\n", ret);
181                 kfree(entries);
182                 return NULL;
183         }
184
185         /* Some versions of flash will give us 0 instead of port count */
186         cnt = ret;
187         if (!cnt) {
188                 for (i = 0; i < NSP_ETH_MAX_COUNT; i++)
189                         if (entries[i].port & NSP_ETH_PORT_LANES_MASK)
190                                 cnt++;
191         }
192
193         table = kzalloc(sizeof(*table) +
194                         sizeof(struct nfp_eth_table_port) * cnt, GFP_KERNEL);
195         if (!table) {
196                 kfree(entries);
197                 return NULL;
198         }
199
200         table->count = cnt;
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,
204                                                &table->ports[j++]);
205
206         kfree(entries);
207
208         return table;
209 }
210
211 /**
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
216  *
217  * Enable or disable PHY module (this usually means setting the TX lanes
218  * disable bits).
219  *
220  * Return: 0 or -ERRNO.
221  */
222 int nfp_eth_set_mod_enable(struct nfp_cpp *cpp, unsigned int idx, bool enable)
223 {
224         struct eth_table_entry *entries;
225         struct nfp_nsp *nsp;
226         u64 reg;
227         int ret;
228
229         entries = kzalloc(NSP_ETH_TABLE_SIZE, GFP_KERNEL);
230         if (!entries)
231                 return -ENOMEM;
232
233         nsp = nfp_nsp_open(cpp);
234         if (IS_ERR(nsp)) {
235                 kfree(entries);
236                 return PTR_ERR(nsp);
237         }
238
239         ret = nfp_nsp_read_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE);
240         if (ret < 0) {
241                 nfp_err(cpp, "reading port table failed %d\n", ret);
242                 goto exit_close_nsp;
243         }
244
245         if (!(entries[idx].port & NSP_ETH_PORT_LANES_MASK)) {
246                 nfp_warn(cpp, "trying to set port state on disabled port %d\n",
247                          idx);
248                 ret = -EINVAL;
249                 goto exit_close_nsp;
250         }
251
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)) {
255                 ret = 0;
256                 goto exit_close_nsp;
257         }
258
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);
263
264         ret = nfp_nsp_write_eth_table(nsp, entries, NSP_ETH_TABLE_SIZE);
265 exit_close_nsp:
266         nfp_nsp_close(nsp);
267         kfree(entries);
268
269         return ret < 0 ? ret : 0;
270 }