#define inet_v6_ipv6only(__sk)         0
 #endif /* defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) */
 
-#define INET6_MATCH(__sk, __saddr, __daddr, __ports, __dif)       \
-       (((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports))   && \
+#define INET6_MATCH(__sk, __hash, __saddr, __daddr, __ports, __dif)\
+       (((__sk)->sk_hash == (__hash))                          && \
+        ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports))   && \
         ((__sk)->sk_family             == AF_INET6)            && \
         ipv6_addr_equal(&inet6_sk(__sk)->daddr, (__saddr))     && \
         ipv6_addr_equal(&inet6_sk(__sk)->rcv_saddr, (__daddr)) && \
 
        TCF_META_ID_SK_SNDBUF,
        TCF_META_ID_SK_ALLOCS,
        TCF_META_ID_SK_ROUTE_CAPS,
-       TCF_META_ID_SK_HASHENT,
+       TCF_META_ID_SK_HASH,
        TCF_META_ID_SK_LINGERTIME,
        TCF_META_ID_SK_ACK_BACKLOG,
        TCF_META_ID_SK_MAX_ACK_BACKLOG,
 
 struct inet_hashinfo;
 
 /* I have no idea if this is a good hash for v6 or not. -DaveM */
-static inline int inet6_ehashfn(const struct in6_addr *laddr, const u16 lport,
-                               const struct in6_addr *faddr, const u16 fport,
-                               const int ehash_size)
+static inline unsigned int inet6_ehashfn(const struct in6_addr *laddr, const u16 lport,
+                               const struct in6_addr *faddr, const u16 fport)
 {
-       int hashent = (lport ^ fport);
+       unsigned int hashent = (lport ^ fport);
 
        hashent ^= (laddr->s6_addr32[3] ^ faddr->s6_addr32[3]);
        hashent ^= hashent >> 16;
        hashent ^= hashent >> 8;
-       return (hashent & (ehash_size - 1));
+       return hashent;
 }
 
-static inline int inet6_sk_ehashfn(const struct sock *sk, const int ehash_size)
+static inline int inet6_sk_ehashfn(const struct sock *sk)
 {
        const struct inet_sock *inet = inet_sk(sk);
        const struct ipv6_pinfo *np = inet6_sk(sk);
        const struct in6_addr *faddr = &np->daddr;
        const __u16 lport = inet->num;
        const __u16 fport = inet->dport;
-       return inet6_ehashfn(laddr, lport, faddr, fport, ehash_size);
+       return inet6_ehashfn(laddr, lport, faddr, fport);
 }
 
 /*
        /* Optimize here for direct hit, only listening connections can
         * have wildcards anyways.
         */
-       const int hash = inet6_ehashfn(daddr, hnum, saddr, sport,
-                                      hashinfo->ehash_size);
-       struct inet_ehash_bucket *head = &hashinfo->ehash[hash];
+       unsigned int hash = inet6_ehashfn(daddr, hnum, saddr, sport);
+       struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash);
 
+       prefetch(head->chain.first);
        read_lock(&head->lock);
        sk_for_each(sk, node, &head->chain) {
                /* For IPV6 do the cheaper port and family tests first. */
-               if (INET6_MATCH(sk, saddr, daddr, ports, dif))
+               if (INET6_MATCH(sk, hash, saddr, daddr, ports, dif))
                        goto hit; /* You sunk my battleship! */
        }
        /* Must check for a TIME_WAIT'er before going to listener hash. */
 
        struct inet_bind_hashbucket     *bhash;
 
        int                             bhash_size;
