xref: /freebsd/sys/dev/mlx5/mlx5_core/mlx5_fs_cmd.c (revision b00ab754)
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 <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 
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 
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 
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 
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 
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 
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 
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