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