net: sched: convert cls_flower->egress_dev users to tc_setup_cb_egdev infra
authorJiri Pirko <jiri@mellanox.com>
Wed, 11 Oct 2017 07:41:09 +0000 (09:41 +0200)
committerDavid S. Miller <davem@davemloft.net>
Thu, 12 Oct 2017 03:15:43 +0000 (20:15 -0700)
The only user of cls_flower->egress_dev is mlx5. So do the conversion
there alongside with the code originating the call in cls_flower
function fl_hw_replace_filter to the newly introduced egress device
callback infrastucture.

Signed-off-by: Jiri Pirko <jiri@mellanox.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/mellanox/mlx5/core/en.h
drivers/net/ethernet/mellanox/mlx5/core/en_main.c
drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
include/net/pkt_cls.h
net/sched/cls_api.c
net/sched/cls_flower.c

index cc13d3dbd3666e346d169ca059900f1faf5ee06f..5ec6d3e8dc89fe0c890b09ea231eba5b82c83d9d 100644 (file)
@@ -1081,6 +1081,9 @@ int mlx5e_ethtool_get_ts_info(struct mlx5e_priv *priv,
 int mlx5e_ethtool_flash_device(struct mlx5e_priv *priv,
                               struct ethtool_flash *flash);
 
+int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
+                  void *type_data);
+
 /* mlx5e generic netdev management API */
 struct net_device*
 mlx5e_create_netdev(struct mlx5_core_dev *mdev, const struct mlx5e_profile *profile,
index cc11bbbd0309d465819abe501859da971239cb0f..2a32102e76486561b5d8a22babb1dbf44604e5c4 100644 (file)
@@ -3108,8 +3108,8 @@ static int mlx5e_setup_tc_cls_flower(struct net_device *dev,
 }
 #endif
 
-static int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
-                         void *type_data)
+int mlx5e_setup_tc(struct net_device *dev, enum tc_setup_type type,
+                  void *type_data)
 {
        switch (type) {
 #ifdef CONFIG_MLX5_ESWITCH
index 45e03c427faf93970a0b35bb17e7f6a0d46fa537..765fc74fbb1b5f1aac15aa82bf8596303226e407 100644 (file)
@@ -34,6 +34,7 @@
 #include <linux/mlx5/fs.h>
 #include <net/switchdev.h>
 #include <net/pkt_cls.h>
+#include <net/act_api.h>
 #include <net/netevent.h>
 #include <net/arp.h>
 
@@ -667,14 +668,6 @@ mlx5e_rep_setup_tc_cls_flower(struct net_device *dev,
            cls_flower->common.chain_index)
                return -EOPNOTSUPP;
 
-       if (cls_flower->egress_dev) {
-               struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
-
-               dev = mlx5_eswitch_get_uplink_netdev(esw);
-               return dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSFLOWER,
-                                                    cls_flower);
-       }
-
        switch (cls_flower->command) {
        case TC_CLSFLOWER_REPLACE:
                return mlx5e_configure_flower(priv, cls_flower);
@@ -698,6 +691,14 @@ static int mlx5e_rep_setup_tc(struct net_device *dev, enum tc_setup_type type,
        }
 }
 
+static int mlx5e_rep_setup_tc_cb(enum tc_setup_type type, void *type_data,
+                                void *cb_priv)
+{
+       struct net_device *dev = cb_priv;
+
+       return mlx5e_setup_tc(dev, type, type_data);
+}
+
 bool mlx5e_is_uplink_rep(struct mlx5e_priv *priv)
 {
        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
@@ -1017,15 +1018,24 @@ mlx5e_vport_rep_load(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep)
                goto err_detach_netdev;
        }
 
+       err = tc_setup_cb_egdev_register(netdev, mlx5e_rep_setup_tc_cb,
+                                        mlx5_eswitch_get_uplink_netdev(esw));
+       if (err)
+               goto err_neigh_cleanup;
+
        err = register_netdev(netdev);
        if (err) {
                pr_warn("Failed to register representor netdev for vport %d\n",
                        rep->vport);
-               goto err_neigh_cleanup;
+               goto err_egdev_cleanup;
        }
 
        return 0;
 
+err_egdev_cleanup:
+       tc_setup_cb_egdev_unregister(netdev, mlx5e_rep_setup_tc_cb,
+                                    mlx5_eswitch_get_uplink_netdev(esw));
+
 err_neigh_cleanup:
        mlx5e_rep_neigh_cleanup(rpriv);
 
@@ -1047,7 +1057,8 @@ mlx5e_vport_rep_unload(struct mlx5_eswitch *esw, struct mlx5_eswitch_rep *rep)
        void *ppriv = priv->ppriv;
 
        unregister_netdev(rep->netdev);
-
+       tc_setup_cb_egdev_unregister(netdev, mlx5e_rep_setup_tc_cb,
+                                    mlx5_eswitch_get_uplink_netdev(esw));
        mlx5e_rep_neigh_cleanup(rpriv);
        mlx5e_detach_netdev(priv);
        mlx5e_destroy_netdev(priv);
index 6f8149c82571df999e857e211e18033c4f61e35c..c0bdf5cad727238650be3ff09c789dd3eeef9bc6 100644 (file)
@@ -206,8 +206,6 @@ int tcf_exts_dump(struct sk_buff *skb, struct tcf_exts *exts);
 int tcf_exts_dump_stats(struct sk_buff *skb, struct tcf_exts *exts);
 int tcf_exts_get_dev(struct net_device *dev, struct tcf_exts *exts,
                     struct net_device **hw_dev);
-int tcf_exts_egdev_cb_call(struct tcf_exts *exts, enum tc_setup_type type,
-                          void *type_data, bool err_stop);
 
 /**
  * struct tcf_pkt_info - packet information
@@ -407,6 +405,9 @@ tcf_match_indev(struct sk_buff *skb, int ifindex)
 }
 #endif /* CONFIG_NET_CLS_IND */
 
+int tc_setup_cb_call(struct tcf_exts *exts, enum tc_setup_type type,
+                    void *type_data, bool err_stop);
+
 struct tc_cls_common_offload {
        u32 chain_index;
        __be16 protocol;
index 99f9432f63cf1c3b61437d6692a3aca6c1693d85..51994a202585ac6e775f5c86d9f561b87b15c714 100644 (file)
@@ -1026,8 +1026,9 @@ int tcf_exts_get_dev(struct net_device *dev, struct tcf_exts *exts,
 }
 EXPORT_SYMBOL(tcf_exts_get_dev);
 
-int tcf_exts_egdev_cb_call(struct tcf_exts *exts, enum tc_setup_type type,
-                          void *type_data, bool err_stop)
+static int tc_exts_setup_cb_egdev_call(struct tcf_exts *exts,
+                                      enum tc_setup_type type,
+                                      void *type_data, bool err_stop)
 {
        int ok_count = 0;
 #ifdef CONFIG_NET_CLS_ACT
@@ -1054,7 +1055,13 @@ int tcf_exts_egdev_cb_call(struct tcf_exts *exts, enum tc_setup_type type,
 #endif
        return ok_count;
 }
-EXPORT_SYMBOL(tcf_exts_egdev_cb_call);
+
+int tc_setup_cb_call(struct tcf_exts *exts, enum tc_setup_type type,
+                    void *type_data, bool err_stop)
+{
+       return tc_exts_setup_cb_egdev_call(exts, type, type_data, err_stop);
+}
+EXPORT_SYMBOL(tc_setup_cb_call);
 
 static int __init tc_filter_init(void)
 {
index db831ac708f60a71cb67824639ede1bdc5dc532b..5b7bb968d1d4418fe6c0fb914646c0c180b525a9 100644 (file)
@@ -88,7 +88,6 @@ struct cls_fl_filter {
        u32 handle;
        u32 flags;
        struct rcu_head rcu;
-       struct net_device *hw_dev;
 };
 
 static unsigned short int fl_mask_range(const struct fl_flow_mask *mask)
@@ -201,16 +200,17 @@ static void fl_destroy_filter(struct rcu_head *head)
 static void fl_hw_destroy_filter(struct tcf_proto *tp, struct cls_fl_filter *f)
 {
        struct tc_cls_flower_offload cls_flower = {};
-       struct net_device *dev = f->hw_dev;
-
-       if (!tc_can_offload(dev))
-               return;
+       struct net_device *dev = tp->q->dev_queue->dev;
 
        tc_cls_common_offload_init(&cls_flower.common, tp);
        cls_flower.command = TC_CLSFLOWER_DESTROY;
        cls_flower.cookie = (unsigned long) f;
 
-       dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSFLOWER, &cls_flower);
+       if (tc_can_offload(dev))
+               dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSFLOWER,
+                                             &cls_flower);
+       tc_setup_cb_call(&f->exts, TC_SETUP_CLSFLOWER,
+                        &cls_flower, false);
 }
 
 static int fl_hw_replace_filter(struct tcf_proto *tp,
@@ -220,20 +220,9 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,
 {
        struct net_device *dev = tp->q->dev_queue->dev;
        struct tc_cls_flower_offload cls_flower = {};
+       bool skip_sw = tc_skip_sw(f->flags);
        int err;
 
-       if (!tc_can_offload(dev)) {
-               if (tcf_exts_get_dev(dev, &f->exts, &f->hw_dev) ||
-                   (f->hw_dev && !tc_can_offload(f->hw_dev))) {
-                       f->hw_dev = dev;
-                       return tc_skip_sw(f->flags) ? -EINVAL : 0;
-               }
-               dev = f->hw_dev;
-               cls_flower.egress_dev = true;
-       } else {
-               f->hw_dev = dev;
-       }
-
        tc_cls_common_offload_init(&cls_flower.common, tp);
        cls_flower.command = TC_CLSFLOWER_REPLACE;
        cls_flower.cookie = (unsigned long) f;
@@ -242,31 +231,47 @@ static int fl_hw_replace_filter(struct tcf_proto *tp,
        cls_flower.key = &f->mkey;
        cls_flower.exts = &f->exts;
 
-       err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSFLOWER,
-                                           &cls_flower);
-       if (!err)
-               f->flags |= TCA_CLS_FLAGS_IN_HW;
+       if (tc_can_offload(dev)) {
+               err = dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSFLOWER,
+                                                   &cls_flower);
+               if (err) {
+                       if (skip_sw)
+                               return err;
+               } else {
+                       f->flags |= TCA_CLS_FLAGS_IN_HW;
+               }
+       }
 
-       if (tc_skip_sw(f->flags))
+       err = tc_setup_cb_call(&f->exts, TC_SETUP_CLSFLOWER,
+                              &cls_flower, skip_sw);
+       if (err < 0) {
+               fl_hw_destroy_filter(tp, f);
                return err;
+       } else if (err > 0) {
+               f->flags |= TCA_CLS_FLAGS_IN_HW;
+       }
+
+       if (skip_sw && !(f->flags & TCA_CLS_FLAGS_IN_HW))
+               return -EINVAL;
+
        return 0;
 }
 
 static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f)
 {
        struct tc_cls_flower_offload cls_flower = {};
-       struct net_device *dev = f->hw_dev;
-
-       if (!tc_can_offload(dev))
-               return;
+       struct net_device *dev = tp->q->dev_queue->dev;
 
        tc_cls_common_offload_init(&cls_flower.common, tp);
        cls_flower.command = TC_CLSFLOWER_STATS;
        cls_flower.cookie = (unsigned long) f;
        cls_flower.exts = &f->exts;
 
-       dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSFLOWER,
-                                     &cls_flower);
+       if (tc_can_offload(dev))
+               dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSFLOWER,
+                                             &cls_flower);
+       tc_setup_cb_call(&f->exts, TC_SETUP_CLSFLOWER,
+                        &cls_flower, false);
 }
 
 static void __fl_delete(struct tcf_proto *tp, struct cls_fl_filter *f)