| 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, |