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(dev: ndev); |
19 | struct flow_action_entry *action; |
20 | struct sparx5 *sparx5; |
21 | int err; |
22 | |
23 | if (!flow_offload_has_one_action(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(vctrl: sparx5->vcap_ctrl, ndev, |
34 | from_cid: tmo->common.chain_index, |
35 | to_cid: action->chain_index, cookie: tmo->cookie, |
36 | enable: 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 | |
65 | static 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(dev: ndev); |
70 | struct sparx5 *sparx5; |
71 | int err; |
72 | |
73 | sparx5 = port->sparx5; |
74 | if (!tmo->rule && tmo->cookie) { |
75 | err = vcap_enable_lookups(vctrl: sparx5->vcap_ctrl, ndev, |
76 | from_cid: 0, to_cid: 0, cookie: tmo->cookie, enable: 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 | |
85 | int 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 | |