net_sch: cbs: Change TC_SETUP_CBS to TC_SETUP_QDISC_CBS
[linux-2.6-microblaze.git] / net / sched / cls_flow.c
index f3be666..9c08fcd 100644 (file)
@@ -57,7 +57,10 @@ struct flow_filter {
        u32                     divisor;
        u32                     baseclass;
        u32                     hashrnd;
-       struct rcu_head         rcu;
+       union {
+               struct work_struct      work;
+               struct rcu_head         rcu;
+       };
 };
 
 static inline u32 addr_fold(void *addr)
@@ -345,9 +348,9 @@ static int flow_classify(struct sk_buff *skb, const struct tcf_proto *tp,
        return -1;
 }
 
-static void flow_perturbation(unsigned long arg)
+static void flow_perturbation(struct timer_list *t)
 {
-       struct flow_filter *f = (struct flow_filter *)arg;
+       struct flow_filter *f = from_timer(f, t, perturb_timer);
 
        get_random_bytes(&f->hashrnd, 4);
        if (f->perturb_period)
@@ -369,14 +372,24 @@ static const struct nla_policy flow_policy[TCA_FLOW_MAX + 1] = {
        [TCA_FLOW_PERTURB]      = { .type = NLA_U32 },
 };
 
-static void flow_destroy_filter(struct rcu_head *head)
+static void flow_destroy_filter_work(struct work_struct *work)
 {
-       struct flow_filter *f = container_of(head, struct flow_filter, rcu);
+       struct flow_filter *f = container_of(work, struct flow_filter, work);
 
+       rtnl_lock();
        del_timer_sync(&f->perturb_timer);
        tcf_exts_destroy(&f->exts);
        tcf_em_tree_destroy(&f->ematches);
        kfree(f);
+       rtnl_unlock();
+}
+
+static void flow_destroy_filter(struct rcu_head *head)
+{
+       struct flow_filter *f = container_of(head, struct flow_filter, rcu);
+
+       INIT_WORK(&f->work, flow_destroy_filter_work);
+       tcf_queue_work(&f->work);
 }
 
 static int flow_change(struct net *net, struct sk_buff *in_skb,
@@ -505,8 +518,7 @@ static int flow_change(struct net *net, struct sk_buff *in_skb,
                get_random_bytes(&fnew->hashrnd, 4);
        }
 
-       setup_deferrable_timer(&fnew->perturb_timer, flow_perturbation,
-                              (unsigned long)fnew);
+       timer_setup(&fnew->perturb_timer, flow_perturbation, TIMER_DEFERRABLE);
 
        netif_keep_dst(qdisc_dev(tp->q));