-       int                             ehash_size;
+       unsigned int                    ehash_size;
 
        /* All sockets in TCP_LISTEN state will be in here.  This is the only
         * table where wildcard'd TCP sockets can exist.  Hash function here
        int                             port_rover;
 };
 
-static inline int inet_ehashfn(const __u32 laddr, const __u16 lport,
-                              const __u32 faddr, const __u16 fport,
-                              const int ehash_size)
+static inline unsigned int inet_ehashfn(const __u32 laddr, const __u16 lport,
+                              const __u32 faddr, const __u16 fport)
 {
-       int h = (laddr ^ lport) ^ (faddr ^ fport);
+       unsigned int h = (laddr ^ lport) ^ (faddr ^ fport);
        h ^= h >> 16;
        h ^= h >> 8;
-       return h & (ehash_size - 1);
+       return h;
 }
 
-static inline int inet_sk_ehashfn(const struct sock *sk, const int ehash_size)
+static inline int inet_sk_ehashfn(const struct sock *sk)
 {
        const struct inet_sock *inet = inet_sk(sk);
        const __u32 laddr = inet->rcv_saddr;
        const __u32 faddr = inet->daddr;
        const __u16 fport = inet->dport;
 
-       return inet_ehashfn(laddr, lport, faddr, fport, ehash_size);
+       return inet_ehashfn(laddr, lport, faddr, fport);
+}
+
+static inline struct inet_ehash_bucket *inet_ehash_bucket(
+       struct inet_hashinfo *hashinfo,
+       unsigned int hash)
+{
+       return &hashinfo->ehash[hash & (hashinfo->ehash_size - 1)];
 }
 
 extern struct inet_bind_bucket *
                lock = &hashinfo->lhash_lock;
                inet_listen_wlock(hashinfo);
        } else {
-               sk->sk_hashent = inet_sk_ehashfn(sk, hashinfo->ehash_size);
-               list = &hashinfo->ehash[sk->sk_hashent].chain;
-               lock = &hashinfo->ehash[sk->sk_hashent].lock;
+               struct inet_ehash_bucket *head;
+               sk->sk_hash = inet_sk_ehashfn(sk);
+               head = inet_ehash_bucket(hashinfo, sk->sk_hash);
+               list = &head->chain;
+               lock = &head->lock;
                write_lock(lock);
        }
        __sk_add_node(sk, list);
                inet_listen_wlock(hashinfo);
                lock = &hashinfo->lhash_lock;
        } else {
-               struct inet_ehash_bucket *head = &hashinfo->ehash[sk->sk_hashent];
-               lock = &head->lock;
-               write_lock_bh(&head->lock);
+               lock = &inet_ehash_bucket(hashinfo, sk->sk_hash)->lock;
+               write_lock_bh(lock);
        }
 
        if (__sk_del_node_init(sk))
 #define INET_ADDR_COOKIE(__name, __saddr, __daddr) \
        const __u64 __name = (((__u64)(__daddr)) << 32) | ((__u64)(__saddr));
 #endif /* __BIG_ENDIAN */
