diff options
author | Stephen Hemminger <shemminger@osdl.org> | 2006-10-16 14:08:56 -0700 |
---|---|---|
committer | Chris Wright <chrisw@sous-sol.org> | 2006-11-03 17:33:45 -0800 |
commit | d5d6dc53434a53022b3f033436e67523b8f23ad6 (patch) | |
tree | 3c9289337dc06e587c6c50546e2bd0515209ee5d /drivers | |
parent | 45f08385d341d43927e936c69b5bdd4b07f1eb40 (diff) |
[PATCH] sky2: accept multicast pause frames
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>
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/net/sky2.c | 20 |
1 files changed, 15 insertions, 5 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c index 4661b1e5a8c6..99f3f36c1869 100644 --- a/drivers/net/sky2.c +++ b/drivers/net/sky2.c @@ -2745,6 +2745,14 @@ static int sky2_set_mac_address(struct net_device *dev, void *p) 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 net_device *dev) 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 net_device *dev) 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, |