Merge branch 'rework/misc-cleanups' into for-linus
[linux-block.git] / drivers / net / ethernet / microchip / sparx5 / sparx5_tc_flower.c
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 /* Remove rule keys that may prevent templates from matching a keyset */
1008 static void sparx5_tc_flower_simplify_rule(struct vcap_admin *admin,
1009                                            struct vcap_rule *vrule,
1010                                            u16 l3_proto)
1011 {
1012         switch (admin->vtype) {
1013         case VCAP_TYPE_IS0:
1014                 vcap_rule_rem_key(vrule, VCAP_KF_ETYPE);
1015                 switch (l3_proto) {
1016                 case ETH_P_IP:
1017                         break;
1018                 case ETH_P_IPV6:
1019                         vcap_rule_rem_key(vrule, VCAP_KF_IP_SNAP_IS);
1020                         break;
1021                 default:
1022                         break;
1023                 }
1024                 break;
1025         case VCAP_TYPE_ES2:
1026                 switch (l3_proto) {
1027                 case ETH_P_IP:
1028                         if (vrule->keyset == VCAP_KFS_IP4_OTHER)
1029                                 vcap_rule_rem_key(vrule, VCAP_KF_TCP_IS);
1030                         break;
1031                 case ETH_P_IPV6:
1032                         if (vrule->keyset == VCAP_KFS_IP6_STD)
1033                                 vcap_rule_rem_key(vrule, VCAP_KF_TCP_IS);
1034                         vcap_rule_rem_key(vrule, VCAP_KF_IP4_IS);
1035                         break;
1036                 default:
1037                         break;
1038                 }
1039                 break;
1040         case VCAP_TYPE_IS2:
1041                 switch (l3_proto) {
1042                 case ETH_P_IP:
1043                 case ETH_P_IPV6:
1044                         vcap_rule_rem_key(vrule, VCAP_KF_IP4_IS);
1045                         break;
1046                 default:
1047                         break;
1048                 }
1049                 break;
1050         default:
1051                 break;
1052         }
1053 }
1054
1055 static bool sparx5_tc_flower_use_template(struct net_device *ndev,
1056                                           struct flow_cls_offload *fco,
1057                                           struct vcap_admin *admin,
1058                                           struct vcap_rule *vrule)
1059 {
1060         struct sparx5_port *port = netdev_priv(ndev);
1061         struct sparx5_tc_flower_template *ftp;
1062
1063         list_for_each_entry(ftp, &port->tc_templates, list) {
1064                 if (ftp->cid != fco->common.chain_index)
1065                         continue;
1066
1067                 vcap_set_rule_set_keyset(vrule, ftp->keyset);
1068                 sparx5_tc_flower_simplify_rule(admin, vrule, ftp->l3_proto);
1069                 return true;
1070         }
1071         return false;
1072 }
1073
1074 static int sparx5_tc_flower_replace(struct net_device *ndev,
1075                                     struct flow_cls_offload *fco,
1076                                     struct vcap_admin *admin,
1077                                     bool ingress)
1078 {
1079         struct sparx5_psfp_sf sf = { .max_sdu = SPX5_PSFP_SF_MAX_SDU };
1080         struct netlink_ext_ack *extack = fco->common.extack;
1081         int err, idx, tc_sg_idx = -1, tc_pol_idx = -1;
1082         struct vcap_tc_flower_parse_usage state = {
1083                 .fco = fco,
1084                 .l3_proto = ETH_P_ALL,
1085                 .admin = admin,
1086         };
1087         struct sparx5_port *port = netdev_priv(ndev);
1088         struct sparx5_multiple_rules multi = {};
1089         struct sparx5 *sparx5 = port->sparx5;
1090         struct sparx5_psfp_sg sg = { 0 };
1091         struct sparx5_psfp_fm fm = { 0 };
1092         struct flow_action_entry *act;
1093         struct vcap_control *vctrl;
1094         struct flow_rule *frule;
1095         struct vcap_rule *vrule;
1096
1097         vctrl = port->sparx5->vcap_ctrl;
1098
1099         err = sparx5_tc_flower_action_check(vctrl, ndev, fco, ingress);
1100         if (err)
1101                 return err;
1102
1103         vrule = vcap_alloc_rule(vctrl, ndev, fco->common.chain_index, VCAP_USER_TC,
1104                                 fco->common.prio, 0);
1105         if (IS_ERR(vrule))
1106                 return PTR_ERR(vrule);
1107
1108         vrule->cookie = fco->cookie;
1109
1110         state.vrule = vrule;
1111         state.frule = flow_cls_offload_flow_rule(fco);
1112         err = sparx5_tc_use_dissectors(&state, admin, vrule);
1113         if (err)
1114                 goto out;
1115
1116         err = sparx5_tc_add_rule_counter(admin, vrule);
1117         if (err)
1118                 goto out;
1119
1120         err = sparx5_tc_add_rule_link_target(admin, vrule,
1121                                              fco->common.chain_index);
1122         if (err)
1123                 goto out;
1124
1125         frule = flow_cls_offload_flow_rule(fco);
1126         flow_action_for_each(idx, act, &frule->action) {
1127                 switch (act->id) {
1128                 case FLOW_ACTION_GATE: {
1129                         err = sparx5_tc_flower_parse_act_gate(&sg, act, extack);
1130                         if (err < 0)
1131                                 goto out;
1132
1133                         tc_sg_idx = act->hw_index;
1134
1135                         break;
1136                 }
1137                 case FLOW_ACTION_POLICE: {
1138                         err = sparx5_tc_flower_parse_act_police(&fm.pol, act,
1139                                                                 extack);
1140                         if (err < 0)
1141                                 goto out;
1142
1143                         tc_pol_idx = fm.pol.idx;
1144                         sf.max_sdu = act->police.mtu;
1145
1146                         break;
1147                 }
1148                 case FLOW_ACTION_TRAP:
1149                         err = sparx5_tc_action_trap(admin, vrule, fco);
1150                         if (err)
1151                                 goto out;
1152                         break;
1153                 case FLOW_ACTION_ACCEPT:
1154                         err = sparx5_tc_set_actionset(admin, vrule);
1155                         if (err)
1156                                 goto out;
1157                         break;
1158                 case FLOW_ACTION_GOTO:
1159                         err = sparx5_tc_set_actionset(admin, vrule);
1160                         if (err)
1161                                 goto out;
1162                         sparx5_tc_add_rule_link(vctrl, admin, vrule,
1163                                                 fco->common.chain_index,
1164                                                 act->chain_index);
1165                         break;
1166                 case FLOW_ACTION_VLAN_POP:
1167                         err = sparx5_tc_action_vlan_pop(admin, vrule, fco,
1168                                                         state.tpid);
1169                         if (err)
1170                                 goto out;
1171                         break;
1172                 case FLOW_ACTION_VLAN_PUSH:
1173                         err = sparx5_tc_action_vlan_push(admin, vrule, fco,
1174                                                          act, state.tpid);
1175                         if (err)
1176                                 goto out;
1177                         break;
1178                 case FLOW_ACTION_VLAN_MANGLE:
1179                         err = sparx5_tc_action_vlan_modify(admin, vrule, fco,
1180                                                            act, state.tpid);
1181                         if (err)
1182                                 goto out;
1183                         break;
1184                 default:
1185                         NL_SET_ERR_MSG_MOD(fco->common.extack,
1186                                            "Unsupported TC action");
1187                         err = -EOPNOTSUPP;
1188                         goto out;
1189                 }
1190         }
1191
1192         /* Setup PSFP */
1193         if (tc_sg_idx >= 0 || tc_pol_idx >= 0) {
1194                 err = sparx5_tc_flower_psfp_setup(sparx5, vrule, tc_sg_idx,
1195                                                   tc_pol_idx, &sg, &fm, &sf);
1196                 if (err)
1197                         goto out;
1198         }
1199
1200         if (!sparx5_tc_flower_use_template(ndev, fco, admin, vrule)) {
1201                 err = sparx5_tc_select_protocol_keyset(ndev, vrule, admin,
1202                                                        state.l3_proto, &multi);
1203                 if (err) {
1204                         NL_SET_ERR_MSG_MOD(fco->common.extack,
1205                                            "No matching port keyset for filter protocol and keys");
1206                         goto out;
1207                 }
1208         }
1209
1210         /* provide the l3 protocol to guide the keyset selection */
1211         err = vcap_val_rule(vrule, state.l3_proto);
1212         if (err) {
1213                 vcap_set_tc_exterr(fco, vrule);
1214                 goto out;
1215         }
1216         err = vcap_add_rule(vrule);
1217         if (err)
1218                 NL_SET_ERR_MSG_MOD(fco->common.extack,
1219                                    "Could not add the filter");
1220
1221         if (state.l3_proto == ETH_P_ALL)
1222                 err = sparx5_tc_add_remaining_rules(vctrl, fco, vrule, admin,
1223                                                     &multi);
1224
1225 out:
1226         vcap_free_rule(vrule);
1227         return err;
1228 }
1229
1230 static void sparx5_tc_free_psfp_resources(struct sparx5 *sparx5,
1231                                           struct vcap_rule *vrule)
1232 {
1233         struct vcap_client_actionfield *afield;
1234         u32 isdx, sfid, sgid, fmid;
1235
1236         /* Check if VCAP_AF_ISDX_VAL action is set for this rule - and if
1237          * it is used for stream and/or flow-meter classification.
1238          */
1239         afield = vcap_find_actionfield(vrule, VCAP_AF_ISDX_VAL);
1240         if (!afield)
1241                 return;
1242
1243         isdx = afield->data.u32.value;
1244         sfid = sparx5_psfp_isdx_get_sf(sparx5, isdx);
1245
1246         if (!sfid)
1247                 return;
1248
1249         fmid = sparx5_psfp_isdx_get_fm(sparx5, isdx);
1250         sgid = sparx5_psfp_sf_get_sg(sparx5, sfid);
1251
1252         if (fmid && sparx5_psfp_fm_del(sparx5, fmid) < 0)
1253                 pr_err("%s:%d Could not delete invalid fmid: %d", __func__,
1254                        __LINE__, fmid);
1255
1256         if (sgid && sparx5_psfp_sg_del(sparx5, sgid) < 0)
1257                 pr_err("%s:%d Could not delete invalid sgid: %d", __func__,
1258                        __LINE__, sgid);
1259
1260         if (sparx5_psfp_sf_del(sparx5, sfid) < 0)
1261                 pr_err("%s:%d Could not delete invalid sfid: %d", __func__,
1262                        __LINE__, sfid);
1263
1264         sparx5_isdx_conf_set(sparx5, isdx, 0, 0);
1265 }
1266
1267 static int sparx5_tc_free_rule_resources(struct net_device *ndev,
1268                                          struct vcap_control *vctrl,
1269                                          int rule_id)
1270 {
1271         struct sparx5_port *port = netdev_priv(ndev);
1272         struct sparx5 *sparx5 = port->sparx5;
1273         struct vcap_rule *vrule;
1274         int ret = 0;
1275
1276         vrule = vcap_get_rule(vctrl, rule_id);
1277         if (IS_ERR(vrule))
1278                 return -EINVAL;
1279
1280         sparx5_tc_free_psfp_resources(sparx5, vrule);
1281
1282         vcap_free_rule(vrule);
1283         return ret;
1284 }
1285
1286 static int sparx5_tc_flower_destroy(struct net_device *ndev,
1287                                     struct flow_cls_offload *fco,
1288                                     struct vcap_admin *admin)
1289 {
1290         struct sparx5_port *port = netdev_priv(ndev);
1291         int err = -ENOENT, count = 0, rule_id;
1292         struct vcap_control *vctrl;
1293
1294         vctrl = port->sparx5->vcap_ctrl;
1295         while (true) {
1296                 rule_id = vcap_lookup_rule_by_cookie(vctrl, fco->cookie);
1297                 if (rule_id <= 0)
1298                         break;
1299                 if (count == 0) {
1300                         /* Resources are attached to the first rule of
1301                          * a set of rules. Only works if the rules are
1302                          * in the correct order.
1303                          */
1304                         err = sparx5_tc_free_rule_resources(ndev, vctrl,
1305                                                             rule_id);
1306                         if (err)
1307                                 pr_err("%s:%d: could not free resources %d\n",
1308                                        __func__, __LINE__, rule_id);
1309                 }
1310                 err = vcap_del_rule(vctrl, ndev, rule_id);
1311                 if (err) {
1312                         pr_err("%s:%d: could not delete rule %d\n",
1313                                __func__, __LINE__, rule_id);
1314                         break;
1315                 }
1316         }
1317         return err;
1318 }
1319
1320 static int sparx5_tc_flower_stats(struct net_device *ndev,
1321                                   struct flow_cls_offload *fco,
1322                                   struct vcap_admin *admin)
1323 {
1324         struct sparx5_port *port = netdev_priv(ndev);
1325         struct vcap_counter ctr = {};
1326         struct vcap_control *vctrl;
1327         ulong lastused = 0;
1328         int err;
1329
1330         vctrl = port->sparx5->vcap_ctrl;
1331         err = vcap_get_rule_count_by_cookie(vctrl, &ctr, fco->cookie);
1332         if (err)
1333                 return err;
1334         flow_stats_update(&fco->stats, 0x0, ctr.value, 0, lastused,
1335                           FLOW_ACTION_HW_STATS_IMMEDIATE);
1336         return err;
1337 }
1338
1339 static int sparx5_tc_flower_template_create(struct net_device *ndev,
1340                                             struct flow_cls_offload *fco,
1341                                             struct vcap_admin *admin)
1342 {
1343         struct sparx5_port *port = netdev_priv(ndev);
1344         struct vcap_tc_flower_parse_usage state = {
1345                 .fco = fco,
1346                 .l3_proto = ETH_P_ALL,
1347                 .admin = admin,
1348         };
1349         struct sparx5_tc_flower_template *ftp;
1350         struct vcap_keyset_list kslist = {};
1351         enum vcap_keyfield_set keysets[10];
1352         struct vcap_control *vctrl;
1353         struct vcap_rule *vrule;
1354         int count, err;
1355
1356         if (admin->vtype == VCAP_TYPE_ES0) {
1357                 pr_err("%s:%d: %s\n", __func__, __LINE__,
1358                        "VCAP does not support templates");
1359                 return -EINVAL;
1360         }
1361
1362         count = vcap_admin_rule_count(admin, fco->common.chain_index);
1363         if (count > 0) {
1364                 pr_err("%s:%d: %s\n", __func__, __LINE__,
1365                        "Filters are already present");
1366                 return -EBUSY;
1367         }
1368
1369         ftp = kzalloc(sizeof(*ftp), GFP_KERNEL);
1370         if (!ftp)
1371                 return -ENOMEM;
1372
1373         ftp->cid = fco->common.chain_index;
1374         ftp->orig = VCAP_KFS_NO_VALUE;
1375         ftp->keyset = VCAP_KFS_NO_VALUE;
1376
1377         vctrl = port->sparx5->vcap_ctrl;
1378         vrule = vcap_alloc_rule(vctrl, ndev, fco->common.chain_index,
1379                                 VCAP_USER_TC, fco->common.prio, 0);
1380         if (IS_ERR(vrule)) {
1381                 err = PTR_ERR(vrule);
1382                 goto err_rule;
1383         }
1384
1385         state.vrule = vrule;
1386         state.frule = flow_cls_offload_flow_rule(fco);
1387         err = sparx5_tc_use_dissectors(&state, admin, vrule);
1388         if (err) {
1389                 pr_err("%s:%d: key error: %d\n", __func__, __LINE__, err);
1390                 goto out;
1391         }
1392
1393         ftp->l3_proto = state.l3_proto;
1394
1395         sparx5_tc_flower_simplify_rule(admin, vrule, state.l3_proto);
1396
1397         /* Find the keysets that the rule can use */
1398         kslist.keysets = keysets;
1399         kslist.max = ARRAY_SIZE(keysets);
1400         if (!vcap_rule_find_keysets(vrule, &kslist)) {
1401                 pr_err("%s:%d: %s\n", __func__, __LINE__,
1402                        "Could not find a suitable keyset");
1403                 err = -ENOENT;
1404                 goto out;
1405         }
1406
1407         ftp->keyset = vcap_select_min_rule_keyset(vctrl, admin->vtype, &kslist);
1408         kslist.cnt = 0;
1409         sparx5_vcap_set_port_keyset(ndev, admin, fco->common.chain_index,
1410                                     state.l3_proto,
1411                                     ftp->keyset,
1412                                     &kslist);
1413
1414         if (kslist.cnt > 0)
1415                 ftp->orig = kslist.keysets[0];
1416
1417         /* Store new template */
1418         list_add_tail(&ftp->list, &port->tc_templates);
1419         vcap_free_rule(vrule);
1420         return 0;
1421
1422 out:
1423         vcap_free_rule(vrule);
1424 err_rule:
1425         kfree(ftp);
1426         return err;
1427 }
1428
1429 static int sparx5_tc_flower_template_destroy(struct net_device *ndev,
1430                                              struct flow_cls_offload *fco,
1431                                              struct vcap_admin *admin)
1432 {
1433         struct sparx5_port *port = netdev_priv(ndev);
1434         struct sparx5_tc_flower_template *ftp, *tmp;
1435         int err = -ENOENT;
1436
1437         /* Rules using the template are removed by the tc framework */
1438         list_for_each_entry_safe(ftp, tmp, &port->tc_templates, list) {
1439                 if (ftp->cid != fco->common.chain_index)
1440                         continue;
1441
1442                 sparx5_vcap_set_port_keyset(ndev, admin,
1443                                             fco->common.chain_index,
1444                                             ftp->l3_proto, ftp->orig,
1445                                             NULL);
1446                 list_del(&ftp->list);
1447                 kfree(ftp);
1448                 break;
1449         }
1450         return err;
1451 }
1452
1453 int sparx5_tc_flower(struct net_device *ndev, struct flow_cls_offload *fco,
1454                      bool ingress)
1455 {
1456         struct sparx5_port *port = netdev_priv(ndev);
1457         struct vcap_control *vctrl;
1458         struct vcap_admin *admin;
1459         int err = -EINVAL;
1460
1461         /* Get vcap instance from the chain id */
1462         vctrl = port->sparx5->vcap_ctrl;
1463         admin = vcap_find_admin(vctrl, fco->common.chain_index);
1464         if (!admin) {
1465                 NL_SET_ERR_MSG_MOD(fco->common.extack, "Invalid chain");
1466                 return err;
1467         }
1468
1469         switch (fco->command) {
1470         case FLOW_CLS_REPLACE:
1471                 return sparx5_tc_flower_replace(ndev, fco, admin, ingress);
1472         case FLOW_CLS_DESTROY:
1473                 return sparx5_tc_flower_destroy(ndev, fco, admin);
1474         case FLOW_CLS_STATS:
1475                 return sparx5_tc_flower_stats(ndev, fco, admin);
1476         case FLOW_CLS_TMPLT_CREATE:
1477                 return sparx5_tc_flower_template_create(ndev, fco, admin);
1478         case FLOW_CLS_TMPLT_DESTROY:
1479                 return sparx5_tc_flower_template_destroy(ndev, fco, admin);
1480         default:
1481                 return -EOPNOTSUPP;
1482         }
1483 }