aboutsummaryrefslogtreecommitdiffstats
path: root/net/core
diff options
context:
space:
mode:
authorEliezer Tamir <eliezer.tamir@linux.intel.com>2013-06-10 04:39:41 -0400
committerDavid S. Miller <davem@davemloft.net>2013-06-11 00:22:35 -0400
commitaf12fa6e46aa651e7b86a4c4117b562518fef184 (patch)
tree1425ef11083e66af192c33abb3b1fa3b04b26f4b /net/core
parent6f00a0229627ca189529cad3f9154ac2f9e5c7db (diff)
net: add napi_id and hash
Adds a napi_id and a hashing mechanism to lookup a napi by id. This will be used by subsequent patches to implement low latency Ethernet device polling. Based on a code sample by Eric Dumazet. Signed-off-by: Eliezer Tamir <eliezer.tamir@linux.intel.com> Signed-off-by: Eric Dumazet <edumazet@google.com> Tested-by: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'net/core')
-rw-r--r--net/core/dev.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/net/core/dev.c b/net/core/dev.c
index 9c18557f93c6..fa007dba6beb 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -129,6 +129,7 @@
129#include <linux/inetdevice.h> 129#include <linux/inetdevice.h>
130#include <linux/cpu_rmap.h> 130#include <linux/cpu_rmap.h>
131#include <linux/static_key.h> 131#include <linux/static_key.h>
132#include <linux/hashtable.h>
132 133
133#include "net-sysfs.h" 134#include "net-sysfs.h"
134 135
@@ -166,6 +167,12 @@ static struct list_head offload_base __read_mostly;
166DEFINE_RWLOCK(dev_base_lock); 167DEFINE_RWLOCK(dev_base_lock);
167EXPORT_SYMBOL(dev_base_lock); 168EXPORT_SYMBOL(dev_base_lock);
168 169
170/* protects napi_hash addition/deletion and napi_gen_id */
171static DEFINE_SPINLOCK(napi_hash_lock);
172
173static unsigned int napi_gen_id;
174static DEFINE_HASHTABLE(napi_hash, 8);
175
169seqcount_t devnet_rename_seq; 176seqcount_t devnet_rename_seq;
170 177
171static inline void dev_base_seq_inc(struct net *net) 178static inline void dev_base_seq_inc(struct net *net)
@@ -4136,6 +4143,58 @@ void napi_complete(struct napi_struct *n)
4136} 4143}
4137EXPORT_SYMBOL(napi_complete); 4144EXPORT_SYMBOL(napi_complete);
4138 4145
4146/* must be called under rcu_read_lock(), as we dont take a reference */
4147struct napi_struct *napi_by_id(unsigned int napi_id)
4148{
4149 unsigned int hash = napi_id % HASH_SIZE(napi_hash);
4150 struct napi_struct *napi;
4151
4152 hlist_for_each_entry_rcu(napi, &napi_hash[hash], napi_hash_node)
4153 if (napi->napi_id == napi_id)
4154 return napi;
4155
4156 return NULL;
4157}
4158EXPORT_SYMBOL_GPL(napi_by_id);
4159
4160void napi_hash_add(struct napi_struct *napi)
4161{
4162 if (!test_and_set_bit(NAPI_STATE_HASHED, &napi->state)) {
4163
4164 spin_lock(&napi_hash_lock);
4165
4166 /* 0 is not a valid id, we also skip an id that is taken
4167 * we expect both events to be extremely rare
4168 */
4169 napi->napi_id = 0;
4170 while (!napi->napi_id) {
4171 napi->napi_id = ++napi_gen_id;
4172 if (napi_by_id(napi->napi_id))
4173 napi->napi_id = 0;
4174 }
4175
4176 hlist_add_head_rcu(&napi->napi_hash_node,
4177 &napi_hash[napi->napi_id % HASH_SIZE(napi_hash)]);
4178
4179 spin_unlock(&napi_hash_lock);
4180 }
4181}
4182EXPORT_SYMBOL_GPL(napi_hash_add);
4183
4184/* Warning : caller is responsible to make sure rcu grace period
4185 * is respected before freeing memory containing @napi
4186 */
4187void napi_hash_del(struct napi_struct *napi)
4188{
4189 spin_lock(&napi_hash_lock);
4190
4191 if (test_and_clear_bit(NAPI_STATE_HASHED, &napi->state))
4192 hlist_del_rcu(&napi->napi_hash_node);
4193
4194 spin_unlock(&napi_hash_lock);
4195}
4196EXPORT_SYMBOL_GPL(napi_hash_del);
4197
4139void netif_napi_add(struct net_device *dev, struct napi_struct *napi, 4198void netif_napi_add(struct net_device *dev, struct napi_struct *napi,
4140 int (*poll)(struct napi_struct *, int), int weight) 4199 int (*poll)(struct napi_struct *, int), int weight)
4141{ 4200{