#include <asm/byteorder.h>
 
 /* This is for all connections with a full identity, no wildcards.
- * New scheme, half the table is for TIME_WAIT, the other half is
- * for the rest.  I'll experiment with dynamic table growth later.
+ * One chain is dedicated to TIME_WAIT sockets.
+ * I'll experiment with dynamic table growth later.
  */
 struct inet_ehash_bucket {
        rwlock_t          lock;
        struct hlist_head chain;
+       struct hlist_head twchain;
 };
 
 /* There are a few simple rules, which allow for local port reuse by
         *
         *          TCP_ESTABLISHED <= sk->sk_state < TCP_CLOSE
         *
-        * First half of the table is for sockets not in TIME_WAIT, second half
-        * is for TIME_WAIT sockets only.
+        * TIME_WAIT sockets use a separate chain (twchain).
         */
        struct inet_ehash_bucket        *ehash;
 
        }
 
        /* Must check for a TIME_WAIT'er before going to listener hash. */
-       sk_for_each(sk, node, &(head + hashinfo->ehash_size)->chain) {
+       sk_for_each(sk, node, &head->twchain) {
                if (INET_TW_MATCH(sk, hash, acookie, saddr, daddr, ports, dif))
                        goto hit;
        }
 
        do {
                dccp_hashinfo.ehash_size = (1UL << ehash_order) * PAGE_SIZE /
                                        sizeof(struct inet_ehash_bucket);
-               dccp_hashinfo.ehash_size >>= 1;
                while (dccp_hashinfo.ehash_size &
                       (dccp_hashinfo.ehash_size - 1))
                        dccp_hashinfo.ehash_size--;
                goto out_free_bind_bucket_cachep;
        }
 
-       for (i = 0; i < (dccp_hashinfo.ehash_size << 1); i++) {
+       for (i = 0; i < dccp_hashinfo.ehash_size; i++) {
                rwlock_init(&dccp_hashinfo.ehash[i].lock);
                INIT_HLIST_HEAD(&dccp_hashinfo.ehash[i].chain);
+               INIT_HLIST_HEAD(&dccp_hashinfo.ehash[i].twchain);
        }
 
        bhash_order = ehash_order;
 
                        struct inet_timewait_sock *tw;
 
                        inet_twsk_for_each(tw, node,
-                                   &hashinfo->ehash[i + hashinfo->ehash_size].chain) {
+                                   &head->twchain) {
 
                                if (num < s_num)
                                        goto next_dying;
 
        write_lock(&head->lock);
 
        /* Check TIME-WAIT sockets first. */
-       sk_for_each(sk2, node, &(head + hinfo->ehash_size)->chain) {
+       sk_for_each(sk2, node, &head->twchain) {
                tw = inet_twsk(sk2);
 
                if (INET_TW_MATCH(sk2, hash, acookie, saddr, daddr, ports, dif)) {
 
        if (__sk_del_node_init(sk))
                sock_prot_dec_use(sk->sk_prot);
 
-       /* Step 3: Hash TW into TIMEWAIT half of established hash table. */
-       inet_twsk_add_node(tw, &(ehead + hashinfo->ehash_size)->chain);
+       /* Step 3: Hash TW into TIMEWAIT chain. */
+       inet_twsk_add_node(tw, &ehead->twchain);
        atomic_inc(&tw->tw_refcnt);
 
        write_unlock(&ehead->lock);
 
                                        &tcp_hashinfo.ehash_size,
                                        NULL,
                                        0);
-       tcp_hashinfo.ehash_size = (1 << tcp_hashinfo.ehash_size) >> 1;
-       for (i = 0; i < (tcp_hashinfo.ehash_size << 1); i++) {
+       tcp_hashinfo.ehash_size = 1 << tcp_hashinfo.ehash_size;
+       for (i = 0; i < tcp_hashinfo.ehash_size; i++) {
                rwlock_init(&tcp_hashinfo.ehash[i].lock);
                INIT_HLIST_HEAD(&tcp_hashinfo.ehash[i].chain);
+               INIT_HLIST_HEAD(&tcp_hashinfo.ehash[i].twchain);
        }
 
        tcp_hashinfo.bhash =
 
        printk(KERN_INFO "TCP: Hash tables configured "
               "(established %d bind %d)\n",
-              tcp_hashinfo.ehash_size << 1, tcp_hashinfo.bhash_size);
+              tcp_hashinfo.ehash_size, tcp_hashinfo.bhash_size);
 
        tcp_register_congestion_control(&tcp_reno);
 }
 
                }
                st->state = TCP_SEQ_STATE_TIME_WAIT;
                inet_twsk_for_each(tw, node,
-                                  &tcp_hashinfo.ehash[st->bucket + tcp_hashinfo.ehash_size].chain) {
+                                  &tcp_hashinfo.ehash[st->bucket].twchain) {
                        if (tw->tw_family != st->family) {
                                continue;
                        }
        }
 
        st->state = TCP_SEQ_STATE_TIME_WAIT;
-       tw = tw_head(&tcp_hashinfo.ehash[st->bucket + tcp_hashinfo.ehash_size].chain);
+       tw = tw_head(&tcp_hashinfo.ehash[st->bucket].twchain);
        goto get_tw;
 found:
        cur = sk;
 
                        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) {
+       sk_for_each(sk, node, &head->twchain) {
                const struct inet_timewait_sock *tw = inet_twsk(sk);
 
                if(*((__portpair *)&(tw->tw_dport))     == ports        &&
        write_lock(&head->lock);
 
        /* Check TIME-WAIT sockets first. */
-       sk_for_each(sk2, node, &(head + hinfo->ehash_size)->chain) {
+       sk_for_each(sk2, node, &head->twchain) {
                const struct inet6_timewait_sock *tw6 = inet6_twsk(sk2);
 
                tw = inet_twsk(sk2);