goto out;
 
        orig_node = curr_gateway_tmp->orig_node;
+       if (!orig_node)
+               goto out;
 
-       if (orig_node)
-               kref_get(&orig_node->refcount);
+       if (!atomic_inc_not_zero(&orig_node->refcount))
+               orig_node = NULL;
 
 out:
        rcu_read_unlock();
 
        if (neigh_node)
                neigh_node_free_ref(neigh_node);
        if (orig_node)
-               kref_put(&orig_node->refcount, orig_node_free_ref);
+               orig_node_free_ref(orig_node);
        return len;
 }
 
 
        return neigh_node;
 }
 
-void orig_node_free_ref(struct kref *refcount)
+static void orig_node_free_rcu(struct rcu_head *rcu)
 {
        struct hlist_node *node, *node_tmp;
        struct neigh_node *neigh_node, *tmp_neigh_node;
        struct orig_node *orig_node;
 
-       orig_node = container_of(refcount, struct orig_node, refcount);
+       orig_node = container_of(rcu, struct orig_node, rcu);
 
        spin_lock_bh(&orig_node->neigh_list_lock);
 
        kfree(orig_node);
 }
 
+void orig_node_free_ref(struct orig_node *orig_node)
+{
+       if (atomic_dec_and_test(&orig_node->refcount))
+               call_rcu(&orig_node->rcu, orig_node_free_rcu);
+}
+
 void originator_free(struct bat_priv *bat_priv)
 {
        struct hashtable_t *hash = bat_priv->orig_hash;
                                          head, hash_entry) {
 
                        hlist_del_rcu(node);
-                       kref_put(&orig_node->refcount, orig_node_free_ref);
+                       orig_node_free_ref(orig_node);
                }
                spin_unlock_bh(list_lock);
        }
        spin_lock_init(&orig_node->ogm_cnt_lock);
        spin_lock_init(&orig_node->bcast_seqno_lock);
        spin_lock_init(&orig_node->neigh_list_lock);
-       kref_init(&orig_node->refcount);
+
+       /* extra reference for return */
+       atomic_set(&orig_node->refcount, 2);
 
        orig_node->bat_priv = bat_priv;
        memcpy(orig_node->orig, addr, ETH_ALEN);
        if (hash_added < 0)
                goto free_bcast_own_sum;
 
-       /* extra reference for return */
-       kref_get(&orig_node->refcount);
        return orig_node;
 free_bcast_own_sum:
        kfree(orig_node->bcast_own_sum);
                                if (orig_node->gw_flags)
                                        gw_node_delete(bat_priv, orig_node);
                                hlist_del_rcu(node);
-                               kref_put(&orig_node->refcount,
-                                        orig_node_free_ref);
+                               orig_node_free_ref(orig_node);
                                continue;
                        }
 
 
 int originator_init(struct bat_priv *bat_priv);
 void originator_free(struct bat_priv *bat_priv);
 void purge_orig_ref(struct bat_priv *bat_priv);
-void orig_node_free_ref(struct kref *refcount);
+void orig_node_free_ref(struct orig_node *orig_node);
 struct orig_node *get_orig_node(struct bat_priv *bat_priv, uint8_t *addr);
 struct neigh_node *create_neighbor(struct orig_node *orig_node,
                                   struct orig_node *orig_neigh_node,
                if (!compare_eth(orig_node, data))
                        continue;
 
+               if (!atomic_inc_not_zero(&orig_node->refcount))
+                       continue;
+
                orig_node_tmp = orig_node;
-               kref_get(&orig_node_tmp->refcount);
                break;
        }
        rcu_read_unlock();
 
                neigh_node = create_neighbor(orig_node, orig_tmp,
                                             ethhdr->h_source, if_incoming);
 
-               kref_put(&orig_tmp->refcount, orig_node_free_ref);
+               orig_node_free_ref(orig_tmp);
                if (!neigh_node)
                        goto unlock;
 
 
 out:
        spin_unlock_bh(&orig_node->ogm_cnt_lock);
-       kref_put(&orig_node->refcount, orig_node_free_ref);
+       orig_node_free_ref(orig_node);
        return ret;
 }
 
 
                bat_dbg(DBG_BATMAN, bat_priv, "Drop packet: "
                        "originator packet from myself (via neighbor)\n");
-               kref_put(&orig_neigh_node->refcount, orig_node_free_ref);
+               orig_node_free_ref(orig_neigh_node);
                return;
        }
 
                                0, hna_buff_len, if_incoming);
 
 out_neigh:
