Backport egdev mechanism to redhat kernel 3.10.0-1127

In the latest linux kernel, egdev mechanism is removed.
But in some functions, this egdev mechanism is still used.
So this egdev mechanism is backported into compat directory.

The following patch is to backport the egdev mechanism to

redhat kernel 3.10.0-1127.

diff --git a/compat/compat-3.10.c b/compat/compat-3.10.c
index cc8c4c9f8..5165e64d3 100644
--- a/compat/compat-3.10.c
+++ b/compat/compat-3.10.c
@@ -33,3 +33,219 @@ int pci_vfs_assigned(struct pci_dev *pdev)
 }
 EXPORT_SYMBOL_GPL(pci_vfs_assigned);
 #endif /* HAVE_PCI_VFS_ASSIGNED */
+
+#include <linux/rhashtable.h>
+#include <net/act_api.h>
+
+struct tcf_action_net {
+    struct rhashtable egdev_ht;
+};
+
+static unsigned int tcf_action_net_id;
+
+struct tcf_action_egdev_cb {
+    struct list_head list;
+    tc_setup_cb_t *cb;
+    void *cb_priv;
+};
+
+struct tcf_action_egdev {
+    struct rhash_head ht_node;
+    const struct net_device *dev;
+    unsigned int refcnt;
+    struct list_head cb_list;
+};
+
+static const struct rhashtable_params tcf_action_egdev_ht_params = {
+    .key_offset = offsetof(struct tcf_action_egdev, dev),
+    .head_offset = offsetof(struct tcf_action_egdev, ht_node),
+    .key_len = sizeof(const struct net_device *),
+};
+
+static struct tcf_action_egdev *
+tcf_action_egdev_lookup(const struct net_device *dev)
+{
+    struct net *net = dev_net(dev);
+    struct tcf_action_net *tan = net_generic(net, tcf_action_net_id);
+
+    return rhashtable_lookup_fast(&tan->egdev_ht, &dev,
+                      tcf_action_egdev_ht_params);
+}
+
+static struct tcf_action_egdev *
+tcf_action_egdev_get(const struct net_device *dev)
+{
+    struct tcf_action_egdev *egdev;
+    struct tcf_action_net *tan;
+
+    egdev = tcf_action_egdev_lookup(dev);
+    if (egdev)
+        goto inc_ref;
+
+    egdev = kzalloc(sizeof(*egdev), GFP_KERNEL);
+    if (!egdev)
+        return NULL;
+    INIT_LIST_HEAD(&egdev->cb_list);
+    egdev->dev = dev;
+    tan = net_generic(dev_net(dev), tcf_action_net_id);
+    rhashtable_insert_fast(&tan->egdev_ht, &egdev->ht_node,
+                   tcf_action_egdev_ht_params);
+
+inc_ref:
+    egdev->refcnt++;
+    return egdev;
+}
+
+static void tcf_action_egdev_put(struct tcf_action_egdev *egdev)
+{
+    struct tcf_action_net *tan;
+
+    if (--egdev->refcnt)
+        return;
+    tan = net_generic(dev_net(egdev->dev), tcf_action_net_id);
+    rhashtable_remove_fast(&tan->egdev_ht, &egdev->ht_node,
+                   tcf_action_egdev_ht_params);
+    kfree(egdev);
+}
+
+static struct tcf_action_egdev_cb *
+tcf_action_egdev_cb_lookup(struct tcf_action_egdev *egdev,
+               tc_setup_cb_t *cb, void *cb_priv)
+{
+    struct tcf_action_egdev_cb *egdev_cb;
+
+    list_for_each_entry(egdev_cb, &egdev->cb_list, list)
+        if (egdev_cb->cb == cb && egdev_cb->cb_priv == cb_priv)
+            return egdev_cb;
+    return NULL;
+}
+
+static int tcf_action_egdev_cb_call(struct tcf_action_egdev *egdev,
+                    enum tc_setup_type type,
+                    void *type_data, bool err_stop)
+{
+    struct tcf_action_egdev_cb *egdev_cb;
+    int ok_count = 0;
+    int err;
+
+    list_for_each_entry(egdev_cb, &egdev->cb_list, list) {
+        err = egdev_cb->cb(type, type_data, egdev_cb->cb_priv);
+        if (err) {
+            if (err_stop)
+                return err;
+        } else {
+            ok_count++;
+        }
+    }
+    return ok_count;
+}
+
+static int tcf_action_egdev_cb_add(struct tcf_action_egdev *egdev,
+                   tc_setup_cb_t *cb, void *cb_priv)
+{
+    struct tcf_action_egdev_cb *egdev_cb;
+
+    egdev_cb = tcf_action_egdev_cb_lookup(egdev, cb, cb_priv);
+    if (WARN_ON(egdev_cb))
+        return -EEXIST;
+    egdev_cb = kzalloc(sizeof(*egdev_cb), GFP_KERNEL);
+    if (!egdev_cb)
+        return -ENOMEM;
+    egdev_cb->cb = cb;
+    egdev_cb->cb_priv = cb_priv;
+    list_add(&egdev_cb->list, &egdev->cb_list);
+    return 0;
+}
+
+static void tcf_action_egdev_cb_del(struct tcf_action_egdev *egdev,
+                    tc_setup_cb_t *cb, void *cb_priv)
+{
+    struct tcf_action_egdev_cb *egdev_cb;
+
+    egdev_cb = tcf_action_egdev_cb_lookup(egdev, cb, cb_priv);
+    if (WARN_ON(!egdev_cb))
+        return;
+    list_del(&egdev_cb->list);
+    kfree(egdev_cb);
+}
+
+static int __tc_setup_cb_egdev_register(const struct net_device *dev,
+                    tc_setup_cb_t *cb, void *cb_priv)
+{
+    struct tcf_action_egdev *egdev = tcf_action_egdev_get(dev);
+    int err;
+
+    if (!egdev)
+        return -ENOMEM;
+    err = tcf_action_egdev_cb_add(egdev, cb, cb_priv);
+    if (err)
+        goto err_cb_add;
+    return 0;
+
+err_cb_add:
+    tcf_action_egdev_put(egdev);
+    return err;
+}
+int tc_setup_cb_egdev_register(const struct net_device *dev,
+                   tc_setup_cb_t *cb, void *cb_priv)
+{
+    int err;
+
+    rtnl_lock();
+    err = __tc_setup_cb_egdev_register(dev, cb, cb_priv);
+    rtnl_unlock();
+    return err;
+}
+EXPORT_SYMBOL_GPL(tc_setup_cb_egdev_register);
+
+static void __tc_setup_cb_egdev_unregister(const struct net_device *dev,
+                       tc_setup_cb_t *cb, void *cb_priv)
+{
+    struct tcf_action_egdev *egdev = tcf_action_egdev_lookup(dev);
+
+    if (WARN_ON(!egdev))
+        return;
+    tcf_action_egdev_cb_del(egdev, cb, cb_priv);
+    tcf_action_egdev_put(egdev);
+}
+void tc_setup_cb_egdev_unregister(const struct net_device *dev,
+                  tc_setup_cb_t *cb, void *cb_priv)
+{
+    rtnl_lock();
+    __tc_setup_cb_egdev_unregister(dev, cb, cb_priv);
+    rtnl_unlock();
+}
+EXPORT_SYMBOL_GPL(tc_setup_cb_egdev_unregister);
+
+int tc_setup_cb_egdev_call(const struct net_device *dev,
+               enum tc_setup_type type, void *type_data,
+               bool err_stop)
+{
+    struct tcf_action_egdev *egdev = tcf_action_egdev_lookup(dev);
+
+    if (!egdev)
+        return 0;
+    return tcf_action_egdev_cb_call(egdev, type, type_data, err_stop);
+}
+EXPORT_SYMBOL_GPL(tc_setup_cb_egdev_call);
+
+static __net_init int tcf_action_net_init(struct net *net)
+{
+    struct tcf_action_net *tan = net_generic(net, tcf_action_net_id);
+
+    return rhashtable_init(&tan->egdev_ht, &tcf_action_egdev_ht_params);
+}
+
+static void __net_exit tcf_action_net_exit(struct net *net)
+{
+    struct tcf_action_net *tan = net_generic(net, tcf_action_net_id);
+
+    rhashtable_destroy(&tan->egdev_ht);
+}
+
+static struct pernet_operations tcf_action_net_ops = {
+    .init = tcf_action_net_init,
+    .exit = tcf_action_net_exit,
+    .id = &tcf_action_net_id,
+    .size = sizeof(struct tcf_action_net),
+};
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
index 6a8c71df9..80f58c4d3 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c
@@ -57,6 +57,8 @@
 #include "miniflow.h"
 #endif
 
+#include "linux/compat-3.10.h"
+
 #define MLX5E_REP_PARAMS_DEF_NUM_CHANNELS 1
 
 extern const struct mlx5e_profile mlx5e_nic_profile;
diff --git a/include/linux/compat-3.10.h b/include/linux/compat-3.10.h
index 7e95e1386..b944c41fb 100644
--- a/include/linux/compat-3.10.h
+++ b/include/linux/compat-3.10.h
@@ -51,5 +51,12 @@
 #define random32() prandom_u32()
 
 #endif /* (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)) */
-
+#include <net/act_api.h>
+int tc_setup_cb_egdev_register(const struct net_device *dev,
+                   tc_setup_cb_t *cb, void *cb_priv);
+void tc_setup_cb_egdev_unregister(const struct net_device *dev,
+                  tc_setup_cb_t *cb, void *cb_priv);
+int tc_setup_cb_egdev_call(const struct net_device *dev,
+               enum tc_setup_type type, void *type_data,
+               bool err_stop);
 #endif /* LINUX_3_10_COMPAT_H */
 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mounter625

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值