aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/sched/cls_flower.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index b480d7c792ba..5b5722c8b32c 100644
--- a/net/sched/cls_flower.c
+++ b/net/sched/cls_flower.c
@@ -87,7 +87,10 @@ struct cls_fl_filter {
87 struct list_head list; 87 struct list_head list;
88 u32 handle; 88 u32 handle;
89 u32 flags; 89 u32 flags;
90 struct rcu_head rcu; 90 union {
91 struct work_struct work;
92 struct rcu_head rcu;
93 };
91 struct net_device *hw_dev; 94 struct net_device *hw_dev;
92}; 95};
93 96
@@ -215,12 +218,22 @@ static int fl_init(struct tcf_proto *tp)
215 return 0; 218 return 0;
216} 219}
217 220
218static void fl_destroy_filter(struct rcu_head *head) 221static void fl_destroy_filter_work(struct work_struct *work)
219{ 222{
220 struct cls_fl_filter *f = container_of(head, struct cls_fl_filter, rcu); 223 struct cls_fl_filter *f = container_of(work, struct cls_fl_filter, work);
221 224
225 rtnl_lock();
222 tcf_exts_destroy(&f->exts); 226 tcf_exts_destroy(&f->exts);
223 kfree(f); 227 kfree(f);
228 rtnl_unlock();
229}
230
231static void fl_destroy_filter(struct rcu_head *head)
232{
233 struct cls_fl_filter *f = container_of(head, struct cls_fl_filter, rcu);
234
235 INIT_WORK(&f->work, fl_destroy_filter_work);
236 tcf_queue_work(&f->work);
224} 237}
225 238
226static void fl_hw_destroy_filter(struct tcf_proto *tp, struct cls_fl_filter *f) 239static void fl_hw_destroy_filter(struct tcf_proto *tp, struct cls_fl_filter *f)