aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/sfc
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/sfc')
-rw-r--r--drivers/net/ethernet/sfc/ethtool.c211
-rw-r--r--drivers/net/ethernet/sfc/filter.c455
-rw-r--r--drivers/net/ethernet/sfc/filter.h220
3 files changed, 494 insertions, 392 deletions
diff --git a/drivers/net/ethernet/sfc/ethtool.c b/drivers/net/ethernet/sfc/ethtool.c
index ec5cacd427ec..58ae28b8820d 100644
--- a/drivers/net/ethernet/sfc/ethtool.c
+++ b/drivers/net/ethernet/sfc/ethtool.c
@@ -799,11 +799,12 @@ static int efx_ethtool_reset(struct net_device *net_dev, u32 *flags)
799 return efx_reset(efx, rc); 799 return efx_reset(efx, rc);
800} 800}
801 801
802/* MAC address mask including only MC flag */ 802/* MAC address mask including only I/G bit */
803static const u8 mac_addr_mc_mask[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 }; 803static const u8 mac_addr_ig_mask[ETH_ALEN] = { 0x01, 0, 0, 0, 0, 0 };
804 804
805#define IP4_ADDR_FULL_MASK ((__force __be32)~0) 805#define IP4_ADDR_FULL_MASK ((__force __be32)~0)
806#define PORT_FULL_MASK ((__force __be16)~0) 806#define PORT_FULL_MASK ((__force __be16)~0)
807#define ETHER_TYPE_FULL_MASK ((__force __be16)~0)
807 808
808static int efx_ethtool_get_class_rule(struct efx_nic *efx, 809static int efx_ethtool_get_class_rule(struct efx_nic *efx,
809 struct ethtool_rx_flow_spec *rule) 810 struct ethtool_rx_flow_spec *rule)
@@ -813,8 +814,6 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx,
813 struct ethhdr *mac_entry = &rule->h_u.ether_spec; 814 struct ethhdr *mac_entry = &rule->h_u.ether_spec;
814 struct ethhdr *mac_mask = &rule->m_u.ether_spec; 815 struct ethhdr *mac_mask = &rule->m_u.ether_spec;
815 struct efx_filter_spec spec; 816 struct efx_filter_spec spec;
816 u16 vid;
817 u8 proto;
818 int rc; 817 int rc;
819 818
820 rc = efx_filter_get_filter_safe(efx, EFX_FILTER_PRI_MANUAL, 819 rc = efx_filter_get_filter_safe(efx, EFX_FILTER_PRI_MANUAL,
@@ -827,39 +826,67 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx,
827 else 826 else
828 rule->ring_cookie = spec.dmaq_id; 827 rule->ring_cookie = spec.dmaq_id;
829 828
830 if (spec.type == EFX_FILTER_MC_DEF || spec.type == EFX_FILTER_UC_DEF) { 829 if ((spec.match_flags & EFX_FILTER_MATCH_ETHER_TYPE) &&
831 rule->flow_type = ETHER_FLOW; 830 spec.ether_type == htons(ETH_P_IP) &&
832 memcpy(mac_mask->h_dest, mac_addr_mc_mask, ETH_ALEN); 831 (spec.match_flags & EFX_FILTER_MATCH_IP_PROTO) &&
833 if (spec.type == EFX_FILTER_MC_DEF) 832 (spec.ip_proto == IPPROTO_TCP || spec.ip_proto == IPPROTO_UDP) &&
834 memcpy(mac_entry->h_dest, mac_addr_mc_mask, ETH_ALEN); 833 !(spec.match_flags &
835 return 0; 834 ~(EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_OUTER_VID |
836 } 835 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_REM_HOST |
837 836 EFX_FILTER_MATCH_IP_PROTO |
838 rc = efx_filter_get_eth_local(&spec, &vid, mac_entry->h_dest); 837 EFX_FILTER_MATCH_LOC_PORT | EFX_FILTER_MATCH_REM_PORT))) {
839 if (rc == 0) { 838 rule->flow_type = ((spec.ip_proto == IPPROTO_TCP) ?
839 TCP_V4_FLOW : UDP_V4_FLOW);
840 if (spec.match_flags & EFX_FILTER_MATCH_LOC_HOST) {
841 ip_entry->ip4dst = spec.loc_host[0];
842 ip_mask->ip4dst = IP4_ADDR_FULL_MASK;
843 }
844 if (spec.match_flags & EFX_FILTER_MATCH_REM_HOST) {
845 ip_entry->ip4src = spec.rem_host[0];
846 ip_mask->ip4src = IP4_ADDR_FULL_MASK;
847 }
848 if (spec.match_flags & EFX_FILTER_MATCH_LOC_PORT) {
849 ip_entry->pdst = spec.loc_port;
850 ip_mask->pdst = PORT_FULL_MASK;
851 }
852 if (spec.match_flags & EFX_FILTER_MATCH_REM_PORT) {
853 ip_entry->psrc = spec.rem_port;
854 ip_mask->psrc = PORT_FULL_MASK;
855 }
856 } else if (!(spec.match_flags &
857 ~(EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_LOC_MAC_IG |
858 EFX_FILTER_MATCH_REM_MAC | EFX_FILTER_MATCH_ETHER_TYPE |
859 EFX_FILTER_MATCH_OUTER_VID))) {
840 rule->flow_type = ETHER_FLOW; 860 rule->flow_type = ETHER_FLOW;
841 memset(mac_mask->h_dest, ~0, ETH_ALEN); 861 if (spec.match_flags &
842 if (vid != EFX_FILTER_VID_UNSPEC) { 862 (EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_LOC_MAC_IG)) {
843 rule->flow_type |= FLOW_EXT; 863 memcpy(mac_entry->h_dest, spec.loc_mac, ETH_ALEN);
844 rule->h_ext.vlan_tci = htons(vid); 864 if (spec.match_flags & EFX_FILTER_MATCH_LOC_MAC)
845 rule->m_ext.vlan_tci = htons(0xfff); 865 memset(mac_mask->h_dest, ~0, ETH_ALEN);
866 else
867 memcpy(mac_mask->h_dest, mac_addr_ig_mask,
868 ETH_ALEN);
846 } 869 }
847 return 0; 870 if (spec.match_flags & EFX_FILTER_MATCH_REM_MAC) {
871 memcpy(mac_entry->h_source, spec.rem_mac, ETH_ALEN);
872 memset(mac_mask->h_source, ~0, ETH_ALEN);
873 }
874 if (spec.match_flags & EFX_FILTER_MATCH_ETHER_TYPE) {
875 mac_entry->h_proto = spec.ether_type;
876 mac_mask->h_proto = ETHER_TYPE_FULL_MASK;
877 }
878 } else {
879 /* The above should handle all filters that we insert */
880 WARN_ON(1);
881 return -EINVAL;
848 } 882 }
849 883
850 rc = efx_filter_get_ipv4_local(&spec, &proto, 884 if (spec.match_flags & EFX_FILTER_MATCH_OUTER_VID) {
851 &ip_entry->ip4dst, &ip_entry->pdst); 885 rule->flow_type |= FLOW_EXT;
852 if (rc != 0) { 886 rule->h_ext.vlan_tci = spec.outer_vid;
853 rc = efx_filter_get_ipv4_full( 887 rule->m_ext.vlan_tci = htons(0xfff);
854 &spec, &proto, &ip_entry->ip4dst, &ip_entry->pdst,
855 &ip_entry->ip4src, &ip_entry->psrc);
856 EFX_WARN_ON_PARANOID(rc);
857 ip_mask->ip4src = IP4_ADDR_FULL_MASK;
858 ip_mask->psrc = PORT_FULL_MASK;
859 } 888 }
860 rule->flow_type = (proto == IPPROTO_TCP) ? TCP_V4_FLOW : UDP_V4_FLOW; 889
861 ip_mask->ip4dst = IP4_ADDR_FULL_MASK;
862 ip_mask->pdst = PORT_FULL_MASK;
863 return rc; 890 return rc;
864} 891}
865 892
@@ -969,80 +996,78 @@ static int efx_ethtool_set_class_rule(struct efx_nic *efx,
969 (rule->ring_cookie == RX_CLS_FLOW_DISC) ? 996 (rule->ring_cookie == RX_CLS_FLOW_DISC) ?
970 EFX_FILTER_RX_DMAQ_ID_DROP : rule->ring_cookie); 997 EFX_FILTER_RX_DMAQ_ID_DROP : rule->ring_cookie);
971 998
972 switch (rule->flow_type) { 999 switch (rule->flow_type & ~FLOW_EXT) {
973 case TCP_V4_FLOW: 1000 case TCP_V4_FLOW:
974 case UDP_V4_FLOW: { 1001 case UDP_V4_FLOW:
975 u8 proto = (rule->flow_type == TCP_V4_FLOW ? 1002 spec.match_flags = (EFX_FILTER_MATCH_ETHER_TYPE |
976 IPPROTO_TCP : IPPROTO_UDP); 1003 EFX_FILTER_MATCH_IP_PROTO);
977 1004 spec.ether_type = htons(ETH_P_IP);
978 /* Must match all of destination, */ 1005 spec.ip_proto = ((rule->flow_type & ~FLOW_EXT) == TCP_V4_FLOW ?
979 if (!(ip_mask->ip4dst == IP4_ADDR_FULL_MASK && 1006 IPPROTO_TCP : IPPROTO_UDP);
980 ip_mask->pdst == PORT_FULL_MASK)) 1007 if (ip_mask->ip4dst) {
981 return -EINVAL; 1008 if (ip_mask->ip4dst != IP4_ADDR_FULL_MASK)
982 /* all or none of source, */ 1009 return -EINVAL;
983 if ((ip_mask->ip4src || ip_mask->psrc) && 1010 spec.match_flags |= EFX_FILTER_MATCH_LOC_HOST;
984 !(ip_mask->ip4src == IP4_ADDR_FULL_MASK && 1011 spec.loc_host[0] = ip_entry->ip4dst;
985 ip_mask->psrc == PORT_FULL_MASK)) 1012 }
986 return -EINVAL; 1013 if (ip_mask->ip4src) {
987 /* and nothing else */ 1014 if (ip_mask->ip4src != IP4_ADDR_FULL_MASK)
988 if (ip_mask->tos || rule->m_ext.vlan_tci) 1015 return -EINVAL;
1016 spec.match_flags |= EFX_FILTER_MATCH_REM_HOST;
1017 spec.rem_host[0] = ip_entry->ip4src;
1018 }
1019 if (ip_mask->pdst) {
1020 if (ip_mask->pdst != PORT_FULL_MASK)
1021 return -EINVAL;
1022 spec.match_flags |= EFX_FILTER_MATCH_LOC_PORT;
1023 spec.loc_port = ip_entry->pdst;
1024 }
1025 if (ip_mask->psrc) {
1026 if (ip_mask->psrc != PORT_FULL_MASK)
1027 return -EINVAL;
1028 spec.match_flags |= EFX_FILTER_MATCH_REM_PORT;
1029 spec.rem_port = ip_entry->psrc;
1030 }
1031 if (ip_mask->tos)
989 return -EINVAL; 1032 return -EINVAL;
990
991 if (ip_mask->ip4src)
992 rc = efx_filter_set_ipv4_full(&spec, proto,
993 ip_entry->ip4dst,
994 ip_entry->pdst,
995 ip_entry->ip4src,
996 ip_entry->psrc);
997 else
998 rc = efx_filter_set_ipv4_local(&spec, proto,
999 ip_entry->ip4dst,
1000 ip_entry->pdst);
1001 if (rc)
1002 return rc;
1003 break; 1033 break;
1004 }
1005
1006 case ETHER_FLOW | FLOW_EXT:
1007 case ETHER_FLOW: {
1008 u16 vlan_tag_mask = (rule->flow_type & FLOW_EXT ?
1009 ntohs(rule->m_ext.vlan_tci) : 0);
1010 1034
1011 /* Must not match on source address or Ethertype */ 1035 case ETHER_FLOW:
1012 if (!is_zero_ether_addr(mac_mask->h_source) || 1036 if (!is_zero_ether_addr(mac_mask->h_dest)) {
1013 mac_mask->h_proto) 1037 if (ether_addr_equal(mac_mask->h_dest,
1014 return -EINVAL; 1038 mac_addr_ig_mask))
1015 1039 spec.match_flags |= EFX_FILTER_MATCH_LOC_MAC_IG;
1016 /* Is it a default UC or MC filter? */ 1040 else if (is_broadcast_ether_addr(mac_mask->h_dest))
1017 if (ether_addr_equal(mac_mask->h_dest, mac_addr_mc_mask) && 1041 spec.match_flags |= EFX_FILTER_MATCH_LOC_MAC;
1018 vlan_tag_mask == 0) {
1019 if (is_multicast_ether_addr(mac_entry->h_dest))
1020 rc = efx_filter_set_mc_def(&spec);
1021 else 1042 else
1022 rc = efx_filter_set_uc_def(&spec); 1043 return -EINVAL;
1044 memcpy(spec.loc_mac, mac_entry->h_dest, ETH_ALEN);
1023 } 1045 }
1024 /* Otherwise, it must match all of destination and all 1046 if (!is_zero_ether_addr(mac_mask->h_source)) {
1025 * or none of VID. 1047 if (!is_broadcast_ether_addr(mac_mask->h_source))
1026 */ 1048 return -EINVAL;
1027 else if (is_broadcast_ether_addr(mac_mask->h_dest) && 1049 spec.match_flags |= EFX_FILTER_MATCH_REM_MAC;
1028 (vlan_tag_mask == 0xfff || vlan_tag_mask == 0)) { 1050 memcpy(spec.rem_mac, mac_entry->h_source, ETH_ALEN);
1029 rc = efx_filter_set_eth_local( 1051 }
1030 &spec, 1052 if (mac_mask->h_proto) {
1031 vlan_tag_mask ? 1053 if (mac_mask->h_proto != ETHER_TYPE_FULL_MASK)
1032 ntohs(rule->h_ext.vlan_tci) : EFX_FILTER_VID_UNSPEC, 1054 return -EINVAL;
1033 mac_entry->h_dest); 1055 spec.match_flags |= EFX_FILTER_MATCH_ETHER_TYPE;
1034 } else { 1056 spec.ether_type = mac_entry->h_proto;
1035 rc = -EINVAL;
1036 } 1057 }
1037 if (rc)
1038 return rc;
1039 break; 1058 break;
1040 }
1041 1059
1042 default: 1060 default:
1043 return -EINVAL; 1061 return -EINVAL;
1044 } 1062 }
1045 1063
1064 if ((rule->flow_type & FLOW_EXT) && rule->m_ext.vlan_tci) {
1065 if (rule->m_ext.vlan_tci != htons(0xfff))
1066 return -EINVAL;
1067 spec.match_flags |= EFX_FILTER_MATCH_OUTER_VID;
1068 spec.outer_vid = rule->h_ext.vlan_tci;
1069 }
1070
1046 rc = efx_filter_insert_filter(efx, &spec, true); 1071 rc = efx_filter_insert_filter(efx, &spec, true);
1047 if (rc < 0) 1072 if (rc < 0)
1048 return rc; 1073 return rc;
diff --git a/drivers/net/ethernet/sfc/filter.c b/drivers/net/ethernet/sfc/filter.c
index c547630cfee4..96f8f2e34403 100644
--- a/drivers/net/ethernet/sfc/filter.c
+++ b/drivers/net/ethernet/sfc/filter.c
@@ -32,6 +32,18 @@
32 * counter-productive. */ 32 * counter-productive. */
33#define EFX_FARCH_FILTER_CTL_SRCH_HINT_MAX 5 33#define EFX_FARCH_FILTER_CTL_SRCH_HINT_MAX 5
34 34
35enum efx_farch_filter_type {
36 EFX_FARCH_FILTER_TCP_FULL = 0,
37 EFX_FARCH_FILTER_TCP_WILD,
38 EFX_FARCH_FILTER_UDP_FULL,
39 EFX_FARCH_FILTER_UDP_WILD,
40 EFX_FARCH_FILTER_MAC_FULL = 4,
41 EFX_FARCH_FILTER_MAC_WILD,
42 EFX_FARCH_FILTER_UC_DEF = 8,
43 EFX_FARCH_FILTER_MC_DEF,
44 EFX_FARCH_FILTER_TYPE_COUNT, /* number of specific types */
45};
46
35enum efx_farch_filter_table_id { 47enum efx_farch_filter_table_id {
36 EFX_FARCH_FILTER_TABLE_RX_IP = 0, 48 EFX_FARCH_FILTER_TABLE_RX_IP = 0,
37 EFX_FARCH_FILTER_TABLE_RX_MAC, 49 EFX_FARCH_FILTER_TABLE_RX_MAC,
@@ -62,7 +74,7 @@ struct efx_farch_filter_table {
62 unsigned used; /* number currently used */ 74 unsigned used; /* number currently used */
63 unsigned long *used_bitmap; 75 unsigned long *used_bitmap;
64 struct efx_farch_filter_spec *spec; 76 struct efx_farch_filter_spec *spec;
65 unsigned search_depth[EFX_FILTER_TYPE_COUNT]; 77 unsigned search_depth[EFX_FARCH_FILTER_TYPE_COUNT];
66}; 78};
67 79
68struct efx_filter_state { 80struct efx_filter_state {
@@ -106,33 +118,22 @@ static enum efx_farch_filter_table_id
106efx_farch_filter_spec_table_id(const struct efx_farch_filter_spec *spec) 118efx_farch_filter_spec_table_id(const struct efx_farch_filter_spec *spec)
107{ 119{
108 BUILD_BUG_ON(EFX_FARCH_FILTER_TABLE_RX_IP != 120 BUILD_BUG_ON(EFX_FARCH_FILTER_TABLE_RX_IP !=
109 (EFX_FILTER_TCP_FULL >> 2)); 121 (EFX_FARCH_FILTER_TCP_FULL >> 2));
110 BUILD_BUG_ON(EFX_FARCH_FILTER_TABLE_RX_IP != 122 BUILD_BUG_ON(EFX_FARCH_FILTER_TABLE_RX_IP !=
111 (EFX_FILTER_TCP_WILD >> 2)); 123 (EFX_FARCH_FILTER_TCP_WILD >> 2));
112 BUILD_BUG_ON(EFX_FARCH_FILTER_TABLE_RX_IP != 124 BUILD_BUG_ON(EFX_FARCH_FILTER_TABLE_RX_IP !=
113 (EFX_FILTER_UDP_FULL >> 2)); 125 (EFX_FARCH_FILTER_UDP_FULL >> 2));
114 BUILD_BUG_ON(EFX_FARCH_FILTER_TABLE_RX_IP != 126 BUILD_BUG_ON(EFX_FARCH_FILTER_TABLE_RX_IP !=
115 (EFX_FILTER_UDP_WILD >> 2)); 127 (EFX_FARCH_FILTER_UDP_WILD >> 2));
116 BUILD_BUG_ON(EFX_FARCH_FILTER_TABLE_RX_MAC != 128 BUILD_BUG_ON(EFX_FARCH_FILTER_TABLE_RX_MAC !=
117 (EFX_FILTER_MAC_FULL >> 2)); 129 (EFX_FARCH_FILTER_MAC_FULL >> 2));
118 BUILD_BUG_ON(EFX_FARCH_FILTER_TABLE_RX_MAC != 130 BUILD_BUG_ON(EFX_FARCH_FILTER_TABLE_RX_MAC !=
119 (EFX_FILTER_MAC_WILD >> 2)); 131 (EFX_FARCH_FILTER_MAC_WILD >> 2));
120 BUILD_BUG_ON(EFX_FARCH_FILTER_TABLE_TX_MAC != 132 BUILD_BUG_ON(EFX_FARCH_FILTER_TABLE_TX_MAC !=
121 EFX_FARCH_FILTER_TABLE_RX_MAC + 2); 133 EFX_FARCH_FILTER_TABLE_RX_MAC + 2);
122 EFX_BUG_ON_PARANOID(spec->type == EFX_FILTER_UNSPEC);
123 return (spec->type >> 2) + ((spec->flags & EFX_FILTER_FLAG_TX) ? 2 : 0); 134 return (spec->type >> 2) + ((spec->flags & EFX_FILTER_FLAG_TX) ? 2 : 0);
124} 135}
125 136
126static struct efx_farch_filter_table *
127efx_farch_filter_spec_table(struct efx_filter_state *state,
128 const struct efx_farch_filter_spec *spec)
129{
130 if (spec->type == EFX_FILTER_UNSPEC)
131 return NULL;
132 else
133 return &state->table[efx_farch_filter_spec_table_id(spec)];
134}
135
136static void 137static void
137efx_farch_filter_table_reset_search_depth(struct efx_farch_filter_table *table) 138efx_farch_filter_table_reset_search_depth(struct efx_farch_filter_table *table)
138{ 139{
@@ -149,27 +150,27 @@ static void efx_farch_filter_push_rx_config(struct efx_nic *efx)
149 150
150 table = &state->table[EFX_FARCH_FILTER_TABLE_RX_IP]; 151 table = &state->table[EFX_FARCH_FILTER_TABLE_RX_IP];
151 EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_TCP_FULL_SRCH_LIMIT, 152 EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_TCP_FULL_SRCH_LIMIT,
152 table->search_depth[EFX_FILTER_TCP_FULL] + 153 table->search_depth[EFX_FARCH_FILTER_TCP_FULL] +
153 EFX_FARCH_FILTER_CTL_SRCH_FUDGE_FULL); 154 EFX_FARCH_FILTER_CTL_SRCH_FUDGE_FULL);
154 EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_TCP_WILD_SRCH_LIMIT, 155 EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_TCP_WILD_SRCH_LIMIT,
155 table->search_depth[EFX_FILTER_TCP_WILD] + 156 table->search_depth[EFX_FARCH_FILTER_TCP_WILD] +
156 EFX_FARCH_FILTER_CTL_SRCH_FUDGE_WILD); 157 EFX_FARCH_FILTER_CTL_SRCH_FUDGE_WILD);
157 EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_UDP_FULL_SRCH_LIMIT, 158 EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_UDP_FULL_SRCH_LIMIT,
158 table->search_depth[EFX_FILTER_UDP_FULL] + 159 table->search_depth[EFX_FARCH_FILTER_UDP_FULL] +
159 EFX_FARCH_FILTER_CTL_SRCH_FUDGE_FULL); 160 EFX_FARCH_FILTER_CTL_SRCH_FUDGE_FULL);
160 EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_UDP_WILD_SRCH_LIMIT, 161 EFX_SET_OWORD_FIELD(filter_ctl, FRF_BZ_UDP_WILD_SRCH_LIMIT,
161 table->search_depth[EFX_FILTER_UDP_WILD] + 162 table->search_depth[EFX_FARCH_FILTER_UDP_WILD] +
162 EFX_FARCH_FILTER_CTL_SRCH_FUDGE_WILD); 163 EFX_FARCH_FILTER_CTL_SRCH_FUDGE_WILD);
163 164
164 table = &state->table[EFX_FARCH_FILTER_TABLE_RX_MAC]; 165 table = &state->table[EFX_FARCH_FILTER_TABLE_RX_MAC];
165 if (table->size) { 166 if (table->size) {
166 EFX_SET_OWORD_FIELD( 167 EFX_SET_OWORD_FIELD(
167 filter_ctl, FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT, 168 filter_ctl, FRF_CZ_ETHERNET_FULL_SEARCH_LIMIT,
168 table->search_depth[EFX_FILTER_MAC_FULL] + 169 table->search_depth[EFX_FARCH_FILTER_MAC_FULL] +
169 EFX_FARCH_FILTER_CTL_SRCH_FUDGE_FULL); 170 EFX_FARCH_FILTER_CTL_SRCH_FUDGE_FULL);
170 EFX_SET_OWORD_FIELD( 171 EFX_SET_OWORD_FIELD(
171 filter_ctl, FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT, 172 filter_ctl, FRF_CZ_ETHERNET_WILDCARD_SEARCH_LIMIT,
172 table->search_depth[EFX_FILTER_MAC_WILD] + 173 table->search_depth[EFX_FARCH_FILTER_MAC_WILD] +
173 EFX_FARCH_FILTER_CTL_SRCH_FUDGE_WILD); 174 EFX_FARCH_FILTER_CTL_SRCH_FUDGE_WILD);
174 } 175 }
175 176
@@ -225,223 +226,202 @@ static void efx_farch_filter_push_tx_limits(struct efx_nic *efx)
225 if (table->size) { 226 if (table->size) {
226 EFX_SET_OWORD_FIELD( 227 EFX_SET_OWORD_FIELD(
227 tx_cfg, FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE, 228 tx_cfg, FRF_CZ_TX_ETH_FILTER_FULL_SEARCH_RANGE,
228 table->search_depth[EFX_FILTER_MAC_FULL] + 229 table->search_depth[EFX_FARCH_FILTER_MAC_FULL] +
229 EFX_FARCH_FILTER_CTL_SRCH_FUDGE_FULL); 230 EFX_FARCH_FILTER_CTL_SRCH_FUDGE_FULL);
230 EFX_SET_OWORD_FIELD( 231 EFX_SET_OWORD_FIELD(
231 tx_cfg, FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE, 232 tx_cfg, FRF_CZ_TX_ETH_FILTER_WILD_SEARCH_RANGE,
232 table->search_depth[EFX_FILTER_MAC_WILD] + 233 table->search_depth[EFX_FARCH_FILTER_MAC_WILD] +
233 EFX_FARCH_FILTER_CTL_SRCH_FUDGE_WILD); 234 EFX_FARCH_FILTER_CTL_SRCH_FUDGE_WILD);
234 } 235 }
235 236
236 efx_writeo(efx, &tx_cfg, FR_AZ_TX_CFG); 237 efx_writeo(efx, &tx_cfg, FR_AZ_TX_CFG);
237} 238}
238 239
239static inline void __efx_filter_set_ipv4(struct efx_filter_spec *spec, 240static int
240 __be32 host1, __be16 port1, 241efx_farch_filter_from_gen_spec(struct efx_farch_filter_spec *spec,
241 __be32 host2, __be16 port2) 242 const struct efx_filter_spec *gen_spec)
242{
243 spec->data[0] = ntohl(host1) << 16 | ntohs(port1);
244 spec->data[1] = ntohs(port2) << 16 | ntohl(host1) >> 16;
245 spec->data[2] = ntohl(host2);
246}
247
248static inline void __efx_filter_get_ipv4(const struct efx_filter_spec *spec,
249 __be32 *host1, __be16 *port1,
250 __be32 *host2, __be16 *port2)
251{
252 *host1 = htonl(spec->data[0] >> 16 | spec->data[1] << 16);
253 *port1 = htons(spec->data[0]);
254 *host2 = htonl(spec->data[2]);
255 *port2 = htons(spec->data[1] >> 16);
256}
257
258/**
259 * efx_filter_set_ipv4_local - specify IPv4 host, transport protocol and port
260 * @spec: Specification to initialise
261 * @proto: Transport layer protocol number
262 * @host: Local host address (network byte order)
263 * @port: Local port (network byte order)
264 */
265int efx_filter_set_ipv4_local(struct efx_filter_spec *spec, u8 proto,
266 __be32 host, __be16 port)
267{ 243{
268 __be32 host1; 244 bool is_full = false;
269 __be16 port1;
270
271 EFX_BUG_ON_PARANOID(!(spec->flags & EFX_FILTER_FLAG_RX));
272
273 /* This cannot currently be combined with other filtering */
274 if (spec->type != EFX_FILTER_UNSPEC)
275 return -EPROTONOSUPPORT;
276 245
277 if (port == 0) 246 if ((gen_spec->flags & EFX_FILTER_FLAG_RX_RSS) &&
247 gen_spec->rss_context != EFX_FILTER_RSS_CONTEXT_DEFAULT)
278 return -EINVAL; 248 return -EINVAL;
279 249
280 switch (proto) { 250 spec->priority = gen_spec->priority;
281 case IPPROTO_TCP: 251 spec->flags = gen_spec->flags;
282 spec->type = EFX_FILTER_TCP_WILD; 252 spec->dmaq_id = gen_spec->dmaq_id;
283 break;
284 case IPPROTO_UDP:
285 spec->type = EFX_FILTER_UDP_WILD;
286 break;
287 default:
288 return -EPROTONOSUPPORT;
289 }
290
291 /* Filter is constructed in terms of source and destination,
292 * with the odd wrinkle that the ports are swapped in a UDP
293 * wildcard filter. We need to convert from local and remote
294 * (= zero for wildcard) addresses.
295 */
296 host1 = 0;
297 if (proto != IPPROTO_UDP) {
298 port1 = 0;
299 } else {
300 port1 = port;
301 port = 0;
302 }
303
304 __efx_filter_set_ipv4(spec, host1, port1, host, port);
305 return 0;
306}
307 253
308int efx_filter_get_ipv4_local(const struct efx_filter_spec *spec, 254 switch (gen_spec->match_flags) {
309 u8 *proto, __be32 *host, __be16 *port) 255 case (EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
310{ 256 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
311 __be32 host1; 257 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT):
312 __be16 port1; 258 is_full = true;
259 /* fall through */
260 case (EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
261 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT): {
262 __be32 rhost, host1, host2;
263 __be16 rport, port1, port2;
313 264
314 switch (spec->type) { 265 EFX_BUG_ON_PARANOID(!(gen_spec->flags & EFX_FILTER_FLAG_RX));
315 case EFX_FILTER_TCP_WILD:
316 *proto = IPPROTO_TCP;
317 __efx_filter_get_ipv4(spec, &host1, &port1, host, port);
318 return 0;
319 case EFX_FILTER_UDP_WILD:
320 *proto = IPPROTO_UDP;
321 __efx_filter_get_ipv4(spec, &host1, port, host, &port1);
322 return 0;
323 default:
324 return -EINVAL;
325 }
326}
327
328/**
329 * efx_filter_set_ipv4_full - specify IPv4 hosts, transport protocol and ports
330 * @spec: Specification to initialise
331 * @proto: Transport layer protocol number
332 * @host: Local host address (network byte order)
333 * @port: Local port (network byte order)
334 * @rhost: Remote host address (network byte order)
335 * @rport: Remote port (network byte order)
336 */
337int efx_filter_set_ipv4_full(struct efx_filter_spec *spec, u8 proto,
338 __be32 host, __be16 port,
339 __be32 rhost, __be16 rport)
340{
341 EFX_BUG_ON_PARANOID(!(spec->flags & EFX_FILTER_FLAG_RX));
342 266
343 /* This cannot currently be combined with other filtering */ 267 if (gen_spec->ether_type != htons(ETH_P_IP))
344 if (spec->type != EFX_FILTER_UNSPEC) 268 return -EPROTONOSUPPORT;
345 return -EPROTONOSUPPORT; 269 if (gen_spec->loc_port == 0 ||
270 (is_full && gen_spec->rem_port == 0))
271 return -EADDRNOTAVAIL;
272 switch (gen_spec->ip_proto) {
273 case IPPROTO_TCP:
274 spec->type = (is_full ? EFX_FARCH_FILTER_TCP_FULL :
275 EFX_FARCH_FILTER_TCP_WILD);
276 break;
277 case IPPROTO_UDP:
278 spec->type = (is_full ? EFX_FARCH_FILTER_UDP_FULL :
279 EFX_FARCH_FILTER_UDP_WILD);
280 break;
281 default:
282 return -EPROTONOSUPPORT;
283 }
346 284
347 if (port == 0 || rport == 0) 285 /* Filter is constructed in terms of source and destination,
348 return -EINVAL; 286 * with the odd wrinkle that the ports are swapped in a UDP
287 * wildcard filter. We need to convert from local and remote
288 * (= zero for wildcard) addresses.
289 */
290 rhost = is_full ? gen_spec->rem_host[0] : 0;
291 rport = is_full ? gen_spec->rem_port : 0;
292 host1 = rhost;
293 host2 = gen_spec->loc_host[0];
294 if (!is_full && gen_spec->ip_proto == IPPROTO_UDP) {
295 port1 = gen_spec->loc_port;
296 port2 = rport;
297 } else {
298 port1 = rport;
299 port2 = gen_spec->loc_port;
300 }
301 spec->data[0] = ntohl(host1) << 16 | ntohs(port1);
302 spec->data[1] = ntohs(port2) << 16 | ntohl(host1) >> 16;
303 spec->data[2] = ntohl(host2);
349 304
350 switch (proto) {
351 case IPPROTO_TCP:
352 spec->type = EFX_FILTER_TCP_FULL;
353 break; 305 break;
354 case IPPROTO_UDP:
355 spec->type = EFX_FILTER_UDP_FULL;
356 break;
357 default:
358 return -EPROTONOSUPPORT;
359 } 306 }
360 307
361 __efx_filter_set_ipv4(spec, rhost, rport, host, port); 308 case EFX_FILTER_MATCH_LOC_MAC | EFX_FILTER_MATCH_OUTER_VID:
362 return 0; 309 is_full = true;
363} 310 /* fall through */
364 311 case EFX_FILTER_MATCH_LOC_MAC:
365int efx_filter_get_ipv4_full(const struct efx_filter_spec *spec, 312 spec->type = (is_full ? EFX_FARCH_FILTER_MAC_FULL :
366 u8 *proto, __be32 *host, __be16 *port, 313 EFX_FARCH_FILTER_MAC_WILD);
367 __be32 *rhost, __be16 *rport) 314 spec->data[0] = is_full ? ntohs(gen_spec->outer_vid) : 0;
368{ 315 spec->data[1] = (gen_spec->loc_mac[2] << 24 |
369 switch (spec->type) { 316 gen_spec->loc_mac[3] << 16 |
370 case EFX_FILTER_TCP_FULL: 317 gen_spec->loc_mac[4] << 8 |
371 *proto = IPPROTO_TCP; 318 gen_spec->loc_mac[5]);
319 spec->data[2] = (gen_spec->loc_mac[0] << 8 |
320 gen_spec->loc_mac[1]);
372 break; 321 break;
373 case EFX_FILTER_UDP_FULL: 322
374 *proto = IPPROTO_UDP; 323 case EFX_FILTER_MATCH_LOC_MAC_IG:
324 spec->type = (is_multicast_ether_addr(gen_spec->loc_mac) ?
325 EFX_FARCH_FILTER_MC_DEF :
326 EFX_FARCH_FILTER_UC_DEF);
327 memset(spec->data, 0, sizeof(spec->data)); /* ensure equality */
375 break; 328 break;
329
376 default: 330 default:
377 return -EINVAL; 331 return -EPROTONOSUPPORT;
378 } 332 }
379 333
380 __efx_filter_get_ipv4(spec, rhost, rport, host, port);
381 return 0; 334 return 0;
382} 335}
383 336
384/** 337static void
385 * efx_filter_set_eth_local - specify local Ethernet address and optional VID 338efx_farch_filter_to_gen_spec(struct efx_filter_spec *gen_spec,
386 * @spec: Specification to initialise 339 const struct efx_farch_filter_spec *spec)
387 * @vid: VLAN ID to match, or %EFX_FILTER_VID_UNSPEC
388 * @addr: Local Ethernet MAC address
389 */
390int efx_filter_set_eth_local(struct efx_filter_spec *spec,
391 u16 vid, const u8 *addr)
392{ 340{
393 EFX_BUG_ON_PARANOID(!(spec->flags & 341 bool is_full = false;
394 (EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_TX)));
395
396 /* This cannot currently be combined with other filtering */
397 if (spec->type != EFX_FILTER_UNSPEC)
398 return -EPROTONOSUPPORT;
399
400 if (vid == EFX_FILTER_VID_UNSPEC) {
401 spec->type = EFX_FILTER_MAC_WILD;
402 spec->data[0] = 0;
403 } else {
404 spec->type = EFX_FILTER_MAC_FULL;
405 spec->data[0] = vid;
406 }
407 342
408 spec->data[1] = addr[2] << 24 | addr[3] << 16 | addr[4] << 8 | addr[5]; 343 /* *gen_spec should be completely initialised, to be consistent
409 spec->data[2] = addr[0] << 8 | addr[1]; 344 * with efx_filter_init_{rx,tx}() and in case we want to copy
410 return 0; 345 * it back to userland.
411} 346 */
347 memset(gen_spec, 0, sizeof(*gen_spec));
412 348
413/** 349 gen_spec->priority = spec->priority;
414 * efx_filter_set_uc_def - specify matching otherwise-unmatched unicast 350 gen_spec->flags = spec->flags;
415 * @spec: Specification to initialise 351 gen_spec->dmaq_id = spec->dmaq_id;
416 */
417int efx_filter_set_uc_def(struct efx_filter_spec *spec)
418{
419 EFX_BUG_ON_PARANOID(!(spec->flags &
420 (EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_TX)));
421 352
422 if (spec->type != EFX_FILTER_UNSPEC) 353 switch (spec->type) {
423 return -EINVAL; 354 case EFX_FARCH_FILTER_TCP_FULL:
355 case EFX_FARCH_FILTER_UDP_FULL:
356 is_full = true;
357 /* fall through */
358 case EFX_FARCH_FILTER_TCP_WILD:
359 case EFX_FARCH_FILTER_UDP_WILD: {
360 __be32 host1, host2;
361 __be16 port1, port2;
362
363 gen_spec->match_flags =
364 EFX_FILTER_MATCH_ETHER_TYPE |
365 EFX_FILTER_MATCH_IP_PROTO |
366 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
367 if (is_full)
368 gen_spec->match_flags |= (EFX_FILTER_MATCH_REM_HOST |
369 EFX_FILTER_MATCH_REM_PORT);
370 gen_spec->ether_type = htons(ETH_P_IP);
371 gen_spec->ip_proto =
372 (spec->type == EFX_FARCH_FILTER_TCP_FULL ||
373 spec->type == EFX_FARCH_FILTER_TCP_WILD) ?
374 IPPROTO_TCP : IPPROTO_UDP;
375
376 host1 = htonl(spec->data[0] >> 16 | spec->data[1] << 16);
377 port1 = htons(spec->data[0]);
378 host2 = htonl(spec->data[2]);
379 port2 = htons(spec->data[1] >> 16);
380 if (spec->flags & EFX_FILTER_FLAG_TX) {
381 gen_spec->loc_host[0] = host1;
382 gen_spec->rem_host[0] = host2;
383 } else {
384 gen_spec->loc_host[0] = host2;
385 gen_spec->rem_host[0] = host1;
386 }
387 if (!!(gen_spec->flags & EFX_FILTER_FLAG_TX) ^
388 (!is_full && gen_spec->ip_proto == IPPROTO_UDP)) {
389 gen_spec->loc_port = port1;
390 gen_spec->rem_port = port2;
391 } else {
392 gen_spec->loc_port = port2;
393 gen_spec->rem_port = port1;
394 }
424 395
425 spec->type = EFX_FILTER_UC_DEF; 396 break;
426 memset(spec->data, 0, sizeof(spec->data)); /* ensure equality */ 397 }
427 return 0;
428}
429 398
430/** 399 case EFX_FARCH_FILTER_MAC_FULL:
431 * efx_filter_set_mc_def - specify matching otherwise-unmatched multicast 400 is_full = true;
432 * @spec: Specification to initialise 401 /* fall through */
433 */ 402 case EFX_FARCH_FILTER_MAC_WILD:
434int efx_filter_set_mc_def(struct efx_filter_spec *spec) 403 gen_spec->match_flags = EFX_FILTER_MATCH_LOC_MAC;
435{ 404 if (is_full)
436 EFX_BUG_ON_PARANOID(!(spec->flags & 405 gen_spec->match_flags |= EFX_FILTER_MATCH_OUTER_VID;
437 (EFX_FILTER_FLAG_RX | EFX_FILTER_FLAG_TX))); 406 gen_spec->loc_mac[0] = spec->data[2] >> 8;
407 gen_spec->loc_mac[1] = spec->data[2];
408 gen_spec->loc_mac[2] = spec->data[1] >> 24;
409 gen_spec->loc_mac[3] = spec->data[1] >> 16;
410 gen_spec->loc_mac[4] = spec->data[1] >> 8;
411 gen_spec->loc_mac[5] = spec->data[1];
412 gen_spec->outer_vid = htons(spec->data[0]);
413 break;
438 414
439 if (spec->type != EFX_FILTER_UNSPEC) 415 case EFX_FARCH_FILTER_UC_DEF:
440 return -EINVAL; 416 case EFX_FARCH_FILTER_MC_DEF:
417 gen_spec->match_flags = EFX_FILTER_MATCH_LOC_MAC_IG;
418 gen_spec->loc_mac[0] = spec->type == EFX_FARCH_FILTER_MC_DEF;
419 break;
441 420
442 spec->type = EFX_FILTER_MC_DEF; 421 default:
443 memset(spec->data, 0, sizeof(spec->data)); /* ensure equality */ 422 WARN_ON(1);
444 return 0; 423 break;
424 }
445} 425}
446 426
447static void 427static void
@@ -455,7 +435,7 @@ efx_farch_filter_reset_rx_def(struct efx_nic *efx, unsigned filter_idx)
455 /* If there's only one channel then disable RSS for non VF 435 /* If there's only one channel then disable RSS for non VF
456 * traffic, thereby allowing VFs to use RSS when the PF can't. 436 * traffic, thereby allowing VFs to use RSS when the PF can't.
457 */ 437 */
458 spec->type = EFX_FILTER_UC_DEF + filter_idx; 438 spec->type = EFX_FARCH_FILTER_UC_DEF + filter_idx;
459 spec->priority = EFX_FILTER_PRI_MANUAL; 439 spec->priority = EFX_FILTER_PRI_MANUAL;
460 spec->flags = (EFX_FILTER_FLAG_RX | 440 spec->flags = (EFX_FILTER_FLAG_RX |
461 (efx->n_rx_channels > 1 ? EFX_FILTER_FLAG_RX_RSS : 0) | 441 (efx->n_rx_channels > 1 ? EFX_FILTER_FLAG_RX_RSS : 0) |
@@ -464,29 +444,6 @@ efx_farch_filter_reset_rx_def(struct efx_nic *efx, unsigned filter_idx)
464 table->used_bitmap[0] |= 1 << filter_idx; 444 table->used_bitmap[0] |= 1 << filter_idx;
465} 445}
466 446
467int efx_filter_get_eth_local(const struct efx_filter_spec *spec,
468 u16 *vid, u8 *addr)
469{
470 switch (spec->type) {
471 case EFX_FILTER_MAC_WILD:
472 *vid = EFX_FILTER_VID_UNSPEC;
473 break;
474 case EFX_FILTER_MAC_FULL:
475 *vid = spec->data[0];
476 break;
477 default:
478 return -EINVAL;
479 }
480
481 addr[0] = spec->data[2] >> 8;
482 addr[1] = spec->data[2];
483 addr[2] = spec->data[1] >> 24;
484 addr[3] = spec->data[1] >> 16;
485 addr[4] = spec->data[1] >> 8;
486 addr[5] = spec->data[1];
487 return 0;
488}
489
490/* Build a filter entry and return its n-tuple key. */ 447/* Build a filter entry and return its n-tuple key. */
491static u32 efx_farch_filter_build(efx_oword_t *filter, 448static u32 efx_farch_filter_build(efx_oword_t *filter,
492 struct efx_farch_filter_spec *spec) 449 struct efx_farch_filter_spec *spec)
@@ -495,8 +452,8 @@ static u32 efx_farch_filter_build(efx_oword_t *filter,
495 452
496 switch (efx_farch_filter_spec_table_id(spec)) { 453 switch (efx_farch_filter_spec_table_id(spec)) {
497 case EFX_FARCH_FILTER_TABLE_RX_IP: { 454 case EFX_FARCH_FILTER_TABLE_RX_IP: {
498 bool is_udp = (spec->type == EFX_FILTER_UDP_FULL || 455 bool is_udp = (spec->type == EFX_FARCH_FILTER_UDP_FULL ||
499 spec->type == EFX_FILTER_UDP_WILD); 456 spec->type == EFX_FARCH_FILTER_UDP_WILD);
500 EFX_POPULATE_OWORD_7( 457 EFX_POPULATE_OWORD_7(
501 *filter, 458 *filter,
502 FRF_BZ_RSS_EN, 459 FRF_BZ_RSS_EN,
@@ -513,7 +470,7 @@ static u32 efx_farch_filter_build(efx_oword_t *filter,
513 } 470 }
514 471
515 case EFX_FARCH_FILTER_TABLE_RX_MAC: { 472 case EFX_FARCH_FILTER_TABLE_RX_MAC: {
516 bool is_wild = spec->type == EFX_FILTER_MAC_WILD; 473 bool is_wild = spec->type == EFX_FARCH_FILTER_MAC_WILD;
517 EFX_POPULATE_OWORD_7( 474 EFX_POPULATE_OWORD_7(
518 *filter, 475 *filter,
519 FRF_CZ_RMFT_RSS_EN, 476 FRF_CZ_RMFT_RSS_EN,
@@ -530,7 +487,7 @@ static u32 efx_farch_filter_build(efx_oword_t *filter,
530 } 487 }
531 488
532 case EFX_FARCH_FILTER_TABLE_TX_MAC: { 489 case EFX_FARCH_FILTER_TABLE_TX_MAC: {
533 bool is_wild = spec->type == EFX_FILTER_MAC_WILD; 490 bool is_wild = spec->type == EFX_FARCH_FILTER_MAC_WILD;
534 EFX_POPULATE_OWORD_5(*filter, 491 EFX_POPULATE_OWORD_5(*filter,
535 FRF_CZ_TMFT_TXQ_ID, spec->dmaq_id, 492 FRF_CZ_TMFT_TXQ_ID, spec->dmaq_id,
536 FRF_CZ_TMFT_WILDCARD_MATCH, is_wild, 493 FRF_CZ_TMFT_WILDCARD_MATCH, is_wild,
@@ -573,15 +530,15 @@ static bool efx_farch_filter_equal(const struct efx_farch_filter_spec *left,
573 530
574#define EFX_FARCH_FILTER_MATCH_PRI_COUNT 5 531#define EFX_FARCH_FILTER_MATCH_PRI_COUNT 5
575 532
576static const u8 efx_farch_filter_type_match_pri[EFX_FILTER_TYPE_COUNT] = { 533static const u8 efx_farch_filter_type_match_pri[EFX_FARCH_FILTER_TYPE_COUNT] = {
577 [EFX_FILTER_TCP_FULL] = 0, 534 [EFX_FARCH_FILTER_TCP_FULL] = 0,
578 [EFX_FILTER_UDP_FULL] = 0, 535 [EFX_FARCH_FILTER_UDP_FULL] = 0,
579 [EFX_FILTER_TCP_WILD] = 1, 536 [EFX_FARCH_FILTER_TCP_WILD] = 1,
580 [EFX_FILTER_UDP_WILD] = 1, 537 [EFX_FARCH_FILTER_UDP_WILD] = 1,
581 [EFX_FILTER_MAC_FULL] = 2, 538 [EFX_FARCH_FILTER_MAC_FULL] = 2,
582 [EFX_FILTER_MAC_WILD] = 3, 539 [EFX_FARCH_FILTER_MAC_WILD] = 3,
583 [EFX_FILTER_UC_DEF] = 4, 540 [EFX_FARCH_FILTER_UC_DEF] = 4,
584 [EFX_FILTER_MC_DEF] = 4, 541 [EFX_FARCH_FILTER_MC_DEF] = 4,
585}; 542};
586 543
587static const enum efx_farch_filter_table_id efx_farch_filter_range_table[] = { 544static const enum efx_farch_filter_table_id efx_farch_filter_range_table[] = {
@@ -672,11 +629,12 @@ s32 efx_filter_insert_filter(struct efx_nic *efx,
672 unsigned int depth = 0; 629 unsigned int depth = 0;
673 int rc; 630 int rc;
674 631
675 /* XXX efx_farch_filter_spec and efx_filter_spec will diverge in future */ 632 rc = efx_farch_filter_from_gen_spec(&spec, gen_spec);
676 memcpy(&spec, gen_spec, sizeof(*gen_spec)); 633 if (rc)
634 return rc;
677 635
678 table = efx_farch_filter_spec_table(state, &spec); 636 table = &state->table[efx_farch_filter_spec_table_id(&spec)];
679 if (!table || table->size == 0) 637 if (table->size == 0)
680 return -EINVAL; 638 return -EINVAL;
681 639
682 netif_vdbg(efx, hw, efx->net_dev, 640 netif_vdbg(efx, hw, efx->net_dev,
@@ -687,8 +645,8 @@ s32 efx_filter_insert_filter(struct efx_nic *efx,
687 /* One filter spec per type */ 645 /* One filter spec per type */
688 BUILD_BUG_ON(EFX_FARCH_FILTER_INDEX_UC_DEF != 0); 646 BUILD_BUG_ON(EFX_FARCH_FILTER_INDEX_UC_DEF != 0);
689 BUILD_BUG_ON(EFX_FARCH_FILTER_INDEX_MC_DEF != 647 BUILD_BUG_ON(EFX_FARCH_FILTER_INDEX_MC_DEF !=
690 EFX_FILTER_MC_DEF - EFX_FILTER_UC_DEF); 648 EFX_FARCH_FILTER_MC_DEF - EFX_FARCH_FILTER_UC_DEF);
691 rep_index = spec.type - EFX_FILTER_UC_DEF; 649 rep_index = spec.type - EFX_FARCH_FILTER_UC_DEF;
692 ins_index = rep_index; 650 ins_index = rep_index;
693 651
694 spin_lock_bh(&state->lock); 652 spin_lock_bh(&state->lock);
@@ -911,8 +869,7 @@ int efx_filter_get_filter_safe(struct efx_nic *efx,
911 869
912 if (test_bit(filter_idx, table->used_bitmap) && 870 if (test_bit(filter_idx, table->used_bitmap) &&
913 spec->priority == priority) { 871 spec->priority == priority) {
914 /* XXX efx_farch_filter_spec and efx_filter_spec will diverge */ 872 efx_farch_filter_to_gen_spec(spec_buf, spec);
915 memcpy(spec_buf, spec, sizeof(*spec));
916 rc = 0; 873 rc = 0;
917 } else { 874 } else {
918 rc = -ENOENT; 875 rc = -ENOENT;
diff --git a/drivers/net/ethernet/sfc/filter.h b/drivers/net/ethernet/sfc/filter.h
index b1170d44171e..1b410defccec 100644
--- a/drivers/net/ethernet/sfc/filter.h
+++ b/drivers/net/ethernet/sfc/filter.h
@@ -11,32 +11,49 @@
11#define EFX_FILTER_H 11#define EFX_FILTER_H
12 12
13#include <linux/types.h> 13#include <linux/types.h>
14#include <linux/if_ether.h>
15#include <asm/byteorder.h>
14 16
15/** 17/**
16 * enum efx_filter_type - type of hardware filter 18 * enum efx_filter_match_flags - Flags for hardware filter match type
17 * @EFX_FILTER_TCP_FULL: Matching TCP/IPv4 4-tuple 19 * @EFX_FILTER_MATCH_REM_HOST: Match by remote IP host address
18 * @EFX_FILTER_TCP_WILD: Matching TCP/IPv4 destination (host, port) 20 * @EFX_FILTER_MATCH_LOC_HOST: Match by local IP host address
19 * @EFX_FILTER_UDP_FULL: Matching UDP/IPv4 4-tuple 21 * @EFX_FILTER_MATCH_REM_MAC: Match by remote MAC address
20 * @EFX_FILTER_UDP_WILD: Matching UDP/IPv4 destination (host, port) 22 * @EFX_FILTER_MATCH_REM_PORT: Match by remote TCP/UDP port
21 * @EFX_FILTER_MAC_FULL: Matching Ethernet destination MAC address, VID 23 * @EFX_FILTER_MATCH_LOC_MAC: Match by local MAC address
22 * @EFX_FILTER_MAC_WILD: Matching Ethernet destination MAC address 24 * @EFX_FILTER_MATCH_LOC_PORT: Match by local TCP/UDP port
23 * @EFX_FILTER_UC_DEF: Matching all otherwise unmatched unicast 25 * @EFX_FILTER_MATCH_ETHER_TYPE: Match by Ether-type
24 * @EFX_FILTER_MC_DEF: Matching all otherwise unmatched multicast 26 * @EFX_FILTER_MATCH_INNER_VID: Match by inner VLAN ID
25 * @EFX_FILTER_UNSPEC: Match type is unspecified 27 * @EFX_FILTER_MATCH_OUTER_VID: Match by outer VLAN ID
28 * @EFX_FILTER_MATCH_IP_PROTO: Match by IP transport protocol
29 * @EFX_FILTER_MATCH_LOC_MAC_IG: Match by local MAC address I/G bit.
30 * Used for RX default unicast and multicast/broadcast filters.
26 * 31 *
27 * Falcon NICs only support the TCP/IPv4 and UDP/IPv4 filter types. 32 * Only some combinations are supported, depending on NIC type:
33 *
34 * - Falcon supports RX filters matching by {TCP,UDP}/IPv4 4-tuple or
35 * local 2-tuple (only implemented for Falcon B0)
36 *
37 * - Siena supports RX and TX filters matching by {TCP,UDP}/IPv4 4-tuple
38 * or local 2-tuple, or local MAC with or without outer VID, and RX
39 * default filters
40 *
41 * - Huntington supports filter matching controlled by firmware, potentially
42 * using {TCP,UDP}/IPv{4,6} 4-tuple or local 2-tuple, local MAC or I/G bit,
43 * with or without outer and inner VID
28 */ 44 */
29enum efx_filter_type { 45enum efx_filter_match_flags {
30 EFX_FILTER_TCP_FULL = 0, 46 EFX_FILTER_MATCH_REM_HOST = 0x0001,
31 EFX_FILTER_TCP_WILD, 47 EFX_FILTER_MATCH_LOC_HOST = 0x0002,
32 EFX_FILTER_UDP_FULL, 48 EFX_FILTER_MATCH_REM_MAC = 0x0004,
33 EFX_FILTER_UDP_WILD, 49 EFX_FILTER_MATCH_REM_PORT = 0x0008,
34 EFX_FILTER_MAC_FULL = 4, 50 EFX_FILTER_MATCH_LOC_MAC = 0x0010,
35 EFX_FILTER_MAC_WILD, 51 EFX_FILTER_MATCH_LOC_PORT = 0x0020,
36 EFX_FILTER_UC_DEF = 8, 52 EFX_FILTER_MATCH_ETHER_TYPE = 0x0040,
37 EFX_FILTER_MC_DEF, 53 EFX_FILTER_MATCH_INNER_VID = 0x0080,
38 EFX_FILTER_TYPE_COUNT, /* number of specific types */ 54 EFX_FILTER_MATCH_OUTER_VID = 0x0100,
39 EFX_FILTER_UNSPEC = 0xf, 55 EFX_FILTER_MATCH_IP_PROTO = 0x0200,
56 EFX_FILTER_MATCH_LOC_MAC_IG = 0x0400,
40}; 57};
41 58
42/** 59/**
@@ -73,29 +90,55 @@ enum efx_filter_flags {
73 90
74/** 91/**
75 * struct efx_filter_spec - specification for a hardware filter 92 * struct efx_filter_spec - specification for a hardware filter
76 * @type: Type of match to be performed, from &enum efx_filter_type 93 * @match_flags: Match type flags, from &enum efx_filter_match_flags
77 * @priority: Priority of the filter, from &enum efx_filter_priority 94 * @priority: Priority of the filter, from &enum efx_filter_priority
78 * @flags: Miscellaneous flags, from &enum efx_filter_flags 95 * @flags: Miscellaneous flags, from &enum efx_filter_flags
96 * @rss_context: RSS context to use, if %EFX_FILTER_FLAG_RX_RSS is set
79 * @dmaq_id: Source/target queue index, or %EFX_FILTER_RX_DMAQ_ID_DROP for 97 * @dmaq_id: Source/target queue index, or %EFX_FILTER_RX_DMAQ_ID_DROP for
80 * an RX drop filter 98 * an RX drop filter
81 * @data: Match data (type-dependent) 99 * @outer_vid: Outer VLAN ID to match, if %EFX_FILTER_MATCH_OUTER_VID is set
100 * @inner_vid: Inner VLAN ID to match, if %EFX_FILTER_MATCH_INNER_VID is set
101 * @loc_mac: Local MAC address to match, if %EFX_FILTER_MATCH_LOC_MAC or
102 * %EFX_FILTER_MATCH_LOC_MAC_IG is set
103 * @rem_mac: Remote MAC address to match, if %EFX_FILTER_MATCH_REM_MAC is set
104 * @ether_type: Ether-type to match, if %EFX_FILTER_MATCH_ETHER_TYPE is set
105 * @ip_proto: IP transport protocol to match, if %EFX_FILTER_MATCH_IP_PROTO
106 * is set
107 * @loc_host: Local IP host to match, if %EFX_FILTER_MATCH_LOC_HOST is set
108 * @rem_host: Remote IP host to match, if %EFX_FILTER_MATCH_REM_HOST is set
109 * @loc_port: Local TCP/UDP port to match, if %EFX_FILTER_MATCH_LOC_PORT is set
110 * @rem_port: Remote TCP/UDP port to match, if %EFX_FILTER_MATCH_REM_PORT is set
82 * 111 *
83 * Use the efx_filter_set_*() functions to initialise the @type and 112 * The efx_filter_init_rx() or efx_filter_init_tx() function *must* be
84 * @data fields. 113 * used to initialise the structure. The efx_filter_set_*() functions
114 * may then be used to set @rss_context, @match_flags and related
115 * fields.
85 * 116 *
86 * The @priority field is used by software to determine whether a new 117 * The @priority field is used by software to determine whether a new
87 * filter may replace an old one. The hardware priority of a filter 118 * filter may replace an old one. The hardware priority of a filter
88 * depends on the filter type. 119 * depends on which fields are matched.
89 */ 120 */
90struct efx_filter_spec { 121struct efx_filter_spec {
91 u8 type:4; 122 u32 match_flags:12;
92 u8 priority:4; 123 u32 priority:2;
93 u8 flags; 124 u32 flags:6;
94 u16 dmaq_id; 125 u32 dmaq_id:12;
95 u32 data[3]; 126 u32 rss_context;
127 __be16 outer_vid __aligned(4); /* allow jhash2() of match values */
128 __be16 inner_vid;
129 u8 loc_mac[ETH_ALEN];
130 u8 rem_mac[ETH_ALEN];
131 __be16 ether_type;
132 u8 ip_proto;
133 __be32 loc_host[4];
134 __be32 rem_host[4];
135 __be16 loc_port;
136 __be16 rem_port;
137 /* total 64 bytes */
96}; 138};
97 139
98enum { 140enum {
141 EFX_FILTER_RSS_CONTEXT_DEFAULT = 0xffffffff,
99 EFX_FILTER_RX_DMAQ_ID_DROP = 0xfff 142 EFX_FILTER_RX_DMAQ_ID_DROP = 0xfff
100}; 143};
101 144
@@ -104,39 +147,116 @@ static inline void efx_filter_init_rx(struct efx_filter_spec *spec,
104 enum efx_filter_flags flags, 147 enum efx_filter_flags flags,
105 unsigned rxq_id) 148 unsigned rxq_id)
106{ 149{
107 spec->type = EFX_FILTER_UNSPEC; 150 memset(spec, 0, sizeof(*spec));
108 spec->priority = priority; 151 spec->priority = priority;
109 spec->flags = EFX_FILTER_FLAG_RX | flags; 152 spec->flags = EFX_FILTER_FLAG_RX | flags;
153 spec->rss_context = EFX_FILTER_RSS_CONTEXT_DEFAULT;
110 spec->dmaq_id = rxq_id; 154 spec->dmaq_id = rxq_id;
111} 155}
112 156
113static inline void efx_filter_init_tx(struct efx_filter_spec *spec, 157static inline void efx_filter_init_tx(struct efx_filter_spec *spec,
114 unsigned txq_id) 158 unsigned txq_id)
115{ 159{
116 spec->type = EFX_FILTER_UNSPEC; 160 memset(spec, 0, sizeof(*spec));
117 spec->priority = EFX_FILTER_PRI_REQUIRED; 161 spec->priority = EFX_FILTER_PRI_REQUIRED;
118 spec->flags = EFX_FILTER_FLAG_TX; 162 spec->flags = EFX_FILTER_FLAG_TX;
119 spec->dmaq_id = txq_id; 163 spec->dmaq_id = txq_id;
120} 164}
121 165
122extern int efx_filter_set_ipv4_local(struct efx_filter_spec *spec, u8 proto, 166/**
123 __be32 host, __be16 port); 167 * efx_filter_set_ipv4_local - specify IPv4 host, transport protocol and port
124extern int efx_filter_get_ipv4_local(const struct efx_filter_spec *spec, 168 * @spec: Specification to initialise
125 u8 *proto, __be32 *host, __be16 *port); 169 * @proto: Transport layer protocol number
126extern int efx_filter_set_ipv4_full(struct efx_filter_spec *spec, u8 proto, 170 * @host: Local host address (network byte order)
127 __be32 host, __be16 port, 171 * @port: Local port (network byte order)
128 __be32 rhost, __be16 rport); 172 */
129extern int efx_filter_get_ipv4_full(const struct efx_filter_spec *spec, 173static inline int
130 u8 *proto, __be32 *host, __be16 *port, 174efx_filter_set_ipv4_local(struct efx_filter_spec *spec, u8 proto,
131 __be32 *rhost, __be16 *rport); 175 __be32 host, __be16 port)
132extern int efx_filter_set_eth_local(struct efx_filter_spec *spec, 176{
133 u16 vid, const u8 *addr); 177 spec->match_flags |=
134extern int efx_filter_get_eth_local(const struct efx_filter_spec *spec, 178 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
135 u16 *vid, u8 *addr); 179 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT;
136extern int efx_filter_set_uc_def(struct efx_filter_spec *spec); 180 spec->ether_type = htons(ETH_P_IP);
137extern int efx_filter_set_mc_def(struct efx_filter_spec *spec); 181 spec->ip_proto = proto;
182 spec->loc_host[0] = host;
183 spec->loc_port = port;
184 return 0;
185}
186
187/**
188 * efx_filter_set_ipv4_full - specify IPv4 hosts, transport protocol and ports
189 * @spec: Specification to initialise
190 * @proto: Transport layer protocol number
191 * @lhost: Local host address (network byte order)
192 * @lport: Local port (network byte order)
193 * @rhost: Remote host address (network byte order)
194 * @rport: Remote port (network byte order)
195 */
196static inline int
197efx_filter_set_ipv4_full(struct efx_filter_spec *spec, u8 proto,
198 __be32 lhost, __be16 lport,
199 __be32 rhost, __be16 rport)
200{
201 spec->match_flags |=
202 EFX_FILTER_MATCH_ETHER_TYPE | EFX_FILTER_MATCH_IP_PROTO |
203 EFX_FILTER_MATCH_LOC_HOST | EFX_FILTER_MATCH_LOC_PORT |
204 EFX_FILTER_MATCH_REM_HOST | EFX_FILTER_MATCH_REM_PORT;
205 spec->ether_type = htons(ETH_P_IP);
206 spec->ip_proto = proto;
207 spec->loc_host[0] = lhost;
208 spec->loc_port = lport;
209 spec->rem_host[0] = rhost;
210 spec->rem_port = rport;
211 return 0;
212}
213
138enum { 214enum {
139 EFX_FILTER_VID_UNSPEC = 0xffff, 215 EFX_FILTER_VID_UNSPEC = 0xffff,
140}; 216};
141 217
218/**
219 * efx_filter_set_eth_local - specify local Ethernet address and/or VID
220 * @spec: Specification to initialise
221 * @vid: Outer VLAN ID to match, or %EFX_FILTER_VID_UNSPEC
222 * @addr: Local Ethernet MAC address, or %NULL
223 */
224static inline int efx_filter_set_eth_local(struct efx_filter_spec *spec,
225 u16 vid, const u8 *addr)
226{
227 if (vid == EFX_FILTER_VID_UNSPEC && addr == NULL)
228 return -EINVAL;
229
230 if (vid != EFX_FILTER_VID_UNSPEC) {
231 spec->match_flags |= EFX_FILTER_MATCH_OUTER_VID;
232 spec->outer_vid = htons(vid);
233 }
234 if (addr != NULL) {
235 spec->match_flags |= EFX_FILTER_MATCH_LOC_MAC;
236 memcpy(spec->loc_mac, addr, ETH_ALEN);
237 }
238 return 0;
239}
240
241/**
242 * efx_filter_set_uc_def - specify matching otherwise-unmatched unicast
243 * @spec: Specification to initialise
244 */
245static inline int efx_filter_set_uc_def(struct efx_filter_spec *spec)
246{
247 spec->match_flags |= EFX_FILTER_MATCH_LOC_MAC_IG;
248 return 0;
249}
250
251/**
252 * efx_filter_set_mc_def - specify matching otherwise-unmatched multicast
253 * @spec: Specification to initialise
254 */
255static inline int efx_filter_set_mc_def(struct efx_filter_spec *spec)
256{
257 spec->match_flags |= EFX_FILTER_MATCH_LOC_MAC_IG;
258 spec->loc_mac[0] = 1;
259 return 0;
260}
261
142#endif /* EFX_FILTER_H */ 262#endif /* EFX_FILTER_H */