Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
[firefly-linux-kernel-4.4.55.git] / net / sched / cls_u32.c
index ef97a646ee9411a13ad48ed849cc47ecb4b8a4cd..0472909bb014c258e92f796736be7a527af843d1 100644 (file)
@@ -358,8 +358,7 @@ static int u32_destroy_key(struct tcf_proto *tp,
                           struct tc_u_knode *n,
                           bool free_pf)
 {
-       tcf_unbind_filter(tp, &n->res);
-       tcf_exts_destroy(tp, &n->exts);
+       tcf_exts_destroy(&n->exts);
        if (n->ht_down)
                n->ht_down->refcnt--;
 #ifdef CONFIG_CLS_U32_PERF
@@ -416,6 +415,7 @@ static int u32_delete_key(struct tcf_proto *tp, struct tc_u_knode *key)
                        if (pkp == key) {
                                RCU_INIT_POINTER(*kp, key->next);
 
+                               tcf_unbind_filter(tp, &key->res);
                                call_rcu(&key->rcu, u32_delete_key_freepf_rcu);
                                return 0;
                        }
@@ -425,7 +425,7 @@ static int u32_delete_key(struct tcf_proto *tp, struct tc_u_knode *key)
        return 0;
 }
 
-static void u32_clear_hnode(struct tc_u_hnode *ht)
+static void u32_clear_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht)
 {
        struct tc_u_knode *n;
        unsigned int h;
@@ -434,6 +434,7 @@ static void u32_clear_hnode(struct tc_u_hnode *ht)
                while ((n = rtnl_dereference(ht->ht[h])) != NULL) {
                        RCU_INIT_POINTER(ht->ht[h],
                                         rtnl_dereference(n->next));
+                       tcf_unbind_filter(tp, &n->res);
                        call_rcu(&n->rcu, u32_delete_key_freepf_rcu);
                }
        }
@@ -447,7 +448,7 @@ static int u32_destroy_hnode(struct tcf_proto *tp, struct tc_u_hnode *ht)
 
        WARN_ON(ht->refcnt);
 
-       u32_clear_hnode(ht);
+       u32_clear_hnode(tp, ht);
 
        hn = &tp_c->hlist;
        for (phn = rtnl_dereference(*hn);
@@ -482,7 +483,7 @@ static void u32_destroy(struct tcf_proto *tp)
                     ht;
                     ht = rtnl_dereference(ht->next)) {
                        ht->refcnt--;
-                       u32_clear_hnode(ht);
+                       u32_clear_hnode(tp, ht);
                }
 
                while ((ht = rtnl_dereference(tp_c->hlist)) != NULL) {
@@ -606,7 +607,7 @@ static int u32_set_parms(struct net *net, struct tcf_proto *tp,
 
        return 0;
 errout:
-       tcf_exts_destroy(tp, &e);
+       tcf_exts_destroy(&e);
        return err;
 }
 
@@ -731,6 +732,7 @@ static int u32_change(struct net *net, struct sk_buff *in_skb,
                }
 
                u32_replace_knode(tp, tp_c, new);
+               tcf_unbind_filter(tp, &n->res);
                call_rcu(&n->rcu, u32_delete_key_rcu);
                return 0;
        }