diff options
-rw-r--r-- | drivers/net/skge.c | 43 | ||||
-rw-r--r-- | drivers/net/skge.h | 3 |
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 | ||
2770 | static const u8 pause_mc_addr[ETH_ALEN] = { 0x1, 0x80, 0xc2, 0x0, 0x0, 0x1 }; | ||
2771 | |||
2772 | static 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 | |||
2770 | static void genesis_set_multicast(struct net_device *dev) | 2781 | static 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 | ||
2815 | static 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 | |||
2803 | static void yukon_set_multicast(struct net_device *dev) | 2821 | static 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 */ |