xref: /freebsd-13-stable/sys/dev/mlx5/mlx5_core/mlx5_fs_cmd.c (revision f8167e0404dab9ffeaca95853dd237ab7c587f82)
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 
26 #include "opt_rss.h"
27 #include "opt_ratelimit.h"
28 
29 #include <linux/types.h>
30 #include <linux/module.h>
31 #include <dev/mlx5/mlx5_ifc.h>
32 #include <dev/mlx5/device.h>
33 #include <dev/mlx5/fs.h>
34 
35 #include <dev/mlx5/mlx5_core/fs_core.h>
36 #include <dev/mlx5/mlx5_core/mlx5_core.h>
37 
mlx5_cmd_update_root_ft(struct mlx5_core_dev * dev,enum fs_ft_type type,unsigned int id)38 int mlx5_cmd_update_root_ft(struct mlx5_core_dev *dev,
39 			    enum fs_ft_type type,
40 			    unsigned int id)
41 {
42 	u32 in[MLX5_ST_SZ_DW(set_flow_table_root_in)] = {0};
43 	u32 out[MLX5_ST_SZ_DW(set_flow_table_root_out)] = {0};
44 
45 	if (!dev)
46 		return -EINVAL;
47 
48 	MLX5_SET(set_flow_table_root_in, in, opcode,
49 		 MLX5_CMD_OP_SET_FLOW_TABLE_ROOT);
50 	MLX5_SET(set_flow_table_root_in, in, table_type, type);
51 	MLX5_SET(set_flow_table_root_in, in, table_id, id);
52 
53 	return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
54 }
55 
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)56 int mlx5_cmd_fs_create_ft(struct mlx5_core_dev *dev,
57 			  u16 vport,
58 			  enum fs_ft_type type, unsigned int level,
59 			  unsigned int log_size, unsigned int *table_id)
60 {
61 	u32 in[MLX5_ST_SZ_DW(create_flow_table_in)] = {0};
62 	u32 out[MLX5_ST_SZ_DW(create_flow_table_out)] = {0};
63 	int err;
64 
65 	if (!dev)
66 		return -EINVAL;
67 
68 	MLX5_SET(create_flow_table_in, in, opcode,
69 		 MLX5_CMD_OP_CREATE_FLOW_TABLE);
70 
71 	MLX5_SET(create_flow_table_in, in, table_type, type);
72 	MLX5_SET(create_flow_table_in, in, flow_table_context.level, level);
73 	MLX5_SET(create_flow_table_in, in, flow_table_context.log_size,
74 		 log_size);
75 	if (vport) {
76 		MLX5_SET(create_flow_table_in, in, vport_number, vport);
77 		MLX5_SET(create_flow_table_in, in, other_vport, 1);
78 	}
79 
80 	err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
81 	if (!err)
82 		*table_id = MLX5_GET(create_flow_table_out, out, table_id);
83 
84 	return err;
85 }
86 
mlx5_cmd_fs_destroy_ft(struct mlx5_core_dev * dev,u16 vport,enum fs_ft_type type,unsigned int table_id)87 int mlx5_cmd_fs_destroy_ft(struct mlx5_core_dev *dev,
88 			   u16 vport,
89 			   enum fs_ft_type type, unsigned int table_id)
90 {
91 	u32 in[MLX5_ST_SZ_DW(destroy_flow_table_in)] = {0};
92 	u32 out[MLX5_ST_SZ_DW(destroy_flow_table_out)] = {0};
93 
94 	if (!dev)
95 		return -EINVAL;
96 
97 	MLX5_SET(destroy_flow_table_in, in, opcode,
98 		 MLX5_CMD_OP_DESTROY_FLOW_TABLE);
99 	MLX5_SET(destroy_flow_table_in, in, table_type, type);
100 	MLX5_SET(destroy_flow_table_in, in, table_id, table_id);
101 	if (vport) {
102 		MLX5_SET(destroy_flow_table_in, in, vport_number, vport);
103 		MLX5_SET(destroy_flow_table_in, in, other_vport, 1);
104 	}
105 
106 	return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
107 }
108 
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)109 int mlx5_cmd_fs_create_fg(struct mlx5_core_dev *dev,
110 			  u32 *in,
111 			  u16 vport,
112 			  enum fs_ft_type type, unsigned int table_id,
113 			  unsigned int *group_id)
114 {
115 	u32 out[MLX5_ST_SZ_DW(create_flow_group_out)] = {0};
116 	int err;
117 	int inlen = MLX5_ST_SZ_BYTES(create_flow_group_in);
118 	if (!dev)
119 		return -EINVAL;
120 
121 	MLX5_SET(create_flow_group_in, in, opcode,
122 		 MLX5_CMD_OP_CREATE_FLOW_GROUP);
123 	MLX5_SET(create_flow_group_in, in, table_type, type);
124 	MLX5_SET(create_flow_group_in, in, table_id, table_id);
125 	if (vport) {
126 		MLX5_SET(create_flow_group_in, in, vport_number, vport);
127 		MLX5_SET(create_flow_group_in, in, other_vport, 1);
128 	}
129 
130 	err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
131 	if (!err)
132 		*group_id = MLX5_GET(create_flow_group_out, out, group_id);
133 
134 	return err;
135 }
136 
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)137 int mlx5_cmd_fs_destroy_fg(struct mlx5_core_dev *dev,
138 			   u16 vport,
139 			   enum fs_ft_type type, unsigned int table_id,
140 			   unsigned int group_id)
141 {
142 	u32 in[MLX5_ST_SZ_DW(destroy_flow_group_in)] = {0};
143 	u32 out[MLX5_ST_SZ_DW(destroy_flow_group_out)] = {0};
144 
145 	if (!dev)
146 		return -EINVAL;
147 
148 	MLX5_SET(destroy_flow_group_in, in, opcode,
149 		 MLX5_CMD_OP_DESTROY_FLOW_GROUP);
150 	MLX5_SET(destroy_flow_group_in, in, table_type, type);
151 	MLX5_SET(destroy_flow_group_in, in, table_id,   table_id);
152 	MLX5_SET(destroy_flow_group_in, in, group_id, group_id);
153 	if (vport) {
154 		MLX5_SET(destroy_flow_group_in, in, vport_number, vport);
155 		MLX5_SET(destroy_flow_group_in, in, other_vport, 1);
156 	}
157 
158 	return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
159 }
160 
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)161 int mlx5_cmd_fs_set_fte(struct mlx5_core_dev *dev,
162 			u16 vport,
163 			enum fs_fte_status *fte_status,
164 			u32 *match_val,
165 			enum fs_ft_type type, unsigned int table_id,
166 			unsigned int index, unsigned int group_id,
167 			unsigned int flow_tag,
168 			unsigned short action, int dest_size,
169 			struct list_head *dests)  /* mlx5_flow_desination */
170 {
171 	u32 out[MLX5_ST_SZ_DW(set_fte_out)] = {0};
172 	u32 *in;
173 	unsigned int inlen;
174 	struct mlx5_flow_rule *dst;
175 	void *in_flow_context;
176 	void *in_match_value;
177 	void *in_dests;
178 	int err;
179 	int opmod = 0;
180 	int modify_mask = 0;
181 	int atomic_mod_cap;
182 
183 	if (action != MLX5_FLOW_CONTEXT_ACTION_FWD_DEST)
184 		dest_size = 0;
185 
186 	inlen = MLX5_ST_SZ_BYTES(set_fte_in) +
187 		dest_size * MLX5_ST_SZ_BYTES(dest_format_struct);
188 
189 	if (!dev)
190 		return -EINVAL;
191 
192 	if (*fte_status & FS_FTE_STATUS_EXISTING) {
193 		atomic_mod_cap = MLX5_CAP_FLOWTABLE(dev,
194 						    flow_table_properties_nic_receive.
195 						    flow_modify_en);
196 		if (!atomic_mod_cap)
197 			return -ENOTSUPP;
198 		opmod = 1;
199 		modify_mask = 1 <<
200 			MLX5_SET_FTE_MODIFY_ENABLE_MASK_DESTINATION_LIST;
201 	}
202 
203 	in = mlx5_vzalloc(inlen);
204 	if (!in) {
205 		mlx5_core_warn(dev, "failed to allocate inbox\n");
206 		return -ENOMEM;
207 	}
208 
209 	MLX5_SET(set_fte_in, in, opcode, MLX5_CMD_OP_SET_FLOW_TABLE_ENTRY);
210 	MLX5_SET(set_fte_in, in, op_mod, opmod);
211 	MLX5_SET(set_fte_in, in, modify_enable_mask, modify_mask);
212 	MLX5_SET(set_fte_in, in, table_type, type);
213 	MLX5_SET(set_fte_in, in, table_id,   table_id);
214 	MLX5_SET(set_fte_in, in, flow_index, index);
215 	if (vport) {
216 		MLX5_SET(set_fte_in, in, vport_number, vport);
217 		MLX5_SET(set_fte_in, in, other_vport, 1);
218 	}
219 
220 	in_flow_context = MLX5_ADDR_OF(set_fte_in, in, flow_context);
221 	MLX5_SET(flow_context, in_flow_context, group_id, group_id);
222 	MLX5_SET(flow_context, in_flow_context, flow_tag, flow_tag);
223 	MLX5_SET(flow_context, in_flow_context, action, action);
224 	MLX5_SET(flow_context, in_flow_context, destination_list_size,
225 		 dest_size);
226 	in_match_value = MLX5_ADDR_OF(flow_context, in_flow_context,
227 				      match_value);
228 	memcpy(in_match_value, match_val, MLX5_ST_SZ_BYTES(fte_match_param));
229 	if (dest_size) {
230 		in_dests = MLX5_ADDR_OF(flow_context, in_flow_context, destination);
231 		list_for_each_entry(dst, dests, base.list) {
232 			unsigned int id;
233 
234 			MLX5_SET(dest_format_struct, in_dests, destination_type,
235 				 dst->dest_attr.type);
236 			if (dst->dest_attr.type ==
237 				MLX5_FLOW_CONTEXT_DEST_TYPE_FLOW_TABLE)
238 				id = dst->dest_attr.ft->id;
239 			else
240 				id = dst->dest_attr.tir_num;
241 			MLX5_SET(dest_format_struct, in_dests, destination_id, id);
242 			in_dests += MLX5_ST_SZ_BYTES(dest_format_struct);
243 		}
244 	}
245 
246 	err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out));
247 	if (!err)
248 		*fte_status |= FS_FTE_STATUS_EXISTING;
249 
250 	kvfree(in);
251 
252 	return err;
253 }
254 
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)255 int mlx5_cmd_fs_delete_fte(struct mlx5_core_dev *dev,
256 			   u16 vport,
257 			   enum fs_fte_status *fte_status,
258 			   enum fs_ft_type type, unsigned int table_id,
259 			   unsigned int index)
260 {
261 	u32 in[MLX5_ST_SZ_DW(delete_fte_in)] = {0};
262 	u32 out[MLX5_ST_SZ_DW(delete_fte_out)] = {0};
263 	int err;
264 
265 	if (!(*fte_status & FS_FTE_STATUS_EXISTING))
266 		return 0;
267 
268 	if (!dev)
269 		return -EINVAL;
270 
271 	MLX5_SET(delete_fte_in, in, opcode, MLX5_CMD_OP_DELETE_FLOW_TABLE_ENTRY);
272 	MLX5_SET(delete_fte_in, in, table_type, type);
273 	MLX5_SET(delete_fte_in, in, table_id, table_id);
274 	MLX5_SET(delete_fte_in, in, flow_index, index);
275 	if (vport) {
276 		MLX5_SET(delete_fte_in, in, vport_number,  vport);
277 		MLX5_SET(delete_fte_in, in, other_vport, 1);
278 	}
279 
280 	err =  mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out));
281 	if (!err)
282 		*fte_status = 0;
283 
284 	return err;
285 }
286