aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/ethernet/microchip/sparx5/sparx5_tc_matchall.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/ethernet/microchip/sparx5/sparx5_tc_matchall.c')
-rw-r--r--drivers/net/ethernet/microchip/sparx5/sparx5_tc_matchall.c97
1 files changed, 97 insertions, 0 deletions
diff --git a/drivers/net/ethernet/microchip/sparx5/sparx5_tc_matchall.c b/drivers/net/ethernet/microchip/sparx5/sparx5_tc_matchall.c
new file mode 100644
index 00000000000000..30dd61e5d150fb
--- /dev/null
+++ b/drivers/net/ethernet/microchip/sparx5/sparx5_tc_matchall.c
@@ -0,0 +1,97 @@
+// SPDX-License-Identifier: GPL-2.0+
+/* Microchip VCAP API
+ *
+ * Copyright (c) 2022 Microchip Technology Inc. and its subsidiaries.
+ */
+
+#include "sparx5_tc.h"
+#include "vcap_api.h"
+#include "vcap_api_client.h"
+#include "sparx5_main_regs.h"
+#include "sparx5_main.h"
+#include "sparx5_vcap_impl.h"
+
+static int sparx5_tc_matchall_replace(struct net_device *ndev,
+ struct tc_cls_matchall_offload *tmo,
+ bool ingress)
+{
+ struct sparx5_port *port = netdev_priv(ndev);
+ struct flow_action_entry *action;
+ struct sparx5 *sparx5;
+ int err;
+
+ if (!flow_offload_has_one_action(&tmo->rule->action)) {
+ NL_SET_ERR_MSG_MOD(tmo->common.extack,
+ "Only one action per filter is supported");
+ return -EOPNOTSUPP;
+ }
+ action = &tmo->rule->action.entries[0];
+
+ sparx5 = port->sparx5;
+ switch (action->id) {
+ case FLOW_ACTION_GOTO:
+ err = vcap_enable_lookups(sparx5->vcap_ctrl, ndev,
+ action->chain_index, tmo->cookie,
+ true);
+ if (err == -EFAULT) {
+ NL_SET_ERR_MSG_MOD(tmo->common.extack,
+ "Unsupported goto chain");
+ return -EOPNOTSUPP;
+ }
+ if (err == -EADDRINUSE) {
+ NL_SET_ERR_MSG_MOD(tmo->common.extack,
+ "VCAP already enabled");
+ return -EOPNOTSUPP;
+ }
+ if (err) {
+ NL_SET_ERR_MSG_MOD(tmo->common.extack,
+ "Could not enable VCAP lookups");
+ return err;
+ }
+ break;
+ default:
+ NL_SET_ERR_MSG_MOD(tmo->common.extack, "Unsupported action");
+ return -EOPNOTSUPP;
+ }
+ return 0;
+}
+
+static int sparx5_tc_matchall_destroy(struct net_device *ndev,
+ struct tc_cls_matchall_offload *tmo,
+ bool ingress)
+{
+ struct sparx5_port *port = netdev_priv(ndev);
+ struct sparx5 *sparx5;
+ int err;
+
+ sparx5 = port->sparx5;
+ if (!tmo->rule && tmo->cookie) {
+ err = vcap_enable_lookups(sparx5->vcap_ctrl, ndev, 0,
+ tmo->cookie, false);
+ if (err)
+ return err;
+ return 0;
+ }
+ NL_SET_ERR_MSG_MOD(tmo->common.extack, "Unsupported action");
+ return -EOPNOTSUPP;
+}
+
+int sparx5_tc_matchall(struct net_device *ndev,
+ struct tc_cls_matchall_offload *tmo,
+ bool ingress)
+{
+ if (!tc_cls_can_offload_and_chain0(ndev, &tmo->common)) {
+ NL_SET_ERR_MSG_MOD(tmo->common.extack,
+ "Only chain zero is supported");
+ return -EOPNOTSUPP;
+ }
+
+ switch (tmo->command) {
+ case TC_CLSMATCHALL_REPLACE:
+ return sparx5_tc_matchall_replace(ndev, tmo, ingress);
+ case TC_CLSMATCHALL_DESTROY:
+ return sparx5_tc_matchall_destroy(ndev, tmo, ingress);
+ default:
+ return -EOPNOTSUPP;
+ }
+}