]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/mlx5/mlx5_core/mlx5_fs_cmd.c
MFV r337195: 9454 ::zfs_blkstats should count embedded blocks
[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)] = {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 }