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