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