aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2018-08-21 15:45:45 -0400
committerDavid S. Miller <davem@davemloft.net>2018-08-21 15:45:45 -0400
commit78c452fe70681c6e6383916a264e0bf010e98058 (patch)
tree445afddd040006b43d6d2ad85118b558ded5ca6c
parentb93c1b5ac8643cc08bb74fa8ae21d6c63dfcb23d (diff)
parent5ffe57da29b3802baeddaa40909682bbb4cb4d48 (diff)
Merge branch 'net_sched-fixes'
Cong Wang says: ==================== net_sched: pending clean up and bug fixes This patchset aims to clean up and fixes some bugs in current merge window, this is why it is targeting -net. Patch 1-5 are clean up Vlad's patches merged in current merge window, patch 6 is just a trivial cleanup. Patch 7 reverts a lockdep warning fix and patch 8 provides a better fix for it. Patch 9 fixes a potential deadlock found by me during code review. Please see each patch for details. ==================== Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
-rw-r--r--drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c6
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c10
-rw-r--r--drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c5
-rw-r--r--drivers/net/ethernet/intel/ixgbe/ixgbe_main.c6
-rw-r--r--drivers/net/ethernet/mellanox/mlx5/core/en_tc.c19
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum.c3
-rw-r--r--drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c6
-rw-r--r--drivers/net/ethernet/netronome/nfp/flower/action.c6
-rw-r--r--drivers/net/ethernet/qlogic/qede/qede_filter.c6
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c5
-rw-r--r--include/net/act_api.h7
-rw-r--r--include/net/pkt_cls.h25
-rw-r--r--net/dsa/slave.c4
-rw-r--r--net/sched/act_api.c70
-rw-r--r--net/sched/act_bpf.c8
-rw-r--r--net/sched/act_connmark.c8
-rw-r--r--net/sched/act_csum.c8
-rw-r--r--net/sched/act_gact.c8
-rw-r--r--net/sched/act_ife.c92
-rw-r--r--net/sched/act_ipt.c16
-rw-r--r--net/sched/act_mirred.c8
-rw-r--r--net/sched/act_nat.c8
-rw-r--r--net/sched/act_pedit.c8
-rw-r--r--net/sched/act_police.c8
-rw-r--r--net/sched/act_sample.c8
-rw-r--r--net/sched/act_simple.c8
-rw-r--r--net/sched/act_skbedit.c8
-rw-r--r--net/sched/act_skbmod.c8
-rw-r--r--net/sched/act_tunnel_key.c8
-rw-r--r--net/sched/act_vlan.c8
30 files changed, 108 insertions, 290 deletions
diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
index 139d96c5a023..092c817f8f11 100644
--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
+++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c
@@ -110,16 +110,14 @@ static int bnxt_tc_parse_actions(struct bnxt *bp,
110 struct tcf_exts *tc_exts) 110 struct tcf_exts *tc_exts)
111{ 111{
112 const struct tc_action *tc_act; 112 const struct tc_action *tc_act;
113 LIST_HEAD(tc_actions); 113 int i, rc;
114 int rc;
115 114
116 if (!tcf_exts_has_actions(tc_exts)) { 115 if (!tcf_exts_has_actions(tc_exts)) {
117 netdev_info(bp->dev, "no actions"); 116 netdev_info(bp->dev, "no actions");
118 return -EINVAL; 117 return -EINVAL;
119 } 118 }
120 119
121 tcf_exts_to_list(tc_exts, &tc_actions); 120 tcf_exts_for_each_action(i, tc_act, tc_exts) {
122 list_for_each_entry(tc_act, &tc_actions, list) {
123 /* Drop action */ 121 /* Drop action */
124 if (is_tcf_gact_shot(tc_act)) { 122 if (is_tcf_gact_shot(tc_act)) {
125 actions->flags |= BNXT_TC_ACTION_FLAG_DROP; 123 actions->flags |= BNXT_TC_ACTION_FLAG_DROP;
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
index 623f73dd7738..c116f96956fe 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_flower.c
@@ -417,10 +417,9 @@ static void cxgb4_process_flow_actions(struct net_device *in,
417 struct ch_filter_specification *fs) 417 struct ch_filter_specification *fs)
418{ 418{
419 const struct tc_action *a; 419 const struct tc_action *a;
420 LIST_HEAD(actions); 420 int i;
421 421
422 tcf_exts_to_list(cls->exts, &actions); 422 tcf_exts_for_each_action(i, a, cls->exts) {
423 list_for_each_entry(a, &actions, list) {
424 if (is_tcf_gact_ok(a)) { 423 if (is_tcf_gact_ok(a)) {
425 fs->action = FILTER_PASS; 424 fs->action = FILTER_PASS;
426 } else if (is_tcf_gact_shot(a)) { 425 } else if (is_tcf_gact_shot(a)) {
@@ -591,10 +590,9 @@ static int cxgb4_validate_flow_actions(struct net_device *dev,
591 bool act_redir = false; 590 bool act_redir = false;
592 bool act_pedit = false; 591 bool act_pedit = false;
593 bool act_vlan = false; 592 bool act_vlan = false;
594 LIST_HEAD(actions); 593 int i;
595 594
596 tcf_exts_to_list(cls->exts, &actions); 595 tcf_exts_for_each_action(i, a, cls->exts) {
597 list_for_each_entry(a, &actions, list) {
598 if (is_tcf_gact_ok(a)) { 596 if (is_tcf_gact_ok(a)) {
599 /* Do nothing */ 597 /* Do nothing */
600 } else if (is_tcf_gact_shot(a)) { 598 } else if (is_tcf_gact_shot(a)) {
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c
index 18eb2aedd4cb..c7d2b4dc7568 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_tc_u32.c
@@ -93,14 +93,13 @@ static int fill_action_fields(struct adapter *adap,
93 unsigned int num_actions = 0; 93 unsigned int num_actions = 0;
94 const struct tc_action *a; 94 const struct tc_action *a;
95 struct tcf_exts *exts; 95 struct tcf_exts *exts;
96 LIST_HEAD(actions); 96 int i;
97 97
98 exts = cls->knode.exts; 98 exts = cls->knode.exts;
99 if (!tcf_exts_has_actions(exts)) 99 if (!tcf_exts_has_actions(exts))
100 return -EINVAL; 100 return -EINVAL;
101 101
102 tcf_exts_to_list(exts, &actions); 102 tcf_exts_for_each_action(i, a, exts) {
103 list_for_each_entry(a, &actions, list) {
104 /* Don't allow more than one action per rule. */ 103 /* Don't allow more than one action per rule. */
105 if (num_actions) 104 if (num_actions)
106 return -EINVAL; 105 return -EINVAL;
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
index 447098005490..af4c9ae7f432 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
@@ -9171,14 +9171,12 @@ static int parse_tc_actions(struct ixgbe_adapter *adapter,
9171 struct tcf_exts *exts, u64 *action, u8 *queue) 9171 struct tcf_exts *exts, u64 *action, u8 *queue)
9172{ 9172{
9173 const struct tc_action *a; 9173 const struct tc_action *a;
9174 LIST_HEAD(actions); 9174 int i;
9175 9175
9176 if (!tcf_exts_has_actions(exts)) 9176 if (!tcf_exts_has_actions(exts))
9177 return -EINVAL; 9177 return -EINVAL;
9178 9178
9179 tcf_exts_to_list(exts, &actions); 9179 tcf_exts_for_each_action(i, a, exts) {
9180 list_for_each_entry(a, &actions, list) {
9181
9182 /* Drop action */ 9180 /* Drop action */
9183 if (is_tcf_gact_shot(a)) { 9181 if (is_tcf_gact_shot(a)) {
9184 *action = IXGBE_FDIR_DROP_QUEUE; 9182 *action = IXGBE_FDIR_DROP_QUEUE;
diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
index 9131a1376e7d..9fed54017659 100644
--- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
+++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
@@ -1982,14 +1982,15 @@ static bool modify_header_match_supported(struct mlx5_flow_spec *spec,
1982 goto out_ok; 1982 goto out_ok;
1983 1983
1984 modify_ip_header = false; 1984 modify_ip_header = false;
1985 tcf_exts_to_list(exts, &actions); 1985 tcf_exts_for_each_action(i, a, exts) {
1986 list_for_each_entry(a, &actions, list) { 1986 int k;
1987
1987 if (!is_tcf_pedit(a)) 1988 if (!is_tcf_pedit(a))
1988 continue; 1989 continue;
1989 1990
1990 nkeys = tcf_pedit_nkeys(a); 1991 nkeys = tcf_pedit_nkeys(a);
1991 for (i = 0; i < nkeys; i++) { 1992 for (k = 0; k < nkeys; k++) {
1992 htype = tcf_pedit_htype(a, i); 1993 htype = tcf_pedit_htype(a, k);
1993 if (htype == TCA_PEDIT_KEY_EX_HDR_TYPE_IP4 || 1994 if (htype == TCA_PEDIT_KEY_EX_HDR_TYPE_IP4 ||
1994 htype == TCA_PEDIT_KEY_EX_HDR_TYPE_IP6) { 1995 htype == TCA_PEDIT_KEY_EX_HDR_TYPE_IP6) {
1995 modify_ip_header = true; 1996 modify_ip_header = true;
@@ -2053,15 +2054,14 @@ static int parse_tc_nic_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
2053 const struct tc_action *a; 2054 const struct tc_action *a;
2054 LIST_HEAD(actions); 2055 LIST_HEAD(actions);
2055 u32 action = 0; 2056 u32 action = 0;
2056 int err; 2057 int err, i;
2057 2058
2058 if (!tcf_exts_has_actions(exts)) 2059 if (!tcf_exts_has_actions(exts))
2059 return -EINVAL; 2060 return -EINVAL;
2060 2061
2061 attr->flow_tag = MLX5_FS_DEFAULT_FLOW_TAG; 2062 attr->flow_tag = MLX5_FS_DEFAULT_FLOW_TAG;
2062 2063
2063 tcf_exts_to_list(exts, &actions); 2064 tcf_exts_for_each_action(i, a, exts) {
2064 list_for_each_entry(a, &actions, list) {
2065 if (is_tcf_gact_shot(a)) { 2065 if (is_tcf_gact_shot(a)) {
2066 action |= MLX5_FLOW_CONTEXT_ACTION_DROP; 2066 action |= MLX5_FLOW_CONTEXT_ACTION_DROP;
2067 if (MLX5_CAP_FLOWTABLE(priv->mdev, 2067 if (MLX5_CAP_FLOWTABLE(priv->mdev,
@@ -2666,7 +2666,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
2666 LIST_HEAD(actions); 2666 LIST_HEAD(actions);
2667 bool encap = false; 2667 bool encap = false;
2668 u32 action = 0; 2668 u32 action = 0;
2669 int err; 2669 int err, i;
2670 2670
2671 if (!tcf_exts_has_actions(exts)) 2671 if (!tcf_exts_has_actions(exts))
2672 return -EINVAL; 2672 return -EINVAL;
@@ -2674,8 +2674,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
2674 attr->in_rep = rpriv->rep; 2674 attr->in_rep = rpriv->rep;
2675 attr->in_mdev = priv->mdev; 2675 attr->in_mdev = priv->mdev;
2676 2676
2677 tcf_exts_to_list(exts, &actions); 2677 tcf_exts_for_each_action(i, a, exts) {
2678 list_for_each_entry(a, &actions, list) {
2679 if (is_tcf_gact_shot(a)) { 2678 if (is_tcf_gact_shot(a)) {
2680 action |= MLX5_FLOW_CONTEXT_ACTION_DROP | 2679 action |= MLX5_FLOW_CONTEXT_ACTION_DROP |
2681 MLX5_FLOW_CONTEXT_ACTION_COUNT; 2680 MLX5_FLOW_CONTEXT_ACTION_COUNT;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
index 6070d1591d1e..930700413b1d 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c
@@ -1346,8 +1346,7 @@ static int mlxsw_sp_port_add_cls_matchall(struct mlxsw_sp_port *mlxsw_sp_port,
1346 return -ENOMEM; 1346 return -ENOMEM;
1347 mall_tc_entry->cookie = f->cookie; 1347 mall_tc_entry->cookie = f->cookie;
1348 1348
1349 tcf_exts_to_list(f->exts, &actions); 1349 a = tcf_exts_first_action(f->exts);
1350 a = list_first_entry(&actions, struct tc_action, list);
1351 1350
1352 if (is_tcf_mirred_egress_mirror(a) && protocol == htons(ETH_P_ALL)) { 1351 if (is_tcf_mirred_egress_mirror(a) && protocol == htons(ETH_P_ALL)) {
1353 struct mlxsw_sp_port_mall_mirror_tc_entry *mirror; 1352 struct mlxsw_sp_port_mall_mirror_tc_entry *mirror;
diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
index ebd1b24ebaa5..8d211972c5e9 100644
--- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
+++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_flower.c
@@ -21,8 +21,7 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
21 struct netlink_ext_ack *extack) 21 struct netlink_ext_ack *extack)
22{ 22{
23 const struct tc_action *a; 23 const struct tc_action *a;
24 LIST_HEAD(actions); 24 int err, i;
25 int err;
26 25
27 if (!tcf_exts_has_actions(exts)) 26 if (!tcf_exts_has_actions(exts))
28 return 0; 27 return 0;
@@ -32,8 +31,7 @@ static int mlxsw_sp_flower_parse_actions(struct mlxsw_sp *mlxsw_sp,
32 if (err) 31 if (err)
33 return err; 32 return err;
34 33
35 tcf_exts_to_list(exts, &actions); 34 tcf_exts_for_each_action(i, a, exts) {
36 list_for_each_entry(a, &actions, list) {
37 if (is_tcf_gact_ok(a)) { 35 if (is_tcf_gact_ok(a)) {
38 err = mlxsw_sp_acl_rulei_act_terminate(rulei); 36 err = mlxsw_sp_acl_rulei_act_terminate(rulei);
39 if (err) { 37 if (err) {
diff --git a/drivers/net/ethernet/netronome/nfp/flower/action.c b/drivers/net/ethernet/netronome/nfp/flower/action.c
index 0ba0356ec4e6..9044496803e6 100644
--- a/drivers/net/ethernet/netronome/nfp/flower/action.c
+++ b/drivers/net/ethernet/netronome/nfp/flower/action.c
@@ -796,11 +796,10 @@ int nfp_flower_compile_action(struct nfp_app *app,
796 struct net_device *netdev, 796 struct net_device *netdev,
797 struct nfp_fl_payload *nfp_flow) 797 struct nfp_fl_payload *nfp_flow)
798{ 798{
799 int act_len, act_cnt, err, tun_out_cnt, out_cnt; 799 int act_len, act_cnt, err, tun_out_cnt, out_cnt, i;
800 enum nfp_flower_tun_type tun_type; 800 enum nfp_flower_tun_type tun_type;
801 const struct tc_action *a; 801 const struct tc_action *a;
802 u32 csum_updated = 0; 802 u32 csum_updated = 0;
803 LIST_HEAD(actions);
804 803
805 memset(nfp_flow->action_data, 0, NFP_FL_MAX_A_SIZ); 804 memset(nfp_flow->action_data, 0, NFP_FL_MAX_A_SIZ);
806 nfp_flow->meta.act_len = 0; 805 nfp_flow->meta.act_len = 0;
@@ -810,8 +809,7 @@ int nfp_flower_compile_action(struct nfp_app *app,
810 tun_out_cnt = 0; 809 tun_out_cnt = 0;
811 out_cnt = 0; 810 out_cnt = 0;
812 811
813 tcf_exts_to_list(flow->exts, &actions); 812 tcf_exts_for_each_action(i, a, flow->exts) {
814 list_for_each_entry(a, &actions, list) {
815 err = nfp_flower_loop_action(app, a, flow, nfp_flow, &act_len, 813 err = nfp_flower_loop_action(app, a, flow, nfp_flow, &act_len,
816 netdev, &tun_type, &tun_out_cnt, 814 netdev, &tun_type, &tun_out_cnt,
817 &out_cnt, &csum_updated); 815 &out_cnt, &csum_updated);
diff --git a/drivers/net/ethernet/qlogic/qede/qede_filter.c b/drivers/net/ethernet/qlogic/qede/qede_filter.c
index 9673d19308e6..b16ce7d93caf 100644
--- a/drivers/net/ethernet/qlogic/qede/qede_filter.c
+++ b/drivers/net/ethernet/qlogic/qede/qede_filter.c
@@ -2006,18 +2006,16 @@ unlock:
2006static int qede_parse_actions(struct qede_dev *edev, 2006static int qede_parse_actions(struct qede_dev *edev,
2007 struct tcf_exts *exts) 2007 struct tcf_exts *exts)
2008{ 2008{
2009 int rc = -EINVAL, num_act = 0; 2009 int rc = -EINVAL, num_act = 0, i;
2010 const struct tc_action *a; 2010 const struct tc_action *a;
2011 bool is_drop = false; 2011 bool is_drop = false;
2012 LIST_HEAD(actions);
2013 2012
2014 if (!tcf_exts_has_actions(exts)) { 2013 if (!tcf_exts_has_actions(exts)) {
2015 DP_NOTICE(edev, "No tc actions received\n"); 2014 DP_NOTICE(edev, "No tc actions received\n");
2016 return rc; 2015 return rc;
2017 } 2016 }
2018 2017
2019 tcf_exts_to_list(exts, &actions); 2018 tcf_exts_for_each_action(i, a, exts) {
2020 list_for_each_entry(a, &actions, list) {
2021 num_act++; 2019 num_act++;
2022 2020
2023 if (is_tcf_gact_shot(a)) 2021 if (is_tcf_gact_shot(a))
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
index 1a96dd9c1091..531294f4978b 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_tc.c
@@ -61,7 +61,7 @@ static int tc_fill_actions(struct stmmac_tc_entry *entry,
61 struct stmmac_tc_entry *action_entry = entry; 61 struct stmmac_tc_entry *action_entry = entry;
62 const struct tc_action *act; 62 const struct tc_action *act;
63 struct tcf_exts *exts; 63 struct tcf_exts *exts;
64 LIST_HEAD(actions); 64 int i;
65 65
66 exts = cls->knode.exts; 66 exts = cls->knode.exts;
67 if (!tcf_exts_has_actions(exts)) 67 if (!tcf_exts_has_actions(exts))
@@ -69,8 +69,7 @@ static int tc_fill_actions(struct stmmac_tc_entry *entry,
69 if (frag) 69 if (frag)
70 action_entry = frag; 70 action_entry = frag;
71 71
72 tcf_exts_to_list(exts, &actions); 72 tcf_exts_for_each_action(i, act, exts) {
73 list_for_each_entry(act, &actions, list) {
74 /* Accept */ 73 /* Accept */
75 if (is_tcf_gact_ok(act)) { 74 if (is_tcf_gact_ok(act)) {
76 action_entry->val.af = 1; 75 action_entry->val.af = 1;
diff --git a/include/net/act_api.h b/include/net/act_api.h
index 1ad5b19e83a9..970303448c90 100644
--- a/include/net/act_api.h
+++ b/include/net/act_api.h
@@ -23,13 +23,11 @@ struct tc_action {
23 const struct tc_action_ops *ops; 23 const struct tc_action_ops *ops;
24 __u32 type; /* for backward compat(TCA_OLD_COMPAT) */ 24 __u32 type; /* for backward compat(TCA_OLD_COMPAT) */
25 __u32 order; 25 __u32 order;
26 struct list_head list;
27 struct tcf_idrinfo *idrinfo; 26 struct tcf_idrinfo *idrinfo;
28 27
29 u32 tcfa_index; 28 u32 tcfa_index;
30 refcount_t tcfa_refcnt; 29 refcount_t tcfa_refcnt;
31 atomic_t tcfa_bindcnt; 30 atomic_t tcfa_bindcnt;
32 u32 tcfa_capab;
33 int tcfa_action; 31 int tcfa_action;
34 struct tcf_t tcfa_tm; 32 struct tcf_t tcfa_tm;
35 struct gnet_stats_basic_packed tcfa_bstats; 33 struct gnet_stats_basic_packed tcfa_bstats;
@@ -44,7 +42,6 @@ struct tc_action {
44#define tcf_index common.tcfa_index 42#define tcf_index common.tcfa_index
45#define tcf_refcnt common.tcfa_refcnt 43#define tcf_refcnt common.tcfa_refcnt
46#define tcf_bindcnt common.tcfa_bindcnt 44#define tcf_bindcnt common.tcfa_bindcnt
47#define tcf_capab common.tcfa_capab
48#define tcf_action common.tcfa_action 45#define tcf_action common.tcfa_action
49#define tcf_tm common.tcfa_tm 46#define tcf_tm common.tcfa_tm
50#define tcf_bstats common.tcfa_bstats 47#define tcf_bstats common.tcfa_bstats
@@ -102,7 +99,6 @@ struct tc_action_ops {
102 size_t (*get_fill_size)(const struct tc_action *act); 99 size_t (*get_fill_size)(const struct tc_action *act);
103 struct net_device *(*get_dev)(const struct tc_action *a); 100 struct net_device *(*get_dev)(const struct tc_action *a);
104 void (*put_dev)(struct net_device *dev); 101 void (*put_dev)(struct net_device *dev);
105 int (*delete)(struct net *net, u32 index);
106}; 102};
107 103
108struct tc_action_net { 104struct tc_action_net {
@@ -148,8 +144,6 @@ int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
148 const struct tc_action_ops *ops, 144 const struct tc_action_ops *ops,
149 struct netlink_ext_ack *extack); 145 struct netlink_ext_ack *extack);
150int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index); 146int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index);
151bool tcf_idr_check(struct tc_action_net *tn, u32 index, struct tc_action **a,
152 int bind);
153int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est, 147int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
154 struct tc_action **a, const struct tc_action_ops *ops, 148 struct tc_action **a, const struct tc_action_ops *ops,
155 int bind, bool cpustats); 149 int bind, bool cpustats);
@@ -158,7 +152,6 @@ void tcf_idr_insert(struct tc_action_net *tn, struct tc_action *a);
158void tcf_idr_cleanup(struct tc_action_net *tn, u32 index); 152void tcf_idr_cleanup(struct tc_action_net *tn, u32 index);
159int tcf_idr_check_alloc(struct tc_action_net *tn, u32 *index, 153int tcf_idr_check_alloc(struct tc_action_net *tn, u32 *index,
160 struct tc_action **a, int bind); 154 struct tc_action **a, int bind);
161int tcf_idr_delete_index(struct tc_action_net *tn, u32 index);
162int __tcf_idr_release(struct tc_action *a, bool bind, bool strict); 155int __tcf_idr_release(struct tc_action *a, bool bind, bool strict);
163 156
164static inline int tcf_idr_release(struct tc_action *a, bool bind) 157static inline int tcf_idr_release(struct tc_action *a, bool bind)
diff --git a/include/net/pkt_cls.h b/include/net/pkt_cls.h
index ef727f71336e..c17d51865469 100644
--- a/include/net/pkt_cls.h
+++ b/include/net/pkt_cls.h
@@ -298,19 +298,13 @@ static inline void tcf_exts_put_net(struct tcf_exts *exts)
298#endif 298#endif
299} 299}
300 300
301static inline void tcf_exts_to_list(const struct tcf_exts *exts,
302 struct list_head *actions)
303{
304#ifdef CONFIG_NET_CLS_ACT 301#ifdef CONFIG_NET_CLS_ACT
305 int i; 302#define tcf_exts_for_each_action(i, a, exts) \
306 303 for (i = 0; i < TCA_ACT_MAX_PRIO && ((a) = (exts)->actions[i]); i++)
307 for (i = 0; i < exts->nr_actions; i++) { 304#else
308 struct tc_action *a = exts->actions[i]; 305#define tcf_exts_for_each_action(i, a, exts) \
309 306 for (; 0; )
310 list_add_tail(&a->list, actions);
311 }
312#endif 307#endif
313}
314 308
315static inline void 309static inline void
316tcf_exts_stats_update(const struct tcf_exts *exts, 310tcf_exts_stats_update(const struct tcf_exts *exts,
@@ -361,6 +355,15 @@ static inline bool tcf_exts_has_one_action(struct tcf_exts *exts)
361#endif 355#endif
362} 356}
363 357
358static inline struct tc_action *tcf_exts_first_action(struct tcf_exts *exts)
359{
360#ifdef CONFIG_NET_CLS_ACT
361 return exts->actions[0];
362#else
363 return NULL;
364#endif
365}
366
364/** 367/**
365 * tcf_exts_exec - execute tc filter extensions 368 * tcf_exts_exec - execute tc filter extensions
366 * @skb: socket buffer 369 * @skb: socket buffer
diff --git a/net/dsa/slave.c b/net/dsa/slave.c
index 962c4fd338ba..1c45c1d6d241 100644
--- a/net/dsa/slave.c
+++ b/net/dsa/slave.c
@@ -767,7 +767,6 @@ static int dsa_slave_add_cls_matchall(struct net_device *dev,
767 const struct tc_action *a; 767 const struct tc_action *a;
768 struct dsa_port *to_dp; 768 struct dsa_port *to_dp;
769 int err = -EOPNOTSUPP; 769 int err = -EOPNOTSUPP;
770 LIST_HEAD(actions);
771 770
772 if (!ds->ops->port_mirror_add) 771 if (!ds->ops->port_mirror_add)
773 return err; 772 return err;
@@ -775,8 +774,7 @@ static int dsa_slave_add_cls_matchall(struct net_device *dev,
775 if (!tcf_exts_has_one_action(cls->exts)) 774 if (!tcf_exts_has_one_action(cls->exts))
776 return err; 775 return err;
777 776
778 tcf_exts_to_list(cls->exts, &actions); 777 a = tcf_exts_first_action(cls->exts);
779 a = list_first_entry(&actions, struct tc_action, list);
780 778
781 if (is_tcf_mirred_egress_mirror(a) && protocol == htons(ETH_P_ALL)) { 779 if (is_tcf_mirred_egress_mirror(a) && protocol == htons(ETH_P_ALL)) {
782 struct dsa_mall_mirror_tc_entry *mirror; 780 struct dsa_mall_mirror_tc_entry *mirror;
diff --git a/net/sched/act_api.c b/net/sched/act_api.c
index 229d63c99be2..db83dac1e7f4 100644
--- a/net/sched/act_api.c
+++ b/net/sched/act_api.c
@@ -300,21 +300,17 @@ int tcf_generic_walker(struct tc_action_net *tn, struct sk_buff *skb,
300} 300}
301EXPORT_SYMBOL(tcf_generic_walker); 301EXPORT_SYMBOL(tcf_generic_walker);
302 302
303static bool __tcf_idr_check(struct tc_action_net *tn, u32 index, 303int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index)
304 struct tc_action **a, int bind)
305{ 304{
306 struct tcf_idrinfo *idrinfo = tn->idrinfo; 305 struct tcf_idrinfo *idrinfo = tn->idrinfo;
307 struct tc_action *p; 306 struct tc_action *p;
308 307
309 spin_lock(&idrinfo->lock); 308 spin_lock(&idrinfo->lock);
310 p = idr_find(&idrinfo->action_idr, index); 309 p = idr_find(&idrinfo->action_idr, index);
311 if (IS_ERR(p)) { 310 if (IS_ERR(p))
312 p = NULL; 311 p = NULL;
313 } else if (p) { 312 else if (p)
314 refcount_inc(&p->tcfa_refcnt); 313 refcount_inc(&p->tcfa_refcnt);
315 if (bind)
316 atomic_inc(&p->tcfa_bindcnt);
317 }
318 spin_unlock(&idrinfo->lock); 314 spin_unlock(&idrinfo->lock);
319 315
320 if (p) { 316 if (p) {
@@ -323,23 +319,10 @@ static bool __tcf_idr_check(struct tc_action_net *tn, u32 index,
323 } 319 }
324 return false; 320 return false;
325} 321}
326
327int tcf_idr_search(struct tc_action_net *tn, struct tc_action **a, u32 index)
328{
329 return __tcf_idr_check(tn, index, a, 0);
330}
331EXPORT_SYMBOL(tcf_idr_search); 322EXPORT_SYMBOL(tcf_idr_search);
332 323
333bool tcf_idr_check(struct tc_action_net *tn, u32 index, struct tc_action **a, 324static int tcf_idr_delete_index(struct tcf_idrinfo *idrinfo, u32 index)
334 int bind)
335{ 325{
336 return __tcf_idr_check(tn, index, a, bind);
337}
338EXPORT_SYMBOL(tcf_idr_check);
339
340int tcf_idr_delete_index(struct tc_action_net *tn, u32 index)
341{
342 struct tcf_idrinfo *idrinfo = tn->idrinfo;
343 struct tc_action *p; 326 struct tc_action *p;
344 int ret = 0; 327 int ret = 0;
345 328
@@ -370,7 +353,6 @@ int tcf_idr_delete_index(struct tc_action_net *tn, u32 index)
370 spin_unlock(&idrinfo->lock); 353 spin_unlock(&idrinfo->lock);
371 return ret; 354 return ret;
372} 355}
373EXPORT_SYMBOL(tcf_idr_delete_index);
374 356
375int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est, 357int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
376 struct tc_action **a, const struct tc_action_ops *ops, 358 struct tc_action **a, const struct tc_action_ops *ops,
@@ -409,7 +391,6 @@ int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est,
409 391
410 p->idrinfo = idrinfo; 392 p->idrinfo = idrinfo;
411 p->ops = ops; 393 p->ops = ops;
412 INIT_LIST_HEAD(&p->list);
413 *a = p; 394 *a = p;
414 return 0; 395 return 0;
415err3: 396err3:
@@ -686,14 +667,18 @@ static int tcf_action_put(struct tc_action *p)
686 return __tcf_action_put(p, false); 667 return __tcf_action_put(p, false);
687} 668}
688 669
670/* Put all actions in this array, skip those NULL's. */
689static void tcf_action_put_many(struct tc_action *actions[]) 671static void tcf_action_put_many(struct tc_action *actions[])
690{ 672{
691 int i; 673 int i;
692 674
693 for (i = 0; i < TCA_ACT_MAX_PRIO && actions[i]; i++) { 675 for (i = 0; i < TCA_ACT_MAX_PRIO; i++) {
694 struct tc_action *a = actions[i]; 676 struct tc_action *a = actions[i];
695 const struct tc_action_ops *ops = a->ops; 677 const struct tc_action_ops *ops;
696 678
679 if (!a)
680 continue;
681 ops = a->ops;
697 if (tcf_action_put(a)) 682 if (tcf_action_put(a))
698 module_put(ops->owner); 683 module_put(ops->owner);
699 } 684 }
@@ -1175,41 +1160,38 @@ err_out:
1175 return err; 1160 return err;
1176} 1161}
1177 1162
1178static int tcf_action_delete(struct net *net, struct tc_action *actions[], 1163static int tcf_action_delete(struct net *net, struct tc_action *actions[])
1179 int *acts_deleted, struct netlink_ext_ack *extack)
1180{ 1164{
1181 u32 act_index; 1165 int i;
1182 int ret, i;
1183 1166
1184 for (i = 0; i < TCA_ACT_MAX_PRIO && actions[i]; i++) { 1167 for (i = 0; i < TCA_ACT_MAX_PRIO && actions[i]; i++) {
1185 struct tc_action *a = actions[i]; 1168 struct tc_action *a = actions[i];
1186 const struct tc_action_ops *ops = a->ops; 1169 const struct tc_action_ops *ops = a->ops;
1187
1188 /* Actions can be deleted concurrently so we must save their 1170 /* Actions can be deleted concurrently so we must save their
1189 * type and id to search again after reference is released. 1171 * type and id to search again after reference is released.
1190 */ 1172 */
1191 act_index = a->tcfa_index; 1173 struct tcf_idrinfo *idrinfo = a->idrinfo;
1174 u32 act_index = a->tcfa_index;
1192 1175
1193 if (tcf_action_put(a)) { 1176 if (tcf_action_put(a)) {
1194 /* last reference, action was deleted concurrently */ 1177 /* last reference, action was deleted concurrently */
1195 module_put(ops->owner); 1178 module_put(ops->owner);
1196 } else { 1179 } else {
1180 int ret;
1181
1197 /* now do the delete */ 1182 /* now do the delete */
1198 ret = ops->delete(net, act_index); 1183 ret = tcf_idr_delete_index(idrinfo, act_index);
1199 if (ret < 0) { 1184 if (ret < 0)
1200 *acts_deleted = i + 1;
1201 return ret; 1185 return ret;
1202 }
1203 } 1186 }
1187 actions[i] = NULL;
1204 } 1188 }
1205 *acts_deleted = i;
1206 return 0; 1189 return 0;
1207} 1190}
1208 1191
1209static int 1192static int
1210tcf_del_notify(struct net *net, struct nlmsghdr *n, struct tc_action *actions[], 1193tcf_del_notify(struct net *net, struct nlmsghdr *n, struct tc_action *actions[],
1211 int *acts_deleted, u32 portid, size_t attr_size, 1194 u32 portid, size_t attr_size, struct netlink_ext_ack *extack)
1212 struct netlink_ext_ack *extack)
1213{ 1195{
1214 int ret; 1196 int ret;
1215 struct sk_buff *skb; 1197 struct sk_buff *skb;
@@ -1227,7 +1209,7 @@ tcf_del_notify(struct net *net, struct nlmsghdr *n, struct tc_action *actions[],
1227 } 1209 }
1228 1210
1229 /* now do the delete */ 1211 /* now do the delete */
1230 ret = tcf_action_delete(net, actions, acts_deleted, extack); 1212 ret = tcf_action_delete(net, actions);
1231 if (ret < 0) { 1213 if (ret < 0) {
1232 NL_SET_ERR_MSG(extack, "Failed to delete TC action"); 1214 NL_SET_ERR_MSG(extack, "Failed to delete TC action");
1233 kfree_skb(skb); 1215 kfree_skb(skb);
@@ -1249,8 +1231,7 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
1249 struct nlattr *tb[TCA_ACT_MAX_PRIO + 1]; 1231 struct nlattr *tb[TCA_ACT_MAX_PRIO + 1];
1250 struct tc_action *act; 1232 struct tc_action *act;
1251 size_t attr_size = 0; 1233 size_t attr_size = 0;
1252 struct tc_action *actions[TCA_ACT_MAX_PRIO + 1] = {}; 1234 struct tc_action *actions[TCA_ACT_MAX_PRIO] = {};
1253 int acts_deleted = 0;
1254 1235
1255 ret = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, extack); 1236 ret = nla_parse_nested(tb, TCA_ACT_MAX_PRIO, nla, NULL, extack);
1256 if (ret < 0) 1237 if (ret < 0)
@@ -1280,14 +1261,13 @@ tca_action_gd(struct net *net, struct nlattr *nla, struct nlmsghdr *n,
1280 if (event == RTM_GETACTION) 1261 if (event == RTM_GETACTION)
1281 ret = tcf_get_notify(net, portid, n, actions, event, extack); 1262 ret = tcf_get_notify(net, portid, n, actions, event, extack);
1282 else { /* delete */ 1263 else { /* delete */
1283 ret = tcf_del_notify(net, n, actions, &acts_deleted, portid, 1264 ret = tcf_del_notify(net, n, actions, portid, attr_size, extack);
1284 attr_size, extack);
1285 if (ret) 1265 if (ret)
1286 goto err; 1266 goto err;
1287 return ret; 1267 return 0;
1288 } 1268 }
1289err: 1269err:
1290 tcf_action_put_many(&actions[acts_deleted]); 1270 tcf_action_put_many(actions);
1291 return ret; 1271 return ret;
1292} 1272}
1293 1273
diff --git a/net/sched/act_bpf.c b/net/sched/act_bpf.c
index d30b23e42436..0c68bc9cf0b4 100644
--- a/net/sched/act_bpf.c
+++ b/net/sched/act_bpf.c
@@ -395,13 +395,6 @@ static int tcf_bpf_search(struct net *net, struct tc_action **a, u32 index,
395 return tcf_idr_search(tn, a, index); 395 return tcf_idr_search(tn, a, index);
396} 396}
397 397
398static int tcf_bpf_delete(struct net *net, u32 index)
399{
400 struct tc_action_net *tn = net_generic(net, bpf_net_id);
401
402 return tcf_idr_delete_index(tn, index);
403}
404
405static struct tc_action_ops act_bpf_ops __read_mostly = { 398static struct tc_action_ops act_bpf_ops __read_mostly = {
406 .kind = "bpf", 399 .kind = "bpf",
407 .type = TCA_ACT_BPF, 400 .type = TCA_ACT_BPF,
@@ -412,7 +405,6 @@ static struct tc_action_ops act_bpf_ops __read_mostly = {
412 .init = tcf_bpf_init, 405 .init = tcf_bpf_init,
413 .walk = tcf_bpf_walker, 406 .walk = tcf_bpf_walker,
414 .lookup = tcf_bpf_search, 407 .lookup = tcf_bpf_search,
415 .delete = tcf_bpf_delete,
416 .size = sizeof(struct tcf_bpf), 408 .size = sizeof(struct tcf_bpf),
417}; 409};
418 410
diff --git a/net/sched/act_connmark.c b/net/sched/act_connmark.c
index 54c0bf54f2ac..6f0f273f1139 100644
--- a/net/sched/act_connmark.c
+++ b/net/sched/act_connmark.c
@@ -198,13 +198,6 @@ static int tcf_connmark_search(struct net *net, struct tc_action **a, u32 index,
198 return tcf_idr_search(tn, a, index); 198 return tcf_idr_search(tn, a, index);
199} 199}
200 200
201static int tcf_connmark_delete(struct net *net, u32 index)
202{
203 struct tc_action_net *tn = net_generic(net, connmark_net_id);
204
205 return tcf_idr_delete_index(tn, index);
206}
207
208static struct tc_action_ops act_connmark_ops = { 201static struct tc_action_ops act_connmark_ops = {
209 .kind = "connmark", 202 .kind = "connmark",
210 .type = TCA_ACT_CONNMARK, 203 .type = TCA_ACT_CONNMARK,
@@ -214,7 +207,6 @@ static struct tc_action_ops act_connmark_ops = {
214 .init = tcf_connmark_init, 207 .init = tcf_connmark_init,
215 .walk = tcf_connmark_walker, 208 .walk = tcf_connmark_walker,
216 .lookup = tcf_connmark_search, 209 .lookup = tcf_connmark_search,
217 .delete = tcf_connmark_delete,
218 .size = sizeof(struct tcf_connmark_info), 210 .size = sizeof(struct tcf_connmark_info),
219}; 211};
220 212
diff --git a/net/sched/act_csum.c b/net/sched/act_csum.c
index e698d3fe2080..b8a67ae3105a 100644
--- a/net/sched/act_csum.c
+++ b/net/sched/act_csum.c
@@ -659,13 +659,6 @@ static size_t tcf_csum_get_fill_size(const struct tc_action *act)
659 return nla_total_size(sizeof(struct tc_csum)); 659 return nla_total_size(sizeof(struct tc_csum));
660} 660}
661 661
662static int tcf_csum_delete(struct net *net, u32 index)
663{
664 struct tc_action_net *tn = net_generic(net, csum_net_id);
665
666 return tcf_idr_delete_index(tn, index);
667}
668
669static struct tc_action_ops act_csum_ops = { 662static struct tc_action_ops act_csum_ops = {
670 .kind = "csum", 663 .kind = "csum",
671 .type = TCA_ACT_CSUM, 664 .type = TCA_ACT_CSUM,
@@ -677,7 +670,6 @@ static struct tc_action_ops act_csum_ops = {
677 .walk = tcf_csum_walker, 670 .walk = tcf_csum_walker,
678 .lookup = tcf_csum_search, 671 .lookup = tcf_csum_search,
679 .get_fill_size = tcf_csum_get_fill_size, 672 .get_fill_size = tcf_csum_get_fill_size,
680 .delete = tcf_csum_delete,
681 .size = sizeof(struct tcf_csum), 673 .size = sizeof(struct tcf_csum),
682}; 674};
683 675
diff --git a/net/sched/act_gact.c b/net/sched/act_gact.c
index 6a3f25a8ffb3..cd1d9bd32ef9 100644
--- a/net/sched/act_gact.c
+++ b/net/sched/act_gact.c
@@ -243,13 +243,6 @@ static size_t tcf_gact_get_fill_size(const struct tc_action *act)
243 return sz; 243 return sz;
244} 244}
245 245
246static int tcf_gact_delete(struct net *net, u32 index)
247{
248 struct tc_action_net *tn = net_generic(net, gact_net_id);
249
250 return tcf_idr_delete_index(tn, index);
251}
252
253static struct tc_action_ops act_gact_ops = { 246static struct tc_action_ops act_gact_ops = {
254 .kind = "gact", 247 .kind = "gact",
255 .type = TCA_ACT_GACT, 248 .type = TCA_ACT_GACT,
@@ -261,7 +254,6 @@ static struct tc_action_ops act_gact_ops = {
261 .walk = tcf_gact_walker, 254 .walk = tcf_gact_walker,
262 .lookup = tcf_gact_search, 255 .lookup = tcf_gact_search,
263 .get_fill_size = tcf_gact_get_fill_size, 256 .get_fill_size = tcf_gact_get_fill_size,
264 .delete = tcf_gact_delete,
265 .size = sizeof(struct tcf_gact), 257 .size = sizeof(struct tcf_gact),
266}; 258};
267 259
diff --git a/net/sched/act_ife.c b/net/sched/act_ife.c
index d1081bdf1bdb..196430aefe87 100644
--- a/net/sched/act_ife.c
+++ b/net/sched/act_ife.c
@@ -167,16 +167,16 @@ static struct tcf_meta_ops *find_ife_oplist(u16 metaid)
167{ 167{
168 struct tcf_meta_ops *o; 168 struct tcf_meta_ops *o;
169 169
170 read_lock_bh(&ife_mod_lock); 170 read_lock(&ife_mod_lock);
171 list_for_each_entry(o, &ifeoplist, list) { 171 list_for_each_entry(o, &ifeoplist, list) {
172 if (o->metaid == metaid) { 172 if (o->metaid == metaid) {
173 if (!try_module_get(o->owner)) 173 if (!try_module_get(o->owner))
174 o = NULL; 174 o = NULL;
175 read_unlock_bh(&ife_mod_lock); 175 read_unlock(&ife_mod_lock);
176 return o; 176 return o;
177 } 177 }
178 } 178 }
179 read_unlock_bh(&ife_mod_lock); 179 read_unlock(&ife_mod_lock);
180 180
181 return NULL; 181 return NULL;
182} 182}
@@ -190,12 +190,12 @@ int register_ife_op(struct tcf_meta_ops *mops)
190 !mops->get || !mops->alloc) 190 !mops->get || !mops->alloc)
191 return -EINVAL; 191 return -EINVAL;
192 192
193 write_lock_bh(&ife_mod_lock); 193 write_lock(&ife_mod_lock);
194 194
195 list_for_each_entry(m, &ifeoplist, list) { 195 list_for_each_entry(m, &ifeoplist, list) {
196 if (m->metaid == mops->metaid || 196 if (m->metaid == mops->metaid ||
197 (strcmp(mops->name, m->name) == 0)) { 197 (strcmp(mops->name, m->name) == 0)) {
198 write_unlock_bh(&ife_mod_lock); 198 write_unlock(&ife_mod_lock);
199 return -EEXIST; 199 return -EEXIST;
200 } 200 }
201 } 201 }
@@ -204,7 +204,7 @@ int register_ife_op(struct tcf_meta_ops *mops)
204 mops->release = ife_release_meta_gen; 204 mops->release = ife_release_meta_gen;
205 205
206 list_add_tail(&mops->list, &ifeoplist); 206 list_add_tail(&mops->list, &ifeoplist);
207 write_unlock_bh(&ife_mod_lock); 207 write_unlock(&ife_mod_lock);
208 return 0; 208 return 0;
209} 209}
210EXPORT_SYMBOL_GPL(unregister_ife_op); 210EXPORT_SYMBOL_GPL(unregister_ife_op);
@@ -214,7 +214,7 @@ int unregister_ife_op(struct tcf_meta_ops *mops)
214 struct tcf_meta_ops *m; 214 struct tcf_meta_ops *m;
215 int err = -ENOENT; 215 int err = -ENOENT;
216 216
217 write_lock_bh(&ife_mod_lock); 217 write_lock(&ife_mod_lock);
218 list_for_each_entry(m, &ifeoplist, list) { 218 list_for_each_entry(m, &ifeoplist, list) {
219 if (m->metaid == mops->metaid) { 219 if (m->metaid == mops->metaid) {
220 list_del(&mops->list); 220 list_del(&mops->list);
@@ -222,7 +222,7 @@ int unregister_ife_op(struct tcf_meta_ops *mops)
222 break; 222 break;
223 } 223 }
224 } 224 }
225 write_unlock_bh(&ife_mod_lock); 225 write_unlock(&ife_mod_lock);
226 226
227 return err; 227 return err;
228} 228}
@@ -265,11 +265,8 @@ static const char *ife_meta_id2name(u32 metaid)
265#endif 265#endif
266 266
267/* called when adding new meta information 267/* called when adding new meta information
268 * under ife->tcf_lock for existing action
269*/ 268*/
270static int load_metaops_and_vet(struct tcf_ife_info *ife, u32 metaid, 269static int load_metaops_and_vet(u32 metaid, void *val, int len, bool rtnl_held)
271 void *val, int len, bool exists,
272 bool rtnl_held)
273{ 270{
274 struct tcf_meta_ops *ops = find_ife_oplist(metaid); 271 struct tcf_meta_ops *ops = find_ife_oplist(metaid);
275 int ret = 0; 272 int ret = 0;
@@ -277,15 +274,11 @@ static int load_metaops_and_vet(struct tcf_ife_info *ife, u32 metaid,
277 if (!ops) { 274 if (!ops) {
278 ret = -ENOENT; 275 ret = -ENOENT;
279#ifdef CONFIG_MODULES 276#ifdef CONFIG_MODULES
280 if (exists)
281 spin_unlock_bh(&ife->tcf_lock);
282 if (rtnl_held) 277 if (rtnl_held)
283 rtnl_unlock(); 278 rtnl_unlock();
284 request_module("ife-meta-%s", ife_meta_id2name(metaid)); 279 request_module("ife-meta-%s", ife_meta_id2name(metaid));
285 if (rtnl_held) 280 if (rtnl_held)
286 rtnl_lock(); 281 rtnl_lock();
287 if (exists)
288 spin_lock_bh(&ife->tcf_lock);
289 ops = find_ife_oplist(metaid); 282 ops = find_ife_oplist(metaid);
290#endif 283#endif
291 } 284 }
@@ -302,24 +295,17 @@ static int load_metaops_and_vet(struct tcf_ife_info *ife, u32 metaid,
302} 295}
303 296
304/* called when adding new meta information 297/* called when adding new meta information
305 * under ife->tcf_lock for existing action
306*/ 298*/
307static int add_metainfo(struct tcf_ife_info *ife, u32 metaid, void *metaval, 299static int __add_metainfo(const struct tcf_meta_ops *ops,
308 int len, bool atomic) 300 struct tcf_ife_info *ife, u32 metaid, void *metaval,
301 int len, bool atomic, bool exists)
309{ 302{
310 struct tcf_meta_info *mi = NULL; 303 struct tcf_meta_info *mi = NULL;
311 struct tcf_meta_ops *ops = find_ife_oplist(metaid);
312 int ret = 0; 304 int ret = 0;
313 305
314 if (!ops)
315 return -ENOENT;
316
317 mi = kzalloc(sizeof(*mi), atomic ? GFP_ATOMIC : GFP_KERNEL); 306 mi = kzalloc(sizeof(*mi), atomic ? GFP_ATOMIC : GFP_KERNEL);
318 if (!mi) { 307 if (!mi)
319 /*put back what find_ife_oplist took */
320 module_put(ops->owner);
321 return -ENOMEM; 308 return -ENOMEM;
322 }
323 309
324 mi->metaid = metaid; 310 mi->metaid = metaid;
325 mi->ops = ops; 311 mi->ops = ops;
@@ -327,29 +313,47 @@ static int add_metainfo(struct tcf_ife_info *ife, u32 metaid, void *metaval,
327 ret = ops->alloc(mi, metaval, atomic ? GFP_ATOMIC : GFP_KERNEL); 313 ret = ops->alloc(mi, metaval, atomic ? GFP_ATOMIC : GFP_KERNEL);
328 if (ret != 0) { 314 if (ret != 0) {
329 kfree(mi); 315 kfree(mi);
330 module_put(ops->owner);
331 return ret; 316 return ret;
332 } 317 }
333 } 318 }
334 319
320 if (exists)
321 spin_lock_bh(&ife->tcf_lock);
335 list_add_tail(&mi->metalist, &ife->metalist); 322 list_add_tail(&mi->metalist, &ife->metalist);
323 if (exists)
324 spin_unlock_bh(&ife->tcf_lock);
325
326 return ret;
327}
328
329static int add_metainfo(struct tcf_ife_info *ife, u32 metaid, void *metaval,
330 int len, bool exists)
331{
332 const struct tcf_meta_ops *ops = find_ife_oplist(metaid);
333 int ret;
336 334
335 if (!ops)
336 return -ENOENT;
337 ret = __add_metainfo(ops, ife, metaid, metaval, len, false, exists);
338 if (ret)
339 /*put back what find_ife_oplist took */
340 module_put(ops->owner);
337 return ret; 341 return ret;
338} 342}
339 343
340static int use_all_metadata(struct tcf_ife_info *ife) 344static int use_all_metadata(struct tcf_ife_info *ife, bool exists)
341{ 345{
342 struct tcf_meta_ops *o; 346 struct tcf_meta_ops *o;
343 int rc = 0; 347 int rc = 0;
344 int installed = 0; 348 int installed = 0;
345 349
346 read_lock_bh(&ife_mod_lock); 350 read_lock(&ife_mod_lock);
347 list_for_each_entry(o, &ifeoplist, list) { 351 list_for_each_entry(o, &ifeoplist, list) {
348 rc = add_metainfo(ife, o->metaid, NULL, 0, true); 352 rc = __add_metainfo(o, ife, o->metaid, NULL, 0, true, exists);
349 if (rc == 0) 353 if (rc == 0)
350 installed += 1; 354 installed += 1;
351 } 355 }
352 read_unlock_bh(&ife_mod_lock); 356 read_unlock(&ife_mod_lock);
353 357
354 if (installed) 358 if (installed)
355 return 0; 359 return 0;
@@ -422,7 +426,6 @@ static void tcf_ife_cleanup(struct tc_action *a)
422 kfree_rcu(p, rcu); 426 kfree_rcu(p, rcu);
423} 427}
424 428
425/* under ife->tcf_lock for existing action */
426static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb, 429static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb,
427 bool exists, bool rtnl_held) 430 bool exists, bool rtnl_held)
428{ 431{
@@ -436,8 +439,7 @@ static int populate_metalist(struct tcf_ife_info *ife, struct nlattr **tb,
436 val = nla_data(tb[i]); 439 val = nla_data(tb[i]);
437 len = nla_len(tb[i]); 440 len = nla_len(tb[i]);
438 441
439 rc = load_metaops_and_vet(ife, i, val, len, exists, 442 rc = load_metaops_and_vet(i, val, len, rtnl_held);
440 rtnl_held);
441 if (rc != 0) 443 if (rc != 0)
442 return rc; 444 return rc;
443 445
@@ -540,8 +542,6 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
540 p->eth_type = ife_type; 542 p->eth_type = ife_type;
541 } 543 }
542 544
543 if (exists)
544 spin_lock_bh(&ife->tcf_lock);
545 545
546 if (ret == ACT_P_CREATED) 546 if (ret == ACT_P_CREATED)
547 INIT_LIST_HEAD(&ife->metalist); 547 INIT_LIST_HEAD(&ife->metalist);
@@ -551,10 +551,7 @@ static int tcf_ife_init(struct net *net, struct nlattr *nla,
551 NULL, NULL); 551 NULL, NULL);
552 if (err) { 552 if (err) {
553metadata_parse_err: 553metadata_parse_err:
554 if (exists)
555 spin_unlock_bh(&ife->tcf_lock);
556 tcf_idr_release(*a, bind); 554 tcf_idr_release(*a, bind);
557
558 kfree(p); 555 kfree(p);
559 return err; 556 return err;
560 } 557 }
@@ -569,17 +566,16 @@ metadata_parse_err:
569 * as we can. You better have at least one else we are 566 * as we can. You better have at least one else we are
570 * going to bail out 567 * going to bail out
571 */ 568 */
572 err = use_all_metadata(ife); 569 err = use_all_metadata(ife, exists);
573 if (err) { 570 if (err) {
574 if (exists)
575 spin_unlock_bh(&ife->tcf_lock);
576 tcf_idr_release(*a, bind); 571 tcf_idr_release(*a, bind);
577
578 kfree(p); 572 kfree(p);
579 return err; 573 return err;
580 } 574 }
581 } 575 }
582 576
577 if (exists)
578 spin_lock_bh(&ife->tcf_lock);
583 ife->tcf_action = parm->action; 579 ife->tcf_action = parm->action;
584 /* protected by tcf_lock when modifying existing action */ 580 /* protected by tcf_lock when modifying existing action */
585 rcu_swap_protected(ife->params, p, 1); 581 rcu_swap_protected(ife->params, p, 1);
@@ -853,13 +849,6 @@ static int tcf_ife_search(struct net *net, struct tc_action **a, u32 index,
853 return tcf_idr_search(tn, a, index); 849 return tcf_idr_search(tn, a, index);
854} 850}
855 851
856static int tcf_ife_delete(struct net *net, u32 index)
857{
858 struct tc_action_net *tn = net_generic(net, ife_net_id);
859
860 return tcf_idr_delete_index(tn, index);
861}
862
863static struct tc_action_ops act_ife_ops = { 852static struct tc_action_ops act_ife_ops = {
864 .kind = "ife", 853 .kind = "ife",
865 .type = TCA_ACT_IFE, 854 .type = TCA_ACT_IFE,
@@ -870,7 +859,6 @@ static struct tc_action_ops act_ife_ops = {
870 .init = tcf_ife_init, 859 .init = tcf_ife_init,
871 .walk = tcf_ife_walker, 860 .walk = tcf_ife_walker,
872 .lookup = tcf_ife_search, 861 .lookup = tcf_ife_search,
873 .delete = tcf_ife_delete,
874 .size = sizeof(struct tcf_ife_info), 862 .size = sizeof(struct tcf_ife_info),
875}; 863};
876 864
diff --git a/net/sched/act_ipt.c b/net/sched/act_ipt.c
index 51f235bbeb5b..23273b5303fd 100644
--- a/net/sched/act_ipt.c
+++ b/net/sched/act_ipt.c
@@ -337,13 +337,6 @@ static int tcf_ipt_search(struct net *net, struct tc_action **a, u32 index,
337 return tcf_idr_search(tn, a, index); 337 return tcf_idr_search(tn, a, index);
338} 338}
339 339
340static int tcf_ipt_delete(struct net *net, u32 index)
341{
342 struct tc_action_net *tn = net_generic(net, ipt_net_id);
343
344 return tcf_idr_delete_index(tn, index);
345}
346
347static struct tc_action_ops act_ipt_ops = { 340static struct tc_action_ops act_ipt_ops = {
348 .kind = "ipt", 341 .kind = "ipt",
349 .type = TCA_ACT_IPT, 342 .type = TCA_ACT_IPT,
@@ -354,7 +347,6 @@ static struct tc_action_ops act_ipt_ops = {
354 .init = tcf_ipt_init, 347 .init = tcf_ipt_init,
355 .walk = tcf_ipt_walker, 348 .walk = tcf_ipt_walker,
356 .lookup = tcf_ipt_search, 349 .lookup = tcf_ipt_search,
357 .delete = tcf_ipt_delete,
358 .size = sizeof(struct tcf_ipt), 350 .size = sizeof(struct tcf_ipt),
359}; 351};
360 352
@@ -395,13 +387,6 @@ static int tcf_xt_search(struct net *net, struct tc_action **a, u32 index,
395 return tcf_idr_search(tn, a, index); 387 return tcf_idr_search(tn, a, index);
396} 388}
397 389
398static int tcf_xt_delete(struct net *net, u32 index)
399{
400 struct tc_action_net *tn = net_generic(net, xt_net_id);
401
402 return tcf_idr_delete_index(tn, index);
403}
404
405static struct tc_action_ops act_xt_ops = { 390static struct tc_action_ops act_xt_ops = {
406 .kind = "xt", 391 .kind = "xt",
407 .type = TCA_ACT_XT, 392 .type = TCA_ACT_XT,
@@ -412,7 +397,6 @@ static struct tc_action_ops act_xt_ops = {
412 .init = tcf_xt_init, 397 .init = tcf_xt_init,
413 .walk = tcf_xt_walker, 398 .walk = tcf_xt_walker,
414 .lookup = tcf_xt_search, 399 .lookup = tcf_xt_search,
415 .delete = tcf_xt_delete,
416 .size = sizeof(struct tcf_ipt), 400 .size = sizeof(struct tcf_ipt),
417}; 401};
418 402
diff --git a/net/sched/act_mirred.c b/net/sched/act_mirred.c
index 38fd20f10f67..8bf66d0a6800 100644
--- a/net/sched/act_mirred.c
+++ b/net/sched/act_mirred.c
@@ -395,13 +395,6 @@ static void tcf_mirred_put_dev(struct net_device *dev)
395 dev_put(dev); 395 dev_put(dev);
396} 396}
397 397
398static int tcf_mirred_delete(struct net *net, u32 index)
399{
400 struct tc_action_net *tn = net_generic(net, mirred_net_id);
401
402 return tcf_idr_delete_index(tn, index);
403}
404
405static struct tc_action_ops act_mirred_ops = { 398static struct tc_action_ops act_mirred_ops = {
406 .kind = "mirred", 399 .kind = "mirred",
407 .type = TCA_ACT_MIRRED, 400 .type = TCA_ACT_MIRRED,
@@ -416,7 +409,6 @@ static struct tc_action_ops act_mirred_ops = {
416 .size = sizeof(struct tcf_mirred), 409 .size = sizeof(struct tcf_mirred),
417 .get_dev = tcf_mirred_get_dev, 410 .get_dev = tcf_mirred_get_dev,
418 .put_dev = tcf_mirred_put_dev, 411 .put_dev = tcf_mirred_put_dev,
419 .delete = tcf_mirred_delete,
420}; 412};
421 413
422static __net_init int mirred_init_net(struct net *net) 414static __net_init int mirred_init_net(struct net *net)
diff --git a/net/sched/act_nat.c b/net/sched/act_nat.c
index 822e903bfc25..4313aa102440 100644
--- a/net/sched/act_nat.c
+++ b/net/sched/act_nat.c
@@ -300,13 +300,6 @@ static int tcf_nat_search(struct net *net, struct tc_action **a, u32 index,
300 return tcf_idr_search(tn, a, index); 300 return tcf_idr_search(tn, a, index);
301} 301}
302 302
303static int tcf_nat_delete(struct net *net, u32 index)
304{
305 struct tc_action_net *tn = net_generic(net, nat_net_id);
306
307 return tcf_idr_delete_index(tn, index);
308}
309
310static struct tc_action_ops act_nat_ops = { 303static struct tc_action_ops act_nat_ops = {
311 .kind = "nat", 304 .kind = "nat",
312 .type = TCA_ACT_NAT, 305 .type = TCA_ACT_NAT,
@@ -316,7 +309,6 @@ static struct tc_action_ops act_nat_ops = {
316 .init = tcf_nat_init, 309 .init = tcf_nat_init,
317 .walk = tcf_nat_walker, 310 .walk = tcf_nat_walker,
318 .lookup = tcf_nat_search, 311 .lookup = tcf_nat_search,
319 .delete = tcf_nat_delete,
320 .size = sizeof(struct tcf_nat), 312 .size = sizeof(struct tcf_nat),
321}; 313};
322 314
diff --git a/net/sched/act_pedit.c b/net/sched/act_pedit.c
index 8a7a7cb94e83..107034070019 100644
--- a/net/sched/act_pedit.c
+++ b/net/sched/act_pedit.c
@@ -460,13 +460,6 @@ static int tcf_pedit_search(struct net *net, struct tc_action **a, u32 index,
460 return tcf_idr_search(tn, a, index); 460 return tcf_idr_search(tn, a, index);
461} 461}
462 462
463static int tcf_pedit_delete(struct net *net, u32 index)
464{
465 struct tc_action_net *tn = net_generic(net, pedit_net_id);
466
467 return tcf_idr_delete_index(tn, index);
468}
469
470static struct tc_action_ops act_pedit_ops = { 463static struct tc_action_ops act_pedit_ops = {
471 .kind = "pedit", 464 .kind = "pedit",
472 .type = TCA_ACT_PEDIT, 465 .type = TCA_ACT_PEDIT,
@@ -477,7 +470,6 @@ static struct tc_action_ops act_pedit_ops = {
477 .init = tcf_pedit_init, 470 .init = tcf_pedit_init,
478 .walk = tcf_pedit_walker, 471 .walk = tcf_pedit_walker,
479 .lookup = tcf_pedit_search, 472 .lookup = tcf_pedit_search,
480 .delete = tcf_pedit_delete,
481 .size = sizeof(struct tcf_pedit), 473 .size = sizeof(struct tcf_pedit),
482}; 474};
483 475
diff --git a/net/sched/act_police.c b/net/sched/act_police.c
index 06f0742db593..5d8bfa878477 100644
--- a/net/sched/act_police.c
+++ b/net/sched/act_police.c
@@ -320,13 +320,6 @@ static int tcf_police_search(struct net *net, struct tc_action **a, u32 index,
320 return tcf_idr_search(tn, a, index); 320 return tcf_idr_search(tn, a, index);
321} 321}
322 322
323static int tcf_police_delete(struct net *net, u32 index)
324{
325 struct tc_action_net *tn = net_generic(net, police_net_id);
326
327 return tcf_idr_delete_index(tn, index);
328}
329
330MODULE_AUTHOR("Alexey Kuznetsov"); 323MODULE_AUTHOR("Alexey Kuznetsov");
331MODULE_DESCRIPTION("Policing actions"); 324MODULE_DESCRIPTION("Policing actions");
332MODULE_LICENSE("GPL"); 325MODULE_LICENSE("GPL");
@@ -340,7 +333,6 @@ static struct tc_action_ops act_police_ops = {
340 .init = tcf_police_init, 333 .init = tcf_police_init,
341 .walk = tcf_police_walker, 334 .walk = tcf_police_walker,
342 .lookup = tcf_police_search, 335 .lookup = tcf_police_search,
343 .delete = tcf_police_delete,
344 .size = sizeof(struct tcf_police), 336 .size = sizeof(struct tcf_police),
345}; 337};
346 338
diff --git a/net/sched/act_sample.c b/net/sched/act_sample.c
index 207b4132d1b0..44e9c00657bc 100644
--- a/net/sched/act_sample.c
+++ b/net/sched/act_sample.c
@@ -232,13 +232,6 @@ static int tcf_sample_search(struct net *net, struct tc_action **a, u32 index,
232 return tcf_idr_search(tn, a, index); 232 return tcf_idr_search(tn, a, index);
233} 233}
234 234
235static int tcf_sample_delete(struct net *net, u32 index)
236{
237 struct tc_action_net *tn = net_generic(net, sample_net_id);
238
239 return tcf_idr_delete_index(tn, index);
240}
241
242static struct tc_action_ops act_sample_ops = { 235static struct tc_action_ops act_sample_ops = {
243 .kind = "sample", 236 .kind = "sample",
244 .type = TCA_ACT_SAMPLE, 237 .type = TCA_ACT_SAMPLE,
@@ -249,7 +242,6 @@ static struct tc_action_ops act_sample_ops = {
249 .cleanup = tcf_sample_cleanup, 242 .cleanup = tcf_sample_cleanup,
250 .walk = tcf_sample_walker, 243 .walk = tcf_sample_walker,
251 .lookup = tcf_sample_search, 244 .lookup = tcf_sample_search,
252 .delete = tcf_sample_delete,
253 .size = sizeof(struct tcf_sample), 245 .size = sizeof(struct tcf_sample),
254}; 246};
255 247
diff --git a/net/sched/act_simple.c b/net/sched/act_simple.c
index e616523ba3c1..52400d49f81f 100644
--- a/net/sched/act_simple.c
+++ b/net/sched/act_simple.c
@@ -196,13 +196,6 @@ static int tcf_simp_search(struct net *net, struct tc_action **a, u32 index,
196 return tcf_idr_search(tn, a, index); 196 return tcf_idr_search(tn, a, index);
197} 197}
198 198
199static int tcf_simp_delete(struct net *net, u32 index)
200{
201 struct tc_action_net *tn = net_generic(net, simp_net_id);
202
203 return tcf_idr_delete_index(tn, index);
204}
205
206static struct tc_action_ops act_simp_ops = { 199static struct tc_action_ops act_simp_ops = {
207 .kind = "simple", 200 .kind = "simple",
208 .type = TCA_ACT_SIMP, 201 .type = TCA_ACT_SIMP,
@@ -213,7 +206,6 @@ static struct tc_action_ops act_simp_ops = {
213 .init = tcf_simp_init, 206 .init = tcf_simp_init,
214 .walk = tcf_simp_walker, 207 .walk = tcf_simp_walker,
215 .lookup = tcf_simp_search, 208 .lookup = tcf_simp_search,
216 .delete = tcf_simp_delete,
217 .size = sizeof(struct tcf_defact), 209 .size = sizeof(struct tcf_defact),
218}; 210};
219 211
diff --git a/net/sched/act_skbedit.c b/net/sched/act_skbedit.c
index 926d7bc4a89d..73e44ce2a883 100644
--- a/net/sched/act_skbedit.c
+++ b/net/sched/act_skbedit.c
@@ -299,13 +299,6 @@ static int tcf_skbedit_search(struct net *net, struct tc_action **a, u32 index,
299 return tcf_idr_search(tn, a, index); 299 return tcf_idr_search(tn, a, index);
300} 300}
301 301
302static int tcf_skbedit_delete(struct net *net, u32 index)
303{
304 struct tc_action_net *tn = net_generic(net, skbedit_net_id);
305
306 return tcf_idr_delete_index(tn, index);
307}
308
309static struct tc_action_ops act_skbedit_ops = { 302static struct tc_action_ops act_skbedit_ops = {
310 .kind = "skbedit", 303 .kind = "skbedit",
311 .type = TCA_ACT_SKBEDIT, 304 .type = TCA_ACT_SKBEDIT,
@@ -316,7 +309,6 @@ static struct tc_action_ops act_skbedit_ops = {
316 .cleanup = tcf_skbedit_cleanup, 309 .cleanup = tcf_skbedit_cleanup,
317 .walk = tcf_skbedit_walker, 310 .walk = tcf_skbedit_walker,
318 .lookup = tcf_skbedit_search, 311 .lookup = tcf_skbedit_search,
319 .delete = tcf_skbedit_delete,
320 .size = sizeof(struct tcf_skbedit), 312 .size = sizeof(struct tcf_skbedit),
321}; 313};
322 314
diff --git a/net/sched/act_skbmod.c b/net/sched/act_skbmod.c
index d6a1af0c4171..588077fafd6c 100644
--- a/net/sched/act_skbmod.c
+++ b/net/sched/act_skbmod.c
@@ -259,13 +259,6 @@ static int tcf_skbmod_search(struct net *net, struct tc_action **a, u32 index,
259 return tcf_idr_search(tn, a, index); 259 return tcf_idr_search(tn, a, index);
260} 260}
261 261
262static int tcf_skbmod_delete(struct net *net, u32 index)
263{
264 struct tc_action_net *tn = net_generic(net, skbmod_net_id);
265
266 return tcf_idr_delete_index(tn, index);
267}
268
269static struct tc_action_ops act_skbmod_ops = { 262static struct tc_action_ops act_skbmod_ops = {
270 .kind = "skbmod", 263 .kind = "skbmod",
271 .type = TCA_ACT_SKBMOD, 264 .type = TCA_ACT_SKBMOD,
@@ -276,7 +269,6 @@ static struct tc_action_ops act_skbmod_ops = {
276 .cleanup = tcf_skbmod_cleanup, 269 .cleanup = tcf_skbmod_cleanup,
277 .walk = tcf_skbmod_walker, 270 .walk = tcf_skbmod_walker,
278 .lookup = tcf_skbmod_search, 271 .lookup = tcf_skbmod_search,
279 .delete = tcf_skbmod_delete,
280 .size = sizeof(struct tcf_skbmod), 272 .size = sizeof(struct tcf_skbmod),
281}; 273};
282 274
diff --git a/net/sched/act_tunnel_key.c b/net/sched/act_tunnel_key.c
index 8f09cf08d8fe..420759153d5f 100644
--- a/net/sched/act_tunnel_key.c
+++ b/net/sched/act_tunnel_key.c
@@ -548,13 +548,6 @@ static int tunnel_key_search(struct net *net, struct tc_action **a, u32 index,
548 return tcf_idr_search(tn, a, index); 548 return tcf_idr_search(tn, a, index);
549} 549}
550 550
551static int tunnel_key_delete(struct net *net, u32 index)
552{
553 struct tc_action_net *tn = net_generic(net, tunnel_key_net_id);
554
555 return tcf_idr_delete_index(tn, index);
556}
557
558static struct tc_action_ops act_tunnel_key_ops = { 551static struct tc_action_ops act_tunnel_key_ops = {
559 .kind = "tunnel_key", 552 .kind = "tunnel_key",
560 .type = TCA_ACT_TUNNEL_KEY, 553 .type = TCA_ACT_TUNNEL_KEY,
@@ -565,7 +558,6 @@ static struct tc_action_ops act_tunnel_key_ops = {
565 .cleanup = tunnel_key_release, 558 .cleanup = tunnel_key_release,
566 .walk = tunnel_key_walker, 559 .walk = tunnel_key_walker,
567 .lookup = tunnel_key_search, 560 .lookup = tunnel_key_search,
568 .delete = tunnel_key_delete,
569 .size = sizeof(struct tcf_tunnel_key), 561 .size = sizeof(struct tcf_tunnel_key),
570}; 562};
571 563
diff --git a/net/sched/act_vlan.c b/net/sched/act_vlan.c
index 209e70ad2c09..033d273afe50 100644
--- a/net/sched/act_vlan.c
+++ b/net/sched/act_vlan.c
@@ -296,13 +296,6 @@ static int tcf_vlan_search(struct net *net, struct tc_action **a, u32 index,
296 return tcf_idr_search(tn, a, index); 296 return tcf_idr_search(tn, a, index);
297} 297}
298 298
299static int tcf_vlan_delete(struct net *net, u32 index)
300{
301 struct tc_action_net *tn = net_generic(net, vlan_net_id);
302
303 return tcf_idr_delete_index(tn, index);
304}
305
306static struct tc_action_ops act_vlan_ops = { 299static struct tc_action_ops act_vlan_ops = {
307 .kind = "vlan", 300 .kind = "vlan",
308 .type = TCA_ACT_VLAN, 301 .type = TCA_ACT_VLAN,
@@ -313,7 +306,6 @@ static struct tc_action_ops act_vlan_ops = {
313 .cleanup = tcf_vlan_cleanup, 306 .cleanup = tcf_vlan_cleanup,
314 .walk = tcf_vlan_walker, 307 .walk = tcf_vlan_walker,
315 .lookup = tcf_vlan_search, 308 .lookup = tcf_vlan_search,
316 .delete = tcf_vlan_delete,
317 .size = sizeof(struct tcf_vlan), 309 .size = sizeof(struct tcf_vlan),
318}; 310};
319 311