]>
Commit | Line | Data |
---|---|---|
c06f7f46 GKH |
1 | From e2269308359d5863b6aa1fcb95a425a2ab255f1f Mon Sep 17 00:00:00 2001 |
2 | From: Ben Hutchings <ben@decadent.org.uk> | |
3 | Date: Thu, 14 Oct 2010 17:41:53 +0000 | |
4 | Subject: r6040: Fix multicast filter some more | |
5 | ||
6 | From: Ben Hutchings <ben@decadent.org.uk> | |
7 | ||
8 | commit e2269308359d5863b6aa1fcb95a425a2ab255f1f upstream. | |
9 | ||
10 | This code has been broken forever, but in several different and | |
11 | creative ways. | |
12 | ||
13 | So far as I can work out, the R6040 MAC filter has 4 exact-match | |
14 | entries, the first of which the driver uses for its assigned unicast | |
15 | address, plus a 64-entry hash-based filter for multicast addresses | |
16 | (maybe unicast as well?). | |
17 | ||
18 | The original version of this code would write the first 4 multicast | |
19 | addresses as exact-match entries from offset 1 (bug #1: there is no | |
20 | entry 4 so this could write to some PHY registers). It would fill the | |
21 | remainder of the exact-match entries with the broadcast address (bug #2: | |
22 | this would overwrite the last used entry). If more than 4 multicast | |
23 | addresses were configured, it would set up the hash table, write some | |
24 | random crap to the MAC control register (bug #3) and finally walk off | |
25 | the end of the list when filling the exact-match entries (bug #4). | |
26 | ||
27 | All of this seems to be pointless, since it sets the promiscuous bit | |
28 | when the interface is made promiscuous or if >4 multicast addresses | |
29 | are enabled, and never clears it (bug #5, masking bug #2). | |
30 | ||
31 | The recent(ish) changes to the multicast list fixed bug #4, but | |
32 | completely removed the limit on iteration over the exact-match entries | |
33 | (bug #6). | |
34 | ||
35 | Bug #4 was reported as | |
36 | <https://bugzilla.kernel.org/show_bug.cgi?id=15355> and more recently | |
37 | as <http://bugs.debian.org/600155>. Florian Fainelli attempted to fix | |
38 | these in commit 3bcf8229a8c49769e48d3e0bd1e20d8e003f8106, but that | |
39 | actually dealt with bugs #1-3, bug #4 having been fixed in mainline at | |
40 | that point. | |
41 | ||
42 | That commit fixes the most important current bug #6. | |
43 | ||
44 | Signed-off-by: Ben Hutchings <ben@decadent.org.uk> | |
45 | Signed-off-by: David S. Miller <davem@davemloft.net> | |
46 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
47 | ||
48 | --- | |
49 | drivers/net/r6040.c | 22 ++++++++++++---------- | |
50 | 1 file changed, 12 insertions(+), 10 deletions(-) | |
51 | ||
52 | --- a/drivers/net/r6040.c | |
53 | +++ b/drivers/net/r6040.c | |
54 | @@ -893,16 +893,18 @@ static void r6040_multicast_list(struct | |
55 | /* Multicast Address 1~4 case */ | |
56 | i = 0; | |
57 | netdev_for_each_mc_addr(ha, dev) { | |
58 | - if (i < MCAST_MAX) { | |
59 | - adrp = (u16 *) ha->addr; | |
60 | - iowrite16(adrp[0], ioaddr + MID_1L + 8 * i); | |
61 | - iowrite16(adrp[1], ioaddr + MID_1M + 8 * i); | |
62 | - iowrite16(adrp[2], ioaddr + MID_1H + 8 * i); | |
63 | - } else { | |
64 | - iowrite16(0xffff, ioaddr + MID_1L + 8 * i); | |
65 | - iowrite16(0xffff, ioaddr + MID_1M + 8 * i); | |
66 | - iowrite16(0xffff, ioaddr + MID_1H + 8 * i); | |
67 | - } | |
68 | + if (i >= MCAST_MAX) | |
69 | + break; | |
70 | + adrp = (u16 *) ha->addr; | |
71 | + iowrite16(adrp[0], ioaddr + MID_1L + 8 * i); | |
72 | + iowrite16(adrp[1], ioaddr + MID_1M + 8 * i); | |
73 | + iowrite16(adrp[2], ioaddr + MID_1H + 8 * i); | |
74 | + i++; | |
75 | + } | |
76 | + while (i < MCAST_MAX) { | |
77 | + iowrite16(0xffff, ioaddr + MID_1L + 8 * i); | |
78 | + iowrite16(0xffff, ioaddr + MID_1M + 8 * i); | |
79 | + iowrite16(0xffff, ioaddr + MID_1H + 8 * i); | |
80 | i++; | |
81 | } | |
82 | } |