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_fdir_get_gen_prgm_pkt - generate a training packet
497  * @hw: pointer to the hardware structure
498  * @input: flow director filter data structure
499  * @pkt: pointer to return filter packet
500  * @frag: generate a fragment packet
501  * @tun: true implies generate a tunnel packet
502  */
503 enum ice_status
504 ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
505 			  u8 *pkt, bool frag, bool tun)
506 {
507 	enum ice_fltr_ptype flow;
508 	u16 tnl_port;
509 	u8 *loc;
510 	u16 idx;
511 
512 	if (input->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) {
513 		switch (input->ip.v4.proto) {
514 		case IPPROTO_TCP:
515 			flow = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
516 			break;
517 		case IPPROTO_UDP:
518 			flow = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
519 			break;
520 		case IPPROTO_SCTP:
521 			flow = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
522 			break;
523 		case IPPROTO_IP:
524 			flow = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
525 			break;
526 		default:
527 			return ICE_ERR_PARAM;
528 		}
529 	} else if (input->flow_type == ICE_FLTR_PTYPE_NONF_IPV6_OTHER) {
530 		switch (input->ip.v6.proto) {
531 		case IPPROTO_TCP:
532 			flow = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
533 			break;
534 		case IPPROTO_UDP:
535 			flow = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
536 			break;
537 		case IPPROTO_SCTP:
538 			flow = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
539 			break;
540 		case IPPROTO_IP:
541 			flow = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
542 			break;
543 		default:
544 			return ICE_ERR_PARAM;
545 		}
546 	} else {
547 		flow = input->flow_type;
548 	}
549 
550 	for (idx = 0; idx < ICE_FDIR_NUM_PKT; idx++)
551 		if (ice_fdir_pkt[idx].flow == flow)
552 			break;
553 	if (idx == ICE_FDIR_NUM_PKT)
554 		return ICE_ERR_PARAM;
555 	if (!tun) {
556 		memcpy(pkt, ice_fdir_pkt[idx].pkt, ice_fdir_pkt[idx].pkt_len);
557 		loc = pkt;
558 	} else {
559 		if (!ice_get_open_tunnel_port(hw, TNL_ALL, &tnl_port))
560 			return ICE_ERR_DOES_NOT_EXIST;
561 		if (!ice_fdir_pkt[idx].tun_pkt)
562 			return ICE_ERR_PARAM;
563 		memcpy(pkt, ice_fdir_pkt[idx].tun_pkt,
564 		       ice_fdir_pkt[idx].tun_pkt_len);
565 		ice_pkt_insert_u16(pkt, ICE_IPV4_UDP_DST_PORT_OFFSET,
566 				   htons(tnl_port));
567 		loc = &pkt[ICE_FDIR_TUN_PKT_OFF];
568 	}
569 
570 	/* Reverse the src and dst, since the HW expects them to be from Tx
571 	 * perspective. The input from user is from Rx filter perspective.
572 	 */
573 	switch (flow) {
574 	case ICE_FLTR_PTYPE_NONF_IPV4_TCP:
575 		ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
576 				   input->ip.v4.src_ip);
577 		ice_pkt_insert_u16(loc, ICE_IPV4_TCP_DST_PORT_OFFSET,
578 				   input->ip.v4.src_port);
579 		ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
580 				   input->ip.v4.dst_ip);
581 		ice_pkt_insert_u16(loc, ICE_IPV4_TCP_SRC_PORT_OFFSET,
582 				   input->ip.v4.dst_port);
583 		if (frag)
584 			loc[20] = ICE_FDIR_IPV4_PKT_FLAG_DF;
585 		break;
586 	case ICE_FLTR_PTYPE_NONF_IPV4_UDP:
587 		ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
588 				   input->ip.v4.src_ip);
589 		ice_pkt_insert_u16(loc, ICE_IPV4_UDP_DST_PORT_OFFSET,
590 				   input->ip.v4.src_port);
591 		ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
592 				   input->ip.v4.dst_ip);
593 		ice_pkt_insert_u16(loc, ICE_IPV4_UDP_SRC_PORT_OFFSET,
594 				   input->ip.v4.dst_port);
595 		break;
596 	case ICE_FLTR_PTYPE_NONF_IPV4_SCTP:
597 		ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
598 				   input->ip.v4.src_ip);
599 		ice_pkt_insert_u16(loc, ICE_IPV4_SCTP_DST_PORT_OFFSET,
600 				   input->ip.v4.src_port);
601 		ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
602 				   input->ip.v4.dst_ip);
603 		ice_pkt_insert_u16(loc, ICE_IPV4_SCTP_SRC_PORT_OFFSET,
604 				   input->ip.v4.dst_port);
605 		break;
606 	case ICE_FLTR_PTYPE_NONF_IPV4_OTHER:
607 		ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
608 				   input->ip.v4.src_ip);
609 		ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
610 				   input->ip.v4.dst_ip);
611 		ice_pkt_insert_u16(loc, ICE_IPV4_PROTO_OFFSET, 0);
612 		break;
613 	case ICE_FLTR_PTYPE_NONF_IPV6_TCP:
614 		ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
615 					 input->ip.v6.src_ip);
616 		ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
617 					 input->ip.v6.dst_ip);
618 		ice_pkt_insert_u16(loc, ICE_IPV6_TCP_DST_PORT_OFFSET,
619 				   input->ip.v6.src_port);
620 		ice_pkt_insert_u16(loc, ICE_IPV6_TCP_SRC_PORT_OFFSET,
621 				   input->ip.v6.dst_port);
622 		break;
623 	case ICE_FLTR_PTYPE_NONF_IPV6_UDP:
624 		ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
625 					 input->ip.v6.src_ip);
626 		ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
627 					 input->ip.v6.dst_ip);
628 		ice_pkt_insert_u16(loc, ICE_IPV6_UDP_DST_PORT_OFFSET,
629 				   input->ip.v6.src_port);
630 		ice_pkt_insert_u16(loc, ICE_IPV6_UDP_SRC_PORT_OFFSET,
631 				   input->ip.v6.dst_port);
632 		break;
633 	case ICE_FLTR_PTYPE_NONF_IPV6_SCTP:
634 		ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
635 					 input->ip.v6.src_ip);
636 		ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
637 					 input->ip.v6.dst_ip);
638 		ice_pkt_insert_u16(loc, ICE_IPV6_SCTP_DST_PORT_OFFSET,
639 				   input->ip.v6.src_port);
640 		ice_pkt_insert_u16(loc, ICE_IPV6_SCTP_SRC_PORT_OFFSET,
641 				   input->ip.v6.dst_port);
642 		break;
643 	case ICE_FLTR_PTYPE_NONF_IPV6_OTHER:
644 		ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
645 					 input->ip.v6.src_ip);
646 		ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
647 					 input->ip.v6.dst_ip);
648 		break;
649 	default:
650 		return ICE_ERR_PARAM;
651 	}
652 
653 	if (input->flex_fltr)
654 		ice_pkt_insert_u16(loc, input->flex_offset, input->flex_word);
655 
656 	return 0;
657 }
658 
659 /**
660  * ice_fdir_has_frag - does flow type have 2 ptypes
661  * @flow: flow ptype
662  *
663  * returns true is there is a fragment packet for this ptype
664  */
665 bool ice_fdir_has_frag(enum ice_fltr_ptype flow)
666 {
667 	if (flow == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
668 		return true;
669 	else
670 		return false;
671 }
672 
673 /**
674  * ice_fdir_find_by_idx - find filter with idx
675  * @hw: pointer to hardware structure
676  * @fltr_idx: index to find.
677  *
678  * Returns pointer to filter if found or null
679  */
680 struct ice_fdir_fltr *
681 ice_fdir_find_fltr_by_idx(struct ice_hw *hw, u32 fltr_idx)
682 {
683 	struct ice_fdir_fltr *rule;
684 
685 	list_for_each_entry(rule, &hw->fdir_list_head, fltr_node) {
686 		/* rule ID found in the list */
687 		if (fltr_idx == rule->fltr_id)
688 			return rule;
689 		if (fltr_idx < rule->fltr_id)
690 			break;
691 	}
692 	return NULL;
693 }
694 
695 /**
696  * ice_fdir_list_add_fltr - add a new node to the flow director filter list
697  * @hw: hardware structure
698  * @fltr: filter node to add to structure
699  */
700 void ice_fdir_list_add_fltr(struct ice_hw *hw, struct ice_fdir_fltr *fltr)
701 {
702 	struct ice_fdir_fltr *rule, *parent = NULL;
703 
704 	list_for_each_entry(rule, &hw->fdir_list_head, fltr_node) {
705 		/* rule ID found or pass its spot in the list */
706 		if (rule->fltr_id >= fltr->fltr_id)
707 			break;
708 		parent = rule;
709 	}
710 
711 	if (parent)
712 		list_add(&fltr->fltr_node, &parent->fltr_node);
713 	else
714 		list_add(&fltr->fltr_node, &hw->fdir_list_head);
715 }
716 
717 /**
718  * ice_fdir_update_cntrs - increment / decrement filter counter
719  * @hw: pointer to hardware structure
720  * @flow: filter flow type
721  * @add: true implies filters added
722  */
723 void
724 ice_fdir_update_cntrs(struct ice_hw *hw, enum ice_fltr_ptype flow, bool add)
725 {
726 	int incr;
727 
728 	incr = add ? 1 : -1;
729 	hw->fdir_active_fltr += incr;
730 
731 	if (flow == ICE_FLTR_PTYPE_NONF_NONE || flow >= ICE_FLTR_PTYPE_MAX)
732 		ice_debug(hw, ICE_DBG_SW, "Unknown filter type %d\n", flow);
733 	else
734 		hw->fdir_fltr_cnt[flow] += incr;
735 }
736 
737 /**
738  * ice_cmp_ipv6_addr - compare 2 IP v6 addresses
739  * @a: IP v6 address
740  * @b: IP v6 address
741  *
742  * Returns 0 on equal, returns non-0 if different
743  */
744 static int ice_cmp_ipv6_addr(__be32 *a, __be32 *b)
745 {
746 	return memcmp(a, b, 4 * sizeof(__be32));
747 }
748 
749 /**
750  * ice_fdir_comp_rules - compare 2 filters
751  * @a: a Flow Director filter data structure
752  * @b: a Flow Director filter data structure
753  * @v6: bool true if v6 filter
754  *
755  * Returns true if the filters match
756  */
757 static bool
758 ice_fdir_comp_rules(struct ice_fdir_fltr *a,  struct ice_fdir_fltr *b, bool v6)
759 {
760 	enum ice_fltr_ptype flow_type = a->flow_type;
761 
762 	/* The calling function already checks that the two filters have the
763 	 * same flow_type.
764 	 */
765 	if (!v6) {
766 		if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP ||
767 		    flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
768 		    flow_type == ICE_FLTR_PTYPE_NONF_IPV4_SCTP) {
769 			if (a->ip.v4.dst_ip == b->ip.v4.dst_ip &&
770 			    a->ip.v4.src_ip == b->ip.v4.src_ip &&
771 			    a->ip.v4.dst_port == b->ip.v4.dst_port &&
772 			    a->ip.v4.src_port == b->ip.v4.src_port)
773 				return true;
774 		} else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) {
775 			if (a->ip.v4.dst_ip == b->ip.v4.dst_ip &&
776 			    a->ip.v4.src_ip == b->ip.v4.src_ip &&
777 			    a->ip.v4.l4_header == b->ip.v4.l4_header &&
778 			    a->ip.v4.proto == b->ip.v4.proto &&
779 			    a->ip.v4.ip_ver == b->ip.v4.ip_ver &&
780 			    a->ip.v4.tos == b->ip.v4.tos)
781 				return true;
782 		}
783 	} else {
784 		if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP ||
785 		    flow_type == ICE_FLTR_PTYPE_NONF_IPV6_TCP ||
786 		    flow_type == ICE_FLTR_PTYPE_NONF_IPV6_SCTP) {
787 			if (a->ip.v6.dst_port == b->ip.v6.dst_port &&
788 			    a->ip.v6.src_port == b->ip.v6.src_port &&
789 			    !ice_cmp_ipv6_addr(a->ip.v6.dst_ip,
790 					       b->ip.v6.dst_ip) &&
791 			    !ice_cmp_ipv6_addr(a->ip.v6.src_ip,
792 					       b->ip.v6.src_ip))
793 				return true;
794 		} else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_OTHER) {
795 			if (a->ip.v6.dst_port == b->ip.v6.dst_port &&
796 			    a->ip.v6.src_port == b->ip.v6.src_port)
797 				return true;
798 		}
799 	}
800 
801 	return false;
802 }
803 
804 /**
805  * ice_fdir_is_dup_fltr - test if filter is already in list for PF
806  * @hw: hardware data structure
807  * @input: Flow Director filter data structure
808  *
809  * Returns true if the filter is found in the list
810  */
811 bool ice_fdir_is_dup_fltr(struct ice_hw *hw, struct ice_fdir_fltr *input)
812 {
813 	struct ice_fdir_fltr *rule;
814 	bool ret = false;
815 
816 	list_for_each_entry(rule, &hw->fdir_list_head, fltr_node) {
817 		enum ice_fltr_ptype flow_type;
818 
819 		if (rule->flow_type != input->flow_type)
820 			continue;
821 
822 		flow_type = input->flow_type;
823 		if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP ||
824 		    flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
825 		    flow_type == ICE_FLTR_PTYPE_NONF_IPV4_SCTP ||
826 		    flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
827 			ret = ice_fdir_comp_rules(rule, input, false);
828 		else
829 			ret = ice_fdir_comp_rules(rule, input, true);
830 		if (ret) {
831 			if (rule->fltr_id == input->fltr_id &&
832 			    rule->q_index != input->q_index)
833 				ret = false;
834 			else
835 				break;
836 		}
837 	}
838 
839 	return ret;
840 }
841