aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/cassini.c72
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
3002static 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. */
3003static u32 cas_setup_multicast(struct cas *cp) 3037static 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