-#define INET_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)\
-       (((*((__u64 *)&(inet_sk(__sk)->daddr))) == (__cookie))  &&      \
+#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
+       (((__sk)->sk_hash == (__hash))                          &&      \
+        ((*((__u64 *)&(inet_sk(__sk)->daddr))) == (__cookie))  &&      \
         ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports))   &&      \
         (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-#define INET_TW_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)\
-       (((*((__u64 *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) &&  \
+#define INET_TW_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)\
+       (((__sk)->sk_hash == (__hash))                          &&      \
+        ((*((__u64 *)&(inet_twsk(__sk)->tw_daddr))) == (__cookie)) &&  \
         ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&   \
         (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
 #else /* 32-bit arch */
 #define INET_ADDR_COOKIE(__name, __saddr, __daddr)
-#define INET_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)   \
-       ((inet_sk(__sk)->daddr          == (__saddr))           &&      \
+#define INET_MATCH(__sk, __hash, __cookie, __saddr, __daddr, __ports, __dif)   \
+       (((__sk)->sk_hash == (__hash))                          &&      \
+        (inet_sk(__sk)->daddr          == (__saddr))           &&      \
         (inet_sk(__sk)->rcv_saddr      == (__daddr))           &&      \
         ((*((__u32 *)&(inet_sk(__sk)->dport))) == (__ports))   &&      \
         (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
-#define INET_TW_MATCH(__sk, __cookie, __saddr, __daddr, __ports, __dif)        \
-       ((inet_twsk(__sk)->tw_daddr     == (__saddr))           &&      \
+#define INET_TW_MATCH(__sk, __hash,__cookie, __saddr, __daddr, __ports, __dif) \
+       (((__sk)->sk_hash == (__hash))                          &&      \
+        (inet_twsk(__sk)->tw_daddr     == (__saddr))           &&      \
         (inet_twsk(__sk)->tw_rcv_saddr == (__daddr))           &&      \
         ((*((__u32 *)&(inet_twsk(__sk)->tw_dport))) == (__ports)) &&   \
         (!((__sk)->sk_bound_dev_if) || ((__sk)->sk_bound_dev_if == (__dif))))
        /* Optimize here for direct hit, only listening connections can
         * have wildcards anyways.
         */
-       const int hash = inet_ehashfn(daddr, hnum, saddr, sport, hashinfo->ehash_size);
-       struct inet_ehash_bucket *head = &hashinfo->ehash[hash];
+       unsigned int hash = inet_ehashfn(daddr, hnum, saddr, sport);
+       struct inet_ehash_bucket *head = inet_ehash_bucket(hashinfo, hash);
 
+       prefetch(head->chain.first);
        read_lock(&head->lock);
        sk_for_each(sk, node, &head->chain) {
-               if (INET_MATCH(sk, acookie, saddr, daddr, ports, dif))
+               if (INET_MATCH(sk, hash, acookie, saddr, daddr, ports, dif))
                        goto hit; /* You sunk my battleship! */
        }
 
        /* Must check for a TIME_WAIT'er before going to listener hash. */
        sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) {
-               if (INET_TW_MATCH(sk, acookie, saddr, daddr, ports, dif))
+               if (INET_TW_MATCH(sk, hash, acookie, saddr, daddr, ports, dif))
                        goto hit;
        }
        sk = NULL;
 
 #define tw_node                        __tw_common.skc_node
 #define tw_bind_node           __tw_common.skc_bind_node
 #define tw_refcnt              __tw_common.skc_refcnt
+#define tw_hash                        __tw_common.skc_hash
 #define tw_prot                        __tw_common.skc_prot
        volatile unsigned char  tw_substate;
        /* 3 bits hole, try to pack */
        /* And these are ours. */
        __u8                    tw_ipv6only:1;
        /* 31 bits hole, try to pack */
-       int                     tw_hashent;
        int                     tw_timeout;
        unsigned long           tw_ttd;
        struct inet_bind_bucket *tw_tb;
 
  *     @skc_node: main hash linkage for various protocol lookup tables
  *     @skc_bind_node: bind hash linkage for various protocol lookup tables
  *     @skc_refcnt: reference count
+ *     @skc_hash: hash value used with various protocol lookup tables
  *     @skc_prot: protocol handlers inside a network family
  *
  *     This is the minimal network layer representation of sockets, the header
        struct hlist_node       skc_node;
        struct hlist_node       skc_bind_node;
        atomic_t                skc_refcnt;
+       unsigned int            skc_hash;
        struct proto            *skc_prot;
 };
 
   *    @sk_no_check: %SO_NO_CHECK setting, wether or not checkup packets
   *    @sk_route_caps: route capabilities (e.g. %NETIF_F_TSO)
   *    @sk_lingertime: %SO_LINGER l_linger setting
-  *    @sk_hashent: hash entry in several tables (e.g. inet_hashinfo.ehash)
   *    @sk_backlog: always used with the per-socket spinlock held
   *    @sk_callback_lock: used with the callbacks in the end of this struct
   *    @sk_error_queue: rarely used
 #define sk_node                        __sk_common.skc_node
 #define sk_bind_node           __sk_common.skc_bind_node
 #define sk_refcnt              __sk_common.skc_refcnt
+#define sk_hash                        __sk_common.skc_hash
 #define sk_prot                        __sk_common.skc_prot
        unsigned char           sk_shutdown : 2,
                                sk_no_check : 2,
        unsigned int            sk_allocation;
        int                     sk_sndbuf;
        int                     sk_route_caps;
-       int                     sk_hashent;
        unsigned long           sk_flags;
        unsigned long           sk_lingertime;
        /*
 
        struct atm_vcc *vcc = atm_sk(sk);
        struct hlist_head *head = &vcc_hash[vcc->vci &
                                        (VCC_HTABLE_SIZE - 1)];
-       sk->sk_hashent = vcc->vci & (VCC_HTABLE_SIZE - 1);
+       sk->sk_hash = vcc->vci & (VCC_HTABLE_SIZE - 1);
        sk_add_node(sk, head);
 }
 
 
        const int dif = sk->sk_bound_dev_if;
        INET_ADDR_COOKIE(acookie, saddr, daddr)
        const __u32 ports = INET_COMBINED_PORTS(inet->dport, lport);
-       const int hash = inet_ehashfn(daddr, lport, saddr, inet->dport,
-                                     dccp_hashinfo.ehash_size);
-       struct inet_ehash_bucket *head = &dccp_hashinfo.ehash[hash];
+       unsigned int hash = inet_ehashfn(daddr, lport, saddr, inet->dport);
+       struct inet_ehash_bucket *head = inet_ehash_bucket(&dccp_hashinfo, hash);
        const struct sock *sk2;
        const struct hlist_node *node;
        struct inet_timewait_sock *tw;
 
+       prefetch(head->chain.first);
        write_lock(&head->lock);
 
        /* Check TIME-WAIT sockets first. */
        sk_for_each(sk2, node, &(head + dccp_hashinfo.ehash_size)->chain) {
                tw = inet_twsk(sk2);
 
-               if (INET_TW_MATCH(sk2, acookie, saddr, daddr, ports, dif))
+               if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif))
                        goto not_unique;
        }
        tw = NULL;
 
        /* And established part... */
        sk_for_each(sk2, node, &head->chain) {
-               if (INET_MATCH(sk2, acookie, saddr, daddr, ports, dif))
+               if (INET_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif))
                        goto not_unique;
        }
 
         * in hash table socket with a funny identity. */
        inet->num = lport;
        inet->sport = htons(lport);
-       sk->sk_hashent = hash;
+       sk->sk_hash = hash;
        BUG_TRAP(sk_unhashed(sk));
        __sk_add_node(sk, &head->chain);
        sock_prot_inc_use(sk->sk_prot);
 
        struct inet_bind_hashbucket *bhead;
        struct inet_bind_bucket *tb;
        /* Unlink from established hashes. */
-       struct inet_ehash_bucket *ehead = &hashinfo->ehash[tw->tw_hashent];
+       struct inet_ehash_bucket *ehead = inet_ehash_bucket(hashinfo, tw->tw_hash);
 
        write_lock(&ehead->lock);
        if (hlist_unhashed(&tw->tw_node)) {
 {
        const struct inet_sock *inet = inet_sk(sk);
        const struct inet_connection_sock *icsk = inet_csk(sk);
-       struct inet_ehash_bucket *ehead = &hashinfo->ehash[sk->sk_hashent];
+       struct inet_ehash_bucket *ehead = inet_ehash_bucket(hashinfo, sk->sk_hash);
        struct inet_bind_hashbucket *bhead;
        /* Step 1: Put TW into bind hash. Original socket stays there too.
           Note, that any socket with inet->num != 0 MUST be bound in
                tw->tw_dport        = inet->dport;
                tw->tw_family       = sk->sk_family;
                tw->tw_reuse        = sk->sk_reuse;
-               tw->tw_hashent      = sk->sk_hashent;
+               tw->tw_hash         = sk->sk_hash;
                tw->tw_ipv6only     = 0;
                tw->tw_prot         = sk->sk_prot_creator;
                atomic_set(&tw->tw_refcnt, 1);
 
        int dif = sk->sk_bound_dev_if;
        INET_ADDR_COOKIE(acookie, saddr, daddr)
        const __u32 ports = INET_COMBINED_PORTS(inet->dport, lport);
-       const int hash = inet_ehashfn(daddr, lport, saddr, inet->dport, tcp_hashinfo.ehash_size);
-       struct inet_ehash_bucket *head = &tcp_hashinfo.ehash[hash];
+       unsigned int hash = inet_ehashfn(daddr, lport, saddr, inet->dport);
+       struct inet_ehash_bucket *head = inet_ehash_bucket(&tcp_hashinfo, hash);
        struct sock *sk2;
        const struct hlist_node *node;
        struct inet_timewait_sock *tw;
 
+       prefetch(head->chain.first);
        write_lock(&head->lock);
 
        /* Check TIME-WAIT sockets first. */
        sk_for_each(sk2, node, &(head + tcp_hashinfo.ehash_size)->chain) {
                tw = inet_twsk(sk2);
 
-               if (INET_TW_MATCH(sk2, acookie, saddr, daddr, ports, dif)) {
+               if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif)) {
                        const struct tcp_timewait_sock *tcptw = tcp_twsk(sk2);
                        struct tcp_sock *tp = tcp_sk(sk);
 
 
        /* And established part... */
        sk_for_each(sk2, node, &head->chain) {
-               if (INET_MATCH(sk2, acookie, saddr, daddr, ports, dif))
+               if (INET_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif))
                        goto not_unique;
        }
 
         * in hash table socket with a funny identity. */
        inet->num = lport;
        inet->sport = htons(lport);
-       sk->sk_hashent = hash;
+       sk->sk_hash = hash;
        BUG_TRAP(sk_unhashed(sk));
        __sk_add_node(sk, &head->chain);
        sock_prot_inc_use(sk->sk_prot);
 
                lock = &tcp_hashinfo.lhash_lock;
                inet_listen_wlock(&tcp_hashinfo);
        } else {
-               sk->sk_hashent = inet6_sk_ehashfn(sk, tcp_hashinfo.ehash_size);
-               list = &tcp_hashinfo.ehash[sk->sk_hashent].chain;
-               lock = &tcp_hashinfo.ehash[sk->sk_hashent].lock;
+               unsigned int hash;
+               sk->sk_hash = hash = inet6_sk_ehashfn(sk);
+               hash &= (tcp_hashinfo.ehash_size - 1);
+               list = &tcp_hashinfo.ehash[hash].chain;
+               lock = &tcp_hashinfo.ehash[hash].lock;
                write_lock(lock);
        }
 
        const struct in6_addr *saddr = &np->daddr;
        const int dif = sk->sk_bound_dev_if;
        const u32 ports = INET_COMBINED_PORTS(inet->dport, lport);
-       const int hash = inet6_ehashfn(daddr, inet->num, saddr, inet->dport,
-                                      tcp_hashinfo.ehash_size);
-       struct inet_ehash_bucket *head = &tcp_hashinfo.ehash[hash];
+       unsigned int hash = inet6_ehashfn(daddr, inet->num, saddr, inet->dport);
+       struct inet_ehash_bucket *head = inet_ehash_bucket(&tcp_hashinfo, hash);
        struct sock *sk2;
        const struct hlist_node *node;
        struct inet_timewait_sock *tw;
 
+       prefetch(head->chain.first);
        write_lock(&head->lock);
 
        /* Check TIME-WAIT sockets first. */
 
        /* And established part... */
        sk_for_each(sk2, node, &head->chain) {
-               if (INET6_MATCH(sk2, saddr, daddr, ports, dif))
+               if (INET6_MATCH(sk2, hash, saddr, daddr, ports, dif))
                        goto not_unique;
        }
 
 unique:
        BUG_TRAP(sk_unhashed(sk));
        __sk_add_node(sk, &head->chain);
-       sk->sk_hashent = hash;
+       sk->sk_hash = hash;
        sock_prot_inc_use(sk->sk_prot);
        write_unlock(&head->lock);
 
 
        dst->value = skb->sk->sk_route_caps;
 }
 
-META_COLLECTOR(int_sk_hashent)
+META_COLLECTOR(int_sk_hash)
 {
        SKIP_NONLOCAL(skb);
-       dst->value = skb->sk->sk_hashent;
+       dst->value = skb->sk->sk_hash;
 }
 
 META_COLLECTOR(int_sk_lingertime)
                [META_ID(SK_FORWARD_ALLOCS)]    = META_FUNC(int_sk_fwd_alloc),
                [META_ID(SK_ALLOCS)]            = META_FUNC(int_sk_alloc),
                [META_ID(SK_ROUTE_CAPS)]        = META_FUNC(int_sk_route_caps),
-               [META_ID(SK_HASHENT)]           = META_FUNC(int_sk_hashent),
+               [META_ID(SK_HASH)]              = META_FUNC(int_sk_hash),
                [META_ID(SK_LINGERTIME)]        = META_FUNC(int_sk_lingertime),
                [META_ID(SK_ACK_BACKLOG)]       = META_FUNC(int_sk_ack_bl),
                [META_ID(SK_MAX_ACK_BACKLOG)]   = META_FUNC(int_sk_max_ack_bl),