aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/skge.c43
-rw-r--r--drivers/net/skge.h3
2 files changed, 33 insertions, 13 deletions
diff --git a/drivers/net/skge.c b/drivers/net/skge.c
index c3d2e0a2c4e6..f59f37aaccec 100644
--- a/drivers/net/skge.c
+++ b/drivers/net/skge.c
@@ -2767,6 +2767,17 @@ static int skge_change_mtu(struct net_device *dev, int new_mtu)
2767 return err; 2767 return err;
2768} 2768}
2769 2769
2770static const u8 pause_mc_addr[ETH_ALEN] = { 0x1, 0x80, 0xc2, 0x0, 0x0, 0x1 };
2771
2772static void genesis_add_filter(u8 filter[8], const u8 *addr)
2773{
2774 u32 crc, bit;
2775
2776 crc = ether_crc_le(ETH_ALEN, addr);
2777 bit = ~crc & 0x3f;
2778 filter[bit/8] |= 1 << (bit%8);
2779}
2780
2770static void genesis_set_multicast(struct net_device *dev) 2781static void genesis_set_multicast(struct net_device *dev)
2771{ 2782{
2772 struct skge_port *skge = netdev_priv(dev); 2783 struct skge_port *skge = netdev_priv(dev);
@@ -2788,24 +2799,33 @@ static void genesis_set_multicast(struct net_device *dev)
2788 memset(filter, 0xff, sizeof(filter)); 2799 memset(filter, 0xff, sizeof(filter));
2789 else { 2800 else {
2790 memset(filter, 0, sizeof(filter)); 2801 memset(filter, 0, sizeof(filter));
2791 for (i = 0; list && i < count; i++, list = list->next) { 2802
2792 u32 crc, bit; 2803 if (skge->flow_status == FLOW_STAT_REM_SEND
2793 crc = ether_crc_le(ETH_ALEN, list->dmi_addr); 2804 || skge->flow_status == FLOW_STAT_SYMMETRIC)
2794 bit = ~crc & 0x3f; 2805 genesis_add_filter(filter, pause_mc_addr);
2795 filter[bit/8] |= 1 << (bit%8); 2806
2796 } 2807 for (i = 0; list && i < count; i++, list = list->next)
2808 genesis_add_filter(filter, list->dmi_addr);
2797 } 2809 }
2798 2810
2799 xm_write32(hw, port, XM_MODE, mode); 2811 xm_write32(hw, port, XM_MODE, mode);
2800 xm_outhash(hw, port, XM_HSM, filter); 2812 xm_outhash(hw, port, XM_HSM, filter);
2801} 2813}
2802 2814
2815static void yukon_add_filter(u8 filter[8], const u8 *addr)
2816{
2817 u32 bit = ether_crc(ETH_ALEN, addr) & 0x3f;
2818 filter[bit/8] |= 1 << (bit%8);
2819}
2820
2803static void yukon_set_multicast(struct net_device *dev) 2821static void yukon_set_multicast(struct net_device *dev)
2804{ 2822{
2805 struct skge_port *skge = netdev_priv(dev); 2823 struct skge_port *skge = netdev_priv(dev);
2806 struct skge_hw *hw = skge->hw; 2824 struct skge_hw *hw = skge->hw;
2807 int port = skge->port; 2825 int port = skge->port;
2808 struct dev_mc_list *list = dev->mc_list; 2826 struct dev_mc_list *list = dev->mc_list;
2827 int rx_pause = (skge->flow_status == FLOW_STAT_REM_SEND
2828 || skge->flow_status == FLOW_STAT_SYMMETRIC);
2809 u16 reg; 2829 u16 reg;
2810 u8 filter[8]; 2830 u8 filter[8];
2811 2831
@@ -2818,16 +2838,17 @@ static void yukon_set_multicast(struct net_device *dev)
2818 reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA); 2838 reg &= ~(GM_RXCR_UCF_ENA | GM_RXCR_MCF_ENA);
2819 else if (dev->flags & IFF_ALLMULTI) /* all multicast */ 2839 else if (dev->flags & IFF_ALLMULTI) /* all multicast */
2820 memset(filter, 0xff, sizeof(filter)); 2840 memset(filter, 0xff, sizeof(filter));
2821 else if (dev->mc_count == 0) /* no multicast */ 2841 else if (dev->mc_count == 0 && !rx_pause)/* no multicast */
2822 reg &= ~GM_RXCR_MCF_ENA; 2842 reg &= ~GM_RXCR_MCF_ENA;
2823 else { 2843 else {
2824 int i; 2844 int i;
2825 reg |= GM_RXCR_MCF_ENA; 2845 reg |= GM_RXCR_MCF_ENA;
2826 2846
2827 for (i = 0; list && i < dev->mc_count; i++, list = list->next) { 2847 if (rx_pause)
2828 u32 bit = ether_crc(ETH_ALEN, list->dmi_addr) & 0x3f; 2848 yukon_add_filter(filter, pause_mc_addr);
2829 filter[bit/8] |= 1 << (bit%8); 2849
2830 } 2850 for (i = 0; list && i < dev->mc_count; i++, list = list->next)
2851 yukon_add_filter(filter, list->dmi_addr);
2831 } 2852 }
2832 2853
2833 2854
diff --git a/drivers/net/skge.h b/drivers/net/skge.h
index 17b1b479dff5..e9354dfa7e9a 100644
--- a/drivers/net/skge.h
+++ b/drivers/net/skge.h
@@ -1849,8 +1849,7 @@ enum {
1849 GMR_FS_JABBER, 1849 GMR_FS_JABBER,
1850/* Rx GMAC FIFO Flush Mask (default) */ 1850/* Rx GMAC FIFO Flush Mask (default) */
1851 RX_FF_FL_DEF_MSK = GMR_FS_CRC_ERR | GMR_FS_RX_FF_OV |GMR_FS_MII_ERR | 1851 RX_FF_FL_DEF_MSK = GMR_FS_CRC_ERR | GMR_FS_RX_FF_OV |GMR_FS_MII_ERR |
1852 GMR_FS_BAD_FC | GMR_FS_GOOD_FC | GMR_FS_UN_SIZE | 1852 GMR_FS_BAD_FC | GMR_FS_UN_SIZE | GMR_FS_JABBER,
1853 GMR_FS_JABBER,
1854}; 1853};
1855 1854
1856/* RX_GMF_CTRL_T 32 bit Rx GMAC FIFO Control/Test */ 1855/* RX_GMF_CTRL_T 32 bit Rx GMAC FIFO Control/Test */