summaryrefslogtreecommitdiffstats
path: root/include/net/ndisc.h
diff options
context:
space:
mode:
authorDaniel Vetter <daniel.vetter@ffwll.ch>2012-02-10 16:52:55 +0100
committerDaniel Vetter <daniel.vetter@ffwll.ch>2012-02-10 17:14:49 +0100
commit9edd576d89a5b6d3e136d7dcab654d887c0d25b7 (patch)
treed19670de2256f8187321de3a41fa4a10d3c8e402 /include/net/ndisc.h
parente21af88d39796c907c38648c824be3d646ffbe35 (diff)
parent28a4d5675857f6386930a324317281cb8ed1e5d0 (diff)
Merge remote-tracking branch 'airlied/drm-fixes' into drm-intel-next-queued
Back-merge from drm-fixes into drm-intel-next to sort out two things: - interlaced support: -fixes contains a bugfix to correctly clear interlaced configuration bits in case the bios sets up an interlaced mode and we want to set up the progressive mode (current kernels don't support interlaced). The actual feature work to support interlaced depends upon (and conflicts with) this bugfix. - forcewake voodoo to workaround missed IRQ issues: -fixes only enabled this for ivybridge, but some recent bug reports indicate that we need this on Sandybridge, too. But in a slightly different flavour and with other fixes and reworks on top. Additionally there are some forcewake cleanup patches heading to -next that would conflict with currrent -fixes. Signed-Off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
Diffstat (limited to 'include/net/ndisc.h')
-rw-r--r--include/net/ndisc.h45
1 files changed, 36 insertions, 9 deletions
diff --git a/include/net/ndisc.h b/include/net/ndisc.h
index 62beeb97c4b..e3133c23980 100644
--- a/include/net/ndisc.h
+++ b/include/net/ndisc.h
@@ -79,6 +79,42 @@ struct nd_opt_hdr {
__u8 nd_opt_len;
} __packed;
+static inline u32 ndisc_hashfn(const void *pkey, const struct net_device *dev, __u32 *hash_rnd)
+{
+ const u32 *p32 = pkey;
+
+ return (((p32[0] ^ dev->ifindex) * hash_rnd[0]) +
+ (p32[1] * hash_rnd[1]) +
+ (p32[2] * hash_rnd[2]) +
+ (p32[3] * hash_rnd[3]));
+}
+
+static inline struct neighbour *__ipv6_neigh_lookup(struct neigh_table *tbl, struct net_device *dev, const void *pkey)
+{
+ struct neigh_hash_table *nht;
+ const u32 *p32 = pkey;
+ struct neighbour *n;
+ u32 hash_val;
+
+ rcu_read_lock_bh();
+ nht = rcu_dereference_bh(tbl->nht);
+ hash_val = ndisc_hashfn(pkey, dev, nht->hash_rnd) >> (32 - nht->hash_shift);
+ for (n = rcu_dereference_bh(nht->hash_buckets[hash_val]);
+ n != NULL;
+ n = rcu_dereference_bh(n->next)) {
+ u32 *n32 = (u32 *) n->primary_key;
+ if (n->dev == dev &&
+ ((n32[0] ^ p32[0]) | (n32[1] ^ p32[1]) |
+ (n32[2] ^ p32[2]) | (n32[3] ^ p32[3])) == 0) {
+ if (!atomic_inc_not_zero(&n->refcnt))
+ n = NULL;
+ break;
+ }
+ }
+ rcu_read_unlock_bh();
+
+ return n;
+}
extern int ndisc_init(void);
@@ -145,13 +181,4 @@ int ndisc_ifinfo_sysctl_strategy(ctl_table *ctl,
extern void inet6_ifinfo_notify(int event,
struct inet6_dev *idev);
-static inline struct neighbour * ndisc_get_neigh(struct net_device *dev, const struct in6_addr *addr)
-{
-
- if (dev)
- return __neigh_lookup_errno(&nd_tbl, addr, dev);
-
- return ERR_PTR(-ENODEV);
-}
-
#endif