]>
Commit | Line | Data |
---|---|---|
afb736e9 AV |
1 | /* |
2 | * Copyright (c) 2013-2015, Mellanox Technologies, Ltd. All rights reserved. | |
3 | * | |
4 | * This software is available to you under a choice of one of two | |
5 | * licenses. You may choose to be licensed under the terms of the GNU | |
6 | * General Public License (GPL) Version 2, available from the file | |
7 | * COPYING in the main directory of this source tree, or the | |
8 | * OpenIB.org BSD license below: | |
9 | * | |
10 | * Redistribution and use in source and binary forms, with or | |
11 | * without modification, are permitted provided that the following | |
12 | * conditions are met: | |
13 | * | |
14 | * - Redistributions of source code must retain the above | |
15 | * copyright notice, this list of conditions and the following | |
16 | * disclaimer. | |
17 | * | |
18 | * - Redistributions in binary form must reproduce the above | |
19 | * copyright notice, this list of conditions and the following | |
20 | * disclaimer in the documentation and/or other materials | |
21 | * provided with the distribution. | |
22 | * | |
23 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | |
24 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | |
25 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | |
26 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS | |
27 | * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN | |
28 | * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
29 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |
30 | * SOFTWARE. | |
31 | */ | |
32 | ||
33 | #include <linux/mlx5/driver.h> | |
34 | #include "mlx5_core.h" | |
8d7f9ecb | 35 | #include <linux/mlx5/transobj.h> |
afb736e9 | 36 | |
8d7f9ecb | 37 | int mlx5_core_alloc_transport_domain(struct mlx5_core_dev *dev, u32 *tdn) |
56508b50 | 38 | { |
c4f287c4 SM |
39 | u32 in[MLX5_ST_SZ_DW(alloc_transport_domain_in)] = {0}; |
40 | u32 out[MLX5_ST_SZ_DW(alloc_transport_domain_out)] = {0}; | |
56508b50 AS |
41 | int err; |
42 | ||
56508b50 AS |
43 | MLX5_SET(alloc_transport_domain_in, in, opcode, |
44 | MLX5_CMD_OP_ALLOC_TRANSPORT_DOMAIN); | |
45 | ||
c4f287c4 | 46 | err = mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); |
56508b50 AS |
47 | if (!err) |
48 | *tdn = MLX5_GET(alloc_transport_domain_out, out, | |
49 | transport_domain); | |
50 | ||
51 | return err; | |
52 | } | |
8d7f9ecb | 53 | EXPORT_SYMBOL(mlx5_core_alloc_transport_domain); |
56508b50 | 54 | |
8d7f9ecb | 55 | void mlx5_core_dealloc_transport_domain(struct mlx5_core_dev *dev, u32 tdn) |
56508b50 | 56 | { |
c4f287c4 SM |
57 | u32 in[MLX5_ST_SZ_DW(dealloc_transport_domain_in)] = {0}; |
58 | u32 out[MLX5_ST_SZ_DW(dealloc_transport_domain_out)] = {0}; | |
56508b50 AS |
59 | |
60 | MLX5_SET(dealloc_transport_domain_in, in, opcode, | |
61 | MLX5_CMD_OP_DEALLOC_TRANSPORT_DOMAIN); | |
62 | MLX5_SET(dealloc_transport_domain_in, in, transport_domain, tdn); | |
c4f287c4 | 63 | mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); |
56508b50 | 64 | } |
8d7f9ecb | 65 | EXPORT_SYMBOL(mlx5_core_dealloc_transport_domain); |
56508b50 | 66 | |
7db22ffb | 67 | int mlx5_core_create_rq(struct mlx5_core_dev *dev, u32 *in, int inlen, u32 *rqn) |
afb736e9 | 68 | { |
c4f287c4 | 69 | u32 out[MLX5_ST_SZ_DW(create_rq_out)] = {0}; |
afb736e9 AV |
70 | int err; |
71 | ||
72 | MLX5_SET(create_rq_in, in, opcode, MLX5_CMD_OP_CREATE_RQ); | |
c4f287c4 | 73 | err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); |
afb736e9 AV |
74 | if (!err) |
75 | *rqn = MLX5_GET(create_rq_out, out, rqn); | |
76 | ||
77 | return err; | |
78 | } | |
16bd0201 | 79 | EXPORT_SYMBOL(mlx5_core_create_rq); |
afb736e9 | 80 | |
7db22ffb | 81 | int mlx5_core_modify_rq(struct mlx5_core_dev *dev, u32 rqn, u32 *in, int inlen) |
afb736e9 AV |
82 | { |
83 | u32 out[MLX5_ST_SZ_DW(modify_rq_out)]; | |
84 | ||
85 | MLX5_SET(modify_rq_in, in, rqn, rqn); | |
86 | MLX5_SET(modify_rq_in, in, opcode, MLX5_CMD_OP_MODIFY_RQ); | |
87 | ||
88 | memset(out, 0, sizeof(out)); | |
c4f287c4 | 89 | return mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); |
afb736e9 | 90 | } |
8d7f9ecb | 91 | EXPORT_SYMBOL(mlx5_core_modify_rq); |
afb736e9 | 92 | |
7db22ffb | 93 | void mlx5_core_destroy_rq(struct mlx5_core_dev *dev, u32 rqn) |
afb736e9 | 94 | { |
c4f287c4 SM |
95 | u32 in[MLX5_ST_SZ_DW(destroy_rq_in)] = {0}; |
96 | u32 out[MLX5_ST_SZ_DW(destroy_rq_out)] = {0}; | |
afb736e9 AV |
97 | |
98 | MLX5_SET(destroy_rq_in, in, opcode, MLX5_CMD_OP_DESTROY_RQ); | |
99 | MLX5_SET(destroy_rq_in, in, rqn, rqn); | |
c4f287c4 | 100 | mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); |
afb736e9 | 101 | } |
16bd0201 | 102 | EXPORT_SYMBOL(mlx5_core_destroy_rq); |
afb736e9 | 103 | |
6d2f89df | 104 | int mlx5_core_query_rq(struct mlx5_core_dev *dev, u32 rqn, u32 *out) |
105 | { | |
106 | u32 in[MLX5_ST_SZ_DW(query_rq_in)] = {0}; | |
107 | int outlen = MLX5_ST_SZ_BYTES(query_rq_out); | |
108 | ||
109 | MLX5_SET(query_rq_in, in, opcode, MLX5_CMD_OP_QUERY_RQ); | |
110 | MLX5_SET(query_rq_in, in, rqn, rqn); | |
111 | ||
c4f287c4 | 112 | return mlx5_cmd_exec(dev, in, sizeof(in), out, outlen); |
6d2f89df | 113 | } |
114 | EXPORT_SYMBOL(mlx5_core_query_rq); | |
115 | ||
7db22ffb | 116 | int mlx5_core_create_sq(struct mlx5_core_dev *dev, u32 *in, int inlen, u32 *sqn) |
afb736e9 | 117 | { |
c4f287c4 | 118 | u32 out[MLX5_ST_SZ_DW(create_sq_out)] = {0}; |
afb736e9 AV |
119 | int err; |
120 | ||
121 | MLX5_SET(create_sq_in, in, opcode, MLX5_CMD_OP_CREATE_SQ); | |
c4f287c4 | 122 | err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); |
afb736e9 AV |
123 | if (!err) |
124 | *sqn = MLX5_GET(create_sq_out, out, sqn); | |
125 | ||
126 | return err; | |
127 | } | |
128 | ||
7db22ffb | 129 | int mlx5_core_modify_sq(struct mlx5_core_dev *dev, u32 sqn, u32 *in, int inlen) |
afb736e9 | 130 | { |
c4f287c4 | 131 | u32 out[MLX5_ST_SZ_DW(modify_sq_out)] = {0}; |
afb736e9 AV |
132 | |
133 | MLX5_SET(modify_sq_in, in, sqn, sqn); | |
134 | MLX5_SET(modify_sq_in, in, opcode, MLX5_CMD_OP_MODIFY_SQ); | |
c4f287c4 | 135 | return mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); |
afb736e9 | 136 | } |
8d7f9ecb | 137 | EXPORT_SYMBOL(mlx5_core_modify_sq); |
afb736e9 | 138 | |
7db22ffb | 139 | void mlx5_core_destroy_sq(struct mlx5_core_dev *dev, u32 sqn) |
afb736e9 | 140 | { |
c4f287c4 SM |
141 | u32 in[MLX5_ST_SZ_DW(destroy_sq_in)] = {0}; |
142 | u32 out[MLX5_ST_SZ_DW(destroy_sq_out)] = {0}; | |
afb736e9 AV |
143 | |
144 | MLX5_SET(destroy_sq_in, in, opcode, MLX5_CMD_OP_DESTROY_SQ); | |
145 | MLX5_SET(destroy_sq_in, in, sqn, sqn); | |
c4f287c4 | 146 | mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); |
afb736e9 AV |
147 | } |
148 | ||
6d2f89df | 149 | int mlx5_core_query_sq(struct mlx5_core_dev *dev, u32 sqn, u32 *out) |
150 | { | |
151 | u32 in[MLX5_ST_SZ_DW(query_sq_in)] = {0}; | |
152 | int outlen = MLX5_ST_SZ_BYTES(query_sq_out); | |
153 | ||
154 | MLX5_SET(query_sq_in, in, opcode, MLX5_CMD_OP_QUERY_SQ); | |
155 | MLX5_SET(query_sq_in, in, sqn, sqn); | |
c4f287c4 | 156 | return mlx5_cmd_exec(dev, in, sizeof(in), out, outlen); |
6d2f89df | 157 | } |
158 | EXPORT_SYMBOL(mlx5_core_query_sq); | |
159 | ||
28160771 EBE |
160 | int mlx5_core_query_sq_state(struct mlx5_core_dev *dev, u32 sqn, u8 *state) |
161 | { | |
162 | void *out; | |
163 | void *sqc; | |
164 | int inlen; | |
165 | int err; | |
166 | ||
167 | inlen = MLX5_ST_SZ_BYTES(query_sq_out); | |
168 | out = kvzalloc(inlen, GFP_KERNEL); | |
169 | if (!out) | |
170 | return -ENOMEM; | |
171 | ||
172 | err = mlx5_core_query_sq(dev, sqn, out); | |
173 | if (err) | |
174 | goto out; | |
175 | ||
176 | sqc = MLX5_ADDR_OF(query_sq_out, out, sq_context); | |
177 | *state = MLX5_GET(sqc, sqc, state); | |
178 | ||
179 | out: | |
180 | kvfree(out); | |
181 | return err; | |
182 | } | |
183 | EXPORT_SYMBOL_GPL(mlx5_core_query_sq_state); | |
184 | ||
7db22ffb HA |
185 | int mlx5_core_create_tir(struct mlx5_core_dev *dev, u32 *in, int inlen, |
186 | u32 *tirn) | |
afb736e9 | 187 | { |
c4f287c4 | 188 | u32 out[MLX5_ST_SZ_DW(create_tir_out)] = {0}; |
afb736e9 AV |
189 | int err; |
190 | ||
191 | MLX5_SET(create_tir_in, in, opcode, MLX5_CMD_OP_CREATE_TIR); | |
192 | ||
193 | memset(out, 0, sizeof(out)); | |
c4f287c4 | 194 | err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); |
afb736e9 AV |
195 | if (!err) |
196 | *tirn = MLX5_GET(create_tir_out, out, tirn); | |
197 | ||
198 | return err; | |
199 | } | |
8d7f9ecb | 200 | EXPORT_SYMBOL(mlx5_core_create_tir); |
afb736e9 | 201 | |
d9eea403 AS |
202 | int mlx5_core_modify_tir(struct mlx5_core_dev *dev, u32 tirn, u32 *in, |
203 | int inlen) | |
204 | { | |
c4f287c4 | 205 | u32 out[MLX5_ST_SZ_DW(modify_tir_out)] = {0}; |
d9eea403 AS |
206 | |
207 | MLX5_SET(modify_tir_in, in, tirn, tirn); | |
208 | MLX5_SET(modify_tir_in, in, opcode, MLX5_CMD_OP_MODIFY_TIR); | |
c4f287c4 | 209 | return mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); |
d9eea403 AS |
210 | } |
211 | ||
7db22ffb | 212 | void mlx5_core_destroy_tir(struct mlx5_core_dev *dev, u32 tirn) |
afb736e9 | 213 | { |
c4f287c4 SM |
214 | u32 in[MLX5_ST_SZ_DW(destroy_tir_in)] = {0}; |
215 | u32 out[MLX5_ST_SZ_DW(destroy_tir_out)] = {0}; | |
afb736e9 AV |
216 | |
217 | MLX5_SET(destroy_tir_in, in, opcode, MLX5_CMD_OP_DESTROY_TIR); | |
218 | MLX5_SET(destroy_tir_in, in, tirn, tirn); | |
c4f287c4 | 219 | mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); |
afb736e9 | 220 | } |
8d7f9ecb | 221 | EXPORT_SYMBOL(mlx5_core_destroy_tir); |
afb736e9 | 222 | |
7db22ffb HA |
223 | int mlx5_core_create_tis(struct mlx5_core_dev *dev, u32 *in, int inlen, |
224 | u32 *tisn) | |
afb736e9 | 225 | { |
c4f287c4 | 226 | u32 out[MLX5_ST_SZ_DW(create_tis_out)] = {0}; |
afb736e9 AV |
227 | int err; |
228 | ||
229 | MLX5_SET(create_tis_in, in, opcode, MLX5_CMD_OP_CREATE_TIS); | |
c4f287c4 | 230 | err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); |
afb736e9 AV |
231 | if (!err) |
232 | *tisn = MLX5_GET(create_tis_out, out, tisn); | |
233 | ||
234 | return err; | |
235 | } | |
8d7f9ecb | 236 | EXPORT_SYMBOL(mlx5_core_create_tis); |
afb736e9 | 237 | |
75850d0b | 238 | int mlx5_core_modify_tis(struct mlx5_core_dev *dev, u32 tisn, u32 *in, |
239 | int inlen) | |
240 | { | |
241 | u32 out[MLX5_ST_SZ_DW(modify_tis_out)] = {0}; | |
242 | ||
243 | MLX5_SET(modify_tis_in, in, tisn, tisn); | |
244 | MLX5_SET(modify_tis_in, in, opcode, MLX5_CMD_OP_MODIFY_TIS); | |
245 | ||
c4f287c4 | 246 | return mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); |
75850d0b | 247 | } |
248 | EXPORT_SYMBOL(mlx5_core_modify_tis); | |
249 | ||
7db22ffb | 250 | void mlx5_core_destroy_tis(struct mlx5_core_dev *dev, u32 tisn) |
afb736e9 | 251 | { |
c4f287c4 SM |
252 | u32 in[MLX5_ST_SZ_DW(destroy_tis_in)] = {0}; |
253 | u32 out[MLX5_ST_SZ_DW(destroy_tis_out)] = {0}; | |
afb736e9 AV |
254 | |
255 | MLX5_SET(destroy_tis_in, in, opcode, MLX5_CMD_OP_DESTROY_TIS); | |
256 | MLX5_SET(destroy_tis_in, in, tisn, tisn); | |
c4f287c4 | 257 | mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); |
afb736e9 | 258 | } |
8d7f9ecb | 259 | EXPORT_SYMBOL(mlx5_core_destroy_tis); |
01949d01 HA |
260 | |
261 | int mlx5_core_create_rmp(struct mlx5_core_dev *dev, u32 *in, int inlen, | |
262 | u32 *rmpn) | |
263 | { | |
c4f287c4 | 264 | u32 out[MLX5_ST_SZ_DW(create_rmp_out)] = {0}; |
01949d01 HA |
265 | int err; |
266 | ||
267 | MLX5_SET(create_rmp_in, in, opcode, MLX5_CMD_OP_CREATE_RMP); | |
c4f287c4 | 268 | err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); |
01949d01 HA |
269 | if (!err) |
270 | *rmpn = MLX5_GET(create_rmp_out, out, rmpn); | |
271 | ||
272 | return err; | |
273 | } | |
274 | ||
275 | int mlx5_core_modify_rmp(struct mlx5_core_dev *dev, u32 *in, int inlen) | |
276 | { | |
c4f287c4 | 277 | u32 out[MLX5_ST_SZ_DW(modify_rmp_out)] = {0}; |
01949d01 HA |
278 | |
279 | MLX5_SET(modify_rmp_in, in, opcode, MLX5_CMD_OP_MODIFY_RMP); | |
c4f287c4 | 280 | return mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); |
01949d01 HA |
281 | } |
282 | ||
283 | int mlx5_core_destroy_rmp(struct mlx5_core_dev *dev, u32 rmpn) | |
284 | { | |
c4f287c4 SM |
285 | u32 in[MLX5_ST_SZ_DW(destroy_rmp_in)] = {0}; |
286 | u32 out[MLX5_ST_SZ_DW(destroy_rmp_out)] = {0}; | |
01949d01 HA |
287 | |
288 | MLX5_SET(destroy_rmp_in, in, opcode, MLX5_CMD_OP_DESTROY_RMP); | |
289 | MLX5_SET(destroy_rmp_in, in, rmpn, rmpn); | |
c4f287c4 | 290 | return mlx5_cmd_exec(dev, in, sizeof(in), out, |
01949d01 HA |
291 | sizeof(out)); |
292 | } | |
293 | ||
294 | int mlx5_core_query_rmp(struct mlx5_core_dev *dev, u32 rmpn, u32 *out) | |
295 | { | |
c4f287c4 | 296 | u32 in[MLX5_ST_SZ_DW(query_rmp_in)] = {0}; |
01949d01 HA |
297 | int outlen = MLX5_ST_SZ_BYTES(query_rmp_out); |
298 | ||
01949d01 HA |
299 | MLX5_SET(query_rmp_in, in, opcode, MLX5_CMD_OP_QUERY_RMP); |
300 | MLX5_SET(query_rmp_in, in, rmpn, rmpn); | |
c4f287c4 | 301 | return mlx5_cmd_exec(dev, in, sizeof(in), out, outlen); |
01949d01 HA |
302 | } |
303 | ||
304 | int mlx5_core_arm_rmp(struct mlx5_core_dev *dev, u32 rmpn, u16 lwm) | |
305 | { | |
306 | void *in; | |
307 | void *rmpc; | |
308 | void *wq; | |
309 | void *bitmask; | |
310 | int err; | |
311 | ||
1b9a07ee | 312 | in = kvzalloc(MLX5_ST_SZ_BYTES(modify_rmp_in), GFP_KERNEL); |
01949d01 HA |
313 | if (!in) |
314 | return -ENOMEM; | |
315 | ||
316 | rmpc = MLX5_ADDR_OF(modify_rmp_in, in, ctx); | |
317 | bitmask = MLX5_ADDR_OF(modify_rmp_in, in, bitmask); | |
318 | wq = MLX5_ADDR_OF(rmpc, rmpc, wq); | |
319 | ||
320 | MLX5_SET(modify_rmp_in, in, rmp_state, MLX5_RMPC_STATE_RDY); | |
321 | MLX5_SET(modify_rmp_in, in, rmpn, rmpn); | |
322 | MLX5_SET(wq, wq, lwm, lwm); | |
323 | MLX5_SET(rmp_bitmask, bitmask, lwm, 1); | |
324 | MLX5_SET(rmpc, rmpc, state, MLX5_RMPC_STATE_RDY); | |
325 | ||
326 | err = mlx5_core_modify_rmp(dev, in, MLX5_ST_SZ_BYTES(modify_rmp_in)); | |
327 | ||
328 | kvfree(in); | |
329 | ||
330 | return err; | |
331 | } | |
332 | ||
333 | int mlx5_core_create_xsrq(struct mlx5_core_dev *dev, u32 *in, int inlen, | |
334 | u32 *xsrqn) | |
335 | { | |
c4f287c4 | 336 | u32 out[MLX5_ST_SZ_DW(create_xrc_srq_out)] = {0}; |
01949d01 HA |
337 | int err; |
338 | ||
339 | MLX5_SET(create_xrc_srq_in, in, opcode, MLX5_CMD_OP_CREATE_XRC_SRQ); | |
c4f287c4 | 340 | err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); |
01949d01 HA |
341 | if (!err) |
342 | *xsrqn = MLX5_GET(create_xrc_srq_out, out, xrc_srqn); | |
343 | ||
344 | return err; | |
345 | } | |
346 | ||
347 | int mlx5_core_destroy_xsrq(struct mlx5_core_dev *dev, u32 xsrqn) | |
348 | { | |
c4f287c4 SM |
349 | u32 in[MLX5_ST_SZ_DW(destroy_xrc_srq_in)] = {0}; |
350 | u32 out[MLX5_ST_SZ_DW(destroy_xrc_srq_out)] = {0}; | |
01949d01 HA |
351 | |
352 | MLX5_SET(destroy_xrc_srq_in, in, opcode, MLX5_CMD_OP_DESTROY_XRC_SRQ); | |
353 | MLX5_SET(destroy_xrc_srq_in, in, xrc_srqn, xsrqn); | |
c4f287c4 | 354 | return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); |
01949d01 HA |
355 | } |
356 | ||
357 | int mlx5_core_query_xsrq(struct mlx5_core_dev *dev, u32 xsrqn, u32 *out) | |
358 | { | |
c4f287c4 | 359 | u32 in[MLX5_ST_SZ_DW(query_xrc_srq_in)] = {0}; |
01949d01 HA |
360 | void *srqc; |
361 | void *xrc_srqc; | |
362 | int err; | |
363 | ||
01949d01 HA |
364 | MLX5_SET(query_xrc_srq_in, in, opcode, MLX5_CMD_OP_QUERY_XRC_SRQ); |
365 | MLX5_SET(query_xrc_srq_in, in, xrc_srqn, xsrqn); | |
c4f287c4 SM |
366 | err = mlx5_cmd_exec(dev, in, sizeof(in), out, |
367 | MLX5_ST_SZ_BYTES(query_xrc_srq_out)); | |
01949d01 HA |
368 | if (!err) { |
369 | xrc_srqc = MLX5_ADDR_OF(query_xrc_srq_out, out, | |
370 | xrc_srq_context_entry); | |
371 | srqc = MLX5_ADDR_OF(query_srq_out, out, srq_context_entry); | |
372 | memcpy(srqc, xrc_srqc, MLX5_ST_SZ_BYTES(srqc)); | |
373 | } | |
374 | ||
375 | return err; | |
376 | } | |
377 | ||
378 | int mlx5_core_arm_xsrq(struct mlx5_core_dev *dev, u32 xsrqn, u16 lwm) | |
379 | { | |
c4f287c4 SM |
380 | u32 in[MLX5_ST_SZ_DW(arm_xrc_srq_in)] = {0}; |
381 | u32 out[MLX5_ST_SZ_DW(arm_xrc_srq_out)] = {0}; | |
01949d01 HA |
382 | |
383 | MLX5_SET(arm_xrc_srq_in, in, opcode, MLX5_CMD_OP_ARM_XRC_SRQ); | |
384 | MLX5_SET(arm_xrc_srq_in, in, xrc_srqn, xsrqn); | |
385 | MLX5_SET(arm_xrc_srq_in, in, lwm, lwm); | |
386 | MLX5_SET(arm_xrc_srq_in, in, op_mod, | |
387 | MLX5_ARM_XRC_SRQ_IN_OP_MOD_XRC_SRQ); | |
c4f287c4 | 388 | return mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); |
01949d01 | 389 | } |
1fc22739 AS |
390 | |
391 | int mlx5_core_create_rqt(struct mlx5_core_dev *dev, u32 *in, int inlen, | |
392 | u32 *rqtn) | |
393 | { | |
c4f287c4 | 394 | u32 out[MLX5_ST_SZ_DW(create_rqt_out)] = {0}; |
1fc22739 AS |
395 | int err; |
396 | ||
397 | MLX5_SET(create_rqt_in, in, opcode, MLX5_CMD_OP_CREATE_RQT); | |
c4f287c4 | 398 | err = mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); |
1fc22739 AS |
399 | if (!err) |
400 | *rqtn = MLX5_GET(create_rqt_out, out, rqtn); | |
401 | ||
402 | return err; | |
403 | } | |
16bd0201 | 404 | EXPORT_SYMBOL(mlx5_core_create_rqt); |
1fc22739 | 405 | |
5c50368f AS |
406 | int mlx5_core_modify_rqt(struct mlx5_core_dev *dev, u32 rqtn, u32 *in, |
407 | int inlen) | |
408 | { | |
c4f287c4 | 409 | u32 out[MLX5_ST_SZ_DW(modify_rqt_out)] = {0}; |
5c50368f AS |
410 | |
411 | MLX5_SET(modify_rqt_in, in, rqtn, rqtn); | |
412 | MLX5_SET(modify_rqt_in, in, opcode, MLX5_CMD_OP_MODIFY_RQT); | |
c4f287c4 | 413 | return mlx5_cmd_exec(dev, in, inlen, out, sizeof(out)); |
5c50368f AS |
414 | } |
415 | ||
1fc22739 AS |
416 | void mlx5_core_destroy_rqt(struct mlx5_core_dev *dev, u32 rqtn) |
417 | { | |
c4f287c4 SM |
418 | u32 in[MLX5_ST_SZ_DW(destroy_rqt_in)] = {0}; |
419 | u32 out[MLX5_ST_SZ_DW(destroy_rqt_out)] = {0}; | |
1fc22739 AS |
420 | |
421 | MLX5_SET(destroy_rqt_in, in, opcode, MLX5_CMD_OP_DESTROY_RQT); | |
422 | MLX5_SET(destroy_rqt_in, in, rqtn, rqtn); | |
c4f287c4 | 423 | mlx5_cmd_exec(dev, in, sizeof(in), out, sizeof(out)); |
1fc22739 | 424 | } |
16bd0201 | 425 | EXPORT_SYMBOL(mlx5_core_destroy_rqt); |
18e568c3 OG |
426 | |
427 | static int mlx5_hairpin_create_rq(struct mlx5_core_dev *mdev, | |
428 | struct mlx5_hairpin_params *params, u32 *rqn) | |
429 | { | |
430 | u32 in[MLX5_ST_SZ_DW(create_rq_in)] = {0}; | |
431 | void *rqc, *wq; | |
432 | ||
433 | rqc = MLX5_ADDR_OF(create_rq_in, in, ctx); | |
434 | wq = MLX5_ADDR_OF(rqc, rqc, wq); | |
435 | ||
436 | MLX5_SET(rqc, rqc, hairpin, 1); | |
437 | MLX5_SET(rqc, rqc, state, MLX5_RQC_STATE_RST); | |
438 | MLX5_SET(rqc, rqc, counter_set_id, params->q_counter); | |
439 | ||
440 | MLX5_SET(wq, wq, log_hairpin_data_sz, params->log_data_size); | |
4d533e0f | 441 | MLX5_SET(wq, wq, log_hairpin_num_packets, params->log_num_packets); |
18e568c3 OG |
442 | |
443 | return mlx5_core_create_rq(mdev, in, MLX5_ST_SZ_BYTES(create_rq_in), rqn); | |
444 | } | |
445 | ||
446 | static int mlx5_hairpin_create_sq(struct mlx5_core_dev *mdev, | |
447 | struct mlx5_hairpin_params *params, u32 *sqn) | |
448 | { | |
449 | u32 in[MLX5_ST_SZ_DW(create_sq_in)] = {0}; | |
450 | void *sqc, *wq; | |
451 | ||
452 | sqc = MLX5_ADDR_OF(create_sq_in, in, ctx); | |
453 | wq = MLX5_ADDR_OF(sqc, sqc, wq); | |
454 | ||
455 | MLX5_SET(sqc, sqc, hairpin, 1); | |
456 | MLX5_SET(sqc, sqc, state, MLX5_SQC_STATE_RST); | |
457 | ||
458 | MLX5_SET(wq, wq, log_hairpin_data_sz, params->log_data_size); | |
4d533e0f | 459 | MLX5_SET(wq, wq, log_hairpin_num_packets, params->log_num_packets); |
18e568c3 OG |
460 | |
461 | return mlx5_core_create_sq(mdev, in, MLX5_ST_SZ_BYTES(create_sq_in), sqn); | |
462 | } | |
463 | ||
464 | static int mlx5_hairpin_create_queues(struct mlx5_hairpin *hp, | |
465 | struct mlx5_hairpin_params *params) | |
466 | { | |
ddae74ac | 467 | int i, j, err; |
18e568c3 | 468 | |
ddae74ac OG |
469 | for (i = 0; i < hp->num_channels; i++) { |
470 | err = mlx5_hairpin_create_rq(hp->func_mdev, params, &hp->rqn[i]); | |
471 | if (err) | |
472 | goto out_err_rq; | |
473 | } | |
18e568c3 | 474 | |
ddae74ac OG |
475 | for (i = 0; i < hp->num_channels; i++) { |
476 | err = mlx5_hairpin_create_sq(hp->peer_mdev, params, &hp->sqn[i]); | |
477 | if (err) | |
478 | goto out_err_sq; | |
479 | } | |
18e568c3 OG |
480 | |
481 | return 0; | |
482 | ||
483 | out_err_sq: | |
ddae74ac OG |
484 | for (j = 0; j < i; j++) |
485 | mlx5_core_destroy_sq(hp->peer_mdev, hp->sqn[j]); | |
486 | i = hp->num_channels; | |
18e568c3 | 487 | out_err_rq: |
ddae74ac OG |
488 | for (j = 0; j < i; j++) |
489 | mlx5_core_destroy_rq(hp->func_mdev, hp->rqn[j]); | |
18e568c3 OG |
490 | return err; |
491 | } | |
492 | ||
493 | static void mlx5_hairpin_destroy_queues(struct mlx5_hairpin *hp) | |
494 | { | |
ddae74ac OG |
495 | int i; |
496 | ||
497 | for (i = 0; i < hp->num_channels; i++) { | |
498 | mlx5_core_destroy_rq(hp->func_mdev, hp->rqn[i]); | |
499 | mlx5_core_destroy_sq(hp->peer_mdev, hp->sqn[i]); | |
500 | } | |
18e568c3 OG |
501 | } |
502 | ||
503 | static int mlx5_hairpin_modify_rq(struct mlx5_core_dev *func_mdev, u32 rqn, | |
504 | int curr_state, int next_state, | |
505 | u16 peer_vhca, u32 peer_sq) | |
506 | { | |
507 | u32 in[MLX5_ST_SZ_DW(modify_rq_in)] = {0}; | |
508 | void *rqc; | |
509 | ||
510 | rqc = MLX5_ADDR_OF(modify_rq_in, in, ctx); | |
511 | ||
512 | if (next_state == MLX5_RQC_STATE_RDY) { | |
513 | MLX5_SET(rqc, rqc, hairpin_peer_sq, peer_sq); | |
514 | MLX5_SET(rqc, rqc, hairpin_peer_vhca, peer_vhca); | |
515 | } | |
516 | ||
517 | MLX5_SET(modify_rq_in, in, rq_state, curr_state); | |
518 | MLX5_SET(rqc, rqc, state, next_state); | |
519 | ||
520 | return mlx5_core_modify_rq(func_mdev, rqn, | |
521 | in, MLX5_ST_SZ_BYTES(modify_rq_in)); | |
522 | } | |
523 | ||
524 | static int mlx5_hairpin_modify_sq(struct mlx5_core_dev *peer_mdev, u32 sqn, | |
525 | int curr_state, int next_state, | |
526 | u16 peer_vhca, u32 peer_rq) | |
527 | { | |
528 | u32 in[MLX5_ST_SZ_DW(modify_sq_in)] = {0}; | |
529 | void *sqc; | |
530 | ||
531 | sqc = MLX5_ADDR_OF(modify_sq_in, in, ctx); | |
532 | ||
533 | if (next_state == MLX5_RQC_STATE_RDY) { | |
534 | MLX5_SET(sqc, sqc, hairpin_peer_rq, peer_rq); | |
535 | MLX5_SET(sqc, sqc, hairpin_peer_vhca, peer_vhca); | |
536 | } | |
537 | ||
538 | MLX5_SET(modify_sq_in, in, sq_state, curr_state); | |
539 | MLX5_SET(sqc, sqc, state, next_state); | |
540 | ||
541 | return mlx5_core_modify_sq(peer_mdev, sqn, | |
542 | in, MLX5_ST_SZ_BYTES(modify_sq_in)); | |
543 | } | |
544 | ||
545 | static int mlx5_hairpin_pair_queues(struct mlx5_hairpin *hp) | |
546 | { | |
ddae74ac | 547 | int i, j, err; |
18e568c3 | 548 | |
ddae74ac OG |
549 | /* set peer SQs */ |
550 | for (i = 0; i < hp->num_channels; i++) { | |
551 | err = mlx5_hairpin_modify_sq(hp->peer_mdev, hp->sqn[i], | |
552 | MLX5_SQC_STATE_RST, MLX5_SQC_STATE_RDY, | |
553 | MLX5_CAP_GEN(hp->func_mdev, vhca_id), hp->rqn[i]); | |
554 | if (err) | |
555 | goto err_modify_sq; | |
556 | } | |
18e568c3 | 557 | |
ddae74ac OG |
558 | /* set func RQs */ |
559 | for (i = 0; i < hp->num_channels; i++) { | |
560 | err = mlx5_hairpin_modify_rq(hp->func_mdev, hp->rqn[i], | |
561 | MLX5_RQC_STATE_RST, MLX5_RQC_STATE_RDY, | |
562 | MLX5_CAP_GEN(hp->peer_mdev, vhca_id), hp->sqn[i]); | |
563 | if (err) | |
564 | goto err_modify_rq; | |
565 | } | |
18e568c3 OG |
566 | |
567 | return 0; | |
568 | ||
569 | err_modify_rq: | |
ddae74ac OG |
570 | for (j = 0; j < i; j++) |
571 | mlx5_hairpin_modify_rq(hp->func_mdev, hp->rqn[j], MLX5_RQC_STATE_RDY, | |
572 | MLX5_RQC_STATE_RST, 0, 0); | |
573 | i = hp->num_channels; | |
18e568c3 | 574 | err_modify_sq: |
ddae74ac OG |
575 | for (j = 0; j < i; j++) |
576 | mlx5_hairpin_modify_sq(hp->peer_mdev, hp->sqn[j], MLX5_SQC_STATE_RDY, | |
577 | MLX5_SQC_STATE_RST, 0, 0); | |
18e568c3 OG |
578 | return err; |
579 | } | |
580 | ||
581 | static void mlx5_hairpin_unpair_queues(struct mlx5_hairpin *hp) | |
582 | { | |
ddae74ac OG |
583 | int i; |
584 | ||
585 | /* unset func RQs */ | |
586 | for (i = 0; i < hp->num_channels; i++) | |
587 | mlx5_hairpin_modify_rq(hp->func_mdev, hp->rqn[i], MLX5_RQC_STATE_RDY, | |
588 | MLX5_RQC_STATE_RST, 0, 0); | |
18e568c3 | 589 | |
ddae74ac OG |
590 | /* unset peer SQs */ |
591 | for (i = 0; i < hp->num_channels; i++) | |
592 | mlx5_hairpin_modify_sq(hp->peer_mdev, hp->sqn[i], MLX5_SQC_STATE_RDY, | |
593 | MLX5_SQC_STATE_RST, 0, 0); | |
18e568c3 OG |
594 | } |
595 | ||
596 | struct mlx5_hairpin * | |
597 | mlx5_core_hairpin_create(struct mlx5_core_dev *func_mdev, | |
598 | struct mlx5_core_dev *peer_mdev, | |
599 | struct mlx5_hairpin_params *params) | |
600 | { | |
601 | struct mlx5_hairpin *hp; | |
602 | int size, err; | |
603 | ||
ddae74ac | 604 | size = sizeof(*hp) + params->num_channels * 2 * sizeof(u32); |
18e568c3 OG |
605 | hp = kzalloc(size, GFP_KERNEL); |
606 | if (!hp) | |
607 | return ERR_PTR(-ENOMEM); | |
608 | ||
609 | hp->func_mdev = func_mdev; | |
610 | hp->peer_mdev = peer_mdev; | |
ddae74ac OG |
611 | hp->num_channels = params->num_channels; |
612 | ||
613 | hp->rqn = (void *)hp + sizeof(*hp); | |
614 | hp->sqn = hp->rqn + params->num_channels; | |
18e568c3 OG |
615 | |
616 | /* alloc and pair func --> peer hairpin */ | |
617 | err = mlx5_hairpin_create_queues(hp, params); | |
618 | if (err) | |
619 | goto err_create_queues; | |
620 | ||
621 | err = mlx5_hairpin_pair_queues(hp); | |
622 | if (err) | |
623 | goto err_pair_queues; | |
624 | ||
625 | return hp; | |
626 | ||
627 | err_pair_queues: | |
628 | mlx5_hairpin_destroy_queues(hp); | |
629 | err_create_queues: | |
630 | kfree(hp); | |
631 | return ERR_PTR(err); | |
632 | } | |
633 | ||
634 | void mlx5_core_hairpin_destroy(struct mlx5_hairpin *hp) | |
635 | { | |
636 | mlx5_hairpin_unpair_queues(hp); | |
637 | mlx5_hairpin_destroy_queues(hp); | |
638 | kfree(hp); | |
639 | } |