-       if (!is_single_hop_neigh)
-               kref_put(&orig_neigh_node->refcount, orig_node_free_ref);
+       if ((orig_neigh_node) && (!is_single_hop_neigh))
+               orig_node_free_ref(orig_neigh_node);
 out:
-       kref_put(&orig_node->refcount, orig_node_free_ref);
+       orig_node_free_ref(orig_node);
 }
 
 int recv_bat_packet(struct sk_buff *skb, struct batman_if *batman_if)
        if (neigh_node)
                neigh_node_free_ref(neigh_node);
        if (orig_node)
-               kref_put(&orig_node->refcount, orig_node_free_ref);
+               orig_node_free_ref(orig_node);
        return ret;
 }
 
        if (neigh_node)
                neigh_node_free_ref(neigh_node);
        if (orig_node)
-               kref_put(&orig_node->refcount, orig_node_free_ref);
+               orig_node_free_ref(orig_node);
        return ret;
 }
 
        if (neigh_node)
                neigh_node_free_ref(neigh_node);
        if (orig_node)
-               kref_put(&orig_node->refcount, orig_node_free_ref);
+               orig_node_free_ref(orig_node);
        return ret;
 }
 
                if (!primary_orig_node)
                        goto return_router;
 
-               kref_put(&primary_orig_node->refcount, orig_node_free_ref);
+               orig_node_free_ref(primary_orig_node);
        }
 
        /* with less than 2 candidates, we can't do any
        if (neigh_node)
                neigh_node_free_ref(neigh_node);
        if (orig_node)
-               kref_put(&orig_node->refcount, orig_node_free_ref);
+               orig_node_free_ref(orig_node);
        return ret;
 }
 
        spin_unlock_bh(&bat_priv->orig_hash_lock);
 out:
        if (orig_node)
-               kref_put(&orig_node->refcount, orig_node_free_ref);
+               orig_node_free_ref(orig_node);
        return ret;
 }
 
 
 struct orig_node *transtable_search(struct bat_priv *bat_priv, uint8_t *addr)
 {
        struct hna_global_entry *hna_global_entry;
+       struct orig_node *orig_node = NULL;
 
        spin_lock_bh(&bat_priv->hna_ghash_lock);
        hna_global_entry = hna_global_hash_find(bat_priv, addr);
 
-       if (hna_global_entry)
-               kref_get(&hna_global_entry->orig_node->refcount);
+       if (!hna_global_entry)
+               goto out;
 
-       spin_unlock_bh(&bat_priv->hna_ghash_lock);
+       if (!atomic_inc_not_zero(&hna_global_entry->orig_node->refcount))
+               goto out;
 
-       if (!hna_global_entry)
-               return NULL;
+       orig_node = hna_global_entry->orig_node;
 
-       return hna_global_entry->orig_node;
+out:
+       spin_unlock_bh(&bat_priv->hna_ghash_lock);
+       return orig_node;
 }
 
        struct hlist_head neigh_list;
        struct list_head frag_list;
        spinlock_t neigh_list_lock; /* protects neighbor list */
-       struct kref refcount;
+       atomic_t refcount;
+       struct rcu_head rcu;
        struct hlist_node hash_entry;
        struct bat_priv *bat_priv;
        unsigned long last_frag_packet;
 
        spin_unlock_bh(&bat_priv->orig_hash_lock);
 out:
        if (orig_node)
-               kref_put(&orig_node->refcount, orig_node_free_ref);
+               orig_node_free_ref(orig_node);
        return ret;
 }
 
 {
        struct ethhdr *ethhdr = (struct ethhdr *)skb->data;
        struct unicast_packet *unicast_packet;
-       struct orig_node *orig_node = NULL;
+       struct orig_node *orig_node;
        struct batman_if *batman_if;
        struct neigh_node *neigh_node;
        int data_len = skb->len;
        if (neigh_node)
                neigh_node_free_ref(neigh_node);
        if (orig_node)
-               kref_put(&orig_node->refcount, orig_node_free_ref);
+               orig_node_free_ref(orig_node);
        if (ret == 1)
                kfree_skb(skb);
        return ret;
 
        if (neigh_node)
                neigh_node_free_ref(neigh_node);
        if (orig_node)
-               kref_put(&orig_node->refcount, orig_node_free_ref);
+               orig_node_free_ref(orig_node);
        return;
 }