xref: /openbmc/linux/drivers/net/ethernet/netronome/nfp/flower/main.c (revision 4da722ca19f30f7db250db808d1ab1703607a932)
1 /*
2  * Copyright (C) 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 #include <linux/etherdevice.h>
35 #include <linux/pci.h>
36 #include <linux/skbuff.h>
37 #include <linux/vmalloc.h>
38 #include <net/devlink.h>
39 #include <net/dst_metadata.h>
40 
41 #include "main.h"
42 #include "../nfpcore/nfp_cpp.h"
43 #include "../nfpcore/nfp_nffw.h"
44 #include "../nfpcore/nfp_nsp.h"
45 #include "../nfp_app.h"
46 #include "../nfp_main.h"
47 #include "../nfp_net.h"
48 #include "../nfp_net_repr.h"
49 #include "../nfp_port.h"
50 #include "./cmsg.h"
51 
52 #define NFP_FLOWER_ALLOWED_VER 0x0001000000010000UL
53 
54 static const char *nfp_flower_extra_cap(struct nfp_app *app, struct nfp_net *nn)
55 {
56 	return "FLOWER";
57 }
58 
59 static enum devlink_eswitch_mode eswitch_mode_get(struct nfp_app *app)
60 {
61 	return DEVLINK_ESWITCH_MODE_SWITCHDEV;
62 }
63 
64 static enum nfp_repr_type
65 nfp_flower_repr_get_type_and_port(struct nfp_app *app, u32 port_id, u8 *port)
66 {
67 	switch (FIELD_GET(NFP_FLOWER_CMSG_PORT_TYPE, port_id)) {
68 	case NFP_FLOWER_CMSG_PORT_TYPE_PHYS_PORT:
69 		*port = FIELD_GET(NFP_FLOWER_CMSG_PORT_PHYS_PORT_NUM,
70 				  port_id);
71 		return NFP_REPR_TYPE_PHYS_PORT;
72 
73 	case NFP_FLOWER_CMSG_PORT_TYPE_PCIE_PORT:
74 		*port = FIELD_GET(NFP_FLOWER_CMSG_PORT_VNIC, port_id);
75 		if (FIELD_GET(NFP_FLOWER_CMSG_PORT_VNIC_TYPE, port_id) ==
76 		    NFP_FLOWER_CMSG_PORT_VNIC_TYPE_PF)
77 			return NFP_REPR_TYPE_PF;
78 		else
79 			return NFP_REPR_TYPE_VF;
80 	}
81 
82 	return NFP_FLOWER_CMSG_PORT_TYPE_UNSPEC;
83 }
84 
85 static struct net_device *
86 nfp_flower_repr_get(struct nfp_app *app, u32 port_id)
87 {
88 	enum nfp_repr_type repr_type;
89 	struct nfp_reprs *reprs;
90 	u8 port = 0;
91 
92 	repr_type = nfp_flower_repr_get_type_and_port(app, port_id, &port);
93 
94 	reprs = rcu_dereference(app->reprs[repr_type]);
95 	if (!reprs)
96 		return NULL;
97 
98 	if (port >= reprs->num_reprs)
99 		return NULL;
100 
101 	return reprs->reprs[port];
102 }
103 
104 static int
105 nfp_flower_repr_netdev_open(struct nfp_app *app, struct nfp_repr *repr)
106 {
107 	int err;
108 
109 	err = nfp_flower_cmsg_portmod(repr, true);
110 	if (err)
111 		return err;
112 
113 	netif_carrier_on(repr->netdev);
114 	netif_tx_wake_all_queues(repr->netdev);
115 
116 	return 0;
117 }
118 
119 static int
120 nfp_flower_repr_netdev_stop(struct nfp_app *app, struct nfp_repr *repr)
121 {
122 	netif_carrier_off(repr->netdev);
123 	netif_tx_disable(repr->netdev);
124 
125 	return nfp_flower_cmsg_portmod(repr, false);
126 }
127 
128 static void nfp_flower_sriov_disable(struct nfp_app *app)
129 {
130 	nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_VF);
131 }
132 
133 static int
134 nfp_flower_spawn_vnic_reprs(struct nfp_app *app,
135 			    enum nfp_flower_cmsg_port_vnic_type vnic_type,
136 			    enum nfp_repr_type repr_type, unsigned int cnt)
137 {
138 	u8 nfp_pcie = nfp_cppcore_pcie_unit(app->pf->cpp);
139 	struct nfp_flower_priv *priv = app->priv;
140 	struct nfp_reprs *reprs, *old_reprs;
141 	enum nfp_port_type port_type;
142 	const u8 queue = 0;
143 	int i, err;
144 
145 	port_type = repr_type == NFP_REPR_TYPE_PF ? NFP_PORT_PF_PORT :
146 						    NFP_PORT_VF_PORT;
147 
148 	reprs = nfp_reprs_alloc(cnt);
149 	if (!reprs)
150 		return -ENOMEM;
151 
152 	for (i = 0; i < cnt; i++) {
153 		struct nfp_port *port;
154 		u32 port_id;
155 
156 		reprs->reprs[i] = nfp_repr_alloc(app);
157 		if (!reprs->reprs[i]) {
158 			err = -ENOMEM;
159 			goto err_reprs_clean;
160 		}
161 
162 		port = nfp_port_alloc(app, port_type, reprs->reprs[i]);
163 		if (repr_type == NFP_REPR_TYPE_PF) {
164 			port->pf_id = i;
165 		} else {
166 			port->pf_id = 0; /* For now we only support 1 PF */
167 			port->vf_id = i;
168 		}
169 
170 		eth_hw_addr_random(reprs->reprs[i]);
171 
172 		port_id = nfp_flower_cmsg_pcie_port(nfp_pcie, vnic_type,
173 						    i, queue);
174 		err = nfp_repr_init(app, reprs->reprs[i],
175 				    port_id, port, priv->nn->dp.netdev);
176 		if (err) {
177 			nfp_port_free(port);
178 			goto err_reprs_clean;
179 		}
180 
181 		nfp_info(app->cpp, "%s%d Representor(%s) created\n",
182 			 repr_type == NFP_REPR_TYPE_PF ? "PF" : "VF", i,
183 			 reprs->reprs[i]->name);
184 	}
185 
186 	old_reprs = nfp_app_reprs_set(app, repr_type, reprs);
187 	if (IS_ERR(old_reprs)) {
188 		err = PTR_ERR(old_reprs);
189 		goto err_reprs_clean;
190 	}
191 
192 	return 0;
193 err_reprs_clean:
194 	nfp_reprs_clean_and_free(reprs);
195 	return err;
196 }
197 
198 static int nfp_flower_sriov_enable(struct nfp_app *app, int num_vfs)
199 {
200 	return nfp_flower_spawn_vnic_reprs(app,
201 					   NFP_FLOWER_CMSG_PORT_VNIC_TYPE_VF,
202 					   NFP_REPR_TYPE_VF, num_vfs);
203 }
204 
205 static void nfp_flower_stop(struct nfp_app *app)
206 {
207 	nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PF);
208 	nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PHYS_PORT);
209 
210 }
211 
212 static int
213 nfp_flower_spawn_phy_reprs(struct nfp_app *app, struct nfp_flower_priv *priv)
214 {
215 	struct nfp_eth_table *eth_tbl = app->pf->eth_tbl;
216 	struct nfp_reprs *reprs, *old_reprs;
217 	unsigned int i;
218 	int err;
219 
220 	reprs = nfp_reprs_alloc(eth_tbl->max_index + 1);
221 	if (!reprs)
222 		return -ENOMEM;
223 
224 	for (i = 0; i < eth_tbl->count; i++) {
225 		int phys_port = eth_tbl->ports[i].index;
226 		struct nfp_port *port;
227 		u32 cmsg_port_id;
228 
229 		reprs->reprs[phys_port] = nfp_repr_alloc(app);
230 		if (!reprs->reprs[phys_port]) {
231 			err = -ENOMEM;
232 			goto err_reprs_clean;
233 		}
234 
235 		port = nfp_port_alloc(app, NFP_PORT_PHYS_PORT,
236 				      reprs->reprs[phys_port]);
237 		if (IS_ERR(port)) {
238 			err = PTR_ERR(port);
239 			goto err_reprs_clean;
240 		}
241 		err = nfp_port_init_phy_port(app->pf, app, port, i);
242 		if (err) {
243 			nfp_port_free(port);
244 			goto err_reprs_clean;
245 		}
246 
247 		SET_NETDEV_DEV(reprs->reprs[phys_port], &priv->nn->pdev->dev);
248 		nfp_net_get_mac_addr(app->pf, port);
249 
250 		cmsg_port_id = nfp_flower_cmsg_phys_port(phys_port);
251 		err = nfp_repr_init(app, reprs->reprs[phys_port],
252 				    cmsg_port_id, port, priv->nn->dp.netdev);
253 		if (err) {
254 			nfp_port_free(port);
255 			goto err_reprs_clean;
256 		}
257 
258 		nfp_info(app->cpp, "Phys Port %d Representor(%s) created\n",
259 			 phys_port, reprs->reprs[phys_port]->name);
260 	}
261 
262 	old_reprs = nfp_app_reprs_set(app, NFP_REPR_TYPE_PHYS_PORT, reprs);
263 	if (IS_ERR(old_reprs)) {
264 		err = PTR_ERR(old_reprs);
265 		goto err_reprs_clean;
266 	}
267 
268 	return 0;
269 err_reprs_clean:
270 	nfp_reprs_clean_and_free(reprs);
271 	return err;
272 }
273 
274 static int nfp_flower_start(struct nfp_app *app)
275 {
276 	int err;
277 
278 	err = nfp_flower_spawn_phy_reprs(app, app->priv);
279 	if (err)
280 		return err;
281 
282 	return nfp_flower_spawn_vnic_reprs(app,
283 					   NFP_FLOWER_CMSG_PORT_VNIC_TYPE_PF,
284 					   NFP_REPR_TYPE_PF, 1);
285 }
286 
287 static int nfp_flower_vnic_init(struct nfp_app *app, struct nfp_net *nn,
288 				unsigned int id)
289 {
290 	struct nfp_flower_priv *priv = app->priv;
291 
292 	if (id > 0) {
293 		nfp_warn(app->cpp, "FlowerNIC doesn't support more than one data vNIC\n");
294 		goto err_invalid_port;
295 	}
296 
297 	priv->nn = nn;
298 
299 	eth_hw_addr_random(nn->dp.netdev);
300 	netif_keep_dst(nn->dp.netdev);
301 
302 	return 0;
303 
304 err_invalid_port:
305 	nn->port = nfp_port_alloc(app, NFP_PORT_INVALID, nn->dp.netdev);
306 	return PTR_ERR_OR_ZERO(nn->port);
307 }
308 
309 static int nfp_flower_init(struct nfp_app *app)
310 {
311 	const struct nfp_pf *pf = app->pf;
312 	u64 version;
313 	int err;
314 
315 	if (!pf->eth_tbl) {
316 		nfp_warn(app->cpp, "FlowerNIC requires eth table\n");
317 		return -EINVAL;
318 	}
319 
320 	if (!pf->mac_stats_bar) {
321 		nfp_warn(app->cpp, "FlowerNIC requires mac_stats BAR\n");
322 		return -EINVAL;
323 	}
324 
325 	if (!pf->vf_cfg_bar) {
326 		nfp_warn(app->cpp, "FlowerNIC requires vf_cfg BAR\n");
327 		return -EINVAL;
328 	}
329 
330 	version = nfp_rtsym_read_le(app->pf->rtbl, "hw_flower_version", &err);
331 	if (err) {
332 		nfp_warn(app->cpp, "FlowerNIC requires hw_flower_version memory symbol\n");
333 		return err;
334 	}
335 
336 	/* We need to ensure hardware has enough flower capabilities. */
337 	if (version != NFP_FLOWER_ALLOWED_VER) {
338 		nfp_warn(app->cpp, "FlowerNIC: unsupported firmware version\n");
339 		return -EINVAL;
340 	}
341 
342 	app->priv = vzalloc(sizeof(struct nfp_flower_priv));
343 	if (!app->priv)
344 		return -ENOMEM;
345 
346 	err = nfp_flower_metadata_init(app);
347 	if (err)
348 		goto err_free_app_priv;
349 
350 	return 0;
351 
352 err_free_app_priv:
353 	vfree(app->priv);
354 	return err;
355 }
356 
357 static void nfp_flower_clean(struct nfp_app *app)
358 {
359 	nfp_flower_metadata_cleanup(app);
360 	vfree(app->priv);
361 	app->priv = NULL;
362 }
363 
364 const struct nfp_app_type app_flower = {
365 	.id		= NFP_APP_FLOWER_NIC,
366 	.name		= "flower",
367 	.ctrl_has_meta	= true,
368 
369 	.extra_cap	= nfp_flower_extra_cap,
370 
371 	.init		= nfp_flower_init,
372 	.clean		= nfp_flower_clean,
373 
374 	.vnic_init	= nfp_flower_vnic_init,
375 
376 	.repr_open	= nfp_flower_repr_netdev_open,
377 	.repr_stop	= nfp_flower_repr_netdev_stop,
378 
379 	.start		= nfp_flower_start,
380 	.stop		= nfp_flower_stop,
381 
382 	.ctrl_msg_rx	= nfp_flower_cmsg_rx,
383 
384 	.sriov_enable	= nfp_flower_sriov_enable,
385 	.sriov_disable	= nfp_flower_sriov_disable,
386 
387 	.eswitch_mode_get  = eswitch_mode_get,
388 	.repr_get	= nfp_flower_repr_get,
389 
390 	.setup_tc	= nfp_flower_setup_tc,
391 };
392