From 6a541b7523e44d53ea0c354939f035c335afaf11 Mon Sep 17 00:00:00 2001 From: Aidan Williams Date: Wed, 30 Jan 2008 16:52:23 +0800 Subject: [PATCH] --- yaml --- r: 82689 b: refs/heads/master c: 775919bc23880f250ca1029a6420187ee4bb5b26 h: refs/heads/master i: 82687: 2fedd354574f7338045ec54f5d7a758514dc635a v: v3 --- [refs] | 2 +- trunk/drivers/net/bfin_mac.c | 42 +++++++++++++++++++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/[refs] b/[refs] index 877eff0e2f05..39900ab901c8 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 7cc8f38188133e0c278b9f207d63c2c2b4d98236 +refs/heads/master: 775919bc23880f250ca1029a6420187ee4bb5b26 diff --git a/trunk/drivers/net/bfin_mac.c b/trunk/drivers/net/bfin_mac.c index ee398196ea80..c6586cdb8b95 100644 --- a/trunk/drivers/net/bfin_mac.c +++ b/trunk/drivers/net/bfin_mac.c @@ -11,6 +11,7 @@ * Description: * * Modified: + * 2006-12-19 Aidan Williams, multicast hash support * Copyright 2004-2006 Analog Devices Inc. * * Bugs: Enter bugs at http://blackfin.uclinux.org/ @@ -800,6 +801,39 @@ static void bf537mac_timeout(struct net_device *dev) netif_wake_queue(dev); } +static void bf537mac_multicast_hash(struct net_device *dev) +{ + u32 emac_hashhi, emac_hashlo; + struct dev_mc_list *dmi = dev->mc_list; + char *addrs; + int i; + u32 crc; + + emac_hashhi = emac_hashlo = 0; + + for (i = 0; i < dev->mc_count; i++) { + addrs = dmi->dmi_addr; + dmi = dmi->next; + + /* skip non-multicast addresses */ + if (!(*addrs & 1)) + continue; + + crc = ether_crc(ETH_ALEN, addrs); + crc >>= 26; + + if (crc & 0x20) + emac_hashhi |= 1 << (crc & 0x1f); + else + emac_hashlo |= 1 << (crc & 0x1f); + } + + bfin_write_EMAC_HASHHI(emac_hashhi); + bfin_write_EMAC_HASHLO(emac_hashlo); + + return; +} + /* * This routine will, depending on the values passed to it, * either make it accept multicast packets, go into @@ -815,11 +849,17 @@ static void bf537mac_set_multicast_list(struct net_device *dev) sysctl = bfin_read_EMAC_OPMODE(); sysctl |= RAF; bfin_write_EMAC_OPMODE(sysctl); - } else if (dev->flags & IFF_ALLMULTI || dev->mc_count) { + } else if (dev->flags & IFF_ALLMULTI) { /* accept all multicast */ sysctl = bfin_read_EMAC_OPMODE(); sysctl |= PAM; bfin_write_EMAC_OPMODE(sysctl); + } else if (dev->mc_count) { + /* set up multicast hash table */ + sysctl = bfin_read_EMAC_OPMODE(); + sysctl |= HM; + bfin_write_EMAC_OPMODE(sysctl); + bf537mac_multicast_hash(dev); } else { /* clear promisc or multicast mode */ sysctl = bfin_read_EMAC_OPMODE();