aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJakub Kicinski <jakub.kicinski@netronome.com>2018-02-07 23:55:24 -0500
committerDavid S. Miller <davem@davemloft.net>2018-02-08 10:01:27 -0500
commitd692403e5cf8008f31f5664a6f3ce3e65d54f458 (patch)
tree497dfc82655e28d9159888154ad9d23248f9d176
parent0b9de4ca853b6ba2c92ff0b4602281001b166639 (diff)
nfp: forbid disabling hw-tc-offload on representors while offload active
All netdevs which can accept TC offloads must implement .ndo_set_features(). nfp_reprs currently do not do that, which means hw-tc-offload can be turned on and off even when offloads are active. Whether the offloads are active is really a question to nfp_ports, so remove the per-app tc_busy callback indirection thing, and simply count the number of offloaded items in nfp_port structure. Fixes: 8a2768732a4d ("nfp: provide infrastructure for offloading flower based TC filters") Signed-off-by: Jakub Kicinski <jakub.kicinski@netronome.com> Reviewed-by: Simon Horman <simon.horman@netronome.com> Tested-by: Pieter Jansen van Vuuren <pieter.jansenvanvuuren@netronome.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/netronome/nfp/bpf/main.c9
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/offload.c4
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_app.h9
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_common.c7
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_net_repr.c1
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_port.c18
-rw-r--r--drivers/net/ethernet/netronome/nfp/nfp_port.h6
7 files changed, 33 insertions, 21 deletions
diff --git a/drivers/net/ethernet/netronome/nfp/bpf/main.c b/drivers/net/ethernet/netronome/nfp/bpf/main.c
index 61898dda11cf..34e98aa6b956 100644
--- a/drivers/net/ethernet/netronome/nfp/bpf/main.c
+++ b/drivers/net/ethernet/netronome/nfp/bpf/main.c
@@ -182,6 +182,7 @@ static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type,
182 return err; 182 return err;
183 183
184 bv->tc_prog = cls_bpf->prog; 184 bv->tc_prog = cls_bpf->prog;
185 nn->port->tc_offload_cnt = !!bv->tc_prog;
185 return 0; 186 return 0;
186} 187}
187 188
@@ -219,13 +220,6 @@ static int nfp_bpf_setup_tc(struct nfp_app *app, struct net_device *netdev,
219 } 220 }
220} 221}
221 222
222static bool nfp_bpf_tc_busy(struct nfp_app *app, struct nfp_net *nn)
223{
224 struct nfp_bpf_vnic *bv = nn->app_priv;
225
226 return !!bv->tc_prog;
227}
228
229static int 223static int
230nfp_bpf_change_mtu(struct nfp_app *app, struct net_device *netdev, int new_mtu) 224nfp_bpf_change_mtu(struct nfp_app *app, struct net_device *netdev, int new_mtu)
231{ 225{
@@ -429,7 +423,6 @@ const struct nfp_app_type app_bpf = {
429 .ctrl_msg_rx = nfp_bpf_ctrl_msg_rx, 423 .ctrl_msg_rx = nfp_bpf_ctrl_msg_rx,
430 424
431 .setup_tc = nfp_bpf_setup_tc, 425 .setup_tc = nfp_bpf_setup_tc,
432 .tc_busy = nfp_bpf_tc_busy,
433 .bpf = nfp_ndo_bpf, 426 .bpf = nfp_ndo_bpf,
434 .xdp_offload = nfp_bpf_xdp_offload, 427 .xdp_offload = nfp_bpf_xdp_offload,
435}; 428};
diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c
index 08c4c6dc5f7f..eb5c13dea8f5 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/offload.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c
@@ -349,6 +349,7 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
349 struct tc_cls_flower_offload *flow, bool egress) 349 struct tc_cls_flower_offload *flow, bool egress)
350{ 350{
351 enum nfp_flower_tun_type tun_type = NFP_FL_TUNNEL_NONE; 351 enum nfp_flower_tun_type tun_type = NFP_FL_TUNNEL_NONE;
352 struct nfp_port *port = nfp_port_from_netdev(netdev);
352 struct nfp_flower_priv *priv = app->priv; 353 struct nfp_flower_priv *priv = app->priv;
353 struct nfp_fl_payload *flow_pay; 354 struct nfp_fl_payload *flow_pay;
354 struct nfp_fl_key_ls *key_layer; 355 struct nfp_fl_key_ls *key_layer;
@@ -390,6 +391,7 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
390 INIT_HLIST_NODE(&flow_pay->link); 391 INIT_HLIST_NODE(&flow_pay->link);
391 flow_pay->tc_flower_cookie = flow->cookie; 392 flow_pay->tc_flower_cookie = flow->cookie;
392 hash_add_rcu(priv->flow_table, &flow_pay->link, flow->cookie); 393 hash_add_rcu(priv->flow_table, &flow_pay->link, flow->cookie);
394 port->tc_offload_cnt++;
393 395
394 /* Deallocate flow payload when flower rule has been destroyed. */ 396 /* Deallocate flow payload when flower rule has been destroyed. */
395 kfree(key_layer); 397 kfree(key_layer);
@@ -421,6 +423,7 @@ static int
421nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev, 423nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev,
422 struct tc_cls_flower_offload *flow) 424 struct tc_cls_flower_offload *flow)
423{ 425{
426 struct nfp_port *port = nfp_port_from_netdev(netdev);
424 struct nfp_fl_payload *nfp_flow; 427 struct nfp_fl_payload *nfp_flow;
425 int err; 428 int err;
426 429
@@ -442,6 +445,7 @@ nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev,
442 445
443err_free_flow: 446err_free_flow:
444 hash_del_rcu(&nfp_flow->link); 447 hash_del_rcu(&nfp_flow->link);
448 port->tc_offload_cnt--;
445 kfree(nfp_flow->action_data); 449 kfree(nfp_flow->action_data);
446 kfree(nfp_flow->mask_data); 450 kfree(nfp_flow->mask_data);
447 kfree(nfp_flow->unmasked_data); 451 kfree(nfp_flow->unmasked_data);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_app.h b/drivers/net/ethernet/netronome/nfp/nfp_app.h
index 437964afa8ee..20546ae67909 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_app.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_app.h
@@ -92,7 +92,6 @@ extern const struct nfp_app_type app_flower;
92 * @stop: stop application logic 92 * @stop: stop application logic
93 * @ctrl_msg_rx: control message handler 93 * @ctrl_msg_rx: control message handler
94 * @setup_tc: setup TC ndo 94 * @setup_tc: setup TC ndo
95 * @tc_busy: TC HW offload busy (rules loaded)
96 * @bpf: BPF ndo offload-related calls 95 * @bpf: BPF ndo offload-related calls
97 * @xdp_offload: offload an XDP program 96 * @xdp_offload: offload an XDP program
98 * @eswitch_mode_get: get SR-IOV eswitch mode 97 * @eswitch_mode_get: get SR-IOV eswitch mode
@@ -135,7 +134,6 @@ struct nfp_app_type {
135 134
136 int (*setup_tc)(struct nfp_app *app, struct net_device *netdev, 135 int (*setup_tc)(struct nfp_app *app, struct net_device *netdev,
137 enum tc_setup_type type, void *type_data); 136 enum tc_setup_type type, void *type_data);
138 bool (*tc_busy)(struct nfp_app *app, struct nfp_net *nn);
139 int (*bpf)(struct nfp_app *app, struct nfp_net *nn, 137 int (*bpf)(struct nfp_app *app, struct nfp_net *nn,
140 struct netdev_bpf *xdp); 138 struct netdev_bpf *xdp);
141 int (*xdp_offload)(struct nfp_app *app, struct nfp_net *nn, 139 int (*xdp_offload)(struct nfp_app *app, struct nfp_net *nn,
@@ -301,13 +299,6 @@ static inline bool nfp_app_has_tc(struct nfp_app *app)
301 return app && app->type->setup_tc; 299 return app && app->type->setup_tc;
302} 300}
303 301
304static inline bool nfp_app_tc_busy(struct nfp_app *app, struct nfp_net *nn)
305{
306 if (!app || !app->type->tc_busy)
307 return false;
308 return app->type->tc_busy(app, nn);
309}
310
311static inline int nfp_app_setup_tc(struct nfp_app *app, 302static inline int nfp_app_setup_tc(struct nfp_app *app,
312 struct net_device *netdev, 303 struct net_device *netdev,
313 enum tc_setup_type type, void *type_data) 304 enum tc_setup_type type, void *type_data)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
index fe77ea8b656c..19e989239af7 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_common.c
@@ -3210,10 +3210,9 @@ static int nfp_net_set_features(struct net_device *netdev,
3210 new_ctrl &= ~NFP_NET_CFG_CTRL_GATHER; 3210 new_ctrl &= ~NFP_NET_CFG_CTRL_GATHER;
3211 } 3211 }
3212 3212
3213 if (changed & NETIF_F_HW_TC && nfp_app_tc_busy(nn->app, nn)) { 3213 err = nfp_port_set_features(netdev, features);
3214 nn_err(nn, "Cannot disable HW TC offload while in use\n"); 3214 if (err)
3215 return -EBUSY; 3215 return err;
3216 }
3217 3216
3218 nn_dbg(nn, "Feature change 0x%llx -> 0x%llx (changed=0x%llx)\n", 3217 nn_dbg(nn, "Feature change 0x%llx -> 0x%llx (changed=0x%llx)\n",
3219 netdev->features, features, changed); 3218 netdev->features, features, changed);
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
index f67da6bde9da..619570524d2a 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
@@ -265,6 +265,7 @@ const struct net_device_ops nfp_repr_netdev_ops = {
265 .ndo_set_vf_spoofchk = nfp_app_set_vf_spoofchk, 265 .ndo_set_vf_spoofchk = nfp_app_set_vf_spoofchk,
266 .ndo_get_vf_config = nfp_app_get_vf_config, 266 .ndo_get_vf_config = nfp_app_get_vf_config,
267 .ndo_set_vf_link_state = nfp_app_set_vf_link_state, 267 .ndo_set_vf_link_state = nfp_app_set_vf_link_state,
268 .ndo_set_features = nfp_port_set_features,
268}; 269};
269 270
270static void nfp_repr_clean(struct nfp_repr *repr) 271static void nfp_repr_clean(struct nfp_repr *repr)
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_port.c b/drivers/net/ethernet/netronome/nfp/nfp_port.c
index 34a6e035fe9a..7bd8be5c833b 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_port.c
+++ b/drivers/net/ethernet/netronome/nfp/nfp_port.c
@@ -32,6 +32,7 @@
32 */ 32 */
33 33
34#include <linux/lockdep.h> 34#include <linux/lockdep.h>
35#include <linux/netdevice.h>
35#include <net/switchdev.h> 36#include <net/switchdev.h>
36 37
37#include "nfpcore/nfp_cpp.h" 38#include "nfpcore/nfp_cpp.h"
@@ -100,6 +101,23 @@ int nfp_port_setup_tc(struct net_device *netdev, enum tc_setup_type type,
100 return nfp_app_setup_tc(port->app, netdev, type, type_data); 101 return nfp_app_setup_tc(port->app, netdev, type, type_data);
101} 102}
102 103
104int nfp_port_set_features(struct net_device *netdev, netdev_features_t features)
105{
106 struct nfp_port *port;
107
108 port = nfp_port_from_netdev(netdev);
109 if (!port)
110 return 0;
111
112 if ((netdev->features & NETIF_F_HW_TC) > (features & NETIF_F_HW_TC) &&
113 port->tc_offload_cnt) {
114 netdev_err(netdev, "Cannot disable HW TC offload while offloads active\n");
115 return -EBUSY;
116 }
117
118 return 0;
119}
120
103struct nfp_port * 121struct nfp_port *
104nfp_port_from_id(struct nfp_pf *pf, enum nfp_port_type type, unsigned int id) 122nfp_port_from_id(struct nfp_pf *pf, enum nfp_port_type type, unsigned int id)
105{ 123{
diff --git a/drivers/net/ethernet/netronome/nfp/nfp_port.h b/drivers/net/ethernet/netronome/nfp/nfp_port.h
index 21bd4aa32646..fa7e669a969c 100644
--- a/drivers/net/ethernet/netronome/nfp/nfp_port.h
+++ b/drivers/net/ethernet/netronome/nfp/nfp_port.h
@@ -72,6 +72,8 @@ enum nfp_port_flags {
72 * @netdev: backpointer to associated netdev 72 * @netdev: backpointer to associated netdev
73 * @type: what port type does the entity represent 73 * @type: what port type does the entity represent
74 * @flags: port flags 74 * @flags: port flags
75 * @tc_offload_cnt: number of active TC offloads, how offloads are counted
76 * is not defined, use as a boolean
75 * @app: backpointer to the app structure 77 * @app: backpointer to the app structure
76 * @dl_port: devlink port structure 78 * @dl_port: devlink port structure
77 * @eth_id: for %NFP_PORT_PHYS_PORT port ID in NFP enumeration scheme 79 * @eth_id: for %NFP_PORT_PHYS_PORT port ID in NFP enumeration scheme
@@ -87,6 +89,7 @@ struct nfp_port {
87 enum nfp_port_type type; 89 enum nfp_port_type type;
88 90
89 unsigned long flags; 91 unsigned long flags;
92 unsigned long tc_offload_cnt;
90 93
91 struct nfp_app *app; 94 struct nfp_app *app;
92 95
@@ -121,6 +124,9 @@ static inline bool nfp_port_is_vnic(const struct nfp_port *port)
121 return port->type == NFP_PORT_PF_PORT || port->type == NFP_PORT_VF_PORT; 124 return port->type == NFP_PORT_PF_PORT || port->type == NFP_PORT_VF_PORT;
122} 125}
123 126
127int
128nfp_port_set_features(struct net_device *netdev, netdev_features_t features);
129
124struct nfp_port *nfp_port_from_netdev(struct net_device *netdev); 130struct nfp_port *nfp_port_from_netdev(struct net_device *netdev);
125struct nfp_port * 131struct nfp_port *
126nfp_port_from_id(struct nfp_pf *pf, enum nfp_port_type type, unsigned int id); 132nfp_port_from_id(struct nfp_pf *pf, enum nfp_port_type type, unsigned int id);