xref: /linux/drivers/net/ethernet/microchip/sparx5/sparx5_tc_flower.c (revision 655614ea2bd3b5774cdb95c7630d8327bf221934)
1 // SPDX-License-Identifier: GPL-2.0+
2 /* Microchip VCAP API
3  *
4  * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.
5  */
6 
7 #include <net/tc_act/tc_gate.h>
8 #include <net/tcp.h>
9 
10 #include "sparx5_tc.h"
11 #include "vcap_api.h"
12 #include "vcap_api_client.h"
13 #include "vcap_tc.h"
14 #include "sparx5_main.h"
15 #include "sparx5_vcap_impl.h"
16 
17 #define SPX5_MAX_RULE_SIZE 13 /* allows X1, X2, X4, X6 and X12 rules */
18 
19 /* Collect keysets and type ids for multiple rules per size */
20 struct sparx5_wildcard_rule {
21 	bool selected;
22 	u8 value;
23 	u8 mask;
24 	enum vcap_keyfield_set keyset;
25 };
26 
27 struct sparx5_multiple_rules {
28 	struct sparx5_wildcard_rule rule[SPX5_MAX_RULE_SIZE];
29 };
30 
31 struct sparx5_tc_flower_template {
32 	struct list_head list; /* for insertion in the list of templates */
33 	int cid; /* chain id */
34 	enum vcap_keyfield_set orig; /* keyset used before the template */
35 	enum vcap_keyfield_set keyset; /* new keyset used by template */
36 	u16 l3_proto; /* protocol specified in the template */
37 };
38 
39 /* SparX-5 VCAP fragment types:
40  * 0 = no fragment, 1 = initial fragment,
41  * 2 = suspicious fragment, 3 = valid follow-up fragment
42  */
43 enum {                   /* key / mask */
44 	FRAG_NOT   = 0x03, /* 0 / 3 */
45 	FRAG_SOME  = 0x11, /* 1 / 1 */
46 	FRAG_FIRST = 0x13, /* 1 / 3 */
47 	FRAG_LATER = 0x33, /* 3 / 3 */
48 	FRAG_INVAL = 0xff, /* invalid */
49 };
50 
51 /* Flower fragment flag to VCAP fragment type mapping */
52 static const u8 sparx5_vcap_frag_map[4][4] = {		  /* is_frag */
53 	{ FRAG_INVAL, FRAG_INVAL, FRAG_INVAL, FRAG_FIRST }, /* 0/0 */
54 	{ FRAG_NOT,   FRAG_NOT,   FRAG_INVAL, FRAG_INVAL }, /* 0/1 */
55 	{ FRAG_INVAL, FRAG_INVAL, FRAG_INVAL, FRAG_INVAL }, /* 1/0 */
56 	{ FRAG_SOME,  FRAG_LATER, FRAG_INVAL, FRAG_FIRST }  /* 1/1 */
57 	/* 0/0	      0/1	  1/0	      1/1 <-- first_frag */
58 };
59 
60 static int
61 sparx5_tc_flower_es0_tpid(struct vcap_tc_flower_parse_usage *st)
62 {
63 	int err = 0;
64 
65 	switch (st->tpid) {
66 	case ETH_P_8021Q:
67 		err = vcap_rule_add_key_u32(st->vrule,
68 					    VCAP_KF_8021Q_TPID,
69 					    SPX5_TPID_SEL_8100, ~0);
70 		break;
71 	case ETH_P_8021AD:
72 		err = vcap_rule_add_key_u32(st->vrule,
73 					    VCAP_KF_8021Q_TPID,
74 					    SPX5_TPID_SEL_88A8, ~0);
75 		break;
76 	default:
77 		NL_SET_ERR_MSG_MOD(st->fco->common.extack,
78 				   "Invalid vlan proto");
79 		err = -EINVAL;
80 		break;
81 	}
82 	return err;
83 }
84 
85 static int
86 sparx5_tc_flower_handler_basic_usage(struct vcap_tc_flower_parse_usage *st)
87 {
88 	struct flow_match_basic mt;
89 	int err = 0;
90 
91 	flow_rule_match_basic(st->frule, &mt);
92 
93 	if (mt.mask->n_proto) {
94 		st->l3_proto = be16_to_cpu(mt.key->n_proto);
95 		if (!sparx5_vcap_is_known_etype(st->admin, st->l3_proto)) {
96 			err = vcap_rule_add_key_u32(st->vrule, VCAP_KF_ETYPE,
97 						    st->l3_proto, ~0);
98 			if (err)
99 				goto out;
100 		} else if (st->l3_proto == ETH_P_IP) {
101 			err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_IP4_IS,
102 						    VCAP_BIT_1);
103 			if (err)
104 				goto out;
105 		} else if (st->l3_proto == ETH_P_IPV6) {
106 			err = vcap_rule_add_key_bit(st->vrule, VCAP_KF_IP4_IS,
107 						    VCAP_BIT_0);
108 			if (err)
109 				goto out;
110 			if (st->admin->vtype == VCAP_TYPE_IS0) {
111 				err = vcap_rule_add_key_bit(st->vrule,
112 							    VCAP_KF_IP_SNAP_IS,
113 							    VCAP_BIT_1);
114 				if (err)
115 					goto out;
116 			}
117 		}
118 	}
119 
120 	if (mt.mask->ip_proto) {
121 		st->l4_proto = mt.key->ip_proto;
122 		if (st->l4_proto == IPPROTO_TCP) {
123 			err = vcap_rule_add_key_bit(st->vrule,
124 						    VCAP_KF_TCP_IS,
125 						    VCAP_BIT_1);
126 			if (err)
127 				goto out;
128 		} else if (st->l4_proto == IPPROTO_UDP) {
129 			err = vcap_rule_add_key_bit(st->vrule,
130 						    VCAP_KF_TCP_IS,
131 						    VCAP_BIT_0);
132 			if (err)
133 				goto out;
134 			if (st->admin->vtype == VCAP_TYPE_IS0) {
135 				err = vcap_rule_add_key_bit(st->vrule,
136 							    VCAP_KF_TCP_UDP_IS,
137 							    VCAP_BIT_1);
138 				if (err)
139 					goto out;
140 			}
141 		} else {
142 			err = vcap_rule_add_key_u32(st->vrule,
143 						    VCAP_KF_L3_IP_PROTO,
144 						    st->l4_proto, ~0);
145 			if (err)
146 				goto out;
147 		}
148 	}
149 
150 	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_BASIC);
151 
152 	return err;
153 
154 out:
155 	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_proto parse error");
156 	return err;
157 }
158 
159 static int
160 sparx5_tc_flower_handler_control_usage(struct vcap_tc_flower_parse_usage *st)
161 {
162 	struct flow_match_control mt;
163 	u32 value, mask;
164 	int err = 0;
165 
166 	flow_rule_match_control(st->frule, &mt);
167 
168 	if (mt.mask->flags) {
169 		u8 is_frag_key = !!(mt.key->flags & FLOW_DIS_IS_FRAGMENT);
170 		u8 is_frag_mask = !!(mt.mask->flags & FLOW_DIS_IS_FRAGMENT);
171 		u8 is_frag_idx = (is_frag_key << 1) | is_frag_mask;
172 
173 		u8 first_frag_key = !!(mt.key->flags & FLOW_DIS_FIRST_FRAG);
174 		u8 first_frag_mask = !!(mt.mask->flags & FLOW_DIS_FIRST_FRAG);
175 		u8 first_frag_idx = (first_frag_key << 1) | first_frag_mask;
176 
177 		/* Lookup verdict based on the 2 + 2 input bits */
178 		u8 vdt = sparx5_vcap_frag_map[is_frag_idx][first_frag_idx];
179 
180 		if (vdt == FRAG_INVAL) {
181 			NL_SET_ERR_MSG_MOD(st->fco->common.extack,
182 					   "Match on invalid fragment flag combination");
183 			return -EINVAL;
184 		}
185 
186 		/* Extract VCAP fragment key and mask from verdict */
187 		value = (vdt >> 4) & 0x3;
188 		mask = vdt & 0x3;
189 
190 		err = vcap_rule_add_key_u32(st->vrule,
191 					    VCAP_KF_L3_FRAGMENT_TYPE,
192 					    value, mask);
193 		if (err)
194 			goto out;
195 	}
196 
197 	st->used_keys |= BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL);
198 
199 	return err;
200 
201 out:
202 	NL_SET_ERR_MSG_MOD(st->fco->common.extack, "ip_frag parse error");
203 	return err;
204 }
205 
206 static int
207 sparx5_tc_flower_handler_cvlan_usage(struct vcap_tc_flower_parse_usage *st)
208 {
209 	if (st->admin->vtype != VCAP_TYPE_IS0) {
210 		NL_SET_ERR_MSG_MOD(st->fco->common.extack,
211 				   "cvlan not supported in this VCAP");
212 		return -EINVAL;
213 	}
214 
215 	return vcap_tc_flower_handler_cvlan_usage(st);
216 }
217 
218 static int
219 sparx5_tc_flower_handler_vlan_usage(struct vcap_tc_flower_parse_usage *st)
220 {
221 	enum vcap_key_field vid_key = VCAP_KF_8021Q_VID_CLS;
222 	enum vcap_key_field pcp_key = VCAP_KF_8021Q_PCP_CLS;
223 	int err;
224 
225 	if (st->admin->vtype == VCAP_TYPE_IS0) {
226 		vid_key = VCAP_KF_8021Q_VID0;
227 		pcp_key = VCAP_KF_8021Q_PCP0;
228 	}
229 
230 	err = vcap_tc_flower_handler_vlan_usage(st, vid_key, pcp_key);
231 	if (err)
232 		return err;
233 
234 	if (st->admin->vtype == VCAP_TYPE_ES0 && st->tpid)
235 		err = sparx5_tc_flower_es0_tpid(st);
236 
237 	return err;
238 }
239 
240 static int (*sparx5_tc_flower_usage_handlers[])(struct vcap_tc_flower_parse_usage *st) = {
241 	[FLOW_DISSECTOR_KEY_ETH_ADDRS] = vcap_tc_flower_handler_ethaddr_usage,
242 	[FLOW_DISSECTOR_KEY_IPV4_ADDRS] = vcap_tc_flower_handler_ipv4_usage,
243 	[FLOW_DISSECTOR_KEY_IPV6_ADDRS] = vcap_tc_flower_handler_ipv6_usage,
244 	[FLOW_DISSECTOR_KEY_CONTROL] = sparx5_tc_flower_handler_control_usage,
245 	[FLOW_DISSECTOR_KEY_PORTS] = vcap_tc_flower_handler_portnum_usage,
246 	[FLOW_DISSECTOR_KEY_BASIC] = sparx5_tc_flower_handler_basic_usage,
247 	[FLOW_DISSECTOR_KEY_CVLAN] = sparx5_tc_flower_handler_cvlan_usage,
248 	[FLOW_DISSECTOR_KEY_VLAN] = sparx5_tc_flower_handler_vlan_usage,
249 	[FLOW_DISSECTOR_KEY_TCP] = vcap_tc_flower_handler_tcp_usage,
250 	[FLOW_DISSECTOR_KEY_ARP] = vcap_tc_flower_handler_arp_usage,
251 	[FLOW_DISSECTOR_KEY_IP] = vcap_tc_flower_handler_ip_usage,
252 };
253 
254 static int sparx5_tc_use_dissectors(struct vcap_tc_flower_parse_usage *st,
255 				    struct vcap_admin *admin,
256 				    struct vcap_rule *vrule)
257 {
258 	int idx, err = 0;
259 
260 	for (idx = 0; idx < ARRAY_SIZE(sparx5_tc_flower_usage_handlers); ++idx) {
261 		if (!flow_rule_match_key(st->frule, idx))
262 			continue;
263 		if (!sparx5_tc_flower_usage_handlers[idx])
264 			continue;
265 		err = sparx5_tc_flower_usage_handlers[idx](st);
266 		if (err)
267 			return err;
268 	}
269 
270 	if (st->frule->match.dissector->used_keys ^ st->used_keys) {
271 		NL_SET_ERR_MSG_MOD(st->fco->common.extack,
272 				   "Unsupported match item");
273 		return -ENOENT;
274 	}
275 
276 	return err;
277 }
278 
279 static int sparx5_tc_flower_action_check(struct vcap_control *vctrl,
280 					 struct net_device *ndev,
281 					 struct flow_cls_offload *fco,
282 					 bool ingress)
283 {
284 	struct flow_rule *rule = flow_cls_offload_flow_rule(fco);
285 	struct flow_action_entry *actent, *last_actent = NULL;
286 	struct flow_action *act = &rule->action;
287 	u64 action_mask = 0;
288 	int idx;
289 
290 	if (!flow_action_has_entries(act)) {
291 		NL_SET_ERR_MSG_MOD(fco->common.extack, "No actions");
292 		return -EINVAL;
293 	}
294 
295 	if (!flow_action_basic_hw_stats_check(act, fco->common.extack))
296 		return -EOPNOTSUPP;
297 
298 	flow_action_for_each(idx, actent, act) {
299 		if (action_mask & BIT(actent->id)) {
300 			NL_SET_ERR_MSG_MOD(fco->common.extack,
301 					   "More actions of the same type");
302 			return -EINVAL;
303 		}
304 		action_mask |= BIT(actent->id);
305 		last_actent = actent; /* Save last action for later check */
306 	}
307 
308 	/* Check if last action is a goto
309 	 * The last chain/lookup does not need to have a goto action
310 	 */
311 	if (last_actent->id == FLOW_ACTION_GOTO) {
312 		/* Check if the destination chain is in one of the VCAPs */
313 		if (!vcap_is_next_lookup(vctrl, fco->common.chain_index,
314 					 last_actent->chain_index)) {
315 			NL_SET_ERR_MSG_MOD(fco->common.extack,
316 					   "Invalid goto chain");
317 			return -EINVAL;
318 		}
319 	} else if (!vcap_is_last_chain(vctrl, fco->common.chain_index,
320 				       ingress)) {
321 		NL_SET_ERR_MSG_MOD(fco->common.extack,
322 				   "Last action must be 'goto'");
323 		return -EINVAL;
324 	}
325 
326 	/* Catch unsupported combinations of actions */
327 	if (action_mask & BIT(FLOW_ACTION_TRAP) &&
328 	    action_mask & BIT(FLOW_ACTION_ACCEPT)) {
329 		NL_SET_ERR_MSG_MOD(fco->common.extack,
330 				   "Cannot combine pass and trap action");
331 		return -EOPNOTSUPP;
332 	}
333 
334 	if (action_mask & BIT(FLOW_ACTION_VLAN_PUSH) &&
335 	    action_mask & BIT(FLOW_ACTION_VLAN_POP)) {
336 		NL_SET_ERR_MSG_MOD(fco->common.extack,
337 				   "Cannot combine vlan push and pop action");
338 		return -EOPNOTSUPP;
339 	}
340 
341 	if (action_mask & BIT(FLOW_ACTION_VLAN_PUSH) &&
342 	    action_mask & BIT(FLOW_ACTION_VLAN_MANGLE)) {
343 		NL_SET_ERR_MSG_MOD(fco->common.extack,
344 				   "Cannot combine vlan push and modify action");
345 		return -EOPNOTSUPP;
346 	}
347 
348 	if (action_mask & BIT(FLOW_ACTION_VLAN_POP) &&
349 	    action_mask & BIT(FLOW_ACTION_VLAN_MANGLE)) {
350 		NL_SET_ERR_MSG_MOD(fco->common.extack,
351 				   "Cannot combine vlan pop and modify action");
352 		return -EOPNOTSUPP;
353 	}
354 
355 	return 0;
356 }
357 
358 /* Add a rule counter action */
359 static int sparx5_tc_add_rule_counter(struct vcap_admin *admin,
360 				      struct vcap_rule *vrule)
361 {
362 	int err;
363 
364 	switch (admin->vtype) {
365 	case VCAP_TYPE_IS0:
366 		break;
367 	case VCAP_TYPE_ES0:
368 		err = vcap_rule_mod_action_u32(vrule, VCAP_AF_ESDX,
369 					       vrule->id);
370 		if (err)
371 			return err;
372 		vcap_rule_set_counter_id(vrule, vrule->id);
373 		break;
374 	case VCAP_TYPE_IS2:
375 	case VCAP_TYPE_ES2:
376 		err = vcap_rule_mod_action_u32(vrule, VCAP_AF_CNT_ID,
377 					       vrule->id);
378 		if (err)
379 			return err;
380 		vcap_rule_set_counter_id(vrule, vrule->id);
381 		break;
382 	default:
383 		pr_err("%s:%d: vcap type: %d not supported\n",
384 		       __func__, __LINE__, admin->vtype);
385 		break;
386 	}
387 	return 0;
388 }
389 
390 /* Collect all port keysets and apply the first of them, possibly wildcarded */
391 static int sparx5_tc_select_protocol_keyset(struct net_device *ndev,
392 					    struct vcap_rule *vrule,
393 					    struct vcap_admin *admin,
394 					    u16 l3_proto,
395 					    struct sparx5_multiple_rules *multi)
396 {
397 	struct sparx5_port *port = netdev_priv(ndev);
398 	struct vcap_keyset_list portkeysetlist = {};
399 	enum vcap_keyfield_set portkeysets[10] = {};
400 	struct vcap_keyset_list matches = {};
401 	enum vcap_keyfield_set keysets[10];
402 	int idx, jdx, err = 0, count = 0;
403 	struct sparx5_wildcard_rule *mru;
404 	const struct vcap_set *kinfo;
405 	struct vcap_control *vctrl;
406 
407 	vctrl = port->sparx5->vcap_ctrl;
408 
409 	/* Find the keysets that the rule can use */
410 	matches.keysets = keysets;
411 	matches.max = ARRAY_SIZE(keysets);
412 	if (!vcap_rule_find_keysets(vrule, &matches))
413 		return -EINVAL;
414 
415 	/* Find the keysets that the port configuration supports */
416 	portkeysetlist.max = ARRAY_SIZE(portkeysets);
417 	portkeysetlist.keysets = portkeysets;
418 	err = sparx5_vcap_get_port_keyset(ndev,
419 					  admin, vrule->vcap_chain_id,
420 					  l3_proto,
421 					  &portkeysetlist);
422 	if (err)
423 		return err;
424 
425 	/* Find the intersection of the two sets of keyset */
426 	for (idx = 0; idx < portkeysetlist.cnt; ++idx) {
427 		kinfo = vcap_keyfieldset(vctrl, admin->vtype,
428 					 portkeysetlist.keysets[idx]);
429 		if (!kinfo)
430 			continue;
431 
432 		/* Find a port keyset that matches the required keys
433 		 * If there are multiple keysets then compose a type id mask
434 		 */
435 		for (jdx = 0; jdx < matches.cnt; ++jdx) {
436 			if (portkeysetlist.keysets[idx] != matches.keysets[jdx])
437 				continue;
438 
439 			mru = &multi->rule[kinfo->sw_per_item];
440 			if (!mru->selected) {
441 				mru->selected = true;
442 				mru->keyset = portkeysetlist.keysets[idx];
443 				mru->value = kinfo->type_id;
444 			}
445 			mru->value &= kinfo->type_id;
446 			mru->mask |= kinfo->type_id;
447 			++count;
448 		}
449 	}
450 	if (count == 0)
451 		return -EPROTO;
452 
453 	if (l3_proto == ETH_P_ALL && count < portkeysetlist.cnt)
454 		return -ENOENT;
455 
456 	for (idx = 0; idx < SPX5_MAX_RULE_SIZE; ++idx) {
457 		mru = &multi->rule[idx];
458 		if (!mru->selected)
459 			continue;
460 
461 		/* Align the mask to the combined value */
462 		mru->mask ^= mru->value;
463 	}
464 
465 	/* Set the chosen keyset on the rule and set a wildcarded type if there
466 	 * are more than one keyset
467 	 */
468 	for (idx = 0; idx < SPX5_MAX_RULE_SIZE; ++idx) {
469 		mru = &multi->rule[idx];
470 		if (!mru->selected)
471 			continue;
472 
473 		vcap_set_rule_set_keyset(vrule, mru->keyset);
474 		if (count > 1)
475 			/* Some keysets do not have a type field */
476 			vcap_rule_mod_key_u32(vrule, VCAP_KF_TYPE,
477 					      mru->value,
478 					      ~mru->mask);
479 		mru->selected = false; /* mark as done */
480 		break; /* Stop here and add more rules later */
481 	}
482 	return err;
483 }
484 
485 static int sparx5_tc_add_rule_copy(struct vcap_control *vctrl,
486 				   struct flow_cls_offload *fco,
487 				   struct vcap_rule *erule,
488 				   struct vcap_admin *admin,
489 				   struct sparx5_wildcard_rule *rule)
490 {
491 	enum vcap_key_field keylist[] = {
492 		VCAP_KF_IF_IGR_PORT_MASK,
493 		VCAP_KF_IF_IGR_PORT_MASK_SEL,
494 		VCAP_KF_IF_IGR_PORT_MASK_RNG,
495 		VCAP_KF_LOOKUP_FIRST_IS,
496 		VCAP_KF_TYPE,
497 	};
498 	struct vcap_rule *vrule;
499 	int err;
500 
501 	/* Add an extra rule with a special user and the new keyset */
502 	erule->user = VCAP_USER_TC_EXTRA;
503 	vrule = vcap_copy_rule(erule);
504 	if (IS_ERR(vrule))
505 		return PTR_ERR(vrule);
506 
507 	/* Link the new rule to the existing rule with the cookie */
508 	vrule->cookie = erule->cookie;
509 	vcap_filter_rule_keys(vrule, keylist, ARRAY_SIZE(keylist), true);
510 	err = vcap_set_rule_set_keyset(vrule, rule->keyset);
511 	if (err) {
512 		pr_err("%s:%d: could not set keyset %s in rule: %u\n",
513 		       __func__, __LINE__,
514 		       vcap_keyset_name(vctrl, rule->keyset),
515 		       vrule->id);
516 		goto out;
517 	}
518 
519 	/* Some keysets do not have a type field, so ignore return value */
520 	vcap_rule_mod_key_u32(vrule, VCAP_KF_TYPE, rule->value, ~rule->mask);
521 
522 	err = vcap_set_rule_set_actionset(vrule, erule->actionset);
523 	if (err)
524 		goto out;
525 
526 	err = sparx5_tc_add_rule_counter(admin, vrule);
527 	if (err)
528 		goto out;
529 
530 	err = vcap_val_rule(vrule, ETH_P_ALL);
531 	if (err) {
532 		pr_err("%s:%d: could not validate rule: %u\n",
533 		       __func__, __LINE__, vrule->id);
534 		vcap_set_tc_exterr(fco, vrule);
535 		goto out;
536 	}
537 	err = vcap_add_rule(vrule);
538 	if (err) {
539 		pr_err("%s:%d: could not add rule: %u\n",
540 		       __func__, __LINE__, vrule->id);
541 		goto out;
542 	}
543 out:
544 	vcap_free_rule(vrule);
545 	return err;
546 }
547 
548 static int sparx5_tc_add_remaining_rules(struct vcap_control *vctrl,
549 					 struct flow_cls_offload *fco,
550 					 struct vcap_rule *erule,
551 					 struct vcap_admin *admin,
552 					 struct sparx5_multiple_rules *multi)
553 {
554 	int idx, err = 0;
555 
556 	for (idx = 0; idx < SPX5_MAX_RULE_SIZE; ++idx) {
557 		if (!multi->rule[idx].selected)
558 			continue;
559 
560 		err = sparx5_tc_add_rule_copy(vctrl, fco, erule, admin,
561 					      &multi->rule[idx]);
562 		if (err)
563 			break;
564 	}
565 	return err;
566 }
567 
568 /* Add the actionset that is the default for the VCAP type */
569 static int sparx5_tc_set_actionset(struct vcap_admin *admin,
570 				   struct vcap_rule *vrule)
571 {
572 	enum vcap_actionfield_set aset;
573 	int err = 0;
574 
575 	switch (admin->vtype) {
576 	case VCAP_TYPE_IS0:
577 		aset = VCAP_AFS_CLASSIFICATION;
578 		break;
579 	case VCAP_TYPE_IS2:
580 		aset = VCAP_AFS_BASE_TYPE;
581 		break;
582 	case VCAP_TYPE_ES0:
583 		aset = VCAP_AFS_ES0;
584 		break;
585 	case VCAP_TYPE_ES2:
586 		aset = VCAP_AFS_BASE_TYPE;
587 		break;
588 	default:
589 		pr_err("%s:%d: %s\n", __func__, __LINE__, "Invalid VCAP type");
590 		return -EINVAL;
591 	}
592 	/* Do not overwrite any current actionset */
593 	if (vrule->actionset == VCAP_AFS_NO_VALUE)
594 		err = vcap_set_rule_set_actionset(vrule, aset);
595 	return err;
596 }
597 
598 /* Add the VCAP key to match on for a rule target value */
599 static int sparx5_tc_add_rule_link_target(struct vcap_admin *admin,
600 					  struct vcap_rule *vrule,
601 					  int target_cid)
602 {
603 	int link_val = target_cid % VCAP_CID_LOOKUP_SIZE;
604 	int err;
605 
606 	if (!link_val)
607 		return 0;
608 
609 	switch (admin->vtype) {
610 	case VCAP_TYPE_IS0:
611 		/* Add NXT_IDX key for chaining rules between IS0 instances */
612 		err = vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_GEN_IDX_SEL,
613 					    1, /* enable */
614 					    ~0);
615 		if (err)
616 			return err;
617 		return vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_GEN_IDX,
618 					     link_val, /* target */
619 					     ~0);
620 	case VCAP_TYPE_IS2:
621 		/* Add PAG key for chaining rules from IS0 */
622 		return vcap_rule_add_key_u32(vrule, VCAP_KF_LOOKUP_PAG,
623 					     link_val, /* target */
624 					     ~0);
625 	case VCAP_TYPE_ES0:
626 	case VCAP_TYPE_ES2:
627 		/* Add ISDX key for chaining rules from IS0 */
628 		return vcap_rule_add_key_u32(vrule, VCAP_KF_ISDX_CLS, link_val,
629 					     ~0);
630 	default:
631 		break;
632 	}
633 	return 0;
634 }
635 
636 /* Add the VCAP action that adds a target value to a rule */
637 static int sparx5_tc_add_rule_link(struct vcap_control *vctrl,
638 				   struct vcap_admin *admin,
639 				   struct vcap_rule *vrule,
640 				   int from_cid, int to_cid)
641 {
642 	struct vcap_admin *to_admin = vcap_find_admin(vctrl, to_cid);
643 	int diff, err = 0;
644 
645 	if (!to_admin) {
646 		pr_err("%s:%d: unsupported chain direction: %d\n",
647 		       __func__, __LINE__, to_cid);
648 		return -EINVAL;
649 	}
650 
651 	diff = vcap_chain_offset(vctrl, from_cid, to_cid);
652 	if (!diff)
653 		return 0;
654 
655 	if (admin->vtype == VCAP_TYPE_IS0 &&
656 	    to_admin->vtype == VCAP_TYPE_IS0) {
657 		/* Between IS0 instances the G_IDX value is used */
658 		err = vcap_rule_add_action_u32(vrule, VCAP_AF_NXT_IDX, diff);
659 		if (err)
660 			goto out;
661 		err = vcap_rule_add_action_u32(vrule, VCAP_AF_NXT_IDX_CTRL,
662 					       1); /* Replace */
663 		if (err)
664 			goto out;
665 	} else if (admin->vtype == VCAP_TYPE_IS0 &&
666 		   to_admin->vtype == VCAP_TYPE_IS2) {
667 		/* Between IS0 and IS2 the PAG value is used */
668 		err = vcap_rule_add_action_u32(vrule, VCAP_AF_PAG_VAL, diff);
669 		if (err)
670 			goto out;
671 		err = vcap_rule_add_action_u32(vrule,
672 					       VCAP_AF_PAG_OVERRIDE_MASK,
673 					       0xff);
674 		if (err)
675 			goto out;
676 	} else if (admin->vtype == VCAP_TYPE_IS0 &&
677 		   (to_admin->vtype == VCAP_TYPE_ES0 ||
678 		    to_admin->vtype == VCAP_TYPE_ES2)) {
679 		/* Between IS0 and ES0/ES2 the ISDX value is used */
680 		err = vcap_rule_add_action_u32(vrule, VCAP_AF_ISDX_VAL,
681 					       diff);
682 		if (err)
683 			goto out;
684 		err = vcap_rule_add_action_bit(vrule,
685 					       VCAP_AF_ISDX_ADD_REPLACE_SEL,
686 					       VCAP_BIT_1);
687 		if (err)
688 			goto out;
689 	} else {
690 		pr_err("%s:%d: unsupported chain destination: %d\n",
691 		       __func__, __LINE__, to_cid);
692 		err = -EOPNOTSUPP;
693 	}
694 out:
695 	return err;
696 }
697 
698 static int sparx5_tc_flower_parse_act_gate(struct sparx5_psfp_sg *sg,
699 					   struct flow_action_entry *act,
700 					   struct netlink_ext_ack *extack)
701 {
702 	int i;
703 
704 	if (act->gate.prio < -1 || act->gate.prio > SPX5_PSFP_SG_MAX_IPV) {
705 		NL_SET_ERR_MSG_MOD(extack, "Invalid gate priority");
706 		return -EINVAL;
707 	}
708 
709 	if (act->gate.cycletime < SPX5_PSFP_SG_MIN_CYCLE_TIME_NS ||
710 	    act->gate.cycletime > SPX5_PSFP_SG_MAX_CYCLE_TIME_NS) {
711 		NL_SET_ERR_MSG_MOD(extack, "Invalid gate cycletime");
712 		return -EINVAL;
713 	}
714 
715 	if (act->gate.cycletimeext > SPX5_PSFP_SG_MAX_CYCLE_TIME_NS) {
716 		NL_SET_ERR_MSG_MOD(extack, "Invalid gate cycletimeext");
717 		return -EINVAL;
718 	}
719 
720 	if (act->gate.num_entries >= SPX5_PSFP_GCE_CNT) {
721 		NL_SET_ERR_MSG_MOD(extack, "Invalid number of gate entries");
722 		return -EINVAL;
723 	}
724 
725 	sg->gate_state = true;
726 	sg->ipv = act->gate.prio;
727 	sg->num_entries = act->gate.num_entries;
728 	sg->cycletime = act->gate.cycletime;
729 	sg->cycletimeext = act->gate.cycletimeext;
730 
731 	for (i = 0; i < sg->num_entries; i++) {
732 		sg->gce[i].gate_state = !!act->gate.entries[i].gate_state;
733 		sg->gce[i].interval = act->gate.entries[i].interval;
734 		sg->gce[i].ipv = act->gate.entries[i].ipv;
735 		sg->gce[i].maxoctets = act->gate.entries[i].maxoctets;
736 	}
737 
738 	return 0;
739 }
740 
741 static int sparx5_tc_flower_parse_act_police(struct sparx5_policer *pol,
742 					     struct flow_action_entry *act,
743 					     struct netlink_ext_ack *extack)
744 {
745 	pol->type = SPX5_POL_SERVICE;
746 	pol->rate = div_u64(act->police.rate_bytes_ps, 1000) * 8;
747 	pol->burst = act->police.burst;
748 	pol->idx = act->hw_index;
749 
750 	/* rate is now in kbit */
751 	if (pol->rate > DIV_ROUND_UP(SPX5_SDLB_GROUP_RATE_MAX, 1000)) {
752 		NL_SET_ERR_MSG_MOD(extack, "Maximum rate exceeded");
753 		return -EINVAL;
754 	}
755 
756 	if (act->police.exceed.act_id != FLOW_ACTION_DROP) {
757 		NL_SET_ERR_MSG_MOD(extack, "Offload not supported when exceed action is not drop");
758 		return -EOPNOTSUPP;
759 	}
760 
761 	if (act->police.notexceed.act_id != FLOW_ACTION_PIPE &&
762 	    act->police.notexceed.act_id != FLOW_ACTION_ACCEPT) {
763 		NL_SET_ERR_MSG_MOD(extack, "Offload not supported when conform action is not pipe or ok");
764 		return -EOPNOTSUPP;
765 	}
766 
767 	return 0;
768 }
769 
770 static int sparx5_tc_flower_psfp_setup(struct sparx5 *sparx5,
771 				       struct vcap_rule *vrule, int sg_idx,
772 				       int pol_idx, struct sparx5_psfp_sg *sg,
773 				       struct sparx5_psfp_fm *fm,
774 				       struct sparx5_psfp_sf *sf)
775 {
776 	u32 psfp_sfid = 0, psfp_fmid = 0, psfp_sgid = 0;
777 	int ret;
778 
779 	/* Must always have a stream gate - max sdu (filter option) is evaluated
780 	 * after frames have passed the gate, so in case of only a policer, we
781 	 * allocate a stream gate that is always open.
782 	 */
783 	if (sg_idx < 0) {
784 		sg_idx = sparx5_pool_idx_to_id(SPX5_PSFP_SG_OPEN);
785 		sg->ipv = 0; /* Disabled */
786 		sg->cycletime = SPX5_PSFP_SG_CYCLE_TIME_DEFAULT;
787 		sg->num_entries = 1;
788 		sg->gate_state = 1; /* Open */
789 		sg->gate_enabled = 1;
790 		sg->gce[0].gate_state = 1;
791 		sg->gce[0].interval = SPX5_PSFP_SG_CYCLE_TIME_DEFAULT;
792 		sg->gce[0].ipv = 0;
793 		sg->gce[0].maxoctets = 0; /* Disabled */
794 	}
795 
796 	ret = sparx5_psfp_sg_add(sparx5, sg_idx, sg, &psfp_sgid);
797 	if (ret < 0)
798 		return ret;
799 
800 	if (pol_idx >= 0) {
801 		/* Add new flow-meter */
802 		ret = sparx5_psfp_fm_add(sparx5, pol_idx, fm, &psfp_fmid);
803 		if (ret < 0)
804 			return ret;
805 	}
806 
807 	/* Map stream filter to stream gate */
808 	sf->sgid = psfp_sgid;
809 
810 	/* Add new stream-filter and map it to a steam gate */
811 	ret = sparx5_psfp_sf_add(sparx5, sf, &psfp_sfid);
812 	if (ret < 0)
813 		return ret;
814 
815 	/* Streams are classified by ISDX - map ISDX 1:1 to sfid for now. */
816 	sparx5_isdx_conf_set(sparx5, psfp_sfid, psfp_sfid, psfp_fmid);
817 
818 	ret = vcap_rule_add_action_bit(vrule, VCAP_AF_ISDX_ADD_REPLACE_SEL,
819 				       VCAP_BIT_1);
820 	if (ret)
821 		return ret;
822 
823 	ret = vcap_rule_add_action_u32(vrule, VCAP_AF_ISDX_VAL, psfp_sfid);
824 	if (ret)
825 		return ret;
826 
827 	return 0;
828 }
829 
830 /* Handle the action trap for a VCAP rule */
831 static int sparx5_tc_action_trap(struct vcap_admin *admin,
832 				 struct vcap_rule *vrule,
833 				 struct flow_cls_offload *fco)
834 {
835 	int err = 0;
836 
837 	switch (admin->vtype) {
838 	case VCAP_TYPE_IS2:
839 		err = vcap_rule_add_action_bit(vrule,
840 					       VCAP_AF_CPU_COPY_ENA,
841 					       VCAP_BIT_1);
842 		if (err)
843 			break;
844 		err = vcap_rule_add_action_u32(vrule,
845 					       VCAP_AF_CPU_QUEUE_NUM, 0);
846 		if (err)
847 			break;
848 		err = vcap_rule_add_action_u32(vrule,
849 					       VCAP_AF_MASK_MODE,
850 					       SPX5_PMM_REPLACE_ALL);
851 		break;
852 	case VCAP_TYPE_ES0:
853 		err = vcap_rule_add_action_u32(vrule,
854 					       VCAP_AF_FWD_SEL,
855 					       SPX5_FWSEL_REDIRECT_TO_LOOPBACK);
856 		break;
857 	case VCAP_TYPE_ES2:
858 		err = vcap_rule_add_action_bit(vrule,
859 					       VCAP_AF_CPU_COPY_ENA,
860 					       VCAP_BIT_1);
861 		if (err)
862 			break;
863 		err = vcap_rule_add_action_u32(vrule,
864 					       VCAP_AF_CPU_QUEUE_NUM, 0);
865 		break;
866 	default:
867 		NL_SET_ERR_MSG_MOD(fco->common.extack,
868 				   "Trap action not supported in this VCAP");
869 		err = -EOPNOTSUPP;
870 		break;
871 	}
872 	return err;
873 }
874 
875 static int sparx5_tc_action_vlan_pop(struct vcap_admin *admin,
876 				     struct vcap_rule *vrule,
877 				     struct flow_cls_offload *fco,
878 				     u16 tpid)
879 {
880 	int err = 0;
881 
882 	switch (admin->vtype) {
883 	case VCAP_TYPE_ES0:
884 		break;
885 	default:
886 		NL_SET_ERR_MSG_MOD(fco->common.extack,
887 				   "VLAN pop action not supported in this VCAP");
888 		return -EOPNOTSUPP;
889 	}
890 
891 	switch (tpid) {
892 	case ETH_P_8021Q:
893 	case ETH_P_8021AD:
894 		err = vcap_rule_add_action_u32(vrule,
895 					       VCAP_AF_PUSH_OUTER_TAG,
896 					       SPX5_OTAG_UNTAG);
897 		break;
898 	default:
899 		NL_SET_ERR_MSG_MOD(fco->common.extack,
900 				   "Invalid vlan proto");
901 		err = -EINVAL;
902 	}
903 	return err;
904 }
905 
906 static int sparx5_tc_action_vlan_modify(struct vcap_admin *admin,
907 					struct vcap_rule *vrule,
908 					struct flow_cls_offload *fco,
909 					struct flow_action_entry *act,
910 					u16 tpid)
911 {
912 	int err = 0;
913 
914 	switch (admin->vtype) {
915 	case VCAP_TYPE_ES0:
916 		err = vcap_rule_add_action_u32(vrule,
917 					       VCAP_AF_PUSH_OUTER_TAG,
918 					       SPX5_OTAG_TAG_A);
919 		if (err)
920 			return err;
921 		break;
922 	default:
923 		NL_SET_ERR_MSG_MOD(fco->common.extack,
924 				   "VLAN modify action not supported in this VCAP");
925 		return -EOPNOTSUPP;
926 	}
927 
928 	switch (tpid) {
929 	case ETH_P_8021Q:
930 		err = vcap_rule_add_action_u32(vrule,
931 					       VCAP_AF_TAG_A_TPID_SEL,
932 					       SPX5_TPID_A_8100);
933 		break;
934 	case ETH_P_8021AD:
935 		err = vcap_rule_add_action_u32(vrule,
936 					       VCAP_AF_TAG_A_TPID_SEL,
937 					       SPX5_TPID_A_88A8);
938 		break;
939 	default:
940 		NL_SET_ERR_MSG_MOD(fco->common.extack,
941 				   "Invalid vlan proto");
942 		err = -EINVAL;
943 	}
944 	if (err)
945 		return err;
946 
947 	err = vcap_rule_add_action_u32(vrule,
948 				       VCAP_AF_TAG_A_VID_SEL,
949 				       SPX5_VID_A_VAL);
950 	if (err)
951 		return err;
952 
953 	err = vcap_rule_add_action_u32(vrule,
954 				       VCAP_AF_VID_A_VAL,
955 				       act->vlan.vid);
956 	if (err)
957 		return err;
958 
959 	err = vcap_rule_add_action_u32(vrule,
960 				       VCAP_AF_TAG_A_PCP_SEL,
961 				       SPX5_PCP_A_VAL);
962 	if (err)
963 		return err;
964 
965 	err = vcap_rule_add_action_u32(vrule,
966 				       VCAP_AF_PCP_A_VAL,
967 				       act->vlan.prio);
968 	if (err)
969 		return err;
970 
971 	return vcap_rule_add_action_u32(vrule,
972 					VCAP_AF_TAG_A_DEI_SEL,
973 					SPX5_DEI_A_CLASSIFIED);
974 }
975 
976 static int sparx5_tc_action_vlan_push(struct vcap_admin *admin,
977 				      struct vcap_rule *vrule,
978 				      struct flow_cls_offload *fco,
979 				      struct flow_action_entry *act,
980 				      u16 tpid)
981 {
982 	u16 act_tpid = be16_to_cpu(act->vlan.proto);
983 	int err = 0;
984 
985 	switch (admin->vtype) {
986 	case VCAP_TYPE_ES0:
987 		break;
988 	default:
989 		NL_SET_ERR_MSG_MOD(fco->common.extack,
990 				   "VLAN push action not supported in this VCAP");
991 		return -EOPNOTSUPP;
992 	}
993 
994 	if (tpid == ETH_P_8021AD) {
995 		NL_SET_ERR_MSG_MOD(fco->common.extack,
996 				   "Cannot push on double tagged frames");
997 		return -EOPNOTSUPP;
998 	}
999 
1000 	err = sparx5_tc_action_vlan_modify(admin, vrule, fco, act, act_tpid);
1001 	if (err)
1002 		return err;
1003 
1004 	switch (act_tpid) {
1005 	case ETH_P_8021Q:
1006 		break;
1007 	case ETH_P_8021AD:
1008 		/* Push classified tag as inner tag */
1009 		err = vcap_rule_add_action_u32(vrule,
1010 					       VCAP_AF_PUSH_INNER_TAG,
1011 					       SPX5_ITAG_PUSH_B_TAG);
1012 		if (err)
1013 			break;
1014 		err = vcap_rule_add_action_u32(vrule,
1015 					       VCAP_AF_TAG_B_TPID_SEL,
1016 					       SPX5_TPID_B_CLASSIFIED);
1017 		break;
1018 	default:
1019 		NL_SET_ERR_MSG_MOD(fco->common.extack,
1020 				   "Invalid vlan proto");
1021 		err = -EINVAL;
1022 	}
1023 	return err;
1024 }
1025 
1026 static void sparx5_tc_flower_set_port_mask(struct vcap_u72_action *ports,
1027 					   struct net_device *ndev)
1028 {
1029 	struct sparx5_port *port = netdev_priv(ndev);
1030 	int byidx = port->portno / BITS_PER_BYTE;
1031 	int biidx = port->portno % BITS_PER_BYTE;
1032 
1033 	ports->value[byidx] |= BIT(biidx);
1034 }
1035 
1036 static int sparx5_tc_action_mirred(struct vcap_admin *admin,
1037 				   struct vcap_rule *vrule,
1038 				   struct flow_cls_offload *fco,
1039 				   struct flow_action_entry *act)
1040 {
1041 	struct vcap_u72_action ports = {0};
1042 	int err;
1043 
1044 	if (admin->vtype != VCAP_TYPE_IS0 && admin->vtype != VCAP_TYPE_IS2) {
1045 		NL_SET_ERR_MSG_MOD(fco->common.extack,
1046 				   "Mirror action not supported in this VCAP");
1047 		return -EOPNOTSUPP;
1048 	}
1049 
1050 	err = vcap_rule_add_action_u32(vrule, VCAP_AF_MASK_MODE,
1051 				       SPX5_PMM_OR_DSTMASK);
1052 	if (err)
1053 		return err;
1054 
1055 	sparx5_tc_flower_set_port_mask(&ports, act->dev);
1056 
1057 	return vcap_rule_add_action_u72(vrule, VCAP_AF_PORT_MASK, &ports);
1058 }
1059 
1060 static int sparx5_tc_action_redirect(struct vcap_admin *admin,
1061 				     struct vcap_rule *vrule,
1062 				     struct flow_cls_offload *fco,
1063 				     struct flow_action_entry *act)
1064 {
1065 	struct vcap_u72_action ports = {0};
1066 	int err;
1067 
1068 	if (admin->vtype != VCAP_TYPE_IS0 && admin->vtype != VCAP_TYPE_IS2) {
1069 		NL_SET_ERR_MSG_MOD(fco->common.extack,
1070 				   "Redirect action not supported in this VCAP");
1071 		return -EOPNOTSUPP;
1072 	}
1073 
1074 	err = vcap_rule_add_action_u32(vrule, VCAP_AF_MASK_MODE,
1075 				       SPX5_PMM_REPLACE_ALL);
1076 	if (err)
1077 		return err;
1078 
1079 	sparx5_tc_flower_set_port_mask(&ports, act->dev);
1080 
1081 	return vcap_rule_add_action_u72(vrule, VCAP_AF_PORT_MASK, &ports);
1082 }
1083 
1084 /* Remove rule keys that may prevent templates from matching a keyset */
1085 static void sparx5_tc_flower_simplify_rule(struct vcap_admin *admin,
1086 					   struct vcap_rule *vrule,
1087 					   u16 l3_proto)
1088 {
1089 	switch (admin->vtype) {
1090 	case VCAP_TYPE_IS0:
1091 		vcap_rule_rem_key(vrule, VCAP_KF_ETYPE);
1092 		switch (l3_proto) {
1093 		case ETH_P_IP:
1094 			break;
1095 		case ETH_P_IPV6:
1096 			vcap_rule_rem_key(vrule, VCAP_KF_IP_SNAP_IS);
1097 			break;
1098 		default:
1099 			break;
1100 		}
1101 		break;
1102 	case VCAP_TYPE_ES2:
1103 		switch (l3_proto) {
1104 		case ETH_P_IP:
1105 			if (vrule->keyset == VCAP_KFS_IP4_OTHER)
1106 				vcap_rule_rem_key(vrule, VCAP_KF_TCP_IS);
1107 			break;
1108 		case ETH_P_IPV6:
1109 			if (vrule->keyset == VCAP_KFS_IP6_STD)
1110 				vcap_rule_rem_key(vrule, VCAP_KF_TCP_IS);
1111 			vcap_rule_rem_key(vrule, VCAP_KF_IP4_IS);
1112 			break;
1113 		default:
1114 			break;
1115 		}
1116 		break;
1117 	case VCAP_TYPE_IS2:
1118 		switch (l3_proto) {
1119 		case ETH_P_IP:
1120 		case ETH_P_IPV6:
1121 			vcap_rule_rem_key(vrule, VCAP_KF_IP4_IS);
1122 			break;
1123 		default:
1124 			break;
1125 		}
1126 		break;
1127 	default:
1128 		break;
1129 	}
1130 }
1131 
1132 static bool sparx5_tc_flower_use_template(struct net_device *ndev,
1133 					  struct flow_cls_offload *fco,
1134 					  struct vcap_admin *admin,
1135 					  struct vcap_rule *vrule)
1136 {
1137 	struct sparx5_port *port = netdev_priv(ndev);
1138 	struct sparx5_tc_flower_template *ftp;
1139 
1140 	list_for_each_entry(ftp, &port->tc_templates, list) {
1141 		if (ftp->cid != fco->common.chain_index)
1142 			continue;
1143 
1144 		vcap_set_rule_set_keyset(vrule, ftp->keyset);
1145 		sparx5_tc_flower_simplify_rule(admin, vrule, ftp->l3_proto);
1146 		return true;
1147 	}
1148 	return false;
1149 }
1150 
1151 static int sparx5_tc_flower_replace(struct net_device *ndev,
1152 				    struct flow_cls_offload *fco,
1153 				    struct vcap_admin *admin,
1154 				    bool ingress)
1155 {
1156 	struct sparx5_psfp_sf sf = { .max_sdu = SPX5_PSFP_SF_MAX_SDU };
1157 	struct netlink_ext_ack *extack = fco->common.extack;
1158 	int err, idx, tc_sg_idx = -1, tc_pol_idx = -1;
1159 	struct vcap_tc_flower_parse_usage state = {
1160 		.fco = fco,
1161 		.l3_proto = ETH_P_ALL,
1162 		.admin = admin,
1163 	};
1164 	struct sparx5_port *port = netdev_priv(ndev);
1165 	struct sparx5_multiple_rules multi = {};
1166 	struct sparx5 *sparx5 = port->sparx5;
1167 	struct sparx5_psfp_sg sg = { 0 };
1168 	struct sparx5_psfp_fm fm = { 0 };
1169 	struct flow_action_entry *act;
1170 	struct vcap_control *vctrl;
1171 	struct flow_rule *frule;
1172 	struct vcap_rule *vrule;
1173 
1174 	vctrl = port->sparx5->vcap_ctrl;
1175 
1176 	err = sparx5_tc_flower_action_check(vctrl, ndev, fco, ingress);
1177 	if (err)
1178 		return err;
1179 
1180 	vrule = vcap_alloc_rule(vctrl, ndev, fco->common.chain_index, VCAP_USER_TC,
1181 				fco->common.prio, 0);
1182 	if (IS_ERR(vrule))
1183 		return PTR_ERR(vrule);
1184 
1185 	vrule->cookie = fco->cookie;
1186 
1187 	state.vrule = vrule;
1188 	state.frule = flow_cls_offload_flow_rule(fco);
1189 	err = sparx5_tc_use_dissectors(&state, admin, vrule);
1190 	if (err)
1191 		goto out;
1192 
1193 	err = sparx5_tc_add_rule_counter(admin, vrule);
1194 	if (err)
1195 		goto out;
1196 
1197 	err = sparx5_tc_add_rule_link_target(admin, vrule,
1198 					     fco->common.chain_index);
1199 	if (err)
1200 		goto out;
1201 
1202 	frule = flow_cls_offload_flow_rule(fco);
1203 	flow_action_for_each(idx, act, &frule->action) {
1204 		switch (act->id) {
1205 		case FLOW_ACTION_GATE: {
1206 			err = sparx5_tc_flower_parse_act_gate(&sg, act, extack);
1207 			if (err < 0)
1208 				goto out;
1209 
1210 			tc_sg_idx = act->hw_index;
1211 
1212 			break;
1213 		}
1214 		case FLOW_ACTION_POLICE: {
1215 			err = sparx5_tc_flower_parse_act_police(&fm.pol, act,
1216 								extack);
1217 			if (err < 0)
1218 				goto out;
1219 
1220 			tc_pol_idx = fm.pol.idx;
1221 			sf.max_sdu = act->police.mtu;
1222 
1223 			break;
1224 		}
1225 		case FLOW_ACTION_TRAP:
1226 			err = sparx5_tc_action_trap(admin, vrule, fco);
1227 			if (err)
1228 				goto out;
1229 			break;
1230 		case FLOW_ACTION_MIRRED:
1231 			err = sparx5_tc_action_mirred(admin, vrule, fco, act);
1232 			if (err)
1233 				goto out;
1234 			break;
1235 		case FLOW_ACTION_REDIRECT:
1236 			err = sparx5_tc_action_redirect(admin, vrule, fco, act);
1237 			if (err)
1238 				goto out;
1239 			break;
1240 		case FLOW_ACTION_ACCEPT:
1241 			err = sparx5_tc_set_actionset(admin, vrule);
1242 			if (err)
1243 				goto out;
1244 			break;
1245 		case FLOW_ACTION_GOTO:
1246 			err = sparx5_tc_set_actionset(admin, vrule);
1247 			if (err)
1248 				goto out;
1249 			sparx5_tc_add_rule_link(vctrl, admin, vrule,
1250 						fco->common.chain_index,
1251 						act->chain_index);
1252 			break;
1253 		case FLOW_ACTION_VLAN_POP:
1254 			err = sparx5_tc_action_vlan_pop(admin, vrule, fco,
1255 							state.tpid);
1256 			if (err)
1257 				goto out;
1258 			break;
1259 		case FLOW_ACTION_VLAN_PUSH:
1260 			err = sparx5_tc_action_vlan_push(admin, vrule, fco,
1261 							 act, state.tpid);
1262 			if (err)
1263 				goto out;
1264 			break;
1265 		case FLOW_ACTION_VLAN_MANGLE:
1266 			err = sparx5_tc_action_vlan_modify(admin, vrule, fco,
1267 							   act, state.tpid);
1268 			if (err)
1269 				goto out;
1270 			break;
1271 		default:
1272 			NL_SET_ERR_MSG_MOD(fco->common.extack,
1273 					   "Unsupported TC action");
1274 			err = -EOPNOTSUPP;
1275 			goto out;
1276 		}
1277 	}
1278 
1279 	/* Setup PSFP */
1280 	if (tc_sg_idx >= 0 || tc_pol_idx >= 0) {
1281 		err = sparx5_tc_flower_psfp_setup(sparx5, vrule, tc_sg_idx,
1282 						  tc_pol_idx, &sg, &fm, &sf);
1283 		if (err)
1284 			goto out;
1285 	}
1286 
1287 	if (!sparx5_tc_flower_use_template(ndev, fco, admin, vrule)) {
1288 		err = sparx5_tc_select_protocol_keyset(ndev, vrule, admin,
1289 						       state.l3_proto, &multi);
1290 		if (err) {
1291 			NL_SET_ERR_MSG_MOD(fco->common.extack,
1292 					   "No matching port keyset for filter protocol and keys");
1293 			goto out;
1294 		}
1295 	}
1296 
1297 	/* provide the l3 protocol to guide the keyset selection */
1298 	err = vcap_val_rule(vrule, state.l3_proto);
1299 	if (err) {
1300 		vcap_set_tc_exterr(fco, vrule);
1301 		goto out;
1302 	}
1303 	err = vcap_add_rule(vrule);
1304 	if (err)
1305 		NL_SET_ERR_MSG_MOD(fco->common.extack,
1306 				   "Could not add the filter");
1307 
1308 	if (state.l3_proto == ETH_P_ALL)
1309 		err = sparx5_tc_add_remaining_rules(vctrl, fco, vrule, admin,
1310 						    &multi);
1311 
1312 out:
1313 	vcap_free_rule(vrule);
1314 	return err;
1315 }
1316 
1317 static void sparx5_tc_free_psfp_resources(struct sparx5 *sparx5,
1318 					  struct vcap_rule *vrule)
1319 {
1320 	struct vcap_client_actionfield *afield;
1321 	u32 isdx, sfid, sgid, fmid;
1322 
1323 	/* Check if VCAP_AF_ISDX_VAL action is set for this rule - and if
1324 	 * it is used for stream and/or flow-meter classification.
1325 	 */
1326 	afield = vcap_find_actionfield(vrule, VCAP_AF_ISDX_VAL);
1327 	if (!afield)
1328 		return;
1329 
1330 	isdx = afield->data.u32.value;
1331 	sfid = sparx5_psfp_isdx_get_sf(sparx5, isdx);
1332 
1333 	if (!sfid)
1334 		return;
1335 
1336 	fmid = sparx5_psfp_isdx_get_fm(sparx5, isdx);
1337 	sgid = sparx5_psfp_sf_get_sg(sparx5, sfid);
1338 
1339 	if (fmid && sparx5_psfp_fm_del(sparx5, fmid) < 0)
1340 		pr_err("%s:%d Could not delete invalid fmid: %d", __func__,
1341 		       __LINE__, fmid);
1342 
1343 	if (sgid && sparx5_psfp_sg_del(sparx5, sgid) < 0)
1344 		pr_err("%s:%d Could not delete invalid sgid: %d", __func__,
1345 		       __LINE__, sgid);
1346 
1347 	if (sparx5_psfp_sf_del(sparx5, sfid) < 0)
1348 		pr_err("%s:%d Could not delete invalid sfid: %d", __func__,
1349 		       __LINE__, sfid);
1350 
1351 	sparx5_isdx_conf_set(sparx5, isdx, 0, 0);
1352 }
1353 
1354 static int sparx5_tc_free_rule_resources(struct net_device *ndev,
1355 					 struct vcap_control *vctrl,
1356 					 int rule_id)
1357 {
1358 	struct sparx5_port *port = netdev_priv(ndev);
1359 	struct sparx5 *sparx5 = port->sparx5;
1360 	struct vcap_rule *vrule;
1361 	int ret = 0;
1362 
1363 	vrule = vcap_get_rule(vctrl, rule_id);
1364 	if (IS_ERR(vrule))
1365 		return -EINVAL;
1366 
1367 	sparx5_tc_free_psfp_resources(sparx5, vrule);
1368 
1369 	vcap_free_rule(vrule);
1370 	return ret;
1371 }
1372 
1373 static int sparx5_tc_flower_destroy(struct net_device *ndev,
1374 				    struct flow_cls_offload *fco,
1375 				    struct vcap_admin *admin)
1376 {
1377 	struct sparx5_port *port = netdev_priv(ndev);
1378 	int err = -ENOENT, count = 0, rule_id;
1379 	struct vcap_control *vctrl;
1380 
1381 	vctrl = port->sparx5->vcap_ctrl;
1382 	while (true) {
1383 		rule_id = vcap_lookup_rule_by_cookie(vctrl, fco->cookie);
1384 		if (rule_id <= 0)
1385 			break;
1386 		if (count == 0) {
1387 			/* Resources are attached to the first rule of
1388 			 * a set of rules. Only works if the rules are
1389 			 * in the correct order.
1390 			 */
1391 			err = sparx5_tc_free_rule_resources(ndev, vctrl,
1392 							    rule_id);
1393 			if (err)
1394 				pr_err("%s:%d: could not free resources %d\n",
1395 				       __func__, __LINE__, rule_id);
1396 		}
1397 		err = vcap_del_rule(vctrl, ndev, rule_id);
1398 		if (err) {
1399 			pr_err("%s:%d: could not delete rule %d\n",
1400 			       __func__, __LINE__, rule_id);
1401 			break;
1402 		}
1403 	}
1404 	return err;
1405 }
1406 
1407 static int sparx5_tc_flower_stats(struct net_device *ndev,
1408 				  struct flow_cls_offload *fco,
1409 				  struct vcap_admin *admin)
1410 {
1411 	struct sparx5_port *port = netdev_priv(ndev);
1412 	struct vcap_counter ctr = {};
1413 	struct vcap_control *vctrl;
1414 	ulong lastused = 0;
1415 	int err;
1416 
1417 	vctrl = port->sparx5->vcap_ctrl;
1418 	err = vcap_get_rule_count_by_cookie(vctrl, &ctr, fco->cookie);
1419 	if (err)
1420 		return err;
1421 	flow_stats_update(&fco->stats, 0x0, ctr.value, 0, lastused,
1422 			  FLOW_ACTION_HW_STATS_IMMEDIATE);
1423 	return err;
1424 }
1425 
1426 static int sparx5_tc_flower_template_create(struct net_device *ndev,
1427 					    struct flow_cls_offload *fco,
1428 					    struct vcap_admin *admin)
1429 {
1430 	struct sparx5_port *port = netdev_priv(ndev);
1431 	struct vcap_tc_flower_parse_usage state = {
1432 		.fco = fco,
1433 		.l3_proto = ETH_P_ALL,
1434 		.admin = admin,
1435 	};
1436 	struct sparx5_tc_flower_template *ftp;
1437 	struct vcap_keyset_list kslist = {};
1438 	enum vcap_keyfield_set keysets[10];
1439 	struct vcap_control *vctrl;
1440 	struct vcap_rule *vrule;
1441 	int count, err;
1442 
1443 	if (admin->vtype == VCAP_TYPE_ES0) {
1444 		pr_err("%s:%d: %s\n", __func__, __LINE__,
1445 		       "VCAP does not support templates");
1446 		return -EINVAL;
1447 	}
1448 
1449 	count = vcap_admin_rule_count(admin, fco->common.chain_index);
1450 	if (count > 0) {
1451 		pr_err("%s:%d: %s\n", __func__, __LINE__,
1452 		       "Filters are already present");
1453 		return -EBUSY;
1454 	}
1455 
1456 	ftp = kzalloc(sizeof(*ftp), GFP_KERNEL);
1457 	if (!ftp)
1458 		return -ENOMEM;
1459 
1460 	ftp->cid = fco->common.chain_index;
1461 	ftp->orig = VCAP_KFS_NO_VALUE;
1462 	ftp->keyset = VCAP_KFS_NO_VALUE;
1463 
1464 	vctrl = port->sparx5->vcap_ctrl;
1465 	vrule = vcap_alloc_rule(vctrl, ndev, fco->common.chain_index,
1466 				VCAP_USER_TC, fco->common.prio, 0);
1467 	if (IS_ERR(vrule)) {
1468 		err = PTR_ERR(vrule);
1469 		goto err_rule;
1470 	}
1471 
1472 	state.vrule = vrule;
1473 	state.frule = flow_cls_offload_flow_rule(fco);
1474 	err = sparx5_tc_use_dissectors(&state, admin, vrule);
1475 	if (err) {
1476 		pr_err("%s:%d: key error: %d\n", __func__, __LINE__, err);
1477 		goto out;
1478 	}
1479 
1480 	ftp->l3_proto = state.l3_proto;
1481 
1482 	sparx5_tc_flower_simplify_rule(admin, vrule, state.l3_proto);
1483 
1484 	/* Find the keysets that the rule can use */
1485 	kslist.keysets = keysets;
1486 	kslist.max = ARRAY_SIZE(keysets);
1487 	if (!vcap_rule_find_keysets(vrule, &kslist)) {
1488 		pr_err("%s:%d: %s\n", __func__, __LINE__,
1489 		       "Could not find a suitable keyset");
1490 		err = -ENOENT;
1491 		goto out;
1492 	}
1493 
1494 	ftp->keyset = vcap_select_min_rule_keyset(vctrl, admin->vtype, &kslist);
1495 	kslist.cnt = 0;
1496 	sparx5_vcap_set_port_keyset(ndev, admin, fco->common.chain_index,
1497 				    state.l3_proto,
1498 				    ftp->keyset,
1499 				    &kslist);
1500 
1501 	if (kslist.cnt > 0)
1502 		ftp->orig = kslist.keysets[0];
1503 
1504 	/* Store new template */
1505 	list_add_tail(&ftp->list, &port->tc_templates);
1506 	vcap_free_rule(vrule);
1507 	return 0;
1508 
1509 out:
1510 	vcap_free_rule(vrule);
1511 err_rule:
1512 	kfree(ftp);
1513 	return err;
1514 }
1515 
1516 static int sparx5_tc_flower_template_destroy(struct net_device *ndev,
1517 					     struct flow_cls_offload *fco,
1518 					     struct vcap_admin *admin)
1519 {
1520 	struct sparx5_port *port = netdev_priv(ndev);
1521 	struct sparx5_tc_flower_template *ftp, *tmp;
1522 	int err = -ENOENT;
1523 
1524 	/* Rules using the template are removed by the tc framework */
1525 	list_for_each_entry_safe(ftp, tmp, &port->tc_templates, list) {
1526 		if (ftp->cid != fco->common.chain_index)
1527 			continue;
1528 
1529 		sparx5_vcap_set_port_keyset(ndev, admin,
1530 					    fco->common.chain_index,
1531 					    ftp->l3_proto, ftp->orig,
1532 					    NULL);
1533 		list_del(&ftp->list);
1534 		kfree(ftp);
1535 		break;
1536 	}
1537 	return err;
1538 }
1539 
1540 int sparx5_tc_flower(struct net_device *ndev, struct flow_cls_offload *fco,
1541 		     bool ingress)
1542 {
1543 	struct sparx5_port *port = netdev_priv(ndev);
1544 	struct vcap_control *vctrl;
1545 	struct vcap_admin *admin;
1546 	int err = -EINVAL;
1547 
1548 	/* Get vcap instance from the chain id */
1549 	vctrl = port->sparx5->vcap_ctrl;
1550 	admin = vcap_find_admin(vctrl, fco->common.chain_index);
1551 	if (!admin) {
1552 		NL_SET_ERR_MSG_MOD(fco->common.extack, "Invalid chain");
1553 		return err;
1554 	}
1555 
1556 	switch (fco->command) {
1557 	case FLOW_CLS_REPLACE:
1558 		return sparx5_tc_flower_replace(ndev, fco, admin, ingress);
1559 	case FLOW_CLS_DESTROY:
1560 		return sparx5_tc_flower_destroy(ndev, fco, admin);
1561 	case FLOW_CLS_STATS:
1562 		return sparx5_tc_flower_stats(ndev, fco, admin);
1563 	case FLOW_CLS_TMPLT_CREATE:
1564 		return sparx5_tc_flower_template_create(ndev, fco, admin);
1565 	case FLOW_CLS_TMPLT_DESTROY:
1566 		return sparx5_tc_flower_template_destroy(ndev, fco, admin);
1567 	default:
1568 		return -EOPNOTSUPP;
1569 	}
1570 }
1571