diff options
author | Aidan Williams <aidan@nicta.com.au> | 2008-01-30 03:52:23 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-02-03 07:28:47 -0500 |
commit | 775919bc23880f250ca1029a6420187ee4bb5b26 (patch) | |
tree | 1dc0ce2d7f978ea912cea8bfcc2c540f682b308e /drivers/net/bfin_mac.c | |
parent | 7cc8f38188133e0c278b9f207d63c2c2b4d98236 (diff) |
EMAC driver: bf537 MAC multicast hash filtering patch
The bf537 Ethernet MAC driver in the 2007R1.1-RC3 kernel (and the
current kernel) do not implement multicast hash filtering. This
is a performance problem if you have lots of multicast on your network.
This patch plugs the right bits into the multicast hash registers.
Signed-off-by: Aidan Williams <aidan@nicta.com.au>
Signed-off-by: Bryan Wu <bryan.wu@analog.com>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/bfin_mac.c')
-rw-r--r-- | drivers/net/bfin_mac.c | 42 |
1 files changed, 41 insertions, 1 deletions
diff --git a/drivers/net/bfin_mac.c b/drivers/net/bfin_mac.c index ee398196ea80..c6586cdb8b95 100644 --- a/drivers/net/bfin_mac.c +++ b/drivers/net/bfin_mac.c | |||
@@ -11,6 +11,7 @@ | |||
11 | * Description: | 11 | * Description: |
12 | * | 12 | * |
13 | * Modified: | 13 | * Modified: |
14 | * 2006-12-19 Aidan Williams, multicast hash support | ||
14 | * Copyright 2004-2006 Analog Devices Inc. | 15 | * Copyright 2004-2006 Analog Devices Inc. |
15 | * | 16 | * |
16 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ | 17 | * Bugs: Enter bugs at http://blackfin.uclinux.org/ |
@@ -800,6 +801,39 @@ static void bf537mac_timeout(struct net_device *dev) | |||
800 | netif_wake_queue(dev); | 801 | netif_wake_queue(dev); |
801 | } | 802 | } |
802 | 803 | ||
804 | static void bf537mac_multicast_hash(struct net_device *dev) | ||
805 | { | ||
806 | u32 emac_hashhi, emac_hashlo; | ||
807 | struct dev_mc_list *dmi = dev->mc_list; | ||
808 | char *addrs; | ||
809 | int i; | ||
810 | u32 crc; | ||
811 | |||
812 | emac_hashhi = emac_hashlo = 0; | ||
813 | |||
814 | for (i = 0; i < dev->mc_count; i++) { | ||
815 | addrs = dmi->dmi_addr; | ||
816 | dmi = dmi->next; | ||
817 | |||
818 | /* skip non-multicast addresses */ | ||
819 | if (!(*addrs & 1)) | ||
820 | continue; | ||
821 | |||
822 | crc = ether_crc(ETH_ALEN, addrs); | ||
823 | crc >>= 26; | ||
824 | |||
825 | if (crc & 0x20) | ||
826 | emac_hashhi |= 1 << (crc & 0x1f); | ||
827 | else | ||
828 | emac_hashlo |= 1 << (crc & 0x1f); | ||
829 | } | ||
830 | |||
831 | bfin_write_EMAC_HASHHI(emac_hashhi); | ||
832 | bfin_write_EMAC_HASHLO(emac_hashlo); | ||
833 | |||
834 | return; | ||
835 | } | ||
836 | |||
803 | /* | 837 | /* |
804 | * This routine will, depending on the values passed to it, | 838 | * This routine will, depending on the values passed to it, |
805 | * either make it accept multicast packets, go into | 839 | * either make it accept multicast packets, go into |
@@ -815,11 +849,17 @@ static void bf537mac_set_multicast_list(struct net_device *dev) | |||
815 | sysctl = bfin_read_EMAC_OPMODE(); | 849 | sysctl = bfin_read_EMAC_OPMODE(); |
816 | sysctl |= RAF; | 850 | sysctl |= RAF; |
817 | bfin_write_EMAC_OPMODE(sysctl); | 851 | bfin_write_EMAC_OPMODE(sysctl); |
818 | } else if (dev->flags & IFF_ALLMULTI || dev->mc_count) { | 852 | } else if (dev->flags & IFF_ALLMULTI) { |
819 | /* accept all multicast */ | 853 | /* accept all multicast */ |
820 | sysctl = bfin_read_EMAC_OPMODE(); | 854 | sysctl = bfin_read_EMAC_OPMODE(); |
821 | sysctl |= PAM; | 855 | sysctl |= PAM; |
822 | bfin_write_EMAC_OPMODE(sysctl); | 856 | bfin_write_EMAC_OPMODE(sysctl); |
857 | } else if (dev->mc_count) { | ||
858 | /* set up multicast hash table */ | ||
859 | sysctl = bfin_read_EMAC_OPMODE(); | ||
860 | sysctl |= HM; | ||
861 | bfin_write_EMAC_OPMODE(sysctl); | ||
862 | bf537mac_multicast_hash(dev); | ||
823 | } else { | 863 | } else { |
824 | /* clear promisc or multicast mode */ | 864 | /* clear promisc or multicast mode */ |
825 | sysctl = bfin_read_EMAC_OPMODE(); | 865 | sysctl = bfin_read_EMAC_OPMODE(); |