diff options
author | Eliezer Tamir <eliezer.tamir@linux.intel.com> | 2013-06-10 04:39:41 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2013-06-11 00:22:35 -0400 |
commit | af12fa6e46aa651e7b86a4c4117b562518fef184 (patch) | |
tree | 1425ef11083e66af192c33abb3b1fa3b04b26f4b /net/core | |
parent | 6f00a0229627ca189529cad3f9154ac2f9e5c7db (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.c | 59 |
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; | |||
166 | DEFINE_RWLOCK(dev_base_lock); | 167 | DEFINE_RWLOCK(dev_base_lock); |
167 | EXPORT_SYMBOL(dev_base_lock); | 168 | EXPORT_SYMBOL(dev_base_lock); |
168 | 169 | ||
170 | /* protects napi_hash addition/deletion and napi_gen_id */ | ||
171 | static DEFINE_SPINLOCK(napi_hash_lock); | ||
172 | |||
173 | static unsigned int napi_gen_id; | ||
174 | static DEFINE_HASHTABLE(napi_hash, 8); | ||
175 | |||
169 | seqcount_t devnet_rename_seq; | 176 | seqcount_t devnet_rename_seq; |
170 | 177 | ||
171 | static inline void dev_base_seq_inc(struct net *net) | 178 | static inline void dev_base_seq_inc(struct net *net) |
@@ -4136,6 +4143,58 @@ void napi_complete(struct napi_struct *n) | |||
4136 | } | 4143 | } |
4137 | EXPORT_SYMBOL(napi_complete); | 4144 | EXPORT_SYMBOL(napi_complete); |
4138 | 4145 | ||
4146 | /* must be called under rcu_read_lock(), as we dont take a reference */ | ||
4147 | struct 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 | } | ||
4158 | EXPORT_SYMBOL_GPL(napi_by_id); | ||
4159 | |||
4160 | void 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 | } | ||
4182 | EXPORT_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 | */ | ||
4187 | void 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 | } | ||
4196 | EXPORT_SYMBOL_GPL(napi_hash_del); | ||
4197 | |||
4139 | void netif_napi_add(struct net_device *dev, struct napi_struct *napi, | 4198 | void 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 | { |