]> git.proxmox.com Git - mirror_ubuntu-bionic-kernel.git/commitdiff
nfp: forbid disabling hw-tc-offload on representors while offload active
authorJakub Kicinski <jakub.kicinski@netronome.com>
Thu, 8 Feb 2018 04:55:24 +0000 (20:55 -0800)
committerSeth Forshee <seth.forshee@canonical.com>
Wed, 28 Mar 2018 17:15:25 +0000 (12:15 -0500)
BugLink: http://bugs.launchpad.net/bugs/1752828
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>
(back-ported from commit d692403e5cf8008f31f5664a6f3ce3e65d54f458)
Signed-off-by: Kamal Mostafa <kamal@canonical.com>
Signed-off-by: Seth Forshee <seth.forshee@canonical.com>
drivers/net/ethernet/netronome/nfp/bpf/main.c
drivers/net/ethernet/netronome/nfp/flower/offload.c
drivers/net/ethernet/netronome/nfp/nfp_app.h
drivers/net/ethernet/netronome/nfp/nfp_net_common.c
drivers/net/ethernet/netronome/nfp/nfp_net_repr.c
drivers/net/ethernet/netronome/nfp/nfp_port.c
drivers/net/ethernet/netronome/nfp/nfp_port.h

index 9af15d1b0b7fb5fd4f689b5a4335f24bb78a1668..42223170b1e679fc1053d19d49e946f82b5a7215 100644 (file)
@@ -164,6 +164,7 @@ static int nfp_bpf_setup_tc_block_cb(enum tc_setup_type type,
                return err;
 
        bv->tc_prog = cls_bpf->prog;
+       nn->port->tc_offload_cnt = !!bv->tc_prog;
        return 0;
 }
 
@@ -201,11 +202,6 @@ static int nfp_bpf_setup_tc(struct nfp_app *app, struct net_device *netdev,
        }
 }
 
