summaryrefslogtreecommitdiffstats
path: root/net/ipv6/protocol.c
diff options
context:
space:
mode:
authorPekka Enberg <penberg@kernel.org>2010-10-24 19:57:05 +0300
committerPekka Enberg <penberg@kernel.org>2010-10-24 19:57:05 +0300
commit6d4121f6c20a0e86231d52f535f1c82423b3326f (patch)
tree5c235cac699ca86b504850aa663ddadde0455a61 /net/ipv6/protocol.c
parent92a5bbc11ff2442a54b2f1d313088c245828ef4e (diff)
parent35da7a307c535f9c2929cae277f3df425c9f9b1e (diff)
Merge branch 'master' into for-linus
Conflicts: include/linux/percpu.h mm/percpu.c
Diffstat (limited to 'net/ipv6/protocol.c')
-rw-r--r--net/ipv6/protocol.c32
1 files changed, 4 insertions, 28 deletions
diff --git a/net/ipv6/protocol.c b/net/ipv6/protocol.c
index 1fa3468f0f3..9bb936ae245 100644
--- a/net/ipv6/protocol.c
+++ b/net/ipv6/protocol.c
@@ -25,28 +25,14 @@
#include <linux/spinlock.h>
#include <net/protocol.h>
-const struct inet6_protocol *inet6_protos[MAX_INET_PROTOS];
-static DEFINE_SPINLOCK(inet6_proto_lock);
-
+const struct inet6_protocol *inet6_protos[MAX_INET_PROTOS] __read_mostly;
int inet6_add_protocol(const struct inet6_protocol *prot, unsigned char protocol)
{
- int ret, hash = protocol & (MAX_INET_PROTOS - 1);
-
- spin_lock_bh(&inet6_proto_lock);
-
- if (inet6_protos[hash]) {
- ret = -1;
- } else {
- inet6_protos[hash] = prot;
- ret = 0;
- }
-
- spin_unlock_bh(&inet6_proto_lock);
+ int hash = protocol & (MAX_INET_PROTOS - 1);
- return ret;
+ return !cmpxchg(&inet6_protos[hash], NULL, prot) ? 0 : -1;
}
-
EXPORT_SYMBOL(inet6_add_protocol);
/*
@@ -57,20 +43,10 @@ int inet6_del_protocol(const struct inet6_protocol *prot, unsigned char protocol
{
int ret, hash = protocol & (MAX_INET_PROTOS - 1);
- spin_lock_bh(&inet6_proto_lock);
-
- if (inet6_protos[hash] != prot) {
- ret = -1;
- } else {
- inet6_protos[hash] = NULL;
- ret = 0;
- }
-
- spin_unlock_bh(&inet6_proto_lock);
+ ret = (cmpxchg(&inet6_protos[hash], prot, NULL) == prot) ? 0 : -1;
synchronize_net();
return ret;
}
-
EXPORT_SYMBOL(inet6_del_protocol);