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
14static 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					  tmo->common.chain_index,
35					  action->chain_index, tmo->cookie,
36					  true);
37		if (err == -EFAULT) {
38			NL_SET_ERR_MSG_MOD(tmo->common.extack,
39					   "Unsupported goto chain");
40			return -EOPNOTSUPP;
41		}
42		if (err == -EADDRINUSE) {
43			NL_SET_ERR_MSG_MOD(tmo->common.extack,
44					   "VCAP already enabled");
45			return -EOPNOTSUPP;
46		}
47		if (err == -EADDRNOTAVAIL) {
48			NL_SET_ERR_MSG_MOD(tmo->common.extack,
49					   "Already matching this chain");
50			return -EOPNOTSUPP;
51		}
52		if (err) {
53			NL_SET_ERR_MSG_MOD(tmo->common.extack,
54					   "Could not enable VCAP lookups");
55			return err;
56		}
57		break;
58	default:
59		NL_SET_ERR_MSG_MOD(tmo->common.extack, "Unsupported action");
60		return -EOPNOTSUPP;
61	}
62	return 0;
63}
64
65static int sparx5_tc_matchall_destroy(struct net_device *ndev,
66				      struct tc_cls_matchall_offload *tmo,
67				      bool ingress)
68{
69	struct sparx5_port *port = netdev_priv(ndev);
70	struct sparx5 *sparx5;
71	int err;
72
73	sparx5 = port->sparx5;
74	if (!tmo->rule && tmo->cookie) {
75		err = vcap_enable_lookups(sparx5->vcap_ctrl, ndev,
76					  0, 0, tmo->cookie, false);
77		if (err)
78			return err;
79		return 0;
80	}
81	NL_SET_ERR_MSG_MOD(tmo->common.extack, "Unsupported action");
82	return -EOPNOTSUPP;
83}
84
85int sparx5_tc_matchall(struct net_device *ndev,
86		       struct tc_cls_matchall_offload *tmo,
87		       bool ingress)
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