2.6.36-stable review patch.  If anyone has any objections, please let us know.

------------------

From: Ben Hutchings <[email protected]>

commit e2269308359d5863b6aa1fcb95a425a2ab255f1f upstream.

This code has been broken forever, but in several different and
creative ways.

So far as I can work out, the R6040 MAC filter has 4 exact-match
entries, the first of which the driver uses for its assigned unicast
address, plus a 64-entry hash-based filter for multicast addresses
(maybe unicast as well?).

The original version of this code would write the first 4 multicast
addresses as exact-match entries from offset 1 (bug #1: there is no
entry 4 so this could write to some PHY registers).  It would fill the
remainder of the exact-match entries with the broadcast address (bug #2:
this would overwrite the last used entry).  If more than 4 multicast
addresses were configured, it would set up the hash table, write some
random crap to the MAC control register (bug #3) and finally walk off
the end of the list when filling the exact-match entries (bug #4).

All of this seems to be pointless, since it sets the promiscuous bit
when the interface is made promiscuous or if >4 multicast addresses
are enabled, and never clears it (bug #5, masking bug #2).

The recent(ish) changes to the multicast list fixed bug #4, but
completely removed the limit on iteration over the exact-match entries
(bug #6).

Bug #4 was reported as
<https://bugzilla.kernel.org/show_bug.cgi?id=15355> and more recently
as <http://bugs.debian.org/600155>.  Florian Fainelli attempted to fix
these in commit 3bcf8229a8c49769e48d3e0bd1e20d8e003f8106, but that
actually dealt with bugs #1-3, bug #4 having been fixed in mainline at
that point.

That commit fixes the most important current bug #6.

Signed-off-by: Ben Hutchings <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
Signed-off-by: Greg Kroah-Hartman <[email protected]>

---
 drivers/net/r6040.c |   22 ++++++++++++----------
 1 file changed, 12 insertions(+), 10 deletions(-)

--- a/drivers/net/r6040.c
+++ b/drivers/net/r6040.c
@@ -893,16 +893,18 @@ static void r6040_multicast_list(struct
        /* Multicast Address 1~4 case */
        i = 0;
        netdev_for_each_mc_addr(ha, dev) {
-               if (i < MCAST_MAX) {
-                       adrp = (u16 *) ha->addr;
-                       iowrite16(adrp[0], ioaddr + MID_1L + 8 * i);
-                       iowrite16(adrp[1], ioaddr + MID_1M + 8 * i);
-                       iowrite16(adrp[2], ioaddr + MID_1H + 8 * i);
-               } else {
-                       iowrite16(0xffff, ioaddr + MID_1L + 8 * i);
-                       iowrite16(0xffff, ioaddr + MID_1M + 8 * i);
-                       iowrite16(0xffff, ioaddr + MID_1H + 8 * i);
-               }
+               if (i >= MCAST_MAX)
+                       break;
+               adrp = (u16 *) ha->addr;
+               iowrite16(adrp[0], ioaddr + MID_1L + 8 * i);
+               iowrite16(adrp[1], ioaddr + MID_1M + 8 * i);
+               iowrite16(adrp[2], ioaddr + MID_1H + 8 * i);
+               i++;
+       }
+       while (i < MCAST_MAX) {
+               iowrite16(0xffff, ioaddr + MID_1L + 8 * i);
+               iowrite16(0xffff, ioaddr + MID_1M + 8 * i);
+               iowrite16(0xffff, ioaddr + MID_1H + 8 * i);
                i++;
        }
 }


_______________________________________________
stable mailing list
[email protected]
http://linux.kernel.org/mailman/listinfo/stable

Reply via email to