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_pkt_insert_mac_addr - insert a MAC addr into a memory buffer.
497 * @pkt: packet buffer
498 * @addr: MAC address to convert and insert into pkt at offset
500 static void ice_pkt_insert_mac_addr(u8 *pkt, u8 *addr)
502 ether_addr_copy(pkt, addr);
506 * ice_fdir_get_gen_prgm_pkt - generate a training packet
507 * @hw: pointer to the hardware structure
508 * @input: flow director filter data structure
509 * @pkt: pointer to return filter packet
510 * @frag: generate a fragment packet
511 * @tun: true implies generate a tunnel packet
514 ice_fdir_get_gen_prgm_pkt(struct ice_hw *hw, struct ice_fdir_fltr *input,
515 u8 *pkt, bool frag, bool tun)
517 enum ice_fltr_ptype flow;
522 if (input->flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) {
523 switch (input->ip.v4.proto) {
525 flow = ICE_FLTR_PTYPE_NONF_IPV4_TCP;
528 flow = ICE_FLTR_PTYPE_NONF_IPV4_UDP;
531 flow = ICE_FLTR_PTYPE_NONF_IPV4_SCTP;
534 flow = ICE_FLTR_PTYPE_NONF_IPV4_OTHER;
537 return ICE_ERR_PARAM;
539 } else if (input->flow_type == ICE_FLTR_PTYPE_NONF_IPV6_OTHER) {
540 switch (input->ip.v6.proto) {
542 flow = ICE_FLTR_PTYPE_NONF_IPV6_TCP;
545 flow = ICE_FLTR_PTYPE_NONF_IPV6_UDP;
548 flow = ICE_FLTR_PTYPE_NONF_IPV6_SCTP;
551 flow = ICE_FLTR_PTYPE_NONF_IPV6_OTHER;
554 return ICE_ERR_PARAM;
557 flow = input->flow_type;
560 for (idx = 0; idx < ICE_FDIR_NUM_PKT; idx++)
561 if (ice_fdir_pkt[idx].flow == flow)
563 if (idx == ICE_FDIR_NUM_PKT)
564 return ICE_ERR_PARAM;
566 memcpy(pkt, ice_fdir_pkt[idx].pkt, ice_fdir_pkt[idx].pkt_len);
569 if (!ice_get_open_tunnel_port(hw, &tnl_port))
570 return ICE_ERR_DOES_NOT_EXIST;
571 if (!ice_fdir_pkt[idx].tun_pkt)
572 return ICE_ERR_PARAM;
573 memcpy(pkt, ice_fdir_pkt[idx].tun_pkt,
574 ice_fdir_pkt[idx].tun_pkt_len);
575 ice_pkt_insert_u16(pkt, ICE_IPV4_UDP_DST_PORT_OFFSET,
577 loc = &pkt[ICE_FDIR_TUN_PKT_OFF];
580 /* Reverse the src and dst, since the HW expects them to be from Tx
581 * perspective. The input from user is from Rx filter perspective.
584 case ICE_FLTR_PTYPE_NONF_IPV4_TCP:
585 ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
586 input->ip.v4.src_ip);
587 ice_pkt_insert_u16(loc, ICE_IPV4_TCP_DST_PORT_OFFSET,
588 input->ip.v4.src_port);
589 ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
590 input->ip.v4.dst_ip);
591 ice_pkt_insert_u16(loc, ICE_IPV4_TCP_SRC_PORT_OFFSET,
592 input->ip.v4.dst_port);
593 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
595 loc[20] = ICE_FDIR_IPV4_PKT_FLAG_DF;
597 case ICE_FLTR_PTYPE_NONF_IPV4_UDP:
598 ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
599 input->ip.v4.src_ip);
600 ice_pkt_insert_u16(loc, ICE_IPV4_UDP_DST_PORT_OFFSET,
601 input->ip.v4.src_port);
602 ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
603 input->ip.v4.dst_ip);
604 ice_pkt_insert_u16(loc, ICE_IPV4_UDP_SRC_PORT_OFFSET,
605 input->ip.v4.dst_port);
606 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
607 ice_pkt_insert_mac_addr(loc + ETH_ALEN,
608 input->ext_data.src_mac);
610 case ICE_FLTR_PTYPE_NONF_IPV4_SCTP:
611 ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
612 input->ip.v4.src_ip);
613 ice_pkt_insert_u16(loc, ICE_IPV4_SCTP_DST_PORT_OFFSET,
614 input->ip.v4.src_port);
615 ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
616 input->ip.v4.dst_ip);
617 ice_pkt_insert_u16(loc, ICE_IPV4_SCTP_SRC_PORT_OFFSET,
618 input->ip.v4.dst_port);
619 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
621 case ICE_FLTR_PTYPE_NONF_IPV4_OTHER:
622 ice_pkt_insert_u32(loc, ICE_IPV4_DST_ADDR_OFFSET,
623 input->ip.v4.src_ip);
624 ice_pkt_insert_u32(loc, ICE_IPV4_SRC_ADDR_OFFSET,
625 input->ip.v4.dst_ip);
626 ice_pkt_insert_u16(loc, ICE_IPV4_PROTO_OFFSET, 0);
627 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
629 case ICE_FLTR_PTYPE_NONF_IPV6_TCP:
630 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
631 input->ip.v6.src_ip);
632 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
633 input->ip.v6.dst_ip);
634 ice_pkt_insert_u16(loc, ICE_IPV6_TCP_DST_PORT_OFFSET,
635 input->ip.v6.src_port);
636 ice_pkt_insert_u16(loc, ICE_IPV6_TCP_SRC_PORT_OFFSET,
637 input->ip.v6.dst_port);
638 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
640 case ICE_FLTR_PTYPE_NONF_IPV6_UDP:
641 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
642 input->ip.v6.src_ip);
643 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
644 input->ip.v6.dst_ip);
645 ice_pkt_insert_u16(loc, ICE_IPV6_UDP_DST_PORT_OFFSET,
646 input->ip.v6.src_port);
647 ice_pkt_insert_u16(loc, ICE_IPV6_UDP_SRC_PORT_OFFSET,
648 input->ip.v6.dst_port);
649 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
651 case ICE_FLTR_PTYPE_NONF_IPV6_SCTP:
652 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
653 input->ip.v6.src_ip);
654 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
655 input->ip.v6.dst_ip);
656 ice_pkt_insert_u16(loc, ICE_IPV6_SCTP_DST_PORT_OFFSET,
657 input->ip.v6.src_port);
658 ice_pkt_insert_u16(loc, ICE_IPV6_SCTP_SRC_PORT_OFFSET,
659 input->ip.v6.dst_port);
660 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
662 case ICE_FLTR_PTYPE_NONF_IPV6_OTHER:
663 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_DST_ADDR_OFFSET,
664 input->ip.v6.src_ip);
665 ice_pkt_insert_ipv6_addr(loc, ICE_IPV6_SRC_ADDR_OFFSET,
666 input->ip.v6.dst_ip);
667 ice_pkt_insert_mac_addr(loc, input->ext_data.dst_mac);
670 return ICE_ERR_PARAM;
673 if (input->flex_fltr)
674 ice_pkt_insert_u16(loc, input->flex_offset, input->flex_word);
680 * ice_fdir_has_frag - does flow type have 2 ptypes
683 * returns true is there is a fragment packet for this ptype
685 bool ice_fdir_has_frag(enum ice_fltr_ptype flow)
687 if (flow == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
694 * ice_fdir_find_by_idx - find filter with idx
695 * @hw: pointer to hardware structure
696 * @fltr_idx: index to find.
698 * Returns pointer to filter if found or null
700 struct ice_fdir_fltr *
701 ice_fdir_find_fltr_by_idx(struct ice_hw *hw, u32 fltr_idx)
703 struct ice_fdir_fltr *rule;
705 list_for_each_entry(rule, &hw->fdir_list_head, fltr_node) {
706 /* rule ID found in the list */
707 if (fltr_idx == rule->fltr_id)
709 if (fltr_idx < rule->fltr_id)
716 * ice_fdir_list_add_fltr - add a new node to the flow director filter list
717 * @hw: hardware structure
718 * @fltr: filter node to add to structure
720 void ice_fdir_list_add_fltr(struct ice_hw *hw, struct ice_fdir_fltr *fltr)
722 struct ice_fdir_fltr *rule, *parent = NULL;
724 list_for_each_entry(rule, &hw->fdir_list_head, fltr_node) {
725 /* rule ID found or pass its spot in the list */
726 if (rule->fltr_id >= fltr->fltr_id)
732 list_add(&fltr->fltr_node, &parent->fltr_node);
734 list_add(&fltr->fltr_node, &hw->fdir_list_head);
738 * ice_fdir_update_cntrs - increment / decrement filter counter
739 * @hw: pointer to hardware structure
740 * @flow: filter flow type
741 * @add: true implies filters added
744 ice_fdir_update_cntrs(struct ice_hw *hw, enum ice_fltr_ptype flow, bool add)
749 hw->fdir_active_fltr += incr;
751 if (flow == ICE_FLTR_PTYPE_NONF_NONE || flow >= ICE_FLTR_PTYPE_MAX)
752 ice_debug(hw, ICE_DBG_SW, "Unknown filter type %d\n", flow);
754 hw->fdir_fltr_cnt[flow] += incr;
758 * ice_cmp_ipv6_addr - compare 2 IP v6 addresses
762 * Returns 0 on equal, returns non-0 if different
764 static int ice_cmp_ipv6_addr(__be32 *a, __be32 *b)
766 return memcmp(a, b, 4 * sizeof(__be32));
770 * ice_fdir_comp_rules - compare 2 filters
771 * @a: a Flow Director filter data structure
772 * @b: a Flow Director filter data structure
773 * @v6: bool true if v6 filter
775 * Returns true if the filters match
778 ice_fdir_comp_rules(struct ice_fdir_fltr *a, struct ice_fdir_fltr *b, bool v6)
780 enum ice_fltr_ptype flow_type = a->flow_type;
782 /* The calling function already checks that the two filters have the
786 if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP ||
787 flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
788 flow_type == ICE_FLTR_PTYPE_NONF_IPV4_SCTP) {
789 if (a->ip.v4.dst_ip == b->ip.v4.dst_ip &&
790 a->ip.v4.src_ip == b->ip.v4.src_ip &&
791 a->ip.v4.dst_port == b->ip.v4.dst_port &&
792 a->ip.v4.src_port == b->ip.v4.src_port)
794 } else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER) {
795 if (a->ip.v4.dst_ip == b->ip.v4.dst_ip &&
796 a->ip.v4.src_ip == b->ip.v4.src_ip &&
797 a->ip.v4.l4_header == b->ip.v4.l4_header &&
798 a->ip.v4.proto == b->ip.v4.proto &&
799 a->ip.v4.ip_ver == b->ip.v4.ip_ver &&
800 a->ip.v4.tos == b->ip.v4.tos)
804 if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_UDP ||
805 flow_type == ICE_FLTR_PTYPE_NONF_IPV6_TCP ||
806 flow_type == ICE_FLTR_PTYPE_NONF_IPV6_SCTP) {
807 if (a->ip.v6.dst_port == b->ip.v6.dst_port &&
808 a->ip.v6.src_port == b->ip.v6.src_port &&
809 !ice_cmp_ipv6_addr(a->ip.v6.dst_ip,
811 !ice_cmp_ipv6_addr(a->ip.v6.src_ip,
814 } else if (flow_type == ICE_FLTR_PTYPE_NONF_IPV6_OTHER) {
815 if (a->ip.v6.dst_port == b->ip.v6.dst_port &&
816 a->ip.v6.src_port == b->ip.v6.src_port)
825 * ice_fdir_is_dup_fltr - test if filter is already in list for PF
826 * @hw: hardware data structure
827 * @input: Flow Director filter data structure
829 * Returns true if the filter is found in the list
831 bool ice_fdir_is_dup_fltr(struct ice_hw *hw, struct ice_fdir_fltr *input)
833 struct ice_fdir_fltr *rule;
836 list_for_each_entry(rule, &hw->fdir_list_head, fltr_node) {
837 enum ice_fltr_ptype flow_type;
839 if (rule->flow_type != input->flow_type)
842 flow_type = input->flow_type;
843 if (flow_type == ICE_FLTR_PTYPE_NONF_IPV4_TCP ||
844 flow_type == ICE_FLTR_PTYPE_NONF_IPV4_UDP ||
845 flow_type == ICE_FLTR_PTYPE_NONF_IPV4_SCTP ||
846 flow_type == ICE_FLTR_PTYPE_NONF_IPV4_OTHER)
847 ret = ice_fdir_comp_rules(rule, input, false);
849 ret = ice_fdir_comp_rules(rule, input, true);
851 if (rule->fltr_id == input->fltr_id &&
852 rule->q_index != input->q_index)