1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright (C) 2018-2020, Intel Corporation. */
4 #include "ice_common.h"
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
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
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,
219 /* Flow Director no-op training packet table */
220 static const struct ice_fdir_base_pkt ice_fdir_pkt[] = {
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,
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,
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,
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,
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,
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,
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,
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,
263 #define ICE_FDIR_NUM_PKT ARRAY_SIZE(ice_fdir_pkt)
266 * ice_set_dflt_val_fd_desc
267 * @fd_fltr_ctx: pointer to fd filter descriptor
269 static void ice_set_dflt_val_fd_desc(struct ice_fd_fltr_desc_ctx *fd_fltr_ctx)
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;
293 * ice_set_fd_desc_val
294 * @ctx: pointer to fd filter descriptor context
295 * @fdir_desc: populated with fd filter descriptor values
298 ice_set_fd_desc_val(struct ice_fd_fltr_desc_ctx *ctx,
299 struct ice_fltr_desc *fdir_desc)
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);
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);
357 * ice_fdir_get_prgm_desc - set a fdir descriptor from a fdir filter struct
358 * @hw: pointer to the hardware structure
360 * @fdesc: filter descriptor
361 * @add: if add is true, this is an add operation, false implies delete
364 ice_fdir_get_prgm_desc(struct ice_hw *hw, struct ice_fdir_fltr *input,
365 struct ice_fltr_desc *fdesc, bool add)
367 struct ice_fd_fltr_desc_ctx fdir_fltr_ctx = { 0 };
369 /* set default context info */
370 ice_set_dflt_val_fd_desc(&fdir_fltr_ctx);
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;
378 fdir_fltr_ctx.drop = ICE_FXD_FLTR_QW0_DROP_NO;
379 fdir_fltr_ctx.qindex = input->q_index;
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);
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
402 enum ice_status ice_alloc_fd_res_cntr(struct ice_hw *hw, u16 *cntr_id)
404 return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_COUNTER_BLOCK,
405 ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, cntr_id);
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
413 enum ice_status ice_free_fd_res_cntr(struct ice_hw *hw, u16 cntr_id)
415 return ice_free_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_COUNTER_BLOCK,
416 ICE_AQC_RES_TYPE_FLAG_DEDICATED, 1, cntr_id);
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
426 ice_alloc_fd_guar_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr)
428 return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_GUARANTEED_ENTRIES,
429 ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
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
440 ice_alloc_fd_shrd_item(struct ice_hw *hw, u16 *cntr_id, u16 num_fltr)
442 return ice_alloc_res_cntr(hw, ICE_AQC_RES_TYPE_FDIR_SHARED_ENTRIES,
443 ICE_AQC_RES_TYPE_FLAG_DEDICATED, num_fltr,
448 * ice_get_fdir_cnt_all - get the number of Flow Director filters
449 * @hw: hardware data structure
451 * Returns the number of filters available on device
453 int ice_get_fdir_cnt_all(struct ice_hw *hw)
455 return hw->func_caps.fd_fltr_guar + hw->func_caps.fd_fltr_best_effort;
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
464 static void ice_pkt_insert_ipv6_addr(u8 *pkt, int offset, __be32 *addr)
468 for (idx = 0; idx < ICE_IPV6_ADDR_LEN_AS_U32; idx++)
469 memcpy(pkt + offset + idx * sizeof(*addr), &addr[idx],
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
479 static void ice_pkt_insert_u16(u8 *pkt, int offset, __be16 data)
481 memcpy(pkt + offset, &data, sizeof(data));
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
490 static void ice_pkt_insert_u32(u8 *pkt, int offset, __be32 data)
492 memcpy(pkt + offset, &data, sizeof(data));
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
504 ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
505 u8 *pkt, bool frag, bool tun)
507 enum ice_fltr_ptype flow;
512 if (input->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) {
513 switch (input->ip.v4.proto) {
515 flow = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
518 flow = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
521 flow = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
524 flow = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
527 return ICE_ERR_PARAM;
529 } else if (input->flow_type == ICE_FLTR_PTYPE_NONF_IPV6_OTHER) {
530 switch (input->ip.v6.proto) {
532 flow = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
535 flow = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
538 flow = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
541 flow = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
544 return ICE_ERR_PARAM;
547 flow = input->flow_type;
550 for (idx = 0; idx < ICE_FDIR_NUM_PKT; idx++)
551 if (ice_fdir_pkt[idx].flow == flow)
553 if (idx == ICE_FDIR_NUM_PKT)
554 return ICE_ERR_PARAM;
556 memcpy(pkt, ice_fdir_pkt[idx].pkt, ice_fdir_pkt[idx].pkt_len);
559 if (!ice_get_open_tunnel_port(hw, &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,
567 loc = &pkt[ICE_FDIR_TUN_PKT_OFF];
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.
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);
584 loc[20] = ICE_FDIR_IPV4_PKT_FLAG_DF;
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);
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);
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);
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);
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);
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);
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);
650 return ICE_ERR_PARAM;
653 if (input->flex_fltr)
654 ice_pkt_insert_u16(loc, input->flex_offset, input->flex_word);
660 * ice_fdir_has_frag - does flow type have 2 ptypes
663 * returns true is there is a fragment packet for this ptype
665 bool ice_fdir_has_frag(enum ice_fltr_ptype flow)
667 if (flow == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
674 * ice_fdir_find_by_idx - find filter with idx
675 * @hw: pointer to hardware structure
676 * @fltr_idx: index to find.
678 * Returns pointer to filter if found or null
680 struct ice_fdir_fltr *
681 ice_fdir_find_fltr_by_idx(struct ice_hw *hw, u32 fltr_idx)
683 struct ice_fdir_fltr *rule;
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)
689 if (fltr_idx < rule->fltr_id)
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
700 void ice_fdir_list_add_fltr(struct ice_hw *hw, struct ice_fdir_fltr *fltr)
702 struct ice_fdir_fltr *rule, *parent = NULL;
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)
712 list_add(&fltr->fltr_node, &parent->fltr_node);
714 list_add(&fltr->fltr_node, &hw->fdir_list_head);
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
724 ice_fdir_update_cntrs(struct ice_hw *hw, enum ice_fltr_ptype flow, bool add)
729 hw->fdir_active_fltr += incr;
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);
734 hw->fdir_fltr_cnt[flow] += incr;
738 * ice_cmp_ipv6_addr - compare 2 IP v6 addresses
742 * Returns 0 on equal, returns non-0 if different
744 static int ice_cmp_ipv6_addr(__be32 *a, __be32 *b)
746 return memcmp(a, b, 4 * sizeof(__be32));
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
755 * Returns true if the filters match
758 ice_fdir_comp_rules(struct ice_fdir_fltr *a, struct ice_fdir_fltr *b, bool v6)
760 enum ice_fltr_ptype flow_type = a->flow_type;
762 /* The calling function already checks that the two filters have the
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)
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)
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,
791 !ice_cmp_ipv6_addr(a->ip.v6.src_ip,
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)
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
809 * Returns true if the filter is found in the list
811 bool ice_fdir_is_dup_fltr(struct ice_hw *hw, struct ice_fdir_fltr *input)
813 struct ice_fdir_fltr *rule;
816 list_for_each_entry(rule, &hw->fdir_list_head, fltr_node) {
817 enum ice_fltr_ptype flow_type;
819 if (rule->flow_type != input->flow_type)
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);
829 ret = ice_fdir_comp_rules(rule, input, true);
831 if (rule->fltr_id == input->fltr_id &&
832 rule->q_index != input->q_index)