diff options
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/cassini.c | 72 |
1 files changed, 35 insertions, 37 deletions
diff --git a/drivers/net/cassini.c b/drivers/net/cassini.c index ad47e5126fde..f90cac43130d 100644 --- a/drivers/net/cassini.c +++ b/drivers/net/cassini.c | |||
@@ -2999,6 +2999,40 @@ static inline void cas_init_dma(struct cas *cp) | |||
2999 | cas_init_rx_dma(cp); | 2999 | cas_init_rx_dma(cp); |
3000 | } | 3000 | } |
3001 | 3001 | ||
3002 | static void cas_process_mc_list(struct cas *cp) | ||
3003 | { | ||
3004 | u16 hash_table[16]; | ||
3005 | u32 crc; | ||
3006 | struct dev_mc_list *dmi; | ||
3007 | int i = 1; | ||
3008 | |||
3009 | memset(hash_table, 0, sizeof(hash_table)); | ||
3010 | netdev_for_each_mc_addr(dmi, cp->dev) { | ||
3011 | if (i <= CAS_MC_EXACT_MATCH_SIZE) { | ||
3012 | /* use the alternate mac address registers for the | ||
3013 | * first 15 multicast addresses | ||
3014 | */ | ||
3015 | writel((dmi->dmi_addr[4] << 8) | dmi->dmi_addr[5], | ||
3016 | cp->regs + REG_MAC_ADDRN(i*3 + 0)); | ||
3017 | writel((dmi->dmi_addr[2] << 8) | dmi->dmi_addr[3], | ||
3018 | cp->regs + REG_MAC_ADDRN(i*3 + 1)); | ||
3019 | writel((dmi->dmi_addr[0] << 8) | dmi->dmi_addr[1], | ||
3020 | cp->regs + REG_MAC_ADDRN(i*3 + 2)); | ||
3021 | i++; | ||
3022 | } | ||
3023 | else { | ||
3024 | /* use hw hash table for the next series of | ||
3025 | * multicast addresses | ||
3026 | */ | ||
3027 | crc = ether_crc_le(ETH_ALEN, dmi->dmi_addr); | ||
3028 | crc >>= 24; | ||
3029 | hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf)); | ||
3030 | } | ||
3031 | } | ||
3032 | for (i = 0; i < 16; i++) | ||
3033 | writel(hash_table[i], cp->regs + REG_MAC_HASH_TABLEN(i)); | ||
3034 | } | ||
3035 | |||
3002 | /* Must be invoked under cp->lock. */ | 3036 | /* Must be invoked under cp->lock. */ |
3003 | static u32 cas_setup_multicast(struct cas *cp) | 3037 | static u32 cas_setup_multicast(struct cas *cp) |
3004 | { | 3038 | { |
@@ -3014,43 +3048,7 @@ static u32 cas_setup_multicast(struct cas *cp) | |||
3014 | rxcfg |= MAC_RX_CFG_HASH_FILTER_EN; | 3048 | rxcfg |= MAC_RX_CFG_HASH_FILTER_EN; |
3015 | 3049 | ||
3016 | } else { | 3050 | } else { |
3017 | u16 hash_table[16]; | 3051 | cas_process_mc_list(cp); |
3018 | u32 crc; | ||
3019 | struct dev_mc_list *dmi = cp->dev->mc_list; | ||
3020 | int i; | ||
3021 | |||
3022 | /* use the alternate mac address registers for the | ||
3023 | * first 15 multicast addresses | ||
3024 | */ | ||
3025 | for (i = 1; i <= CAS_MC_EXACT_MATCH_SIZE; i++) { | ||
3026 | if (!dmi) { | ||
3027 | writel(0x0, cp->regs + REG_MAC_ADDRN(i*3 + 0)); | ||
3028 | writel(0x0, cp->regs + REG_MAC_ADDRN(i*3 + 1)); | ||
3029 | writel(0x0, cp->regs + REG_MAC_ADDRN(i*3 + 2)); | ||
3030 | continue; | ||
3031 | } | ||
3032 | writel((dmi->dmi_addr[4] << 8) | dmi->dmi_addr[5], | ||
3033 | cp->regs + REG_MAC_ADDRN(i*3 + 0)); | ||
3034 | writel((dmi->dmi_addr[2] << 8) | dmi->dmi_addr[3], | ||
3035 | cp->regs + REG_MAC_ADDRN(i*3 + 1)); | ||
3036 | writel((dmi->dmi_addr[0] << 8) | dmi->dmi_addr[1], | ||
3037 | cp->regs + REG_MAC_ADDRN(i*3 + 2)); | ||
3038 | dmi = dmi->next; | ||
3039 | } | ||
3040 | |||
3041 | /* use hw hash table for the next series of | ||
3042 | * multicast addresses | ||
3043 | */ | ||
3044 | memset(hash_table, 0, sizeof(hash_table)); | ||
3045 | while (dmi) { | ||
3046 | crc = ether_crc_le(ETH_ALEN, dmi->dmi_addr); | ||
3047 | crc >>= 24; | ||
3048 | hash_table[crc >> 4] |= 1 << (15 - (crc & 0xf)); | ||
3049 | dmi = dmi->next; | ||
3050 | } | ||
3051 | for (i=0; i < 16; i++) | ||
3052 | writel(hash_table[i], cp->regs + | ||
3053 | REG_MAC_HASH_TABLEN(i)); | ||
3054 | rxcfg |= MAC_RX_CFG_HASH_FILTER_EN; | 3052 | rxcfg |= MAC_RX_CFG_HASH_FILTER_EN; |
3055 | } | 3053 | } |
3056 | 3054 | ||