3a2175b30f0cf7b0adf88790a250eee3a50b923b
[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                 if (input->dest_ctl ==
347                     ICE_FLTR_PRGM_DESC_DEST_DIRECT_PKT_QGROUP)
348                         fdir_fltr_ctx.toq = input->q_region;
349                 fdir_fltr_ctx.drop = ICE_FXD_FLTR_QW0_DROP_NO;
350                 fdir_fltr_ctx.qindex = input->q_index;
351         }
352         fdir_fltr_ctx.cnt_ena = input->cnt_ena;
353         fdir_fltr_ctx.cnt_index = input->cnt_index;
354         fdir_fltr_ctx.fd_vsi = ice_get_hw_vsi_num(hw, input->dest_vsi);
355         fdir_fltr_ctx.evict_ena = ICE_FXD_FLTR_QW0_EVICT_ENA_FALSE;
356         fdir_fltr_ctx.toq_prio = 3;
357         fdir_fltr_ctx.pcmd = (add) ? ICE_FXD_FLTR_QW1_PCMD_ADD :
358                 ICE_FXD_FLTR_QW1_PCMD_REMOVE;
359         fdir_fltr_ctx.swap = ICE_FXD_FLTR_QW1_SWAP_NOT_SET;
360         fdir_fltr_ctx.comp_q = ICE_FXD_FLTR_QW0_COMP_Q_ZERO;
361         fdir_fltr_ctx.comp_report = ICE_FXD_FLTR_QW0_COMP_REPORT_SW;
362         fdir_fltr_ctx.fdid_prio = 3;
363         fdir_fltr_ctx.desc_prof = 1;
364         fdir_fltr_ctx.desc_prof_prio = 3;
365         ice_set_fd_desc_val(&fdir_fltr_ctx, fdesc);
366 }
367
368 /**
369  * ice_set_fd_desc_val
370  * @fd_fltr_ctx: pointer to fd filter descriptor context
371  * @fdir_desc: populated with fd filter descriptor values
372  */
373 void
374 ice_set_fd_desc_val(struct ice_fd_fltr_desc_ctx *fd_fltr_ctx,
375                     struct ice_fltr_desc *fdir_desc)
376 {
377         u64 ctx_buf[2] = { 0 };
378
379         ice_set_ctx((u8 *)fd_fltr_ctx, (u8 *)ctx_buf,
380                     ice_fd_fltr_desc_ctx_info);
381         fdir_desc->qidx_compq_space_stat = CPU_TO_LE64(ctx_buf[0]);
382         fdir_desc->dtype_cmd_vsi_fdid = CPU_TO_LE64(ctx_buf[1]);
383 }
384
385 /**
386  * ice_alloc_fd_res_cntr - obtain counter resource for FD type
387  * @hw: pointer to the hardware structure
388  * @cntr_id: returns counter index
389  */
390 enum ice_status ice_alloc_fd_res_cntr(struct ice_hw *hw, u16 *cntr_id)
391 {
392         return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_COUNTER_BLOCK,
393                                   ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, cntr_id);
394 }
395
396 /**
397  * ice_free_fd_res_cntr - Free counter resource for FD type
398  * @hw: pointer to the hardware structure
399  * @cntr_id: counter index to be freed
400  */
401 enum ice_status ice_free_fd_res_cntr(struct ice_hw *hw, u16 cntr_id)
402 {
403         return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_COUNTER_BLOCK,
404                                  ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, cntr_id);
405 }
406
407 /**
408  * ice_alloc_fd_guar_item - allocate resource for FD guaranteed entries
409  * @hw: pointer to the hardware structure
410  * @cntr_id: returns counter index
411  * @num_fltr: number of filter entries to be allocated
412  */
413 enum ice_status
414 ice_alloc_fd_guar_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr)
415 {
416         return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_GUARANTEED_ENTRIES,
417                                   ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
418                                   cntr_id);
419 }
420
421 /**
422  * ice_free_fd_guar_item - Free flow director guaranteed entries
423  * @hw: pointer to the hardware structure
424  * @cntr_id: counter index that needs to be freed
425  * @num_fltr: number of filters to be freed
426  */
427 enum ice_status
428 ice_free_fd_guar_item(struct ice_hw *hw, u16 cntr_id, u16 num_fltr)
429 {
430         return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_GUARANTEED_ENTRIES,
431                                  ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
432                                  cntr_id);
433 }
434
435 /**
436  * ice_alloc_fd_shrd_item - allocate resource for flow director shared entries
437  * @hw: pointer to the hardware structure
438  * @cntr_id: returns counter index
439  * @num_fltr: number of filter entries to be allocated
440  */
441 enum ice_status
442 ice_alloc_fd_shrd_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr)
443 {
444         return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_SHARED_ENTRIES,
445                                   ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
446                                   cntr_id);
447 }
448
449 /**
450  * ice_free_fd_shrd_item - Free flow director shared entries
451  * @hw: pointer to the hardware structure
452  * @cntr_id: counter index that needs to be freed
453  * @num_fltr: number of filters to be freed
454  */
455 enum ice_status
456 ice_free_fd_shrd_item(struct ice_hw *hw, u16 cntr_id, u16 num_fltr)
457 {
458         return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_SHARED_ENTRIES,
459                                  ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
460                                  cntr_id);
461 }
462
463 /**
464  * ice_get_fdir_cnt_all - get the number of Flow Director filters
465  * @hw: hardware data structure
466  *
467  * Returns the number of filters available on device
468  */
469 int ice_get_fdir_cnt_all(struct ice_hw *hw)
470 {
471         return hw->func_caps.fd_fltr_guar +
472                hw->func_caps.fd_fltr_best_effort;
473 }
474
475 /**
476  * ice_pkt_insert_ipv6_addr - insert a be32 IPv6 address into a memory buffer.
477  * @pkt: packet buffer
478  * @offset: offset into buffer
479  * @addr: IPv6 address to convert and insert into pkt at offset
480  */
481 static void ice_pkt_insert_ipv6_addr(u8 *pkt, int offset, __be32 *addr)
482 {
483         int idx;
484
485         for (idx = 0; idx < ICE_IPV6_ADDR_LEN_AS_U32; idx++)
486                 ice_memcpy(pkt + offset + idx * sizeof(*addr), &addr[idx],
487                            sizeof(*addr), ICE_NONDMA_TO_NONDMA);
488 }
489
490 /**
491  * ice_pkt_insert_u8 - insert a u8 value into a memory buffer.
492  * @pkt: packet buffer
493  * @offset: offset into buffer
494  * @data: 8 bit value to convert and insert into pkt at offset
495  */
496 static void ice_pkt_insert_u8(u8 *pkt, int offset, u8 data)
497 {
498         ice_memcpy(pkt + offset, &data, sizeof(data), ICE_NONDMA_TO_NONDMA);
499 }
500
501 /**
502  * ice_pkt_insert_u8_tc - insert a u8 value into a memory buffer for tc ipv6.
503  * @pkt: packet buffer
504  * @offset: offset into buffer
505  * @data: 8 bit value to convert and insert into pkt at offset
506  *
507  * This function is designed for inserting Traffic Class (tc) for IPv6,
508  * since that tc is not aligned in number of bytes. Here we split it out
509  * into two part and fill each byte with data copy from pkt, then insert
510  * the two bytes data one by one.
511  */
512 static void ice_pkt_insert_u8_tc(u8 *pkt, int offset, u8 data)
513 {
514         u8 high, low;
515
516         high = (data >> 4) + (*(pkt + offset) & 0xF0);
517         ice_memcpy(pkt + offset, &high, sizeof(high), ICE_NONDMA_TO_NONDMA);
518
519         low = (*(pkt + offset + 1) & 0x0F) + ((data & 0x0F) << 4);
520         ice_memcpy(pkt + offset + 1, &low, sizeof(low), ICE_NONDMA_TO_NONDMA);
521 }
522
523 /**
524  * ice_pkt_insert_u16 - insert a be16 value into a memory buffer.
525  * @pkt: packet buffer
526  * @offset: offset into buffer
527  * @data: 16 bit value to convert and insert into pkt at offset
528  */
529 static void ice_pkt_insert_u16(u8 *pkt, int offset, __be16 data)
530 {
531         ice_memcpy(pkt + offset, &data, sizeof(data), ICE_NONDMA_TO_NONDMA);
532 }
533
534 /**
535  * ice_pkt_insert_u32 - insert a be32 value into a memory buffer.
536  * @pkt: packet buffer
537  * @offset: offset into buffer
538  * @data: 32 bit value to convert and insert into pkt at offset
539  */
540 static void ice_pkt_insert_u32(u8 *pkt, int offset, __be32 data)
541 {
542         ice_memcpy(pkt + offset, &data, sizeof(data), ICE_NONDMA_TO_NONDMA);
543 }
544
545 /**
546  * ice_pkt_insert_mac_addr - insert a MAC addr into a memory buffer.
547  * @pkt: packet buffer
548  * @offset: offset into buffer
549  * @addr: MAC address to convert and insert into pkt at offset
550  */
551 static void ice_pkt_insert_mac_addr(u8 *pkt, u8 *addr)
552 {
553         ice_memcpy(pkt, addr, ETH_ALEN, ICE_NONDMA_TO_NONDMA);
554 }
555
556 /**
557  * ice_fdir_get_gen_prgm_pkt - generate a training packet
558  * @hw: pointer to the hardware structure
559  * @input: flow director filter data structure
560  * @pkt: pointer to return filter packet
561  * @frag: generate a fragment packet
562  * @tun: true implies generate a tunnel packet
563  */
564 enum ice_status
565 ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
566                           u8 *pkt, bool frag, bool tun)
567 {
568         enum ice_fltr_ptype flow;
569         u16 tnl_port;
570         u8 *loc;
571         u16 idx;
572
573         if (input->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) {
574                 switch (input->ip.v4.proto) {
575                 case ICE_IP_PROTO_TCP:
576                         flow = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
577                         break;
578                 case ICE_IP_PROTO_UDP:
579                         flow = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
580                         break;
581                 case ICE_IP_PROTO_SCTP:
582                         flow = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
583                         break;
584                 default:
585                         flow = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
586                         break;
587                 }
588         } else if (input->flow_type == ICE_FLTR_PTYPE_NONF_IPV6_OTHER) {
589                 switch (input->ip.v6.proto) {
590                 case ICE_IP_PROTO_TCP:
591                         flow = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
592                         break;
593                 case ICE_IP_PROTO_UDP:
594                         flow = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
595                         break;
596                 case ICE_IP_PROTO_SCTP:
597                         flow = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
598                         break;
599                 default:
600                         flow = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
601                         break;
602                 }
603         } else {
604                 flow = input->flow_type;
605         }
606
607         for (idx = 0; idx < ICE_FDIR_NUM_PKT; idx++)
608                 if (ice_fdir_pkt[idx].flow == flow)
609                         break;
610         if (idx == ICE_FDIR_NUM_PKT)
611                 return ICE_ERR_PARAM;
612         if (!tun) {
613                 ice_memcpy(pkt, ice_fdir_pkt[idx].pkt,
614                            ice_fdir_pkt[idx].pkt_len, ICE_NONDMA_TO_NONDMA);
615                 loc = pkt;
616         } else {
617                 if (!ice_get_open_tunnel_port(hw, TNL_ALL, &tnl_port))
618                         return ICE_ERR_DOES_NOT_EXIST;
619                 if (!ice_fdir_pkt[idx].tun_pkt)
620                         return ICE_ERR_PARAM;
621                 ice_memcpy(pkt, ice_fdir_pkt[idx].tun_pkt,
622                            ice_fdir_pkt[idx].tun_pkt_len, ICE_NONDMA_TO_NONDMA);
623                 ice_pkt_insert_u16(pkt, ICE_IPV4_UDP_DST_PORT_OFFSET,
624                                    HTONS(tnl_port));
625                 loc = &pkt[ICE_FDIR_TUN_PKT_OFF];
626         }
627
628         switch (flow) {
629         case ICE_FLTR_PTYPE_NONF_IPV4_TCP:
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_TCP_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_TCP_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                 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
641                 if (frag)
642                         loc[20] = ICE_FDIR_IPV4_PKT_FLAG_DF;
643                 break;
644         case ICE_FLTR_PTYPE_NONF_IPV4_UDP:
645                 ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
646                                    input->ip.v4.dst_ip);
647                 ice_pkt_insert_u16(loc, ICE_IPV4_UDP_DST_PORT_OFFSET,
648                                    input->ip.v4.dst_port);
649                 ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
650                                    input->ip.v4.src_ip);
651                 ice_pkt_insert_u16(loc, ICE_IPV4_UDP_SRC_PORT_OFFSET,
652                                    input->ip.v4.src_port);
653                 ice_pkt_insert_u8(loc, ICE_IPV4_TOS_OFFSET, input->ip.v4.tos);
654                 ice_pkt_insert_u8(loc, ICE_IPV4_TTL_OFFSET, input->ip.v4.ttl);
655                 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
656                 break;
657         case ICE_FLTR_PTYPE_NONF_IPV4_SCTP:
658                 ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
659                                    input->ip.v4.dst_ip);
660                 ice_pkt_insert_u16(loc, ICE_IPV4_SCTP_DST_PORT_OFFSET,
661                                    input->ip.v4.dst_port);
662                 ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
663                                    input->ip.v4.src_ip);
664                 ice_pkt_insert_u16(loc, ICE_IPV4_SCTP_SRC_PORT_OFFSET,
665                                    input->ip.v4.src_port);
666                 ice_pkt_insert_u8(loc, ICE_IPV4_TOS_OFFSET, input->ip.v4.tos);
667                 ice_pkt_insert_u8(loc, ICE_IPV4_TTL_OFFSET, input->ip.v4.ttl);
668                 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
669                 break;
670         case ICE_FLTR_PTYPE_NONF_IPV4_OTHER:
671                 ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
672                                    input->ip.v4.dst_ip);
673                 ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
674                                    input->ip.v4.src_ip);
675                 ice_pkt_insert_u8(loc, ICE_IPV4_TOS_OFFSET, input->ip.v4.tos);
676                 ice_pkt_insert_u8(loc, ICE_IPV4_TTL_OFFSET, input->ip.v4.ttl);
677                 ice_pkt_insert_u8(loc, ICE_IPV4_PROTO_OFFSET,
678                                   input->ip.v4.proto);
679                 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
680                 break;
681         case ICE_FLTR_PTYPE_NONF_IPV6_TCP:
682                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
683                                          input->ip.v6.dst_ip);
684                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
685                                          input->ip.v6.src_ip);
686                 ice_pkt_insert_u16(loc, ICE_IPV6_TCP_DST_PORT_OFFSET,
687                                    input->ip.v6.dst_port);
688                 ice_pkt_insert_u16(loc, ICE_IPV6_TCP_SRC_PORT_OFFSET,
689                                    input->ip.v6.src_port);
690                 ice_pkt_insert_u8_tc(loc, ICE_IPV6_TC_OFFSET, input->ip.v6.tc);
691                 ice_pkt_insert_u8(loc, ICE_IPV6_HLIM_OFFSET, input->ip.v6.hlim);
692                 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
693                 break;
694         case ICE_FLTR_PTYPE_NONF_IPV6_UDP:
695                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
696                                          input->ip.v6.dst_ip);
697                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
698                                          input->ip.v6.src_ip);
699                 ice_pkt_insert_u16(loc, ICE_IPV6_UDP_DST_PORT_OFFSET,
700                                    input->ip.v6.dst_port);
701                 ice_pkt_insert_u16(loc, ICE_IPV6_UDP_SRC_PORT_OFFSET,
702                                    input->ip.v6.src_port);
703                 ice_pkt_insert_u8_tc(loc, ICE_IPV6_TC_OFFSET, input->ip.v6.tc);
704                 ice_pkt_insert_u8(loc, ICE_IPV6_HLIM_OFFSET, input->ip.v6.hlim);
705                 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
706                 break;
707         case ICE_FLTR_PTYPE_NONF_IPV6_SCTP:
708                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
709                                          input->ip.v6.dst_ip);
710                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
711                                          input->ip.v6.src_ip);
712                 ice_pkt_insert_u16(loc, ICE_IPV6_SCTP_DST_PORT_OFFSET,
713                                    input->ip.v6.dst_port);
714                 ice_pkt_insert_u16(loc, ICE_IPV6_SCTP_SRC_PORT_OFFSET,
715                                    input->ip.v6.src_port);
716                 ice_pkt_insert_u8_tc(loc, ICE_IPV6_TC_OFFSET, input->ip.v6.tc);
717                 ice_pkt_insert_u8(loc, ICE_IPV6_HLIM_OFFSET, input->ip.v6.hlim);
718                 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
719                 break;
720         case ICE_FLTR_PTYPE_NONF_IPV6_OTHER:
721                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
722                                          input->ip.v6.dst_ip);
723                 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
724                                          input->ip.v6.src_ip);
725                 ice_pkt_insert_u8_tc(loc, ICE_IPV6_TC_OFFSET, input->ip.v6.tc);
726                 ice_pkt_insert_u8(loc, ICE_IPV6_HLIM_OFFSET, input->ip.v6.hlim);
727                 ice_pkt_insert_u8(loc, ICE_IPV6_PROTO_OFFSET,
728                                   input->ip.v6.proto);
729                 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
730                 break;
731         default:
732                 return ICE_ERR_PARAM;
733         }
734
735         if (input->flex_fltr)
736                 ice_pkt_insert_u16(loc, input->flex_offset, input->flex_word);
737
738         return ICE_SUCCESS;
739 }
740
741 /**
742  * ice_fdir_get_prgm_pkt - generate a training packet
743  * @input: flow director filter data structure
744  * @pkt: pointer to return filter packet
745  * @frag: generate a fragment packet
746  */
747 enum ice_status
748 ice_fdir_get_prgm_pkt(struct ice_fdir_fltr *input, u8 *pkt, bool frag)
749 {
750         return ice_fdir_get_gen_prgm_pkt(NULL, input, pkt, frag, false);
751 }
752
753 /**
754  * ice_fdir_has_frag - does flow type have 2 ptypes
755  * @flow: flow ptype
756  *
757  * returns true is there is a fragment packet for this ptype
758  */
759 bool ice_fdir_has_frag(enum ice_fltr_ptype flow)
760 {
761         if (flow == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
762                 return true;
763         else
764                 return false;
765 }
766
767 /**
768  * ice_fdir_find_by_idx - find filter with idx
769  * @hw: pointer to hardware structure
770  * @fltr_idx: index to find.
771  *
772  * Returns pointer to filter if found or null
773  */
774 struct ice_fdir_fltr *
775 ice_fdir_find_fltr_by_idx(struct ice_hw *hw, u32 fltr_idx)
776 {
777         struct ice_fdir_fltr *rule = NULL;
778
779         LIST_FOR_EACH_ENTRY(rule, &hw->fdir_list_head, ice_fdir_fltr,
780                             fltr_node) {
781                 /* rule ID found in the list */
782                 if (fltr_idx == rule->fltr_id)
783                         return rule;
784                 if (fltr_idx < rule->fltr_id)
785                         break;
786         }
787         return NULL;
788 }
789
790 /**
791  * ice_fdir_list_add_fltr - add a new node to the flow director filter list
792  * @hw: hardware structure
793  * @fltr: filter node to add to structure
794  */
795 void ice_fdir_list_add_fltr(struct ice_hw *hw, struct ice_fdir_fltr *fltr)
796 {
797         struct ice_fdir_fltr *rule, *parent = NULL;
798
799         LIST_FOR_EACH_ENTRY(rule, &hw->fdir_list_head, ice_fdir_fltr,
800                             fltr_node) {
801                 /* rule ID found or pass its spot in the list */
802                 if (rule->fltr_id >= fltr->fltr_id)
803                         break;
804                 parent = rule;
805         }
806
807         if (parent)
808                 LIST_ADD_AFTER(&fltr->fltr_node, &parent->fltr_node);
809         else
810                 LIST_ADD(&fltr->fltr_node, &hw->fdir_list_head);
811 }
812
813 /**
814  * ice_fdir_update_cntrs - increment / decrement filter counter
815  * @hw: pointer to hardware structure
816  * @flow: filter flow type
817  * @add: true implies filters added
818  */
819 void
820 ice_fdir_update_cntrs(struct ice_hw *hw, enum ice_fltr_ptype flow, bool add)
821 {
822         int incr;
823
824         incr = (add) ? 1 : -1;
825         hw->fdir_active_fltr += incr;
826         if (flow == ICE_FLTR_PTYPE_NONF_NONE || flow >= ICE_FLTR_PTYPE_MAX)
827                 ice_debug(hw, ICE_DBG_SW, "Unknown filter type %d\n", flow);
828         else
829                 hw->fdir_fltr_cnt[flow] += incr;
830 }
831
832 /**
833  * ice_cmp_ipv6_addr - compare 2 IP v6 addresses
834  * @a: IP v6 address
835  * @b: IP v6 address
836  *
837  * Returns 0 on equal, returns non-0 if different
838  */
839 static int ice_cmp_ipv6_addr(__be32 *a, __be32 *b)
840 {
841         return memcmp(a, b, 4 * sizeof(__be32));
842 }
843
844 /**
845  * ice_fdir_comp_ipv6_rules - compare 2 filters
846  * @a: a Flow Director filter data structure
847  * @b: a Flow Director filter data structure
848  * @v6: bool true if v6 filter
849  *
850  * Returns true if the filters match
851  */
852 static bool
853 ice_fdir_comp_rules(struct ice_fdir_fltr *a,  struct ice_fdir_fltr *b, bool v6)
854 {
855         enum ice_fltr_ptype flow_type = a->flow_type;
856
857         /* The calling function already checks that the two filters have the
858          * same flow_type.
859          */
860         if (!v6) {
861                 if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP ||
862                     flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
863                     flow_type == ICE_FLTR_PTYPE_NONF_IPV4_SCTP) {
864                         if (a->ip.v4.dst_ip == b->ip.v4.dst_ip &&
865                             a->ip.v4.src_ip == b->ip.v4.src_ip &&
866                             a->ip.v4.dst_port == b->ip.v4.dst_port &&
867                             a->ip.v4.src_port == b->ip.v4.src_port)
868                                 return true;
869                 } else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) {
870                         if (a->ip.v4.dst_ip == b->ip.v4.dst_ip &&
871                             a->ip.v4.src_ip == b->ip.v4.src_ip &&
872                             a->ip.v4.l4_header == b->ip.v4.l4_header &&
873                             a->ip.v4.proto == b->ip.v4.proto &&
874                             a->ip.v4.ip_ver == b->ip.v4.ip_ver &&
875                             a->ip.v4.tos == b->ip.v4.tos)
876                                 return true;
877                 }
878         } else {
879                 if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP ||
880                     flow_type == ICE_FLTR_PTYPE_NONF_IPV6_TCP ||
881                     flow_type == ICE_FLTR_PTYPE_NONF_IPV6_SCTP) {
882                         if (a->ip.v6.dst_port == b->ip.v6.dst_port &&
883                             a->ip.v6.src_port == b->ip.v6.src_port &&
884                             !ice_cmp_ipv6_addr(a->ip.v6.dst_ip,
885                                                b->ip.v6.dst_ip) &&
886                             !ice_cmp_ipv6_addr(a->ip.v6.src_ip,
887                                                b->ip.v6.src_ip))
888                                 return true;
889                 } else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_OTHER) {
890                         if (a->ip.v6.dst_port == b->ip.v6.dst_port &&
891                             a->ip.v6.src_port == b->ip.v6.src_port)
892                                 return true;
893                 }
894         }
895
896         return false;
897 }
898
899 /**
900  * ice_fdir_is_dup_fltr - test if filter is already in list for PF
901  * @hw: hardware data structure
902  * @input: Flow Director filter data structure
903  *
904  * Returns true if the filter is found in the list
905  */
906 bool ice_fdir_is_dup_fltr(struct ice_hw *hw, struct ice_fdir_fltr *input)
907 {
908         enum ice_fltr_ptype flow_type;
909         struct ice_fdir_fltr *rule;
910         bool ret = false;
911
912         rule = NULL;
913
914         LIST_FOR_EACH_ENTRY(rule, &hw->fdir_list_head, ice_fdir_fltr,
915                             fltr_node) {
916                 if (rule->flow_type == input->flow_type) {
917                         flow_type = input->flow_type;
918                         if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP ||
919                             flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
920                             flow_type == ICE_FLTR_PTYPE_NONF_IPV4_SCTP ||
921                             flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
922                                 ret = ice_fdir_comp_rules(rule, input, false);
923                         else
924                                 ret = ice_fdir_comp_rules(rule, input, true);
925                         if (ret) {
926                                 if (rule->fltr_id == input->fltr_id &&
927                                     rule->q_index != input->q_index)
928                                         ret = false;
929                                 else
930                                         break;
931                         }
932                 }
933         }
934
935         return ret;
936 }
937
938 /**
939  * ice_clear_vsi_fd_table - admin command to clear FD table for a VSI
940  * @hw: hardware data structure
941  * @vsi_num: vsi_num (HW VSI num)
942  *
943  * Clears FD table entries by issuing admin command (direct, 0x0B06)
944  * Must to pass valid vsi_num as returned by "AddVSI".
945  */
946 enum ice_status ice_clear_vsi_fd_table(struct ice_hw *hw, u16 vsi_num)
947 {
948         struct ice_aqc_clear_fd_table *cmd;
949         struct ice_aq_desc desc;
950
951         cmd = &desc.params.clear_fd_table;
952         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_fd_table);
953         cmd->clear_type = CL_FD_VM_VF_TYPE_VSI_IDX;
954
955         cmd->vsi_index = CPU_TO_LE16(vsi_num);
956         return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
957 }
958
959 /**
960  * ice_clear_pf_fd_table - admin command to clear FD table for PF
961  * @hw: hardware data structure
962  *
963  * Clears FD table entries for a PF by issuing admin command (direct, 0x0B06)
964  */
965 enum ice_status ice_clear_pf_fd_table(struct ice_hw *hw)
966 {
967         struct ice_aqc_clear_fd_table *cmd;
968         struct ice_aq_desc desc;
969
970         cmd = &desc.params.clear_fd_table;
971         ice_fill_dflt_direct_cmd_desc(&desc, ice_aqc_opc_clear_fd_table);
972         cmd->clear_type = CL_FD_VM_VF_TYPE_PF_IDX;
973         /* vsi_index must be 0 to clear FD table for a PF */
974         cmd->vsi_index = CPU_TO_LE16(0);
975
976         return ice_aq_send_cmd(hw, &desc, NULL, 0, NULL);
977 }