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 "sparx5_tc.h"
8 #include "vcap_api.h"
9 #include "vcap_api_client.h"
10 #include "sparx5_main_regs.h"
11 #include "sparx5_main.h"
12 #include "sparx5_vcap_impl.h"
13 
14 static int sparx5_tc_matchall_replace(struct net_device *ndev,
15 				      struct tc_cls_matchall_offload *tmo,
16 				      bool ingress)
17 {
18 	struct sparx5_port *port = netdev_priv(ndev);
19 	struct flow_action_entry *action;
20 	struct sparx5 *sparx5;
21 	int err;
22 
23 	if (!flow_offload_has_one_action(&tmo->rule->action)) {
24 		NL_SET_ERR_MSG_MOD(tmo->common.extack,
25 				   "Only one action per filter is supported");
26 		return -EOPNOTSUPP;
27 	}
28 	action = &tmo->rule->action.entries[0];
29 
30 	sparx5 = port->sparx5;
31 	switch (action->id) {
32 	case FLOW_ACTION_GOTO:
33 		err = vcap_enable_lookups(sparx5->vcap_ctrl, ndev,
34 					  action->chain_index, tmo->cookie,
35 					  true);
36 		if (err == -EFAULT) {
37 			NL_SET_ERR_MSG_MOD(tmo->common.extack,
38 					   "Unsupported goto chain");
39 			return -EOPNOTSUPP;
40 		}
41 		if (err == -EADDRINUSE) {
42 			NL_SET_ERR_MSG_MOD(tmo->common.extack,
43 					   "VCAP already enabled");
44 			return -EOPNOTSUPP;
45 		}
46 		if (err) {
47 			NL_SET_ERR_MSG_MOD(tmo->common.extack,
48 					   "Could not enable VCAP lookups");
49 			return err;
50 		}
51 		break;
52 	default:
53 		NL_SET_ERR_MSG_MOD(tmo->common.extack, "Unsupported action");
54 		return -EOPNOTSUPP;
55 	}
56 	return 0;
57 }
58 
59 static int sparx5_tc_matchall_destroy(struct net_device *ndev,
60 				      struct tc_cls_matchall_offload *tmo,
61 				      bool ingress)
62 {
63 	struct sparx5_port *port = netdev_priv(ndev);
64 	struct sparx5 *sparx5;
65 	int err;
66 
67 	sparx5 = port->sparx5;
68 	if (!tmo->rule && tmo->cookie) {
69 		err = vcap_enable_lookups(sparx5->vcap_ctrl, ndev, 0,
70 					  tmo->cookie, false);
71 		if (err)
72 			return err;
73 		return 0;
74 	}
75 	NL_SET_ERR_MSG_MOD(tmo->common.extack, "Unsupported action");
76 	return -EOPNOTSUPP;
77 }
78 
79 int sparx5_tc_matchall(struct net_device *ndev,
80 		       struct tc_cls_matchall_offload *tmo,
81 		       bool ingress)
82 {
83 	if (!tc_cls_can_offload_and_chain0(ndev, &tmo->common)) {
84 		NL_SET_ERR_MSG_MOD(tmo->common.extack,
85 				   "Only chain zero is supported");
86 		return -EOPNOTSUPP;
87 	}
88 
89 	switch (tmo->command) {
90 	case TC_CLSMATCHALL_REPLACE:
91 		return sparx5_tc_matchall_replace(ndev, tmo, ingress);
92 	case TC_CLSMATCHALL_DESTROY:
93 		return sparx5_tc_matchall_destroy(ndev, tmo, ingress);
94 	default:
95 		return -EOPNOTSUPP;
96 	}
97 }
98