.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB |
---|
1 | 2 | /* |
---|
2 | | - * Copyright (c) 2013-2015, Mellanox Technologies. 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. |
---|
| 3 | + * Copyright (c) 2013-2018, Mellanox Technologies inc. All rights reserved. |
---|
31 | 4 | */ |
---|
32 | 5 | |
---|
33 | 6 | #include <linux/module.h> |
---|
34 | 7 | #include <linux/mlx5/qp.h> |
---|
35 | | -#include <linux/mlx5/srq.h> |
---|
36 | 8 | #include <linux/slab.h> |
---|
37 | 9 | #include <rdma/ib_umem.h> |
---|
38 | 10 | #include <rdma/ib_user_verbs.h> |
---|
39 | | - |
---|
40 | 11 | #include "mlx5_ib.h" |
---|
41 | | - |
---|
42 | | -/* not supported currently */ |
---|
43 | | -static int srq_signature; |
---|
| 12 | +#include "srq.h" |
---|
44 | 13 | |
---|
45 | 14 | static void *get_wqe(struct mlx5_ib_srq *srq, int n) |
---|
46 | 15 | { |
---|
47 | | - return mlx5_buf_offset(&srq->buf, n << srq->msrq.wqe_shift); |
---|
| 16 | + return mlx5_frag_buf_get_wqe(&srq->fbc, n); |
---|
48 | 17 | } |
---|
49 | 18 | |
---|
50 | 19 | static void mlx5_ib_srq_event(struct mlx5_core_srq *srq, enum mlx5_event type) |
---|
.. | .. |
---|
78 | 47 | { |
---|
79 | 48 | struct mlx5_ib_dev *dev = to_mdev(pd->device); |
---|
80 | 49 | struct mlx5_ib_create_srq ucmd = {}; |
---|
| 50 | + struct mlx5_ib_ucontext *ucontext = rdma_udata_to_drv_context( |
---|
| 51 | + udata, struct mlx5_ib_ucontext, ibucontext); |
---|
81 | 52 | size_t ucmdlen; |
---|
82 | 53 | int err; |
---|
83 | 54 | int npages; |
---|
.. | .. |
---|
102 | 73 | return -EINVAL; |
---|
103 | 74 | |
---|
104 | 75 | if (in->type != IB_SRQT_BASIC) { |
---|
105 | | - err = get_srq_user_index(to_mucontext(pd->uobject->context), |
---|
106 | | - &ucmd, udata->inlen, &uidx); |
---|
| 76 | + err = get_srq_user_index(ucontext, &ucmd, udata->inlen, &uidx); |
---|
107 | 77 | if (err) |
---|
108 | 78 | return err; |
---|
109 | 79 | } |
---|
110 | 80 | |
---|
111 | 81 | srq->wq_sig = !!(ucmd.flags & MLX5_SRQ_FLAG_SIGNATURE); |
---|
112 | 82 | |
---|
113 | | - srq->umem = ib_umem_get(pd->uobject->context, ucmd.buf_addr, buf_size, |
---|
114 | | - 0, 0); |
---|
| 83 | + srq->umem = ib_umem_get(pd->device, ucmd.buf_addr, buf_size, 0); |
---|
115 | 84 | if (IS_ERR(srq->umem)) { |
---|
116 | 85 | mlx5_ib_dbg(dev, "failed umem get, size %d\n", buf_size); |
---|
117 | 86 | err = PTR_ERR(srq->umem); |
---|
.. | .. |
---|
135 | 104 | |
---|
136 | 105 | mlx5_ib_populate_pas(dev, srq->umem, page_shift, in->pas, 0); |
---|
137 | 106 | |
---|
138 | | - err = mlx5_ib_db_map_user(to_mucontext(pd->uobject->context), |
---|
139 | | - ucmd.db_addr, &srq->db); |
---|
| 107 | + err = mlx5_ib_db_map_user(ucontext, udata, ucmd.db_addr, &srq->db); |
---|
140 | 108 | if (err) { |
---|
141 | 109 | mlx5_ib_dbg(dev, "map doorbell failed\n"); |
---|
142 | 110 | goto err_in; |
---|
.. | .. |
---|
144 | 112 | |
---|
145 | 113 | in->log_page_size = page_shift - MLX5_ADAPTER_PAGE_SHIFT; |
---|
146 | 114 | in->page_offset = offset; |
---|
| 115 | + in->uid = (in->type != IB_SRQT_XRC) ? to_mpd(pd)->uid : 0; |
---|
147 | 116 | if (MLX5_CAP_GEN(dev->mdev, cqe_version) == MLX5_CQE_VERSION_V1 && |
---|
148 | 117 | in->type != IB_SRQT_BASIC) |
---|
149 | 118 | in->user_index = uidx; |
---|
.. | .. |
---|
172 | 141 | return err; |
---|
173 | 142 | } |
---|
174 | 143 | |
---|
175 | | - if (mlx5_buf_alloc(dev->mdev, buf_size, &srq->buf)) { |
---|
| 144 | + if (mlx5_frag_buf_alloc_node(dev->mdev, buf_size, &srq->buf, |
---|
| 145 | + dev->mdev->priv.numa_node)) { |
---|
176 | 146 | mlx5_ib_dbg(dev, "buf alloc failed\n"); |
---|
177 | 147 | err = -ENOMEM; |
---|
178 | 148 | goto err_db; |
---|
179 | 149 | } |
---|
| 150 | + |
---|
| 151 | + mlx5_init_fbc(srq->buf.frags, srq->msrq.wqe_shift, ilog2(srq->msrq.max), |
---|
| 152 | + &srq->fbc); |
---|
180 | 153 | |
---|
181 | 154 | srq->head = 0; |
---|
182 | 155 | srq->tail = srq->msrq.max - 1; |
---|
.. | .. |
---|
194 | 167 | err = -ENOMEM; |
---|
195 | 168 | goto err_buf; |
---|
196 | 169 | } |
---|
197 | | - mlx5_fill_page_array(&srq->buf, in->pas); |
---|
| 170 | + mlx5_fill_page_frag_array(&srq->buf, in->pas); |
---|
198 | 171 | |
---|
199 | 172 | srq->wrid = kvmalloc_array(srq->msrq.max, sizeof(u64), GFP_KERNEL); |
---|
200 | 173 | if (!srq->wrid) { |
---|
201 | 174 | err = -ENOMEM; |
---|
202 | 175 | goto err_in; |
---|
203 | 176 | } |
---|
204 | | - srq->wq_sig = !!srq_signature; |
---|
| 177 | + srq->wq_sig = 0; |
---|
205 | 178 | |
---|
206 | 179 | in->log_page_size = srq->buf.page_shift - MLX5_ADAPTER_PAGE_SHIFT; |
---|
207 | 180 | if (MLX5_CAP_GEN(dev->mdev, cqe_version) == MLX5_CQE_VERSION_V1 && |
---|
.. | .. |
---|
214 | 187 | kvfree(in->pas); |
---|
215 | 188 | |
---|
216 | 189 | err_buf: |
---|
217 | | - mlx5_buf_free(dev->mdev, &srq->buf); |
---|
| 190 | + mlx5_frag_buf_free(dev->mdev, &srq->buf); |
---|
218 | 191 | |
---|
219 | 192 | err_db: |
---|
220 | 193 | mlx5_db_free(dev->mdev, &srq->db); |
---|
221 | 194 | return err; |
---|
222 | 195 | } |
---|
223 | 196 | |
---|
224 | | -static void destroy_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq) |
---|
| 197 | +static void destroy_srq_user(struct ib_pd *pd, struct mlx5_ib_srq *srq, |
---|
| 198 | + struct ib_udata *udata) |
---|
225 | 199 | { |
---|
226 | | - mlx5_ib_db_unmap_user(to_mucontext(pd->uobject->context), &srq->db); |
---|
| 200 | + mlx5_ib_db_unmap_user( |
---|
| 201 | + rdma_udata_to_drv_context( |
---|
| 202 | + udata, |
---|
| 203 | + struct mlx5_ib_ucontext, |
---|
| 204 | + ibucontext), |
---|
| 205 | + &srq->db); |
---|
227 | 206 | ib_umem_release(srq->umem); |
---|
228 | 207 | } |
---|
229 | 208 | |
---|
.. | .. |
---|
231 | 210 | static void destroy_srq_kernel(struct mlx5_ib_dev *dev, struct mlx5_ib_srq *srq) |
---|
232 | 211 | { |
---|
233 | 212 | kvfree(srq->wrid); |
---|
234 | | - mlx5_buf_free(dev->mdev, &srq->buf); |
---|
| 213 | + mlx5_frag_buf_free(dev->mdev, &srq->buf); |
---|
235 | 214 | mlx5_db_free(dev->mdev, &srq->db); |
---|
236 | 215 | } |
---|
237 | 216 | |
---|
238 | | -struct ib_srq *mlx5_ib_create_srq(struct ib_pd *pd, |
---|
239 | | - struct ib_srq_init_attr *init_attr, |
---|
240 | | - struct ib_udata *udata) |
---|
| 217 | +int mlx5_ib_create_srq(struct ib_srq *ib_srq, |
---|
| 218 | + struct ib_srq_init_attr *init_attr, |
---|
| 219 | + struct ib_udata *udata) |
---|
241 | 220 | { |
---|
242 | | - struct mlx5_ib_dev *dev = to_mdev(pd->device); |
---|
243 | | - struct mlx5_ib_srq *srq; |
---|
| 221 | + struct mlx5_ib_dev *dev = to_mdev(ib_srq->device); |
---|
| 222 | + struct mlx5_ib_srq *srq = to_msrq(ib_srq); |
---|
244 | 223 | size_t desc_size; |
---|
245 | 224 | size_t buf_size; |
---|
246 | 225 | int err; |
---|
247 | | - struct mlx5_srq_attr in = {0}; |
---|
| 226 | + struct mlx5_srq_attr in = {}; |
---|
248 | 227 | __u32 max_srq_wqes = 1 << MLX5_CAP_GEN(dev->mdev, log_max_srq_sz); |
---|
249 | 228 | |
---|
250 | 229 | /* Sanity check SRQ size before proceeding */ |
---|
.. | .. |
---|
252 | 231 | mlx5_ib_dbg(dev, "max_wr %d, cap %d\n", |
---|
253 | 232 | init_attr->attr.max_wr, |
---|
254 | 233 | max_srq_wqes); |
---|
255 | | - return ERR_PTR(-EINVAL); |
---|
| 234 | + return -EINVAL; |
---|
256 | 235 | } |
---|
257 | | - |
---|
258 | | - srq = kmalloc(sizeof(*srq), GFP_KERNEL); |
---|
259 | | - if (!srq) |
---|
260 | | - return ERR_PTR(-ENOMEM); |
---|
261 | 236 | |
---|
262 | 237 | mutex_init(&srq->mutex); |
---|
263 | 238 | spin_lock_init(&srq->lock); |
---|
.. | .. |
---|
266 | 241 | |
---|
267 | 242 | desc_size = sizeof(struct mlx5_wqe_srq_next_seg) + |
---|
268 | 243 | srq->msrq.max_gs * sizeof(struct mlx5_wqe_data_seg); |
---|
269 | | - if (desc_size == 0 || srq->msrq.max_gs > desc_size) { |
---|
270 | | - err = -EINVAL; |
---|
271 | | - goto err_srq; |
---|
272 | | - } |
---|
| 244 | + if (desc_size == 0 || srq->msrq.max_gs > desc_size) |
---|
| 245 | + return -EINVAL; |
---|
| 246 | + |
---|
273 | 247 | desc_size = roundup_pow_of_two(desc_size); |
---|
274 | 248 | desc_size = max_t(size_t, 32, desc_size); |
---|
275 | | - if (desc_size < sizeof(struct mlx5_wqe_srq_next_seg)) { |
---|
276 | | - err = -EINVAL; |
---|
277 | | - goto err_srq; |
---|
278 | | - } |
---|
| 249 | + if (desc_size < sizeof(struct mlx5_wqe_srq_next_seg)) |
---|
| 250 | + return -EINVAL; |
---|
| 251 | + |
---|
279 | 252 | srq->msrq.max_avail_gather = (desc_size - sizeof(struct mlx5_wqe_srq_next_seg)) / |
---|
280 | 253 | sizeof(struct mlx5_wqe_data_seg); |
---|
281 | 254 | srq->msrq.wqe_shift = ilog2(desc_size); |
---|
282 | 255 | buf_size = srq->msrq.max * desc_size; |
---|
283 | | - if (buf_size < desc_size) { |
---|
284 | | - err = -EINVAL; |
---|
285 | | - goto err_srq; |
---|
286 | | - } |
---|
| 256 | + if (buf_size < desc_size) |
---|
| 257 | + return -EINVAL; |
---|
| 258 | + |
---|
287 | 259 | in.type = init_attr->srq_type; |
---|
288 | 260 | |
---|
289 | | - if (pd->uobject) |
---|
290 | | - err = create_srq_user(pd, srq, &in, udata, buf_size); |
---|
| 261 | + if (udata) |
---|
| 262 | + err = create_srq_user(ib_srq->pd, srq, &in, udata, buf_size); |
---|
291 | 263 | else |
---|
292 | 264 | err = create_srq_kernel(dev, srq, &in, buf_size); |
---|
293 | 265 | |
---|
294 | 266 | if (err) { |
---|
295 | 267 | mlx5_ib_warn(dev, "create srq %s failed, err %d\n", |
---|
296 | | - pd->uobject ? "user" : "kernel", err); |
---|
297 | | - goto err_srq; |
---|
| 268 | + udata ? "user" : "kernel", err); |
---|
| 269 | + return err; |
---|
298 | 270 | } |
---|
299 | 271 | |
---|
300 | 272 | in.log_size = ilog2(srq->msrq.max); |
---|
.. | .. |
---|
302 | 274 | if (srq->wq_sig) |
---|
303 | 275 | in.flags |= MLX5_SRQ_FLAG_WQ_SIG; |
---|
304 | 276 | |
---|
305 | | - if (init_attr->srq_type == IB_SRQT_XRC) |
---|
| 277 | + if (init_attr->srq_type == IB_SRQT_XRC && init_attr->ext.xrc.xrcd) |
---|
306 | 278 | in.xrcd = to_mxrcd(init_attr->ext.xrc.xrcd)->xrcdn; |
---|
307 | 279 | else |
---|
308 | | - in.xrcd = to_mxrcd(dev->devr.x0)->xrcdn; |
---|
| 280 | + in.xrcd = dev->devr.xrcdn0; |
---|
309 | 281 | |
---|
310 | 282 | if (init_attr->srq_type == IB_SRQT_TM) { |
---|
311 | 283 | in.tm_log_list_size = |
---|
.. | .. |
---|
324 | 296 | else |
---|
325 | 297 | in.cqn = to_mcq(dev->devr.c0)->mcq.cqn; |
---|
326 | 298 | |
---|
327 | | - in.pd = to_mpd(pd)->pdn; |
---|
| 299 | + in.pd = to_mpd(ib_srq->pd)->pdn; |
---|
328 | 300 | in.db_record = srq->db.dma; |
---|
329 | | - err = mlx5_core_create_srq(dev->mdev, &srq->msrq, &in); |
---|
| 301 | + err = mlx5_cmd_create_srq(dev, &srq->msrq, &in); |
---|
330 | 302 | kvfree(in.pas); |
---|
331 | 303 | if (err) { |
---|
332 | 304 | mlx5_ib_dbg(dev, "create SRQ failed, err %d\n", err); |
---|
.. | .. |
---|
338 | 310 | srq->msrq.event = mlx5_ib_srq_event; |
---|
339 | 311 | srq->ibsrq.ext.xrc.srq_num = srq->msrq.srqn; |
---|
340 | 312 | |
---|
341 | | - if (pd->uobject) |
---|
342 | | - if (ib_copy_to_udata(udata, &srq->msrq.srqn, sizeof(__u32))) { |
---|
| 313 | + if (udata) { |
---|
| 314 | + struct mlx5_ib_create_srq_resp resp = { |
---|
| 315 | + .srqn = srq->msrq.srqn, |
---|
| 316 | + }; |
---|
| 317 | + |
---|
| 318 | + if (ib_copy_to_udata(udata, &resp, min(udata->outlen, |
---|
| 319 | + sizeof(resp)))) { |
---|
343 | 320 | mlx5_ib_dbg(dev, "copy to user failed\n"); |
---|
344 | 321 | err = -EFAULT; |
---|
345 | 322 | goto err_core; |
---|
346 | 323 | } |
---|
| 324 | + } |
---|
347 | 325 | |
---|
348 | 326 | init_attr->attr.max_wr = srq->msrq.max - 1; |
---|
349 | 327 | |
---|
350 | | - return &srq->ibsrq; |
---|
| 328 | + return 0; |
---|
351 | 329 | |
---|
352 | 330 | err_core: |
---|
353 | | - mlx5_core_destroy_srq(dev->mdev, &srq->msrq); |
---|
| 331 | + mlx5_cmd_destroy_srq(dev, &srq->msrq); |
---|
354 | 332 | |
---|
355 | 333 | err_usr_kern_srq: |
---|
356 | | - if (pd->uobject) |
---|
357 | | - destroy_srq_user(pd, srq); |
---|
| 334 | + if (udata) |
---|
| 335 | + destroy_srq_user(ib_srq->pd, srq, udata); |
---|
358 | 336 | else |
---|
359 | 337 | destroy_srq_kernel(dev, srq); |
---|
360 | 338 | |
---|
361 | | -err_srq: |
---|
362 | | - kfree(srq); |
---|
363 | | - |
---|
364 | | - return ERR_PTR(err); |
---|
| 339 | + return err; |
---|
365 | 340 | } |
---|
366 | 341 | |
---|
367 | 342 | int mlx5_ib_modify_srq(struct ib_srq *ibsrq, struct ib_srq_attr *attr, |
---|
.. | .. |
---|
380 | 355 | return -EINVAL; |
---|
381 | 356 | |
---|
382 | 357 | mutex_lock(&srq->mutex); |
---|
383 | | - ret = mlx5_core_arm_srq(dev->mdev, &srq->msrq, attr->srq_limit, 1); |
---|
| 358 | + ret = mlx5_cmd_arm_srq(dev, &srq->msrq, attr->srq_limit, 1); |
---|
384 | 359 | mutex_unlock(&srq->mutex); |
---|
385 | 360 | |
---|
386 | 361 | if (ret) |
---|
.. | .. |
---|
401 | 376 | if (!out) |
---|
402 | 377 | return -ENOMEM; |
---|
403 | 378 | |
---|
404 | | - ret = mlx5_core_query_srq(dev->mdev, &srq->msrq, out); |
---|
| 379 | + ret = mlx5_cmd_query_srq(dev, &srq->msrq, out); |
---|
405 | 380 | if (ret) |
---|
406 | 381 | goto out_box; |
---|
407 | 382 | |
---|
.. | .. |
---|
414 | 389 | return ret; |
---|
415 | 390 | } |
---|
416 | 391 | |
---|
417 | | -int mlx5_ib_destroy_srq(struct ib_srq *srq) |
---|
| 392 | +int mlx5_ib_destroy_srq(struct ib_srq *srq, struct ib_udata *udata) |
---|
418 | 393 | { |
---|
419 | 394 | struct mlx5_ib_dev *dev = to_mdev(srq->device); |
---|
420 | 395 | struct mlx5_ib_srq *msrq = to_msrq(srq); |
---|
| 396 | + int ret; |
---|
421 | 397 | |
---|
422 | | - mlx5_core_destroy_srq(dev->mdev, &msrq->msrq); |
---|
| 398 | + ret = mlx5_cmd_destroy_srq(dev, &msrq->msrq); |
---|
| 399 | + if (ret) |
---|
| 400 | + return ret; |
---|
423 | 401 | |
---|
424 | | - if (srq->uobject) { |
---|
425 | | - mlx5_ib_db_unmap_user(to_mucontext(srq->uobject->context), &msrq->db); |
---|
426 | | - ib_umem_release(msrq->umem); |
---|
427 | | - } else { |
---|
| 402 | + if (udata) |
---|
| 403 | + destroy_srq_user(srq->pd, msrq, udata); |
---|
| 404 | + else |
---|
428 | 405 | destroy_srq_kernel(dev, msrq); |
---|
429 | | - } |
---|
430 | | - |
---|
431 | | - kfree(srq); |
---|
432 | 406 | return 0; |
---|
433 | 407 | } |
---|
434 | 408 | |
---|