cpuidle: psci: Do not suspend topology CPUs on PREEMPT_RT
[linux-block.git] / drivers / net / ethernet / mellanox / mlx5 / core / en / tc / act / police.c
1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 // Copyright (c) 2021, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3
4 #include "act.h"
5 #include "en/tc_priv.h"
6 #include "fs_core.h"
7
8 static bool police_act_validate_control(enum flow_action_id act_id,
9                                         struct netlink_ext_ack *extack)
10 {
11         if (act_id != FLOW_ACTION_PIPE &&
12             act_id != FLOW_ACTION_ACCEPT &&
13             act_id != FLOW_ACTION_JUMP &&
14             act_id != FLOW_ACTION_DROP) {
15                 NL_SET_ERR_MSG_MOD(extack,
16                                    "Offload not supported when conform-exceed action is not pipe, ok, jump or drop");
17                 return false;
18         }
19
20         return true;
21 }
22
23 static int police_act_validate(const struct flow_action_entry *act,
24                                struct netlink_ext_ack *extack)
25 {
26         if (!police_act_validate_control(act->police.exceed.act_id, extack) ||
27             !police_act_validate_control(act->police.notexceed.act_id, extack))
28                 return -EOPNOTSUPP;
29
30         if (act->police.peakrate_bytes_ps ||
31             act->police.avrate || act->police.overhead) {
32                 NL_SET_ERR_MSG_MOD(extack,
33                                    "Offload not supported when peakrate/avrate/overhead is configured");
34                 return -EOPNOTSUPP;
35         }
36
37         if (act->police.rate_pkt_ps) {
38                 NL_SET_ERR_MSG_MOD(extack,
39                                    "QoS offload not support packets per second");
40                 return -EOPNOTSUPP;
41         }
42
43         return 0;
44 }
45
46 static bool
47 tc_act_can_offload_police(struct mlx5e_tc_act_parse_state *parse_state,
48                           const struct flow_action_entry *act,
49                           int act_index,
50                           struct mlx5_flow_attr *attr)
51 {
52         int err;
53
54         err = police_act_validate(act, parse_state->extack);
55         if (err)
56                 return false;
57
58         return !!mlx5e_get_flow_meters(parse_state->flow->priv->mdev);
59 }
60
61 static int
62 fill_meter_params_from_act(const struct flow_action_entry *act,
63                            struct mlx5e_flow_meter_params *params)
64 {
65         params->index = act->hw_index;
66         if (act->police.rate_bytes_ps) {
67                 params->mode = MLX5_RATE_LIMIT_BPS;
68                 /* change rate to bits per second */
69                 params->rate = act->police.rate_bytes_ps << 3;
70                 params->burst = act->police.burst;
71         } else if (act->police.rate_pkt_ps) {
72                 params->mode = MLX5_RATE_LIMIT_PPS;
73                 params->rate = act->police.rate_pkt_ps;
74                 params->burst = act->police.burst_pkt;
75         } else if (act->police.mtu) {
76                 params->mtu = act->police.mtu;
77         } else {
78                 return -EOPNOTSUPP;
79         }
80
81         return 0;
82 }
83
84 static int
85 tc_act_parse_police(struct mlx5e_tc_act_parse_state *parse_state,
86                     const struct flow_action_entry *act,
87                     struct mlx5e_priv *priv,
88                     struct mlx5_flow_attr *attr)
89 {
90         enum mlx5_flow_namespace_type ns =  mlx5e_get_flow_namespace(parse_state->flow);
91         struct mlx5e_flow_meter_params *params = &attr->meter_attr.params;
92         int err;
93
94         err = fill_meter_params_from_act(act, params);
95         if (err)
96                 return err;
97
98         if (params->mtu) {
99                 if (!(mlx5_fs_get_capabilities(priv->mdev, ns) &
100                       MLX5_FLOW_STEERING_CAP_MATCH_RANGES))
101                         return -EOPNOTSUPP;
102
103                 attr->action |= MLX5_FLOW_CONTEXT_ACTION_FWD_DEST;
104                 attr->flags |= MLX5_ATTR_FLAG_MTU;
105         } else {
106                 attr->action |= MLX5_FLOW_CONTEXT_ACTION_EXECUTE_ASO;
107                 attr->exe_aso_type = MLX5_EXE_ASO_FLOW_METER;
108         }
109
110         return 0;
111 }
112
113 static bool
114 tc_act_is_multi_table_act_police(struct mlx5e_priv *priv,
115                                  const struct flow_action_entry *act,
116                                  struct mlx5_flow_attr *attr)
117 {
118         return true;
119 }
120
121 static int
122 tc_act_police_offload(struct mlx5e_priv *priv,
123                       struct flow_offload_action *fl_act,
124                       struct flow_action_entry *act)
125 {
126         struct mlx5e_flow_meter_params params = {};
127         struct mlx5e_flow_meter_handle *meter;
128         int err = 0;
129
130         err = police_act_validate(act, fl_act->extack);
131         if (err)
132                 return err;
133
134         err = fill_meter_params_from_act(act, &params);
135         if (err)
136                 return err;
137
138         meter = mlx5e_tc_meter_get(priv->mdev, &params);
139         if (IS_ERR(meter) && PTR_ERR(meter) == -ENOENT) {
140                 meter = mlx5e_tc_meter_replace(priv->mdev, &params);
141         } else if (!IS_ERR(meter)) {
142                 err = mlx5e_tc_meter_update(meter, &params);
143                 mlx5e_tc_meter_put(meter);
144         }
145
146         if (IS_ERR(meter)) {
147                 NL_SET_ERR_MSG_MOD(fl_act->extack, "Failed to get flow meter");
148                 mlx5_core_err(priv->mdev, "Failed to get flow meter %d\n", params.index);
149                 err = PTR_ERR(meter);
150         }
151
152         return err;
153 }
154
155 static int
156 tc_act_police_destroy(struct mlx5e_priv *priv,
157                       struct flow_offload_action *fl_act)
158 {
159         struct mlx5e_flow_meter_params params = {};
160         struct mlx5e_flow_meter_handle *meter;
161
162         params.index = fl_act->index;
163         meter = mlx5e_tc_meter_get(priv->mdev, &params);
164         if (IS_ERR(meter)) {
165                 NL_SET_ERR_MSG_MOD(fl_act->extack, "Failed to get flow meter");
166                 mlx5_core_err(priv->mdev, "Failed to get flow meter %d\n", params.index);
167                 return PTR_ERR(meter);
168         }
169         /* first put for the get and second for cleanup */
170         mlx5e_tc_meter_put(meter);
171         mlx5e_tc_meter_put(meter);
172         return 0;
173 }
174
175 static int
176 tc_act_police_stats(struct mlx5e_priv *priv,
177                     struct flow_offload_action *fl_act)
178 {
179         struct mlx5e_flow_meter_params params = {};
180         struct mlx5e_flow_meter_handle *meter;
181         u64 bytes, packets, drops, lastuse;
182
183         params.index = fl_act->index;
184         meter = mlx5e_tc_meter_get(priv->mdev, &params);
185         if (IS_ERR(meter)) {
186                 NL_SET_ERR_MSG_MOD(fl_act->extack, "Failed to get flow meter");
187                 mlx5_core_err(priv->mdev, "Failed to get flow meter %d\n", params.index);
188                 return PTR_ERR(meter);
189         }
190
191         mlx5e_tc_meter_get_stats(meter, &bytes, &packets, &drops, &lastuse);
192         flow_stats_update(&fl_act->stats, bytes, packets, drops, lastuse,
193                           FLOW_ACTION_HW_STATS_DELAYED);
194         mlx5e_tc_meter_put(meter);
195         return 0;
196 }
197
198 static bool
199 tc_act_police_get_branch_ctrl(const struct flow_action_entry *act,
200                               struct mlx5e_tc_act_branch_ctrl *cond_true,
201                               struct mlx5e_tc_act_branch_ctrl *cond_false)
202 {
203         cond_true->act_id = act->police.notexceed.act_id;
204         cond_true->extval = act->police.notexceed.extval;
205
206         cond_false->act_id = act->police.exceed.act_id;
207         cond_false->extval = act->police.exceed.extval;
208         return true;
209 }
210
211 struct mlx5e_tc_act mlx5e_tc_act_police = {
212         .can_offload = tc_act_can_offload_police,
213         .parse_action = tc_act_parse_police,
214         .is_multi_table_act = tc_act_is_multi_table_act_police,
215         .offload_action = tc_act_police_offload,
216         .destroy_action = tc_act_police_destroy,
217         .stats_action = tc_act_police_stats,
218         .get_branch_ctrl = tc_act_police_get_branch_ctrl,
219 };