aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/cxgb4vf
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2010-12-08 16:15:38 -0500
committerDavid S. Miller <davem@davemloft.net>2010-12-08 16:47:38 -0500
commitfe6c791570efe717946ea7b7dd50aec96b70d551 (patch)
tree1becb5e8aea7a9c9a7d78f987bd73b0a5d8ee434 /drivers/net/cxgb4vf
parentf8bf5681cf15f77692c8ad8cb95d059ff7c622c9 (diff)
parentf19872575ff7819a3723154657a497d9bca66b33 (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
Conflicts: drivers/net/wireless/ath/ath9k/ar9003_eeprom.c net/llc/af_llc.c
Diffstat (limited to 'drivers/net/cxgb4vf')
-rw-r--r--drivers/net/cxgb4vf/cxgb4vf_main.c73
-rw-r--r--drivers/net/cxgb4vf/t4vf_hw.c94
2 files changed, 104 insertions, 63 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 */
820static inline int collect_netdev_uc_list_addrs(const struct net_device *dev, 821static 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 */
839static inline int collect_netdev_mc_list_addrs(const struct net_device *dev, 844static 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,
diff --git a/drivers/net/cxgb4vf/t4vf_hw.c b/drivers/net/cxgb4vf/t4vf_hw.c
index f7d7f976064b..35fc803a6a04 100644
--- a/drivers/net/cxgb4vf/t4vf_hw.c
+++ b/drivers/net/cxgb4vf/t4vf_hw.c
@@ -1014,48 +1014,72 @@ int t4vf_alloc_mac_filt(struct adapter *adapter, unsigned int viid, bool free,
1014 unsigned int naddr, const u8 **addr, u16 *idx, 1014 unsigned int naddr, const u8 **addr, u16 *idx,
1015 u64 *hash, bool sleep_ok) 1015 u64 *hash, bool sleep_ok)
1016{ 1016{
1017 int i, ret; 1017 int offset, ret = 0;
1018 unsigned nfilters = 0;
1019 unsigned int rem = naddr;
1018 struct fw_vi_mac_cmd cmd, rpl; 1020 struct fw_vi_mac_cmd cmd, rpl;
1019 struct fw_vi_mac_exact *p;
1020 size_t len16;
1021 1021
1022 if (naddr > ARRAY_SIZE(cmd.u.exact)) 1022 if (naddr > FW_CLS_TCAM_NUM_ENTRIES)
1023 return -EINVAL; 1023 return -EINVAL;
1024 len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd,
1025 u.exact[naddr]), 16);
1026 1024
1027 memset(&cmd, 0, sizeof(cmd)); 1025 for (offset = 0; offset < naddr; /**/) {
1028 cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_MAC_CMD) | 1026 unsigned int fw_naddr = (rem < ARRAY_SIZE(cmd.u.exact)
1029 FW_CMD_REQUEST | 1027 ? rem
1030 FW_CMD_WRITE | 1028 : ARRAY_SIZE(cmd.u.exact));
1031 (free ? FW_CMD_EXEC : 0) | 1029 size_t len16 = DIV_ROUND_UP(offsetof(struct fw_vi_mac_cmd,
1032 FW_VI_MAC_CMD_VIID(viid)); 1030 u.exact[fw_naddr]), 16);
1033 cmd.freemacs_to_len16 = cpu_to_be32(FW_VI_MAC_CMD_FREEMACS(free) | 1031 struct fw_vi_mac_exact *p;
1034 FW_CMD_LEN16(len16)); 1032 int i;
1035 1033
1036 for (i = 0, p = cmd.u.exact; i < naddr; i++, p++) { 1034 memset(&cmd, 0, sizeof(cmd));
1037 p->valid_to_idx = 1035 cmd.op_to_viid = cpu_to_be32(FW_CMD_OP(FW_VI_MAC_CMD) |
1038 cpu_to_be16(FW_VI_MAC_CMD_VALID | 1036 FW_CMD_REQUEST |
1039 FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC)); 1037 FW_CMD_WRITE |
1040 memcpy(p->macaddr, addr[i], sizeof(p->macaddr)); 1038 (free ? FW_CMD_EXEC : 0) |
1041 } 1039 FW_VI_MAC_CMD_VIID(viid));
1040 cmd.freemacs_to_len16 =
1041 cpu_to_be32(FW_VI_MAC_CMD_FREEMACS(free) |
1042 FW_CMD_LEN16(len16));
1043
1044 for (i = 0, p = cmd.u.exact; i < fw_naddr; i++, p++) {
1045 p->valid_to_idx = cpu_to_be16(
1046 FW_VI_MAC_CMD_VALID |
1047 FW_VI_MAC_CMD_IDX(FW_VI_MAC_ADD_MAC));
1048 memcpy(p->macaddr, addr[offset+i], sizeof(p->macaddr));
1049 }
1050
1051
1052 ret = t4vf_wr_mbox_core(adapter, &cmd, sizeof(cmd), &rpl,
1053 sleep_ok);
1054 if (ret && ret != -ENOMEM)
1055 break;
1042 1056
1043 ret = t4vf_wr_mbox_core(adapter, &cmd, sizeof(cmd), &rpl, sleep_ok); 1057 for (i = 0, p = rpl.u.exact; i < fw_naddr; i++, p++) {
1044 if (ret) 1058 u16 index = FW_VI_MAC_CMD_IDX_GET(
1045 return ret; 1059 be16_to_cpu(p->valid_to_idx));
1046 1060
1047 for (i = 0, p = rpl.u.exact; i < naddr; i++, p++) { 1061 if (idx)
1048 u16 index = FW_VI_MAC_CMD_IDX_GET(be16_to_cpu(p->valid_to_idx)); 1062 idx[offset+i] =
1049 1063 (index >= FW_CLS_TCAM_NUM_ENTRIES
1050 if (idx) 1064 ? 0xffff
1051 idx[i] = (index >= FW_CLS_TCAM_NUM_ENTRIES 1065 : index);
1052 ? 0xffff 1066 if (index < FW_CLS_TCAM_NUM_ENTRIES)
1053 : index); 1067 nfilters++;
1054 if (index < FW_CLS_TCAM_NUM_ENTRIES) 1068 else if (hash)
1055 ret++; 1069 *hash |= (1ULL << hash_mac_addr(addr[offset+i]));
1056 else if (hash) 1070 }
1057 *hash |= (1 << hash_mac_addr(addr[i])); 1071
1072 free = false;
1073 offset += fw_naddr;
1074 rem -= fw_naddr;
1058 } 1075 }
1076
1077 /*
1078 * If there were no errors or we merely ran out of room in our MAC
1079 * address arena, return the number of filters actually written.
1080 */
1081 if (ret == 0 || ret == -ENOMEM)
1082 ret = nfilters;
1059 return ret; 1083 return ret;
1060} 1084}
1061 1085