Skip to content

Commit ebe60f3

Browse files
bwhacksgregkh
authored andcommitted
r6040: Fix multicast filter some more
[ Upstream commit e226930 ] 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 torvalds#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 3bcf822, 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 torvalds#6. Signed-off-by: Ben Hutchings <[email protected]> Signed-off-by: David S. Miller <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent 2556c3e commit ebe60f3

File tree

1 file changed

+12
-10
lines changed

1 file changed

+12
-10
lines changed

drivers/net/r6040.c

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -988,16 +988,18 @@ static void r6040_multicast_list(struct net_device *dev)
988988
/* Multicast Address 1~4 case */
989989
i = 0;
990990
netdev_for_each_mc_addr(ha, dev) {
991-
if (i < MCAST_MAX) {
992-
adrp = (u16 *) ha->addr;
993-
iowrite16(adrp[0], ioaddr + MID_1L + 8 * i);
994-
iowrite16(adrp[1], ioaddr + MID_1M + 8 * i);
995-
iowrite16(adrp[2], ioaddr + MID_1H + 8 * i);
996-
} else {
997-
iowrite16(0xffff, ioaddr + MID_1L + 8 * i);
998-
iowrite16(0xffff, ioaddr + MID_1M + 8 * i);
999-
iowrite16(0xffff, ioaddr + MID_1H + 8 * i);
1000-
}
991+
if (i >= MCAST_MAX)
992+
break;
993+
adrp = (u16 *) ha->addr;
994+
iowrite16(adrp[0], ioaddr + MID_1L + 8 * i);
995+
iowrite16(adrp[1], ioaddr + MID_1M + 8 * i);
996+
iowrite16(adrp[2], ioaddr + MID_1H + 8 * i);
997+
i++;
998+
}
999+
while (i < MCAST_MAX) {
1000+
iowrite16(0xffff, ioaddr + MID_1L + 8 * i);
1001+
iowrite16(0xffff, ioaddr + MID_1M + 8 * i);
1002+
iowrite16(0xffff, ioaddr + MID_1H + 8 * i);
10011003
i++;
10021004
}
10031005
}

0 commit comments

Comments
 (0)