1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /* Copyright (c) 2024 NVIDIA Corporation & Affiliates */
3
4 #include "mlx5hws_internal.h"
5
6 /* Pattern tunnel Layer bits. */
7 #define MLX5_FLOW_LAYER_VXLAN BIT(12)
8 #define MLX5_FLOW_LAYER_VXLAN_GPE BIT(13)
9 #define MLX5_FLOW_LAYER_GRE BIT(14)
10 #define MLX5_FLOW_LAYER_MPLS BIT(15)
11
12 /* Pattern tunnel Layer bits (continued). */
13 #define MLX5_FLOW_LAYER_IPIP BIT(23)
14 #define MLX5_FLOW_LAYER_IPV6_ENCAP BIT(24)
15 #define MLX5_FLOW_LAYER_NVGRE BIT(25)
16 #define MLX5_FLOW_LAYER_GENEVE BIT(26)
17
18 #define MLX5_FLOW_ITEM_FLEX_TUNNEL BIT_ULL(39)
19
20 /* Tunnel Masks. */
21 #define MLX5_FLOW_LAYER_TUNNEL \
22 (MLX5_FLOW_LAYER_VXLAN | MLX5_FLOW_LAYER_VXLAN_GPE | \
23 MLX5_FLOW_LAYER_GRE | MLX5_FLOW_LAYER_NVGRE | MLX5_FLOW_LAYER_MPLS | \
24 MLX5_FLOW_LAYER_IPIP | MLX5_FLOW_LAYER_IPV6_ENCAP | \
25 MLX5_FLOW_LAYER_GENEVE | MLX5_FLOW_LAYER_GTP | \
26 MLX5_FLOW_ITEM_FLEX_TUNNEL)
27
28 #define GTP_PDU_SC 0x85
29 #define BAD_PORT 0xBAD
30 #define ETH_TYPE_IPV4_VXLAN 0x0800
31 #define ETH_TYPE_IPV6_VXLAN 0x86DD
32 #define UDP_GTPU_PORT 2152
33 #define UDP_PORT_MPLS 6635
34 #define UDP_GENEVE_PORT 6081
35 #define UDP_ROCEV2_PORT 4791
36 #define HWS_FLOW_LAYER_TUNNEL_NO_MPLS (MLX5_FLOW_LAYER_TUNNEL & ~MLX5_FLOW_LAYER_MPLS)
37
38 #define STE_NO_VLAN 0x0
39 #define STE_SVLAN 0x1
40 #define STE_CVLAN 0x2
41 #define STE_NO_L3 0x0
42 #define STE_IPV4 0x1
43 #define STE_IPV6 0x2
44 #define STE_NO_L4 0x0
45 #define STE_TCP 0x1
46 #define STE_UDP 0x2
47 #define STE_ICMP 0x3
48 #define STE_ESP 0x3
49
50 #define IPV4 0x4
51 #define IPV6 0x6
52
53 /* Setter function based on bit offset and mask, for 32bit DW */
54 #define _HWS_SET32(p, v, byte_off, bit_off, mask) \
55 do { \
56 u32 _v = v; \
57 *((__be32 *)(p) + ((byte_off) / 4)) = \
58 cpu_to_be32((be32_to_cpu(*((__be32 *)(p) + \
59 ((byte_off) / 4))) & \
60 (~((mask) << (bit_off)))) | \
61 (((_v) & (mask)) << \
62 (bit_off))); \
63 } while (0)
64
65 /* Setter function based on bit offset and mask, for unaligned 32bit DW */
66 #define HWS_SET32(p, v, byte_off, bit_off, mask) \
67 do { \
68 if (unlikely((bit_off) < 0)) { \
69 u32 _bit_off = -1 * (bit_off); \
70 u32 second_dw_mask = (mask) & ((1 << _bit_off) - 1); \
71 _HWS_SET32(p, (v) >> _bit_off, byte_off, 0, (mask) >> _bit_off); \
72 _HWS_SET32(p, (v) & second_dw_mask, (byte_off) + DW_SIZE, \
73 (bit_off) % BITS_IN_DW, second_dw_mask); \
74 } else { \
75 _HWS_SET32(p, v, byte_off, (bit_off), (mask)); \
76 } \
77 } while (0)
78
79 /* Getter for up to aligned 32bit DW */
80 #define HWS_GET32(p, byte_off, bit_off, mask) \
81 ((be32_to_cpu(*((__be32 *)(p) + ((byte_off) / 4))) >> (bit_off)) & (mask))
82
83 #define HWS_CALC_FNAME(field, inner) \
84 ((inner) ? MLX5HWS_DEFINER_FNAME_##field##_I : \
85 MLX5HWS_DEFINER_FNAME_##field##_O)
86
87 #define HWS_GET_MATCH_PARAM(match_param, hdr) \
88 MLX5_GET(fte_match_param, match_param, hdr)
89
90 #define HWS_IS_FLD_SET(match_param, hdr) \
91 (!!(HWS_GET_MATCH_PARAM(match_param, hdr)))
92
93 #define HWS_IS_FLD_SET_DW_ARR(match_param, hdr, sz_in_bits) ({ \
94 BUILD_BUG_ON((sz_in_bits) % 32); \
95 u32 sz = sz_in_bits; \
96 u32 res = 0; \
97 u32 dw_off = __mlx5_dw_off(fte_match_param, hdr); \
98 while (!res && sz >= 32) { \
99 res = *((match_param) + (dw_off++)); \
100 sz -= 32; \
101 } \
102 res; \
103 })
104
105 #define HWS_IS_FLD_SET_SZ(match_param, hdr, sz_in_bits) \
106 (((sz_in_bits) > 32) ? HWS_IS_FLD_SET_DW_ARR(match_param, hdr, sz_in_bits) : \
107 !!(HWS_GET_MATCH_PARAM(match_param, hdr)))
108
109 #define HWS_GET64_MATCH_PARAM(match_param, hdr) \
110 MLX5_GET64(fte_match_param, match_param, hdr)
111
112 #define HWS_IS_FLD64_SET(match_param, hdr) \
113 (!!(HWS_GET64_MATCH_PARAM(match_param, hdr)))
114
115 #define HWS_CALC_HDR_SRC(fc, s_hdr) \
116 do { \
117 (fc)->s_bit_mask = __mlx5_mask(fte_match_param, s_hdr); \
118 (fc)->s_bit_off = __mlx5_dw_bit_off(fte_match_param, s_hdr); \
119 (fc)->s_byte_off = MLX5_BYTE_OFF(fte_match_param, s_hdr); \
120 } while (0)
121
122 #define HWS_CALC_HDR_DST(fc, d_hdr) \
123 do { \
124 (fc)->bit_mask = __mlx5_mask(definer_hl, d_hdr); \
125 (fc)->bit_off = __mlx5_dw_bit_off(definer_hl, d_hdr); \
126 (fc)->byte_off = MLX5_BYTE_OFF(definer_hl, d_hdr); \
127 } while (0)
128
129 #define HWS_CALC_HDR(fc, s_hdr, d_hdr) \
130 do { \
131 HWS_CALC_HDR_SRC(fc, s_hdr); \
132 HWS_CALC_HDR_DST(fc, d_hdr); \
133 (fc)->tag_set = &hws_definer_generic_set; \
134 } while (0)
135
136 #define HWS_SET_HDR(fc_arr, match_param, fname, s_hdr, d_hdr) \
137 do { \
138 if (HWS_IS_FLD_SET(match_param, s_hdr)) \
139 HWS_CALC_HDR(&(fc_arr)[MLX5HWS_DEFINER_FNAME_##fname], s_hdr, d_hdr); \
140 } while (0)
141
142 struct mlx5hws_definer_sel_ctrl {
143 u8 allowed_full_dw; /* Full DW selectors cover all offsets */
144 u8 allowed_lim_dw; /* Limited DW selectors cover offset < 64 */
145 u8 allowed_bytes; /* Bytes selectors, up to offset 255 */
146 u8 used_full_dw;
147 u8 used_lim_dw;
148 u8 used_bytes;
149 u8 full_dw_selector[DW_SELECTORS];
150 u8 lim_dw_selector[DW_SELECTORS_LIMITED];
151 u8 byte_selector[BYTE_SELECTORS];
152 };
153
154 struct mlx5hws_definer_conv_data {
155 struct mlx5hws_context *ctx;
156 struct mlx5hws_definer_fc *fc;
157 /* enum mlx5hws_definer_match_flag */
158 u32 match_flags;
159 };
160
161 static void
hws_definer_ones_set(struct mlx5hws_definer_fc * fc,void * match_param,u8 * tag)162 hws_definer_ones_set(struct mlx5hws_definer_fc *fc,
163 void *match_param,
164 u8 *tag)
165 {
166 HWS_SET32(tag, -1, fc->byte_off, fc->bit_off, fc->bit_mask);
167 }
168
169 static void
hws_definer_generic_set(struct mlx5hws_definer_fc * fc,void * match_param,u8 * tag)170 hws_definer_generic_set(struct mlx5hws_definer_fc *fc,
171 void *match_param,
172 u8 *tag)
173 {
174 /* Can be optimized */
175 u32 val = HWS_GET32(match_param, fc->s_byte_off, fc->s_bit_off, fc->s_bit_mask);
176
177 HWS_SET32(tag, val, fc->byte_off, fc->bit_off, fc->bit_mask);
178 }
179
180 static void
hws_definer_outer_vlan_type_set(struct mlx5hws_definer_fc * fc,void * match_param,u8 * tag)181 hws_definer_outer_vlan_type_set(struct mlx5hws_definer_fc *fc,
182 void *match_param,
183 u8 *tag)
184 {
185 if (HWS_GET_MATCH_PARAM(match_param, outer_headers.cvlan_tag))
186 HWS_SET32(tag, STE_CVLAN, fc->byte_off, fc->bit_off, fc->bit_mask);
187 else if (HWS_GET_MATCH_PARAM(match_param, outer_headers.svlan_tag))
188 HWS_SET32(tag, STE_SVLAN, fc->byte_off, fc->bit_off, fc->bit_mask);
189 else
190 HWS_SET32(tag, STE_NO_VLAN, fc->byte_off, fc->bit_off, fc->bit_mask);
191 }
192
193 static void
hws_definer_inner_vlan_type_set(struct mlx5hws_definer_fc * fc,void * match_param,u8 * tag)194 hws_definer_inner_vlan_type_set(struct mlx5hws_definer_fc *fc,
195 void *match_param,
196 u8 *tag)
197 {
198 if (HWS_GET_MATCH_PARAM(match_param, inner_headers.cvlan_tag))
199 HWS_SET32(tag, STE_CVLAN, fc->byte_off, fc->bit_off, fc->bit_mask);
200 else if (HWS_GET_MATCH_PARAM(match_param, inner_headers.svlan_tag))
201 HWS_SET32(tag, STE_SVLAN, fc->byte_off, fc->bit_off, fc->bit_mask);
202 else
203 HWS_SET32(tag, STE_NO_VLAN, fc->byte_off, fc->bit_off, fc->bit_mask);
204 }
205
206 static void
hws_definer_second_vlan_type_set(struct mlx5hws_definer_fc * fc,void * match_param,u8 * tag,bool inner)207 hws_definer_second_vlan_type_set(struct mlx5hws_definer_fc *fc,
208 void *match_param,
209 u8 *tag,
210 bool inner)
211 {
212 u32 second_cvlan_tag = inner ?
213 HWS_GET_MATCH_PARAM(match_param, misc_parameters.inner_second_cvlan_tag) :
214 HWS_GET_MATCH_PARAM(match_param, misc_parameters.outer_second_cvlan_tag);
215 u32 second_svlan_tag = inner ?
216 HWS_GET_MATCH_PARAM(match_param, misc_parameters.inner_second_svlan_tag) :
217 HWS_GET_MATCH_PARAM(match_param, misc_parameters.outer_second_svlan_tag);
218
219 if (second_cvlan_tag)
220 HWS_SET32(tag, STE_CVLAN, fc->byte_off, fc->bit_off, fc->bit_mask);
221 else if (second_svlan_tag)
222 HWS_SET32(tag, STE_SVLAN, fc->byte_off, fc->bit_off, fc->bit_mask);
223 else
224 HWS_SET32(tag, STE_NO_VLAN, fc->byte_off, fc->bit_off, fc->bit_mask);
225 }
226
227 static void
hws_definer_inner_second_vlan_type_set(struct mlx5hws_definer_fc * fc,void * match_param,u8 * tag)228 hws_definer_inner_second_vlan_type_set(struct mlx5hws_definer_fc *fc,
229 void *match_param,
230 u8 *tag)
231 {
232 hws_definer_second_vlan_type_set(fc, match_param, tag, true);
233 }
234
235 static void
hws_definer_outer_second_vlan_type_set(struct mlx5hws_definer_fc * fc,void * match_param,u8 * tag)236 hws_definer_outer_second_vlan_type_set(struct mlx5hws_definer_fc *fc,
237 void *match_param,
238 u8 *tag)
239 {
240 hws_definer_second_vlan_type_set(fc, match_param, tag, false);
241 }
242
hws_definer_icmp_dw1_set(struct mlx5hws_definer_fc * fc,void * match_param,u8 * tag)243 static void hws_definer_icmp_dw1_set(struct mlx5hws_definer_fc *fc,
244 void *match_param,
245 u8 *tag)
246 {
247 u32 code = HWS_GET_MATCH_PARAM(match_param, misc_parameters_3.icmp_code);
248 u32 type = HWS_GET_MATCH_PARAM(match_param, misc_parameters_3.icmp_type);
249 u32 dw = (type << __mlx5_dw_bit_off(header_icmp, type)) |
250 (code << __mlx5_dw_bit_off(header_icmp, code));
251
252 HWS_SET32(tag, dw, fc->byte_off, fc->bit_off, fc->bit_mask);
253 }
254
255 static void
hws_definer_icmpv6_dw1_set(struct mlx5hws_definer_fc * fc,void * match_param,u8 * tag)256 hws_definer_icmpv6_dw1_set(struct mlx5hws_definer_fc *fc,
257 void *match_param,
258 u8 *tag)
259 {
260 u32 code = HWS_GET_MATCH_PARAM(match_param, misc_parameters_3.icmpv6_code);
261 u32 type = HWS_GET_MATCH_PARAM(match_param, misc_parameters_3.icmpv6_type);
262 u32 dw = (type << __mlx5_dw_bit_off(header_icmp, type)) |
263 (code << __mlx5_dw_bit_off(header_icmp, code));
264
265 HWS_SET32(tag, dw, fc->byte_off, fc->bit_off, fc->bit_mask);
266 }
267
268 static void
hws_definer_l3_type_set(struct mlx5hws_definer_fc * fc,void * match_param,u8 * tag)269 hws_definer_l3_type_set(struct mlx5hws_definer_fc *fc,
270 void *match_param,
271 u8 *tag)
272 {
273 u32 val = HWS_GET32(match_param, fc->s_byte_off, fc->s_bit_off, fc->s_bit_mask);
274
275 if (val == IPV4)
276 HWS_SET32(tag, STE_IPV4, fc->byte_off, fc->bit_off, fc->bit_mask);
277 else if (val == IPV6)
278 HWS_SET32(tag, STE_IPV6, fc->byte_off, fc->bit_off, fc->bit_mask);
279 else
280 HWS_SET32(tag, STE_NO_L3, fc->byte_off, fc->bit_off, fc->bit_mask);
281 }
282
283 static void
hws_definer_set_source_port_gvmi(struct mlx5hws_definer_fc * fc,void * match_param,u8 * tag,struct mlx5hws_context * peer_ctx)284 hws_definer_set_source_port_gvmi(struct mlx5hws_definer_fc *fc,
285 void *match_param,
286 u8 *tag,
287 struct mlx5hws_context *peer_ctx)
288 {
289 u16 source_port = HWS_GET_MATCH_PARAM(match_param, misc_parameters.source_port);
290 u16 vport_gvmi = 0;
291 int ret;
292
293 ret = mlx5hws_vport_get_gvmi(peer_ctx, source_port, &vport_gvmi);
294 if (ret) {
295 HWS_SET32(tag, BAD_PORT, fc->byte_off, fc->bit_off, fc->bit_mask);
296 mlx5hws_err(fc->ctx, "Vport 0x%x is disabled or invalid\n", source_port);
297 return;
298 }
299
300 if (vport_gvmi)
301 HWS_SET32(tag, vport_gvmi, fc->byte_off, fc->bit_off, fc->bit_mask);
302 }
303
304 static void
hws_definer_set_source_gvmi_vhca_id(struct mlx5hws_definer_fc * fc,void * match_param,u8 * tag)305 hws_definer_set_source_gvmi_vhca_id(struct mlx5hws_definer_fc *fc,
306 void *match_param,
307 u8 *tag)
308 __must_hold(&fc->ctx->ctrl_lock)
309 {
310 int id = HWS_GET_MATCH_PARAM(match_param, misc_parameters.source_eswitch_owner_vhca_id);
311 struct mlx5hws_context *peer_ctx;
312
313 if (id == fc->ctx->caps->vhca_id)
314 peer_ctx = fc->ctx;
315 else
316 peer_ctx = xa_load(&fc->ctx->peer_ctx_xa, id);
317
318 if (!peer_ctx) {
319 HWS_SET32(tag, BAD_PORT, fc->byte_off, fc->bit_off, fc->bit_mask);
320 mlx5hws_err(fc->ctx, "Invalid vhca_id provided 0x%x\n", id);
321 return;
322 }
323
324 hws_definer_set_source_port_gvmi(fc, match_param, tag, peer_ctx);
325 }
326
327 static void
hws_definer_set_source_gvmi(struct mlx5hws_definer_fc * fc,void * match_param,u8 * tag)328 hws_definer_set_source_gvmi(struct mlx5hws_definer_fc *fc,
329 void *match_param,
330 u8 *tag)
331 {
332 hws_definer_set_source_port_gvmi(fc, match_param, tag, fc->ctx);
333 }
334
335 static struct mlx5hws_definer_fc *
hws_definer_flex_parser_steering_ok_bits_handler(struct mlx5hws_definer_conv_data * cd,u8 parser_id)336 hws_definer_flex_parser_steering_ok_bits_handler(struct mlx5hws_definer_conv_data *cd,
337 u8 parser_id)
338 {
339 struct mlx5hws_definer_fc *fc;
340
341 switch (parser_id) {
342 case 0:
343 fc = &cd->fc[MLX5HWS_DEFINER_FNAME_FLEX_PARSER0_OK];
344 HWS_CALC_HDR_DST(fc, oks1.flex_parser0_steering_ok);
345 fc->tag_set = &hws_definer_generic_set;
346 break;
347 case 1:
348 fc = &cd->fc[MLX5HWS_DEFINER_FNAME_FLEX_PARSER1_OK];
349 HWS_CALC_HDR_DST(fc, oks1.flex_parser1_steering_ok);
350 fc->tag_set = &hws_definer_generic_set;
351 break;
352 case 2:
353 fc = &cd->fc[MLX5HWS_DEFINER_FNAME_FLEX_PARSER2_OK];
354 HWS_CALC_HDR_DST(fc, oks1.flex_parser2_steering_ok);
355 fc->tag_set = &hws_definer_generic_set;
356 break;
357 case 3:
358 fc = &cd->fc[MLX5HWS_DEFINER_FNAME_FLEX_PARSER3_OK];
359 HWS_CALC_HDR_DST(fc, oks1.flex_parser3_steering_ok);
360 fc->tag_set = &hws_definer_generic_set;
361 break;
362 case 4:
363 fc = &cd->fc[MLX5HWS_DEFINER_FNAME_FLEX_PARSER4_OK];
364 HWS_CALC_HDR_DST(fc, oks1.flex_parser4_steering_ok);
365 fc->tag_set = &hws_definer_generic_set;
366 break;
367 case 5:
368 fc = &cd->fc[MLX5HWS_DEFINER_FNAME_FLEX_PARSER5_OK];
369 HWS_CALC_HDR_DST(fc, oks1.flex_parser5_steering_ok);
370 fc->tag_set = &hws_definer_generic_set;
371 break;
372 case 6:
373 fc = &cd->fc[MLX5HWS_DEFINER_FNAME_FLEX_PARSER6_OK];
374 HWS_CALC_HDR_DST(fc, oks1.flex_parser6_steering_ok);
375 fc->tag_set = &hws_definer_generic_set;
376 break;
377 case 7:
378 fc = &cd->fc[MLX5HWS_DEFINER_FNAME_FLEX_PARSER7_OK];
379 HWS_CALC_HDR_DST(fc, oks1.flex_parser7_steering_ok);
380 fc->tag_set = &hws_definer_generic_set;
381 break;
382 default:
383 mlx5hws_err(cd->ctx, "Unsupported flex parser steering ok index %u\n", parser_id);
384 return NULL;
385 }
386
387 return fc;
388 }
389
390 static struct mlx5hws_definer_fc *
hws_definer_flex_parser_handler(struct mlx5hws_definer_conv_data * cd,u8 parser_id)391 hws_definer_flex_parser_handler(struct mlx5hws_definer_conv_data *cd,
392 u8 parser_id)
393 {
394 struct mlx5hws_definer_fc *fc;
395
396 switch (parser_id) {
397 case 0:
398 fc = &cd->fc[MLX5HWS_DEFINER_FNAME_FLEX_PARSER_0];
399 HWS_CALC_HDR_DST(fc, flex_parser.flex_parser_0);
400 fc->tag_set = &hws_definer_generic_set;
401 break;
402 case 1:
403 fc = &cd->fc[MLX5HWS_DEFINER_FNAME_FLEX_PARSER_1];
404 HWS_CALC_HDR_DST(fc, flex_parser.flex_parser_1);
405 fc->tag_set = &hws_definer_generic_set;
406 break;
407 case 2:
408 fc = &cd->fc[MLX5HWS_DEFINER_FNAME_FLEX_PARSER_2];
409 HWS_CALC_HDR_DST(fc, flex_parser.flex_parser_2);
410 fc->tag_set = &hws_definer_generic_set;
411 break;
412 case 3:
413 fc = &cd->fc[MLX5HWS_DEFINER_FNAME_FLEX_PARSER_3];
414 HWS_CALC_HDR_DST(fc, flex_parser.flex_parser_3);
415 fc->tag_set = &hws_definer_generic_set;
416 break;
417 case 4:
418 fc = &cd->fc[MLX5HWS_DEFINER_FNAME_FLEX_PARSER_4];
419 HWS_CALC_HDR_DST(fc, flex_parser.flex_parser_4);
420 fc->tag_set = &hws_definer_generic_set;
421 break;
422 case 5:
423 fc = &cd->fc[MLX5HWS_DEFINER_FNAME_FLEX_PARSER_5];
424 HWS_CALC_HDR_DST(fc, flex_parser.flex_parser_5);
425 fc->tag_set = &hws_definer_generic_set;
426 break;
427 case 6:
428 fc = &cd->fc[MLX5HWS_DEFINER_FNAME_FLEX_PARSER_6];
429 HWS_CALC_HDR_DST(fc, flex_parser.flex_parser_6);
430 fc->tag_set = &hws_definer_generic_set;
431 break;
432 case 7:
433 fc = &cd->fc[MLX5HWS_DEFINER_FNAME_FLEX_PARSER_7];
434 HWS_CALC_HDR_DST(fc, flex_parser.flex_parser_7);
435 fc->tag_set = &hws_definer_generic_set;
436 break;
437 default:
438 mlx5hws_err(cd->ctx, "Unsupported flex parser %u\n", parser_id);
439 return NULL;
440 }
441
442 return fc;
443 }
444
445 static struct mlx5hws_definer_fc *
hws_definer_misc4_fields_handler(struct mlx5hws_definer_conv_data * cd,bool * parser_is_used,u32 id,u32 value)446 hws_definer_misc4_fields_handler(struct mlx5hws_definer_conv_data *cd,
447 bool *parser_is_used,
448 u32 id,
449 u32 value)
450 {
451 if (id || value) {
452 if (id >= HWS_NUM_OF_FLEX_PARSERS) {
453 mlx5hws_err(cd->ctx, "Unsupported parser id\n");
454 return NULL;
455 }
456
457 if (parser_is_used[id]) {
458 mlx5hws_err(cd->ctx, "Parser id have been used\n");
459 return NULL;
460 }
461 }
462
463 parser_is_used[id] = true;
464
465 return hws_definer_flex_parser_handler(cd, id);
466 }
467
468 static int
hws_definer_check_match_flags(struct mlx5hws_definer_conv_data * cd)469 hws_definer_check_match_flags(struct mlx5hws_definer_conv_data *cd)
470 {
471 u32 flags;
472
473 flags = cd->match_flags & (MLX5HWS_DEFINER_MATCH_FLAG_TNL_VXLAN_GPE |
474 MLX5HWS_DEFINER_MATCH_FLAG_TNL_GENEVE |
475 MLX5HWS_DEFINER_MATCH_FLAG_TNL_GTPU |
476 MLX5HWS_DEFINER_MATCH_FLAG_TNL_GRE |
477 MLX5HWS_DEFINER_MATCH_FLAG_TNL_VXLAN |
478 MLX5HWS_DEFINER_MATCH_FLAG_TNL_HEADER_0_1);
479 if (flags & (flags - 1))
480 goto err_conflict;
481
482 flags = cd->match_flags & (MLX5HWS_DEFINER_MATCH_FLAG_TNL_GRE_OPT_KEY |
483 MLX5HWS_DEFINER_MATCH_FLAG_TNL_HEADER_2);
484
485 if (flags & (flags - 1))
486 goto err_conflict;
487
488 flags = cd->match_flags & (MLX5HWS_DEFINER_MATCH_FLAG_TNL_MPLS_OVER_GRE |
489 MLX5HWS_DEFINER_MATCH_FLAG_TNL_MPLS_OVER_UDP);
490 if (flags & (flags - 1))
491 goto err_conflict;
492
493 flags = cd->match_flags & (MLX5HWS_DEFINER_MATCH_FLAG_ICMPV4 |
494 MLX5HWS_DEFINER_MATCH_FLAG_ICMPV6 |
495 MLX5HWS_DEFINER_MATCH_FLAG_TCP_O |
496 MLX5HWS_DEFINER_MATCH_FLAG_TCP_I);
497 if (flags & (flags - 1))
498 goto err_conflict;
499
500 return 0;
501
502 err_conflict:
503 mlx5hws_err(cd->ctx, "Invalid definer fields combination\n");
504 return -EINVAL;
505 }
506
507 static int
hws_definer_conv_outer(struct mlx5hws_definer_conv_data * cd,u32 * match_param)508 hws_definer_conv_outer(struct mlx5hws_definer_conv_data *cd,
509 u32 *match_param)
510 {
511 bool is_s_ipv6, is_d_ipv6, smac_set, dmac_set;
512 struct mlx5hws_definer_fc *fc = cd->fc;
513 struct mlx5hws_definer_fc *curr_fc;
514 u32 *s_ipv6, *d_ipv6;
515
516 if (HWS_IS_FLD_SET_SZ(match_param, outer_headers.l4_type, 0x2) ||
517 HWS_IS_FLD_SET_SZ(match_param, outer_headers.reserved_at_c2, 0xe) ||
518 HWS_IS_FLD_SET_SZ(match_param, outer_headers.reserved_at_c4, 0x4)) {
519 mlx5hws_err(cd->ctx, "Unsupported outer parameters set\n");
520 return -EINVAL;
521 }
522
523 /* L2 Check ethertype */
524 HWS_SET_HDR(fc, match_param, ETH_TYPE_O,
525 outer_headers.ethertype,
526 eth_l2_outer.l3_ethertype);
527 /* L2 Check SMAC 47_16 */
528 HWS_SET_HDR(fc, match_param, ETH_SMAC_47_16_O,
529 outer_headers.smac_47_16, eth_l2_src_outer.smac_47_16);
530 /* L2 Check SMAC 15_0 */
531 HWS_SET_HDR(fc, match_param, ETH_SMAC_15_0_O,
532 outer_headers.smac_15_0, eth_l2_src_outer.smac_15_0);
533 /* L2 Check DMAC 47_16 */
534 HWS_SET_HDR(fc, match_param, ETH_DMAC_47_16_O,
535 outer_headers.dmac_47_16, eth_l2_outer.dmac_47_16);
536 /* L2 Check DMAC 15_0 */
537 HWS_SET_HDR(fc, match_param, ETH_DMAC_15_0_O,
538 outer_headers.dmac_15_0, eth_l2_outer.dmac_15_0);
539
540 /* L2 VLAN */
541 HWS_SET_HDR(fc, match_param, VLAN_FIRST_PRIO_O,
542 outer_headers.first_prio, eth_l2_outer.first_priority);
543 HWS_SET_HDR(fc, match_param, VLAN_CFI_O,
544 outer_headers.first_cfi, eth_l2_outer.first_cfi);
545 HWS_SET_HDR(fc, match_param, VLAN_ID_O,
546 outer_headers.first_vid, eth_l2_outer.first_vlan_id);
547
548 /* L2 CVLAN and SVLAN */
549 if (HWS_GET_MATCH_PARAM(match_param, outer_headers.cvlan_tag) ||
550 HWS_GET_MATCH_PARAM(match_param, outer_headers.svlan_tag)) {
551 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_VLAN_TYPE_O];
552 HWS_CALC_HDR_DST(curr_fc, eth_l2_outer.first_vlan_qualifier);
553 curr_fc->tag_set = &hws_definer_outer_vlan_type_set;
554 curr_fc->tag_mask_set = &hws_definer_ones_set;
555 }
556
557 /* L3 Check IP header */
558 HWS_SET_HDR(fc, match_param, IP_PROTOCOL_O,
559 outer_headers.ip_protocol,
560 eth_l3_outer.protocol_next_header);
561 HWS_SET_HDR(fc, match_param, IP_TTL_O,
562 outer_headers.ttl_hoplimit,
563 eth_l3_outer.time_to_live_hop_limit);
564
565 /* L3 Check IPv4/IPv6 addresses */
566 s_ipv6 = MLX5_ADDR_OF(fte_match_param, match_param,
567 outer_headers.src_ipv4_src_ipv6.ipv6_layout);
568 d_ipv6 = MLX5_ADDR_OF(fte_match_param, match_param,
569 outer_headers.dst_ipv4_dst_ipv6.ipv6_layout);
570
571 /* Assume IPv6 is used if ipv6 bits are set */
572 is_s_ipv6 = s_ipv6[0] || s_ipv6[1] || s_ipv6[2];
573 is_d_ipv6 = d_ipv6[0] || d_ipv6[1] || d_ipv6[2];
574
575 if (is_s_ipv6) {
576 /* Handle IPv6 source address */
577 HWS_SET_HDR(fc, match_param, IPV6_SRC_127_96_O,
578 outer_headers.src_ipv4_src_ipv6.ipv6_simple_layout.ipv6_127_96,
579 ipv6_src_outer.ipv6_address_127_96);
580 HWS_SET_HDR(fc, match_param, IPV6_SRC_95_64_O,
581 outer_headers.src_ipv4_src_ipv6.ipv6_simple_layout.ipv6_95_64,
582 ipv6_src_outer.ipv6_address_95_64);
583 HWS_SET_HDR(fc, match_param, IPV6_SRC_63_32_O,
584 outer_headers.src_ipv4_src_ipv6.ipv6_simple_layout.ipv6_63_32,
585 ipv6_src_outer.ipv6_address_63_32);
586 HWS_SET_HDR(fc, match_param, IPV6_SRC_31_0_O,
587 outer_headers.src_ipv4_src_ipv6.ipv6_simple_layout.ipv6_31_0,
588 ipv6_src_outer.ipv6_address_31_0);
589 } else {
590 /* Handle IPv4 source address */
591 HWS_SET_HDR(fc, match_param, IPV4_SRC_O,
592 outer_headers.src_ipv4_src_ipv6.ipv6_simple_layout.ipv6_31_0,
593 ipv4_src_dest_outer.source_address);
594 }
595 if (is_d_ipv6) {
596 /* Handle IPv6 destination address */
597 HWS_SET_HDR(fc, match_param, IPV6_DST_127_96_O,
598 outer_headers.dst_ipv4_dst_ipv6.ipv6_simple_layout.ipv6_127_96,
599 ipv6_dst_outer.ipv6_address_127_96);
600 HWS_SET_HDR(fc, match_param, IPV6_DST_95_64_O,
601 outer_headers.dst_ipv4_dst_ipv6.ipv6_simple_layout.ipv6_95_64,
602 ipv6_dst_outer.ipv6_address_95_64);
603 HWS_SET_HDR(fc, match_param, IPV6_DST_63_32_O,
604 outer_headers.dst_ipv4_dst_ipv6.ipv6_simple_layout.ipv6_63_32,
605 ipv6_dst_outer.ipv6_address_63_32);
606 HWS_SET_HDR(fc, match_param, IPV6_DST_31_0_O,
607 outer_headers.dst_ipv4_dst_ipv6.ipv6_simple_layout.ipv6_31_0,
608 ipv6_dst_outer.ipv6_address_31_0);
609 } else {
610 /* Handle IPv4 destination address */
611 HWS_SET_HDR(fc, match_param, IPV4_DST_O,
612 outer_headers.dst_ipv4_dst_ipv6.ipv6_simple_layout.ipv6_31_0,
613 ipv4_src_dest_outer.destination_address);
614 }
615
616 /* L4 Handle TCP/UDP */
617 HWS_SET_HDR(fc, match_param, L4_SPORT_O,
618 outer_headers.tcp_sport, eth_l4_outer.source_port);
619 HWS_SET_HDR(fc, match_param, L4_DPORT_O,
620 outer_headers.tcp_dport, eth_l4_outer.destination_port);
621 HWS_SET_HDR(fc, match_param, L4_SPORT_O,
622 outer_headers.udp_sport, eth_l4_outer.source_port);
623 HWS_SET_HDR(fc, match_param, L4_DPORT_O,
624 outer_headers.udp_dport, eth_l4_outer.destination_port);
625 HWS_SET_HDR(fc, match_param, TCP_FLAGS_O,
626 outer_headers.tcp_flags, eth_l4_outer.tcp_flags);
627
628 /* L3 Handle DSCP, ECN and IHL */
629 HWS_SET_HDR(fc, match_param, IP_DSCP_O,
630 outer_headers.ip_dscp, eth_l3_outer.dscp);
631 HWS_SET_HDR(fc, match_param, IP_ECN_O,
632 outer_headers.ip_ecn, eth_l3_outer.ecn);
633 HWS_SET_HDR(fc, match_param, IPV4_IHL_O,
634 outer_headers.ipv4_ihl, eth_l3_outer.ihl);
635
636 /* Set IP fragmented bit */
637 if (HWS_IS_FLD_SET(match_param, outer_headers.frag)) {
638 smac_set = HWS_IS_FLD_SET(match_param, outer_headers.smac_15_0) ||
639 HWS_IS_FLD_SET(match_param, outer_headers.smac_47_16);
640 dmac_set = HWS_IS_FLD_SET(match_param, outer_headers.dmac_15_0) ||
641 HWS_IS_FLD_SET(match_param, outer_headers.dmac_47_16);
642 if (smac_set == dmac_set) {
643 HWS_SET_HDR(fc, match_param, IP_FRAG_O,
644 outer_headers.frag, eth_l4_outer.ip_fragmented);
645 } else {
646 HWS_SET_HDR(fc, match_param, IP_FRAG_O,
647 outer_headers.frag, eth_l2_src_outer.ip_fragmented);
648 }
649 }
650
651 /* L3_type set */
652 if (HWS_IS_FLD_SET(match_param, outer_headers.ip_version)) {
653 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_ETH_L3_TYPE_O];
654 HWS_CALC_HDR_DST(curr_fc, eth_l2_outer.l3_type);
655 curr_fc->tag_set = &hws_definer_l3_type_set;
656 curr_fc->tag_mask_set = &hws_definer_ones_set;
657 HWS_CALC_HDR_SRC(curr_fc, outer_headers.ip_version);
658 }
659
660 return 0;
661 }
662
663 static int
hws_definer_conv_inner(struct mlx5hws_definer_conv_data * cd,u32 * match_param)664 hws_definer_conv_inner(struct mlx5hws_definer_conv_data *cd,
665 u32 *match_param)
666 {
667 bool is_s_ipv6, is_d_ipv6, smac_set, dmac_set;
668 struct mlx5hws_definer_fc *fc = cd->fc;
669 struct mlx5hws_definer_fc *curr_fc;
670 u32 *s_ipv6, *d_ipv6;
671
672 if (HWS_IS_FLD_SET_SZ(match_param, inner_headers.l4_type, 0x2) ||
673 HWS_IS_FLD_SET_SZ(match_param, inner_headers.reserved_at_c2, 0xe) ||
674 HWS_IS_FLD_SET_SZ(match_param, inner_headers.reserved_at_c4, 0x4)) {
675 mlx5hws_err(cd->ctx, "Unsupported inner parameters set\n");
676 return -EINVAL;
677 }
678
679 /* L2 Check ethertype */
680 HWS_SET_HDR(fc, match_param, ETH_TYPE_I,
681 inner_headers.ethertype,
682 eth_l2_inner.l3_ethertype);
683 /* L2 Check SMAC 47_16 */
684 HWS_SET_HDR(fc, match_param, ETH_SMAC_47_16_I,
685 inner_headers.smac_47_16, eth_l2_src_inner.smac_47_16);
686 /* L2 Check SMAC 15_0 */
687 HWS_SET_HDR(fc, match_param, ETH_SMAC_15_0_I,
688 inner_headers.smac_15_0, eth_l2_src_inner.smac_15_0);
689 /* L2 Check DMAC 47_16 */
690 HWS_SET_HDR(fc, match_param, ETH_DMAC_47_16_I,
691 inner_headers.dmac_47_16, eth_l2_inner.dmac_47_16);
692 /* L2 Check DMAC 15_0 */
693 HWS_SET_HDR(fc, match_param, ETH_DMAC_15_0_I,
694 inner_headers.dmac_15_0, eth_l2_inner.dmac_15_0);
695
696 /* L2 VLAN */
697 HWS_SET_HDR(fc, match_param, VLAN_FIRST_PRIO_I,
698 inner_headers.first_prio, eth_l2_inner.first_priority);
699 HWS_SET_HDR(fc, match_param, VLAN_CFI_I,
700 inner_headers.first_cfi, eth_l2_inner.first_cfi);
701 HWS_SET_HDR(fc, match_param, VLAN_ID_I,
702 inner_headers.first_vid, eth_l2_inner.first_vlan_id);
703
704 /* L2 CVLAN and SVLAN */
705 if (HWS_GET_MATCH_PARAM(match_param, inner_headers.cvlan_tag) ||
706 HWS_GET_MATCH_PARAM(match_param, inner_headers.svlan_tag)) {
707 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_VLAN_TYPE_I];
708 HWS_CALC_HDR_DST(curr_fc, eth_l2_inner.first_vlan_qualifier);
709 curr_fc->tag_set = &hws_definer_inner_vlan_type_set;
710 curr_fc->tag_mask_set = &hws_definer_ones_set;
711 }
712 /* L3 Check IP header */
713 HWS_SET_HDR(fc, match_param, IP_PROTOCOL_I,
714 inner_headers.ip_protocol,
715 eth_l3_inner.protocol_next_header);
716 HWS_SET_HDR(fc, match_param, IP_VERSION_I,
717 inner_headers.ip_version,
718 eth_l3_inner.ip_version);
719 HWS_SET_HDR(fc, match_param, IP_TTL_I,
720 inner_headers.ttl_hoplimit,
721 eth_l3_inner.time_to_live_hop_limit);
722
723 /* L3 Check IPv4/IPv6 addresses */
724 s_ipv6 = MLX5_ADDR_OF(fte_match_param, match_param,
725 inner_headers.src_ipv4_src_ipv6.ipv6_layout);
726 d_ipv6 = MLX5_ADDR_OF(fte_match_param, match_param,
727 inner_headers.dst_ipv4_dst_ipv6.ipv6_layout);
728
729 /* Assume IPv6 is used if ipv6 bits are set */
730 is_s_ipv6 = s_ipv6[0] || s_ipv6[1] || s_ipv6[2];
731 is_d_ipv6 = d_ipv6[0] || d_ipv6[1] || d_ipv6[2];
732
733 if (is_s_ipv6) {
734 /* Handle IPv6 source address */
735 HWS_SET_HDR(fc, match_param, IPV6_SRC_127_96_I,
736 inner_headers.src_ipv4_src_ipv6.ipv6_simple_layout.ipv6_127_96,
737 ipv6_src_inner.ipv6_address_127_96);
738 HWS_SET_HDR(fc, match_param, IPV6_SRC_95_64_I,
739 inner_headers.src_ipv4_src_ipv6.ipv6_simple_layout.ipv6_95_64,
740 ipv6_src_inner.ipv6_address_95_64);
741 HWS_SET_HDR(fc, match_param, IPV6_SRC_63_32_I,
742 inner_headers.src_ipv4_src_ipv6.ipv6_simple_layout.ipv6_63_32,
743 ipv6_src_inner.ipv6_address_63_32);
744 HWS_SET_HDR(fc, match_param, IPV6_SRC_31_0_I,
745 inner_headers.src_ipv4_src_ipv6.ipv6_simple_layout.ipv6_31_0,
746 ipv6_src_inner.ipv6_address_31_0);
747 } else {
748 /* Handle IPv4 source address */
749 HWS_SET_HDR(fc, match_param, IPV4_SRC_I,
750 inner_headers.src_ipv4_src_ipv6.ipv6_simple_layout.ipv6_31_0,
751 ipv4_src_dest_inner.source_address);
752 }
753 if (is_d_ipv6) {
754 /* Handle IPv6 destination address */
755 HWS_SET_HDR(fc, match_param, IPV6_DST_127_96_I,
756 inner_headers.dst_ipv4_dst_ipv6.ipv6_simple_layout.ipv6_127_96,
757 ipv6_dst_inner.ipv6_address_127_96);
758 HWS_SET_HDR(fc, match_param, IPV6_DST_95_64_I,
759 inner_headers.dst_ipv4_dst_ipv6.ipv6_simple_layout.ipv6_95_64,
760 ipv6_dst_inner.ipv6_address_95_64);
761 HWS_SET_HDR(fc, match_param, IPV6_DST_63_32_I,
762 inner_headers.dst_ipv4_dst_ipv6.ipv6_simple_layout.ipv6_63_32,
763 ipv6_dst_inner.ipv6_address_63_32);
764 HWS_SET_HDR(fc, match_param, IPV6_DST_31_0_I,
765 inner_headers.dst_ipv4_dst_ipv6.ipv6_simple_layout.ipv6_31_0,
766 ipv6_dst_inner.ipv6_address_31_0);
767 } else {
768 /* Handle IPv4 destination address */
769 HWS_SET_HDR(fc, match_param, IPV4_DST_I,
770 inner_headers.dst_ipv4_dst_ipv6.ipv6_simple_layout.ipv6_31_0,
771 ipv4_src_dest_inner.destination_address);
772 }
773
774 /* L4 Handle TCP/UDP */
775 HWS_SET_HDR(fc, match_param, L4_SPORT_I,
776 inner_headers.tcp_sport, eth_l4_inner.source_port);
777 HWS_SET_HDR(fc, match_param, L4_DPORT_I,
778 inner_headers.tcp_dport, eth_l4_inner.destination_port);
779 HWS_SET_HDR(fc, match_param, L4_SPORT_I,
780 inner_headers.udp_sport, eth_l4_inner.source_port);
781 HWS_SET_HDR(fc, match_param, L4_DPORT_I,
782 inner_headers.udp_dport, eth_l4_inner.destination_port);
783 HWS_SET_HDR(fc, match_param, TCP_FLAGS_I,
784 inner_headers.tcp_flags, eth_l4_inner.tcp_flags);
785
786 /* L3 Handle DSCP, ECN and IHL */
787 HWS_SET_HDR(fc, match_param, IP_DSCP_I,
788 inner_headers.ip_dscp, eth_l3_inner.dscp);
789 HWS_SET_HDR(fc, match_param, IP_ECN_I,
790 inner_headers.ip_ecn, eth_l3_inner.ecn);
791 HWS_SET_HDR(fc, match_param, IPV4_IHL_I,
792 inner_headers.ipv4_ihl, eth_l3_inner.ihl);
793
794 /* Set IP fragmented bit */
795 if (HWS_IS_FLD_SET(match_param, inner_headers.frag)) {
796 if (HWS_IS_FLD_SET(match_param, misc_parameters.vxlan_vni)) {
797 HWS_SET_HDR(fc, match_param, IP_FRAG_I,
798 inner_headers.frag, eth_l2_inner.ip_fragmented);
799 } else {
800 smac_set = HWS_IS_FLD_SET(match_param, inner_headers.smac_15_0) ||
801 HWS_IS_FLD_SET(match_param, inner_headers.smac_47_16);
802 dmac_set = HWS_IS_FLD_SET(match_param, inner_headers.dmac_15_0) ||
803 HWS_IS_FLD_SET(match_param, inner_headers.dmac_47_16);
804 if (smac_set == dmac_set) {
805 HWS_SET_HDR(fc, match_param, IP_FRAG_I,
806 inner_headers.frag, eth_l4_inner.ip_fragmented);
807 } else {
808 HWS_SET_HDR(fc, match_param, IP_FRAG_I,
809 inner_headers.frag, eth_l2_src_inner.ip_fragmented);
810 }
811 }
812 }
813
814 /* L3_type set */
815 if (HWS_IS_FLD_SET(match_param, inner_headers.ip_version)) {
816 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_ETH_L3_TYPE_I];
817 HWS_CALC_HDR_DST(curr_fc, eth_l2_inner.l3_type);
818 curr_fc->tag_set = &hws_definer_l3_type_set;
819 curr_fc->tag_mask_set = &hws_definer_ones_set;
820 HWS_CALC_HDR_SRC(curr_fc, inner_headers.ip_version);
821 }
822
823 return 0;
824 }
825
826 static int
hws_definer_conv_misc(struct mlx5hws_definer_conv_data * cd,u32 * match_param)827 hws_definer_conv_misc(struct mlx5hws_definer_conv_data *cd,
828 u32 *match_param)
829 {
830 struct mlx5hws_cmd_query_caps *caps = cd->ctx->caps;
831 struct mlx5hws_definer_fc *fc = cd->fc;
832 struct mlx5hws_definer_fc *curr_fc;
833
834 if (HWS_IS_FLD_SET_SZ(match_param, misc_parameters.reserved_at_1, 0x1) ||
835 HWS_IS_FLD_SET_SZ(match_param, misc_parameters.reserved_at_64, 0xc) ||
836 HWS_IS_FLD_SET_SZ(match_param, misc_parameters.reserved_at_d8, 0x6) ||
837 HWS_IS_FLD_SET_SZ(match_param, misc_parameters.reserved_at_e0, 0xc) ||
838 HWS_IS_FLD_SET_SZ(match_param, misc_parameters.reserved_at_100, 0xc) ||
839 HWS_IS_FLD_SET_SZ(match_param, misc_parameters.reserved_at_120, 0xa) ||
840 HWS_IS_FLD_SET_SZ(match_param, misc_parameters.reserved_at_140, 0x8) ||
841 HWS_IS_FLD_SET(match_param, misc_parameters.bth_dst_qp) ||
842 HWS_IS_FLD_SET(match_param, misc_parameters.bth_opcode) ||
843 HWS_IS_FLD_SET(match_param, misc_parameters.inner_esp_spi) ||
844 HWS_IS_FLD_SET(match_param, misc_parameters.outer_esp_spi) ||
845 HWS_IS_FLD_SET(match_param, misc_parameters.source_vhca_port) ||
846 HWS_IS_FLD_SET_SZ(match_param, misc_parameters.reserved_at_1a0, 0x60)) {
847 mlx5hws_err(cd->ctx, "Unsupported misc parameters set\n");
848 return -EINVAL;
849 }
850
851 /* Check GRE related fields */
852 if (HWS_IS_FLD_SET(match_param, misc_parameters.gre_c_present)) {
853 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_GRE;
854 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_GRE_C];
855 HWS_CALC_HDR(curr_fc,
856 misc_parameters.gre_c_present,
857 tunnel_header.tunnel_header_0);
858 curr_fc->bit_mask = __mlx5_mask(header_gre, gre_c_present);
859 curr_fc->bit_off = __mlx5_dw_bit_off(header_gre, gre_c_present);
860 }
861
862 if (HWS_IS_FLD_SET(match_param, misc_parameters.gre_k_present)) {
863 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_GRE;
864 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_GRE_K];
865 HWS_CALC_HDR(curr_fc,
866 misc_parameters.gre_k_present,
867 tunnel_header.tunnel_header_0);
868 curr_fc->bit_mask = __mlx5_mask(header_gre, gre_k_present);
869 curr_fc->bit_off = __mlx5_dw_bit_off(header_gre, gre_k_present);
870 }
871
872 if (HWS_IS_FLD_SET(match_param, misc_parameters.gre_s_present)) {
873 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_GRE;
874 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_GRE_S];
875 HWS_CALC_HDR(curr_fc,
876 misc_parameters.gre_s_present,
877 tunnel_header.tunnel_header_0);
878 curr_fc->bit_mask = __mlx5_mask(header_gre, gre_s_present);
879 curr_fc->bit_off = __mlx5_dw_bit_off(header_gre, gre_s_present);
880 }
881
882 if (HWS_IS_FLD_SET(match_param, misc_parameters.gre_protocol)) {
883 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_GRE;
884 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_GRE_PROTOCOL];
885 HWS_CALC_HDR(curr_fc,
886 misc_parameters.gre_protocol,
887 tunnel_header.tunnel_header_0);
888 curr_fc->bit_mask = __mlx5_mask(header_gre, gre_protocol);
889 curr_fc->bit_off = __mlx5_dw_bit_off(header_gre, gre_protocol);
890 }
891
892 if (HWS_IS_FLD_SET(match_param, misc_parameters.gre_key.key)) {
893 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_GRE |
894 MLX5HWS_DEFINER_MATCH_FLAG_TNL_GRE_OPT_KEY;
895 HWS_SET_HDR(fc, match_param, GRE_OPT_KEY,
896 misc_parameters.gre_key.key, tunnel_header.tunnel_header_2);
897 }
898
899 /* Check GENEVE related fields */
900 if (HWS_IS_FLD_SET(match_param, misc_parameters.geneve_vni)) {
901 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_GENEVE;
902 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_GENEVE_VNI];
903 HWS_CALC_HDR(curr_fc,
904 misc_parameters.geneve_vni,
905 tunnel_header.tunnel_header_1);
906 curr_fc->bit_mask = __mlx5_mask(header_geneve, vni);
907 curr_fc->bit_off = __mlx5_dw_bit_off(header_geneve, vni);
908 }
909
910 if (HWS_IS_FLD_SET(match_param, misc_parameters.geneve_opt_len)) {
911 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_GENEVE;
912 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_GENEVE_OPT_LEN];
913 HWS_CALC_HDR(curr_fc,
914 misc_parameters.geneve_opt_len,
915 tunnel_header.tunnel_header_0);
916 curr_fc->bit_mask = __mlx5_mask(header_geneve, opt_len);
917 curr_fc->bit_off = __mlx5_dw_bit_off(header_geneve, opt_len);
918 }
919
920 if (HWS_IS_FLD_SET(match_param, misc_parameters.geneve_protocol_type)) {
921 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_GENEVE;
922 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_GENEVE_PROTO];
923 HWS_CALC_HDR(curr_fc,
924 misc_parameters.geneve_protocol_type,
925 tunnel_header.tunnel_header_0);
926 curr_fc->bit_mask = __mlx5_mask(header_geneve, protocol_type);
927 curr_fc->bit_off = __mlx5_dw_bit_off(header_geneve, protocol_type);
928 }
929
930 if (HWS_IS_FLD_SET(match_param, misc_parameters.geneve_oam)) {
931 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_GENEVE;
932 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_GENEVE_OAM];
933 HWS_CALC_HDR(curr_fc,
934 misc_parameters.geneve_oam,
935 tunnel_header.tunnel_header_0);
936 curr_fc->bit_mask = __mlx5_mask(header_geneve, o_flag);
937 curr_fc->bit_off = __mlx5_dw_bit_off(header_geneve, o_flag);
938 }
939
940 HWS_SET_HDR(fc, match_param, SOURCE_QP,
941 misc_parameters.source_sqn, source_qp_gvmi.source_qp);
942 HWS_SET_HDR(fc, match_param, IPV6_FLOW_LABEL_O,
943 misc_parameters.outer_ipv6_flow_label, eth_l3_outer.flow_label);
944 HWS_SET_HDR(fc, match_param, IPV6_FLOW_LABEL_I,
945 misc_parameters.inner_ipv6_flow_label, eth_l3_inner.flow_label);
946
947 /* L2 Second VLAN */
948 HWS_SET_HDR(fc, match_param, VLAN_SECOND_PRIO_O,
949 misc_parameters.outer_second_prio, eth_l2_outer.second_priority);
950 HWS_SET_HDR(fc, match_param, VLAN_SECOND_PRIO_I,
951 misc_parameters.inner_second_prio, eth_l2_inner.second_priority);
952 HWS_SET_HDR(fc, match_param, VLAN_SECOND_CFI_O,
953 misc_parameters.outer_second_cfi, eth_l2_outer.second_cfi);
954 HWS_SET_HDR(fc, match_param, VLAN_SECOND_CFI_I,
955 misc_parameters.inner_second_cfi, eth_l2_inner.second_cfi);
956 HWS_SET_HDR(fc, match_param, VLAN_SECOND_ID_O,
957 misc_parameters.outer_second_vid, eth_l2_outer.second_vlan_id);
958 HWS_SET_HDR(fc, match_param, VLAN_SECOND_ID_I,
959 misc_parameters.inner_second_vid, eth_l2_inner.second_vlan_id);
960
961 /* L2 Second CVLAN and SVLAN */
962 if (HWS_GET_MATCH_PARAM(match_param, misc_parameters.outer_second_cvlan_tag) ||
963 HWS_GET_MATCH_PARAM(match_param, misc_parameters.outer_second_svlan_tag)) {
964 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_VLAN_SECOND_TYPE_O];
965 HWS_CALC_HDR_DST(curr_fc, eth_l2_outer.second_vlan_qualifier);
966 curr_fc->tag_set = &hws_definer_outer_second_vlan_type_set;
967 curr_fc->tag_mask_set = &hws_definer_ones_set;
968 }
969
970 if (HWS_GET_MATCH_PARAM(match_param, misc_parameters.inner_second_cvlan_tag) ||
971 HWS_GET_MATCH_PARAM(match_param, misc_parameters.inner_second_svlan_tag)) {
972 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_VLAN_SECOND_TYPE_I];
973 HWS_CALC_HDR_DST(curr_fc, eth_l2_inner.second_vlan_qualifier);
974 curr_fc->tag_set = &hws_definer_inner_second_vlan_type_set;
975 curr_fc->tag_mask_set = &hws_definer_ones_set;
976 }
977
978 /* VXLAN VNI */
979 if (HWS_GET_MATCH_PARAM(match_param, misc_parameters.vxlan_vni)) {
980 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_VXLAN;
981 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_VXLAN_VNI];
982 HWS_CALC_HDR(curr_fc, misc_parameters.vxlan_vni, tunnel_header.tunnel_header_1);
983 curr_fc->bit_mask = __mlx5_mask(header_vxlan, vni);
984 curr_fc->bit_off = __mlx5_dw_bit_off(header_vxlan, vni);
985 }
986
987 /* Flex protocol steering ok bits */
988 if (HWS_GET_MATCH_PARAM(match_param, misc_parameters.geneve_tlv_option_0_exist)) {
989 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_GENEVE;
990
991 if (!caps->flex_parser_ok_bits_supp) {
992 mlx5hws_err(cd->ctx, "Unsupported flex_parser_ok_bits_supp capability\n");
993 return -EOPNOTSUPP;
994 }
995
996 curr_fc = hws_definer_flex_parser_steering_ok_bits_handler(
997 cd, caps->flex_parser_id_geneve_tlv_option_0);
998 if (!curr_fc)
999 return -EINVAL;
1000
1001 HWS_CALC_HDR_SRC(fc, misc_parameters.geneve_tlv_option_0_exist);
1002 }
1003
1004 if (HWS_GET_MATCH_PARAM(match_param, misc_parameters.source_port)) {
1005 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_SOURCE_GVMI];
1006 HWS_CALC_HDR_DST(curr_fc, source_qp_gvmi.source_gvmi);
1007 curr_fc->tag_mask_set = &hws_definer_ones_set;
1008 curr_fc->tag_set = HWS_IS_FLD_SET(match_param,
1009 misc_parameters.source_eswitch_owner_vhca_id) ?
1010 &hws_definer_set_source_gvmi_vhca_id :
1011 &hws_definer_set_source_gvmi;
1012 } else {
1013 if (HWS_IS_FLD_SET(match_param, misc_parameters.source_eswitch_owner_vhca_id)) {
1014 mlx5hws_err(cd->ctx,
1015 "Unsupported source_eswitch_owner_vhca_id field usage\n");
1016 return -EOPNOTSUPP;
1017 }
1018 }
1019
1020 return 0;
1021 }
1022
1023 static int
hws_definer_conv_misc2(struct mlx5hws_definer_conv_data * cd,u32 * match_param)1024 hws_definer_conv_misc2(struct mlx5hws_definer_conv_data *cd,
1025 u32 *match_param)
1026 {
1027 struct mlx5hws_cmd_query_caps *caps = cd->ctx->caps;
1028 struct mlx5hws_definer_fc *fc = cd->fc;
1029 struct mlx5hws_definer_fc *curr_fc;
1030
1031 if (HWS_IS_FLD_SET_SZ(match_param, misc_parameters_2.reserved_at_1a0, 0x8) ||
1032 HWS_IS_FLD_SET_SZ(match_param, misc_parameters_2.reserved_at_1b8, 0x8) ||
1033 HWS_IS_FLD_SET_SZ(match_param, misc_parameters_2.reserved_at_1c0, 0x40) ||
1034 HWS_IS_FLD_SET(match_param, misc_parameters_2.macsec_syndrome) ||
1035 HWS_IS_FLD_SET(match_param, misc_parameters_2.ipsec_syndrome)) {
1036 mlx5hws_err(cd->ctx, "Unsupported misc2 parameters set\n");
1037 return -EINVAL;
1038 }
1039
1040 HWS_SET_HDR(fc, match_param, MPLS0_O,
1041 misc_parameters_2.outer_first_mpls, mpls_outer.mpls0_label);
1042 HWS_SET_HDR(fc, match_param, MPLS0_I,
1043 misc_parameters_2.inner_first_mpls, mpls_inner.mpls0_label);
1044 HWS_SET_HDR(fc, match_param, REG_0,
1045 misc_parameters_2.metadata_reg_c_0, registers.register_c_0);
1046 HWS_SET_HDR(fc, match_param, REG_1,
1047 misc_parameters_2.metadata_reg_c_1, registers.register_c_1);
1048 HWS_SET_HDR(fc, match_param, REG_2,
1049 misc_parameters_2.metadata_reg_c_2, registers.register_c_2);
1050 HWS_SET_HDR(fc, match_param, REG_3,
1051 misc_parameters_2.metadata_reg_c_3, registers.register_c_3);
1052 HWS_SET_HDR(fc, match_param, REG_4,
1053 misc_parameters_2.metadata_reg_c_4, registers.register_c_4);
1054 HWS_SET_HDR(fc, match_param, REG_5,
1055 misc_parameters_2.metadata_reg_c_5, registers.register_c_5);
1056 HWS_SET_HDR(fc, match_param, REG_6,
1057 misc_parameters_2.metadata_reg_c_6, registers.register_c_6);
1058 HWS_SET_HDR(fc, match_param, REG_7,
1059 misc_parameters_2.metadata_reg_c_7, registers.register_c_7);
1060 HWS_SET_HDR(fc, match_param, REG_A,
1061 misc_parameters_2.metadata_reg_a, metadata.general_purpose);
1062
1063 if (HWS_IS_FLD_SET(match_param, misc_parameters_2.outer_first_mpls_over_gre)) {
1064 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_MPLS_OVER_GRE;
1065
1066 if (!(caps->flex_protocols & MLX5_FLEX_PARSER_MPLS_OVER_GRE_ENABLED)) {
1067 mlx5hws_err(cd->ctx, "Unsupported misc2 first mpls over gre parameters set\n");
1068 return -EOPNOTSUPP;
1069 }
1070
1071 curr_fc = hws_definer_flex_parser_handler(cd, caps->flex_parser_id_mpls_over_gre);
1072 if (!curr_fc)
1073 return -EINVAL;
1074
1075 HWS_CALC_HDR_SRC(fc, misc_parameters_2.outer_first_mpls_over_gre);
1076 }
1077
1078 if (HWS_IS_FLD_SET(match_param, misc_parameters_2.outer_first_mpls_over_udp)) {
1079 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_MPLS_OVER_UDP;
1080
1081 if (!(caps->flex_protocols & MLX5_FLEX_PARSER_MPLS_OVER_UDP_ENABLED)) {
1082 mlx5hws_err(cd->ctx, "Unsupported misc2 first mpls over udp parameters set\n");
1083 return -EOPNOTSUPP;
1084 }
1085
1086 curr_fc = hws_definer_flex_parser_handler(cd, caps->flex_parser_id_mpls_over_udp);
1087 if (!curr_fc)
1088 return -EINVAL;
1089
1090 HWS_CALC_HDR_SRC(fc, misc_parameters_2.outer_first_mpls_over_udp);
1091 }
1092
1093 return 0;
1094 }
1095
1096 static int
hws_definer_conv_misc3(struct mlx5hws_definer_conv_data * cd,u32 * match_param)1097 hws_definer_conv_misc3(struct mlx5hws_definer_conv_data *cd, u32 *match_param)
1098 {
1099 struct mlx5hws_cmd_query_caps *caps = cd->ctx->caps;
1100 struct mlx5hws_definer_fc *fc = cd->fc;
1101 struct mlx5hws_definer_fc *curr_fc;
1102 bool vxlan_gpe_flex_parser_enabled;
1103
1104 /* Check reserved and unsupported fields */
1105 if (HWS_IS_FLD_SET_SZ(match_param, misc_parameters_3.reserved_at_80, 0x8) ||
1106 HWS_IS_FLD_SET_SZ(match_param, misc_parameters_3.reserved_at_b0, 0x10) ||
1107 HWS_IS_FLD_SET_SZ(match_param, misc_parameters_3.reserved_at_170, 0x10) ||
1108 HWS_IS_FLD_SET_SZ(match_param, misc_parameters_3.reserved_at_1e0, 0x20)) {
1109 mlx5hws_err(cd->ctx, "Unsupported misc3 parameters set\n");
1110 return -EINVAL;
1111 }
1112
1113 if (HWS_IS_FLD_SET(match_param, misc_parameters_3.inner_tcp_seq_num) ||
1114 HWS_IS_FLD_SET(match_param, misc_parameters_3.inner_tcp_ack_num)) {
1115 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TCP_I;
1116 HWS_SET_HDR(fc, match_param, TCP_SEQ_NUM,
1117 misc_parameters_3.inner_tcp_seq_num, tcp_icmp.tcp_seq);
1118 HWS_SET_HDR(fc, match_param, TCP_ACK_NUM,
1119 misc_parameters_3.inner_tcp_ack_num, tcp_icmp.tcp_ack);
1120 }
1121
1122 if (HWS_IS_FLD_SET(match_param, misc_parameters_3.outer_tcp_seq_num) ||
1123 HWS_IS_FLD_SET(match_param, misc_parameters_3.outer_tcp_ack_num)) {
1124 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TCP_O;
1125 HWS_SET_HDR(fc, match_param, TCP_SEQ_NUM,
1126 misc_parameters_3.outer_tcp_seq_num, tcp_icmp.tcp_seq);
1127 HWS_SET_HDR(fc, match_param, TCP_ACK_NUM,
1128 misc_parameters_3.outer_tcp_ack_num, tcp_icmp.tcp_ack);
1129 }
1130
1131 vxlan_gpe_flex_parser_enabled = caps->flex_protocols & MLX5_FLEX_PARSER_VXLAN_GPE_ENABLED;
1132
1133 if (HWS_IS_FLD_SET(match_param, misc_parameters_3.outer_vxlan_gpe_vni)) {
1134 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_VXLAN_GPE;
1135
1136 if (!vxlan_gpe_flex_parser_enabled) {
1137 mlx5hws_err(cd->ctx, "Unsupported VXLAN GPE flex parser\n");
1138 return -EOPNOTSUPP;
1139 }
1140
1141 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_VXLAN_GPE_VNI];
1142 HWS_CALC_HDR(curr_fc, misc_parameters_3.outer_vxlan_gpe_vni,
1143 tunnel_header.tunnel_header_1);
1144 curr_fc->bit_mask = __mlx5_mask(header_vxlan_gpe, vni);
1145 curr_fc->bit_off = __mlx5_dw_bit_off(header_vxlan_gpe, vni);
1146 }
1147
1148 if (HWS_IS_FLD_SET(match_param, misc_parameters_3.outer_vxlan_gpe_next_protocol)) {
1149 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_VXLAN_GPE;
1150
1151 if (!vxlan_gpe_flex_parser_enabled) {
1152 mlx5hws_err(cd->ctx, "Unsupported VXLAN GPE flex parser\n");
1153 return -EOPNOTSUPP;
1154 }
1155
1156 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_VXLAN_GPE_PROTO];
1157 HWS_CALC_HDR(curr_fc, misc_parameters_3.outer_vxlan_gpe_next_protocol,
1158 tunnel_header.tunnel_header_0);
1159 curr_fc->byte_off += MLX5_BYTE_OFF(header_vxlan_gpe, protocol);
1160 curr_fc->bit_mask = __mlx5_mask(header_vxlan_gpe, protocol);
1161 curr_fc->bit_off = __mlx5_dw_bit_off(header_vxlan_gpe, protocol);
1162 }
1163
1164 if (HWS_IS_FLD_SET(match_param, misc_parameters_3.outer_vxlan_gpe_flags)) {
1165 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_VXLAN_GPE;
1166
1167 if (!vxlan_gpe_flex_parser_enabled) {
1168 mlx5hws_err(cd->ctx, "Unsupported VXLAN GPE flex parser\n");
1169 return -EOPNOTSUPP;
1170 }
1171
1172 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_VXLAN_GPE_FLAGS];
1173 HWS_CALC_HDR(curr_fc, misc_parameters_3.outer_vxlan_gpe_flags,
1174 tunnel_header.tunnel_header_0);
1175 curr_fc->bit_mask = __mlx5_mask(header_vxlan_gpe, flags);
1176 curr_fc->bit_off = __mlx5_dw_bit_off(header_vxlan_gpe, flags);
1177 }
1178
1179 if (HWS_IS_FLD_SET(match_param, misc_parameters_3.icmp_header_data) ||
1180 HWS_IS_FLD_SET(match_param, misc_parameters_3.icmp_type) ||
1181 HWS_IS_FLD_SET(match_param, misc_parameters_3.icmp_code)) {
1182 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_ICMPV4;
1183
1184 if (!(caps->flex_protocols & MLX5_FLEX_PARSER_ICMP_V4_ENABLED)) {
1185 mlx5hws_err(cd->ctx, "Unsupported ICMPv4 flex parser\n");
1186 return -EOPNOTSUPP;
1187 }
1188
1189 HWS_SET_HDR(fc, match_param, ICMP_DW3,
1190 misc_parameters_3.icmp_header_data, tcp_icmp.icmp_dw3);
1191
1192 if (HWS_IS_FLD_SET(match_param, misc_parameters_3.icmp_type) ||
1193 HWS_IS_FLD_SET(match_param, misc_parameters_3.icmp_code)) {
1194 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_ICMP_DW1];
1195 HWS_CALC_HDR_DST(curr_fc, tcp_icmp.icmp_dw1);
1196 curr_fc->tag_set = &hws_definer_icmp_dw1_set;
1197 }
1198 }
1199
1200 if (HWS_IS_FLD_SET(match_param, misc_parameters_3.icmpv6_header_data) ||
1201 HWS_IS_FLD_SET(match_param, misc_parameters_3.icmpv6_type) ||
1202 HWS_IS_FLD_SET(match_param, misc_parameters_3.icmpv6_code)) {
1203 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_ICMPV6;
1204
1205 if (!(caps->flex_protocols & MLX5_FLEX_PARSER_ICMP_V6_ENABLED)) {
1206 mlx5hws_err(cd->ctx, "Unsupported ICMPv6 parser\n");
1207 return -EOPNOTSUPP;
1208 }
1209
1210 HWS_SET_HDR(fc, match_param, ICMP_DW3,
1211 misc_parameters_3.icmpv6_header_data, tcp_icmp.icmp_dw3);
1212
1213 if (HWS_IS_FLD_SET(match_param, misc_parameters_3.icmpv6_type) ||
1214 HWS_IS_FLD_SET(match_param, misc_parameters_3.icmpv6_code)) {
1215 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_ICMP_DW1];
1216 HWS_CALC_HDR_DST(curr_fc, tcp_icmp.icmp_dw1);
1217 curr_fc->tag_set = &hws_definer_icmpv6_dw1_set;
1218 }
1219 }
1220
1221 if (HWS_IS_FLD_SET(match_param, misc_parameters_3.geneve_tlv_option_0_data)) {
1222 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_GENEVE;
1223
1224 curr_fc =
1225 hws_definer_flex_parser_handler(cd,
1226 caps->flex_parser_id_geneve_tlv_option_0);
1227 if (!curr_fc)
1228 return -EINVAL;
1229
1230 HWS_CALC_HDR_SRC(fc, misc_parameters_3.geneve_tlv_option_0_data);
1231 }
1232
1233 if (HWS_IS_FLD_SET(match_param, misc_parameters_3.gtpu_teid)) {
1234 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_GTPU;
1235
1236 if (!(caps->flex_protocols & MLX5_FLEX_PARSER_GTPU_TEID_ENABLED)) {
1237 mlx5hws_err(cd->ctx, "Unsupported GTPU TEID flex parser\n");
1238 return -EOPNOTSUPP;
1239 }
1240
1241 fc = &cd->fc[MLX5HWS_DEFINER_FNAME_GTP_TEID];
1242 fc->tag_set = &hws_definer_generic_set;
1243 fc->bit_mask = __mlx5_mask(header_gtp, teid);
1244 fc->byte_off = caps->format_select_gtpu_dw_1 * DW_SIZE;
1245 HWS_CALC_HDR_SRC(fc, misc_parameters_3.gtpu_teid);
1246 }
1247
1248 if (HWS_IS_FLD_SET(match_param, misc_parameters_3.gtpu_msg_type)) {
1249 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_GTPU;
1250
1251 if (!(caps->flex_protocols & MLX5_FLEX_PARSER_GTPU_ENABLED)) {
1252 mlx5hws_err(cd->ctx, "Unsupported GTPU flex parser\n");
1253 return -EOPNOTSUPP;
1254 }
1255
1256 fc = &cd->fc[MLX5HWS_DEFINER_FNAME_GTP_MSG_TYPE];
1257 fc->tag_set = &hws_definer_generic_set;
1258 fc->bit_mask = __mlx5_mask(header_gtp, msg_type);
1259 fc->bit_off = __mlx5_dw_bit_off(header_gtp, msg_type);
1260 fc->byte_off = caps->format_select_gtpu_dw_0 * DW_SIZE;
1261 HWS_CALC_HDR_SRC(fc, misc_parameters_3.gtpu_msg_type);
1262 }
1263
1264 if (HWS_IS_FLD_SET(match_param, misc_parameters_3.gtpu_msg_flags)) {
1265 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_GTPU;
1266
1267 if (!(caps->flex_protocols & MLX5_FLEX_PARSER_GTPU_ENABLED)) {
1268 mlx5hws_err(cd->ctx, "Unsupported GTPU flex parser\n");
1269 return -EOPNOTSUPP;
1270 }
1271
1272 fc = &cd->fc[MLX5HWS_DEFINER_FNAME_GTP_MSG_TYPE];
1273 fc->tag_set = &hws_definer_generic_set;
1274 fc->bit_mask = __mlx5_mask(header_gtp, msg_flags);
1275 fc->bit_off = __mlx5_dw_bit_off(header_gtp, msg_flags);
1276 fc->byte_off = caps->format_select_gtpu_dw_0 * DW_SIZE;
1277 HWS_CALC_HDR_SRC(fc, misc_parameters_3.gtpu_msg_flags);
1278 }
1279
1280 if (HWS_IS_FLD_SET(match_param, misc_parameters_3.gtpu_dw_2)) {
1281 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_GTPU;
1282
1283 if (!(caps->flex_protocols & MLX5_FLEX_PARSER_GTPU_DW_2_ENABLED)) {
1284 mlx5hws_err(cd->ctx, "Unsupported GTPU DW2 flex parser\n");
1285 return -EOPNOTSUPP;
1286 }
1287
1288 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_GTPU_DW2];
1289 curr_fc->tag_set = &hws_definer_generic_set;
1290 curr_fc->bit_mask = -1;
1291 curr_fc->byte_off = caps->format_select_gtpu_dw_2 * DW_SIZE;
1292 HWS_CALC_HDR_SRC(fc, misc_parameters_3.gtpu_dw_2);
1293 }
1294
1295 if (HWS_IS_FLD_SET(match_param, misc_parameters_3.gtpu_first_ext_dw_0)) {
1296 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_GTPU;
1297
1298 if (!(caps->flex_protocols & MLX5_FLEX_PARSER_GTPU_FIRST_EXT_DW_0_ENABLED)) {
1299 mlx5hws_err(cd->ctx, "Unsupported GTPU first EXT DW0 flex parser\n");
1300 return -EOPNOTSUPP;
1301 }
1302
1303 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_GTPU_FIRST_EXT_DW0];
1304 curr_fc->tag_set = &hws_definer_generic_set;
1305 curr_fc->bit_mask = -1;
1306 curr_fc->byte_off = caps->format_select_gtpu_ext_dw_0 * DW_SIZE;
1307 HWS_CALC_HDR_SRC(fc, misc_parameters_3.gtpu_first_ext_dw_0);
1308 }
1309
1310 if (HWS_IS_FLD_SET(match_param, misc_parameters_3.gtpu_dw_0)) {
1311 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_GTPU;
1312
1313 if (!(caps->flex_protocols & MLX5_FLEX_PARSER_GTPU_DW_0_ENABLED)) {
1314 mlx5hws_err(cd->ctx, "Unsupported GTPU DW0 flex parser\n");
1315 return -EOPNOTSUPP;
1316 }
1317
1318 curr_fc = &fc[MLX5HWS_DEFINER_FNAME_GTPU_DW0];
1319 curr_fc->tag_set = &hws_definer_generic_set;
1320 curr_fc->bit_mask = -1;
1321 curr_fc->byte_off = caps->format_select_gtpu_dw_0 * DW_SIZE;
1322 HWS_CALC_HDR_SRC(fc, misc_parameters_3.gtpu_dw_0);
1323 }
1324
1325 return 0;
1326 }
1327
1328 static int
hws_definer_conv_misc4(struct mlx5hws_definer_conv_data * cd,u32 * match_param)1329 hws_definer_conv_misc4(struct mlx5hws_definer_conv_data *cd,
1330 u32 *match_param)
1331 {
1332 bool parser_is_used[HWS_NUM_OF_FLEX_PARSERS] = {};
1333 struct mlx5hws_definer_fc *fc;
1334 u32 id, value;
1335
1336 if (HWS_IS_FLD_SET_SZ(match_param, misc_parameters_4.reserved_at_100, 0x100)) {
1337 mlx5hws_err(cd->ctx, "Unsupported misc4 parameters set\n");
1338 return -EINVAL;
1339 }
1340
1341 id = HWS_GET_MATCH_PARAM(match_param, misc_parameters_4.prog_sample_field_id_0);
1342 value = HWS_GET_MATCH_PARAM(match_param, misc_parameters_4.prog_sample_field_value_0);
1343 fc = hws_definer_misc4_fields_handler(cd, parser_is_used, id, value);
1344 if (!fc)
1345 return -EINVAL;
1346
1347 HWS_CALC_HDR_SRC(fc, misc_parameters_4.prog_sample_field_value_0);
1348
1349 id = HWS_GET_MATCH_PARAM(match_param, misc_parameters_4.prog_sample_field_id_1);
1350 value = HWS_GET_MATCH_PARAM(match_param, misc_parameters_4.prog_sample_field_value_1);
1351 fc = hws_definer_misc4_fields_handler(cd, parser_is_used, id, value);
1352 if (!fc)
1353 return -EINVAL;
1354
1355 HWS_CALC_HDR_SRC(fc, misc_parameters_4.prog_sample_field_value_1);
1356
1357 id = HWS_GET_MATCH_PARAM(match_param, misc_parameters_4.prog_sample_field_id_2);
1358 value = HWS_GET_MATCH_PARAM(match_param, misc_parameters_4.prog_sample_field_value_2);
1359 fc = hws_definer_misc4_fields_handler(cd, parser_is_used, id, value);
1360 if (!fc)
1361 return -EINVAL;
1362
1363 HWS_CALC_HDR_SRC(fc, misc_parameters_4.prog_sample_field_value_2);
1364
1365 id = HWS_GET_MATCH_PARAM(match_param, misc_parameters_4.prog_sample_field_id_3);
1366 value = HWS_GET_MATCH_PARAM(match_param, misc_parameters_4.prog_sample_field_value_3);
1367 fc = hws_definer_misc4_fields_handler(cd, parser_is_used, id, value);
1368 if (!fc)
1369 return -EINVAL;
1370
1371 HWS_CALC_HDR_SRC(fc, misc_parameters_4.prog_sample_field_value_3);
1372
1373 return 0;
1374 }
1375
1376 static int
hws_definer_conv_misc5(struct mlx5hws_definer_conv_data * cd,u32 * match_param)1377 hws_definer_conv_misc5(struct mlx5hws_definer_conv_data *cd,
1378 u32 *match_param)
1379 {
1380 struct mlx5hws_definer_fc *fc = cd->fc;
1381
1382 if (HWS_IS_FLD_SET(match_param, misc_parameters_5.macsec_tag_0) ||
1383 HWS_IS_FLD_SET(match_param, misc_parameters_5.macsec_tag_1) ||
1384 HWS_IS_FLD_SET(match_param, misc_parameters_5.macsec_tag_2) ||
1385 HWS_IS_FLD_SET(match_param, misc_parameters_5.macsec_tag_3) ||
1386 HWS_IS_FLD_SET_SZ(match_param, misc_parameters_5.reserved_at_100, 0x100)) {
1387 mlx5hws_err(cd->ctx, "Unsupported misc5 parameters set\n");
1388 return -EINVAL;
1389 }
1390
1391 if (HWS_IS_FLD_SET(match_param, misc_parameters_5.tunnel_header_0)) {
1392 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_HEADER_0_1;
1393 HWS_SET_HDR(fc, match_param, TNL_HDR_0,
1394 misc_parameters_5.tunnel_header_0, tunnel_header.tunnel_header_0);
1395 }
1396
1397 if (HWS_IS_FLD_SET(match_param, misc_parameters_5.tunnel_header_1)) {
1398 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_HEADER_0_1;
1399 HWS_SET_HDR(fc, match_param, TNL_HDR_1,
1400 misc_parameters_5.tunnel_header_1, tunnel_header.tunnel_header_1);
1401 }
1402
1403 if (HWS_IS_FLD_SET(match_param, misc_parameters_5.tunnel_header_2)) {
1404 cd->match_flags |= MLX5HWS_DEFINER_MATCH_FLAG_TNL_HEADER_2;
1405 HWS_SET_HDR(fc, match_param, TNL_HDR_2,
1406 misc_parameters_5.tunnel_header_2, tunnel_header.tunnel_header_2);
1407 }
1408
1409 HWS_SET_HDR(fc, match_param, TNL_HDR_3,
1410 misc_parameters_5.tunnel_header_3, tunnel_header.tunnel_header_3);
1411
1412 return 0;
1413 }
1414
hws_definer_get_fc_size(struct mlx5hws_definer_fc * fc)1415 static int hws_definer_get_fc_size(struct mlx5hws_definer_fc *fc)
1416 {
1417 u32 fc_sz = 0;
1418 int i;
1419
1420 /* For empty matcher, ZERO_SIZE_PTR is returned */
1421 if (fc == ZERO_SIZE_PTR)
1422 return 0;
1423
1424 for (i = 0; i < MLX5HWS_DEFINER_FNAME_MAX; i++)
1425 if (fc[i].tag_set)
1426 fc_sz++;
1427 return fc_sz;
1428 }
1429
1430 static struct mlx5hws_definer_fc *
hws_definer_alloc_compressed_fc(struct mlx5hws_definer_fc * fc)1431 hws_definer_alloc_compressed_fc(struct mlx5hws_definer_fc *fc)
1432 {
1433 struct mlx5hws_definer_fc *compressed_fc = NULL;
1434 u32 definer_size = hws_definer_get_fc_size(fc);
1435 u32 fc_sz = 0;
1436 int i;
1437
1438 compressed_fc = kcalloc(definer_size, sizeof(*compressed_fc), GFP_KERNEL);
1439 if (!compressed_fc)
1440 return NULL;
1441
1442 /* For empty matcher, ZERO_SIZE_PTR is returned */
1443 if (!definer_size)
1444 return compressed_fc;
1445
1446 for (i = 0, fc_sz = 0; i < MLX5HWS_DEFINER_FNAME_MAX; i++) {
1447 if (!fc[i].tag_set)
1448 continue;
1449
1450 fc[i].fname = i;
1451 memcpy(&compressed_fc[fc_sz++], &fc[i], sizeof(*compressed_fc));
1452 }
1453
1454 return compressed_fc;
1455 }
1456
1457 static void
hws_definer_set_hl(u8 * hl,struct mlx5hws_definer_fc * fc)1458 hws_definer_set_hl(u8 *hl, struct mlx5hws_definer_fc *fc)
1459 {
1460 int i;
1461
1462 /* nothing to do for empty matcher */
1463 if (fc == ZERO_SIZE_PTR)
1464 return;
1465
1466 for (i = 0; i < MLX5HWS_DEFINER_FNAME_MAX; i++) {
1467 if (!fc[i].tag_set)
1468 continue;
1469
1470 HWS_SET32(hl, -1, fc[i].byte_off, fc[i].bit_off, fc[i].bit_mask);
1471 }
1472 }
1473
1474 static struct mlx5hws_definer_fc *
hws_definer_alloc_fc(struct mlx5hws_context * ctx,size_t len)1475 hws_definer_alloc_fc(struct mlx5hws_context *ctx,
1476 size_t len)
1477 {
1478 struct mlx5hws_definer_fc *fc;
1479 int i;
1480
1481 fc = kcalloc(len, sizeof(*fc), GFP_KERNEL);
1482 if (!fc)
1483 return NULL;
1484
1485 for (i = 0; i < len; i++)
1486 fc[i].ctx = ctx;
1487
1488 return fc;
1489 }
1490
1491 static int
hws_definer_conv_match_params_to_hl(struct mlx5hws_context * ctx,struct mlx5hws_match_template * mt,u8 * hl)1492 hws_definer_conv_match_params_to_hl(struct mlx5hws_context *ctx,
1493 struct mlx5hws_match_template *mt,
1494 u8 *hl)
1495 {
1496 struct mlx5hws_definer_conv_data cd = {0};
1497 struct mlx5hws_definer_fc *fc;
1498 int ret;
1499
1500 fc = hws_definer_alloc_fc(ctx, MLX5HWS_DEFINER_FNAME_MAX);
1501 if (!fc)
1502 return -ENOMEM;
1503
1504 cd.fc = fc;
1505 cd.ctx = ctx;
1506
1507 if (mt->match_criteria_enable & MLX5HWS_DEFINER_MATCH_CRITERIA_MISC6) {
1508 mlx5hws_err(ctx, "Unsupported match_criteria_enable provided\n");
1509 ret = -EOPNOTSUPP;
1510 goto err_free_fc;
1511 }
1512
1513 if (mt->match_criteria_enable & MLX5HWS_DEFINER_MATCH_CRITERIA_OUTER) {
1514 ret = hws_definer_conv_outer(&cd, mt->match_param);
1515 if (ret)
1516 goto err_free_fc;
1517 }
1518
1519 if (mt->match_criteria_enable & MLX5HWS_DEFINER_MATCH_CRITERIA_INNER) {
1520 ret = hws_definer_conv_inner(&cd, mt->match_param);
1521 if (ret)
1522 goto err_free_fc;
1523 }
1524
1525 if (mt->match_criteria_enable & MLX5HWS_DEFINER_MATCH_CRITERIA_MISC) {
1526 ret = hws_definer_conv_misc(&cd, mt->match_param);
1527 if (ret)
1528 goto err_free_fc;
1529 }
1530
1531 if (mt->match_criteria_enable & MLX5HWS_DEFINER_MATCH_CRITERIA_MISC2) {
1532 ret = hws_definer_conv_misc2(&cd, mt->match_param);
1533 if (ret)
1534 goto err_free_fc;
1535 }
1536
1537 if (mt->match_criteria_enable & MLX5HWS_DEFINER_MATCH_CRITERIA_MISC3) {
1538 ret = hws_definer_conv_misc3(&cd, mt->match_param);
1539 if (ret)
1540 goto err_free_fc;
1541 }
1542
1543 if (mt->match_criteria_enable & MLX5HWS_DEFINER_MATCH_CRITERIA_MISC4) {
1544 ret = hws_definer_conv_misc4(&cd, mt->match_param);
1545 if (ret)
1546 goto err_free_fc;
1547 }
1548
1549 if (mt->match_criteria_enable & MLX5HWS_DEFINER_MATCH_CRITERIA_MISC5) {
1550 ret = hws_definer_conv_misc5(&cd, mt->match_param);
1551 if (ret)
1552 goto err_free_fc;
1553 }
1554
1555 /* Check there is no conflicted fields set together */
1556 ret = hws_definer_check_match_flags(&cd);
1557 if (ret)
1558 goto err_free_fc;
1559
1560 /* Allocate fc array on mt */
1561 mt->fc = hws_definer_alloc_compressed_fc(fc);
1562 if (!mt->fc) {
1563 mlx5hws_err(ctx,
1564 "Convert match params: failed to set field copy to match template\n");
1565 ret = -ENOMEM;
1566 goto err_free_fc;
1567 }
1568 mt->fc_sz = hws_definer_get_fc_size(fc);
1569
1570 /* Fill in headers layout */
1571 hws_definer_set_hl(hl, fc);
1572
1573 kfree(fc);
1574 return 0;
1575
1576 err_free_fc:
1577 kfree(fc);
1578 return ret;
1579 }
1580
1581 struct mlx5hws_definer_fc *
mlx5hws_definer_conv_match_params_to_compressed_fc(struct mlx5hws_context * ctx,u8 match_criteria_enable,u32 * match_param,int * fc_sz)1582 mlx5hws_definer_conv_match_params_to_compressed_fc(struct mlx5hws_context *ctx,
1583 u8 match_criteria_enable,
1584 u32 *match_param,
1585 int *fc_sz)
1586 {
1587 struct mlx5hws_definer_fc *compressed_fc = NULL;
1588 struct mlx5hws_definer_conv_data cd = {0};
1589 struct mlx5hws_definer_fc *fc;
1590 int ret;
1591
1592 fc = hws_definer_alloc_fc(ctx, MLX5HWS_DEFINER_FNAME_MAX);
1593 if (!fc)
1594 return NULL;
1595
1596 cd.fc = fc;
1597 cd.ctx = ctx;
1598
1599 if (match_criteria_enable & MLX5HWS_DEFINER_MATCH_CRITERIA_OUTER) {
1600 ret = hws_definer_conv_outer(&cd, match_param);
1601 if (ret)
1602 goto err_free_fc;
1603 }
1604
1605 if (match_criteria_enable & MLX5HWS_DEFINER_MATCH_CRITERIA_INNER) {
1606 ret = hws_definer_conv_inner(&cd, match_param);
1607 if (ret)
1608 goto err_free_fc;
1609 }
1610
1611 if (match_criteria_enable & MLX5HWS_DEFINER_MATCH_CRITERIA_MISC) {
1612 ret = hws_definer_conv_misc(&cd, match_param);
1613 if (ret)
1614 goto err_free_fc;
1615 }
1616
1617 if (match_criteria_enable & MLX5HWS_DEFINER_MATCH_CRITERIA_MISC2) {
1618 ret = hws_definer_conv_misc2(&cd, match_param);
1619 if (ret)
1620 goto err_free_fc;
1621 }
1622
1623 if (match_criteria_enable & MLX5HWS_DEFINER_MATCH_CRITERIA_MISC3) {
1624 ret = hws_definer_conv_misc3(&cd, match_param);
1625 if (ret)
1626 goto err_free_fc;
1627 }
1628
1629 if (match_criteria_enable & MLX5HWS_DEFINER_MATCH_CRITERIA_MISC4) {
1630 ret = hws_definer_conv_misc4(&cd, match_param);
1631 if (ret)
1632 goto err_free_fc;
1633 }
1634
1635 if (match_criteria_enable & MLX5HWS_DEFINER_MATCH_CRITERIA_MISC5) {
1636 ret = hws_definer_conv_misc5(&cd, match_param);
1637 if (ret)
1638 goto err_free_fc;
1639 }
1640
1641 /* Allocate fc array on mt */
1642 compressed_fc = hws_definer_alloc_compressed_fc(fc);
1643 if (!compressed_fc) {
1644 mlx5hws_err(ctx,
1645 "Convert to compressed fc: failed to set field copy to match template\n");
1646 goto err_free_fc;
1647 }
1648 *fc_sz = hws_definer_get_fc_size(fc);
1649
1650 err_free_fc:
1651 kfree(fc);
1652 return compressed_fc;
1653 }
1654
1655 static int
hws_definer_find_byte_in_tag(struct mlx5hws_definer * definer,u32 hl_byte_off,u32 * tag_byte_off)1656 hws_definer_find_byte_in_tag(struct mlx5hws_definer *definer,
1657 u32 hl_byte_off,
1658 u32 *tag_byte_off)
1659 {
1660 int i, dw_to_scan;
1661 u8 byte_offset;
1662
1663 /* Avoid accessing unused DW selectors */
1664 dw_to_scan = mlx5hws_definer_is_jumbo(definer) ?
1665 DW_SELECTORS : DW_SELECTORS_MATCH;
1666
1667 /* Add offset since each DW covers multiple BYTEs */
1668 byte_offset = hl_byte_off % DW_SIZE;
1669 for (i = 0; i < dw_to_scan; i++) {
1670 if (definer->dw_selector[i] == hl_byte_off / DW_SIZE) {
1671 *tag_byte_off = byte_offset + DW_SIZE * (DW_SELECTORS - i - 1);
1672 return 0;
1673 }
1674 }
1675
1676 /* Add offset to skip DWs in definer */
1677 byte_offset = DW_SIZE * DW_SELECTORS;
1678 /* Iterate in reverse since the code uses bytes from 7 -> 0 */
1679 for (i = BYTE_SELECTORS; i-- > 0 ;) {
1680 if (definer->byte_selector[i] == hl_byte_off) {
1681 *tag_byte_off = byte_offset + (BYTE_SELECTORS - i - 1);
1682 return 0;
1683 }
1684 }
1685
1686 return -EINVAL;
1687 }
1688
1689 static int
hws_definer_fc_bind(struct mlx5hws_definer * definer,struct mlx5hws_definer_fc * fc,u32 fc_sz)1690 hws_definer_fc_bind(struct mlx5hws_definer *definer,
1691 struct mlx5hws_definer_fc *fc,
1692 u32 fc_sz)
1693 {
1694 u32 tag_offset = 0;
1695 int ret, byte_diff;
1696 u32 i;
1697
1698 for (i = 0; i < fc_sz; i++) {
1699 /* Map header layout byte offset to byte offset in tag */
1700 ret = hws_definer_find_byte_in_tag(definer, fc->byte_off, &tag_offset);
1701 if (ret)
1702 return ret;
1703
1704 /* Move setter based on the location in the definer */
1705 byte_diff = fc->byte_off % DW_SIZE - tag_offset % DW_SIZE;
1706 fc->bit_off = fc->bit_off + byte_diff * BITS_IN_BYTE;
1707
1708 /* Update offset in headers layout to offset in tag */
1709 fc->byte_off = tag_offset;
1710 fc++;
1711 }
1712
1713 return 0;
1714 }
1715
1716 static bool
hws_definer_best_hl_fit_recu(struct mlx5hws_definer_sel_ctrl * ctrl,u32 cur_dw,u32 * data)1717 hws_definer_best_hl_fit_recu(struct mlx5hws_definer_sel_ctrl *ctrl,
1718 u32 cur_dw,
1719 u32 *data)
1720 {
1721 u8 bytes_set;
1722 int byte_idx;
1723 bool ret;
1724 int i;
1725
1726 /* Reached end, nothing left to do */
1727 if (cur_dw == MLX5_ST_SZ_DW(definer_hl))
1728 return true;
1729
1730 /* No data set, can skip to next DW */
1731 while (!*data) {
1732 cur_dw++;
1733 data++;
1734
1735 /* Reached end, nothing left to do */
1736 if (cur_dw == MLX5_ST_SZ_DW(definer_hl))
1737 return true;
1738 }
1739
1740 /* Used all DW selectors and Byte selectors, no possible solution */
1741 if (ctrl->allowed_full_dw == ctrl->used_full_dw &&
1742 ctrl->allowed_lim_dw == ctrl->used_lim_dw &&
1743 ctrl->allowed_bytes == ctrl->used_bytes)
1744 return false;
1745
1746 /* Try to use limited DW selectors */
1747 if (ctrl->allowed_lim_dw > ctrl->used_lim_dw && cur_dw < 64) {
1748 ctrl->lim_dw_selector[ctrl->used_lim_dw++] = cur_dw;
1749
1750 ret = hws_definer_best_hl_fit_recu(ctrl, cur_dw + 1, data + 1);
1751 if (ret)
1752 return ret;
1753
1754 ctrl->lim_dw_selector[--ctrl->used_lim_dw] = 0;
1755 }
1756
1757 /* Try to use DW selectors */
1758 if (ctrl->allowed_full_dw > ctrl->used_full_dw) {
1759 ctrl->full_dw_selector[ctrl->used_full_dw++] = cur_dw;
1760
1761 ret = hws_definer_best_hl_fit_recu(ctrl, cur_dw + 1, data + 1);
1762 if (ret)
1763 return ret;
1764
1765 ctrl->full_dw_selector[--ctrl->used_full_dw] = 0;
1766 }
1767
1768 /* No byte selector for offset bigger than 255 */
1769 if (cur_dw * DW_SIZE > 255)
1770 return false;
1771
1772 bytes_set = !!(0x000000ff & *data) +
1773 !!(0x0000ff00 & *data) +
1774 !!(0x00ff0000 & *data) +
1775 !!(0xff000000 & *data);
1776
1777 /* Check if there are enough byte selectors left */
1778 if (bytes_set + ctrl->used_bytes > ctrl->allowed_bytes)
1779 return false;
1780
1781 /* Try to use Byte selectors */
1782 for (i = 0; i < DW_SIZE; i++)
1783 if ((0xff000000 >> (i * BITS_IN_BYTE)) & be32_to_cpu((__force __be32)*data)) {
1784 /* Use byte selectors high to low */
1785 byte_idx = ctrl->allowed_bytes - ctrl->used_bytes - 1;
1786 ctrl->byte_selector[byte_idx] = cur_dw * DW_SIZE + i;
1787 ctrl->used_bytes++;
1788 }
1789
1790 ret = hws_definer_best_hl_fit_recu(ctrl, cur_dw + 1, data + 1);
1791 if (ret)
1792 return ret;
1793
1794 for (i = 0; i < DW_SIZE; i++)
1795 if ((0xff << (i * BITS_IN_BYTE)) & be32_to_cpu((__force __be32)*data)) {
1796 ctrl->used_bytes--;
1797 byte_idx = ctrl->allowed_bytes - ctrl->used_bytes - 1;
1798 ctrl->byte_selector[byte_idx] = 0;
1799 }
1800
1801 return false;
1802 }
1803
1804 static void
hws_definer_copy_sel_ctrl(struct mlx5hws_definer_sel_ctrl * ctrl,struct mlx5hws_definer * definer)1805 hws_definer_copy_sel_ctrl(struct mlx5hws_definer_sel_ctrl *ctrl,
1806 struct mlx5hws_definer *definer)
1807 {
1808 memcpy(definer->byte_selector, ctrl->byte_selector, ctrl->allowed_bytes);
1809 memcpy(definer->dw_selector, ctrl->full_dw_selector, ctrl->allowed_full_dw);
1810 memcpy(definer->dw_selector + ctrl->allowed_full_dw,
1811 ctrl->lim_dw_selector, ctrl->allowed_lim_dw);
1812 }
1813
1814 static int
hws_definer_find_best_match_fit(struct mlx5hws_context * ctx,struct mlx5hws_definer * definer,u8 * hl)1815 hws_definer_find_best_match_fit(struct mlx5hws_context *ctx,
1816 struct mlx5hws_definer *definer,
1817 u8 *hl)
1818 {
1819 struct mlx5hws_definer_sel_ctrl ctrl = {0};
1820 bool found;
1821
1822 /* Try to create a match definer */
1823 ctrl.allowed_full_dw = DW_SELECTORS_MATCH;
1824 ctrl.allowed_lim_dw = 0;
1825 ctrl.allowed_bytes = BYTE_SELECTORS;
1826
1827 found = hws_definer_best_hl_fit_recu(&ctrl, 0, (u32 *)hl);
1828 if (found) {
1829 hws_definer_copy_sel_ctrl(&ctrl, definer);
1830 definer->type = MLX5HWS_DEFINER_TYPE_MATCH;
1831 return 0;
1832 }
1833
1834 /* Try to create a full/limited jumbo definer */
1835 ctrl.allowed_full_dw = ctx->caps->full_dw_jumbo_support ? DW_SELECTORS :
1836 DW_SELECTORS_MATCH;
1837 ctrl.allowed_lim_dw = ctx->caps->full_dw_jumbo_support ? 0 :
1838 DW_SELECTORS_LIMITED;
1839 ctrl.allowed_bytes = BYTE_SELECTORS;
1840
1841 found = hws_definer_best_hl_fit_recu(&ctrl, 0, (u32 *)hl);
1842 if (found) {
1843 hws_definer_copy_sel_ctrl(&ctrl, definer);
1844 definer->type = MLX5HWS_DEFINER_TYPE_JUMBO;
1845 return 0;
1846 }
1847
1848 return -E2BIG;
1849 }
1850
1851 static void
hws_definer_create_tag_mask(u32 * match_param,struct mlx5hws_definer_fc * fc,u32 fc_sz,u8 * tag)1852 hws_definer_create_tag_mask(u32 *match_param,
1853 struct mlx5hws_definer_fc *fc,
1854 u32 fc_sz,
1855 u8 *tag)
1856 {
1857 u32 i;
1858
1859 for (i = 0; i < fc_sz; i++) {
1860 if (fc->tag_mask_set)
1861 fc->tag_mask_set(fc, match_param, tag);
1862 else
1863 fc->tag_set(fc, match_param, tag);
1864 fc++;
1865 }
1866 }
1867
mlx5hws_definer_create_tag(u32 * match_param,struct mlx5hws_definer_fc * fc,u32 fc_sz,u8 * tag)1868 void mlx5hws_definer_create_tag(u32 *match_param,
1869 struct mlx5hws_definer_fc *fc,
1870 u32 fc_sz,
1871 u8 *tag)
1872 {
1873 u32 i;
1874
1875 for (i = 0; i < fc_sz; i++) {
1876 fc->tag_set(fc, match_param, tag);
1877 fc++;
1878 }
1879 }
1880
mlx5hws_definer_get_id(struct mlx5hws_definer * definer)1881 int mlx5hws_definer_get_id(struct mlx5hws_definer *definer)
1882 {
1883 return definer->obj_id;
1884 }
1885
mlx5hws_definer_compare(struct mlx5hws_definer * definer_a,struct mlx5hws_definer * definer_b)1886 int mlx5hws_definer_compare(struct mlx5hws_definer *definer_a,
1887 struct mlx5hws_definer *definer_b)
1888 {
1889 int i;
1890
1891 /* Future: Optimize by comparing selectors with valid mask only */
1892 for (i = 0; i < BYTE_SELECTORS; i++)
1893 if (definer_a->byte_selector[i] != definer_b->byte_selector[i])
1894 return 1;
1895
1896 for (i = 0; i < DW_SELECTORS; i++)
1897 if (definer_a->dw_selector[i] != definer_b->dw_selector[i])
1898 return 1;
1899
1900 for (i = 0; i < MLX5HWS_JUMBO_TAG_SZ; i++)
1901 if (definer_a->mask.jumbo[i] != definer_b->mask.jumbo[i])
1902 return 1;
1903
1904 return 0;
1905 }
1906
1907 int
mlx5hws_definer_calc_layout(struct mlx5hws_context * ctx,struct mlx5hws_match_template * mt,struct mlx5hws_definer * match_definer)1908 mlx5hws_definer_calc_layout(struct mlx5hws_context *ctx,
1909 struct mlx5hws_match_template *mt,
1910 struct mlx5hws_definer *match_definer)
1911 {
1912 u8 *match_hl;
1913 int ret;
1914
1915 /* Union header-layout (hl) is used for creating a single definer
1916 * field layout used with different bitmasks for hash and match.
1917 */
1918 match_hl = kzalloc(MLX5_ST_SZ_BYTES(definer_hl), GFP_KERNEL);
1919 if (!match_hl)
1920 return -ENOMEM;
1921
1922 /* Convert all mt items to header layout (hl)
1923 * and allocate the match and range field copy array (fc & fcr).
1924 */
1925 ret = hws_definer_conv_match_params_to_hl(ctx, mt, match_hl);
1926 if (ret) {
1927 mlx5hws_err(ctx, "Failed to convert items to header layout\n");
1928 goto free_match_hl;
1929 }
1930
1931 /* Find the match definer layout for header layout match union */
1932 ret = hws_definer_find_best_match_fit(ctx, match_definer, match_hl);
1933 if (ret) {
1934 if (ret == -E2BIG)
1935 mlx5hws_dbg(ctx,
1936 "Failed to create match definer from header layout - E2BIG\n");
1937 else
1938 mlx5hws_err(ctx,
1939 "Failed to create match definer from header layout (%d)\n",
1940 ret);
1941 goto free_fc;
1942 }
1943
1944 kfree(match_hl);
1945 return 0;
1946
1947 free_fc:
1948 kfree(mt->fc);
1949 free_match_hl:
1950 kfree(match_hl);
1951 return ret;
1952 }
1953
mlx5hws_definer_init_cache(struct mlx5hws_definer_cache ** cache)1954 int mlx5hws_definer_init_cache(struct mlx5hws_definer_cache **cache)
1955 {
1956 struct mlx5hws_definer_cache *new_cache;
1957
1958 new_cache = kzalloc(sizeof(*new_cache), GFP_KERNEL);
1959 if (!new_cache)
1960 return -ENOMEM;
1961
1962 INIT_LIST_HEAD(&new_cache->list_head);
1963 *cache = new_cache;
1964
1965 return 0;
1966 }
1967
mlx5hws_definer_uninit_cache(struct mlx5hws_definer_cache * cache)1968 void mlx5hws_definer_uninit_cache(struct mlx5hws_definer_cache *cache)
1969 {
1970 kfree(cache);
1971 }
1972
mlx5hws_definer_get_obj(struct mlx5hws_context * ctx,struct mlx5hws_definer * definer)1973 int mlx5hws_definer_get_obj(struct mlx5hws_context *ctx,
1974 struct mlx5hws_definer *definer)
1975 {
1976 struct mlx5hws_definer_cache *cache = ctx->definer_cache;
1977 struct mlx5hws_cmd_definer_create_attr def_attr = {0};
1978 struct mlx5hws_definer_cache_item *cached_definer;
1979 u32 obj_id;
1980 int ret;
1981
1982 /* Search definer cache for requested definer */
1983 list_for_each_entry(cached_definer, &cache->list_head, list_node) {
1984 if (mlx5hws_definer_compare(&cached_definer->definer, definer))
1985 continue;
1986
1987 /* Reuse definer and set LRU (move to be first in the list) */
1988 list_del_init(&cached_definer->list_node);
1989 list_add(&cached_definer->list_node, &cache->list_head);
1990 cached_definer->refcount++;
1991 return cached_definer->definer.obj_id;
1992 }
1993
1994 /* Allocate and create definer based on the bitmask tag */
1995 def_attr.match_mask = definer->mask.jumbo;
1996 def_attr.dw_selector = definer->dw_selector;
1997 def_attr.byte_selector = definer->byte_selector;
1998
1999 ret = mlx5hws_cmd_definer_create(ctx->mdev, &def_attr, &obj_id);
2000 if (ret)
2001 return -1;
2002
2003 cached_definer = kzalloc(sizeof(*cached_definer), GFP_KERNEL);
2004 if (!cached_definer)
2005 goto free_definer_obj;
2006
2007 memcpy(&cached_definer->definer, definer, sizeof(*definer));
2008 cached_definer->definer.obj_id = obj_id;
2009 cached_definer->refcount = 1;
2010 list_add(&cached_definer->list_node, &cache->list_head);
2011
2012 return obj_id;
2013
2014 free_definer_obj:
2015 mlx5hws_cmd_definer_destroy(ctx->mdev, obj_id);
2016 return -1;
2017 }
2018
2019 static void
hws_definer_put_obj(struct mlx5hws_context * ctx,u32 obj_id)2020 hws_definer_put_obj(struct mlx5hws_context *ctx, u32 obj_id)
2021 {
2022 struct mlx5hws_definer_cache_item *cached_definer;
2023
2024 list_for_each_entry(cached_definer, &ctx->definer_cache->list_head, list_node) {
2025 if (cached_definer->definer.obj_id != obj_id)
2026 continue;
2027
2028 /* Object found */
2029 if (--cached_definer->refcount)
2030 return;
2031
2032 list_del_init(&cached_definer->list_node);
2033 mlx5hws_cmd_definer_destroy(ctx->mdev, cached_definer->definer.obj_id);
2034 kfree(cached_definer);
2035 return;
2036 }
2037
2038 /* Programming error, object must be part of cache */
2039 pr_warn("HWS: failed putting definer object\n");
2040 }
2041
2042 static struct mlx5hws_definer *
hws_definer_alloc(struct mlx5hws_context * ctx,struct mlx5hws_definer_fc * fc,int fc_sz,u32 * match_param,struct mlx5hws_definer * layout,bool bind_fc)2043 hws_definer_alloc(struct mlx5hws_context *ctx,
2044 struct mlx5hws_definer_fc *fc,
2045 int fc_sz,
2046 u32 *match_param,
2047 struct mlx5hws_definer *layout,
2048 bool bind_fc)
2049 {
2050 struct mlx5hws_definer *definer;
2051 int ret;
2052
2053 definer = kmemdup(layout, sizeof(*definer), GFP_KERNEL);
2054 if (!definer)
2055 return NULL;
2056
2057 /* Align field copy array based on given layout */
2058 if (bind_fc) {
2059 ret = hws_definer_fc_bind(definer, fc, fc_sz);
2060 if (ret) {
2061 mlx5hws_err(ctx, "Failed to bind field copy to definer\n");
2062 goto free_definer;
2063 }
2064 }
2065
2066 /* Create the tag mask used for definer creation */
2067 hws_definer_create_tag_mask(match_param, fc, fc_sz, definer->mask.jumbo);
2068
2069 ret = mlx5hws_definer_get_obj(ctx, definer);
2070 if (ret < 0)
2071 goto free_definer;
2072
2073 definer->obj_id = ret;
2074 return definer;
2075
2076 free_definer:
2077 kfree(definer);
2078 return NULL;
2079 }
2080
mlx5hws_definer_free(struct mlx5hws_context * ctx,struct mlx5hws_definer * definer)2081 void mlx5hws_definer_free(struct mlx5hws_context *ctx,
2082 struct mlx5hws_definer *definer)
2083 {
2084 hws_definer_put_obj(ctx, definer->obj_id);
2085 kfree(definer);
2086 }
2087
2088 static int
hws_definer_mt_match_init(struct mlx5hws_context * ctx,struct mlx5hws_match_template * mt,struct mlx5hws_definer * match_layout)2089 hws_definer_mt_match_init(struct mlx5hws_context *ctx,
2090 struct mlx5hws_match_template *mt,
2091 struct mlx5hws_definer *match_layout)
2092 {
2093 /* Create mandatory match definer */
2094 mt->definer = hws_definer_alloc(ctx,
2095 mt->fc,
2096 mt->fc_sz,
2097 mt->match_param,
2098 match_layout,
2099 true);
2100 if (!mt->definer) {
2101 mlx5hws_err(ctx, "Failed to create match definer\n");
2102 return -EINVAL;
2103 }
2104
2105 return 0;
2106 }
2107
2108 static void
hws_definer_mt_match_uninit(struct mlx5hws_context * ctx,struct mlx5hws_match_template * mt)2109 hws_definer_mt_match_uninit(struct mlx5hws_context *ctx,
2110 struct mlx5hws_match_template *mt)
2111 {
2112 mlx5hws_definer_free(ctx, mt->definer);
2113 }
2114
mlx5hws_definer_mt_init(struct mlx5hws_context * ctx,struct mlx5hws_match_template * mt)2115 int mlx5hws_definer_mt_init(struct mlx5hws_context *ctx,
2116 struct mlx5hws_match_template *mt)
2117 {
2118 struct mlx5hws_definer match_layout = {0};
2119 int ret;
2120
2121 ret = mlx5hws_definer_calc_layout(ctx, mt, &match_layout);
2122 if (ret) {
2123 mlx5hws_err(ctx, "Failed to calculate matcher definer layout\n");
2124 return ret;
2125 }
2126
2127 /* Calculate definers needed for exact match */
2128 ret = hws_definer_mt_match_init(ctx, mt, &match_layout);
2129 if (ret) {
2130 mlx5hws_err(ctx, "Failed to init match definers\n");
2131 goto free_fc;
2132 }
2133
2134 return 0;
2135
2136 free_fc:
2137 kfree(mt->fc);
2138 return ret;
2139 }
2140
mlx5hws_definer_mt_uninit(struct mlx5hws_context * ctx,struct mlx5hws_match_template * mt)2141 void mlx5hws_definer_mt_uninit(struct mlx5hws_context *ctx,
2142 struct mlx5hws_match_template *mt)
2143 {
2144 hws_definer_mt_match_uninit(ctx, mt);
2145 kfree(mt->fc);
2146 }
2147