-static bool nfp_bpf_tc_busy(struct nfp_app *app, struct nfp_net *nn)
-{
-       return nn->dp.ctrl & NFP_NET_CFG_CTRL_BPF;
-}
-
 const struct nfp_app_type app_bpf = {
        .id             = NFP_APP_BPF_NIC,
        .name           = "ebpf",
@@ -216,7 +212,6 @@ const struct nfp_app_type app_bpf = {
        .vnic_free      = nfp_bpf_vnic_free,
 
        .setup_tc       = nfp_bpf_setup_tc,
-       .tc_busy        = nfp_bpf_tc_busy,
        .xdp_offload    = nfp_bpf_xdp_offload,
 
        .bpf_verifier_prep      = nfp_bpf_verifier_prep,
index 553f94f55dce64ba9cdb661ff9bdb04faf41acac..5521da60735a71618241b790d1450ead968266d5 100644 (file)
@@ -325,6 +325,7 @@ static int
 nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
                       struct tc_cls_flower_offload *flow, bool egress)
 {
+       struct nfp_port *port = nfp_port_from_netdev(netdev);
        struct nfp_flower_priv *priv = app->priv;
        struct nfp_fl_payload *flow_pay;
        struct nfp_fl_key_ls *key_layer;
@@ -364,6 +365,7 @@ nfp_flower_add_offload(struct nfp_app *app, struct net_device *netdev,
        INIT_HLIST_NODE(&flow_pay->link);
        flow_pay->tc_flower_cookie = flow->cookie;
        hash_add_rcu(priv->flow_table, &flow_pay->link, flow->cookie);
+       port->tc_offload_cnt++;
 
        /* Deallocate flow payload when flower rule has been destroyed. */
        kfree(key_layer);
@@ -395,6 +397,7 @@ static int
 nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev,
                       struct tc_cls_flower_offload *flow)
 {
+       struct nfp_port *port = nfp_port_from_netdev(netdev);
        struct nfp_fl_payload *nfp_flow;
        int err;
 
@@ -416,6 +419,7 @@ nfp_flower_del_offload(struct nfp_app *app, struct net_device *netdev,
 
 err_free_flow:
        hash_del_rcu(&nfp_flow->link);
+       port->tc_offload_cnt--;
        kfree(nfp_flow->action_data);
        kfree(nfp_flow->mask_data);
        kfree(nfp_flow->unmasked_data);
index 0e5e0305ad1cea276516a9c50122c4a16575d9fe..6d0d599aaa8e944b794d12d34290b58fbedb6a67 100644 (file)
@@ -84,7 +84,6 @@ extern const struct nfp_app_type app_flower;
  * @stop:      stop application logic
  * @ctrl_msg_rx:    control message handler
  * @setup_tc:  setup TC ndo
- * @tc_busy:   TC HW offload busy (rules loaded)
  * @xdp_offload:    offload an XDP program
  * @bpf_verifier_prep: verifier prep for dev-specific BPF programs
  * @bpf_translate:     translate call for dev-specific BPF programs
@@ -124,7 +123,6 @@ struct nfp_app_type {
 
        int (*setup_tc)(struct nfp_app *app, struct net_device *netdev,
                        enum tc_setup_type type, void *type_data);
-       bool (*tc_busy)(struct nfp_app *app, struct nfp_net *nn);
        int (*xdp_offload)(struct nfp_app *app, struct nfp_net *nn,
                           struct bpf_prog *prog);
        int (*bpf_verifier_prep)(struct nfp_app *app, struct nfp_net *nn,
@@ -277,13 +275,6 @@ static inline bool nfp_app_has_tc(struct nfp_app *app)
        return app && app->type->setup_tc;
 }
 
-static inline bool nfp_app_tc_busy(struct nfp_app *app, struct nfp_net *nn)
-{
-       if (!app || !app->type->tc_busy)
-               return false;
-       return app->type->tc_busy(app, nn);
-}
-
 static inline int nfp_app_setup_tc(struct nfp_app *app,
                                   struct net_device *netdev,
                                   enum tc_setup_type type, void *type_data)
index 9290e75f6e30dc4a5aaaaf074ad86a8deb2cb7a8..e4a9ff7a7c17d9d52d5ccfdc15cea5f969e0970c 100644 (file)
@@ -3175,10 +3175,9 @@ static int nfp_net_set_features(struct net_device *netdev,
                        new_ctrl &= ~NFP_NET_CFG_CTRL_GATHER;
        }
 
-       if (changed & NETIF_F_HW_TC && nfp_app_tc_busy(nn->app, nn)) {
-               nn_err(nn, "Cannot disable HW TC offload while in use\n");
-               return -EBUSY;
-       }
+       err = nfp_port_set_features(netdev, features);
+       if (err)
+               return err;
 
        nn_dbg(nn, "Feature change 0x%llx -> 0x%llx (changed=0x%llx)\n",
               netdev->features, features, changed);
index 78b36c67c232f661d5c2633034c5ada015bf1aeb..5a7174efacb2d41cd0b59671a28d86e1d1a9947b 100644 (file)
@@ -250,6 +250,7 @@ const struct net_device_ops nfp_repr_netdev_ops = {
        .ndo_set_vf_spoofchk    = nfp_app_set_vf_spoofchk,
        .ndo_get_vf_config      = nfp_app_get_vf_config,
        .ndo_set_vf_link_state  = nfp_app_set_vf_link_state,
+       .ndo_set_features       = nfp_port_set_features,
 };
 
 static void nfp_repr_clean(struct nfp_repr *repr)
index 34a6e035fe9a207a8ee6a2ebc18a54391e37d826..7bd8be5c833b08f3416fff971e1101bf8791214d 100644 (file)
@@ -32,6 +32,7 @@
  */
 
 #include <linux/lockdep.h>
+#include <linux/netdevice.h>
 #include <net/switchdev.h>
 
 #include "nfpcore/nfp_cpp.h"
@@ -100,6 +101,23 @@ int nfp_port_setup_tc(struct net_device *netdev, enum tc_setup_type type,
        return nfp_app_setup_tc(port->app, netdev, type, type_data);
 }
 
+int nfp_port_set_features(struct net_device *netdev, netdev_features_t features)
+{
+       struct nfp_port *port;
+
+       port = nfp_port_from_netdev(netdev);
+       if (!port)
+               return 0;
+
+       if ((netdev->features & NETIF_F_HW_TC) > (features & NETIF_F_HW_TC) &&
+           port->tc_offload_cnt) {
+               netdev_err(netdev, "Cannot disable HW TC offload while offloads active\n");
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
 struct nfp_port *
 nfp_port_from_id(struct nfp_pf *pf, enum nfp_port_type type, unsigned int id)
 {
index 21bd4aa3264681ea0af49aad1b98a71e0c5c4958..fa7e669a969c6e5baa8aec30fedb410d29806793 100644 (file)
@@ -72,6 +72,8 @@ enum nfp_port_flags {
  * @netdev:    backpointer to associated netdev
  * @type:      what port type does the entity represent
  * @flags:     port flags
+ * @tc_offload_cnt:    number of active TC offloads, how offloads are counted
+ *                     is not defined, use as a boolean
  * @app:       backpointer to the app structure
  * @dl_port:   devlink port structure
  * @eth_id:    for %NFP_PORT_PHYS_PORT port ID in NFP enumeration scheme
@@ -87,6 +89,7 @@ struct nfp_port {
        enum nfp_port_type type;
 
        unsigned long flags;
+       unsigned long tc_offload_cnt;
 
        struct nfp_app *app;
 
@@ -121,6 +124,9 @@ static inline bool nfp_port_is_vnic(const struct nfp_port *port)
        return port->type == NFP_PORT_PF_PORT || port->type == NFP_PORT_VF_PORT;
 }
 
+int
+nfp_port_set_features(struct net_device *netdev, netdev_features_t features);
+
 struct nfp_port *nfp_port_from_netdev(struct net_device *netdev);
 struct nfp_port *
 nfp_port_from_id(struct nfp_pf *pf, enum nfp_port_type type, unsigned int id);