| .. | .. |
|---|
| 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 | |
|---|