1 // SPDX-License-Identifier: GPL-2.0
3 * DPAA2 Ethernet Switch flower support
9 #include "dpaa2-switch.h"
11 static int dpaa2_switch_flower_parse_key(struct flow_cls_offload *cls,
12 struct dpsw_acl_key *acl_key)
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;
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");
33 acl_h = &acl_key->match;
34 acl_m = &acl_key->mask;
36 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_BASIC)) {
37 struct flow_match_basic match;
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);
46 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_ETH_ADDRS)) {
47 struct flow_match_eth_addrs match;
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]);
56 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
57 struct flow_match_vlan match;
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 |
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 |
71 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IPV4_ADDRS)) {
72 struct flow_match_ipv4_addrs match;
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);
81 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_PORTS)) {
82 struct flow_match_ports match;
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);
91 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_IP)) {
92 struct flow_match_ip match;
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");
101 if ((match.mask->tos & 0x3) != 0) {
102 NL_SET_ERR_MSG_MOD(extack,
103 "Matching on ECN not supported, only DSCP");
107 acl_h->l3_dscp = match.key->tos >> 2;
108 acl_m->l3_dscp = match.mask->tos >> 2;
114 int dpaa2_switch_acl_entry_add(struct dpaa2_switch_filter_block *filter_block,
115 struct dpaa2_switch_acl_entry *entry)
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;
124 cmd_buff = kzalloc(DPAA2_ETHSW_PORT_ACL_CMD_BUF_SIZE, GFP_KERNEL);
128 dpsw_acl_prepare_entry_cfg(acl_key, cmd_buff);
130 acl_entry_cfg->key_iova = dma_map_single(dev, cmd_buff,
131 DPAA2_ETHSW_PORT_ACL_CMD_BUF_SIZE,
133 if (unlikely(dma_mapping_error(dev, acl_entry_cfg->key_iova))) {
134 dev_err(dev, "DMA mapping failed\n");
139 err = dpsw_acl_add_entry(ethsw->mc_io, 0, ethsw->dpsw_handle,
140 filter_block->acl_id, acl_entry_cfg);
142 dma_unmap_single(dev, acl_entry_cfg->key_iova,
143 DPAA2_ETHSW_PORT_ACL_CMD_BUF_SIZE,
146 dev_err(dev, "dpsw_acl_add_entry() failed %d\n", err);
157 dpaa2_switch_acl_entry_remove(struct dpaa2_switch_filter_block *block,
158 struct dpaa2_switch_acl_entry *entry)
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;
167 cmd_buff = kzalloc(DPAA2_ETHSW_PORT_ACL_CMD_BUF_SIZE, GFP_KERNEL);
171 dpsw_acl_prepare_entry_cfg(acl_key, cmd_buff);
173 acl_entry_cfg->key_iova = dma_map_single(dev, cmd_buff,
174 DPAA2_ETHSW_PORT_ACL_CMD_BUF_SIZE,
176 if (unlikely(dma_mapping_error(dev, acl_entry_cfg->key_iova))) {
177 dev_err(dev, "DMA mapping failed\n");
182 err = dpsw_acl_remove_entry(ethsw->mc_io, 0, ethsw->dpsw_handle,
183 block->acl_id, acl_entry_cfg);
185 dma_unmap_single(dev, acl_entry_cfg->key_iova,
186 DPAA2_ETHSW_PORT_ACL_CMD_BUF_SIZE, DMA_TO_DEVICE);
188 dev_err(dev, "dpsw_acl_remove_entry() failed %d\n", err);
199 dpaa2_switch_acl_entry_add_to_list(struct dpaa2_switch_filter_block *block,
200 struct dpaa2_switch_acl_entry *entry)
202 struct dpaa2_switch_acl_entry *tmp;
203 struct list_head *pos, *n;
206 if (list_empty(&block->acl_entries)) {
207 list_add(&entry->list, &block->acl_entries);
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)
217 list_add(&entry->list, pos->prev);
221 static struct dpaa2_switch_acl_entry*
222 dpaa2_switch_acl_entry_get_by_index(struct dpaa2_switch_filter_block *block,
225 struct dpaa2_switch_acl_entry *tmp;
228 list_for_each_entry(tmp, &block->acl_entries, list) {
238 dpaa2_switch_acl_entry_set_precedence(struct dpaa2_switch_filter_block *block,
239 struct dpaa2_switch_acl_entry *entry,
244 err = dpaa2_switch_acl_entry_remove(block, entry);
248 entry->cfg.precedence = precedence;
249 return dpaa2_switch_acl_entry_add(block, entry);
253 dpaa2_switch_acl_tbl_add_entry(struct dpaa2_switch_filter_block *block,
254 struct dpaa2_switch_acl_entry *entry)
256 struct dpaa2_switch_acl_entry *tmp;
257 int index, i, precedence, err;
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);
262 /* Move up in priority the ACL entries to make space
263 * for the new filter.
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);
269 err = dpaa2_switch_acl_entry_set_precedence(block, tmp,
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++;
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)
289 struct dpaa2_switch_acl_entry *tmp, *n;
291 list_for_each_entry_safe(tmp, n, &block->acl_entries, list) {
292 if (tmp->cookie == cookie)
299 dpaa2_switch_acl_entry_get_index(struct dpaa2_switch_filter_block *block,
300 struct dpaa2_switch_acl_entry *entry)
302 struct dpaa2_switch_acl_entry *tmp, *n;
305 list_for_each_entry_safe(tmp, n, &block->acl_entries, list) {
306 if (tmp->cookie == entry->cookie)
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)
317 struct dpaa2_switch_mirror_entry *tmp, *n;
319 list_for_each_entry_safe(tmp, n, &block->mirror_entries, list) {
320 if (tmp->cookie == cookie)
327 dpaa2_switch_acl_tbl_remove_entry(struct dpaa2_switch_filter_block *block,
328 struct dpaa2_switch_acl_entry *entry)
330 struct dpaa2_switch_acl_entry *tmp;
331 int index, i, precedence, err;
333 index = dpaa2_switch_acl_entry_get_index(block, entry);
335 /* Remove from hardware the ACL entry */
336 err = dpaa2_switch_acl_entry_remove(block, entry);
340 block->num_acl_rules--;
342 /* Remove it from the list also */
343 list_del(&entry->list);
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,
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)
369 switch (cls_act->id) {
370 case FLOW_ACTION_TRAP:
371 dpsw_act->action = DPSW_ACL_ACTION_REDIRECT_TO_CTRL_IF;
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");
380 dpsw_act->if_id = dpaa2_switch_get_index(ethsw, cls_act->dev);
381 dpsw_act->action = DPSW_ACL_ACTION_REDIRECT;
383 case FLOW_ACTION_DROP:
384 dpsw_act->action = DPSW_ACL_ACTION_DROP;
387 NL_SET_ERR_MSG_MOD(extack,
388 "Action not supported");
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)
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;
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);
417 ethsw->mirror_port = to;
420 /* Setup the same egress mirroring configuration on all the switch
421 * ports that share the same filter block.
423 for_each_set_bit(port, &block_ports, ethsw->sw_attr.num_ifs) {
424 port_priv = ethsw->ports[port];
426 /* We cannot add a per VLAN mirroring rule if the VLAN in
427 * question is not installed on the switch port.
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");
434 goto err_remove_filters;
437 err = dpsw_if_add_reflection(ethsw->mc_io, 0,
441 goto err_remove_filters;
443 ports_added |= BIT(port);
446 list_add(&entry->list, &block->mirror_entries);
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,
456 if (!mirror_port_enabled)
457 ethsw->mirror_port = ethsw->sw_attr.num_ifs;
463 dpaa2_switch_block_remove_mirror(struct dpaa2_switch_filter_block *block,
464 struct dpaa2_switch_mirror_entry *entry)
466 struct dpsw_reflection_cfg *cfg = &entry->cfg;
467 unsigned long block_ports = block->ports;
468 struct ethsw_core *ethsw = block->ethsw;
471 /* Remove this mirroring configuration from all the ports belonging to
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,
478 /* Also remove it from the list of mirror filters */
479 list_del(&entry->list);
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;
490 dpaa2_switch_cls_flower_replace_acl(struct dpaa2_switch_filter_block *block,
491 struct flow_cls_offload *cls)
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;
500 if (dpaa2_switch_acl_tbl_is_full(block)) {
501 NL_SET_ERR_MSG(extack, "Maximum filter capacity reached");
505 acl_entry = kzalloc(sizeof(*acl_entry), GFP_KERNEL);
509 err = dpaa2_switch_flower_parse_key(cls, &acl_entry->key);
513 act = &rule->action.entries[0];
514 err = dpaa2_switch_tc_parse_action_acl(ethsw, act,
515 &acl_entry->cfg.result, extack);
519 acl_entry->prio = cls->common.prio;
520 acl_entry->cookie = cls->cookie;
522 err = dpaa2_switch_acl_tbl_add_entry(block, acl_entry);
534 static int dpaa2_switch_flower_parse_mirror_key(struct flow_cls_offload *cls,
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;
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");
551 if (flow_rule_match_key(rule, FLOW_DISSECTOR_KEY_VLAN)) {
552 struct flow_match_vlan match;
554 flow_rule_match_vlan(rule, &match);
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");
563 if (match.mask->vlan_id != 0xFFF) {
564 NL_SET_ERR_MSG_MOD(extack,
565 "Masked matching not supported");
569 *vlan = (u16)match.key->vlan_id;
577 dpaa2_switch_cls_flower_replace_mirror(struct dpaa2_switch_filter_block *block,
578 struct flow_cls_offload *cls)
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;
590 mirror_port_enabled = (ethsw->mirror_port != ethsw->sw_attr.num_ifs);
591 cls_act = &cls->rule->action.entries[0];
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");
599 if_id = dpaa2_switch_get_index(ethsw, cls_act->dev);
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.
605 if (mirror_port_enabled && ethsw->mirror_port != if_id) {
606 NL_SET_ERR_MSG_MOD(extack,
607 "Multiple mirror ports not supported");
612 err = dpaa2_switch_flower_parse_mirror_key(cls, &vlan);
616 /* Make sure that we don't already have a mirror rule with the same
619 list_for_each_safe(pos, n, &block->mirror_entries) {
620 tmp = list_entry(pos, struct dpaa2_switch_mirror_entry, list);
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");
630 mirror_entry = kzalloc(sizeof(*mirror_entry), GFP_KERNEL);
634 mirror_entry->cfg.filter = DPSW_REFLECTION_FILTER_INGRESS_VLAN;
635 mirror_entry->cfg.vlan_id = vlan;
636 mirror_entry->cookie = cls->cookie;
638 return dpaa2_switch_block_add_mirror(block, mirror_entry, if_id,
642 int dpaa2_switch_cls_flower_replace(struct dpaa2_switch_filter_block *block,
643 struct flow_cls_offload *cls)
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;
649 if (!flow_offload_has_one_action(&rule->action)) {
650 NL_SET_ERR_MSG(extack, "Only singular actions are supported");
654 act = &rule->action.entries[0];
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);
663 NL_SET_ERR_MSG_MOD(extack, "Action not supported");
668 int dpaa2_switch_cls_flower_destroy(struct dpaa2_switch_filter_block *block,
669 struct flow_cls_offload *cls)
671 struct dpaa2_switch_mirror_entry *mirror_entry;
672 struct dpaa2_switch_acl_entry *acl_entry;
674 /* If this filter is a an ACL one, remove it */
675 acl_entry = dpaa2_switch_acl_tbl_find_entry_by_cookie(block,
678 return dpaa2_switch_acl_tbl_remove_entry(block, acl_entry);
680 /* If not, then it has to be a mirror */
681 mirror_entry = dpaa2_switch_mirror_find_entry_by_cookie(block,
684 return dpaa2_switch_block_remove_mirror(block,
691 dpaa2_switch_cls_matchall_replace_acl(struct dpaa2_switch_filter_block *block,
692 struct tc_cls_matchall_offload *cls)
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;
700 if (dpaa2_switch_acl_tbl_is_full(block)) {
701 NL_SET_ERR_MSG(extack, "Maximum filter capacity reached");
705 acl_entry = kzalloc(sizeof(*acl_entry), GFP_KERNEL);
709 act = &cls->rule->action.entries[0];
710 err = dpaa2_switch_tc_parse_action_acl(ethsw, act,
711 &acl_entry->cfg.result, extack);
715 acl_entry->prio = cls->common.prio;
716 acl_entry->cookie = cls->cookie;
718 err = dpaa2_switch_acl_tbl_add_entry(block, acl_entry);
731 dpaa2_switch_cls_matchall_replace_mirror(struct dpaa2_switch_filter_block *block,
732 struct tc_cls_matchall_offload *cls)
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;
743 mirror_port_enabled = (ethsw->mirror_port != ethsw->sw_attr.num_ifs);
744 cls_act = &cls->rule->action.entries[0];
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");
752 if_id = dpaa2_switch_get_index(ethsw, cls_act->dev);
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.
758 if (mirror_port_enabled && ethsw->mirror_port != if_id) {
759 NL_SET_ERR_MSG_MOD(extack,
760 "Multiple mirror ports not supported");
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.
767 list_for_each_safe(pos, n, &block->mirror_entries) {
768 tmp = list_entry(pos, struct dpaa2_switch_mirror_entry, list);
770 if (tmp->cfg.filter == DPSW_REFLECTION_FILTER_INGRESS_ALL) {
771 NL_SET_ERR_MSG_MOD(extack,
772 "Matchall mirror filter already installed");
777 mirror_entry = kzalloc(sizeof(*mirror_entry), GFP_KERNEL);
781 mirror_entry->cfg.filter = DPSW_REFLECTION_FILTER_INGRESS_ALL;
782 mirror_entry->cookie = cls->cookie;
784 return dpaa2_switch_block_add_mirror(block, mirror_entry, if_id,
788 int dpaa2_switch_cls_matchall_replace(struct dpaa2_switch_filter_block *block,
789 struct tc_cls_matchall_offload *cls)
791 struct netlink_ext_ack *extack = cls->common.extack;
792 struct flow_action_entry *act;
794 if (!flow_offload_has_one_action(&cls->rule->action)) {
795 NL_SET_ERR_MSG(extack, "Only singular actions are supported");
799 act = &cls->rule->action.entries[0];
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);
808 NL_SET_ERR_MSG_MOD(extack, "Action not supported");
813 int dpaa2_switch_block_offload_mirror(struct dpaa2_switch_filter_block *block,
814 struct ethsw_port_priv *port_priv)
816 struct ethsw_core *ethsw = port_priv->ethsw_data;
817 struct dpaa2_switch_mirror_entry *tmp;
820 list_for_each_entry(tmp, &block->mirror_entries, list) {
821 err = dpsw_if_add_reflection(ethsw->mc_io, 0,
823 port_priv->idx, &tmp->cfg);
831 list_for_each_entry(tmp, &block->mirror_entries, list)
832 dpsw_if_remove_reflection(ethsw->mc_io, 0,
834 port_priv->idx, &tmp->cfg);
839 int dpaa2_switch_block_unoffload_mirror(struct dpaa2_switch_filter_block *block,
840 struct ethsw_port_priv *port_priv)
842 struct ethsw_core *ethsw = port_priv->ethsw_data;
843 struct dpaa2_switch_mirror_entry *tmp;
846 list_for_each_entry(tmp, &block->mirror_entries, list) {
847 err = dpsw_if_remove_reflection(ethsw->mc_io, 0,
849 port_priv->idx, &tmp->cfg);
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);
864 int dpaa2_switch_cls_matchall_destroy(struct dpaa2_switch_filter_block *block,
865 struct tc_cls_matchall_offload *cls)
867 struct dpaa2_switch_mirror_entry *mirror_entry;
868 struct dpaa2_switch_acl_entry *acl_entry;
870 /* If this filter is a an ACL one, remove it */
871 acl_entry = dpaa2_switch_acl_tbl_find_entry_by_cookie(block,
874 return dpaa2_switch_acl_tbl_remove_entry(block,
877 /* If not, then it has to be a mirror */
878 mirror_entry = dpaa2_switch_mirror_find_entry_by_cookie(block,
881 return dpaa2_switch_block_remove_mirror(block,