1 | /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) */ |
2 | /* Copyright (C) 2017-2018 Netronome Systems, Inc. */ |
3 | |
4 | #ifndef _NFP_APP_H |
5 | #define _NFP_APP_H 1 |
6 | |
7 | #include <net/devlink.h> |
8 | |
9 | #include <trace/events/devlink.h> |
10 | |
11 | #include "nfp_net_repr.h" |
12 | |
13 | #define NFP_APP_CTRL_MTU_MAX U32_MAX |
14 | |
15 | struct bpf_prog; |
16 | struct net_device; |
17 | struct netdev_bpf; |
18 | struct netlink_ext_ack; |
19 | struct pci_dev; |
20 | struct sk_buff; |
21 | struct nfp_app; |
22 | struct nfp_cpp; |
23 | struct nfp_pf; |
24 | struct nfp_repr; |
25 | struct nfp_net; |
26 | |
27 | enum nfp_app_id { |
28 | NFP_APP_CORE_NIC = 0x1, |
29 | NFP_APP_BPF_NIC = 0x2, |
30 | NFP_APP_FLOWER_NIC = 0x3, |
31 | NFP_APP_ACTIVE_BUFFER_MGMT_NIC = 0x4, |
32 | }; |
33 | |
34 | extern const struct nfp_app_type app_nic; |
35 | extern const struct nfp_app_type app_bpf; |
36 | extern const struct nfp_app_type app_flower; |
37 | extern const struct nfp_app_type app_abm; |
38 | |
39 | /** |
40 | * struct nfp_app_type - application definition |
41 | * @id: application ID |
42 | * @name: application name |
43 | * @ctrl_cap_mask: ctrl vNIC capability mask, allows disabling features like |
44 | * IRQMOD which are on by default but counter-productive for |
45 | * control messages which are often latency-sensitive |
46 | * @ctrl_has_meta: control messages have prepend of type:5/port:CTRL |
47 | * |
48 | * Callbacks |
49 | * @init: perform basic app checks and init |
50 | * @clean: clean app state |
51 | * @extra_cap: extra capabilities string |
52 | * @ndo_init: vNIC and repr netdev .ndo_init |
53 | * @ndo_uninit: vNIC and repr netdev .ndo_unint |
54 | * @vnic_alloc: allocate vNICs (assign port types, etc.) |
55 | * @vnic_free: free up app's vNIC state |
56 | * @vnic_init: vNIC netdev was registered |
57 | * @vnic_clean: vNIC netdev about to be unregistered |
58 | * @repr_init: representor about to be registered |
59 | * @repr_preclean: representor about to unregistered, executed before app |
60 | * reference to the it is removed |
61 | * @repr_clean: representor about to be unregistered |
62 | * @repr_open: representor netdev open callback |
63 | * @repr_stop: representor netdev stop callback |
64 | * @check_mtu: MTU change request on a netdev (verify it is valid) |
65 | * @repr_change_mtu: MTU change request on repr (make and verify change) |
66 | * @port_get_stats: get extra ethtool statistics for a port |
67 | * @port_get_stats_count: get count of extra statistics for a port |
68 | * @port_get_stats_strings: get strings for extra statistics |
69 | * @start: start application logic |
70 | * @stop: stop application logic |
71 | * @netdev_event: Netdevice notifier event |
72 | * @ctrl_msg_rx: control message handler |
73 | * @ctrl_msg_rx_raw: handler for control messages from data queues |
74 | * @setup_tc: setup TC ndo |
75 | * @bpf: BPF ndo offload-related calls |
76 | * @xdp_offload: offload an XDP program |
77 | * @eswitch_mode_get: get SR-IOV eswitch mode |
78 | * @eswitch_mode_set: set SR-IOV eswitch mode |
79 | * @sriov_enable: app-specific sriov initialisation |
80 | * @sriov_disable: app-specific sriov clean-up |
81 | * @dev_get: get representor or internal port representing netdev |
82 | */ |
83 | struct nfp_app_type { |
84 | enum nfp_app_id id; |
85 | const char *name; |
86 | |
87 | u32 ctrl_cap_mask; |
88 | bool ctrl_has_meta; |
89 | |
90 | int (*init)(struct nfp_app *app); |
91 | void (*clean)(struct nfp_app *app); |
92 | |
93 | const char *(*)(struct nfp_app *app, struct nfp_net *nn); |
94 | |
95 | int (*ndo_init)(struct nfp_app *app, struct net_device *netdev); |
96 | void (*ndo_uninit)(struct nfp_app *app, struct net_device *netdev); |
97 | |
98 | int (*vnic_alloc)(struct nfp_app *app, struct nfp_net *nn, |
99 | unsigned int id); |
100 | void (*vnic_free)(struct nfp_app *app, struct nfp_net *nn); |
101 | int (*vnic_init)(struct nfp_app *app, struct nfp_net *nn); |
102 | void (*vnic_clean)(struct nfp_app *app, struct nfp_net *nn); |
103 | |
104 | int (*repr_init)(struct nfp_app *app, struct net_device *netdev); |
105 | void (*repr_preclean)(struct nfp_app *app, struct net_device *netdev); |
106 | void (*repr_clean)(struct nfp_app *app, struct net_device *netdev); |
107 | |
108 | int (*repr_open)(struct nfp_app *app, struct nfp_repr *repr); |
109 | int (*repr_stop)(struct nfp_app *app, struct nfp_repr *repr); |
110 | |
111 | int (*check_mtu)(struct nfp_app *app, struct net_device *netdev, |
112 | int new_mtu); |
113 | int (*repr_change_mtu)(struct nfp_app *app, struct net_device *netdev, |
114 | int new_mtu); |
115 | |
116 | u64 *(*port_get_stats)(struct nfp_app *app, |
117 | struct nfp_port *port, u64 *data); |
118 | int (*port_get_stats_count)(struct nfp_app *app, struct nfp_port *port); |
119 | u8 *(*port_get_stats_strings)(struct nfp_app *app, |
120 | struct nfp_port *port, u8 *data); |
121 | |
122 | int (*start)(struct nfp_app *app); |
123 | void (*stop)(struct nfp_app *app); |
124 | |
125 | int (*netdev_event)(struct nfp_app *app, struct net_device *netdev, |
126 | unsigned long event, void *ptr); |
127 | |
128 | void (*ctrl_msg_rx)(struct nfp_app *app, struct sk_buff *skb); |
129 | void (*ctrl_msg_rx_raw)(struct nfp_app *app, const void *data, |
130 | unsigned int len); |
131 | |
132 | int (*setup_tc)(struct nfp_app *app, struct net_device *netdev, |
133 | enum tc_setup_type type, void *type_data); |
134 | int (*bpf)(struct nfp_app *app, struct nfp_net *nn, |
135 | struct netdev_bpf *xdp); |
136 | int (*xdp_offload)(struct nfp_app *app, struct nfp_net *nn, |
137 | struct bpf_prog *prog, |
138 | struct netlink_ext_ack *extack); |
139 | |
140 | int (*sriov_enable)(struct nfp_app *app, int num_vfs); |
141 | void (*sriov_disable)(struct nfp_app *app); |
142 | |
143 | enum devlink_eswitch_mode (*eswitch_mode_get)(struct nfp_app *app); |
144 | int (*eswitch_mode_set)(struct nfp_app *app, u16 mode); |
145 | struct net_device *(*dev_get)(struct nfp_app *app, u32 id, |
146 | bool *redir_egress); |
147 | }; |
148 | |
149 | /** |
150 | * struct nfp_app - NFP application container |
151 | * @pdev: backpointer to PCI device |
152 | * @pf: backpointer to NFP PF structure |
153 | * @cpp: pointer to the CPP handle |
154 | * @ctrl: pointer to ctrl vNIC struct |
155 | * @reprs: array of pointers to representors |
156 | * @type: pointer to const application ops and info |
157 | * @ctrl_mtu: MTU to set on the control vNIC (set in .init()) |
158 | * @netdev_nb: Netdevice notifier block |
159 | * @priv: app-specific priv data |
160 | */ |
161 | struct nfp_app { |
162 | struct pci_dev *pdev; |
163 | struct nfp_pf *pf; |
164 | struct nfp_cpp *cpp; |
165 | |
166 | struct nfp_net *ctrl; |
167 | struct nfp_reprs __rcu *reprs[NFP_REPR_TYPE_MAX + 1]; |
168 | |
169 | const struct nfp_app_type *type; |
170 | unsigned int ctrl_mtu; |
171 | |
172 | struct notifier_block netdev_nb; |
173 | |
174 | void *priv; |
175 | }; |
176 | |
177 | static inline void assert_nfp_app_locked(struct nfp_app *app) |
178 | { |
179 | devl_assert_locked(devlink: priv_to_devlink(priv: app->pf)); |
180 | } |
181 | |
182 | static inline bool nfp_app_is_locked(struct nfp_app *app) |
183 | { |
184 | return devl_lock_is_held(devlink: priv_to_devlink(priv: app->pf)); |
185 | } |
186 | |
187 | void nfp_check_rhashtable_empty(void *ptr, void *arg); |
188 | bool __nfp_ctrl_tx(struct nfp_net *nn, struct sk_buff *skb); |
189 | bool nfp_ctrl_tx(struct nfp_net *nn, struct sk_buff *skb); |
190 | |
191 | static inline int nfp_app_init(struct nfp_app *app) |
192 | { |
193 | if (!app->type->init) |
194 | return 0; |
195 | return app->type->init(app); |
196 | } |
197 | |
198 | static inline void nfp_app_clean(struct nfp_app *app) |
199 | { |
200 | if (app->type->clean) |
201 | app->type->clean(app); |
202 | } |
203 | |
204 | int nfp_app_ndo_init(struct net_device *netdev); |
205 | void nfp_app_ndo_uninit(struct net_device *netdev); |
206 | |
207 | static inline int nfp_app_vnic_alloc(struct nfp_app *app, struct nfp_net *nn, |
208 | unsigned int id) |
209 | { |
210 | return app->type->vnic_alloc(app, nn, id); |
211 | } |
212 | |
213 | static inline void nfp_app_vnic_free(struct nfp_app *app, struct nfp_net *nn) |
214 | { |
215 | if (app->type->vnic_free) |
216 | app->type->vnic_free(app, nn); |
217 | } |
218 | |
219 | static inline int nfp_app_vnic_init(struct nfp_app *app, struct nfp_net *nn) |
220 | { |
221 | if (!app->type->vnic_init) |
222 | return 0; |
223 | return app->type->vnic_init(app, nn); |
224 | } |
225 | |
226 | static inline void nfp_app_vnic_clean(struct nfp_app *app, struct nfp_net *nn) |
227 | { |
228 | if (app->type->vnic_clean) |
229 | app->type->vnic_clean(app, nn); |
230 | } |
231 | |
232 | static inline int nfp_app_repr_open(struct nfp_app *app, struct nfp_repr *repr) |
233 | { |
234 | if (!app->type->repr_open) |
235 | return -EINVAL; |
236 | return app->type->repr_open(app, repr); |
237 | } |
238 | |
239 | static inline int nfp_app_repr_stop(struct nfp_app *app, struct nfp_repr *repr) |
240 | { |
241 | if (!app->type->repr_stop) |
242 | return -EINVAL; |
243 | return app->type->repr_stop(app, repr); |
244 | } |
245 | |
246 | static inline int |
247 | nfp_app_repr_init(struct nfp_app *app, struct net_device *netdev) |
248 | { |
249 | if (!app->type->repr_init) |
250 | return 0; |
251 | return app->type->repr_init(app, netdev); |
252 | } |
253 | |
254 | static inline void |
255 | nfp_app_repr_preclean(struct nfp_app *app, struct net_device *netdev) |
256 | { |
257 | if (app->type->repr_preclean) |
258 | app->type->repr_preclean(app, netdev); |
259 | } |
260 | |
261 | static inline void |
262 | nfp_app_repr_clean(struct nfp_app *app, struct net_device *netdev) |
263 | { |
264 | if (app->type->repr_clean) |
265 | app->type->repr_clean(app, netdev); |
266 | } |
267 | |
268 | static inline int |
269 | nfp_app_check_mtu(struct nfp_app *app, struct net_device *netdev, int new_mtu) |
270 | { |
271 | if (!app || !app->type->check_mtu) |
272 | return 0; |
273 | return app->type->check_mtu(app, netdev, new_mtu); |
274 | } |
275 | |
276 | static inline int |
277 | nfp_app_repr_change_mtu(struct nfp_app *app, struct net_device *netdev, |
278 | int new_mtu) |
279 | { |
280 | if (!app || !app->type->repr_change_mtu) |
281 | return 0; |
282 | return app->type->repr_change_mtu(app, netdev, new_mtu); |
283 | } |
284 | |
285 | static inline const char *nfp_app_name(struct nfp_app *app) |
286 | { |
287 | if (!app) |
288 | return "" ; |
289 | return app->type->name; |
290 | } |
291 | |
292 | static inline bool nfp_app_needs_ctrl_vnic(struct nfp_app *app) |
293 | { |
294 | return app && app->type->ctrl_msg_rx; |
295 | } |
296 | |
297 | static inline bool nfp_app_ctrl_has_meta(struct nfp_app *app) |
298 | { |
299 | return app->type->ctrl_has_meta; |
300 | } |
301 | |
302 | static inline bool nfp_app_ctrl_uses_data_vnics(struct nfp_app *app) |
303 | { |
304 | return app && app->type->ctrl_msg_rx_raw; |
305 | } |
306 | |
307 | static inline const char *(struct nfp_app *app, |
308 | struct nfp_net *nn) |
309 | { |
310 | if (!app || !app->type->extra_cap) |
311 | return "" ; |
312 | return app->type->extra_cap(app, nn); |
313 | } |
314 | |
315 | static inline bool nfp_app_has_tc(struct nfp_app *app) |
316 | { |
317 | return app && app->type->setup_tc; |
318 | } |
319 | |
320 | static inline int nfp_app_setup_tc(struct nfp_app *app, |
321 | struct net_device *netdev, |
322 | enum tc_setup_type type, void *type_data) |
323 | { |
324 | if (!app || !app->type->setup_tc) |
325 | return -EOPNOTSUPP; |
326 | return app->type->setup_tc(app, netdev, type, type_data); |
327 | } |
328 | |
329 | static inline int nfp_app_bpf(struct nfp_app *app, struct nfp_net *nn, |
330 | struct netdev_bpf *bpf) |
331 | { |
332 | if (!app || !app->type->bpf) |
333 | return -EINVAL; |
334 | return app->type->bpf(app, nn, bpf); |
335 | } |
336 | |
337 | static inline int nfp_app_xdp_offload(struct nfp_app *app, struct nfp_net *nn, |
338 | struct bpf_prog *prog, |
339 | struct netlink_ext_ack *extack) |
340 | { |
341 | if (!app || !app->type->xdp_offload) |
342 | return -EOPNOTSUPP; |
343 | return app->type->xdp_offload(app, nn, prog, extack); |
344 | } |
345 | |
346 | static inline bool __nfp_app_ctrl_tx(struct nfp_app *app, struct sk_buff *skb) |
347 | { |
348 | trace_devlink_hwmsg(devlink: priv_to_devlink(priv: app->pf), incoming: false, type: 0, |
349 | buf: skb->data, len: skb->len); |
350 | |
351 | return __nfp_ctrl_tx(nn: app->ctrl, skb); |
352 | } |
353 | |
354 | static inline bool nfp_app_ctrl_tx(struct nfp_app *app, struct sk_buff *skb) |
355 | { |
356 | trace_devlink_hwmsg(devlink: priv_to_devlink(priv: app->pf), incoming: false, type: 0, |
357 | buf: skb->data, len: skb->len); |
358 | |
359 | return nfp_ctrl_tx(nn: app->ctrl, skb); |
360 | } |
361 | |
362 | static inline void nfp_app_ctrl_rx(struct nfp_app *app, struct sk_buff *skb) |
363 | { |
364 | trace_devlink_hwmsg(devlink: priv_to_devlink(priv: app->pf), incoming: true, type: 0, |
365 | buf: skb->data, len: skb->len); |
366 | |
367 | app->type->ctrl_msg_rx(app, skb); |
368 | } |
369 | |
370 | static inline void |
371 | nfp_app_ctrl_rx_raw(struct nfp_app *app, const void *data, unsigned int len) |
372 | { |
373 | if (!app || !app->type->ctrl_msg_rx_raw) |
374 | return; |
375 | |
376 | trace_devlink_hwmsg(devlink: priv_to_devlink(priv: app->pf), incoming: true, type: 0, buf: data, len); |
377 | app->type->ctrl_msg_rx_raw(app, data, len); |
378 | } |
379 | |
380 | static inline int nfp_app_eswitch_mode_get(struct nfp_app *app, u16 *mode) |
381 | { |
382 | if (!app->type->eswitch_mode_get) |
383 | return -EOPNOTSUPP; |
384 | |
385 | *mode = app->type->eswitch_mode_get(app); |
386 | |
387 | return 0; |
388 | } |
389 | |
390 | static inline int nfp_app_eswitch_mode_set(struct nfp_app *app, u16 mode) |
391 | { |
392 | if (!app->type->eswitch_mode_set) |
393 | return -EOPNOTSUPP; |
394 | return app->type->eswitch_mode_set(app, mode); |
395 | } |
396 | |
397 | static inline int nfp_app_sriov_enable(struct nfp_app *app, int num_vfs) |
398 | { |
399 | if (!app || !app->type->sriov_enable) |
400 | return -EOPNOTSUPP; |
401 | return app->type->sriov_enable(app, num_vfs); |
402 | } |
403 | |
404 | static inline void nfp_app_sriov_disable(struct nfp_app *app) |
405 | { |
406 | if (app && app->type->sriov_disable) |
407 | app->type->sriov_disable(app); |
408 | } |
409 | |
410 | static inline |
411 | struct net_device *nfp_app_dev_get(struct nfp_app *app, u32 id, |
412 | bool *redir_egress) |
413 | { |
414 | if (unlikely(!app || !app->type->dev_get)) |
415 | return NULL; |
416 | |
417 | return app->type->dev_get(app, id, redir_egress); |
418 | } |
419 | |
420 | struct nfp_app *nfp_app_from_netdev(struct net_device *netdev); |
421 | |
422 | u64 *nfp_app_port_get_stats(struct nfp_port *port, u64 *data); |
423 | int nfp_app_port_get_stats_count(struct nfp_port *port); |
424 | u8 *nfp_app_port_get_stats_strings(struct nfp_port *port, u8 *data); |
425 | |
426 | struct nfp_reprs * |
427 | nfp_reprs_get_locked(struct nfp_app *app, enum nfp_repr_type type); |
428 | struct nfp_reprs * |
429 | nfp_app_reprs_set(struct nfp_app *app, enum nfp_repr_type type, |
430 | struct nfp_reprs *reprs); |
431 | |
432 | const char *nfp_app_mip_name(struct nfp_app *app); |
433 | struct sk_buff * |
434 | nfp_app_ctrl_msg_alloc(struct nfp_app *app, unsigned int size, gfp_t priority); |
435 | |
436 | struct nfp_app *nfp_app_alloc(struct nfp_pf *pf, enum nfp_app_id id); |
437 | void nfp_app_free(struct nfp_app *app); |
438 | int nfp_app_start(struct nfp_app *app, struct nfp_net *ctrl); |
439 | void nfp_app_stop(struct nfp_app *app); |
440 | |
441 | /* Callbacks shared between apps */ |
442 | |
443 | int nfp_app_nic_vnic_alloc(struct nfp_app *app, struct nfp_net *nn, |
444 | unsigned int id); |
445 | int nfp_app_nic_vnic_init_phy_port(struct nfp_pf *pf, struct nfp_app *app, |
446 | struct nfp_net *nn, unsigned int id); |
447 | |
448 | #endif |
449 | |