aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/sky2.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/sky2.c')
-rw-r--r--drivers/net/sky2.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/drivers/net/sky2.c b/drivers/net/sky2.c
index c19338351780..67ecd66f26d6 100644
--- a/drivers/net/sky2.c
+++ b/drivers/net/sky2.c
@@ -2850,6 +2850,14 @@ static int sky2_set_mac_address(struct net_device *dev, void *p)
2850 return 0; 2850 return 0;
2851} 2851}
2852 2852
2853static void inline sky2_add_filter(u8 filter[8], const u8 *addr)
2854{
2855 u32 bit;
2856
2857 bit = ether_crc(ETH_ALEN, addr) & 63;
2858 filter[bit >> 3] |= 1 << (bit & 7);
2859}
2860
2853static void sky2_set_multicast(struct net_device *dev) 2861static void sky2_set_multicast(struct net_device *dev)
2854{ 2862{
2855 struct sky2_port *sky2 = netdev_priv(dev); 2863 struct sky2_port *sky2 = netdev_priv(dev);
@@ -2858,7 +2866,10 @@ static void sky2_set_multicast(struct net_device *dev)
2858 struct dev_mc_list *list = dev->mc_list; 2866 struct dev_mc_list *list = dev->mc_list;
2859 u16 reg; 2867 u16 reg;
2860 u8 filter[8]; 2868 u8 filter[8];
2869 int rx_pause;
2870 static const u8 pause_mc_addr[ETH_ALEN] = { 0x1, 0x80, 0xc2, 0x0, 0x0, 0x1 };
2861 2871
2872 rx_pause = (sky2->flow_status == FC_RX || sky2->flow_status == FC_BOTH);
2862 memset(filter, 0, sizeof(filter)); 2873 memset(filter, 0, sizeof(filter));
2863 2874
2864 reg = gma_read16(hw, port, GM_RX_CTRL); 2875 reg = gma_read16(hw, port, GM_RX_CTRL);
@@ -2866,18 +2877,19 @@ static void sky2_set_multicast(struct net_device *dev)
2866 2877
2867 if (dev->flags & IFF_PROMISC) /* promiscuous */ 2878 if (dev->flags & IFF_PROMISC) /* promiscuous */
2868 reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); 2879 reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
2869 else if ((dev->flags & IFF_ALLMULTI) || dev->mc_count > 16) /* all multicast */ 2880 else if (dev->flags & IFF_ALLMULTI)
2870 memset(filter, 0xff, sizeof(filter)); 2881 memset(filter, 0xff, sizeof(filter));
2871 else if (dev->mc_count == 0) /* no multicast */ 2882 else if (dev->mc_count == 0 && !rx_pause)
2872 reg &= ~GM_RXCR_MCF_ENA; 2883 reg &= ~GM_RXCR_MCF_ENA;
2873 else { 2884 else {
2874 int i; 2885 int i;
2875 reg |= GM_RXCR_MCF_ENA; 2886 reg |= GM_RXCR_MCF_ENA;
2876 2887
2877 for (i = 0; list && i < dev->mc_count; i++, list = list->next) { 2888 if (rx_pause)
2878 u32 bit = ether_crc(ETH_ALEN, list->dmi_addr) & 0x3f; 2889 sky2_add_filter(filter, pause_mc_addr);
2879 filter[bit / 8] |= 1 << (bit % 8); 2890
2880 } 2891 for (i = 0; list && i < dev->mc_count; i++, list = list->next)
2892 sky2_add_filter(filter, list->dmi_addr);
2881 } 2893 }
2882 2894
2883 gma_write16(hw, port, GM_MC_ADDR_H1, 2895 gma_write16(hw, port, GM_MC_ADDR_H1,