Re: Poss. bug in tulip driver since 2.4.7

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Andrew Morton wrote:

> Prasanna Meda <pmeda@akamai.com> wrote:
> >
> > The inner for loop shown below was not
> >  supposed to be  inside  the  outside  loop.
> >  They  also use  the  same index i.
> >  Due to  this, when mc_count is more than
> >  14,  with non ASIX chips,  panics, corruptions
> >  and  denial of services to multicast addresses
> >  can  result!
> >
> >  http://lxr.linux.no/source/drivers/net/tulip/tulip_core.c#L1055
>
> So can you confirm that the driver works correctly with this change?
>
> --- 25/drivers/net/tulip/tulip_core.c~tulip-hash-fix    2003-11-11 18:51:52.000000000 -0800
> +++ 25-akpm/drivers/net/tulip/tulip_core.c      2003-11-11 18:52:31.000000000 -0800
> @@ -979,12 +979,13 @@ static void build_setup_frame_hash(u16 *
>         for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
>              i++, mclist = mclist->next) {
>                 int index = ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff;
> +               int j;
>
>                 set_bit_le(index, hash_table);
>
> -               for (i = 0; i < 32; i++) {
> -                       *setup_frm++ = hash_table[i];
> -                       *setup_frm++ = hash_table[i];
> +               for (j = 0; j < 32; j++) {
> +                       *setup_frm++ = hash_table[j];
> +                       *setup_frm++ = hash_table[j];
>                 }
>                 setup_frm = &tp->setup_frame[13*6];
>         }

No,  you need to bring the for loop outside the loop.
 - Otherwise we need to reset the setup_frame to
tp->setup_frame after every loop.
 - You do not need to set the setup_frm for every
mc address, we can set once after the complete
has_table is ready.
And also the  2.4 code missed a bit in tx_flags.

We did the following change that makes it identical
to 2.2 tulip driver, and it worked.

--- Linux/drivers/net/tulip/tulip_core.c  Fri Oct 10 20:22:29 2003
+++ linux/drivers/net/tulip/tulip_core.c        Fri Oct 10 20:28:19 2003
@@ -1054,19 +1054,19 @@

        memset(hash_table, 0, sizeof(hash_table));
        set_bit_le(255, hash_table);                    /* Broadcast entry */

        /* This should work on big-endian machines as well. */
       for (i = 0, mclist = dev->mc_list; mclist && i < dev->mc_count;
             i++, mclist = mclist->next) {
                int index = ether_crc_le(ETH_ALEN, mclist->dmi_addr) & 0x1ff;

                set_bit_le(index, hash_table);
+       }

-               for (i = 0; i < 32; i++) {
-                       *setup_frm++ = hash_table[i];
-                       *setup_frm++ = hash_table[i];
-               }
-               setup_frm = &tp->setup_frame[13*6];
+       for (i = 0; i < 32; i++) {
+               *setup_frm++ = hash_table[i];
+               *setup_frm++ = hash_table[i];
        }
+       setup_frm = &tp->setup_frame[13*6];

        /* Fill the final entry with our physical address. */
        eaddrs = (u16 *)dev->dev_addr;
@@ -1166,11 +1168,13 @@
                }
        } else {
                unsigned long flags;
+               u32 tx_flags = 0x08000000 | 192;

                /* Note that only the low-address shortword of setup_frame is valid!
                   The values are doubled for big-endian architectures. */
                if (dev->mc_count > 14) { /* Must use a multicast hash table. */
                        build_setup_frame_hash(tp->setup_frame, dev);
+                       tx_flags = 0x08400000 | 192;
                } else {
                        build_setup_frame_perfect(tp->setup_frame, dev);
                }
@@ -1180,7 +1184,6 @@
                if (tp->cur_tx - tp->dirty_tx > TX_RING_SIZE - 2) {
                        /* Same setup recently queued, we need not add it. */
                } else {
-                       u32 tx_flags = 0x08000000 | 192;
                        unsigned int entry;
                        int dummy = -1;


-
: send the line "unsubscribe linux-net" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux 802.1Q VLAN]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Git]     [Bugtraq]     [Yosemite News and Information]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux PCI]     [Linux Admin]     [Samba]

  Powered by Linux