]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/mlx5/mlx5_core/mlx5_fs_cmd.c
MFC r325648:
[FreeBSD/FreeBSD.git] / sys / dev / mlx5 / mlx5_core / mlx5_fs_cmd.c
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)];
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
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)];
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
94 int 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
118 int 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
149 int 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
175 int 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
270 int 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 }