1 /*-
2 * Copyright (c) 2013-2017, Mellanox Technologies, Ltd. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 *
25 * $FreeBSD: stable/12/sys/dev/mlx5/mlx5_core/mlx5_fs_cmd.c 330647 2018-03-08 10:43:42Z hselasky $
26 */
27
28 #include <linux/types.h>
29 #include <linux/module.h>
30 #include <dev/mlx5/mlx5_ifc.h>
31 #include <dev/mlx5/device.h>
32 #include <dev/mlx5/fs.h>
33
34 #include "fs_core.h"
35 #include "mlx5_core.h"
36
mlx5_cmd_update_root_ft(struct mlx5_core_dev * dev,enum fs_ft_type type,unsigned int id)37 int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev,
38 enum fs_ft_type type,
39 unsigned int id)
40 {
41 u32 in[MLX5_ST_SZ_DW(set_flow_table_root_in)] = {0};
42 u32 out[MLX5_ST_SZ_DW(set_flow_table_root_out)] = {0};
43
44 if (!dev)
45 return -EINVAL;
46
47 MLX5_SET(set_flow_table_root_in, in, opcode,
48 MLX5_CMD_OP_SET_FLOW_TABLE_ROOT);
49 MLX5_SET(set_flow_table_root_in, in, table_type, type);
50 MLX5_SET(set_flow_table_root_in, in, table_id, id);
51
52 return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
53 }
54
mlx5_cmd_fs_create_ft(struct mlx5_core_dev * dev,u16 vport,enum fs_ft_type type,unsigned int level,unsigned int log_size,unsigned int * table_id)55 int mlx5_cmd_fs_create_ft(struct mlx5_core_dev *dev,
56 u16 vport,
57 enum fs_ft_type type, unsigned int level,
58 unsigned int log_size, unsigned int *table_id)
59 {
60 u32 in[MLX5_ST_SZ_DW(create_flow_table_in)] = {0};
61 u32 out[MLX5_ST_SZ_DW(create_flow_table_out)] = {0};
62 int err;
63
64 if (!dev)
65 return -EINVAL;
66
67 MLX5_SET(create_flow_table_in, in, opcode,
68 MLX5_CMD_OP_CREATE_FLOW_TABLE);
69
70 MLX5_SET(create_flow_table_in, in, table_type, type);
71 MLX5_SET(create_flow_table_in, in, flow_table_context.level, level);
72 MLX5_SET(create_flow_table_in, in, flow_table_context.log_size,
73 log_size);
74 if (vport) {
75 MLX5_SET(create_flow_table_in, in, vport_number, vport);
76 MLX5_SET(create_flow_table_in, in, other_vport, 1);
77 }
78
79 err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
80 if (!err)
81 *table_id = MLX5_GET(create_flow_table_out, out, table_id);
82
83 return err;
84 }
85
mlx5_cmd_fs_destroy_ft(struct mlx5_core_dev * dev,u16 vport,enum fs_ft_type type,unsigned int table_id)86 int mlx5_cmd_fs_destroy_ft(struct mlx5_core_dev *dev,
87 u16 vport,
88 enum fs_ft_type type, unsigned int table_id)
89 {
90 u32 in[MLX5_ST_SZ_DW(destroy_flow_table_in)] = {0};
91 u32 out[MLX5_ST_SZ_DW(destroy_flow_table_out)] = {0};
92
93 if (!dev)
94 return -EINVAL;
95
96 MLX5_SET(destroy_flow_table_in, in, opcode,
97 MLX5_CMD_OP_DESTROY_FLOW_TABLE);
98 MLX5_SET(destroy_flow_table_in, in, table_type, type);
99 MLX5_SET(destroy_flow_table_in, in, table_id, table_id);
100 if (vport) {
101 MLX5_SET(destroy_flow_table_in, in, vport_number, vport);
102 MLX5_SET(destroy_flow_table_in, in, other_vport, 1);
103 }
104
105 return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
106 }
107
mlx5_cmd_fs_create_fg(struct mlx5_core_dev * dev,u32 * in,u16 vport,enum fs_ft_type type,unsigned int table_id,unsigned int * group_id)108 int mlx5_cmd_fs_create_fg(struct mlx5_core_dev *dev,
109 u32 *in,
110 u16 vport,
111 enum fs_ft_type type, unsigned int table_id,
112 unsigned int *group_id)
113 {
114 u32 out[MLX5_ST_SZ_DW(create_flow_group_out)] = {0};
115 int err;
116 int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
117 if (!dev)
118 return -EINVAL;
119
120 MLX5_SET(create_flow_group_in, in, opcode,
121 MLX5_CMD_OP_CREATE_FLOW_GROUP);
122 MLX5_SET(create_flow_group_in, in, table_type, type);
123 MLX5_SET(create_flow_group_in, in, table_id, table_id);
124 if (vport) {
125 MLX5_SET(create_flow_group_in, in, vport_number, vport);
126 MLX5_SET(create_flow_group_in, in, other_vport, 1);
127 }
128
129 err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
130 if (!err)
131 *group_id = MLX5_GET(create_flow_group_out, out, group_id);
132
133 return err;
134 }
135
mlx5_cmd_fs_destroy_fg(struct mlx5_core_dev * dev,u16 vport,enum fs_ft_type type,unsigned int table_id,unsigned int group_id)136 int mlx5_cmd_fs_destroy_fg(struct mlx5_core_dev *dev,
137 u16 vport,
138 enum fs_ft_type type, unsigned int table_id,
139 unsigned int group_id)
140 {
141 u32 in[MLX5_ST_SZ_DW(destroy_flow_group_in)] = {0};
142 u32 out[MLX5_ST_SZ_DW(destroy_flow_group_out)] = {0};
143
144 if (!dev)
145 return -EINVAL;
146
147 MLX5_SET(destroy_flow_group_in, in, opcode,
148 MLX5_CMD_OP_DESTROY_FLOW_GROUP);
149 MLX5_SET(destroy_flow_group_in, in, table_type, type);
150 MLX5_SET(destroy_flow_group_in, in, table_id, table_id);
151 MLX5_SET(destroy_flow_group_in, in, group_id, group_id);
152 if (vport) {
153 MLX5_SET(destroy_flow_group_in, in, vport_number, vport);
154 MLX5_SET(destroy_flow_group_in, in, other_vport, 1);
155 }
156
157 return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
158 }
159
mlx5_cmd_fs_set_fte(struct mlx5_core_dev * dev,u16 vport,enum fs_fte_status * fte_status,u32 * match_val,enum fs_ft_type type,unsigned int table_id,unsigned int index,unsigned int group_id,unsigned int flow_tag,unsigned short action,int dest_size,struct list_head * dests)160 int mlx5_cmd_fs_set_fte(struct mlx5_core_dev *dev,
161 u16 vport,
162 enum fs_fte_status *fte_status,
163 u32 *match_val,
164 enum fs_ft_type type, unsigned int table_id,
165 unsigned int index, unsigned int group_id,
166 unsigned int flow_tag,
167 unsigned short action, int dest_size,
168 struct list_head *dests) /* mlx5_flow_desination */
169 {
170 u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {0};
171 u32 *in;
172 unsigned int inlen;
173 struct mlx5_flow_rule *dst;
174 void *in_flow_context;
175 void *in_match_value;
176 void *in_dests;
177 int err;
178 int opmod = 0;
179 int modify_mask = 0;
180 int atomic_mod_cap;
181
182 if (action != MLX5_FLOW_CONTEXT_ACTION_FWD_DEST)
183 dest_size = 0;
184
185 inlen = MLX5_ST_SZ_BYTES(set_fte_in) +
186 dest_size * MLX5_ST_SZ_BYTES(dest_format_struct);
187
188 if (!dev)
189 return -EINVAL;
190
191 if (*fte_status & FS_FTE_STATUS_EXISTING) {
192 atomic_mod_cap = MLX5_CAP_FLOWTABLE(dev,
193 flow_table_properties_nic_receive.
194 flow_modify_en);
195 if (!atomic_mod_cap)
196 return -ENOTSUPP;
197 opmod = 1;
198 modify_mask = 1 <<
199 MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST;
200 }
201
202 in = mlx5_vzalloc(inlen);
203 if (!in) {
204 mlx5_core_warn(dev, "failed to allocate inbox\n");
205 return -ENOMEM;
206 }
207
208 MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY);
209 MLX5_SET(set_fte_in, in, op_mod, opmod);
210 MLX5_SET(set_fte_in, in, modify_enable_mask, modify_mask);
211 MLX5_SET(set_fte_in, in, table_type, type);
212 MLX5_SET(set_fte_in, in, table_id, table_id);
213 MLX5_SET(set_fte_in, in, flow_index, index);
214 if (vport) {
215 MLX5_SET(set_fte_in, in, vport_number, vport);
216 MLX5_SET(set_fte_in, in, other_vport, 1);
217 }
218
219 in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context);
220 MLX5_SET(flow_context, in_flow_context, group_id, group_id);
221 MLX5_SET(flow_context, in_flow_context, flow_tag, flow_tag);
222 MLX5_SET(flow_context, in_flow_context, action, action);
223 MLX5_SET(flow_context, in_flow_context, destination_list_size,
224 dest_size);
225 in_match_value = MLX5_ADDR_OF(flow_context, in_flow_context,
226 match_value);
227 memcpy(in_match_value, match_val, MLX5_ST_SZ_BYTES(fte_match_param));
228 if (dest_size) {
229 in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination);
230 list_for_each_entry(dst, dests, base.list) {
231 unsigned int id;
232
233 MLX5_SET(dest_format_struct, in_dests, destination_type,
234 dst->dest_attr.type);
235 if (dst->dest_attr.type ==
236 MLX5_FLOW_CONTEXT_DEST_TYPE_FLOW_TABLE)
237 id = dst->dest_attr.ft->id;
238 else
239 id = dst->dest_attr.tir_num;
240 MLX5_SET(dest_format_struct, in_dests, destination_id, id);
241 in_dests += MLX5_ST_SZ_BYTES(dest_format_struct);
242 }
243 }
244
245 err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
246 if (!err)
247 *fte_status |= FS_FTE_STATUS_EXISTING;
248
249 kvfree(in);
250
251 return err;
252 }
253
mlx5_cmd_fs_delete_fte(struct mlx5_core_dev * dev,u16 vport,enum fs_fte_status * fte_status,enum fs_ft_type type,unsigned int table_id,unsigned int index)254 int mlx5_cmd_fs_delete_fte(struct mlx5_core_dev *dev,
255 u16 vport,
256 enum fs_fte_status *fte_status,
257 enum fs_ft_type type, unsigned int table_id,
258 unsigned int index)
259 {
260 u32 in[MLX5_ST_SZ_DW(delete_fte_in)] = {0};
261 u32 out[MLX5_ST_SZ_DW(delete_fte_out)] = {0};
262 int err;
263
264 if (!(*fte_status & FS_FTE_STATUS_EXISTING))
265 return 0;
266
267 if (!dev)
268 return -EINVAL;
269
270 MLX5_SET(delete_fte_in, in, opcode, MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY);
271 MLX5_SET(delete_fte_in, in, table_type, type);
272 MLX5_SET(delete_fte_in, in, table_id, table_id);
273 MLX5_SET(delete_fte_in, in, flow_index, index);
274 if (vport) {
275 MLX5_SET(delete_fte_in, in, vport_number, vport);
276 MLX5_SET(delete_fte_in, in, other_vport, 1);
277 }
278
279 err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
280 if (!err)
281 *fte_status = 0;
282
283 return err;
284 }
285