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