struct tc_u_hnode __rcu *next;
        u32                     handle;
        u32                     prio;
-       int                     refcnt;
+       refcount_t              refcnt;
        unsigned int            divisor;
        struct idr              handle_idr;
        bool                    is_root;
 struct tc_u_common {
        struct tc_u_hnode __rcu *hlist;
        void                    *ptr;
-       int                     refcnt;
+       refcount_t              refcnt;
        struct idr              handle_idr;
        struct hlist_node       hnode;
        long                    knodes;
        if (root_ht == NULL)
                return -ENOBUFS;
 
-       root_ht->refcnt++;
+       refcount_set(&root_ht->refcnt, 1);
        root_ht->handle = tp_c ? gen_new_htid(tp_c, root_ht) : 0x80000000;
        root_ht->prio = tp->prio;
        root_ht->is_root = true;
                        kfree(root_ht);
                        return -ENOBUFS;
                }
+               refcount_set(&tp_c->refcnt, 1);
                tp_c->ptr = key;
                INIT_HLIST_NODE(&tp_c->hnode);
                idr_init(&tp_c->handle_idr);
 
                hlist_add_head(&tp_c->hnode, tc_u_hash(key));
+       } else {
+               refcount_inc(&tp_c->refcnt);
        }
 
-       tp_c->refcnt++;
        RCU_INIT_POINTER(root_ht->next, tp_c->hlist);
        rcu_assign_pointer(tp_c->hlist, root_ht);
 
-       root_ht->refcnt++;
+       /* root_ht must be destroyed when tcf_proto is destroyed */
        rcu_assign_pointer(tp->root, root_ht);
        tp->data = tp_c;
        return 0;
        struct tc_u_hnode *ht = rtnl_dereference(n->ht_down);
 
        tcf_exts_destroy(&n->exts);
-       if (ht && --ht->refcnt == 0)
+       if (ht && refcount_dec_and_test(&ht->refcnt))
                kfree(ht);
        kfree(n);
 }
        struct tc_u_hnode __rcu **hn;
        struct tc_u_hnode *phn;
 
-       WARN_ON(--ht->refcnt);
-
        u32_clear_hnode(tp, ht, extack);
 
        hn = &tp_c->hlist;
 
        WARN_ON(root_ht == NULL);
 
-       if (root_ht && --root_ht->refcnt == 1)
+       if (root_ht && refcount_dec_and_test(&root_ht->refcnt))
                u32_destroy_hnode(tp, root_ht, extack);
 
-       if (--tp_c->refcnt == 0) {
+       if (refcount_dec_and_test(&tp_c->refcnt)) {
                struct tc_u_hnode *ht;
 
                hlist_del(&tp_c->hnode);
                        /* u32_destroy_key() will later free ht for us, if it's
                         * still referenced by some knode
                         */
-                       if (--ht->refcnt == 0)
+                       if (refcount_dec_and_test(&ht->refcnt))
                                kfree_rcu(ht, rcu);
                }
 
                return -EINVAL;
        }
 
-       if (ht->refcnt == 1) {
+       if (refcount_dec_if_one(&ht->refcnt)) {
                u32_destroy_hnode(tp, ht, extack);
        } else {
                NL_SET_ERR_MSG_MOD(extack, "Can not delete in-use filter");
        }
 
 out:
-       *last = tp_c->refcnt == 1 && tp_c->knodes == 0;
+       *last = refcount_read(&tp_c->refcnt) == 1 && tp_c->knodes == 0;
        return ret;
 }
 
                                NL_SET_ERR_MSG_MOD(extack, "Not linking to root node");
                                return -EINVAL;
                        }
-                       ht_down->refcnt++;
+                       refcount_inc(&ht_down->refcnt);
                }
 
                ht_old = rtnl_dereference(n->ht_down);
                rcu_assign_pointer(n->ht_down, ht_down);
 
                if (ht_old)
-                       ht_old->refcnt--;
+                       refcount_dec(&ht_old->refcnt);
        }
 
        if (ifindex >= 0)
 
        /* bump reference count as long as we hold pointer to structure */
        if (ht)
-               ht->refcnt++;
+               refcount_inc(&ht->refcnt);
 
        return new;
 }
 
                                ht_old = rtnl_dereference(n->ht_down);
                                if (ht_old)
-                                       ht_old->refcnt++;
+                                       refcount_inc(&ht_old->refcnt);
                        }
                        __u32_destroy_key(new);
                        return err;
                                return err;
                        }
                }
-               ht->refcnt = 1;
+               refcount_set(&ht->refcnt, 1);
                ht->divisor = divisor;
                ht->handle = handle;
                ht->prio = tp->prio;