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