1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) 2018-2020, Intel Corporation. */
3 
4 #include "ice_common.h"
5 
6 /* These are training packet headers used to program flow director filters. */
7 static const u8 ice_fdir_tcpv4_pkt[] = {
8 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
9 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
10 	0x00, 0x28, 0x00, 0x01, 0x00, 0x00, 0x40, 0x06,
11 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
12 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
13 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00,
14 	0x20, 0x00, 0x00, 0x00, 0x00, 0x00
15 };
16 
17 static const u8 ice_fdir_udpv4_pkt[] = {
18 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
19 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
20 	0x00, 0x1C, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
21 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
22 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
23 	0x00, 0x00,
24 };
25 
26 static const u8 ice_fdir_sctpv4_pkt[] = {
27 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
28 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
29 	0x00, 0x20, 0x00, 0x00, 0x40, 0x00, 0x40, 0x84,
30 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
31 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
32 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
33 };
34 
35 static const u8 ice_fdir_ipv4_pkt[] = {
36 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
37 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
38 	0x00, 0x14, 0x00, 0x00, 0x40, 0x00, 0x40, 0x10,
39 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
40 	0x00, 0x00
41 };
42 
43 static const u8 ice_fdir_tcpv6_pkt[] = {
44 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
45 	0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00,
46 	0x00, 0x00, 0x00, 0x14, 0x06, 0x40, 0x00, 0x00,
47 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
48 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
49 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
50 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
51 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
52 	0x00, 0x00, 0x50, 0x00, 0x20, 0x00, 0x00, 0x00,
53 	0x00, 0x00,
54 };
55 
56 static const u8 ice_fdir_udpv6_pkt[] = {
57 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
58 	0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00,
59 	0x00, 0x00, 0x00, 0x08, 0x11, 0x40, 0x00, 0x00,
60 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
61 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
62 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
63 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
64 	0x00, 0x00, 0x00, 0x08, 0x00, 0x00,
65 };
66 
67 static const u8 ice_fdir_sctpv6_pkt[] = {
68 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
69 	0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00,
70 	0x00, 0x00, 0x00, 0x0C, 0x84, 0x40, 0x00, 0x00,
71 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
73 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
74 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
75 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
76 	0x00, 0x00,
77 };
78 
79 static const u8 ice_fdir_ipv6_pkt[] = {
80 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
81 	0x00, 0x00, 0x00, 0x00, 0x86, 0xDD, 0x60, 0x00,
82 	0x00, 0x00, 0x00, 0x00, 0x3B, 0x40, 0x00, 0x00,
83 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
84 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
85 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
86 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
87 };
88 
89 static const u8 ice_fdir_tcp4_tun_pkt[] = {
90 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
91 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
92 	0x00, 0x5a, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
93 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
94 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
95 	0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
96 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
97 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
98 	0x45, 0x00, 0x00, 0x28, 0x00, 0x00, 0x40, 0x00,
99 	0x40, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
100 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
101 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
102 	0x50, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
103 };
104 
105 static const u8 ice_fdir_udp4_tun_pkt[] = {
106 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
107 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
108 	0x00, 0x4e, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
109 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
110 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
111 	0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
112 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
113 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
114 	0x45, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x40, 0x00,
115 	0x40, 0x11, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
116 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
117 	0x00, 0x00, 0x00, 0x00,
118 };
119 
120 static const u8 ice_fdir_sctp4_tun_pkt[] = {
121 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
122 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
123 	0x00, 0x52, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
124 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
125 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
126 	0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
127 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
128 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
129 	0x45, 0x00, 0x00, 0x20, 0x00, 0x01, 0x00, 0x00,
130 	0x40, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
131 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
132 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
133 };
134 
135 static const u8 ice_fdir_ip4_tun_pkt[] = {
136 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
137 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
138 	0x00, 0x46, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
139 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
140 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
141 	0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
142 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
143 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00,
144 	0x45, 0x00, 0x00, 0x14, 0x00, 0x00, 0x00, 0x00,
145 	0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
146 	0x00, 0x00, 0x00, 0x00,
147 };
148 
149 static const u8 ice_fdir_tcp6_tun_pkt[] = {
150 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
151 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
152 	0x00, 0x6e, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
153 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
154 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
155 	0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
156 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
157 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xdd,
158 	0x60, 0x00, 0x00, 0x00, 0x00, 0x14, 0x06, 0x40,
159 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
160 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
161 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
162 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
163 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
164 	0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x20, 0x00,
165 	0x00, 0x00, 0x00, 0x00,
166 };
167 
168 static const u8 ice_fdir_udp6_tun_pkt[] = {
169 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
170 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
171 	0x00, 0x62, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
172 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
173 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
174 	0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
175 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
176 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xdd,
177 	0x60, 0x00, 0x00, 0x00, 0x00, 0x08, 0x11, 0x40,
178 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
179 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
180 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
181 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
182 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
183 };
184 
185 static const u8 ice_fdir_sctp6_tun_pkt[] = {
186 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
187 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
188 	0x00, 0x66, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
189 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
190 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
191 	0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
192 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
193 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xdd,
194 	0x60, 0x00, 0x00, 0x00, 0x00, 0x0c, 0x84, 0x40,
195 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
196 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
197 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
198 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
199 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
200 	0x00, 0x00, 0x00, 0x00,
201 };
202 
203 static const u8 ice_fdir_ip6_tun_pkt[] = {
204 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
205 	0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x45, 0x00,
206 	0x00, 0x5a, 0x00, 0x00, 0x40, 0x00, 0x40, 0x11,
207 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
208 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
209 	0x00, 0x00, 0x04, 0x00, 0x00, 0x03, 0x00, 0x00,
210 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
211 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0xdd,
212 	0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3b, 0x40,
213 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
214 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
215 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
216 	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
217 };
218 
219 /* Flow Director no-op training packet table */
220 static const struct ice_fdir_base_pkt ice_fdir_pkt[] = {
221 	{
222 		ICE_FLTR_PTYPE_NONF_IPV4_TCP,
223 		sizeof(ice_fdir_tcpv4_pkt), ice_fdir_tcpv4_pkt,
224 		sizeof(ice_fdir_tcp4_tun_pkt), ice_fdir_tcp4_tun_pkt,
225 	},
226 	{
227 		ICE_FLTR_PTYPE_NONF_IPV4_UDP,
228 		sizeof(ice_fdir_udpv4_pkt), ice_fdir_udpv4_pkt,
229 		sizeof(ice_fdir_udp4_tun_pkt), ice_fdir_udp4_tun_pkt,
230 	},
231 	{
232 		ICE_FLTR_PTYPE_NONF_IPV4_SCTP,
233 		sizeof(ice_fdir_sctpv4_pkt), ice_fdir_sctpv4_pkt,
234 		sizeof(ice_fdir_sctp4_tun_pkt), ice_fdir_sctp4_tun_pkt,
235 	},
236 	{
237 		ICE_FLTR_PTYPE_NONF_IPV4_OTHER,
238 		sizeof(ice_fdir_ipv4_pkt), ice_fdir_ipv4_pkt,
239 		sizeof(ice_fdir_ip4_tun_pkt), ice_fdir_ip4_tun_pkt,
240 	},
241 	{
242 		ICE_FLTR_PTYPE_NONF_IPV6_TCP,
243 		sizeof(ice_fdir_tcpv6_pkt), ice_fdir_tcpv6_pkt,
244 		sizeof(ice_fdir_tcp6_tun_pkt), ice_fdir_tcp6_tun_pkt,
245 	},
246 	{
247 		ICE_FLTR_PTYPE_NONF_IPV6_UDP,
248 		sizeof(ice_fdir_udpv6_pkt), ice_fdir_udpv6_pkt,
249 		sizeof(ice_fdir_udp6_tun_pkt), ice_fdir_udp6_tun_pkt,
250 	},
251 	{
252 		ICE_FLTR_PTYPE_NONF_IPV6_SCTP,
253 		sizeof(ice_fdir_sctpv6_pkt), ice_fdir_sctpv6_pkt,
254 		sizeof(ice_fdir_sctp6_tun_pkt), ice_fdir_sctp6_tun_pkt,
255 	},
256 	{
257 		ICE_FLTR_PTYPE_NONF_IPV6_OTHER,
258 		sizeof(ice_fdir_ipv6_pkt), ice_fdir_ipv6_pkt,
259 		sizeof(ice_fdir_ip6_tun_pkt), ice_fdir_ip6_tun_pkt,
260 	},
261 };
262 
263 #define ICE_FDIR_NUM_PKT ARRAY_SIZE(ice_fdir_pkt)
264 
265 /**
266  * ice_set_dflt_val_fd_desc
267  * @fd_fltr_ctx: pointer to fd filter descriptor
268  */
269 static void ice_set_dflt_val_fd_desc(struct ice_fd_fltr_desc_ctx *fd_fltr_ctx)
270 {
271 	fd_fltr_ctx->comp_q = ICE_FXD_FLTR_QW0_COMP_Q_ZERO;
272 	fd_fltr_ctx->comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW_FAIL;
273 	fd_fltr_ctx->fd_space = ICE_FXD_FLTR_QW0_FD_SPACE_GUAR_BEST;
274 	fd_fltr_ctx->cnt_ena = ICE_FXD_FLTR_QW0_STAT_ENA_PKTS;
275 	fd_fltr_ctx->evict_ena = ICE_FXD_FLTR_QW0_EVICT_ENA_TRUE;
276 	fd_fltr_ctx->toq = ICE_FXD_FLTR_QW0_TO_Q_EQUALS_QINDEX;
277 	fd_fltr_ctx->toq_prio = ICE_FXD_FLTR_QW0_TO_Q_PRIO1;
278 	fd_fltr_ctx->dpu_recipe = ICE_FXD_FLTR_QW0_DPU_RECIPE_DFLT;
279 	fd_fltr_ctx->drop = ICE_FXD_FLTR_QW0_DROP_NO;
280 	fd_fltr_ctx->flex_prio = ICE_FXD_FLTR_QW0_FLEX_PRI_NONE;
281 	fd_fltr_ctx->flex_mdid = ICE_FXD_FLTR_QW0_FLEX_MDID0;
282 	fd_fltr_ctx->flex_val = ICE_FXD_FLTR_QW0_FLEX_VAL0;
283 	fd_fltr_ctx->dtype = ICE_TX_DESC_DTYPE_FLTR_PROG;
284 	fd_fltr_ctx->desc_prof_prio = ICE_FXD_FLTR_QW1_PROF_PRIO_ZERO;
285 	fd_fltr_ctx->desc_prof = ICE_FXD_FLTR_QW1_PROF_ZERO;
286 	fd_fltr_ctx->swap = ICE_FXD_FLTR_QW1_SWAP_SET;
287 	fd_fltr_ctx->fdid_prio = ICE_FXD_FLTR_QW1_FDID_PRI_ONE;
288 	fd_fltr_ctx->fdid_mdid = ICE_FXD_FLTR_QW1_FDID_MDID_FD;
289 	fd_fltr_ctx->fdid = ICE_FXD_FLTR_QW1_FDID_ZERO;
290 }
291 
292 /**
293  * ice_set_fd_desc_val
294  * @ctx: pointer to fd filter descriptor context
295  * @fdir_desc: populated with fd filter descriptor values
296  */
297 static void
298 ice_set_fd_desc_val(struct ice_fd_fltr_desc_ctx *ctx,
299 		    struct ice_fltr_desc *fdir_desc)
300 {
301 	u64 qword;
302 
303 	/* prep QW0 of FD filter programming desc */
304 	qword = ((u64)ctx->qindex << ICE_FXD_FLTR_QW0_QINDEX_S) &
305 		ICE_FXD_FLTR_QW0_QINDEX_M;
306 	qword |= ((u64)ctx->comp_q << ICE_FXD_FLTR_QW0_COMP_Q_S) &
307 		 ICE_FXD_FLTR_QW0_COMP_Q_M;
308 	qword |= ((u64)ctx->comp_report << ICE_FXD_FLTR_QW0_COMP_REPORT_S) &
309 		 ICE_FXD_FLTR_QW0_COMP_REPORT_M;
310 	qword |= ((u64)ctx->fd_space << ICE_FXD_FLTR_QW0_FD_SPACE_S) &
311 		 ICE_FXD_FLTR_QW0_FD_SPACE_M;
312 	qword |= ((u64)ctx->cnt_index << ICE_FXD_FLTR_QW0_STAT_CNT_S) &
313 		 ICE_FXD_FLTR_QW0_STAT_CNT_M;
314 	qword |= ((u64)ctx->cnt_ena << ICE_FXD_FLTR_QW0_STAT_ENA_S) &
315 		 ICE_FXD_FLTR_QW0_STAT_ENA_M;
316 	qword |= ((u64)ctx->evict_ena << ICE_FXD_FLTR_QW0_EVICT_ENA_S) &
317 		 ICE_FXD_FLTR_QW0_EVICT_ENA_M;
318 	qword |= ((u64)ctx->toq << ICE_FXD_FLTR_QW0_TO_Q_S) &
319 		 ICE_FXD_FLTR_QW0_TO_Q_M;
320 	qword |= ((u64)ctx->toq_prio << ICE_FXD_FLTR_QW0_TO_Q_PRI_S) &
321 		 ICE_FXD_FLTR_QW0_TO_Q_PRI_M;
322 	qword |= ((u64)ctx->dpu_recipe << ICE_FXD_FLTR_QW0_DPU_RECIPE_S) &
323 		 ICE_FXD_FLTR_QW0_DPU_RECIPE_M;
324 	qword |= ((u64)ctx->drop << ICE_FXD_FLTR_QW0_DROP_S) &
325 		 ICE_FXD_FLTR_QW0_DROP_M;
326 	qword |= ((u64)ctx->flex_prio << ICE_FXD_FLTR_QW0_FLEX_PRI_S) &
327 		 ICE_FXD_FLTR_QW0_FLEX_PRI_M;
328 	qword |= ((u64)ctx->flex_mdid << ICE_FXD_FLTR_QW0_FLEX_MDID_S) &
329 		 ICE_FXD_FLTR_QW0_FLEX_MDID_M;
330 	qword |= ((u64)ctx->flex_val << ICE_FXD_FLTR_QW0_FLEX_VAL_S) &
331 		 ICE_FXD_FLTR_QW0_FLEX_VAL_M;
332 	fdir_desc->qidx_compq_space_stat = cpu_to_le64(qword);
333 
334 	/* prep QW1 of FD filter programming desc */
335 	qword = ((u64)ctx->dtype << ICE_FXD_FLTR_QW1_DTYPE_S) &
336 		ICE_FXD_FLTR_QW1_DTYPE_M;
337 	qword |= ((u64)ctx->pcmd << ICE_FXD_FLTR_QW1_PCMD_S) &
338 		 ICE_FXD_FLTR_QW1_PCMD_M;
339 	qword |= ((u64)ctx->desc_prof_prio << ICE_FXD_FLTR_QW1_PROF_PRI_S) &
340 		 ICE_FXD_FLTR_QW1_PROF_PRI_M;
341 	qword |= ((u64)ctx->desc_prof << ICE_FXD_FLTR_QW1_PROF_S) &
342 		 ICE_FXD_FLTR_QW1_PROF_M;
343 	qword |= ((u64)ctx->fd_vsi << ICE_FXD_FLTR_QW1_FD_VSI_S) &
344 		 ICE_FXD_FLTR_QW1_FD_VSI_M;
345 	qword |= ((u64)ctx->swap << ICE_FXD_FLTR_QW1_SWAP_S) &
346 		 ICE_FXD_FLTR_QW1_SWAP_M;
347 	qword |= ((u64)ctx->fdid_prio << ICE_FXD_FLTR_QW1_FDID_PRI_S) &
348 		 ICE_FXD_FLTR_QW1_FDID_PRI_M;
349 	qword |= ((u64)ctx->fdid_mdid << ICE_FXD_FLTR_QW1_FDID_MDID_S) &
350 		 ICE_FXD_FLTR_QW1_FDID_MDID_M;
351 	qword |= ((u64)ctx->fdid << ICE_FXD_FLTR_QW1_FDID_S) &
352 		 ICE_FXD_FLTR_QW1_FDID_M;
353 	fdir_desc->dtype_cmd_vsi_fdid = cpu_to_le64(qword);
354 }
355 
356 /**
357  * ice_fdir_get_prgm_desc - set a fdir descriptor from a fdir filter struct
358  * @hw: pointer to the hardware structure
359  * @input: filter
360  * @fdesc: filter descriptor
361  * @add: if add is true, this is an add operation, false implies delete
362  */
363 void
364 ice_fdir_get_prgm_desc(struct ice_hw *hw, struct ice_fdir_fltr *input,
365 		       struct ice_fltr_desc *fdesc, bool add)
366 {
367 	struct ice_fd_fltr_desc_ctx fdir_fltr_ctx = { 0 };
368 
369 	/* set default context info */
370 	ice_set_dflt_val_fd_desc(&fdir_fltr_ctx);
371 
372 	/* change sideband filtering values */
373 	fdir_fltr_ctx.fdid = input->fltr_id;
374 	if (input->dest_ctl == ICE_FLTR_PRGM_DESC_DEST_DROP_PKT) {
375 		fdir_fltr_ctx.drop = ICE_FXD_FLTR_QW0_DROP_YES;
376 		fdir_fltr_ctx.qindex = 0;
377 	} else {
378 		fdir_fltr_ctx.drop = ICE_FXD_FLTR_QW0_DROP_NO;
379 		fdir_fltr_ctx.qindex = input->q_index;
380 	}
381 	fdir_fltr_ctx.cnt_ena = ICE_FXD_FLTR_QW0_STAT_ENA_PKTS;
382 	fdir_fltr_ctx.cnt_index = input->cnt_index;
383 	fdir_fltr_ctx.fd_vsi = ice_get_hw_vsi_num(hw, input->dest_vsi);
384 	fdir_fltr_ctx.evict_ena = ICE_FXD_FLTR_QW0_EVICT_ENA_FALSE;
385 	fdir_fltr_ctx.toq_prio = 3;
386 	fdir_fltr_ctx.pcmd = add ? ICE_FXD_FLTR_QW1_PCMD_ADD :
387 		ICE_FXD_FLTR_QW1_PCMD_REMOVE;
388 	fdir_fltr_ctx.swap = ICE_FXD_FLTR_QW1_SWAP_NOT_SET;
389 	fdir_fltr_ctx.comp_q = ICE_FXD_FLTR_QW0_COMP_Q_ZERO;
390 	fdir_fltr_ctx.comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW_FAIL;
391 	fdir_fltr_ctx.fdid_prio = 3;
392 	fdir_fltr_ctx.desc_prof = 1;
393 	fdir_fltr_ctx.desc_prof_prio = 3;
394 	ice_set_fd_desc_val(&fdir_fltr_ctx, fdesc);
395 }
396 
397 /**
398  * ice_alloc_fd_res_cntr - obtain counter resource for FD type
399  * @hw: pointer to the hardware structure
400  * @cntr_id: returns counter index
401  */
402 enum ice_status ice_alloc_fd_res_cntr(struct ice_hw *hw, u16 *cntr_id)
403 {
404 	return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_COUNTER_BLOCK,
405 				  ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, cntr_id);
406 }
407 
408 /**
409  * ice_free_fd_res_cntr - Free counter resource for FD type
410  * @hw: pointer to the hardware structure
411  * @cntr_id: counter index to be freed
412  */
413 enum ice_status ice_free_fd_res_cntr(struct ice_hw *hw, u16 cntr_id)
414 {
415 	return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_COUNTER_BLOCK,
416 				 ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, cntr_id);
417 }
418 
419 /**
420  * ice_alloc_fd_guar_item - allocate resource for FD guaranteed entries
421  * @hw: pointer to the hardware structure
422  * @cntr_id: returns counter index
423  * @num_fltr: number of filter entries to be allocated
424  */
425 enum ice_status
426 ice_alloc_fd_guar_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr)
427 {
428 	return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_GUARANTEED_ENTRIES,
429 				  ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
430 				  cntr_id);
431 }
432 
433 /**
434  * ice_alloc_fd_shrd_item - allocate resource for flow director shared entries
435  * @hw: pointer to the hardware structure
436  * @cntr_id: returns counter index
437  * @num_fltr: number of filter entries to be allocated
438  */
439 enum ice_status
440 ice_alloc_fd_shrd_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr)
441 {
442 	return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_SHARED_ENTRIES,
443 				  ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
444 				  cntr_id);
445 }
446 
447 /**
448  * ice_get_fdir_cnt_all - get the number of Flow Director filters
449  * @hw: hardware data structure
450  *
451  * Returns the number of filters available on device
452  */
453 int ice_get_fdir_cnt_all(struct ice_hw *hw)
454 {
455 	return hw->func_caps.fd_fltr_guar + hw->func_caps.fd_fltr_best_effort;
456 }
457 
458 /**
459  * ice_pkt_insert_ipv6_addr - insert a be32 IPv6 address into a memory buffer
460  * @pkt: packet buffer
461  * @offset: offset into buffer
462  * @addr: IPv6 address to convert and insert into pkt at offset
463  */
464 static void ice_pkt_insert_ipv6_addr(u8 *pkt, int offset, __be32 *addr)
465 {
466 	int idx;
467 
468 	for (idx = 0; idx < ICE_IPV6_ADDR_LEN_AS_U32; idx++)
469 		memcpy(pkt + offset + idx * sizeof(*addr), &addr[idx],
470 		       sizeof(*addr));
471 }
472 
473 /**
474  * ice_pkt_insert_u16 - insert a be16 value into a memory buffer
475  * @pkt: packet buffer
476  * @offset: offset into buffer
477  * @data: 16 bit value to convert and insert into pkt at offset
478  */
479 static void ice_pkt_insert_u16(u8 *pkt, int offset, __be16 data)
480 {
481 	memcpy(pkt + offset, &data, sizeof(data));
482 }
483 
484 /**
485  * ice_pkt_insert_u32 - insert a be32 value into a memory buffer
486  * @pkt: packet buffer
487  * @offset: offset into buffer
488  * @data: 32 bit value to convert and insert into pkt at offset
489  */
490 static void ice_pkt_insert_u32(u8 *pkt, int offset, __be32 data)
491 {
492 	memcpy(pkt + offset, &data, sizeof(data));
493 }
494 
495 /**
496  * ice_pkt_insert_mac_addr - insert a MAC addr into a memory buffer.
497  * @pkt: packet buffer
498  * @addr: MAC address to convert and insert into pkt at offset
499  */
500 static void ice_pkt_insert_mac_addr(u8 *pkt, u8 *addr)
501 {
502 	ether_addr_copy(pkt, addr);
503 }
504 
505 /**
506  * ice_fdir_get_gen_prgm_pkt - generate a training packet
507  * @hw: pointer to the hardware structure
508  * @input: flow director filter data structure
509  * @pkt: pointer to return filter packet
510  * @frag: generate a fragment packet
511  * @tun: true implies generate a tunnel packet
512  */
513 enum ice_status
514 ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
515 			  u8 *pkt, bool frag, bool tun)
516 {
517 	enum ice_fltr_ptype flow;
518 	u16 tnl_port;
519 	u8 *loc;
520 	u16 idx;
521 
522 	if (input->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) {
523 		switch (input->ip.v4.proto) {
524 		case IPPROTO_TCP:
525 			flow = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
526 			break;
527 		case IPPROTO_UDP:
528 			flow = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
529 			break;
530 		case IPPROTO_SCTP:
531 			flow = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
532 			break;
533 		case IPPROTO_IP:
534 			flow = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
535 			break;
536 		default:
537 			return ICE_ERR_PARAM;
538 		}
539 	} else if (input->flow_type == ICE_FLTR_PTYPE_NONF_IPV6_OTHER) {
540 		switch (input->ip.v6.proto) {
541 		case IPPROTO_TCP:
542 			flow = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
543 			break;
544 		case IPPROTO_UDP:
545 			flow = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
546 			break;
547 		case IPPROTO_SCTP:
548 			flow = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
549 			break;
550 		case IPPROTO_IP:
551 			flow = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
552 			break;
553 		default:
554 			return ICE_ERR_PARAM;
555 		}
556 	} else {
557 		flow = input->flow_type;
558 	}
559 
560 	for (idx = 0; idx < ICE_FDIR_NUM_PKT; idx++)
561 		if (ice_fdir_pkt[idx].flow == flow)
562 			break;
563 	if (idx == ICE_FDIR_NUM_PKT)
564 		return ICE_ERR_PARAM;
565 	if (!tun) {
566 		memcpy(pkt, ice_fdir_pkt[idx].pkt, ice_fdir_pkt[idx].pkt_len);
567 		loc = pkt;
568 	} else {
569 		if (!ice_get_open_tunnel_port(hw, &tnl_port))
570 			return ICE_ERR_DOES_NOT_EXIST;
571 		if (!ice_fdir_pkt[idx].tun_pkt)
572 			return ICE_ERR_PARAM;
573 		memcpy(pkt, ice_fdir_pkt[idx].tun_pkt,
574 		       ice_fdir_pkt[idx].tun_pkt_len);
575 		ice_pkt_insert_u16(pkt, ICE_IPV4_UDP_DST_PORT_OFFSET,
576 				   htons(tnl_port));
577 		loc = &pkt[ICE_FDIR_TUN_PKT_OFF];
578 	}
579 
580 	/* Reverse the src and dst, since the HW expects them to be from Tx
581 	 * perspective. The input from user is from Rx filter perspective.
582 	 */
583 	switch (flow) {
584 	case ICE_FLTR_PTYPE_NONF_IPV4_TCP:
585 		ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
586 				   input->ip.v4.src_ip);
587 		ice_pkt_insert_u16(loc, ICE_IPV4_TCP_DST_PORT_OFFSET,
588 				   input->ip.v4.src_port);
589 		ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
590 				   input->ip.v4.dst_ip);
591 		ice_pkt_insert_u16(loc, ICE_IPV4_TCP_SRC_PORT_OFFSET,
592 				   input->ip.v4.dst_port);
593 		ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
594 		if (frag)
595 			loc[20] = ICE_FDIR_IPV4_PKT_FLAG_DF;
596 		break;
597 	case ICE_FLTR_PTYPE_NONF_IPV4_UDP:
598 		ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
599 				   input->ip.v4.src_ip);
600 		ice_pkt_insert_u16(loc, ICE_IPV4_UDP_DST_PORT_OFFSET,
601 				   input->ip.v4.src_port);
602 		ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
603 				   input->ip.v4.dst_ip);
604 		ice_pkt_insert_u16(loc, ICE_IPV4_UDP_SRC_PORT_OFFSET,
605 				   input->ip.v4.dst_port);
606 		ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
607 		ice_pkt_insert_mac_addr(loc + ETH_ALEN,
608 					input->ext_data.src_mac);
609 		break;
610 	case ICE_FLTR_PTYPE_NONF_IPV4_SCTP:
611 		ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
612 				   input->ip.v4.src_ip);
613 		ice_pkt_insert_u16(loc, ICE_IPV4_SCTP_DST_PORT_OFFSET,
614 				   input->ip.v4.src_port);
615 		ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
616 				   input->ip.v4.dst_ip);
617 		ice_pkt_insert_u16(loc, ICE_IPV4_SCTP_SRC_PORT_OFFSET,
618 				   input->ip.v4.dst_port);
619 		ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
620 		break;
621 	case ICE_FLTR_PTYPE_NONF_IPV4_OTHER:
622 		ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
623 				   input->ip.v4.src_ip);
624 		ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
625 				   input->ip.v4.dst_ip);
626 		ice_pkt_insert_u16(loc, ICE_IPV4_PROTO_OFFSET, 0);
627 		ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
628 		break;
629 	case ICE_FLTR_PTYPE_NONF_IPV6_TCP:
630 		ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
631 					 input->ip.v6.src_ip);
632 		ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
633 					 input->ip.v6.dst_ip);
634 		ice_pkt_insert_u16(loc, ICE_IPV6_TCP_DST_PORT_OFFSET,
635 				   input->ip.v6.src_port);
636 		ice_pkt_insert_u16(loc, ICE_IPV6_TCP_SRC_PORT_OFFSET,
637 				   input->ip.v6.dst_port);
638 		ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
639 		break;
640 	case ICE_FLTR_PTYPE_NONF_IPV6_UDP:
641 		ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
642 					 input->ip.v6.src_ip);
643 		ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
644 					 input->ip.v6.dst_ip);
645 		ice_pkt_insert_u16(loc, ICE_IPV6_UDP_DST_PORT_OFFSET,
646 				   input->ip.v6.src_port);
647 		ice_pkt_insert_u16(loc, ICE_IPV6_UDP_SRC_PORT_OFFSET,
648 				   input->ip.v6.dst_port);
649 		ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
650 		break;
651 	case ICE_FLTR_PTYPE_NONF_IPV6_SCTP:
652 		ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
653 					 input->ip.v6.src_ip);
654 		ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
655 					 input->ip.v6.dst_ip);
656 		ice_pkt_insert_u16(loc, ICE_IPV6_SCTP_DST_PORT_OFFSET,
657 				   input->ip.v6.src_port);
658 		ice_pkt_insert_u16(loc, ICE_IPV6_SCTP_SRC_PORT_OFFSET,
659 				   input->ip.v6.dst_port);
660 		ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
661 		break;
662 	case ICE_FLTR_PTYPE_NONF_IPV6_OTHER:
663 		ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
664 					 input->ip.v6.src_ip);
665 		ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
666 					 input->ip.v6.dst_ip);
667 		ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
668 		break;
669 	default:
670 		return ICE_ERR_PARAM;
671 	}
672 
673 	if (input->flex_fltr)
674 		ice_pkt_insert_u16(loc, input->flex_offset, input->flex_word);
675 
676 	return 0;
677 }
678 
679 /**
680  * ice_fdir_has_frag - does flow type have 2 ptypes
681  * @flow: flow ptype
682  *
683  * returns true is there is a fragment packet for this ptype
684  */
685 bool ice_fdir_has_frag(enum ice_fltr_ptype flow)
686 {
687 	if (flow == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
688 		return true;
689 	else
690 		return false;
691 }
692 
693 /**
694  * ice_fdir_find_by_idx - find filter with idx
695  * @hw: pointer to hardware structure
696  * @fltr_idx: index to find.
697  *
698  * Returns pointer to filter if found or null
699  */
700 struct ice_fdir_fltr *
701 ice_fdir_find_fltr_by_idx(struct ice_hw *hw, u32 fltr_idx)
702 {
703 	struct ice_fdir_fltr *rule;
704 
705 	list_for_each_entry(rule, &hw->fdir_list_head, fltr_node) {
706 		/* rule ID found in the list */
707 		if (fltr_idx == rule->fltr_id)
708 			return rule;
709 		if (fltr_idx < rule->fltr_id)
710 			break;
711 	}
712 	return NULL;
713 }
714 
715 /**
716  * ice_fdir_list_add_fltr - add a new node to the flow director filter list
717  * @hw: hardware structure
718  * @fltr: filter node to add to structure
719  */
720 void ice_fdir_list_add_fltr(struct ice_hw *hw, struct ice_fdir_fltr *fltr)
721 {
722 	struct ice_fdir_fltr *rule, *parent = NULL;
723 
724 	list_for_each_entry(rule, &hw->fdir_list_head, fltr_node) {
725 		/* rule ID found or pass its spot in the list */
726 		if (rule->fltr_id >= fltr->fltr_id)
727 			break;
728 		parent = rule;
729 	}
730 
731 	if (parent)
732 		list_add(&fltr->fltr_node, &parent->fltr_node);
733 	else
734 		list_add(&fltr->fltr_node, &hw->fdir_list_head);
735 }
736 
737 /**
738  * ice_fdir_update_cntrs - increment / decrement filter counter
739  * @hw: pointer to hardware structure
740  * @flow: filter flow type
741  * @add: true implies filters added
742  */
743 void
744 ice_fdir_update_cntrs(struct ice_hw *hw, enum ice_fltr_ptype flow, bool add)
745 {
746 	int incr;
747 
748 	incr = add ? 1 : -1;
749 	hw->fdir_active_fltr += incr;
750 
751 	if (flow == ICE_FLTR_PTYPE_NONF_NONE || flow >= ICE_FLTR_PTYPE_MAX)
752 		ice_debug(hw, ICE_DBG_SW, "Unknown filter type %d\n", flow);
753 	else
754 		hw->fdir_fltr_cnt[flow] += incr;
755 }
756 
757 /**
758  * ice_cmp_ipv6_addr - compare 2 IP v6 addresses
759  * @a: IP v6 address
760  * @b: IP v6 address
761  *
762  * Returns 0 on equal, returns non-0 if different
763  */
764 static int ice_cmp_ipv6_addr(__be32 *a, __be32 *b)
765 {
766 	return memcmp(a, b, 4 * sizeof(__be32));
767 }
768 
769 /**
770  * ice_fdir_comp_rules - compare 2 filters
771  * @a: a Flow Director filter data structure
772  * @b: a Flow Director filter data structure
773  * @v6: bool true if v6 filter
774  *
775  * Returns true if the filters match
776  */
777 static bool
778 ice_fdir_comp_rules(struct ice_fdir_fltr *a,  struct ice_fdir_fltr *b, bool v6)
779 {
780 	enum ice_fltr_ptype flow_type = a->flow_type;
781 
782 	/* The calling function already checks that the two filters have the
783 	 * same flow_type.
784 	 */
785 	if (!v6) {
786 		if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP ||
787 		    flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
788 		    flow_type == ICE_FLTR_PTYPE_NONF_IPV4_SCTP) {
789 			if (a->ip.v4.dst_ip == b->ip.v4.dst_ip &&
790 			    a->ip.v4.src_ip == b->ip.v4.src_ip &&
791 			    a->ip.v4.dst_port == b->ip.v4.dst_port &&
792 			    a->ip.v4.src_port == b->ip.v4.src_port)
793 				return true;
794 		} else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) {
795 			if (a->ip.v4.dst_ip == b->ip.v4.dst_ip &&
796 			    a->ip.v4.src_ip == b->ip.v4.src_ip &&
797 			    a->ip.v4.l4_header == b->ip.v4.l4_header &&
798 			    a->ip.v4.proto == b->ip.v4.proto &&
799 			    a->ip.v4.ip_ver == b->ip.v4.ip_ver &&
800 			    a->ip.v4.tos == b->ip.v4.tos)
801 				return true;
802 		}
803 	} else {
804 		if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP ||
805 		    flow_type == ICE_FLTR_PTYPE_NONF_IPV6_TCP ||
806 		    flow_type == ICE_FLTR_PTYPE_NONF_IPV6_SCTP) {
807 			if (a->ip.v6.dst_port == b->ip.v6.dst_port &&
808 			    a->ip.v6.src_port == b->ip.v6.src_port &&
809 			    !ice_cmp_ipv6_addr(a->ip.v6.dst_ip,
810 					       b->ip.v6.dst_ip) &&
811 			    !ice_cmp_ipv6_addr(a->ip.v6.src_ip,
812 					       b->ip.v6.src_ip))
813 				return true;
814 		} else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_OTHER) {
815 			if (a->ip.v6.dst_port == b->ip.v6.dst_port &&
816 			    a->ip.v6.src_port == b->ip.v6.src_port)
817 				return true;
818 		}
819 	}
820 
821 	return false;
822 }
823 
824 /**
825  * ice_fdir_is_dup_fltr - test if filter is already in list for PF
826  * @hw: hardware data structure
827  * @input: Flow Director filter data structure
828  *
829  * Returns true if the filter is found in the list
830  */
831 bool ice_fdir_is_dup_fltr(struct ice_hw *hw, struct ice_fdir_fltr *input)
832 {
833 	struct ice_fdir_fltr *rule;
834 	bool ret = false;
835 
836 	list_for_each_entry(rule, &hw->fdir_list_head, fltr_node) {
837 		enum ice_fltr_ptype flow_type;
838 
839 		if (rule->flow_type != input->flow_type)
840 			continue;
841 
842 		flow_type = input->flow_type;
843 		if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP ||
844 		    flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
845 		    flow_type == ICE_FLTR_PTYPE_NONF_IPV4_SCTP ||
846 		    flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
847 			ret = ice_fdir_comp_rules(rule, input, false);
848 		else
849 			ret = ice_fdir_comp_rules(rule, input, true);
850 		if (ret) {
851 			if (rule->fltr_id == input->fltr_id &&
852 			    rule->q_index != input->q_index)
853 				ret = false;
854 			else
855 				break;
856 		}
857 	}
858 
859 	return ret;
860 }
861