diff options
Diffstat (limited to 'drivers/net/cxgb4vf/cxgb4vf_main.c')
-rw-r--r-- | drivers/net/cxgb4vf/cxgb4vf_main.c | 73 |
1 files changed, 45 insertions, 28 deletions
diff --git a/drivers/net/cxgb4vf/cxgb4vf_main.c b/drivers/net/cxgb4vf/cxgb4vf_main.c index 9246d2fa6cf9..f54af48edb93 100644 --- a/drivers/net/cxgb4vf/cxgb4vf_main.c +++ b/drivers/net/cxgb4vf/cxgb4vf_main.c | |||
@@ -814,40 +814,48 @@ static struct net_device_stats *cxgb4vf_get_stats(struct net_device *dev) | |||
814 | } | 814 | } |
815 | 815 | ||
816 | /* | 816 | /* |
817 | * Collect up to maxaddrs worth of a netdevice's unicast addresses into an | 817 | * Collect up to maxaddrs worth of a netdevice's unicast addresses, starting |
818 | * array of addrss pointers and return the number collected. | 818 | * at a specified offset within the list, into an array of addrss pointers and |
819 | * return the number collected. | ||
819 | */ | 820 | */ |
820 | static inline int collect_netdev_uc_list_addrs(const struct net_device *dev, | 821 | static inline unsigned int collect_netdev_uc_list_addrs(const struct net_device *dev, |
821 | const u8 **addr, | 822 | const u8 **addr, |
822 | unsigned int maxaddrs) | 823 | unsigned int offset, |
824 | unsigned int maxaddrs) | ||
823 | { | 825 | { |
826 | unsigned int index = 0; | ||
824 | unsigned int naddr = 0; | 827 | unsigned int naddr = 0; |
825 | const struct netdev_hw_addr *ha; | 828 | const struct netdev_hw_addr *ha; |
826 | 829 | ||
827 | for_each_dev_addr(dev, ha) { | 830 | for_each_dev_addr(dev, ha) |
828 | addr[naddr++] = ha->addr; | 831 | if (index++ >= offset) { |
829 | if (naddr >= maxaddrs) | 832 | addr[naddr++] = ha->addr; |
830 | break; | 833 | if (naddr >= maxaddrs) |
831 | } | 834 | break; |
835 | } | ||
832 | return naddr; | 836 | return naddr; |
833 | } | 837 | } |
834 | 838 | ||
835 | /* | 839 | /* |
836 | * Collect up to maxaddrs worth of a netdevice's multicast addresses into an | 840 | * Collect up to maxaddrs worth of a netdevice's multicast addresses, starting |
837 | * array of addrss pointers and return the number collected. | 841 | * at a specified offset within the list, into an array of addrss pointers and |
842 | * return the number collected. | ||
838 | */ | 843 | */ |
839 | static inline int collect_netdev_mc_list_addrs(const struct net_device *dev, | 844 | static inline unsigned int collect_netdev_mc_list_addrs(const struct net_device *dev, |
840 | const u8 **addr, | 845 | const u8 **addr, |
841 | unsigned int maxaddrs) | 846 | unsigned int offset, |
847 | unsigned int maxaddrs) | ||
842 | { | 848 | { |
849 | unsigned int index = 0; | ||
843 | unsigned int naddr = 0; | 850 | unsigned int naddr = 0; |
844 | const struct netdev_hw_addr *ha; | 851 | const struct netdev_hw_addr *ha; |
845 | 852 | ||
846 | netdev_for_each_mc_addr(ha, dev) { | 853 | netdev_for_each_mc_addr(ha, dev) |
847 | addr[naddr++] = ha->addr; | 854 | if (index++ >= offset) { |
848 | if (naddr >= maxaddrs) | 855 | addr[naddr++] = ha->addr; |
849 | break; | 856 | if (naddr >= maxaddrs) |
850 | } | 857 | break; |
858 | } | ||
851 | return naddr; | 859 | return naddr; |
852 | } | 860 | } |
853 | 861 | ||
@@ -860,16 +868,20 @@ static int set_addr_filters(const struct net_device *dev, bool sleep) | |||
860 | u64 mhash = 0; | 868 | u64 mhash = 0; |
861 | u64 uhash = 0; | 869 | u64 uhash = 0; |
862 | bool free = true; | 870 | bool free = true; |
863 | u16 filt_idx[7]; | 871 | unsigned int offset, naddr; |
864 | const u8 *addr[7]; | 872 | const u8 *addr[7]; |
865 | int ret, naddr = 0; | 873 | int ret; |
866 | const struct port_info *pi = netdev_priv(dev); | 874 | const struct port_info *pi = netdev_priv(dev); |
867 | 875 | ||
868 | /* first do the secondary unicast addresses */ | 876 | /* first do the secondary unicast addresses */ |
869 | naddr = collect_netdev_uc_list_addrs(dev, addr, ARRAY_SIZE(addr)); | 877 | for (offset = 0; ; offset += naddr) { |
870 | if (naddr > 0) { | 878 | naddr = collect_netdev_uc_list_addrs(dev, addr, offset, |
879 | ARRAY_SIZE(addr)); | ||
880 | if (naddr == 0) | ||
881 | break; | ||
882 | |||
871 | ret = t4vf_alloc_mac_filt(pi->adapter, pi->viid, free, | 883 | ret = t4vf_alloc_mac_filt(pi->adapter, pi->viid, free, |
872 | naddr, addr, filt_idx, &uhash, sleep); | 884 | naddr, addr, NULL, &uhash, sleep); |
873 | if (ret < 0) | 885 | if (ret < 0) |
874 | return ret; | 886 | return ret; |
875 | 887 | ||
@@ -877,12 +889,17 @@ static int set_addr_filters(const struct net_device *dev, bool sleep) | |||
877 | } | 889 | } |
878 | 890 | ||
879 | /* next set up the multicast addresses */ | 891 | /* next set up the multicast addresses */ |
880 | naddr = collect_netdev_mc_list_addrs(dev, addr, ARRAY_SIZE(addr)); | 892 | for (offset = 0; ; offset += naddr) { |
881 | if (naddr > 0) { | 893 | naddr = collect_netdev_mc_list_addrs(dev, addr, offset, |
894 | ARRAY_SIZE(addr)); | ||
895 | if (naddr == 0) | ||
896 | break; | ||
897 | |||
882 | ret = t4vf_alloc_mac_filt(pi->adapter, pi->viid, free, | 898 | ret = t4vf_alloc_mac_filt(pi->adapter, pi->viid, free, |
883 | naddr, addr, filt_idx, &mhash, sleep); | 899 | naddr, addr, NULL, &mhash, sleep); |
884 | if (ret < 0) | 900 | if (ret < 0) |
885 | return ret; | 901 | return ret; |
902 | free = false; | ||
886 | } | 903 | } |
887 | 904 | ||
888 | return t4vf_set_addr_hash(pi->adapter, pi->viid, uhash != 0, | 905 | return t4vf_set_addr_hash(pi->adapter, pi->viid, uhash != 0, |