GNU Linux-libre 6.8.7-gnu
[releases.git] / drivers / net / ethernet / freescale / dpaa2 / dpaa2-switch-flower.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * DPAA2 Ethernet Switch flower support
4  *
5  * Copyright 2021 NXP
6  *
7  */
8
9 #include "dpaa2-switch.h"
10
11 static int dpaa2_switch_flower_parse_key(struct flow_cls_offload *cls,
12                                          struct dpsw_acl_key *acl_key)
13 {
14         struct flow_rule *rule = flow_cls_offload_flow_rule(cls);
15         struct flow_dissector *dissector = rule->match.dissector;
16         struct netlink_ext_ack *extack = cls->common.extack;
17         struct dpsw_acl_fields *acl_h, *acl_m;
18
19         if (dissector->used_keys &
20             ~(BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) |
21               BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) |
22               BIT_ULL(FLOW_DISSECTOR_KEY_ETH_ADDRS) |
23               BIT_ULL(FLOW_DISSECTOR_KEY_VLAN) |
24               BIT_ULL(FLOW_DISSECTOR_KEY_PORTS) |
25               BIT_ULL(FLOW_DISSECTOR_KEY_IP) |
26               BIT_ULL(FLOW_DISSECTOR_KEY_IPV6_ADDRS) |
27               BIT_ULL(FLOW_DISSECTOR_KEY_IPV4_ADDRS))) {
28                 NL_SET_ERR_MSG_MOD(extack,
29                                    "Unsupported keys used");
30                 return -EOPNOTSUPP;
31         }
32
33         acl_h = &acl_key->match;
34         acl_m = &acl_key->mask;
35
36         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
37                 struct flow_match_basic match;
38
39                 flow_rule_match_basic(rule, &match);
40                 acl_h->l3_protocol = match.key->ip_proto;
41                 acl_h->l2_ether_type = be16_to_cpu(match.key->n_proto);
42                 acl_m->l3_protocol = match.mask->ip_proto;
43                 acl_m->l2_ether_type = be16_to_cpu(match.mask->n_proto);
44         }
45
46         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
47                 struct flow_match_eth_addrs match;
48
49                 flow_rule_match_eth_addrs(rule, &match);
50                 ether_addr_copy(acl_h->l2_dest_mac, &match.key->dst[0]);
51                 ether_addr_copy(acl_h->l2_source_mac, &match.key->src[0]);
52                 ether_addr_copy(acl_m->l2_dest_mac, &match.mask->dst[0]);
53                 ether_addr_copy(acl_m->l2_source_mac, &match.mask->src[0]);
54         }
55
56         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
57                 struct flow_match_vlan match;
58
59                 flow_rule_match_vlan(rule, &match);
60                 acl_h->l2_vlan_id = match.key->vlan_id;
61                 acl_h->l2_tpid = be16_to_cpu(match.key->vlan_tpid);
62                 acl_h->l2_pcp_dei = match.key->vlan_priority << 1 |
63                                     match.key->vlan_dei;
64
65                 acl_m->l2_vlan_id = match.mask->vlan_id;
66                 acl_m->l2_tpid = be16_to_cpu(match.mask->vlan_tpid);
67                 acl_m->l2_pcp_dei = match.mask->vlan_priority << 1 |
68                                     match.mask->vlan_dei;
69         }
70
71         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
72                 struct flow_match_ipv4_addrs match;
73
74                 flow_rule_match_ipv4_addrs(rule, &match);
75                 acl_h->l3_source_ip = be32_to_cpu(match.key->src);
76                 acl_h->l3_dest_ip = be32_to_cpu(match.key->dst);
77                 acl_m->l3_source_ip = be32_to_cpu(match.mask->src);
78                 acl_m->l3_dest_ip = be32_to_cpu(match.mask->dst);
79         }
80
81         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
82                 struct flow_match_ports match;
83
84                 flow_rule_match_ports(rule, &match);
85                 acl_h->l4_source_port = be16_to_cpu(match.key->src);
86                 acl_h->l4_dest_port = be16_to_cpu(match.key->dst);
87                 acl_m->l4_source_port = be16_to_cpu(match.mask->src);
88                 acl_m->l4_dest_port = be16_to_cpu(match.mask->dst);
89         }
90
91         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
92                 struct flow_match_ip match;
93
94                 flow_rule_match_ip(rule, &match);
95                 if (match.mask->ttl != 0) {
96                         NL_SET_ERR_MSG_MOD(extack,
97                                            "Matching on TTL not supported");
98                         return -EOPNOTSUPP;
99                 }
100
101                 if ((match.mask->tos & 0x3) != 0) {
102                         NL_SET_ERR_MSG_MOD(extack,
103                                            "Matching on ECN not supported, only DSCP");
104                         return -EOPNOTSUPP;
105                 }
106
107                 acl_h->l3_dscp = match.key->tos >> 2;
108                 acl_m->l3_dscp = match.mask->tos >> 2;
109         }
110
111         return 0;
112 }
113
114 int dpaa2_switch_acl_entry_add(struct dpaa2_switch_filter_block *filter_block,
115                                struct dpaa2_switch_acl_entry *entry)
116 {
117         struct dpsw_acl_entry_cfg *acl_entry_cfg = &entry->cfg;
118         struct ethsw_core *ethsw = filter_block->ethsw;
119         struct dpsw_acl_key *acl_key = &entry->key;
120         struct device *dev = ethsw->dev;
121         u8 *cmd_buff;
122         int err;
123
124         cmd_buff = kzalloc(DPAA2_ETHSW_PORT_ACL_CMD_BUF_SIZE, GFP_KERNEL);
125         if (!cmd_buff)
126                 return -ENOMEM;
127
128         dpsw_acl_prepare_entry_cfg(acl_key, cmd_buff);
129
130         acl_entry_cfg->key_iova = dma_map_single(dev, cmd_buff,
131                                                  DPAA2_ETHSW_PORT_ACL_CMD_BUF_SIZE,
132                                                  DMA_TO_DEVICE);
133         if (unlikely(dma_mapping_error(dev, acl_entry_cfg->key_iova))) {
134                 dev_err(dev, "DMA mapping failed\n");
135                 kfree(cmd_buff);
136                 return -EFAULT;
137         }
138
139         err = dpsw_acl_add_entry(ethsw->mc_io, 0, ethsw->dpsw_handle,
140                                  filter_block->acl_id, acl_entry_cfg);
141
142         dma_unmap_single(dev, acl_entry_cfg->key_iova,
143                          DPAA2_ETHSW_PORT_ACL_CMD_BUF_SIZE,
144                          DMA_TO_DEVICE);
145         if (err) {
146                 dev_err(dev, "dpsw_acl_add_entry() failed %d\n", err);
147                 kfree(cmd_buff);
148                 return err;
149         }
150
151         kfree(cmd_buff);
152
153         return 0;
154 }
155
156 static int
157 dpaa2_switch_acl_entry_remove(struct dpaa2_switch_filter_block *block,
158                               struct dpaa2_switch_acl_entry *entry)
159 {
160         struct dpsw_acl_entry_cfg *acl_entry_cfg = &entry->cfg;
161         struct dpsw_acl_key *acl_key = &entry->key;
162         struct ethsw_core *ethsw = block->ethsw;
163         struct device *dev = ethsw->dev;
164         u8 *cmd_buff;
165         int err;
166
167         cmd_buff = kzalloc(DPAA2_ETHSW_PORT_ACL_CMD_BUF_SIZE, GFP_KERNEL);
168         if (!cmd_buff)
169                 return -ENOMEM;
170
171         dpsw_acl_prepare_entry_cfg(acl_key, cmd_buff);
172
173         acl_entry_cfg->key_iova = dma_map_single(dev, cmd_buff,
174                                                  DPAA2_ETHSW_PORT_ACL_CMD_BUF_SIZE,
175                                                  DMA_TO_DEVICE);
176         if (unlikely(dma_mapping_error(dev, acl_entry_cfg->key_iova))) {
177                 dev_err(dev, "DMA mapping failed\n");
178                 kfree(cmd_buff);
179                 return -EFAULT;
180         }
181
182         err = dpsw_acl_remove_entry(ethsw->mc_io, 0, ethsw->dpsw_handle,
183                                     block->acl_id, acl_entry_cfg);
184
185         dma_unmap_single(dev, acl_entry_cfg->key_iova,
186                          DPAA2_ETHSW_PORT_ACL_CMD_BUF_SIZE, DMA_TO_DEVICE);
187         if (err) {
188                 dev_err(dev, "dpsw_acl_remove_entry() failed %d\n", err);
189                 kfree(cmd_buff);
190                 return err;
191         }
192
193         kfree(cmd_buff);
194
195         return 0;
196 }
197
198 static int
199 dpaa2_switch_acl_entry_add_to_list(struct dpaa2_switch_filter_block *block,
200                                    struct dpaa2_switch_acl_entry *entry)
201 {
202         struct dpaa2_switch_acl_entry *tmp;
203         struct list_head *pos, *n;
204         int index = 0;
205
206         if (list_empty(&block->acl_entries)) {
207                 list_add(&entry->list, &block->acl_entries);
208                 return index;
209         }
210
211         list_for_each_safe(pos, n, &block->acl_entries) {
212                 tmp = list_entry(pos, struct dpaa2_switch_acl_entry, list);
213                 if (entry->prio < tmp->prio)
214                         break;
215                 index++;
216         }
217         list_add(&entry->list, pos->prev);
218         return index;
219 }
220
221 static struct dpaa2_switch_acl_entry*
222 dpaa2_switch_acl_entry_get_by_index(struct dpaa2_switch_filter_block *block,
223                                     int index)
224 {
225         struct dpaa2_switch_acl_entry *tmp;
226         int i = 0;
227
228         list_for_each_entry(tmp, &block->acl_entries, list) {
229                 if (i == index)
230                         return tmp;
231                 ++i;
232         }
233
234         return NULL;
235 }
236
237 static int
238 dpaa2_switch_acl_entry_set_precedence(struct dpaa2_switch_filter_block *block,
239                                       struct dpaa2_switch_acl_entry *entry,
240                                       int precedence)
241 {
242         int err;
243
244         err = dpaa2_switch_acl_entry_remove(block, entry);
245         if (err)
246                 return err;
247
248         entry->cfg.precedence = precedence;
249         return dpaa2_switch_acl_entry_add(block, entry);
250 }
251
252 static int
253 dpaa2_switch_acl_tbl_add_entry(struct dpaa2_switch_filter_block *block,
254                                struct dpaa2_switch_acl_entry *entry)
255 {
256         struct dpaa2_switch_acl_entry *tmp;
257         int index, i, precedence, err;
258
259         /* Add the new ACL entry to the linked list and get its index */
260         index = dpaa2_switch_acl_entry_add_to_list(block, entry);
261
262         /* Move up in priority the ACL entries to make space
263          * for the new filter.
264          */
265         precedence = DPAA2_ETHSW_PORT_MAX_ACL_ENTRIES - block->num_acl_rules - 1;
266         for (i = 0; i < index; i++) {
267                 tmp = dpaa2_switch_acl_entry_get_by_index(block, i);
268
269                 err = dpaa2_switch_acl_entry_set_precedence(block, tmp,
270                                                             precedence);
271                 if (err)
272                         return err;
273
274                 precedence++;
275         }
276
277         /* Add the new entry to hardware */
278         entry->cfg.precedence = precedence;
279         err = dpaa2_switch_acl_entry_add(block, entry);
280         block->num_acl_rules++;
281
282         return err;
283 }
284
285 static struct dpaa2_switch_acl_entry *
286 dpaa2_switch_acl_tbl_find_entry_by_cookie(struct dpaa2_switch_filter_block *block,
287                                           unsigned long cookie)
288 {
289         struct dpaa2_switch_acl_entry *tmp, *n;
290
291         list_for_each_entry_safe(tmp, n, &block->acl_entries, list) {
292                 if (tmp->cookie == cookie)
293                         return tmp;
294         }
295         return NULL;
296 }
297
298 static int
299 dpaa2_switch_acl_entry_get_index(struct dpaa2_switch_filter_block *block,
300                                  struct dpaa2_switch_acl_entry *entry)
301 {
302         struct dpaa2_switch_acl_entry *tmp, *n;
303         int index = 0;
304
305         list_for_each_entry_safe(tmp, n, &block->acl_entries, list) {
306                 if (tmp->cookie == entry->cookie)
307                         return index;
308                 index++;
309         }
310         return -ENOENT;
311 }
312
313 static struct dpaa2_switch_mirror_entry *
314 dpaa2_switch_mirror_find_entry_by_cookie(struct dpaa2_switch_filter_block *block,
315                                          unsigned long cookie)
316 {
317         struct dpaa2_switch_mirror_entry *tmp, *n;
318
319         list_for_each_entry_safe(tmp, n, &block->mirror_entries, list) {
320                 if (tmp->cookie == cookie)
321                         return tmp;
322         }
323         return NULL;
324 }
325
326 static int
327 dpaa2_switch_acl_tbl_remove_entry(struct dpaa2_switch_filter_block *block,
328                                   struct dpaa2_switch_acl_entry *entry)
329 {
330         struct dpaa2_switch_acl_entry *tmp;
331         int index, i, precedence, err;
332
333         index = dpaa2_switch_acl_entry_get_index(block, entry);
334
335         /* Remove from hardware the ACL entry */
336         err = dpaa2_switch_acl_entry_remove(block, entry);
337         if (err)
338                 return err;
339
340         block->num_acl_rules--;
341
342         /* Remove it from the list also */
343         list_del(&entry->list);
344
345         /* Move down in priority the entries over the deleted one */
346         precedence = entry->cfg.precedence;
347         for (i = index - 1; i >= 0; i--) {
348                 tmp = dpaa2_switch_acl_entry_get_by_index(block, i);
349                 err = dpaa2_switch_acl_entry_set_precedence(block, tmp,
350                                                             precedence);
351                 if (err)
352                         return err;
353
354                 precedence--;
355         }
356
357         kfree(entry);
358
359         return 0;
360 }
361
362 static int dpaa2_switch_tc_parse_action_acl(struct ethsw_core *ethsw,
363                                             struct flow_action_entry *cls_act,
364                                             struct dpsw_acl_result *dpsw_act,
365                                             struct netlink_ext_ack *extack)
366 {
367         int err = 0;
368
369         switch (cls_act->id) {
370         case FLOW_ACTION_TRAP:
371                 dpsw_act->action = DPSW_ACL_ACTION_REDIRECT_TO_CTRL_IF;
372                 break;
373         case FLOW_ACTION_REDIRECT:
374                 if (!dpaa2_switch_port_dev_check(cls_act->dev)) {
375                         NL_SET_ERR_MSG_MOD(extack,
376                                            "Destination not a DPAA2 switch port");
377                         return -EOPNOTSUPP;
378                 }
379
380                 dpsw_act->if_id = dpaa2_switch_get_index(ethsw, cls_act->dev);
381                 dpsw_act->action = DPSW_ACL_ACTION_REDIRECT;
382                 break;
383         case FLOW_ACTION_DROP:
384                 dpsw_act->action = DPSW_ACL_ACTION_DROP;
385                 break;
386         default:
387                 NL_SET_ERR_MSG_MOD(extack,
388                                    "Action not supported");
389                 err = -EOPNOTSUPP;
390                 goto out;
391         }
392
393 out:
394         return err;
395 }
396
397 static int
398 dpaa2_switch_block_add_mirror(struct dpaa2_switch_filter_block *block,
399                               struct dpaa2_switch_mirror_entry *entry,
400                               u16 to, struct netlink_ext_ack *extack)
401 {
402         unsigned long block_ports = block->ports;
403         struct ethsw_core *ethsw = block->ethsw;
404         struct ethsw_port_priv *port_priv;
405         unsigned long ports_added = 0;
406         u16 vlan = entry->cfg.vlan_id;
407         bool mirror_port_enabled;
408         int err, port;
409
410         /* Setup the mirroring port */
411         mirror_port_enabled = (ethsw->mirror_port != ethsw->sw_attr.num_ifs);
412         if (!mirror_port_enabled) {
413                 err = dpsw_set_reflection_if(ethsw->mc_io, 0,
414                                              ethsw->dpsw_handle, to);
415                 if (err)
416                         return err;
417                 ethsw->mirror_port = to;
418         }
419
420         /* Setup the same egress mirroring configuration on all the switch
421          * ports that share the same filter block.
422          */
423         for_each_set_bit(port, &block_ports, ethsw->sw_attr.num_ifs) {
424                 port_priv = ethsw->ports[port];
425
426                 /* We cannot add a per VLAN mirroring rule if the VLAN in
427                  * question is not installed on the switch port.
428                  */
429                 if (entry->cfg.filter == DPSW_REFLECTION_FILTER_INGRESS_VLAN &&
430                     !(port_priv->vlans[vlan] & ETHSW_VLAN_MEMBER)) {
431                         NL_SET_ERR_MSG(extack,
432                                        "VLAN must be installed on the switch port");
433                         err = -EINVAL;
434                         goto err_remove_filters;
435                 }
436
437                 err = dpsw_if_add_reflection(ethsw->mc_io, 0,
438                                              ethsw->dpsw_handle,
439                                              port, &entry->cfg);
440                 if (err)
441                         goto err_remove_filters;
442
443                 ports_added |= BIT(port);
444         }
445
446         list_add(&entry->list, &block->mirror_entries);
447
448         return 0;
449
450 err_remove_filters:
451         for_each_set_bit(port, &ports_added, ethsw->sw_attr.num_ifs) {
452                 dpsw_if_remove_reflection(ethsw->mc_io, 0, ethsw->dpsw_handle,
453                                           port, &entry->cfg);
454         }
455
456         if (!mirror_port_enabled)
457                 ethsw->mirror_port = ethsw->sw_attr.num_ifs;
458
459         return err;
460 }
461
462 static int
463 dpaa2_switch_block_remove_mirror(struct dpaa2_switch_filter_block *block,
464                                  struct dpaa2_switch_mirror_entry *entry)
465 {
466         struct dpsw_reflection_cfg *cfg = &entry->cfg;
467         unsigned long block_ports = block->ports;
468         struct ethsw_core *ethsw = block->ethsw;
469         int port;
470
471         /* Remove this mirroring configuration from all the ports belonging to
472          * the filter block.
473          */
474         for_each_set_bit(port, &block_ports, ethsw->sw_attr.num_ifs)
475                 dpsw_if_remove_reflection(ethsw->mc_io, 0, ethsw->dpsw_handle,
476                                           port, cfg);
477
478         /* Also remove it from the list of mirror filters */
479         list_del(&entry->list);
480         kfree(entry);
481
482         /* If this was the last mirror filter, then unset the mirror port */
483         if (list_empty(&block->mirror_entries))
484                 ethsw->mirror_port =  ethsw->sw_attr.num_ifs;
485
486         return 0;
487 }
488
489 static int
490 dpaa2_switch_cls_flower_replace_acl(struct dpaa2_switch_filter_block *block,
491                                     struct flow_cls_offload *cls)
492 {
493         struct flow_rule *rule = flow_cls_offload_flow_rule(cls);
494         struct netlink_ext_ack *extack = cls->common.extack;
495         struct dpaa2_switch_acl_entry *acl_entry;
496         struct ethsw_core *ethsw = block->ethsw;
497         struct flow_action_entry *act;
498         int err;
499
500         if (dpaa2_switch_acl_tbl_is_full(block)) {
501                 NL_SET_ERR_MSG(extack, "Maximum filter capacity reached");
502                 return -ENOMEM;
503         }
504
505         acl_entry = kzalloc(sizeof(*acl_entry), GFP_KERNEL);
506         if (!acl_entry)
507                 return -ENOMEM;
508
509         err = dpaa2_switch_flower_parse_key(cls, &acl_entry->key);
510         if (err)
511                 goto free_acl_entry;
512
513         act = &rule->action.entries[0];
514         err = dpaa2_switch_tc_parse_action_acl(ethsw, act,
515                                                &acl_entry->cfg.result, extack);
516         if (err)
517                 goto free_acl_entry;
518
519         acl_entry->prio = cls->common.prio;
520         acl_entry->cookie = cls->cookie;
521
522         err = dpaa2_switch_acl_tbl_add_entry(block, acl_entry);
523         if (err)
524                 goto free_acl_entry;
525
526         return 0;
527
528 free_acl_entry:
529         kfree(acl_entry);
530
531         return err;
532 }
533
534 static int dpaa2_switch_flower_parse_mirror_key(struct flow_cls_offload *cls,
535                                                 u16 *vlan)
536 {
537         struct flow_rule *rule = flow_cls_offload_flow_rule(cls);
538         struct flow_dissector *dissector = rule->match.dissector;
539         struct netlink_ext_ack *extack = cls->common.extack;
540         int ret = -EOPNOTSUPP;
541
542         if (dissector->used_keys &
543             ~(BIT_ULL(FLOW_DISSECTOR_KEY_BASIC) |
544               BIT_ULL(FLOW_DISSECTOR_KEY_CONTROL) |
545               BIT_ULL(FLOW_DISSECTOR_KEY_VLAN))) {
546                 NL_SET_ERR_MSG_MOD(extack,
547                                    "Mirroring is supported only per VLAN");
548                 return -EOPNOTSUPP;
549         }
550
551         if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
552                 struct flow_match_vlan match;
553
554                 flow_rule_match_vlan(rule, &match);
555
556                 if (match.mask->vlan_priority != 0 ||
557                     match.mask->vlan_dei != 0) {
558                         NL_SET_ERR_MSG_MOD(extack,
559                                            "Only matching on VLAN ID supported");
560                         return -EOPNOTSUPP;
561                 }
562
563                 if (match.mask->vlan_id != 0xFFF) {
564                         NL_SET_ERR_MSG_MOD(extack,
565                                            "Masked matching not supported");
566                         return -EOPNOTSUPP;
567                 }
568
569                 *vlan = (u16)match.key->vlan_id;
570                 ret = 0;
571         }
572
573         return ret;
574 }
575
576 static int
577 dpaa2_switch_cls_flower_replace_mirror(struct dpaa2_switch_filter_block *block,
578                                        struct flow_cls_offload *cls)
579 {
580         struct netlink_ext_ack *extack = cls->common.extack;
581         struct dpaa2_switch_mirror_entry *mirror_entry;
582         struct ethsw_core *ethsw = block->ethsw;
583         struct dpaa2_switch_mirror_entry *tmp;
584         struct flow_action_entry *cls_act;
585         struct list_head *pos, *n;
586         bool mirror_port_enabled;
587         u16 if_id, vlan;
588         int err;
589
590         mirror_port_enabled = (ethsw->mirror_port != ethsw->sw_attr.num_ifs);
591         cls_act = &cls->rule->action.entries[0];
592
593         /* Offload rules only when the destination is a DPAA2 switch port */
594         if (!dpaa2_switch_port_dev_check(cls_act->dev)) {
595                 NL_SET_ERR_MSG_MOD(extack,
596                                    "Destination not a DPAA2 switch port");
597                 return -EOPNOTSUPP;
598         }
599         if_id = dpaa2_switch_get_index(ethsw, cls_act->dev);
600
601         /* We have a single mirror port but can configure egress mirroring on
602          * all the other switch ports. We need to allow mirroring rules only
603          * when the destination port is the same.
604          */
605         if (mirror_port_enabled && ethsw->mirror_port != if_id) {
606                 NL_SET_ERR_MSG_MOD(extack,
607                                    "Multiple mirror ports not supported");
608                 return -EBUSY;
609         }
610
611         /* Parse the key */
612         err = dpaa2_switch_flower_parse_mirror_key(cls, &vlan);
613         if (err)
614                 return err;
615
616         /* Make sure that we don't already have a mirror rule with the same
617          * configuration.
618          */
619         list_for_each_safe(pos, n, &block->mirror_entries) {
620                 tmp = list_entry(pos, struct dpaa2_switch_mirror_entry, list);
621
622                 if (tmp->cfg.filter == DPSW_REFLECTION_FILTER_INGRESS_VLAN &&
623                     tmp->cfg.vlan_id == vlan) {
624                         NL_SET_ERR_MSG_MOD(extack,
625                                            "VLAN mirror filter already installed");
626                         return -EBUSY;
627                 }
628         }
629
630         mirror_entry = kzalloc(sizeof(*mirror_entry), GFP_KERNEL);
631         if (!mirror_entry)
632                 return -ENOMEM;
633
634         mirror_entry->cfg.filter = DPSW_REFLECTION_FILTER_INGRESS_VLAN;
635         mirror_entry->cfg.vlan_id = vlan;
636         mirror_entry->cookie = cls->cookie;
637
638         return dpaa2_switch_block_add_mirror(block, mirror_entry, if_id,
639                                              extack);
640 }
641
642 int dpaa2_switch_cls_flower_replace(struct dpaa2_switch_filter_block *block,
643                                     struct flow_cls_offload *cls)
644 {
645         struct flow_rule *rule = flow_cls_offload_flow_rule(cls);
646         struct netlink_ext_ack *extack = cls->common.extack;
647         struct flow_action_entry *act;
648
649         if (!flow_offload_has_one_action(&rule->action)) {
650                 NL_SET_ERR_MSG(extack, "Only singular actions are supported");
651                 return -EOPNOTSUPP;
652         }
653
654         act = &rule->action.entries[0];
655         switch (act->id) {
656         case FLOW_ACTION_REDIRECT:
657         case FLOW_ACTION_TRAP:
658         case FLOW_ACTION_DROP:
659                 return dpaa2_switch_cls_flower_replace_acl(block, cls);
660         case FLOW_ACTION_MIRRED:
661                 return dpaa2_switch_cls_flower_replace_mirror(block, cls);
662         default:
663                 NL_SET_ERR_MSG_MOD(extack, "Action not supported");
664                 return -EOPNOTSUPP;
665         }
666 }
667
668 int dpaa2_switch_cls_flower_destroy(struct dpaa2_switch_filter_block *block,
669                                     struct flow_cls_offload *cls)
670 {
671         struct dpaa2_switch_mirror_entry *mirror_entry;
672         struct dpaa2_switch_acl_entry *acl_entry;
673
674         /* If this filter is a an ACL one, remove it */
675         acl_entry = dpaa2_switch_acl_tbl_find_entry_by_cookie(block,
676                                                               cls->cookie);
677         if (acl_entry)
678                 return dpaa2_switch_acl_tbl_remove_entry(block, acl_entry);
679
680         /* If not, then it has to be a mirror */
681         mirror_entry = dpaa2_switch_mirror_find_entry_by_cookie(block,
682                                                                 cls->cookie);
683         if (mirror_entry)
684                 return dpaa2_switch_block_remove_mirror(block,
685                                                         mirror_entry);
686
687         return 0;
688 }
689
690 static int
691 dpaa2_switch_cls_matchall_replace_acl(struct dpaa2_switch_filter_block *block,
692                                       struct tc_cls_matchall_offload *cls)
693 {
694         struct netlink_ext_ack *extack = cls->common.extack;
695         struct ethsw_core *ethsw = block->ethsw;
696         struct dpaa2_switch_acl_entry *acl_entry;
697         struct flow_action_entry *act;
698         int err;
699
700         if (dpaa2_switch_acl_tbl_is_full(block)) {
701                 NL_SET_ERR_MSG(extack, "Maximum filter capacity reached");
702                 return -ENOMEM;
703         }
704
705         acl_entry = kzalloc(sizeof(*acl_entry), GFP_KERNEL);
706         if (!acl_entry)
707                 return -ENOMEM;
708
709         act = &cls->rule->action.entries[0];
710         err = dpaa2_switch_tc_parse_action_acl(ethsw, act,
711                                                &acl_entry->cfg.result, extack);
712         if (err)
713                 goto free_acl_entry;
714
715         acl_entry->prio = cls->common.prio;
716         acl_entry->cookie = cls->cookie;
717
718         err = dpaa2_switch_acl_tbl_add_entry(block, acl_entry);
719         if (err)
720                 goto free_acl_entry;
721
722         return 0;
723
724 free_acl_entry:
725         kfree(acl_entry);
726
727         return err;
728 }
729
730 static int
731 dpaa2_switch_cls_matchall_replace_mirror(struct dpaa2_switch_filter_block *block,
732                                          struct tc_cls_matchall_offload *cls)
733 {
734         struct netlink_ext_ack *extack = cls->common.extack;
735         struct dpaa2_switch_mirror_entry *mirror_entry;
736         struct ethsw_core *ethsw = block->ethsw;
737         struct dpaa2_switch_mirror_entry *tmp;
738         struct flow_action_entry *cls_act;
739         struct list_head *pos, *n;
740         bool mirror_port_enabled;
741         u16 if_id;
742
743         mirror_port_enabled = (ethsw->mirror_port != ethsw->sw_attr.num_ifs);
744         cls_act = &cls->rule->action.entries[0];
745
746         /* Offload rules only when the destination is a DPAA2 switch port */
747         if (!dpaa2_switch_port_dev_check(cls_act->dev)) {
748                 NL_SET_ERR_MSG_MOD(extack,
749                                    "Destination not a DPAA2 switch port");
750                 return -EOPNOTSUPP;
751         }
752         if_id = dpaa2_switch_get_index(ethsw, cls_act->dev);
753
754         /* We have a single mirror port but can configure egress mirroring on
755          * all the other switch ports. We need to allow mirroring rules only
756          * when the destination port is the same.
757          */
758         if (mirror_port_enabled && ethsw->mirror_port != if_id) {
759                 NL_SET_ERR_MSG_MOD(extack,
760                                    "Multiple mirror ports not supported");
761                 return -EBUSY;
762         }
763
764         /* Make sure that we don't already have a mirror rule with the same
765          * configuration. One matchall rule per block is the maximum.
766          */
767         list_for_each_safe(pos, n, &block->mirror_entries) {
768                 tmp = list_entry(pos, struct dpaa2_switch_mirror_entry, list);
769
770                 if (tmp->cfg.filter == DPSW_REFLECTION_FILTER_INGRESS_ALL) {
771                         NL_SET_ERR_MSG_MOD(extack,
772                                            "Matchall mirror filter already installed");
773                         return -EBUSY;
774                 }
775         }
776
777         mirror_entry = kzalloc(sizeof(*mirror_entry), GFP_KERNEL);
778         if (!mirror_entry)
779                 return -ENOMEM;
780
781         mirror_entry->cfg.filter = DPSW_REFLECTION_FILTER_INGRESS_ALL;
782         mirror_entry->cookie = cls->cookie;
783
784         return dpaa2_switch_block_add_mirror(block, mirror_entry, if_id,
785                                              extack);
786 }
787
788 int dpaa2_switch_cls_matchall_replace(struct dpaa2_switch_filter_block *block,
789                                       struct tc_cls_matchall_offload *cls)
790 {
791         struct netlink_ext_ack *extack = cls->common.extack;
792         struct flow_action_entry *act;
793
794         if (!flow_offload_has_one_action(&cls->rule->action)) {
795                 NL_SET_ERR_MSG(extack, "Only singular actions are supported");
796                 return -EOPNOTSUPP;
797         }
798
799         act = &cls->rule->action.entries[0];
800         switch (act->id) {
801         case FLOW_ACTION_REDIRECT:
802         case FLOW_ACTION_TRAP:
803         case FLOW_ACTION_DROP:
804                 return dpaa2_switch_cls_matchall_replace_acl(block, cls);
805         case FLOW_ACTION_MIRRED:
806                 return dpaa2_switch_cls_matchall_replace_mirror(block, cls);
807         default:
808                 NL_SET_ERR_MSG_MOD(extack, "Action not supported");
809                 return -EOPNOTSUPP;
810         }
811 }
812
813 int dpaa2_switch_block_offload_mirror(struct dpaa2_switch_filter_block *block,
814                                       struct ethsw_port_priv *port_priv)
815 {
816         struct ethsw_core *ethsw = port_priv->ethsw_data;
817         struct dpaa2_switch_mirror_entry *tmp;
818         int err;
819
820         list_for_each_entry(tmp, &block->mirror_entries, list) {
821                 err = dpsw_if_add_reflection(ethsw->mc_io, 0,
822                                              ethsw->dpsw_handle,
823                                              port_priv->idx, &tmp->cfg);
824                 if (err)
825                         goto unwind_add;
826         }
827
828         return 0;
829
830 unwind_add:
831         list_for_each_entry(tmp, &block->mirror_entries, list)
832                 dpsw_if_remove_reflection(ethsw->mc_io, 0,
833                                           ethsw->dpsw_handle,
834                                           port_priv->idx, &tmp->cfg);
835
836         return err;
837 }
838
839 int dpaa2_switch_block_unoffload_mirror(struct dpaa2_switch_filter_block *block,
840                                         struct ethsw_port_priv *port_priv)
841 {
842         struct ethsw_core *ethsw = port_priv->ethsw_data;
843         struct dpaa2_switch_mirror_entry *tmp;
844         int err;
845
846         list_for_each_entry(tmp, &block->mirror_entries, list) {
847                 err = dpsw_if_remove_reflection(ethsw->mc_io, 0,
848                                                 ethsw->dpsw_handle,
849                                                 port_priv->idx, &tmp->cfg);
850                 if (err)
851                         goto unwind_remove;
852         }
853
854         return 0;
855
856 unwind_remove:
857         list_for_each_entry(tmp, &block->mirror_entries, list)
858                 dpsw_if_add_reflection(ethsw->mc_io, 0, ethsw->dpsw_handle,
859                                        port_priv->idx, &tmp->cfg);
860
861         return err;
862 }
863
864 int dpaa2_switch_cls_matchall_destroy(struct dpaa2_switch_filter_block *block,
865                                       struct tc_cls_matchall_offload *cls)
866 {
867         struct dpaa2_switch_mirror_entry *mirror_entry;
868         struct dpaa2_switch_acl_entry *acl_entry;
869
870         /* If this filter is a an ACL one, remove it */
871         acl_entry = dpaa2_switch_acl_tbl_find_entry_by_cookie(block,
872                                                               cls->cookie);
873         if (acl_entry)
874                 return dpaa2_switch_acl_tbl_remove_entry(block,
875                                                          acl_entry);
876
877         /* If not, then it has to be a mirror */
878         mirror_entry = dpaa2_switch_mirror_find_entry_by_cookie(block,
879                                                                 cls->cookie);
880         if (mirror_entry)
881                 return dpaa2_switch_block_remove_mirror(block,
882                                                         mirror_entry);
883
884         return 0;
885 }