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