aboutsummaryrefslogtreecommitdiffstats
path: root/net/sched/cls_flower.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/sched/cls_flower.c')
-rw-r--r--net/sched/cls_flower.c21
1 files changed, 18 insertions, 3 deletions
diff --git a/net/sched/cls_flower.c b/net/sched/cls_flower.c
index d230cb4c8094..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)
@@ -234,6 +247,7 @@ static void fl_hw_destroy_filter(struct tcf_proto *tp, struct cls_fl_filter *f)
234 tc_cls_common_offload_init(&cls_flower.common, tp); 247 tc_cls_common_offload_init(&cls_flower.common, tp);
235 cls_flower.command = TC_CLSFLOWER_DESTROY; 248 cls_flower.command = TC_CLSFLOWER_DESTROY;
236 cls_flower.cookie = (unsigned long) f; 249 cls_flower.cookie = (unsigned long) f;
250 cls_flower.egress_dev = f->hw_dev != tp->q->dev_queue->dev;
237 251
238 dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSFLOWER, &cls_flower); 252 dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSFLOWER, &cls_flower);
239} 253}
@@ -289,6 +303,7 @@ static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f)
289 cls_flower.command = TC_CLSFLOWER_STATS; 303 cls_flower.command = TC_CLSFLOWER_STATS;
290 cls_flower.cookie = (unsigned long) f; 304 cls_flower.cookie = (unsigned long) f;
291 cls_flower.exts = &f->exts; 305 cls_flower.exts = &f->exts;
306 cls_flower.egress_dev = f->hw_dev != tp->q->dev_queue->dev;
292 307
293 dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSFLOWER, 308 dev->netdev_ops->ndo_setup_tc(dev, TC_SETUP_CLSFLOWER,
294 &cls_flower); 309 &cls_flower);