xref: /openbmc/linux/drivers/net/ethernet/microchip/sparx5/sparx5_tc_matchall.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
167456717SSteen Hegelund // SPDX-License-Identifier: GPL-2.0+
267456717SSteen Hegelund /* Microchip VCAP API
367456717SSteen Hegelund  *
467456717SSteen Hegelund  * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.
567456717SSteen Hegelund  */
667456717SSteen Hegelund 
767456717SSteen Hegelund #include "sparx5_tc.h"
867456717SSteen Hegelund #include "vcap_api.h"
967456717SSteen Hegelund #include "vcap_api_client.h"
1067456717SSteen Hegelund #include "sparx5_main_regs.h"
1167456717SSteen Hegelund #include "sparx5_main.h"
1267456717SSteen Hegelund #include "sparx5_vcap_impl.h"
1367456717SSteen Hegelund 
sparx5_tc_matchall_replace(struct net_device * ndev,struct tc_cls_matchall_offload * tmo,bool ingress)1467456717SSteen Hegelund static int sparx5_tc_matchall_replace(struct net_device *ndev,
1567456717SSteen Hegelund 				      struct tc_cls_matchall_offload *tmo,
1667456717SSteen Hegelund 				      bool ingress)
1767456717SSteen Hegelund {
1867456717SSteen Hegelund 	struct sparx5_port *port = netdev_priv(ndev);
1967456717SSteen Hegelund 	struct flow_action_entry *action;
2067456717SSteen Hegelund 	struct sparx5 *sparx5;
2167456717SSteen Hegelund 	int err;
2267456717SSteen Hegelund 
2367456717SSteen Hegelund 	if (!flow_offload_has_one_action(&tmo->rule->action)) {
2467456717SSteen Hegelund 		NL_SET_ERR_MSG_MOD(tmo->common.extack,
2567456717SSteen Hegelund 				   "Only one action per filter is supported");
2667456717SSteen Hegelund 		return -EOPNOTSUPP;
2767456717SSteen Hegelund 	}
2867456717SSteen Hegelund 	action = &tmo->rule->action.entries[0];
2967456717SSteen Hegelund 
3067456717SSteen Hegelund 	sparx5 = port->sparx5;
3167456717SSteen Hegelund 	switch (action->id) {
3267456717SSteen Hegelund 	case FLOW_ACTION_GOTO:
3367456717SSteen Hegelund 		err = vcap_enable_lookups(sparx5->vcap_ctrl, ndev,
34*cfd9e7b7SSteen Hegelund 					  tmo->common.chain_index,
3567456717SSteen Hegelund 					  action->chain_index, tmo->cookie,
3667456717SSteen Hegelund 					  true);
3767456717SSteen Hegelund 		if (err == -EFAULT) {
3867456717SSteen Hegelund 			NL_SET_ERR_MSG_MOD(tmo->common.extack,
3967456717SSteen Hegelund 					   "Unsupported goto chain");
4067456717SSteen Hegelund 			return -EOPNOTSUPP;
4167456717SSteen Hegelund 		}
4267456717SSteen Hegelund 		if (err == -EADDRINUSE) {
4367456717SSteen Hegelund 			NL_SET_ERR_MSG_MOD(tmo->common.extack,
4467456717SSteen Hegelund 					   "VCAP already enabled");
4567456717SSteen Hegelund 			return -EOPNOTSUPP;
4667456717SSteen Hegelund 		}
47*cfd9e7b7SSteen Hegelund 		if (err == -EADDRNOTAVAIL) {
48*cfd9e7b7SSteen Hegelund 			NL_SET_ERR_MSG_MOD(tmo->common.extack,
49*cfd9e7b7SSteen Hegelund 					   "Already matching this chain");
50*cfd9e7b7SSteen Hegelund 			return -EOPNOTSUPP;
51*cfd9e7b7SSteen Hegelund 		}
5267456717SSteen Hegelund 		if (err) {
5367456717SSteen Hegelund 			NL_SET_ERR_MSG_MOD(tmo->common.extack,
5467456717SSteen Hegelund 					   "Could not enable VCAP lookups");
5567456717SSteen Hegelund 			return err;
5667456717SSteen Hegelund 		}
5767456717SSteen Hegelund 		break;
5867456717SSteen Hegelund 	default:
5967456717SSteen Hegelund 		NL_SET_ERR_MSG_MOD(tmo->common.extack, "Unsupported action");
6067456717SSteen Hegelund 		return -EOPNOTSUPP;
6167456717SSteen Hegelund 	}
6267456717SSteen Hegelund 	return 0;
6367456717SSteen Hegelund }
6467456717SSteen Hegelund 
sparx5_tc_matchall_destroy(struct net_device * ndev,struct tc_cls_matchall_offload * tmo,bool ingress)6567456717SSteen Hegelund static int sparx5_tc_matchall_destroy(struct net_device *ndev,
6667456717SSteen Hegelund 				      struct tc_cls_matchall_offload *tmo,
6767456717SSteen Hegelund 				      bool ingress)
6867456717SSteen Hegelund {
6967456717SSteen Hegelund 	struct sparx5_port *port = netdev_priv(ndev);
7067456717SSteen Hegelund 	struct sparx5 *sparx5;
7167456717SSteen Hegelund 	int err;
7267456717SSteen Hegelund 
7367456717SSteen Hegelund 	sparx5 = port->sparx5;
7467456717SSteen Hegelund 	if (!tmo->rule && tmo->cookie) {
75*cfd9e7b7SSteen Hegelund 		err = vcap_enable_lookups(sparx5->vcap_ctrl, ndev,
76*cfd9e7b7SSteen Hegelund 					  0, 0, tmo->cookie, false);
7767456717SSteen Hegelund 		if (err)
7867456717SSteen Hegelund 			return err;
7967456717SSteen Hegelund 		return 0;
8067456717SSteen Hegelund 	}
8167456717SSteen Hegelund 	NL_SET_ERR_MSG_MOD(tmo->common.extack, "Unsupported action");
8267456717SSteen Hegelund 	return -EOPNOTSUPP;
8367456717SSteen Hegelund }
8467456717SSteen Hegelund 
sparx5_tc_matchall(struct net_device * ndev,struct tc_cls_matchall_offload * tmo,bool ingress)8567456717SSteen Hegelund int sparx5_tc_matchall(struct net_device *ndev,
8667456717SSteen Hegelund 		       struct tc_cls_matchall_offload *tmo,
8767456717SSteen Hegelund 		       bool ingress)
8867456717SSteen Hegelund {
8967456717SSteen Hegelund 	switch (tmo->command) {
9067456717SSteen Hegelund 	case TC_CLSMATCHALL_REPLACE:
9167456717SSteen Hegelund 		return sparx5_tc_matchall_replace(ndev, tmo, ingress);
9267456717SSteen Hegelund 	case TC_CLSMATCHALL_DESTROY:
9367456717SSteen Hegelund 		return sparx5_tc_matchall_destroy(ndev, tmo, ingress);
9467456717SSteen Hegelund 	default:
9567456717SSteen Hegelund 		return -EOPNOTSUPP;
9667456717SSteen Hegelund 	}
9767456717SSteen Hegelund }
98