blob: a28467805599240f01a0427cf34ce27914a0ffab [file]
From stable-bounces@linux.kernel.org Mon Oct 16 15:29:40 2006
Date: Mon, 16 Oct 2006 14:08:56 -0700
From: Stephen Hemminger <shemminger@osdl.org>
To: stable@kernel.org
Message-ID: <20061016140856.2f8b3907@freekitty>
Mime-Version: 1.0
Subject: sky2: accept multicast pause frames
Content-Type: text/plain; charset="us-ascii"
From: Stephen Hemminger <shemminger@osdl.org>
When using flow control, the PHY needs to accept multicast pause frames.
Without this fix, these frames were getting discarded by the PHY before
doing any flow control.
Signed-off-by: Stephen Hemminger <shemminger@osdl.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Signed-off-by: Chris Wright <chrisw@sous-sol.org>
---
drivers/net/sky2.c | 20 +++++++++++++++-----
1 file changed, 15 insertions(+), 5 deletions(-)
--- linux-2.6.18.1.orig/drivers/net/sky2.c
+++ linux-2.6.18.1/drivers/net/sky2.c
@@ -2745,6 +2745,14 @@ static int sky2_set_mac_address(struct n
return 0;
}
+static void inline sky2_add_filter(u8 filter[8], const u8 *addr)
+{
+ u32 bit;
+
+ bit = ether_crc(ETH_ALEN, addr) & 63;
+ filter[bit >> 3] |= 1 << (bit & 7);
+}
+
static void sky2_set_multicast(struct net_device *dev)
{
struct sky2_port *sky2 = netdev_priv(dev);
@@ -2753,6 +2761,7 @@ static void sky2_set_multicast(struct ne
struct dev_mc_list *list = dev->mc_list;
u16 reg;
u8 filter[8];
+ static const u8 pause_mc_addr[ETH_ALEN] = { 0x1, 0x80, 0xc2, 0x0, 0x0, 0x1 };
memset(filter, 0, sizeof(filter));
@@ -2763,16 +2772,17 @@ static void sky2_set_multicast(struct ne
reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > 16) /* all multicast */
memset(filter, 0xff, sizeof(filter));
- else if (dev->mc_count == 0) /* no multicast */
+ else if (dev->mc_count == 0 && !sky2->rx_pause)
reg &= ~GM_RXCR_MCF_ENA;
else {
int i;
reg |= GM_RXCR_MCF_ENA;
- for (i = 0; list && i < dev->mc_count; i++, list = list->next) {
- u32 bit = ether_crc(ETH_ALEN, list->dmi_addr) & 0x3f;
- filter[bit / 8] |= 1 << (bit % 8);
- }
+ if (sky2->rx_pause)
+ sky2_add_filter(filter, pause_mc_addr);
+
+ for (i = 0; list && i < dev->mc_count; i++, list = list->next)
+ sky2_add_filter(filter, list->dmi_addr);
}
gma_write16(hw, port, GM_MC_ADDR_H1,