xref: /openbmc/linux/drivers/net/ethernet/netronome/nfp/flower/main.c (revision 2eb3ed33e55d003d721d4d1a5e72fe323c12b4c0)
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 	struct nfp_flower_priv *priv = app->priv;
131 
132 	if (!priv->nn)
133 		return;
134 
135 	nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_VF);
136 }
137 
138 static int
139 nfp_flower_spawn_vnic_reprs(struct nfp_app *app,
140 			    enum nfp_flower_cmsg_port_vnic_type vnic_type,
141 			    enum nfp_repr_type repr_type, unsigned int cnt)
142 {
143 	u8 nfp_pcie = nfp_cppcore_pcie_unit(app->pf->cpp);
144 	struct nfp_flower_priv *priv = app->priv;
145 	enum nfp_port_type port_type;
146 	struct nfp_reprs *reprs;
147 	const u8 queue = 0;
148 	int i, err;
149 
150 	port_type = repr_type == NFP_REPR_TYPE_PF ? NFP_PORT_PF_PORT :
151 						    NFP_PORT_VF_PORT;
152 
153 	reprs = nfp_reprs_alloc(cnt);
154 	if (!reprs)
155 		return -ENOMEM;
156 
157 	for (i = 0; i < cnt; i++) {
158 		struct nfp_port *port;
159 		u32 port_id;
160 
161 		reprs->reprs[i] = nfp_repr_alloc(app);
162 		if (!reprs->reprs[i]) {
163 			err = -ENOMEM;
164 			goto err_reprs_clean;
165 		}
166 
167 		/* For now we only support 1 PF */
168 		WARN_ON(repr_type == NFP_REPR_TYPE_PF && i);
169 
170 		port = nfp_port_alloc(app, port_type, reprs->reprs[i]);
171 		if (repr_type == NFP_REPR_TYPE_PF) {
172 			port->pf_id = i;
173 			port->vnic = priv->nn->dp.ctrl_bar;
174 		} else {
175 			port->pf_id = 0;
176 			port->vf_id = i;
177 			port->vnic =
178 				app->pf->vf_cfg_mem + i * NFP_NET_CFG_BAR_SZ;
179 		}
180 
181 		eth_hw_addr_random(reprs->reprs[i]);
182 
183 		port_id = nfp_flower_cmsg_pcie_port(nfp_pcie, vnic_type,
184 						    i, queue);
185 		err = nfp_repr_init(app, reprs->reprs[i],
186 				    port_id, port, priv->nn->dp.netdev);
187 		if (err) {
188 			nfp_port_free(port);
189 			goto err_reprs_clean;
190 		}
191 
192 		nfp_info(app->cpp, "%s%d Representor(%s) created\n",
193 			 repr_type == NFP_REPR_TYPE_PF ? "PF" : "VF", i,
194 			 reprs->reprs[i]->name);
195 	}
196 
197 	nfp_app_reprs_set(app, repr_type, reprs);
198 
199 	return 0;
200 err_reprs_clean:
201 	nfp_reprs_clean_and_free(reprs);
202 	return err;
203 }
204 
205 static int nfp_flower_sriov_enable(struct nfp_app *app, int num_vfs)
206 {
207 	struct nfp_flower_priv *priv = app->priv;
208 
209 	if (!priv->nn)
210 		return 0;
211 
212 	return nfp_flower_spawn_vnic_reprs(app,
213 					   NFP_FLOWER_CMSG_PORT_VNIC_TYPE_VF,
214 					   NFP_REPR_TYPE_VF, num_vfs);
215 }
216 
217 static int
218 nfp_flower_spawn_phy_reprs(struct nfp_app *app, struct nfp_flower_priv *priv)
219 {
220 	struct nfp_eth_table *eth_tbl = app->pf->eth_tbl;
221 	struct sk_buff *ctrl_skb;
222 	struct nfp_reprs *reprs;
223 	unsigned int i;
224 	int err;
225 
226 	ctrl_skb = nfp_flower_cmsg_mac_repr_start(app, eth_tbl->count);
227 	if (!ctrl_skb)
228 		return -ENOMEM;
229 
230 	reprs = nfp_reprs_alloc(eth_tbl->max_index + 1);
231 	if (!reprs) {
232 		err = -ENOMEM;
233 		goto err_free_ctrl_skb;
234 	}
235 
236 	for (i = 0; i < eth_tbl->count; i++) {
237 		unsigned int phys_port = eth_tbl->ports[i].index;
238 		struct nfp_port *port;
239 		u32 cmsg_port_id;
240 
241 		reprs->reprs[phys_port] = nfp_repr_alloc(app);
242 		if (!reprs->reprs[phys_port]) {
243 			err = -ENOMEM;
244 			goto err_reprs_clean;
245 		}
246 
247 		port = nfp_port_alloc(app, NFP_PORT_PHYS_PORT,
248 				      reprs->reprs[phys_port]);
249 		if (IS_ERR(port)) {
250 			err = PTR_ERR(port);
251 			goto err_reprs_clean;
252 		}
253 		err = nfp_port_init_phy_port(app->pf, app, port, i);
254 		if (err) {
255 			nfp_port_free(port);
256 			goto err_reprs_clean;
257 		}
258 
259 		SET_NETDEV_DEV(reprs->reprs[phys_port], &priv->nn->pdev->dev);
260 		nfp_net_get_mac_addr(app->pf, port);
261 
262 		cmsg_port_id = nfp_flower_cmsg_phys_port(phys_port);
263 		err = nfp_repr_init(app, reprs->reprs[phys_port],
264 				    cmsg_port_id, port, priv->nn->dp.netdev);
265 		if (err) {
266 			nfp_port_free(port);
267 			goto err_reprs_clean;
268 		}
269 
270 		nfp_flower_cmsg_mac_repr_add(ctrl_skb, i,
271 					     eth_tbl->ports[i].nbi,
272 					     eth_tbl->ports[i].base,
273 					     phys_port);
274 
275 		nfp_info(app->cpp, "Phys Port %d Representor(%s) created\n",
276 			 phys_port, reprs->reprs[phys_port]->name);
277 	}
278 
279 	nfp_app_reprs_set(app, NFP_REPR_TYPE_PHYS_PORT, reprs);
280 
281 	/* The MAC_REPR control message should be sent after the MAC
282 	 * representors are registered using nfp_app_reprs_set().  This is
283 	 * because the firmware may respond with control messages for the
284 	 * MAC representors, f.e. to provide the driver with information
285 	 * about their state, and without registration the driver will drop
286 	 * any such messages.
287 	 */
288 	nfp_ctrl_tx(app->ctrl, ctrl_skb);
289 
290 	return 0;
291 err_reprs_clean:
292 	nfp_reprs_clean_and_free(reprs);
293 err_free_ctrl_skb:
294 	kfree_skb(ctrl_skb);
295 	return err;
296 }
297 
298 static int nfp_flower_vnic_alloc(struct nfp_app *app, struct nfp_net *nn,
299 				 unsigned int id)
300 {
301 	if (id > 0) {
302 		nfp_warn(app->cpp, "FlowerNIC doesn't support more than one data vNIC\n");
303 		goto err_invalid_port;
304 	}
305 
306 	eth_hw_addr_random(nn->dp.netdev);
307 	netif_keep_dst(nn->dp.netdev);
308 
309 	return 0;
310 
311 err_invalid_port:
312 	nn->port = nfp_port_alloc(app, NFP_PORT_INVALID, nn->dp.netdev);
313 	return PTR_ERR_OR_ZERO(nn->port);
314 }
315 
316 static void nfp_flower_vnic_clean(struct nfp_app *app, struct nfp_net *nn)
317 {
318 	struct nfp_flower_priv *priv = app->priv;
319 
320 	if (app->pf->num_vfs)
321 		nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_VF);
322 	nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PF);
323 	nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PHYS_PORT);
324 
325 	priv->nn = NULL;
326 }
327 
328 static int nfp_flower_vnic_init(struct nfp_app *app, struct nfp_net *nn)
329 {
330 	struct nfp_flower_priv *priv = app->priv;
331 	int err;
332 
333 	priv->nn = nn;
334 
335 	err = nfp_flower_spawn_phy_reprs(app, app->priv);
336 	if (err)
337 		goto err_clear_nn;
338 
339 	err = nfp_flower_spawn_vnic_reprs(app,
340 					  NFP_FLOWER_CMSG_PORT_VNIC_TYPE_PF,
341 					  NFP_REPR_TYPE_PF, 1);
342 	if (err)
343 		goto err_destroy_reprs_phy;
344 
345 	if (app->pf->num_vfs) {
346 		err = nfp_flower_spawn_vnic_reprs(app,
347 						  NFP_FLOWER_CMSG_PORT_VNIC_TYPE_VF,
348 						  NFP_REPR_TYPE_VF,
349 						  app->pf->num_vfs);
350 		if (err)
351 			goto err_destroy_reprs_pf;
352 	}
353 
354 	return 0;
355 
356 err_destroy_reprs_pf:
357 	nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PF);
358 err_destroy_reprs_phy:
359 	nfp_reprs_clean_and_free_by_type(app, NFP_REPR_TYPE_PHYS_PORT);
360 err_clear_nn:
361 	priv->nn = NULL;
362 	return err;
363 }
364 
365 static int nfp_flower_init(struct nfp_app *app)
366 {
367 	const struct nfp_pf *pf = app->pf;
368 	struct nfp_flower_priv *app_priv;
369 	u64 version;
370 	int err;
371 
372 	if (!pf->eth_tbl) {
373 		nfp_warn(app->cpp, "FlowerNIC requires eth table\n");
374 		return -EINVAL;
375 	}
376 
377 	if (!pf->mac_stats_bar) {
378 		nfp_warn(app->cpp, "FlowerNIC requires mac_stats BAR\n");
379 		return -EINVAL;
380 	}
381 
382 	if (!pf->vf_cfg_bar) {
383 		nfp_warn(app->cpp, "FlowerNIC requires vf_cfg BAR\n");
384 		return -EINVAL;
385 	}
386 
387 	version = nfp_rtsym_read_le(app->pf->rtbl, "hw_flower_version", &err);
388 	if (err) {
389 		nfp_warn(app->cpp, "FlowerNIC requires hw_flower_version memory symbol\n");
390 		return err;
391 	}
392 
393 	/* We need to ensure hardware has enough flower capabilities. */
394 	if (version != NFP_FLOWER_ALLOWED_VER) {
395 		nfp_warn(app->cpp, "FlowerNIC: unsupported firmware version\n");
396 		return -EINVAL;
397 	}
398 
399 	app_priv = vzalloc(sizeof(struct nfp_flower_priv));
400 	if (!app_priv)
401 		return -ENOMEM;
402 
403 	app->priv = app_priv;
404 	app_priv->app = app;
405 	skb_queue_head_init(&app_priv->cmsg_skbs);
406 	INIT_WORK(&app_priv->cmsg_work, nfp_flower_cmsg_process_rx);
407 
408 	err = nfp_flower_metadata_init(app);
409 	if (err)
410 		goto err_free_app_priv;
411 
412 	return 0;
413 
414 err_free_app_priv:
415 	vfree(app->priv);
416 	return err;
417 }
418 
419 static void nfp_flower_clean(struct nfp_app *app)
420 {
421 	struct nfp_flower_priv *app_priv = app->priv;
422 
423 	skb_queue_purge(&app_priv->cmsg_skbs);
424 	flush_work(&app_priv->cmsg_work);
425 
426 	nfp_flower_metadata_cleanup(app);
427 	vfree(app->priv);
428 	app->priv = NULL;
429 }
430 
431 static int nfp_flower_start(struct nfp_app *app)
432 {
433 	return nfp_tunnel_config_start(app);
434 }
435 
436 static void nfp_flower_stop(struct nfp_app *app)
437 {
438 	nfp_tunnel_config_stop(app);
439 }
440 
441 const struct nfp_app_type app_flower = {
442 	.id		= NFP_APP_FLOWER_NIC,
443 	.name		= "flower",
444 	.ctrl_has_meta	= true,
445 
446 	.extra_cap	= nfp_flower_extra_cap,
447 
448 	.init		= nfp_flower_init,
449 	.clean		= nfp_flower_clean,
450 
451 	.vnic_alloc	= nfp_flower_vnic_alloc,
452 	.vnic_init	= nfp_flower_vnic_init,
453 	.vnic_clean	= nfp_flower_vnic_clean,
454 
455 	.repr_open	= nfp_flower_repr_netdev_open,
456 	.repr_stop	= nfp_flower_repr_netdev_stop,
457 
458 	.start		= nfp_flower_start,
459 	.stop		= nfp_flower_stop,
460 
461 	.ctrl_msg_rx	= nfp_flower_cmsg_rx,
462 
463 	.sriov_enable	= nfp_flower_sriov_enable,
464 	.sriov_disable	= nfp_flower_sriov_disable,
465 
466 	.eswitch_mode_get  = eswitch_mode_get,
467 	.repr_get	= nfp_flower_repr_get,
468 
469 	.setup_tc	= nfp_flower_setup_tc,
470 };
471