1d6b92ffaSHans Petter Selasky /* 2d6b92ffaSHans Petter Selasky * Copyright (c) 2012 Mellanox Technologies, Inc. All rights reserved. 3d6b92ffaSHans Petter Selasky * 4d6b92ffaSHans Petter Selasky * This software is available to you under a choice of one of two 5d6b92ffaSHans Petter Selasky * licenses. You may choose to be licensed under the terms of the GNU 6d6b92ffaSHans Petter Selasky * General Public License (GPL) Version 2, available from the file 7d6b92ffaSHans Petter Selasky * COPYING in the main directory of this source tree, or the 8d6b92ffaSHans Petter Selasky * OpenIB.org BSD license below: 9d6b92ffaSHans Petter Selasky * 10d6b92ffaSHans Petter Selasky * Redistribution and use in source and binary forms, with or 11d6b92ffaSHans Petter Selasky * without modification, are permitted provided that the following 12d6b92ffaSHans Petter Selasky * conditions are met: 13d6b92ffaSHans Petter Selasky * 14d6b92ffaSHans Petter Selasky * - Redistributions of source code must retain the above 15d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following 16d6b92ffaSHans Petter Selasky * disclaimer. 17d6b92ffaSHans Petter Selasky * 18d6b92ffaSHans Petter Selasky * - Redistributions in binary form must reproduce the above 19d6b92ffaSHans Petter Selasky * copyright notice, this list of conditions and the following 20d6b92ffaSHans Petter Selasky * disclaimer in the documentation and/or other materials 21d6b92ffaSHans Petter Selasky * provided with the distribution. 22d6b92ffaSHans Petter Selasky * 23d6b92ffaSHans Petter Selasky * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 24d6b92ffaSHans Petter Selasky * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 25d6b92ffaSHans Petter Selasky * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 26d6b92ffaSHans Petter Selasky * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 27d6b92ffaSHans Petter Selasky * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN 28d6b92ffaSHans Petter Selasky * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 29d6b92ffaSHans Petter Selasky * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 30d6b92ffaSHans Petter Selasky * SOFTWARE. 31d6b92ffaSHans Petter Selasky */ 32d6b92ffaSHans Petter Selasky 33d6b92ffaSHans Petter Selasky #include <config.h> 34d6b92ffaSHans Petter Selasky 35d6b92ffaSHans Petter Selasky #include <stdlib.h> 36d6b92ffaSHans Petter Selasky #include <stdio.h> 37d6b92ffaSHans Petter Selasky #include <string.h> 38d6b92ffaSHans Petter Selasky #include <pthread.h> 39d6b92ffaSHans Petter Selasky #include <errno.h> 40d6b92ffaSHans Petter Selasky #include <limits.h> 41d6b92ffaSHans Petter Selasky #include <sys/types.h> 42d6b92ffaSHans Petter Selasky #include <sys/stat.h> 43d6b92ffaSHans Petter Selasky #include <fcntl.h> 44d6b92ffaSHans Petter Selasky #include <unistd.h> 45d6b92ffaSHans Petter Selasky #include <sys/mman.h> 46d6b92ffaSHans Petter Selasky 47d6b92ffaSHans Petter Selasky #include "mlx5.h" 48d6b92ffaSHans Petter Selasky #include "mlx5-abi.h" 49d6b92ffaSHans Petter Selasky #include "wqe.h" 50d6b92ffaSHans Petter Selasky 51d6b92ffaSHans Petter Selasky int mlx5_single_threaded = 0; 52d6b92ffaSHans Petter Selasky 53d6b92ffaSHans Petter Selasky static inline int is_xrc_tgt(int type) 54d6b92ffaSHans Petter Selasky { 55d6b92ffaSHans Petter Selasky return type == IBV_QPT_XRC_RECV; 56d6b92ffaSHans Petter Selasky } 57d6b92ffaSHans Petter Selasky 58d6b92ffaSHans Petter Selasky int mlx5_query_device(struct ibv_context *context, struct ibv_device_attr *attr) 59d6b92ffaSHans Petter Selasky { 60d6b92ffaSHans Petter Selasky struct ibv_query_device cmd; 61d6b92ffaSHans Petter Selasky uint64_t raw_fw_ver; 62d6b92ffaSHans Petter Selasky unsigned major, minor, sub_minor; 63d6b92ffaSHans Petter Selasky int ret; 64d6b92ffaSHans Petter Selasky 65d6b92ffaSHans Petter Selasky ret = ibv_cmd_query_device(context, attr, &raw_fw_ver, &cmd, sizeof cmd); 66d6b92ffaSHans Petter Selasky if (ret) 67d6b92ffaSHans Petter Selasky return ret; 68d6b92ffaSHans Petter Selasky 69d6b92ffaSHans Petter Selasky major = (raw_fw_ver >> 32) & 0xffff; 70d6b92ffaSHans Petter Selasky minor = (raw_fw_ver >> 16) & 0xffff; 71d6b92ffaSHans Petter Selasky sub_minor = raw_fw_ver & 0xffff; 72d6b92ffaSHans Petter Selasky 73d6b92ffaSHans Petter Selasky snprintf(attr->fw_ver, sizeof attr->fw_ver, 74d6b92ffaSHans Petter Selasky "%d.%d.%04d", major, minor, sub_minor); 75d6b92ffaSHans Petter Selasky 76d6b92ffaSHans Petter Selasky return 0; 77d6b92ffaSHans Petter Selasky } 78d6b92ffaSHans Petter Selasky 79d6b92ffaSHans Petter Selasky #define READL(ptr) (*((uint32_t *)(ptr))) 80d6b92ffaSHans Petter Selasky static int mlx5_read_clock(struct ibv_context *context, uint64_t *cycles) 81d6b92ffaSHans Petter Selasky { 82d6b92ffaSHans Petter Selasky unsigned int clockhi, clocklo, clockhi1; 83d6b92ffaSHans Petter Selasky int i; 84d6b92ffaSHans Petter Selasky struct mlx5_context *ctx = to_mctx(context); 85d6b92ffaSHans Petter Selasky 86d6b92ffaSHans Petter Selasky if (!ctx->hca_core_clock) 87d6b92ffaSHans Petter Selasky return -EOPNOTSUPP; 88d6b92ffaSHans Petter Selasky 89d6b92ffaSHans Petter Selasky /* Handle wraparound */ 90d6b92ffaSHans Petter Selasky for (i = 0; i < 2; i++) { 91d6b92ffaSHans Petter Selasky clockhi = be32toh(READL(ctx->hca_core_clock)); 92d6b92ffaSHans Petter Selasky clocklo = be32toh(READL(ctx->hca_core_clock + 4)); 93d6b92ffaSHans Petter Selasky clockhi1 = be32toh(READL(ctx->hca_core_clock)); 94d6b92ffaSHans Petter Selasky if (clockhi == clockhi1) 95d6b92ffaSHans Petter Selasky break; 96d6b92ffaSHans Petter Selasky } 97d6b92ffaSHans Petter Selasky 98d6b92ffaSHans Petter Selasky *cycles = (uint64_t)clockhi << 32 | (uint64_t)clocklo; 99d6b92ffaSHans Petter Selasky 100d6b92ffaSHans Petter Selasky return 0; 101d6b92ffaSHans Petter Selasky } 102d6b92ffaSHans Petter Selasky 103d6b92ffaSHans Petter Selasky int mlx5_query_rt_values(struct ibv_context *context, 104d6b92ffaSHans Petter Selasky struct ibv_values_ex *values) 105d6b92ffaSHans Petter Selasky { 106d6b92ffaSHans Petter Selasky uint32_t comp_mask = 0; 107d6b92ffaSHans Petter Selasky int err = 0; 108d6b92ffaSHans Petter Selasky 109d6b92ffaSHans Petter Selasky if (values->comp_mask & IBV_VALUES_MASK_RAW_CLOCK) { 110d6b92ffaSHans Petter Selasky uint64_t cycles; 111d6b92ffaSHans Petter Selasky 112d6b92ffaSHans Petter Selasky err = mlx5_read_clock(context, &cycles); 113d6b92ffaSHans Petter Selasky if (!err) { 114d6b92ffaSHans Petter Selasky values->raw_clock.tv_sec = 0; 115d6b92ffaSHans Petter Selasky values->raw_clock.tv_nsec = cycles; 116d6b92ffaSHans Petter Selasky comp_mask |= IBV_VALUES_MASK_RAW_CLOCK; 117d6b92ffaSHans Petter Selasky } 118d6b92ffaSHans Petter Selasky } 119d6b92ffaSHans Petter Selasky 120d6b92ffaSHans Petter Selasky values->comp_mask = comp_mask; 121d6b92ffaSHans Petter Selasky 122d6b92ffaSHans Petter Selasky return err; 123d6b92ffaSHans Petter Selasky } 124d6b92ffaSHans Petter Selasky 125d6b92ffaSHans Petter Selasky int mlx5_query_port(struct ibv_context *context, uint8_t port, 126d6b92ffaSHans Petter Selasky struct ibv_port_attr *attr) 127d6b92ffaSHans Petter Selasky { 128d6b92ffaSHans Petter Selasky struct ibv_query_port cmd; 129d6b92ffaSHans Petter Selasky 130d6b92ffaSHans Petter Selasky return ibv_cmd_query_port(context, port, attr, &cmd, sizeof cmd); 131d6b92ffaSHans Petter Selasky } 132d6b92ffaSHans Petter Selasky 133d6b92ffaSHans Petter Selasky struct ibv_pd *mlx5_alloc_pd(struct ibv_context *context) 134d6b92ffaSHans Petter Selasky { 135d6b92ffaSHans Petter Selasky struct ibv_alloc_pd cmd; 136d6b92ffaSHans Petter Selasky struct mlx5_alloc_pd_resp resp; 137d6b92ffaSHans Petter Selasky struct mlx5_pd *pd; 138d6b92ffaSHans Petter Selasky 139d6b92ffaSHans Petter Selasky pd = calloc(1, sizeof *pd); 140d6b92ffaSHans Petter Selasky if (!pd) 141d6b92ffaSHans Petter Selasky return NULL; 142d6b92ffaSHans Petter Selasky 143d6b92ffaSHans Petter Selasky if (ibv_cmd_alloc_pd(context, &pd->ibv_pd, &cmd, sizeof cmd, 144d6b92ffaSHans Petter Selasky &resp.ibv_resp, sizeof resp)) { 145d6b92ffaSHans Petter Selasky free(pd); 146d6b92ffaSHans Petter Selasky return NULL; 147d6b92ffaSHans Petter Selasky } 148d6b92ffaSHans Petter Selasky 149d6b92ffaSHans Petter Selasky pd->pdn = resp.pdn; 150d6b92ffaSHans Petter Selasky 151d6b92ffaSHans Petter Selasky return &pd->ibv_pd; 152d6b92ffaSHans Petter Selasky } 153d6b92ffaSHans Petter Selasky 154d6b92ffaSHans Petter Selasky int mlx5_free_pd(struct ibv_pd *pd) 155d6b92ffaSHans Petter Selasky { 156d6b92ffaSHans Petter Selasky int ret; 157d6b92ffaSHans Petter Selasky 158d6b92ffaSHans Petter Selasky ret = ibv_cmd_dealloc_pd(pd); 159d6b92ffaSHans Petter Selasky if (ret) 160d6b92ffaSHans Petter Selasky return ret; 161d6b92ffaSHans Petter Selasky 162d6b92ffaSHans Petter Selasky free(to_mpd(pd)); 163d6b92ffaSHans Petter Selasky return 0; 164d6b92ffaSHans Petter Selasky } 165d6b92ffaSHans Petter Selasky 166d6b92ffaSHans Petter Selasky struct ibv_mr *mlx5_reg_mr(struct ibv_pd *pd, void *addr, size_t length, 167d6b92ffaSHans Petter Selasky int acc) 168d6b92ffaSHans Petter Selasky { 169d6b92ffaSHans Petter Selasky struct mlx5_mr *mr; 170d6b92ffaSHans Petter Selasky struct ibv_reg_mr cmd; 171d6b92ffaSHans Petter Selasky int ret; 172d6b92ffaSHans Petter Selasky enum ibv_access_flags access = (enum ibv_access_flags)acc; 173d6b92ffaSHans Petter Selasky struct ibv_reg_mr_resp resp; 174d6b92ffaSHans Petter Selasky 175d6b92ffaSHans Petter Selasky mr = calloc(1, sizeof(*mr)); 176d6b92ffaSHans Petter Selasky if (!mr) 177d6b92ffaSHans Petter Selasky return NULL; 178d6b92ffaSHans Petter Selasky 179d6b92ffaSHans Petter Selasky ret = ibv_cmd_reg_mr(pd, addr, length, (uintptr_t)addr, access, 180d6b92ffaSHans Petter Selasky &(mr->ibv_mr), &cmd, sizeof(cmd), &resp, 181d6b92ffaSHans Petter Selasky sizeof resp); 182d6b92ffaSHans Petter Selasky if (ret) { 183d6b92ffaSHans Petter Selasky mlx5_free_buf(&(mr->buf)); 184d6b92ffaSHans Petter Selasky free(mr); 185d6b92ffaSHans Petter Selasky return NULL; 186d6b92ffaSHans Petter Selasky } 187d6b92ffaSHans Petter Selasky mr->alloc_flags = acc; 188d6b92ffaSHans Petter Selasky 189d6b92ffaSHans Petter Selasky return &mr->ibv_mr; 190d6b92ffaSHans Petter Selasky } 191d6b92ffaSHans Petter Selasky 192d6b92ffaSHans Petter Selasky int mlx5_rereg_mr(struct ibv_mr *ibmr, int flags, struct ibv_pd *pd, void *addr, 193d6b92ffaSHans Petter Selasky size_t length, int access) 194d6b92ffaSHans Petter Selasky { 195d6b92ffaSHans Petter Selasky struct ibv_rereg_mr cmd; 196d6b92ffaSHans Petter Selasky struct ibv_rereg_mr_resp resp; 197d6b92ffaSHans Petter Selasky 198d6b92ffaSHans Petter Selasky if (flags & IBV_REREG_MR_KEEP_VALID) 199d6b92ffaSHans Petter Selasky return ENOTSUP; 200d6b92ffaSHans Petter Selasky 201d6b92ffaSHans Petter Selasky return ibv_cmd_rereg_mr(ibmr, flags, addr, length, (uintptr_t)addr, 202d6b92ffaSHans Petter Selasky access, pd, &cmd, sizeof(cmd), &resp, 203d6b92ffaSHans Petter Selasky sizeof(resp)); 204d6b92ffaSHans Petter Selasky } 205d6b92ffaSHans Petter Selasky 206d6b92ffaSHans Petter Selasky int mlx5_dereg_mr(struct ibv_mr *ibmr) 207d6b92ffaSHans Petter Selasky { 208d6b92ffaSHans Petter Selasky int ret; 209d6b92ffaSHans Petter Selasky struct mlx5_mr *mr = to_mmr(ibmr); 210d6b92ffaSHans Petter Selasky 211d6b92ffaSHans Petter Selasky ret = ibv_cmd_dereg_mr(ibmr); 212d6b92ffaSHans Petter Selasky if (ret) 213d6b92ffaSHans Petter Selasky return ret; 214d6b92ffaSHans Petter Selasky 215d6b92ffaSHans Petter Selasky free(mr); 216d6b92ffaSHans Petter Selasky return 0; 217d6b92ffaSHans Petter Selasky } 218d6b92ffaSHans Petter Selasky 219d6b92ffaSHans Petter Selasky struct ibv_mw *mlx5_alloc_mw(struct ibv_pd *pd, enum ibv_mw_type type) 220d6b92ffaSHans Petter Selasky { 221d6b92ffaSHans Petter Selasky struct ibv_mw *mw; 222d6b92ffaSHans Petter Selasky struct ibv_alloc_mw cmd; 223d6b92ffaSHans Petter Selasky struct ibv_alloc_mw_resp resp; 224d6b92ffaSHans Petter Selasky int ret; 225d6b92ffaSHans Petter Selasky 226d6b92ffaSHans Petter Selasky mw = malloc(sizeof(*mw)); 227d6b92ffaSHans Petter Selasky if (!mw) 228d6b92ffaSHans Petter Selasky return NULL; 229d6b92ffaSHans Petter Selasky 230d6b92ffaSHans Petter Selasky memset(mw, 0, sizeof(*mw)); 231d6b92ffaSHans Petter Selasky 232d6b92ffaSHans Petter Selasky ret = ibv_cmd_alloc_mw(pd, type, mw, &cmd, sizeof(cmd), &resp, 233d6b92ffaSHans Petter Selasky sizeof(resp)); 234d6b92ffaSHans Petter Selasky if (ret) { 235d6b92ffaSHans Petter Selasky free(mw); 236d6b92ffaSHans Petter Selasky return NULL; 237d6b92ffaSHans Petter Selasky } 238d6b92ffaSHans Petter Selasky 239d6b92ffaSHans Petter Selasky return mw; 240d6b92ffaSHans Petter Selasky } 241d6b92ffaSHans Petter Selasky 242d6b92ffaSHans Petter Selasky int mlx5_dealloc_mw(struct ibv_mw *mw) 243d6b92ffaSHans Petter Selasky { 244d6b92ffaSHans Petter Selasky int ret; 245d6b92ffaSHans Petter Selasky struct ibv_dealloc_mw cmd; 246d6b92ffaSHans Petter Selasky 247d6b92ffaSHans Petter Selasky ret = ibv_cmd_dealloc_mw(mw, &cmd, sizeof(cmd)); 248d6b92ffaSHans Petter Selasky if (ret) 249d6b92ffaSHans Petter Selasky return ret; 250d6b92ffaSHans Petter Selasky 251d6b92ffaSHans Petter Selasky free(mw); 252d6b92ffaSHans Petter Selasky return 0; 253d6b92ffaSHans Petter Selasky } 254d6b92ffaSHans Petter Selasky 255d6b92ffaSHans Petter Selasky int mlx5_round_up_power_of_two(long long sz) 256d6b92ffaSHans Petter Selasky { 257d6b92ffaSHans Petter Selasky long long ret; 258d6b92ffaSHans Petter Selasky 259d6b92ffaSHans Petter Selasky for (ret = 1; ret < sz; ret <<= 1) 260d6b92ffaSHans Petter Selasky ; /* nothing */ 261d6b92ffaSHans Petter Selasky 262d6b92ffaSHans Petter Selasky if (ret > INT_MAX) { 263d6b92ffaSHans Petter Selasky fprintf(stderr, "%s: roundup overflow\n", __func__); 264d6b92ffaSHans Petter Selasky return -ENOMEM; 265d6b92ffaSHans Petter Selasky } 266d6b92ffaSHans Petter Selasky 267d6b92ffaSHans Petter Selasky return (int)ret; 268d6b92ffaSHans Petter Selasky } 269d6b92ffaSHans Petter Selasky 270d6b92ffaSHans Petter Selasky static int align_queue_size(long long req) 271d6b92ffaSHans Petter Selasky { 272d6b92ffaSHans Petter Selasky return mlx5_round_up_power_of_two(req); 273d6b92ffaSHans Petter Selasky } 274d6b92ffaSHans Petter Selasky 275d6b92ffaSHans Petter Selasky static int get_cqe_size(void) 276d6b92ffaSHans Petter Selasky { 277d6b92ffaSHans Petter Selasky char *env; 278d6b92ffaSHans Petter Selasky int size = 64; 279d6b92ffaSHans Petter Selasky 280d6b92ffaSHans Petter Selasky env = getenv("MLX5_CQE_SIZE"); 281d6b92ffaSHans Petter Selasky if (env) 282d6b92ffaSHans Petter Selasky size = atoi(env); 283d6b92ffaSHans Petter Selasky 284d6b92ffaSHans Petter Selasky switch (size) { 285d6b92ffaSHans Petter Selasky case 64: 286d6b92ffaSHans Petter Selasky case 128: 287d6b92ffaSHans Petter Selasky return size; 288d6b92ffaSHans Petter Selasky 289d6b92ffaSHans Petter Selasky default: 290d6b92ffaSHans Petter Selasky return -EINVAL; 291d6b92ffaSHans Petter Selasky } 292d6b92ffaSHans Petter Selasky } 293d6b92ffaSHans Petter Selasky 294d6b92ffaSHans Petter Selasky static int use_scatter_to_cqe(void) 295d6b92ffaSHans Petter Selasky { 296d6b92ffaSHans Petter Selasky char *env; 297d6b92ffaSHans Petter Selasky 298d6b92ffaSHans Petter Selasky env = getenv("MLX5_SCATTER_TO_CQE"); 299d6b92ffaSHans Petter Selasky if (env && !strcmp(env, "0")) 300d6b92ffaSHans Petter Selasky return 0; 301d6b92ffaSHans Petter Selasky 302d6b92ffaSHans Petter Selasky return 1; 303d6b92ffaSHans Petter Selasky } 304d6b92ffaSHans Petter Selasky 305d6b92ffaSHans Petter Selasky static int srq_sig_enabled(void) 306d6b92ffaSHans Petter Selasky { 307d6b92ffaSHans Petter Selasky char *env; 308d6b92ffaSHans Petter Selasky 309d6b92ffaSHans Petter Selasky env = getenv("MLX5_SRQ_SIGNATURE"); 310d6b92ffaSHans Petter Selasky if (env) 311d6b92ffaSHans Petter Selasky return 1; 312d6b92ffaSHans Petter Selasky 313d6b92ffaSHans Petter Selasky return 0; 314d6b92ffaSHans Petter Selasky } 315d6b92ffaSHans Petter Selasky 316d6b92ffaSHans Petter Selasky static int qp_sig_enabled(void) 317d6b92ffaSHans Petter Selasky { 318d6b92ffaSHans Petter Selasky char *env; 319d6b92ffaSHans Petter Selasky 320d6b92ffaSHans Petter Selasky env = getenv("MLX5_QP_SIGNATURE"); 321d6b92ffaSHans Petter Selasky if (env) 322d6b92ffaSHans Petter Selasky return 1; 323d6b92ffaSHans Petter Selasky 324d6b92ffaSHans Petter Selasky return 0; 325d6b92ffaSHans Petter Selasky } 326d6b92ffaSHans Petter Selasky 327d6b92ffaSHans Petter Selasky enum { 328d6b92ffaSHans Petter Selasky CREATE_CQ_SUPPORTED_WC_FLAGS = IBV_WC_STANDARD_FLAGS | 329d6b92ffaSHans Petter Selasky IBV_WC_EX_WITH_COMPLETION_TIMESTAMP | 330d6b92ffaSHans Petter Selasky IBV_WC_EX_WITH_CVLAN | 331d6b92ffaSHans Petter Selasky IBV_WC_EX_WITH_FLOW_TAG 332d6b92ffaSHans Petter Selasky }; 333d6b92ffaSHans Petter Selasky 334d6b92ffaSHans Petter Selasky enum { 335d6b92ffaSHans Petter Selasky CREATE_CQ_SUPPORTED_COMP_MASK = IBV_CQ_INIT_ATTR_MASK_FLAGS 336d6b92ffaSHans Petter Selasky }; 337d6b92ffaSHans Petter Selasky 338d6b92ffaSHans Petter Selasky enum { 339d6b92ffaSHans Petter Selasky CREATE_CQ_SUPPORTED_FLAGS = IBV_CREATE_CQ_ATTR_SINGLE_THREADED 340d6b92ffaSHans Petter Selasky }; 341d6b92ffaSHans Petter Selasky 342d6b92ffaSHans Petter Selasky static struct ibv_cq_ex *create_cq(struct ibv_context *context, 343d6b92ffaSHans Petter Selasky const struct ibv_cq_init_attr_ex *cq_attr, 344d6b92ffaSHans Petter Selasky int cq_alloc_flags, 345d6b92ffaSHans Petter Selasky struct mlx5dv_cq_init_attr *mlx5cq_attr) 346d6b92ffaSHans Petter Selasky { 347d6b92ffaSHans Petter Selasky struct mlx5_create_cq cmd; 348d6b92ffaSHans Petter Selasky struct mlx5_create_cq_resp resp; 349d6b92ffaSHans Petter Selasky struct mlx5_cq *cq; 350d6b92ffaSHans Petter Selasky int cqe_sz; 351d6b92ffaSHans Petter Selasky int ret; 352d6b92ffaSHans Petter Selasky int ncqe; 353d6b92ffaSHans Petter Selasky struct mlx5_context *mctx = to_mctx(context); 354d6b92ffaSHans Petter Selasky FILE *fp = to_mctx(context)->dbg_fp; 355d6b92ffaSHans Petter Selasky 356d6b92ffaSHans Petter Selasky if (!cq_attr->cqe) { 357d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_CQ, "CQE invalid\n"); 358d6b92ffaSHans Petter Selasky errno = EINVAL; 359d6b92ffaSHans Petter Selasky return NULL; 360d6b92ffaSHans Petter Selasky } 361d6b92ffaSHans Petter Selasky 362d6b92ffaSHans Petter Selasky if (cq_attr->comp_mask & ~CREATE_CQ_SUPPORTED_COMP_MASK) { 363d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_CQ, 364d6b92ffaSHans Petter Selasky "Unsupported comp_mask for create_cq\n"); 365d6b92ffaSHans Petter Selasky errno = EINVAL; 366d6b92ffaSHans Petter Selasky return NULL; 367d6b92ffaSHans Petter Selasky } 368d6b92ffaSHans Petter Selasky 369d6b92ffaSHans Petter Selasky if (cq_attr->comp_mask & IBV_CQ_INIT_ATTR_MASK_FLAGS && 370d6b92ffaSHans Petter Selasky cq_attr->flags & ~CREATE_CQ_SUPPORTED_FLAGS) { 371d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_CQ, 372d6b92ffaSHans Petter Selasky "Unsupported creation flags requested for create_cq\n"); 373d6b92ffaSHans Petter Selasky errno = EINVAL; 374d6b92ffaSHans Petter Selasky return NULL; 375d6b92ffaSHans Petter Selasky } 376d6b92ffaSHans Petter Selasky 377d6b92ffaSHans Petter Selasky if (cq_attr->wc_flags & ~CREATE_CQ_SUPPORTED_WC_FLAGS) { 378d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_CQ, "\n"); 379d6b92ffaSHans Petter Selasky errno = ENOTSUP; 380d6b92ffaSHans Petter Selasky return NULL; 381d6b92ffaSHans Petter Selasky } 382d6b92ffaSHans Petter Selasky 383d6b92ffaSHans Petter Selasky cq = calloc(1, sizeof *cq); 384d6b92ffaSHans Petter Selasky if (!cq) { 385d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_CQ, "\n"); 386d6b92ffaSHans Petter Selasky return NULL; 387d6b92ffaSHans Petter Selasky } 388d6b92ffaSHans Petter Selasky 389d6b92ffaSHans Petter Selasky memset(&cmd, 0, sizeof cmd); 390d6b92ffaSHans Petter Selasky cq->cons_index = 0; 391d6b92ffaSHans Petter Selasky 392d6b92ffaSHans Petter Selasky if (mlx5_spinlock_init(&cq->lock)) 393d6b92ffaSHans Petter Selasky goto err; 394d6b92ffaSHans Petter Selasky 395d6b92ffaSHans Petter Selasky ncqe = align_queue_size(cq_attr->cqe + 1); 396d6b92ffaSHans Petter Selasky if ((ncqe > (1 << 24)) || (ncqe < (cq_attr->cqe + 1))) { 397d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_CQ, "ncqe %d\n", ncqe); 398d6b92ffaSHans Petter Selasky errno = EINVAL; 399d6b92ffaSHans Petter Selasky goto err_spl; 400d6b92ffaSHans Petter Selasky } 401d6b92ffaSHans Petter Selasky 402d6b92ffaSHans Petter Selasky cqe_sz = get_cqe_size(); 403d6b92ffaSHans Petter Selasky if (cqe_sz < 0) { 404d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_CQ, "\n"); 405d6b92ffaSHans Petter Selasky errno = -cqe_sz; 406d6b92ffaSHans Petter Selasky goto err_spl; 407d6b92ffaSHans Petter Selasky } 408d6b92ffaSHans Petter Selasky 409d6b92ffaSHans Petter Selasky if (mlx5_alloc_cq_buf(to_mctx(context), cq, &cq->buf_a, ncqe, cqe_sz)) { 410d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_CQ, "\n"); 411d6b92ffaSHans Petter Selasky goto err_spl; 412d6b92ffaSHans Petter Selasky } 413d6b92ffaSHans Petter Selasky 414d6b92ffaSHans Petter Selasky cq->dbrec = mlx5_alloc_dbrec(to_mctx(context)); 415d6b92ffaSHans Petter Selasky if (!cq->dbrec) { 416d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_CQ, "\n"); 417d6b92ffaSHans Petter Selasky goto err_buf; 418d6b92ffaSHans Petter Selasky } 419d6b92ffaSHans Petter Selasky 420d6b92ffaSHans Petter Selasky cq->dbrec[MLX5_CQ_SET_CI] = 0; 421d6b92ffaSHans Petter Selasky cq->dbrec[MLX5_CQ_ARM_DB] = 0; 422d6b92ffaSHans Petter Selasky cq->arm_sn = 0; 423d6b92ffaSHans Petter Selasky cq->cqe_sz = cqe_sz; 424d6b92ffaSHans Petter Selasky cq->flags = cq_alloc_flags; 425d6b92ffaSHans Petter Selasky 426d6b92ffaSHans Petter Selasky if (cq_attr->comp_mask & IBV_CQ_INIT_ATTR_MASK_FLAGS && 427d6b92ffaSHans Petter Selasky cq_attr->flags & IBV_CREATE_CQ_ATTR_SINGLE_THREADED) 428d6b92ffaSHans Petter Selasky cq->flags |= MLX5_CQ_FLAGS_SINGLE_THREADED; 429d6b92ffaSHans Petter Selasky cmd.buf_addr = (uintptr_t) cq->buf_a.buf; 430d6b92ffaSHans Petter Selasky cmd.db_addr = (uintptr_t) cq->dbrec; 431d6b92ffaSHans Petter Selasky cmd.cqe_size = cqe_sz; 432d6b92ffaSHans Petter Selasky 433d6b92ffaSHans Petter Selasky if (mlx5cq_attr) { 434d6b92ffaSHans Petter Selasky if (mlx5cq_attr->comp_mask & ~(MLX5DV_CQ_INIT_ATTR_MASK_RESERVED - 1)) { 435d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_CQ, 436d6b92ffaSHans Petter Selasky "Unsupported vendor comp_mask for create_cq\n"); 437d6b92ffaSHans Petter Selasky errno = EINVAL; 438d6b92ffaSHans Petter Selasky goto err_db; 439d6b92ffaSHans Petter Selasky } 440d6b92ffaSHans Petter Selasky 441d6b92ffaSHans Petter Selasky if (mlx5cq_attr->comp_mask & MLX5DV_CQ_INIT_ATTR_MASK_COMPRESSED_CQE) { 442d6b92ffaSHans Petter Selasky if (mctx->cqe_comp_caps.max_num && 443d6b92ffaSHans Petter Selasky (mlx5cq_attr->cqe_comp_res_format & 444d6b92ffaSHans Petter Selasky mctx->cqe_comp_caps.supported_format)) { 445d6b92ffaSHans Petter Selasky cmd.cqe_comp_en = 1; 446d6b92ffaSHans Petter Selasky cmd.cqe_comp_res_format = mlx5cq_attr->cqe_comp_res_format; 447d6b92ffaSHans Petter Selasky } else { 448d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_CQ, "CQE Compression is not supported\n"); 449d6b92ffaSHans Petter Selasky errno = EINVAL; 450d6b92ffaSHans Petter Selasky goto err_db; 451d6b92ffaSHans Petter Selasky } 452d6b92ffaSHans Petter Selasky } 453d6b92ffaSHans Petter Selasky } 454d6b92ffaSHans Petter Selasky 455d6b92ffaSHans Petter Selasky ret = ibv_cmd_create_cq(context, ncqe - 1, cq_attr->channel, 456d6b92ffaSHans Petter Selasky cq_attr->comp_vector, 457d6b92ffaSHans Petter Selasky ibv_cq_ex_to_cq(&cq->ibv_cq), &cmd.ibv_cmd, 458d6b92ffaSHans Petter Selasky sizeof(cmd), &resp.ibv_resp, sizeof(resp)); 459d6b92ffaSHans Petter Selasky if (ret) { 460d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_CQ, "ret %d\n", ret); 461d6b92ffaSHans Petter Selasky goto err_db; 462d6b92ffaSHans Petter Selasky } 463d6b92ffaSHans Petter Selasky 464d6b92ffaSHans Petter Selasky cq->active_buf = &cq->buf_a; 465d6b92ffaSHans Petter Selasky cq->resize_buf = NULL; 466d6b92ffaSHans Petter Selasky cq->cqn = resp.cqn; 467d6b92ffaSHans Petter Selasky cq->stall_enable = to_mctx(context)->stall_enable; 468d6b92ffaSHans Petter Selasky cq->stall_adaptive_enable = to_mctx(context)->stall_adaptive_enable; 469d6b92ffaSHans Petter Selasky cq->stall_cycles = to_mctx(context)->stall_cycles; 470d6b92ffaSHans Petter Selasky 471d6b92ffaSHans Petter Selasky if (cq_alloc_flags & MLX5_CQ_FLAGS_EXTENDED) 472d6b92ffaSHans Petter Selasky mlx5_cq_fill_pfns(cq, cq_attr); 473d6b92ffaSHans Petter Selasky 474d6b92ffaSHans Petter Selasky return &cq->ibv_cq; 475d6b92ffaSHans Petter Selasky 476d6b92ffaSHans Petter Selasky err_db: 477d6b92ffaSHans Petter Selasky mlx5_free_db(to_mctx(context), cq->dbrec); 478d6b92ffaSHans Petter Selasky 479d6b92ffaSHans Petter Selasky err_buf: 480d6b92ffaSHans Petter Selasky mlx5_free_cq_buf(to_mctx(context), &cq->buf_a); 481d6b92ffaSHans Petter Selasky 482d6b92ffaSHans Petter Selasky err_spl: 483d6b92ffaSHans Petter Selasky mlx5_spinlock_destroy(&cq->lock); 484d6b92ffaSHans Petter Selasky 485d6b92ffaSHans Petter Selasky err: 486d6b92ffaSHans Petter Selasky free(cq); 487d6b92ffaSHans Petter Selasky 488d6b92ffaSHans Petter Selasky return NULL; 489d6b92ffaSHans Petter Selasky } 490d6b92ffaSHans Petter Selasky 491d6b92ffaSHans Petter Selasky struct ibv_cq *mlx5_create_cq(struct ibv_context *context, int cqe, 492d6b92ffaSHans Petter Selasky struct ibv_comp_channel *channel, 493d6b92ffaSHans Petter Selasky int comp_vector) 494d6b92ffaSHans Petter Selasky { 495d6b92ffaSHans Petter Selasky struct ibv_cq_ex *cq; 496d6b92ffaSHans Petter Selasky struct ibv_cq_init_attr_ex cq_attr = {.cqe = cqe, .channel = channel, 497d6b92ffaSHans Petter Selasky .comp_vector = comp_vector, 498d6b92ffaSHans Petter Selasky .wc_flags = IBV_WC_STANDARD_FLAGS}; 499d6b92ffaSHans Petter Selasky 500d6b92ffaSHans Petter Selasky if (cqe <= 0) { 501d6b92ffaSHans Petter Selasky errno = EINVAL; 502d6b92ffaSHans Petter Selasky return NULL; 503d6b92ffaSHans Petter Selasky } 504d6b92ffaSHans Petter Selasky 505d6b92ffaSHans Petter Selasky cq = create_cq(context, &cq_attr, 0, NULL); 506d6b92ffaSHans Petter Selasky return cq ? ibv_cq_ex_to_cq(cq) : NULL; 507d6b92ffaSHans Petter Selasky } 508d6b92ffaSHans Petter Selasky 509d6b92ffaSHans Petter Selasky struct ibv_cq_ex *mlx5_create_cq_ex(struct ibv_context *context, 510d6b92ffaSHans Petter Selasky struct ibv_cq_init_attr_ex *cq_attr) 511d6b92ffaSHans Petter Selasky { 512d6b92ffaSHans Petter Selasky return create_cq(context, cq_attr, MLX5_CQ_FLAGS_EXTENDED, NULL); 513d6b92ffaSHans Petter Selasky } 514d6b92ffaSHans Petter Selasky 515d6b92ffaSHans Petter Selasky struct ibv_cq_ex *mlx5dv_create_cq(struct ibv_context *context, 516d6b92ffaSHans Petter Selasky struct ibv_cq_init_attr_ex *cq_attr, 517d6b92ffaSHans Petter Selasky struct mlx5dv_cq_init_attr *mlx5_cq_attr) 518d6b92ffaSHans Petter Selasky { 519d6b92ffaSHans Petter Selasky struct ibv_cq_ex *cq; 520a687910fSSean Lim int err = 0; 521d6b92ffaSHans Petter Selasky 522d6b92ffaSHans Petter Selasky cq = create_cq(context, cq_attr, MLX5_CQ_FLAGS_EXTENDED, mlx5_cq_attr); 523d6b92ffaSHans Petter Selasky if (!cq) 524d6b92ffaSHans Petter Selasky return NULL; 525d6b92ffaSHans Petter Selasky 526a687910fSSean Lim err = verbs_init_cq(ibv_cq_ex_to_cq(cq), context, 527d6b92ffaSHans Petter Selasky cq_attr->channel, cq_attr->cq_context); 528a687910fSSean Lim if (err) 529a687910fSSean Lim goto err; 530a687910fSSean Lim 531d6b92ffaSHans Petter Selasky return cq; 532a687910fSSean Lim 533a687910fSSean Lim err: 534a687910fSSean Lim context->ops.destroy_cq(ibv_cq_ex_to_cq(cq)); 535a687910fSSean Lim 536a687910fSSean Lim return NULL; 537d6b92ffaSHans Petter Selasky } 538d6b92ffaSHans Petter Selasky 539d6b92ffaSHans Petter Selasky int mlx5_resize_cq(struct ibv_cq *ibcq, int cqe) 540d6b92ffaSHans Petter Selasky { 541d6b92ffaSHans Petter Selasky struct mlx5_cq *cq = to_mcq(ibcq); 542d6b92ffaSHans Petter Selasky struct mlx5_resize_cq_resp resp; 543d6b92ffaSHans Petter Selasky struct mlx5_resize_cq cmd; 544d6b92ffaSHans Petter Selasky struct mlx5_context *mctx = to_mctx(ibcq->context); 545d6b92ffaSHans Petter Selasky int err; 546d6b92ffaSHans Petter Selasky 547d6b92ffaSHans Petter Selasky if (cqe < 0) { 548d6b92ffaSHans Petter Selasky errno = EINVAL; 549d6b92ffaSHans Petter Selasky return errno; 550d6b92ffaSHans Petter Selasky } 551d6b92ffaSHans Petter Selasky 552d6b92ffaSHans Petter Selasky memset(&cmd, 0, sizeof(cmd)); 553d6b92ffaSHans Petter Selasky memset(&resp, 0, sizeof(resp)); 554d6b92ffaSHans Petter Selasky 555d6b92ffaSHans Petter Selasky if (((long long)cqe * 64) > INT_MAX) 556d6b92ffaSHans Petter Selasky return EINVAL; 557d6b92ffaSHans Petter Selasky 558d6b92ffaSHans Petter Selasky mlx5_spin_lock(&cq->lock); 559d6b92ffaSHans Petter Selasky cq->active_cqes = cq->ibv_cq.cqe; 560d6b92ffaSHans Petter Selasky if (cq->active_buf == &cq->buf_a) 561d6b92ffaSHans Petter Selasky cq->resize_buf = &cq->buf_b; 562d6b92ffaSHans Petter Selasky else 563d6b92ffaSHans Petter Selasky cq->resize_buf = &cq->buf_a; 564d6b92ffaSHans Petter Selasky 565d6b92ffaSHans Petter Selasky cqe = align_queue_size(cqe + 1); 566d6b92ffaSHans Petter Selasky if (cqe == ibcq->cqe + 1) { 567d6b92ffaSHans Petter Selasky cq->resize_buf = NULL; 568d6b92ffaSHans Petter Selasky err = 0; 569d6b92ffaSHans Petter Selasky goto out; 570d6b92ffaSHans Petter Selasky } 571d6b92ffaSHans Petter Selasky 572d6b92ffaSHans Petter Selasky /* currently we don't change cqe size */ 573d6b92ffaSHans Petter Selasky cq->resize_cqe_sz = cq->cqe_sz; 574d6b92ffaSHans Petter Selasky cq->resize_cqes = cqe; 575d6b92ffaSHans Petter Selasky err = mlx5_alloc_cq_buf(mctx, cq, cq->resize_buf, cq->resize_cqes, cq->resize_cqe_sz); 576d6b92ffaSHans Petter Selasky if (err) { 577d6b92ffaSHans Petter Selasky cq->resize_buf = NULL; 578d6b92ffaSHans Petter Selasky errno = ENOMEM; 579d6b92ffaSHans Petter Selasky goto out; 580d6b92ffaSHans Petter Selasky } 581d6b92ffaSHans Petter Selasky 582d6b92ffaSHans Petter Selasky cmd.buf_addr = (uintptr_t)cq->resize_buf->buf; 583d6b92ffaSHans Petter Selasky cmd.cqe_size = cq->resize_cqe_sz; 584d6b92ffaSHans Petter Selasky 585d6b92ffaSHans Petter Selasky err = ibv_cmd_resize_cq(ibcq, cqe - 1, &cmd.ibv_cmd, sizeof(cmd), 586d6b92ffaSHans Petter Selasky &resp.ibv_resp, sizeof(resp)); 587d6b92ffaSHans Petter Selasky if (err) 588d6b92ffaSHans Petter Selasky goto out_buf; 589d6b92ffaSHans Petter Selasky 590d6b92ffaSHans Petter Selasky mlx5_cq_resize_copy_cqes(cq); 591d6b92ffaSHans Petter Selasky mlx5_free_cq_buf(mctx, cq->active_buf); 592d6b92ffaSHans Petter Selasky cq->active_buf = cq->resize_buf; 593d6b92ffaSHans Petter Selasky cq->ibv_cq.cqe = cqe - 1; 594d6b92ffaSHans Petter Selasky mlx5_spin_unlock(&cq->lock); 595d6b92ffaSHans Petter Selasky cq->resize_buf = NULL; 596d6b92ffaSHans Petter Selasky return 0; 597d6b92ffaSHans Petter Selasky 598d6b92ffaSHans Petter Selasky out_buf: 599d6b92ffaSHans Petter Selasky mlx5_free_cq_buf(mctx, cq->resize_buf); 600d6b92ffaSHans Petter Selasky cq->resize_buf = NULL; 601d6b92ffaSHans Petter Selasky 602d6b92ffaSHans Petter Selasky out: 603d6b92ffaSHans Petter Selasky mlx5_spin_unlock(&cq->lock); 604d6b92ffaSHans Petter Selasky return err; 605d6b92ffaSHans Petter Selasky } 606d6b92ffaSHans Petter Selasky 607d6b92ffaSHans Petter Selasky int mlx5_destroy_cq(struct ibv_cq *cq) 608d6b92ffaSHans Petter Selasky { 609d6b92ffaSHans Petter Selasky int ret; 610a687910fSSean Lim struct mlx5_cq *mcq = to_mcq(cq); 611d6b92ffaSHans Petter Selasky 612d6b92ffaSHans Petter Selasky ret = ibv_cmd_destroy_cq(cq); 613d6b92ffaSHans Petter Selasky if (ret) 614d6b92ffaSHans Petter Selasky return ret; 615d6b92ffaSHans Petter Selasky 616a687910fSSean Lim verbs_cleanup_cq(cq); 617d6b92ffaSHans Petter Selasky mlx5_free_db(to_mctx(cq->context), to_mcq(cq)->dbrec); 618d6b92ffaSHans Petter Selasky mlx5_free_cq_buf(to_mctx(cq->context), to_mcq(cq)->active_buf); 619a687910fSSean Lim mlx5_spinlock_destroy(&mcq->lock); 620d6b92ffaSHans Petter Selasky free(to_mcq(cq)); 621d6b92ffaSHans Petter Selasky 622d6b92ffaSHans Petter Selasky return 0; 623d6b92ffaSHans Petter Selasky } 624d6b92ffaSHans Petter Selasky 625d6b92ffaSHans Petter Selasky struct ibv_srq *mlx5_create_srq(struct ibv_pd *pd, 626d6b92ffaSHans Petter Selasky struct ibv_srq_init_attr *attr) 627d6b92ffaSHans Petter Selasky { 628d6b92ffaSHans Petter Selasky struct mlx5_create_srq cmd; 629d6b92ffaSHans Petter Selasky struct mlx5_create_srq_resp resp; 630d6b92ffaSHans Petter Selasky struct mlx5_srq *srq; 631d6b92ffaSHans Petter Selasky int ret; 632d6b92ffaSHans Petter Selasky struct mlx5_context *ctx; 633d6b92ffaSHans Petter Selasky int max_sge; 634d6b92ffaSHans Petter Selasky struct ibv_srq *ibsrq; 635d6b92ffaSHans Petter Selasky 636d6b92ffaSHans Petter Selasky ctx = to_mctx(pd->context); 637d6b92ffaSHans Petter Selasky srq = calloc(1, sizeof *srq); 638d6b92ffaSHans Petter Selasky if (!srq) { 639d6b92ffaSHans Petter Selasky fprintf(stderr, "%s-%d:\n", __func__, __LINE__); 640d6b92ffaSHans Petter Selasky return NULL; 641d6b92ffaSHans Petter Selasky } 642d6b92ffaSHans Petter Selasky ibsrq = &srq->vsrq.srq; 643d6b92ffaSHans Petter Selasky 644d6b92ffaSHans Petter Selasky memset(&cmd, 0, sizeof cmd); 645d6b92ffaSHans Petter Selasky if (mlx5_spinlock_init(&srq->lock)) { 646d6b92ffaSHans Petter Selasky fprintf(stderr, "%s-%d:\n", __func__, __LINE__); 647d6b92ffaSHans Petter Selasky goto err; 648d6b92ffaSHans Petter Selasky } 649d6b92ffaSHans Petter Selasky 650d6b92ffaSHans Petter Selasky if (attr->attr.max_wr > ctx->max_srq_recv_wr) { 651d6b92ffaSHans Petter Selasky fprintf(stderr, "%s-%d:max_wr %d, max_srq_recv_wr %d\n", __func__, __LINE__, 652d6b92ffaSHans Petter Selasky attr->attr.max_wr, ctx->max_srq_recv_wr); 653d6b92ffaSHans Petter Selasky errno = EINVAL; 654a687910fSSean Lim goto err_spl; 655d6b92ffaSHans Petter Selasky } 656d6b92ffaSHans Petter Selasky 657d6b92ffaSHans Petter Selasky /* 658d6b92ffaSHans Petter Selasky * this calculation does not consider required control segments. The 659d6b92ffaSHans Petter Selasky * final calculation is done again later. This is done so to avoid 660d6b92ffaSHans Petter Selasky * overflows of variables 661d6b92ffaSHans Petter Selasky */ 662d6b92ffaSHans Petter Selasky max_sge = ctx->max_rq_desc_sz / sizeof(struct mlx5_wqe_data_seg); 663d6b92ffaSHans Petter Selasky if (attr->attr.max_sge > max_sge) { 664d6b92ffaSHans Petter Selasky fprintf(stderr, "%s-%d:max_wr %d, max_srq_recv_wr %d\n", __func__, __LINE__, 665d6b92ffaSHans Petter Selasky attr->attr.max_wr, ctx->max_srq_recv_wr); 666d6b92ffaSHans Petter Selasky errno = EINVAL; 667a687910fSSean Lim goto err_spl; 668d6b92ffaSHans Petter Selasky } 669d6b92ffaSHans Petter Selasky 670d6b92ffaSHans Petter Selasky srq->max = align_queue_size(attr->attr.max_wr + 1); 671d6b92ffaSHans Petter Selasky srq->max_gs = attr->attr.max_sge; 672d6b92ffaSHans Petter Selasky srq->counter = 0; 673d6b92ffaSHans Petter Selasky 674d6b92ffaSHans Petter Selasky if (mlx5_alloc_srq_buf(pd->context, srq)) { 675d6b92ffaSHans Petter Selasky fprintf(stderr, "%s-%d:\n", __func__, __LINE__); 676a687910fSSean Lim goto err_spl; 677d6b92ffaSHans Petter Selasky } 678d6b92ffaSHans Petter Selasky 679d6b92ffaSHans Petter Selasky srq->db = mlx5_alloc_dbrec(to_mctx(pd->context)); 680d6b92ffaSHans Petter Selasky if (!srq->db) { 681d6b92ffaSHans Petter Selasky fprintf(stderr, "%s-%d:\n", __func__, __LINE__); 682d6b92ffaSHans Petter Selasky goto err_free; 683d6b92ffaSHans Petter Selasky } 684d6b92ffaSHans Petter Selasky 685d6b92ffaSHans Petter Selasky *srq->db = 0; 686d6b92ffaSHans Petter Selasky 687d6b92ffaSHans Petter Selasky cmd.buf_addr = (uintptr_t) srq->buf.buf; 688d6b92ffaSHans Petter Selasky cmd.db_addr = (uintptr_t) srq->db; 689d6b92ffaSHans Petter Selasky srq->wq_sig = srq_sig_enabled(); 690d6b92ffaSHans Petter Selasky if (srq->wq_sig) 691d6b92ffaSHans Petter Selasky cmd.flags = MLX5_SRQ_FLAG_SIGNATURE; 692d6b92ffaSHans Petter Selasky 693d6b92ffaSHans Petter Selasky attr->attr.max_sge = srq->max_gs; 694d6b92ffaSHans Petter Selasky pthread_mutex_lock(&ctx->srq_table_mutex); 695d6b92ffaSHans Petter Selasky ret = ibv_cmd_create_srq(pd, ibsrq, attr, &cmd.ibv_cmd, sizeof(cmd), 696d6b92ffaSHans Petter Selasky &resp.ibv_resp, sizeof(resp)); 697d6b92ffaSHans Petter Selasky if (ret) 698d6b92ffaSHans Petter Selasky goto err_db; 699d6b92ffaSHans Petter Selasky 700d6b92ffaSHans Petter Selasky ret = mlx5_store_srq(ctx, resp.srqn, srq); 701d6b92ffaSHans Petter Selasky if (ret) 702d6b92ffaSHans Petter Selasky goto err_destroy; 703d6b92ffaSHans Petter Selasky 704d6b92ffaSHans Petter Selasky pthread_mutex_unlock(&ctx->srq_table_mutex); 705d6b92ffaSHans Petter Selasky 706d6b92ffaSHans Petter Selasky srq->srqn = resp.srqn; 707d6b92ffaSHans Petter Selasky srq->rsc.rsn = resp.srqn; 708d6b92ffaSHans Petter Selasky srq->rsc.type = MLX5_RSC_TYPE_SRQ; 709d6b92ffaSHans Petter Selasky 710d6b92ffaSHans Petter Selasky return ibsrq; 711d6b92ffaSHans Petter Selasky 712d6b92ffaSHans Petter Selasky err_destroy: 713d6b92ffaSHans Petter Selasky ibv_cmd_destroy_srq(ibsrq); 714d6b92ffaSHans Petter Selasky 715d6b92ffaSHans Petter Selasky err_db: 716d6b92ffaSHans Petter Selasky pthread_mutex_unlock(&ctx->srq_table_mutex); 717d6b92ffaSHans Petter Selasky mlx5_free_db(to_mctx(pd->context), srq->db); 718d6b92ffaSHans Petter Selasky 719d6b92ffaSHans Petter Selasky err_free: 720d6b92ffaSHans Petter Selasky free(srq->wrid); 721d6b92ffaSHans Petter Selasky mlx5_free_buf(&srq->buf); 722d6b92ffaSHans Petter Selasky 723a687910fSSean Lim err_spl: 724a687910fSSean Lim mlx5_spinlock_destroy(&srq->lock); 725a687910fSSean Lim 726d6b92ffaSHans Petter Selasky err: 727d6b92ffaSHans Petter Selasky free(srq); 728d6b92ffaSHans Petter Selasky 729d6b92ffaSHans Petter Selasky return NULL; 730d6b92ffaSHans Petter Selasky } 731d6b92ffaSHans Petter Selasky 732d6b92ffaSHans Petter Selasky int mlx5_modify_srq(struct ibv_srq *srq, 733d6b92ffaSHans Petter Selasky struct ibv_srq_attr *attr, 734d6b92ffaSHans Petter Selasky int attr_mask) 735d6b92ffaSHans Petter Selasky { 736d6b92ffaSHans Petter Selasky struct ibv_modify_srq cmd; 737d6b92ffaSHans Petter Selasky 738d6b92ffaSHans Petter Selasky return ibv_cmd_modify_srq(srq, attr, attr_mask, &cmd, sizeof cmd); 739d6b92ffaSHans Petter Selasky } 740d6b92ffaSHans Petter Selasky 741d6b92ffaSHans Petter Selasky int mlx5_query_srq(struct ibv_srq *srq, 742d6b92ffaSHans Petter Selasky struct ibv_srq_attr *attr) 743d6b92ffaSHans Petter Selasky { 744d6b92ffaSHans Petter Selasky struct ibv_query_srq cmd; 745d6b92ffaSHans Petter Selasky 746d6b92ffaSHans Petter Selasky return ibv_cmd_query_srq(srq, attr, &cmd, sizeof cmd); 747d6b92ffaSHans Petter Selasky } 748d6b92ffaSHans Petter Selasky 749d6b92ffaSHans Petter Selasky int mlx5_destroy_srq(struct ibv_srq *srq) 750d6b92ffaSHans Petter Selasky { 751d6b92ffaSHans Petter Selasky int ret; 752d6b92ffaSHans Petter Selasky struct mlx5_srq *msrq = to_msrq(srq); 753d6b92ffaSHans Petter Selasky struct mlx5_context *ctx = to_mctx(srq->context); 754d6b92ffaSHans Petter Selasky 755d6b92ffaSHans Petter Selasky ret = ibv_cmd_destroy_srq(srq); 756d6b92ffaSHans Petter Selasky if (ret) 757d6b92ffaSHans Petter Selasky return ret; 758d6b92ffaSHans Petter Selasky 759d6b92ffaSHans Petter Selasky if (ctx->cqe_version && msrq->rsc.type == MLX5_RSC_TYPE_XSRQ) 760d6b92ffaSHans Petter Selasky mlx5_clear_uidx(ctx, msrq->rsc.rsn); 761d6b92ffaSHans Petter Selasky else 762d6b92ffaSHans Petter Selasky mlx5_clear_srq(ctx, msrq->srqn); 763d6b92ffaSHans Petter Selasky 764d6b92ffaSHans Petter Selasky mlx5_free_db(ctx, msrq->db); 765d6b92ffaSHans Petter Selasky mlx5_free_buf(&msrq->buf); 766d6b92ffaSHans Petter Selasky free(msrq->wrid); 767a687910fSSean Lim mlx5_spinlock_destroy(&msrq->lock); 768d6b92ffaSHans Petter Selasky free(msrq); 769d6b92ffaSHans Petter Selasky 770d6b92ffaSHans Petter Selasky return 0; 771d6b92ffaSHans Petter Selasky } 772d6b92ffaSHans Petter Selasky 773d6b92ffaSHans Petter Selasky static int sq_overhead(enum ibv_qp_type qp_type) 774d6b92ffaSHans Petter Selasky { 775d6b92ffaSHans Petter Selasky size_t size = 0; 776d6b92ffaSHans Petter Selasky size_t mw_bind_size = 777d6b92ffaSHans Petter Selasky sizeof(struct mlx5_wqe_umr_ctrl_seg) + 778d6b92ffaSHans Petter Selasky sizeof(struct mlx5_wqe_mkey_context_seg) + 779d6b92ffaSHans Petter Selasky max_t(size_t, sizeof(struct mlx5_wqe_umr_klm_seg), 64); 780d6b92ffaSHans Petter Selasky 781d6b92ffaSHans Petter Selasky switch (qp_type) { 782d6b92ffaSHans Petter Selasky case IBV_QPT_RC: 783d6b92ffaSHans Petter Selasky size += sizeof(struct mlx5_wqe_ctrl_seg) + 784d6b92ffaSHans Petter Selasky max(sizeof(struct mlx5_wqe_atomic_seg) + 785d6b92ffaSHans Petter Selasky sizeof(struct mlx5_wqe_raddr_seg), 786d6b92ffaSHans Petter Selasky mw_bind_size); 787d6b92ffaSHans Petter Selasky break; 788d6b92ffaSHans Petter Selasky 789d6b92ffaSHans Petter Selasky case IBV_QPT_UC: 790d6b92ffaSHans Petter Selasky size = sizeof(struct mlx5_wqe_ctrl_seg) + 791d6b92ffaSHans Petter Selasky max(sizeof(struct mlx5_wqe_raddr_seg), 792d6b92ffaSHans Petter Selasky mw_bind_size); 793d6b92ffaSHans Petter Selasky break; 794d6b92ffaSHans Petter Selasky 795d6b92ffaSHans Petter Selasky case IBV_QPT_UD: 796d6b92ffaSHans Petter Selasky size = sizeof(struct mlx5_wqe_ctrl_seg) + 797d6b92ffaSHans Petter Selasky sizeof(struct mlx5_wqe_datagram_seg); 798d6b92ffaSHans Petter Selasky break; 799d6b92ffaSHans Petter Selasky 800d6b92ffaSHans Petter Selasky case IBV_QPT_XRC_SEND: 801d6b92ffaSHans Petter Selasky size = sizeof(struct mlx5_wqe_ctrl_seg) + mw_bind_size; 802d6b92ffaSHans Petter Selasky SWITCH_FALLTHROUGH; 803d6b92ffaSHans Petter Selasky 804d6b92ffaSHans Petter Selasky case IBV_QPT_XRC_RECV: 805d6b92ffaSHans Petter Selasky size = max(size, sizeof(struct mlx5_wqe_ctrl_seg) + 806d6b92ffaSHans Petter Selasky sizeof(struct mlx5_wqe_xrc_seg) + 807d6b92ffaSHans Petter Selasky sizeof(struct mlx5_wqe_raddr_seg)); 808d6b92ffaSHans Petter Selasky break; 809d6b92ffaSHans Petter Selasky 810d6b92ffaSHans Petter Selasky case IBV_QPT_RAW_PACKET: 811d6b92ffaSHans Petter Selasky size = sizeof(struct mlx5_wqe_ctrl_seg) + 812d6b92ffaSHans Petter Selasky sizeof(struct mlx5_wqe_eth_seg); 813d6b92ffaSHans Petter Selasky break; 814d6b92ffaSHans Petter Selasky 815d6b92ffaSHans Petter Selasky default: 816d6b92ffaSHans Petter Selasky return -EINVAL; 817d6b92ffaSHans Petter Selasky } 818d6b92ffaSHans Petter Selasky 819d6b92ffaSHans Petter Selasky return size; 820d6b92ffaSHans Petter Selasky } 821d6b92ffaSHans Petter Selasky 822d6b92ffaSHans Petter Selasky static int mlx5_calc_send_wqe(struct mlx5_context *ctx, 823d6b92ffaSHans Petter Selasky struct ibv_qp_init_attr_ex *attr, 824d6b92ffaSHans Petter Selasky struct mlx5_qp *qp) 825d6b92ffaSHans Petter Selasky { 826d6b92ffaSHans Petter Selasky int size; 827d6b92ffaSHans Petter Selasky int inl_size = 0; 828d6b92ffaSHans Petter Selasky int max_gather; 829d6b92ffaSHans Petter Selasky int tot_size; 830d6b92ffaSHans Petter Selasky 831d6b92ffaSHans Petter Selasky size = sq_overhead(attr->qp_type); 832d6b92ffaSHans Petter Selasky if (size < 0) 833d6b92ffaSHans Petter Selasky return size; 834d6b92ffaSHans Petter Selasky 835d6b92ffaSHans Petter Selasky if (attr->cap.max_inline_data) { 836d6b92ffaSHans Petter Selasky inl_size = size + align(sizeof(struct mlx5_wqe_inl_data_seg) + 837d6b92ffaSHans Petter Selasky attr->cap.max_inline_data, 16); 838d6b92ffaSHans Petter Selasky } 839d6b92ffaSHans Petter Selasky 840d6b92ffaSHans Petter Selasky if (attr->comp_mask & IBV_QP_INIT_ATTR_MAX_TSO_HEADER) { 841d6b92ffaSHans Petter Selasky size += align(attr->max_tso_header, 16); 842d6b92ffaSHans Petter Selasky qp->max_tso_header = attr->max_tso_header; 843d6b92ffaSHans Petter Selasky } 844d6b92ffaSHans Petter Selasky 845d6b92ffaSHans Petter Selasky max_gather = (ctx->max_sq_desc_sz - size) / 846d6b92ffaSHans Petter Selasky sizeof(struct mlx5_wqe_data_seg); 847d6b92ffaSHans Petter Selasky if (attr->cap.max_send_sge > max_gather) 848d6b92ffaSHans Petter Selasky return -EINVAL; 849d6b92ffaSHans Petter Selasky 850d6b92ffaSHans Petter Selasky size += attr->cap.max_send_sge * sizeof(struct mlx5_wqe_data_seg); 851d6b92ffaSHans Petter Selasky tot_size = max_int(size, inl_size); 852d6b92ffaSHans Petter Selasky 853d6b92ffaSHans Petter Selasky if (tot_size > ctx->max_sq_desc_sz) 854d6b92ffaSHans Petter Selasky return -EINVAL; 855d6b92ffaSHans Petter Selasky 856d6b92ffaSHans Petter Selasky return align(tot_size, MLX5_SEND_WQE_BB); 857d6b92ffaSHans Petter Selasky } 858d6b92ffaSHans Petter Selasky 859d6b92ffaSHans Petter Selasky static int mlx5_calc_rcv_wqe(struct mlx5_context *ctx, 860d6b92ffaSHans Petter Selasky struct ibv_qp_init_attr_ex *attr, 861d6b92ffaSHans Petter Selasky struct mlx5_qp *qp) 862d6b92ffaSHans Petter Selasky { 863d6b92ffaSHans Petter Selasky uint32_t size; 864d6b92ffaSHans Petter Selasky int num_scatter; 865d6b92ffaSHans Petter Selasky 866d6b92ffaSHans Petter Selasky if (attr->srq) 867d6b92ffaSHans Petter Selasky return 0; 868d6b92ffaSHans Petter Selasky 869d6b92ffaSHans Petter Selasky num_scatter = max_t(uint32_t, attr->cap.max_recv_sge, 1); 870d6b92ffaSHans Petter Selasky size = sizeof(struct mlx5_wqe_data_seg) * num_scatter; 871d6b92ffaSHans Petter Selasky if (qp->wq_sig) 872d6b92ffaSHans Petter Selasky size += sizeof(struct mlx5_rwqe_sig); 873d6b92ffaSHans Petter Selasky 874d6b92ffaSHans Petter Selasky if (size > ctx->max_rq_desc_sz) 875d6b92ffaSHans Petter Selasky return -EINVAL; 876d6b92ffaSHans Petter Selasky 877d6b92ffaSHans Petter Selasky size = mlx5_round_up_power_of_two(size); 878d6b92ffaSHans Petter Selasky 879d6b92ffaSHans Petter Selasky return size; 880d6b92ffaSHans Petter Selasky } 881d6b92ffaSHans Petter Selasky 882d6b92ffaSHans Petter Selasky static int mlx5_calc_sq_size(struct mlx5_context *ctx, 883d6b92ffaSHans Petter Selasky struct ibv_qp_init_attr_ex *attr, 884d6b92ffaSHans Petter Selasky struct mlx5_qp *qp) 885d6b92ffaSHans Petter Selasky { 886d6b92ffaSHans Petter Selasky int wqe_size; 887d6b92ffaSHans Petter Selasky int wq_size; 888d6b92ffaSHans Petter Selasky FILE *fp = ctx->dbg_fp; 889d6b92ffaSHans Petter Selasky 890d6b92ffaSHans Petter Selasky if (!attr->cap.max_send_wr) 891d6b92ffaSHans Petter Selasky return 0; 892d6b92ffaSHans Petter Selasky 893d6b92ffaSHans Petter Selasky wqe_size = mlx5_calc_send_wqe(ctx, attr, qp); 894d6b92ffaSHans Petter Selasky if (wqe_size < 0) { 895d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_QP, "\n"); 896d6b92ffaSHans Petter Selasky return wqe_size; 897d6b92ffaSHans Petter Selasky } 898d6b92ffaSHans Petter Selasky 899d6b92ffaSHans Petter Selasky if (wqe_size > ctx->max_sq_desc_sz) { 900d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_QP, "\n"); 901d6b92ffaSHans Petter Selasky return -EINVAL; 902d6b92ffaSHans Petter Selasky } 903d6b92ffaSHans Petter Selasky 904d6b92ffaSHans Petter Selasky qp->max_inline_data = wqe_size - sq_overhead(attr->qp_type) - 905d6b92ffaSHans Petter Selasky sizeof(struct mlx5_wqe_inl_data_seg); 906d6b92ffaSHans Petter Selasky attr->cap.max_inline_data = qp->max_inline_data; 907d6b92ffaSHans Petter Selasky 908d6b92ffaSHans Petter Selasky /* 909d6b92ffaSHans Petter Selasky * to avoid overflow, we limit max_send_wr so 910d6b92ffaSHans Petter Selasky * that the multiplication will fit in int 911d6b92ffaSHans Petter Selasky */ 912d6b92ffaSHans Petter Selasky if (attr->cap.max_send_wr > 0x7fffffff / ctx->max_sq_desc_sz) { 913d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_QP, "\n"); 914d6b92ffaSHans Petter Selasky return -EINVAL; 915d6b92ffaSHans Petter Selasky } 916d6b92ffaSHans Petter Selasky 917d6b92ffaSHans Petter Selasky wq_size = mlx5_round_up_power_of_two(attr->cap.max_send_wr * wqe_size); 918d6b92ffaSHans Petter Selasky qp->sq.wqe_cnt = wq_size / MLX5_SEND_WQE_BB; 919d6b92ffaSHans Petter Selasky if (qp->sq.wqe_cnt > ctx->max_send_wqebb) { 920d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_QP, "\n"); 921d6b92ffaSHans Petter Selasky return -EINVAL; 922d6b92ffaSHans Petter Selasky } 923d6b92ffaSHans Petter Selasky 924d6b92ffaSHans Petter Selasky qp->sq.wqe_shift = mlx5_ilog2(MLX5_SEND_WQE_BB); 925d6b92ffaSHans Petter Selasky qp->sq.max_gs = attr->cap.max_send_sge; 926d6b92ffaSHans Petter Selasky qp->sq.max_post = wq_size / wqe_size; 927d6b92ffaSHans Petter Selasky 928d6b92ffaSHans Petter Selasky return wq_size; 929d6b92ffaSHans Petter Selasky } 930d6b92ffaSHans Petter Selasky 931d6b92ffaSHans Petter Selasky static int mlx5_calc_rwq_size(struct mlx5_context *ctx, 932d6b92ffaSHans Petter Selasky struct mlx5_rwq *rwq, 933d6b92ffaSHans Petter Selasky struct ibv_wq_init_attr *attr) 934d6b92ffaSHans Petter Selasky { 935d6b92ffaSHans Petter Selasky size_t wqe_size; 936d6b92ffaSHans Petter Selasky int wq_size; 937d6b92ffaSHans Petter Selasky uint32_t num_scatter; 938d6b92ffaSHans Petter Selasky int scat_spc; 939d6b92ffaSHans Petter Selasky 940d6b92ffaSHans Petter Selasky if (!attr->max_wr) 941d6b92ffaSHans Petter Selasky return -EINVAL; 942d6b92ffaSHans Petter Selasky 943d6b92ffaSHans Petter Selasky /* TBD: check caps for RQ */ 944d6b92ffaSHans Petter Selasky num_scatter = max_t(uint32_t, attr->max_sge, 1); 945d6b92ffaSHans Petter Selasky wqe_size = sizeof(struct mlx5_wqe_data_seg) * num_scatter; 946d6b92ffaSHans Petter Selasky 947d6b92ffaSHans Petter Selasky if (rwq->wq_sig) 948d6b92ffaSHans Petter Selasky wqe_size += sizeof(struct mlx5_rwqe_sig); 949d6b92ffaSHans Petter Selasky 950d6b92ffaSHans Petter Selasky if (wqe_size <= 0 || wqe_size > ctx->max_rq_desc_sz) 951d6b92ffaSHans Petter Selasky return -EINVAL; 952d6b92ffaSHans Petter Selasky 953d6b92ffaSHans Petter Selasky wqe_size = mlx5_round_up_power_of_two(wqe_size); 954d6b92ffaSHans Petter Selasky wq_size = mlx5_round_up_power_of_two(attr->max_wr) * wqe_size; 955d6b92ffaSHans Petter Selasky wq_size = max(wq_size, MLX5_SEND_WQE_BB); 956d6b92ffaSHans Petter Selasky rwq->rq.wqe_cnt = wq_size / wqe_size; 957d6b92ffaSHans Petter Selasky rwq->rq.wqe_shift = mlx5_ilog2(wqe_size); 958d6b92ffaSHans Petter Selasky rwq->rq.max_post = 1 << mlx5_ilog2(wq_size / wqe_size); 959d6b92ffaSHans Petter Selasky scat_spc = wqe_size - 960d6b92ffaSHans Petter Selasky ((rwq->wq_sig) ? sizeof(struct mlx5_rwqe_sig) : 0); 961d6b92ffaSHans Petter Selasky rwq->rq.max_gs = scat_spc / sizeof(struct mlx5_wqe_data_seg); 962d6b92ffaSHans Petter Selasky return wq_size; 963d6b92ffaSHans Petter Selasky } 964d6b92ffaSHans Petter Selasky 965d6b92ffaSHans Petter Selasky static int mlx5_calc_rq_size(struct mlx5_context *ctx, 966d6b92ffaSHans Petter Selasky struct ibv_qp_init_attr_ex *attr, 967d6b92ffaSHans Petter Selasky struct mlx5_qp *qp) 968d6b92ffaSHans Petter Selasky { 969d6b92ffaSHans Petter Selasky int wqe_size; 970d6b92ffaSHans Petter Selasky int wq_size; 971d6b92ffaSHans Petter Selasky int scat_spc; 972d6b92ffaSHans Petter Selasky FILE *fp = ctx->dbg_fp; 973d6b92ffaSHans Petter Selasky 974d6b92ffaSHans Petter Selasky if (!attr->cap.max_recv_wr) 975d6b92ffaSHans Petter Selasky return 0; 976d6b92ffaSHans Petter Selasky 977d6b92ffaSHans Petter Selasky if (attr->cap.max_recv_wr > ctx->max_recv_wr) { 978d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_QP, "\n"); 979d6b92ffaSHans Petter Selasky return -EINVAL; 980d6b92ffaSHans Petter Selasky } 981d6b92ffaSHans Petter Selasky 982d6b92ffaSHans Petter Selasky wqe_size = mlx5_calc_rcv_wqe(ctx, attr, qp); 983d6b92ffaSHans Petter Selasky if (wqe_size < 0 || wqe_size > ctx->max_rq_desc_sz) { 984d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_QP, "\n"); 985d6b92ffaSHans Petter Selasky return -EINVAL; 986d6b92ffaSHans Petter Selasky } 987d6b92ffaSHans Petter Selasky 988d6b92ffaSHans Petter Selasky wq_size = mlx5_round_up_power_of_two(attr->cap.max_recv_wr) * wqe_size; 989d6b92ffaSHans Petter Selasky if (wqe_size) { 990d6b92ffaSHans Petter Selasky wq_size = max(wq_size, MLX5_SEND_WQE_BB); 991d6b92ffaSHans Petter Selasky qp->rq.wqe_cnt = wq_size / wqe_size; 992d6b92ffaSHans Petter Selasky qp->rq.wqe_shift = mlx5_ilog2(wqe_size); 993d6b92ffaSHans Petter Selasky qp->rq.max_post = 1 << mlx5_ilog2(wq_size / wqe_size); 994d6b92ffaSHans Petter Selasky scat_spc = wqe_size - 995d6b92ffaSHans Petter Selasky (qp->wq_sig ? sizeof(struct mlx5_rwqe_sig) : 0); 996d6b92ffaSHans Petter Selasky qp->rq.max_gs = scat_spc / sizeof(struct mlx5_wqe_data_seg); 997d6b92ffaSHans Petter Selasky } else { 998d6b92ffaSHans Petter Selasky qp->rq.wqe_cnt = 0; 999d6b92ffaSHans Petter Selasky qp->rq.wqe_shift = 0; 1000d6b92ffaSHans Petter Selasky qp->rq.max_post = 0; 1001d6b92ffaSHans Petter Selasky qp->rq.max_gs = 0; 1002d6b92ffaSHans Petter Selasky } 1003d6b92ffaSHans Petter Selasky return wq_size; 1004d6b92ffaSHans Petter Selasky } 1005d6b92ffaSHans Petter Selasky 1006d6b92ffaSHans Petter Selasky static int mlx5_calc_wq_size(struct mlx5_context *ctx, 1007d6b92ffaSHans Petter Selasky struct ibv_qp_init_attr_ex *attr, 1008d6b92ffaSHans Petter Selasky struct mlx5_qp *qp) 1009d6b92ffaSHans Petter Selasky { 1010d6b92ffaSHans Petter Selasky int ret; 1011d6b92ffaSHans Petter Selasky int result; 1012d6b92ffaSHans Petter Selasky 1013d6b92ffaSHans Petter Selasky ret = mlx5_calc_sq_size(ctx, attr, qp); 1014d6b92ffaSHans Petter Selasky if (ret < 0) 1015d6b92ffaSHans Petter Selasky return ret; 1016d6b92ffaSHans Petter Selasky 1017d6b92ffaSHans Petter Selasky result = ret; 1018d6b92ffaSHans Petter Selasky ret = mlx5_calc_rq_size(ctx, attr, qp); 1019d6b92ffaSHans Petter Selasky if (ret < 0) 1020d6b92ffaSHans Petter Selasky return ret; 1021d6b92ffaSHans Petter Selasky 1022d6b92ffaSHans Petter Selasky result += ret; 1023d6b92ffaSHans Petter Selasky 1024d6b92ffaSHans Petter Selasky qp->sq.offset = ret; 1025d6b92ffaSHans Petter Selasky qp->rq.offset = 0; 1026d6b92ffaSHans Petter Selasky 1027d6b92ffaSHans Petter Selasky return result; 1028d6b92ffaSHans Petter Selasky } 1029d6b92ffaSHans Petter Selasky 1030d6b92ffaSHans Petter Selasky static void map_uuar(struct ibv_context *context, struct mlx5_qp *qp, 1031d6b92ffaSHans Petter Selasky int uuar_index) 1032d6b92ffaSHans Petter Selasky { 1033d6b92ffaSHans Petter Selasky struct mlx5_context *ctx = to_mctx(context); 1034d6b92ffaSHans Petter Selasky 1035d6b92ffaSHans Petter Selasky qp->bf = &ctx->bfs[uuar_index]; 1036d6b92ffaSHans Petter Selasky } 1037d6b92ffaSHans Petter Selasky 1038d6b92ffaSHans Petter Selasky static const char *qptype2key(enum ibv_qp_type type) 1039d6b92ffaSHans Petter Selasky { 1040d6b92ffaSHans Petter Selasky switch (type) { 1041d6b92ffaSHans Petter Selasky case IBV_QPT_RC: return "HUGE_RC"; 1042d6b92ffaSHans Petter Selasky case IBV_QPT_UC: return "HUGE_UC"; 1043d6b92ffaSHans Petter Selasky case IBV_QPT_UD: return "HUGE_UD"; 1044d6b92ffaSHans Petter Selasky case IBV_QPT_RAW_PACKET: return "HUGE_RAW_ETH"; 1045d6b92ffaSHans Petter Selasky default: return "HUGE_NA"; 1046d6b92ffaSHans Petter Selasky } 1047d6b92ffaSHans Petter Selasky } 1048d6b92ffaSHans Petter Selasky 1049d6b92ffaSHans Petter Selasky static int mlx5_alloc_qp_buf(struct ibv_context *context, 1050d6b92ffaSHans Petter Selasky struct ibv_qp_init_attr_ex *attr, 1051d6b92ffaSHans Petter Selasky struct mlx5_qp *qp, 1052d6b92ffaSHans Petter Selasky int size) 1053d6b92ffaSHans Petter Selasky { 1054d6b92ffaSHans Petter Selasky int err; 1055d6b92ffaSHans Petter Selasky enum mlx5_alloc_type alloc_type; 1056d6b92ffaSHans Petter Selasky enum mlx5_alloc_type default_alloc_type = MLX5_ALLOC_TYPE_ANON; 1057d6b92ffaSHans Petter Selasky const char *qp_huge_key; 1058d6b92ffaSHans Petter Selasky 1059d6b92ffaSHans Petter Selasky if (qp->sq.wqe_cnt) { 1060d6b92ffaSHans Petter Selasky qp->sq.wrid = malloc(qp->sq.wqe_cnt * sizeof(*qp->sq.wrid)); 1061d6b92ffaSHans Petter Selasky if (!qp->sq.wrid) { 1062d6b92ffaSHans Petter Selasky errno = ENOMEM; 1063d6b92ffaSHans Petter Selasky err = -1; 1064d6b92ffaSHans Petter Selasky return err; 1065d6b92ffaSHans Petter Selasky } 1066d6b92ffaSHans Petter Selasky 1067d6b92ffaSHans Petter Selasky qp->sq.wr_data = malloc(qp->sq.wqe_cnt * sizeof(*qp->sq.wr_data)); 1068d6b92ffaSHans Petter Selasky if (!qp->sq.wr_data) { 1069d6b92ffaSHans Petter Selasky errno = ENOMEM; 1070d6b92ffaSHans Petter Selasky err = -1; 1071d6b92ffaSHans Petter Selasky goto ex_wrid; 1072d6b92ffaSHans Petter Selasky } 1073d6b92ffaSHans Petter Selasky } 1074d6b92ffaSHans Petter Selasky 1075d6b92ffaSHans Petter Selasky qp->sq.wqe_head = malloc(qp->sq.wqe_cnt * sizeof(*qp->sq.wqe_head)); 1076d6b92ffaSHans Petter Selasky if (!qp->sq.wqe_head) { 1077d6b92ffaSHans Petter Selasky errno = ENOMEM; 1078d6b92ffaSHans Petter Selasky err = -1; 1079d6b92ffaSHans Petter Selasky goto ex_wrid; 1080d6b92ffaSHans Petter Selasky } 1081d6b92ffaSHans Petter Selasky 1082d6b92ffaSHans Petter Selasky if (qp->rq.wqe_cnt) { 1083d6b92ffaSHans Petter Selasky qp->rq.wrid = malloc(qp->rq.wqe_cnt * sizeof(uint64_t)); 1084d6b92ffaSHans Petter Selasky if (!qp->rq.wrid) { 1085d6b92ffaSHans Petter Selasky errno = ENOMEM; 1086d6b92ffaSHans Petter Selasky err = -1; 1087d6b92ffaSHans Petter Selasky goto ex_wrid; 1088d6b92ffaSHans Petter Selasky } 1089d6b92ffaSHans Petter Selasky } 1090d6b92ffaSHans Petter Selasky 1091d6b92ffaSHans Petter Selasky /* compatibility support */ 1092d6b92ffaSHans Petter Selasky qp_huge_key = qptype2key(qp->ibv_qp->qp_type); 1093d6b92ffaSHans Petter Selasky if (mlx5_use_huge(qp_huge_key)) 1094d6b92ffaSHans Petter Selasky default_alloc_type = MLX5_ALLOC_TYPE_HUGE; 1095d6b92ffaSHans Petter Selasky 1096d6b92ffaSHans Petter Selasky mlx5_get_alloc_type(MLX5_QP_PREFIX, &alloc_type, 1097d6b92ffaSHans Petter Selasky default_alloc_type); 1098d6b92ffaSHans Petter Selasky 1099d6b92ffaSHans Petter Selasky err = mlx5_alloc_prefered_buf(to_mctx(context), &qp->buf, 1100d6b92ffaSHans Petter Selasky align(qp->buf_size, to_mdev 1101d6b92ffaSHans Petter Selasky (context->device)->page_size), 1102d6b92ffaSHans Petter Selasky to_mdev(context->device)->page_size, 1103d6b92ffaSHans Petter Selasky alloc_type, 1104d6b92ffaSHans Petter Selasky MLX5_QP_PREFIX); 1105d6b92ffaSHans Petter Selasky 1106d6b92ffaSHans Petter Selasky if (err) { 1107d6b92ffaSHans Petter Selasky err = -ENOMEM; 1108d6b92ffaSHans Petter Selasky goto ex_wrid; 1109d6b92ffaSHans Petter Selasky } 1110d6b92ffaSHans Petter Selasky 1111d6b92ffaSHans Petter Selasky memset(qp->buf.buf, 0, qp->buf_size); 1112d6b92ffaSHans Petter Selasky 1113d6b92ffaSHans Petter Selasky if (attr->qp_type == IBV_QPT_RAW_PACKET) { 1114d6b92ffaSHans Petter Selasky size_t aligned_sq_buf_size = align(qp->sq_buf_size, 1115d6b92ffaSHans Petter Selasky to_mdev(context->device)->page_size); 1116d6b92ffaSHans Petter Selasky /* For Raw Packet QP, allocate a separate buffer for the SQ */ 1117d6b92ffaSHans Petter Selasky err = mlx5_alloc_prefered_buf(to_mctx(context), &qp->sq_buf, 1118d6b92ffaSHans Petter Selasky aligned_sq_buf_size, 1119d6b92ffaSHans Petter Selasky to_mdev(context->device)->page_size, 1120d6b92ffaSHans Petter Selasky alloc_type, 1121d6b92ffaSHans Petter Selasky MLX5_QP_PREFIX); 1122d6b92ffaSHans Petter Selasky if (err) { 1123d6b92ffaSHans Petter Selasky err = -ENOMEM; 1124d6b92ffaSHans Petter Selasky goto rq_buf; 1125d6b92ffaSHans Petter Selasky } 1126d6b92ffaSHans Petter Selasky 1127d6b92ffaSHans Petter Selasky memset(qp->sq_buf.buf, 0, aligned_sq_buf_size); 1128d6b92ffaSHans Petter Selasky } 1129d6b92ffaSHans Petter Selasky 1130d6b92ffaSHans Petter Selasky return 0; 1131d6b92ffaSHans Petter Selasky rq_buf: 1132d6b92ffaSHans Petter Selasky mlx5_free_actual_buf(to_mctx(qp->verbs_qp.qp.context), &qp->buf); 1133d6b92ffaSHans Petter Selasky ex_wrid: 1134d6b92ffaSHans Petter Selasky if (qp->rq.wrid) 1135d6b92ffaSHans Petter Selasky free(qp->rq.wrid); 1136d6b92ffaSHans Petter Selasky 1137d6b92ffaSHans Petter Selasky if (qp->sq.wqe_head) 1138d6b92ffaSHans Petter Selasky free(qp->sq.wqe_head); 1139d6b92ffaSHans Petter Selasky 1140d6b92ffaSHans Petter Selasky if (qp->sq.wr_data) 1141d6b92ffaSHans Petter Selasky free(qp->sq.wr_data); 1142d6b92ffaSHans Petter Selasky if (qp->sq.wrid) 1143d6b92ffaSHans Petter Selasky free(qp->sq.wrid); 1144d6b92ffaSHans Petter Selasky 1145d6b92ffaSHans Petter Selasky return err; 1146d6b92ffaSHans Petter Selasky } 1147d6b92ffaSHans Petter Selasky 1148d6b92ffaSHans Petter Selasky static void mlx5_free_qp_buf(struct mlx5_qp *qp) 1149d6b92ffaSHans Petter Selasky { 1150d6b92ffaSHans Petter Selasky struct mlx5_context *ctx = to_mctx(qp->ibv_qp->context); 1151d6b92ffaSHans Petter Selasky 1152d6b92ffaSHans Petter Selasky mlx5_free_actual_buf(ctx, &qp->buf); 1153d6b92ffaSHans Petter Selasky 1154d6b92ffaSHans Petter Selasky if (qp->sq_buf.buf) 1155d6b92ffaSHans Petter Selasky mlx5_free_actual_buf(ctx, &qp->sq_buf); 1156d6b92ffaSHans Petter Selasky 1157d6b92ffaSHans Petter Selasky if (qp->rq.wrid) 1158d6b92ffaSHans Petter Selasky free(qp->rq.wrid); 1159d6b92ffaSHans Petter Selasky 1160d6b92ffaSHans Petter Selasky if (qp->sq.wqe_head) 1161d6b92ffaSHans Petter Selasky free(qp->sq.wqe_head); 1162d6b92ffaSHans Petter Selasky 1163d6b92ffaSHans Petter Selasky if (qp->sq.wrid) 1164d6b92ffaSHans Petter Selasky free(qp->sq.wrid); 1165d6b92ffaSHans Petter Selasky 1166d6b92ffaSHans Petter Selasky if (qp->sq.wr_data) 1167d6b92ffaSHans Petter Selasky free(qp->sq.wr_data); 1168d6b92ffaSHans Petter Selasky } 1169d6b92ffaSHans Petter Selasky 1170d6b92ffaSHans Petter Selasky static int mlx5_cmd_create_rss_qp(struct ibv_context *context, 1171d6b92ffaSHans Petter Selasky struct ibv_qp_init_attr_ex *attr, 1172d6b92ffaSHans Petter Selasky struct mlx5_qp *qp) 1173d6b92ffaSHans Petter Selasky { 1174d6b92ffaSHans Petter Selasky struct mlx5_create_qp_ex_rss cmd_ex_rss = {}; 1175d6b92ffaSHans Petter Selasky struct mlx5_create_qp_resp_ex resp = {}; 1176d6b92ffaSHans Petter Selasky int ret; 1177d6b92ffaSHans Petter Selasky 1178d6b92ffaSHans Petter Selasky if (attr->rx_hash_conf.rx_hash_key_len > sizeof(cmd_ex_rss.rx_hash_key)) { 1179d6b92ffaSHans Petter Selasky errno = EINVAL; 1180d6b92ffaSHans Petter Selasky return errno; 1181d6b92ffaSHans Petter Selasky } 1182d6b92ffaSHans Petter Selasky 1183d6b92ffaSHans Petter Selasky cmd_ex_rss.rx_hash_fields_mask = attr->rx_hash_conf.rx_hash_fields_mask; 1184d6b92ffaSHans Petter Selasky cmd_ex_rss.rx_hash_function = attr->rx_hash_conf.rx_hash_function; 1185d6b92ffaSHans Petter Selasky cmd_ex_rss.rx_key_len = attr->rx_hash_conf.rx_hash_key_len; 1186d6b92ffaSHans Petter Selasky memcpy(cmd_ex_rss.rx_hash_key, attr->rx_hash_conf.rx_hash_key, 1187d6b92ffaSHans Petter Selasky attr->rx_hash_conf.rx_hash_key_len); 1188d6b92ffaSHans Petter Selasky 1189d6b92ffaSHans Petter Selasky ret = ibv_cmd_create_qp_ex2(context, &qp->verbs_qp, 1190d6b92ffaSHans Petter Selasky sizeof(qp->verbs_qp), attr, 1191d6b92ffaSHans Petter Selasky &cmd_ex_rss.ibv_cmd, sizeof(cmd_ex_rss.ibv_cmd), 1192d6b92ffaSHans Petter Selasky sizeof(cmd_ex_rss), &resp.ibv_resp, 1193d6b92ffaSHans Petter Selasky sizeof(resp.ibv_resp), sizeof(resp)); 1194d6b92ffaSHans Petter Selasky if (ret) 1195d6b92ffaSHans Petter Selasky return ret; 1196d6b92ffaSHans Petter Selasky 1197d6b92ffaSHans Petter Selasky qp->rss_qp = 1; 1198d6b92ffaSHans Petter Selasky return 0; 1199d6b92ffaSHans Petter Selasky } 1200d6b92ffaSHans Petter Selasky 1201d6b92ffaSHans Petter Selasky static int mlx5_cmd_create_qp_ex(struct ibv_context *context, 1202d6b92ffaSHans Petter Selasky struct ibv_qp_init_attr_ex *attr, 1203d6b92ffaSHans Petter Selasky struct mlx5_create_qp *cmd, 1204d6b92ffaSHans Petter Selasky struct mlx5_qp *qp, 1205d6b92ffaSHans Petter Selasky struct mlx5_create_qp_resp_ex *resp) 1206d6b92ffaSHans Petter Selasky { 1207d6b92ffaSHans Petter Selasky struct mlx5_create_qp_ex cmd_ex; 1208d6b92ffaSHans Petter Selasky int ret; 1209d6b92ffaSHans Petter Selasky 1210d6b92ffaSHans Petter Selasky memset(&cmd_ex, 0, sizeof(cmd_ex)); 1211d6b92ffaSHans Petter Selasky memcpy(&cmd_ex.ibv_cmd.base, &cmd->ibv_cmd.user_handle, 1212d6b92ffaSHans Petter Selasky offsetof(typeof(cmd->ibv_cmd), is_srq) + 1213d6b92ffaSHans Petter Selasky sizeof(cmd->ibv_cmd.is_srq) - 1214d6b92ffaSHans Petter Selasky offsetof(typeof(cmd->ibv_cmd), user_handle)); 1215d6b92ffaSHans Petter Selasky 1216d6b92ffaSHans Petter Selasky memcpy(&cmd_ex.drv_ex, &cmd->buf_addr, 1217d6b92ffaSHans Petter Selasky offsetof(typeof(*cmd), sq_buf_addr) + 1218d6b92ffaSHans Petter Selasky sizeof(cmd->sq_buf_addr) - sizeof(cmd->ibv_cmd)); 1219d6b92ffaSHans Petter Selasky 1220d6b92ffaSHans Petter Selasky ret = ibv_cmd_create_qp_ex2(context, &qp->verbs_qp, 1221d6b92ffaSHans Petter Selasky sizeof(qp->verbs_qp), attr, 1222d6b92ffaSHans Petter Selasky &cmd_ex.ibv_cmd, sizeof(cmd_ex.ibv_cmd), 1223d6b92ffaSHans Petter Selasky sizeof(cmd_ex), &resp->ibv_resp, 1224d6b92ffaSHans Petter Selasky sizeof(resp->ibv_resp), sizeof(*resp)); 1225d6b92ffaSHans Petter Selasky 1226d6b92ffaSHans Petter Selasky return ret; 1227d6b92ffaSHans Petter Selasky } 1228d6b92ffaSHans Petter Selasky 1229d6b92ffaSHans Petter Selasky enum { 1230d6b92ffaSHans Petter Selasky MLX5_CREATE_QP_SUP_COMP_MASK = (IBV_QP_INIT_ATTR_PD | 1231d6b92ffaSHans Petter Selasky IBV_QP_INIT_ATTR_XRCD | 1232d6b92ffaSHans Petter Selasky IBV_QP_INIT_ATTR_CREATE_FLAGS | 1233d6b92ffaSHans Petter Selasky IBV_QP_INIT_ATTR_MAX_TSO_HEADER | 1234d6b92ffaSHans Petter Selasky IBV_QP_INIT_ATTR_IND_TABLE | 1235d6b92ffaSHans Petter Selasky IBV_QP_INIT_ATTR_RX_HASH), 1236d6b92ffaSHans Petter Selasky }; 1237d6b92ffaSHans Petter Selasky 1238d6b92ffaSHans Petter Selasky enum { 1239d6b92ffaSHans Petter Selasky MLX5_CREATE_QP_EX2_COMP_MASK = (IBV_QP_INIT_ATTR_CREATE_FLAGS | 1240d6b92ffaSHans Petter Selasky IBV_QP_INIT_ATTR_MAX_TSO_HEADER | 1241d6b92ffaSHans Petter Selasky IBV_QP_INIT_ATTR_IND_TABLE | 1242d6b92ffaSHans Petter Selasky IBV_QP_INIT_ATTR_RX_HASH), 1243d6b92ffaSHans Petter Selasky }; 1244d6b92ffaSHans Petter Selasky 1245d6b92ffaSHans Petter Selasky static struct ibv_qp *create_qp(struct ibv_context *context, 1246d6b92ffaSHans Petter Selasky struct ibv_qp_init_attr_ex *attr) 1247d6b92ffaSHans Petter Selasky { 1248d6b92ffaSHans Petter Selasky struct mlx5_create_qp cmd; 1249d6b92ffaSHans Petter Selasky struct mlx5_create_qp_resp resp; 1250d6b92ffaSHans Petter Selasky struct mlx5_create_qp_resp_ex resp_ex; 1251d6b92ffaSHans Petter Selasky struct mlx5_qp *qp; 1252d6b92ffaSHans Petter Selasky int ret; 1253d6b92ffaSHans Petter Selasky struct mlx5_context *ctx = to_mctx(context); 1254d6b92ffaSHans Petter Selasky struct ibv_qp *ibqp; 1255d6b92ffaSHans Petter Selasky int32_t usr_idx = 0; 1256d6b92ffaSHans Petter Selasky uint32_t uuar_index; 1257d6b92ffaSHans Petter Selasky FILE *fp = ctx->dbg_fp; 1258d6b92ffaSHans Petter Selasky 1259d6b92ffaSHans Petter Selasky if (attr->comp_mask & ~MLX5_CREATE_QP_SUP_COMP_MASK) 1260d6b92ffaSHans Petter Selasky return NULL; 1261d6b92ffaSHans Petter Selasky 1262d6b92ffaSHans Petter Selasky if ((attr->comp_mask & IBV_QP_INIT_ATTR_MAX_TSO_HEADER) && 1263d6b92ffaSHans Petter Selasky (attr->qp_type != IBV_QPT_RAW_PACKET)) 1264d6b92ffaSHans Petter Selasky return NULL; 1265d6b92ffaSHans Petter Selasky 1266d6b92ffaSHans Petter Selasky qp = calloc(1, sizeof(*qp)); 1267d6b92ffaSHans Petter Selasky if (!qp) { 1268d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_QP, "\n"); 1269d6b92ffaSHans Petter Selasky return NULL; 1270d6b92ffaSHans Petter Selasky } 1271d6b92ffaSHans Petter Selasky ibqp = (struct ibv_qp *)&qp->verbs_qp; 1272d6b92ffaSHans Petter Selasky qp->ibv_qp = ibqp; 1273d6b92ffaSHans Petter Selasky 1274d6b92ffaSHans Petter Selasky memset(&cmd, 0, sizeof(cmd)); 1275d6b92ffaSHans Petter Selasky memset(&resp, 0, sizeof(resp)); 1276d6b92ffaSHans Petter Selasky memset(&resp_ex, 0, sizeof(resp_ex)); 1277d6b92ffaSHans Petter Selasky 1278d6b92ffaSHans Petter Selasky if (attr->comp_mask & IBV_QP_INIT_ATTR_RX_HASH) { 1279d6b92ffaSHans Petter Selasky ret = mlx5_cmd_create_rss_qp(context, attr, qp); 1280d6b92ffaSHans Petter Selasky if (ret) 1281d6b92ffaSHans Petter Selasky goto err; 1282d6b92ffaSHans Petter Selasky 1283d6b92ffaSHans Petter Selasky return ibqp; 1284d6b92ffaSHans Petter Selasky } 1285d6b92ffaSHans Petter Selasky 1286d6b92ffaSHans Petter Selasky qp->wq_sig = qp_sig_enabled(); 1287d6b92ffaSHans Petter Selasky if (qp->wq_sig) 1288d6b92ffaSHans Petter Selasky cmd.flags |= MLX5_QP_FLAG_SIGNATURE; 1289d6b92ffaSHans Petter Selasky 1290d6b92ffaSHans Petter Selasky if (use_scatter_to_cqe()) 1291d6b92ffaSHans Petter Selasky cmd.flags |= MLX5_QP_FLAG_SCATTER_CQE; 1292d6b92ffaSHans Petter Selasky 1293d6b92ffaSHans Petter Selasky ret = mlx5_calc_wq_size(ctx, attr, qp); 1294d6b92ffaSHans Petter Selasky if (ret < 0) { 1295d6b92ffaSHans Petter Selasky errno = -ret; 1296d6b92ffaSHans Petter Selasky goto err; 1297d6b92ffaSHans Petter Selasky } 1298d6b92ffaSHans Petter Selasky 1299d6b92ffaSHans Petter Selasky if (attr->qp_type == IBV_QPT_RAW_PACKET) { 1300d6b92ffaSHans Petter Selasky qp->buf_size = qp->sq.offset; 1301d6b92ffaSHans Petter Selasky qp->sq_buf_size = ret - qp->buf_size; 1302d6b92ffaSHans Petter Selasky qp->sq.offset = 0; 1303d6b92ffaSHans Petter Selasky } else { 1304d6b92ffaSHans Petter Selasky qp->buf_size = ret; 1305d6b92ffaSHans Petter Selasky qp->sq_buf_size = 0; 1306d6b92ffaSHans Petter Selasky } 1307d6b92ffaSHans Petter Selasky 1308d6b92ffaSHans Petter Selasky if (mlx5_alloc_qp_buf(context, attr, qp, ret)) { 1309d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_QP, "\n"); 1310d6b92ffaSHans Petter Selasky goto err; 1311d6b92ffaSHans Petter Selasky } 1312d6b92ffaSHans Petter Selasky 1313d6b92ffaSHans Petter Selasky if (attr->qp_type == IBV_QPT_RAW_PACKET) { 1314d6b92ffaSHans Petter Selasky qp->sq_start = qp->sq_buf.buf; 1315d6b92ffaSHans Petter Selasky qp->sq.qend = qp->sq_buf.buf + 1316d6b92ffaSHans Petter Selasky (qp->sq.wqe_cnt << qp->sq.wqe_shift); 1317d6b92ffaSHans Petter Selasky } else { 1318d6b92ffaSHans Petter Selasky qp->sq_start = qp->buf.buf + qp->sq.offset; 1319d6b92ffaSHans Petter Selasky qp->sq.qend = qp->buf.buf + qp->sq.offset + 1320d6b92ffaSHans Petter Selasky (qp->sq.wqe_cnt << qp->sq.wqe_shift); 1321d6b92ffaSHans Petter Selasky } 1322d6b92ffaSHans Petter Selasky 1323d6b92ffaSHans Petter Selasky mlx5_init_qp_indices(qp); 1324d6b92ffaSHans Petter Selasky 1325a687910fSSean Lim if (mlx5_spinlock_init(&qp->sq.lock)) 1326d6b92ffaSHans Petter Selasky goto err_free_qp_buf; 1327d6b92ffaSHans Petter Selasky 1328a687910fSSean Lim if (mlx5_spinlock_init(&qp->rq.lock)) 1329a687910fSSean Lim goto err_sq_spl; 1330a687910fSSean Lim 1331d6b92ffaSHans Petter Selasky qp->db = mlx5_alloc_dbrec(ctx); 1332d6b92ffaSHans Petter Selasky if (!qp->db) { 1333d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_QP, "\n"); 1334a687910fSSean Lim goto err_rq_spl; 1335d6b92ffaSHans Petter Selasky } 1336d6b92ffaSHans Petter Selasky 1337d6b92ffaSHans Petter Selasky qp->db[MLX5_RCV_DBR] = 0; 1338d6b92ffaSHans Petter Selasky qp->db[MLX5_SND_DBR] = 0; 1339d6b92ffaSHans Petter Selasky 1340d6b92ffaSHans Petter Selasky cmd.buf_addr = (uintptr_t) qp->buf.buf; 1341d6b92ffaSHans Petter Selasky cmd.sq_buf_addr = (attr->qp_type == IBV_QPT_RAW_PACKET) ? 1342d6b92ffaSHans Petter Selasky (uintptr_t) qp->sq_buf.buf : 0; 1343d6b92ffaSHans Petter Selasky cmd.db_addr = (uintptr_t) qp->db; 1344d6b92ffaSHans Petter Selasky cmd.sq_wqe_count = qp->sq.wqe_cnt; 1345d6b92ffaSHans Petter Selasky cmd.rq_wqe_count = qp->rq.wqe_cnt; 1346d6b92ffaSHans Petter Selasky cmd.rq_wqe_shift = qp->rq.wqe_shift; 1347d6b92ffaSHans Petter Selasky 1348d6b92ffaSHans Petter Selasky if (ctx->atomic_cap == IBV_ATOMIC_HCA) 1349d6b92ffaSHans Petter Selasky qp->atomics_enabled = 1; 1350d6b92ffaSHans Petter Selasky 1351d6b92ffaSHans Petter Selasky if (!ctx->cqe_version) { 1352d6b92ffaSHans Petter Selasky cmd.uidx = 0xffffff; 1353d6b92ffaSHans Petter Selasky pthread_mutex_lock(&ctx->qp_table_mutex); 1354d6b92ffaSHans Petter Selasky } else if (!is_xrc_tgt(attr->qp_type)) { 1355d6b92ffaSHans Petter Selasky usr_idx = mlx5_store_uidx(ctx, qp); 1356d6b92ffaSHans Petter Selasky if (usr_idx < 0) { 1357d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_QP, "Couldn't find free user index\n"); 1358d6b92ffaSHans Petter Selasky goto err_rq_db; 1359d6b92ffaSHans Petter Selasky } 1360d6b92ffaSHans Petter Selasky 1361d6b92ffaSHans Petter Selasky cmd.uidx = usr_idx; 1362d6b92ffaSHans Petter Selasky } 1363d6b92ffaSHans Petter Selasky 1364d6b92ffaSHans Petter Selasky if (attr->comp_mask & MLX5_CREATE_QP_EX2_COMP_MASK) 1365d6b92ffaSHans Petter Selasky ret = mlx5_cmd_create_qp_ex(context, attr, &cmd, qp, &resp_ex); 1366d6b92ffaSHans Petter Selasky else 1367d6b92ffaSHans Petter Selasky ret = ibv_cmd_create_qp_ex(context, &qp->verbs_qp, sizeof(qp->verbs_qp), 1368d6b92ffaSHans Petter Selasky attr, &cmd.ibv_cmd, sizeof(cmd), 1369d6b92ffaSHans Petter Selasky &resp.ibv_resp, sizeof(resp)); 1370d6b92ffaSHans Petter Selasky if (ret) { 1371d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_QP, "ret %d\n", ret); 1372d6b92ffaSHans Petter Selasky goto err_free_uidx; 1373d6b92ffaSHans Petter Selasky } 1374d6b92ffaSHans Petter Selasky 1375d6b92ffaSHans Petter Selasky uuar_index = (attr->comp_mask & MLX5_CREATE_QP_EX2_COMP_MASK) ? 1376d6b92ffaSHans Petter Selasky resp_ex.uuar_index : resp.uuar_index; 1377d6b92ffaSHans Petter Selasky if (!ctx->cqe_version) { 1378d6b92ffaSHans Petter Selasky if (qp->sq.wqe_cnt || qp->rq.wqe_cnt) { 1379d6b92ffaSHans Petter Selasky ret = mlx5_store_qp(ctx, ibqp->qp_num, qp); 1380d6b92ffaSHans Petter Selasky if (ret) { 1381d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_QP, "ret %d\n", ret); 1382d6b92ffaSHans Petter Selasky goto err_destroy; 1383d6b92ffaSHans Petter Selasky } 1384d6b92ffaSHans Petter Selasky } 1385d6b92ffaSHans Petter Selasky 1386d6b92ffaSHans Petter Selasky pthread_mutex_unlock(&ctx->qp_table_mutex); 1387d6b92ffaSHans Petter Selasky } 1388d6b92ffaSHans Petter Selasky 1389d6b92ffaSHans Petter Selasky map_uuar(context, qp, uuar_index); 1390d6b92ffaSHans Petter Selasky 1391d6b92ffaSHans Petter Selasky qp->rq.max_post = qp->rq.wqe_cnt; 1392d6b92ffaSHans Petter Selasky if (attr->sq_sig_all) 1393d6b92ffaSHans Petter Selasky qp->sq_signal_bits = MLX5_WQE_CTRL_CQ_UPDATE; 1394d6b92ffaSHans Petter Selasky else 1395d6b92ffaSHans Petter Selasky qp->sq_signal_bits = 0; 1396d6b92ffaSHans Petter Selasky 1397d6b92ffaSHans Petter Selasky attr->cap.max_send_wr = qp->sq.max_post; 1398d6b92ffaSHans Petter Selasky attr->cap.max_recv_wr = qp->rq.max_post; 1399d6b92ffaSHans Petter Selasky attr->cap.max_recv_sge = qp->rq.max_gs; 1400d6b92ffaSHans Petter Selasky 1401d6b92ffaSHans Petter Selasky qp->rsc.type = MLX5_RSC_TYPE_QP; 1402d6b92ffaSHans Petter Selasky qp->rsc.rsn = (ctx->cqe_version && !is_xrc_tgt(attr->qp_type)) ? 1403d6b92ffaSHans Petter Selasky usr_idx : ibqp->qp_num; 1404d6b92ffaSHans Petter Selasky 1405d6b92ffaSHans Petter Selasky return ibqp; 1406d6b92ffaSHans Petter Selasky 1407d6b92ffaSHans Petter Selasky err_destroy: 1408d6b92ffaSHans Petter Selasky ibv_cmd_destroy_qp(ibqp); 1409d6b92ffaSHans Petter Selasky 1410d6b92ffaSHans Petter Selasky err_free_uidx: 1411d6b92ffaSHans Petter Selasky if (!ctx->cqe_version) 1412d6b92ffaSHans Petter Selasky pthread_mutex_unlock(&to_mctx(context)->qp_table_mutex); 1413d6b92ffaSHans Petter Selasky else if (!is_xrc_tgt(attr->qp_type)) 1414d6b92ffaSHans Petter Selasky mlx5_clear_uidx(ctx, usr_idx); 1415d6b92ffaSHans Petter Selasky 1416d6b92ffaSHans Petter Selasky err_rq_db: 1417d6b92ffaSHans Petter Selasky mlx5_free_db(to_mctx(context), qp->db); 1418d6b92ffaSHans Petter Selasky 1419a687910fSSean Lim err_rq_spl: 1420a687910fSSean Lim mlx5_spinlock_destroy(&qp->rq.lock); 1421a687910fSSean Lim 1422a687910fSSean Lim err_sq_spl: 1423a687910fSSean Lim mlx5_spinlock_destroy(&qp->sq.lock); 1424a687910fSSean Lim 1425d6b92ffaSHans Petter Selasky err_free_qp_buf: 1426d6b92ffaSHans Petter Selasky mlx5_free_qp_buf(qp); 1427d6b92ffaSHans Petter Selasky 1428d6b92ffaSHans Petter Selasky err: 1429d6b92ffaSHans Petter Selasky free(qp); 1430d6b92ffaSHans Petter Selasky 1431d6b92ffaSHans Petter Selasky return NULL; 1432d6b92ffaSHans Petter Selasky } 1433d6b92ffaSHans Petter Selasky 1434d6b92ffaSHans Petter Selasky struct ibv_qp *mlx5_create_qp(struct ibv_pd *pd, 1435d6b92ffaSHans Petter Selasky struct ibv_qp_init_attr *attr) 1436d6b92ffaSHans Petter Selasky { 1437d6b92ffaSHans Petter Selasky struct ibv_qp *qp; 1438d6b92ffaSHans Petter Selasky struct ibv_qp_init_attr_ex attrx; 1439d6b92ffaSHans Petter Selasky 1440d6b92ffaSHans Petter Selasky memset(&attrx, 0, sizeof(attrx)); 1441d6b92ffaSHans Petter Selasky memcpy(&attrx, attr, sizeof(*attr)); 1442d6b92ffaSHans Petter Selasky attrx.comp_mask = IBV_QP_INIT_ATTR_PD; 1443d6b92ffaSHans Petter Selasky attrx.pd = pd; 1444d6b92ffaSHans Petter Selasky qp = create_qp(pd->context, &attrx); 1445d6b92ffaSHans Petter Selasky if (qp) 1446d6b92ffaSHans Petter Selasky memcpy(attr, &attrx, sizeof(*attr)); 1447d6b92ffaSHans Petter Selasky 1448d6b92ffaSHans Petter Selasky return qp; 1449d6b92ffaSHans Petter Selasky } 1450d6b92ffaSHans Petter Selasky 1451d6b92ffaSHans Petter Selasky static void mlx5_lock_cqs(struct ibv_qp *qp) 1452d6b92ffaSHans Petter Selasky { 1453d6b92ffaSHans Petter Selasky struct mlx5_cq *send_cq = to_mcq(qp->send_cq); 1454d6b92ffaSHans Petter Selasky struct mlx5_cq *recv_cq = to_mcq(qp->recv_cq); 1455d6b92ffaSHans Petter Selasky 1456d6b92ffaSHans Petter Selasky if (send_cq && recv_cq) { 1457d6b92ffaSHans Petter Selasky if (send_cq == recv_cq) { 1458d6b92ffaSHans Petter Selasky mlx5_spin_lock(&send_cq->lock); 1459d6b92ffaSHans Petter Selasky } else if (send_cq->cqn < recv_cq->cqn) { 1460d6b92ffaSHans Petter Selasky mlx5_spin_lock(&send_cq->lock); 1461d6b92ffaSHans Petter Selasky mlx5_spin_lock(&recv_cq->lock); 1462d6b92ffaSHans Petter Selasky } else { 1463d6b92ffaSHans Petter Selasky mlx5_spin_lock(&recv_cq->lock); 1464d6b92ffaSHans Petter Selasky mlx5_spin_lock(&send_cq->lock); 1465d6b92ffaSHans Petter Selasky } 1466d6b92ffaSHans Petter Selasky } else if (send_cq) { 1467d6b92ffaSHans Petter Selasky mlx5_spin_lock(&send_cq->lock); 1468d6b92ffaSHans Petter Selasky } else if (recv_cq) { 1469d6b92ffaSHans Petter Selasky mlx5_spin_lock(&recv_cq->lock); 1470d6b92ffaSHans Petter Selasky } 1471d6b92ffaSHans Petter Selasky } 1472d6b92ffaSHans Petter Selasky 1473d6b92ffaSHans Petter Selasky static void mlx5_unlock_cqs(struct ibv_qp *qp) 1474d6b92ffaSHans Petter Selasky { 1475d6b92ffaSHans Petter Selasky struct mlx5_cq *send_cq = to_mcq(qp->send_cq); 1476d6b92ffaSHans Petter Selasky struct mlx5_cq *recv_cq = to_mcq(qp->recv_cq); 1477d6b92ffaSHans Petter Selasky 1478d6b92ffaSHans Petter Selasky if (send_cq && recv_cq) { 1479d6b92ffaSHans Petter Selasky if (send_cq == recv_cq) { 1480d6b92ffaSHans Petter Selasky mlx5_spin_unlock(&send_cq->lock); 1481d6b92ffaSHans Petter Selasky } else if (send_cq->cqn < recv_cq->cqn) { 1482d6b92ffaSHans Petter Selasky mlx5_spin_unlock(&recv_cq->lock); 1483d6b92ffaSHans Petter Selasky mlx5_spin_unlock(&send_cq->lock); 1484d6b92ffaSHans Petter Selasky } else { 1485d6b92ffaSHans Petter Selasky mlx5_spin_unlock(&send_cq->lock); 1486d6b92ffaSHans Petter Selasky mlx5_spin_unlock(&recv_cq->lock); 1487d6b92ffaSHans Petter Selasky } 1488d6b92ffaSHans Petter Selasky } else if (send_cq) { 1489d6b92ffaSHans Petter Selasky mlx5_spin_unlock(&send_cq->lock); 1490d6b92ffaSHans Petter Selasky } else if (recv_cq) { 1491d6b92ffaSHans Petter Selasky mlx5_spin_unlock(&recv_cq->lock); 1492d6b92ffaSHans Petter Selasky } 1493d6b92ffaSHans Petter Selasky } 1494d6b92ffaSHans Petter Selasky 1495d6b92ffaSHans Petter Selasky int mlx5_destroy_qp(struct ibv_qp *ibqp) 1496d6b92ffaSHans Petter Selasky { 1497d6b92ffaSHans Petter Selasky struct mlx5_qp *qp = to_mqp(ibqp); 1498d6b92ffaSHans Petter Selasky struct mlx5_context *ctx = to_mctx(ibqp->context); 1499d6b92ffaSHans Petter Selasky int ret; 1500d6b92ffaSHans Petter Selasky 1501d6b92ffaSHans Petter Selasky if (qp->rss_qp) { 1502d6b92ffaSHans Petter Selasky ret = ibv_cmd_destroy_qp(ibqp); 1503d6b92ffaSHans Petter Selasky if (ret) 1504d6b92ffaSHans Petter Selasky return ret; 1505d6b92ffaSHans Petter Selasky goto free; 1506d6b92ffaSHans Petter Selasky } 1507d6b92ffaSHans Petter Selasky 1508d6b92ffaSHans Petter Selasky if (!ctx->cqe_version) 1509d6b92ffaSHans Petter Selasky pthread_mutex_lock(&ctx->qp_table_mutex); 1510d6b92ffaSHans Petter Selasky 1511d6b92ffaSHans Petter Selasky ret = ibv_cmd_destroy_qp(ibqp); 1512d6b92ffaSHans Petter Selasky if (ret) { 1513d6b92ffaSHans Petter Selasky if (!ctx->cqe_version) 1514d6b92ffaSHans Petter Selasky pthread_mutex_unlock(&ctx->qp_table_mutex); 1515d6b92ffaSHans Petter Selasky return ret; 1516d6b92ffaSHans Petter Selasky } 1517d6b92ffaSHans Petter Selasky 1518d6b92ffaSHans Petter Selasky mlx5_lock_cqs(ibqp); 1519d6b92ffaSHans Petter Selasky 1520d6b92ffaSHans Petter Selasky __mlx5_cq_clean(to_mcq(ibqp->recv_cq), qp->rsc.rsn, 1521d6b92ffaSHans Petter Selasky ibqp->srq ? to_msrq(ibqp->srq) : NULL); 1522d6b92ffaSHans Petter Selasky if (ibqp->send_cq != ibqp->recv_cq) 1523d6b92ffaSHans Petter Selasky __mlx5_cq_clean(to_mcq(ibqp->send_cq), qp->rsc.rsn, NULL); 1524d6b92ffaSHans Petter Selasky 1525d6b92ffaSHans Petter Selasky if (!ctx->cqe_version) { 1526d6b92ffaSHans Petter Selasky if (qp->sq.wqe_cnt || qp->rq.wqe_cnt) 1527d6b92ffaSHans Petter Selasky mlx5_clear_qp(ctx, ibqp->qp_num); 1528d6b92ffaSHans Petter Selasky } 1529d6b92ffaSHans Petter Selasky 1530d6b92ffaSHans Petter Selasky mlx5_unlock_cqs(ibqp); 1531d6b92ffaSHans Petter Selasky if (!ctx->cqe_version) 1532d6b92ffaSHans Petter Selasky pthread_mutex_unlock(&ctx->qp_table_mutex); 1533d6b92ffaSHans Petter Selasky else if (!is_xrc_tgt(ibqp->qp_type)) 1534d6b92ffaSHans Petter Selasky mlx5_clear_uidx(ctx, qp->rsc.rsn); 1535d6b92ffaSHans Petter Selasky 1536d6b92ffaSHans Petter Selasky mlx5_free_db(ctx, qp->db); 1537a687910fSSean Lim mlx5_spinlock_destroy(&qp->rq.lock); 1538a687910fSSean Lim mlx5_spinlock_destroy(&qp->sq.lock); 1539d6b92ffaSHans Petter Selasky mlx5_free_qp_buf(qp); 1540d6b92ffaSHans Petter Selasky free: 1541d6b92ffaSHans Petter Selasky free(qp); 1542d6b92ffaSHans Petter Selasky 1543d6b92ffaSHans Petter Selasky return 0; 1544d6b92ffaSHans Petter Selasky } 1545d6b92ffaSHans Petter Selasky 1546d6b92ffaSHans Petter Selasky int mlx5_query_qp(struct ibv_qp *ibqp, struct ibv_qp_attr *attr, 1547d6b92ffaSHans Petter Selasky int attr_mask, struct ibv_qp_init_attr *init_attr) 1548d6b92ffaSHans Petter Selasky { 1549d6b92ffaSHans Petter Selasky struct ibv_query_qp cmd; 1550d6b92ffaSHans Petter Selasky struct mlx5_qp *qp = to_mqp(ibqp); 1551d6b92ffaSHans Petter Selasky int ret; 1552d6b92ffaSHans Petter Selasky 1553d6b92ffaSHans Petter Selasky if (qp->rss_qp) 1554d6b92ffaSHans Petter Selasky return ENOSYS; 1555d6b92ffaSHans Petter Selasky 1556d6b92ffaSHans Petter Selasky ret = ibv_cmd_query_qp(ibqp, attr, attr_mask, init_attr, &cmd, sizeof(cmd)); 1557d6b92ffaSHans Petter Selasky if (ret) 1558d6b92ffaSHans Petter Selasky return ret; 1559d6b92ffaSHans Petter Selasky 1560d6b92ffaSHans Petter Selasky init_attr->cap.max_send_wr = qp->sq.max_post; 1561d6b92ffaSHans Petter Selasky init_attr->cap.max_send_sge = qp->sq.max_gs; 1562d6b92ffaSHans Petter Selasky init_attr->cap.max_inline_data = qp->max_inline_data; 1563d6b92ffaSHans Petter Selasky 1564d6b92ffaSHans Petter Selasky attr->cap = init_attr->cap; 1565d6b92ffaSHans Petter Selasky 1566d6b92ffaSHans Petter Selasky return 0; 1567d6b92ffaSHans Petter Selasky } 1568d6b92ffaSHans Petter Selasky 1569d6b92ffaSHans Petter Selasky enum { 1570d6b92ffaSHans Petter Selasky MLX5_MODIFY_QP_EX_ATTR_MASK = IBV_QP_RATE_LIMIT, 1571d6b92ffaSHans Petter Selasky }; 1572d6b92ffaSHans Petter Selasky 1573d6b92ffaSHans Petter Selasky int mlx5_modify_qp(struct ibv_qp *qp, struct ibv_qp_attr *attr, 1574d6b92ffaSHans Petter Selasky int attr_mask) 1575d6b92ffaSHans Petter Selasky { 1576d6b92ffaSHans Petter Selasky struct ibv_modify_qp cmd = {}; 1577d6b92ffaSHans Petter Selasky struct ibv_modify_qp_ex cmd_ex = {}; 1578d6b92ffaSHans Petter Selasky struct ibv_modify_qp_resp_ex resp = {}; 1579d6b92ffaSHans Petter Selasky struct mlx5_qp *mqp = to_mqp(qp); 1580d6b92ffaSHans Petter Selasky struct mlx5_context *context = to_mctx(qp->context); 1581d6b92ffaSHans Petter Selasky int ret; 1582d6b92ffaSHans Petter Selasky uint32_t *db; 1583d6b92ffaSHans Petter Selasky 1584d6b92ffaSHans Petter Selasky if (mqp->rss_qp) 1585d6b92ffaSHans Petter Selasky return ENOSYS; 1586d6b92ffaSHans Petter Selasky 1587d6b92ffaSHans Petter Selasky if (attr_mask & IBV_QP_PORT) { 1588d6b92ffaSHans Petter Selasky switch (qp->qp_type) { 1589d6b92ffaSHans Petter Selasky case IBV_QPT_RAW_PACKET: 1590d6b92ffaSHans Petter Selasky if (context->cached_link_layer[attr->port_num - 1] == 1591d6b92ffaSHans Petter Selasky IBV_LINK_LAYER_ETHERNET) { 1592d6b92ffaSHans Petter Selasky if (context->cached_device_cap_flags & 1593d6b92ffaSHans Petter Selasky IBV_DEVICE_RAW_IP_CSUM) 1594d6b92ffaSHans Petter Selasky mqp->qp_cap_cache |= 1595d6b92ffaSHans Petter Selasky MLX5_CSUM_SUPPORT_RAW_OVER_ETH | 1596d6b92ffaSHans Petter Selasky MLX5_RX_CSUM_VALID; 1597d6b92ffaSHans Petter Selasky 1598d6b92ffaSHans Petter Selasky if (ibv_is_qpt_supported( 1599d6b92ffaSHans Petter Selasky context->cached_tso_caps.supported_qpts, 1600d6b92ffaSHans Petter Selasky IBV_QPT_RAW_PACKET)) 1601d6b92ffaSHans Petter Selasky mqp->max_tso = 1602d6b92ffaSHans Petter Selasky context->cached_tso_caps.max_tso; 1603d6b92ffaSHans Petter Selasky } 1604d6b92ffaSHans Petter Selasky break; 1605d6b92ffaSHans Petter Selasky default: 1606d6b92ffaSHans Petter Selasky break; 1607d6b92ffaSHans Petter Selasky } 1608d6b92ffaSHans Petter Selasky } 1609d6b92ffaSHans Petter Selasky 1610d6b92ffaSHans Petter Selasky if (attr_mask & MLX5_MODIFY_QP_EX_ATTR_MASK) 1611d6b92ffaSHans Petter Selasky ret = ibv_cmd_modify_qp_ex(qp, attr, attr_mask, 1612d6b92ffaSHans Petter Selasky &cmd_ex, 1613d6b92ffaSHans Petter Selasky sizeof(cmd_ex), sizeof(cmd_ex), 1614d6b92ffaSHans Petter Selasky &resp, 1615d6b92ffaSHans Petter Selasky sizeof(resp), sizeof(resp)); 1616d6b92ffaSHans Petter Selasky else 1617d6b92ffaSHans Petter Selasky ret = ibv_cmd_modify_qp(qp, attr, attr_mask, 1618d6b92ffaSHans Petter Selasky &cmd, sizeof(cmd)); 1619d6b92ffaSHans Petter Selasky 1620d6b92ffaSHans Petter Selasky if (!ret && 1621d6b92ffaSHans Petter Selasky (attr_mask & IBV_QP_STATE) && 1622d6b92ffaSHans Petter Selasky attr->qp_state == IBV_QPS_RESET) { 1623d6b92ffaSHans Petter Selasky if (qp->recv_cq) { 1624d6b92ffaSHans Petter Selasky mlx5_cq_clean(to_mcq(qp->recv_cq), mqp->rsc.rsn, 1625d6b92ffaSHans Petter Selasky qp->srq ? to_msrq(qp->srq) : NULL); 1626d6b92ffaSHans Petter Selasky } 1627d6b92ffaSHans Petter Selasky if (qp->send_cq != qp->recv_cq && qp->send_cq) 1628d6b92ffaSHans Petter Selasky mlx5_cq_clean(to_mcq(qp->send_cq), 1629d6b92ffaSHans Petter Selasky to_mqp(qp)->rsc.rsn, NULL); 1630d6b92ffaSHans Petter Selasky 1631d6b92ffaSHans Petter Selasky mlx5_init_qp_indices(mqp); 1632d6b92ffaSHans Petter Selasky db = mqp->db; 1633d6b92ffaSHans Petter Selasky db[MLX5_RCV_DBR] = 0; 1634d6b92ffaSHans Petter Selasky db[MLX5_SND_DBR] = 0; 1635d6b92ffaSHans Petter Selasky } 1636d6b92ffaSHans Petter Selasky 1637d6b92ffaSHans Petter Selasky /* 1638d6b92ffaSHans Petter Selasky * When the Raw Packet QP is in INIT state, its RQ 1639d6b92ffaSHans Petter Selasky * underneath is already in RDY, which means it can 1640d6b92ffaSHans Petter Selasky * receive packets. According to the IB spec, a QP can't 1641d6b92ffaSHans Petter Selasky * receive packets until moved to RTR state. To achieve this, 1642d6b92ffaSHans Petter Selasky * for Raw Packet QPs, we update the doorbell record 1643d6b92ffaSHans Petter Selasky * once the QP is moved to RTR. 1644d6b92ffaSHans Petter Selasky */ 1645d6b92ffaSHans Petter Selasky if (!ret && 1646d6b92ffaSHans Petter Selasky (attr_mask & IBV_QP_STATE) && 1647d6b92ffaSHans Petter Selasky attr->qp_state == IBV_QPS_RTR && 1648d6b92ffaSHans Petter Selasky qp->qp_type == IBV_QPT_RAW_PACKET) { 1649d6b92ffaSHans Petter Selasky mlx5_spin_lock(&mqp->rq.lock); 1650d6b92ffaSHans Petter Selasky mqp->db[MLX5_RCV_DBR] = htobe32(mqp->rq.head & 0xffff); 1651d6b92ffaSHans Petter Selasky mlx5_spin_unlock(&mqp->rq.lock); 1652d6b92ffaSHans Petter Selasky } 1653d6b92ffaSHans Petter Selasky 1654d6b92ffaSHans Petter Selasky return ret; 1655d6b92ffaSHans Petter Selasky } 1656d6b92ffaSHans Petter Selasky 1657d6b92ffaSHans Petter Selasky #define RROCE_UDP_SPORT_MIN 0xC000 1658d6b92ffaSHans Petter Selasky #define RROCE_UDP_SPORT_MAX 0xFFFF 1659d6b92ffaSHans Petter Selasky struct ibv_ah *mlx5_create_ah(struct ibv_pd *pd, struct ibv_ah_attr *attr) 1660d6b92ffaSHans Petter Selasky { 1661d6b92ffaSHans Petter Selasky struct mlx5_context *ctx = to_mctx(pd->context); 1662d6b92ffaSHans Petter Selasky struct ibv_port_attr port_attr; 1663d6b92ffaSHans Petter Selasky struct mlx5_ah *ah; 1664d6b92ffaSHans Petter Selasky uint32_t gid_type; 1665d6b92ffaSHans Petter Selasky uint32_t tmp; 1666d6b92ffaSHans Petter Selasky uint8_t grh; 1667d6b92ffaSHans Petter Selasky int is_eth; 1668d6b92ffaSHans Petter Selasky 1669d6b92ffaSHans Petter Selasky if (attr->port_num < 1 || attr->port_num > ctx->num_ports) 1670d6b92ffaSHans Petter Selasky return NULL; 1671d6b92ffaSHans Petter Selasky 1672d6b92ffaSHans Petter Selasky if (ctx->cached_link_layer[attr->port_num - 1]) { 1673d6b92ffaSHans Petter Selasky is_eth = ctx->cached_link_layer[attr->port_num - 1] == 1674d6b92ffaSHans Petter Selasky IBV_LINK_LAYER_ETHERNET; 1675d6b92ffaSHans Petter Selasky } else { 1676d6b92ffaSHans Petter Selasky if (ibv_query_port(pd->context, attr->port_num, &port_attr)) 1677d6b92ffaSHans Petter Selasky return NULL; 1678d6b92ffaSHans Petter Selasky 1679d6b92ffaSHans Petter Selasky is_eth = (port_attr.link_layer == IBV_LINK_LAYER_ETHERNET); 1680d6b92ffaSHans Petter Selasky } 1681d6b92ffaSHans Petter Selasky 1682d6b92ffaSHans Petter Selasky if (unlikely((!attr->is_global) && is_eth)) { 1683d6b92ffaSHans Petter Selasky errno = EINVAL; 1684d6b92ffaSHans Petter Selasky return NULL; 1685d6b92ffaSHans Petter Selasky } 1686d6b92ffaSHans Petter Selasky 1687d6b92ffaSHans Petter Selasky ah = calloc(1, sizeof *ah); 1688d6b92ffaSHans Petter Selasky if (!ah) 1689d6b92ffaSHans Petter Selasky return NULL; 1690d6b92ffaSHans Petter Selasky 1691d6b92ffaSHans Petter Selasky if (is_eth) { 1692d6b92ffaSHans Petter Selasky if (ibv_query_gid_type(pd->context, attr->port_num, 1693d6b92ffaSHans Petter Selasky attr->grh.sgid_index, &gid_type)) 1694d6b92ffaSHans Petter Selasky goto err; 1695d6b92ffaSHans Petter Selasky 1696d6b92ffaSHans Petter Selasky if (gid_type == IBV_GID_TYPE_ROCE_V2) 1697d6b92ffaSHans Petter Selasky ah->av.rlid = htobe16(rand() % (RROCE_UDP_SPORT_MAX + 1 1698d6b92ffaSHans Petter Selasky - RROCE_UDP_SPORT_MIN) 1699d6b92ffaSHans Petter Selasky + RROCE_UDP_SPORT_MIN); 1700d6b92ffaSHans Petter Selasky /* Since RoCE packets must contain GRH, this bit is reserved 1701d6b92ffaSHans Petter Selasky * for RoCE and shouldn't be set. 1702d6b92ffaSHans Petter Selasky */ 1703d6b92ffaSHans Petter Selasky grh = 0; 1704d6b92ffaSHans Petter Selasky } else { 1705d6b92ffaSHans Petter Selasky ah->av.fl_mlid = attr->src_path_bits & 0x7f; 1706d6b92ffaSHans Petter Selasky ah->av.rlid = htobe16(attr->dlid); 1707d6b92ffaSHans Petter Selasky grh = 1; 1708d6b92ffaSHans Petter Selasky } 1709d6b92ffaSHans Petter Selasky ah->av.stat_rate_sl = (attr->static_rate << 4) | attr->sl; 1710d6b92ffaSHans Petter Selasky if (attr->is_global) { 1711d6b92ffaSHans Petter Selasky ah->av.tclass = attr->grh.traffic_class; 1712d6b92ffaSHans Petter Selasky ah->av.hop_limit = attr->grh.hop_limit; 1713d6b92ffaSHans Petter Selasky tmp = htobe32((grh << 30) | 1714d6b92ffaSHans Petter Selasky ((attr->grh.sgid_index & 0xff) << 20) | 1715d6b92ffaSHans Petter Selasky (attr->grh.flow_label & 0xfffff)); 1716d6b92ffaSHans Petter Selasky ah->av.grh_gid_fl = tmp; 1717d6b92ffaSHans Petter Selasky memcpy(ah->av.rgid, attr->grh.dgid.raw, 16); 1718d6b92ffaSHans Petter Selasky } 1719d6b92ffaSHans Petter Selasky 1720d6b92ffaSHans Petter Selasky if (is_eth) { 1721d6b92ffaSHans Petter Selasky if (ctx->cmds_supp_uhw & MLX5_USER_CMDS_SUPP_UHW_CREATE_AH) { 1722d6b92ffaSHans Petter Selasky struct mlx5_create_ah_resp resp = {}; 1723d6b92ffaSHans Petter Selasky 1724d6b92ffaSHans Petter Selasky if (ibv_cmd_create_ah(pd, &ah->ibv_ah, attr, &resp.ibv_resp, sizeof(resp))) 1725d6b92ffaSHans Petter Selasky goto err; 1726d6b92ffaSHans Petter Selasky 1727d6b92ffaSHans Petter Selasky ah->kern_ah = true; 1728d6b92ffaSHans Petter Selasky memcpy(ah->av.rmac, resp.dmac, ETHERNET_LL_SIZE); 1729d6b92ffaSHans Petter Selasky } else { 1730d6b92ffaSHans Petter Selasky uint16_t vid; 1731d6b92ffaSHans Petter Selasky 1732d6b92ffaSHans Petter Selasky if (ibv_resolve_eth_l2_from_gid(pd->context, attr, 1733d6b92ffaSHans Petter Selasky ah->av.rmac, &vid)) 1734d6b92ffaSHans Petter Selasky goto err; 1735d6b92ffaSHans Petter Selasky } 1736d6b92ffaSHans Petter Selasky } 1737d6b92ffaSHans Petter Selasky 1738d6b92ffaSHans Petter Selasky return &ah->ibv_ah; 1739d6b92ffaSHans Petter Selasky err: 1740d6b92ffaSHans Petter Selasky free(ah); 1741d6b92ffaSHans Petter Selasky return NULL; 1742d6b92ffaSHans Petter Selasky } 1743d6b92ffaSHans Petter Selasky 1744d6b92ffaSHans Petter Selasky int mlx5_destroy_ah(struct ibv_ah *ah) 1745d6b92ffaSHans Petter Selasky { 1746d6b92ffaSHans Petter Selasky struct mlx5_ah *mah = to_mah(ah); 1747d6b92ffaSHans Petter Selasky int err; 1748d6b92ffaSHans Petter Selasky 1749d6b92ffaSHans Petter Selasky if (mah->kern_ah) { 1750d6b92ffaSHans Petter Selasky err = ibv_cmd_destroy_ah(ah); 1751d6b92ffaSHans Petter Selasky if (err) 1752d6b92ffaSHans Petter Selasky return err; 1753d6b92ffaSHans Petter Selasky } 1754d6b92ffaSHans Petter Selasky 1755d6b92ffaSHans Petter Selasky free(mah); 1756d6b92ffaSHans Petter Selasky return 0; 1757d6b92ffaSHans Petter Selasky } 1758d6b92ffaSHans Petter Selasky 1759d6b92ffaSHans Petter Selasky int mlx5_attach_mcast(struct ibv_qp *qp, const union ibv_gid *gid, uint16_t lid) 1760d6b92ffaSHans Petter Selasky { 1761d6b92ffaSHans Petter Selasky return ibv_cmd_attach_mcast(qp, gid, lid); 1762d6b92ffaSHans Petter Selasky } 1763d6b92ffaSHans Petter Selasky 1764d6b92ffaSHans Petter Selasky int mlx5_detach_mcast(struct ibv_qp *qp, const union ibv_gid *gid, uint16_t lid) 1765d6b92ffaSHans Petter Selasky { 1766d6b92ffaSHans Petter Selasky return ibv_cmd_detach_mcast(qp, gid, lid); 1767d6b92ffaSHans Petter Selasky } 1768d6b92ffaSHans Petter Selasky 1769d6b92ffaSHans Petter Selasky struct ibv_qp *mlx5_create_qp_ex(struct ibv_context *context, 1770d6b92ffaSHans Petter Selasky struct ibv_qp_init_attr_ex *attr) 1771d6b92ffaSHans Petter Selasky { 1772d6b92ffaSHans Petter Selasky return create_qp(context, attr); 1773d6b92ffaSHans Petter Selasky } 1774d6b92ffaSHans Petter Selasky 1775d6b92ffaSHans Petter Selasky int mlx5_get_srq_num(struct ibv_srq *srq, uint32_t *srq_num) 1776d6b92ffaSHans Petter Selasky { 1777d6b92ffaSHans Petter Selasky struct mlx5_srq *msrq = to_msrq(srq); 1778d6b92ffaSHans Petter Selasky 1779d6b92ffaSHans Petter Selasky *srq_num = msrq->srqn; 1780d6b92ffaSHans Petter Selasky 1781d6b92ffaSHans Petter Selasky return 0; 1782d6b92ffaSHans Petter Selasky } 1783d6b92ffaSHans Petter Selasky 1784d6b92ffaSHans Petter Selasky struct ibv_xrcd * 1785d6b92ffaSHans Petter Selasky mlx5_open_xrcd(struct ibv_context *context, 1786d6b92ffaSHans Petter Selasky struct ibv_xrcd_init_attr *xrcd_init_attr) 1787d6b92ffaSHans Petter Selasky { 1788d6b92ffaSHans Petter Selasky int err; 1789d6b92ffaSHans Petter Selasky struct verbs_xrcd *xrcd; 1790d6b92ffaSHans Petter Selasky struct ibv_open_xrcd cmd = {}; 1791d6b92ffaSHans Petter Selasky struct ibv_open_xrcd_resp resp = {}; 1792d6b92ffaSHans Petter Selasky 1793d6b92ffaSHans Petter Selasky xrcd = calloc(1, sizeof(*xrcd)); 1794d6b92ffaSHans Petter Selasky if (!xrcd) 1795d6b92ffaSHans Petter Selasky return NULL; 1796d6b92ffaSHans Petter Selasky 1797d6b92ffaSHans Petter Selasky err = ibv_cmd_open_xrcd(context, xrcd, sizeof(*xrcd), xrcd_init_attr, 1798d6b92ffaSHans Petter Selasky &cmd, sizeof(cmd), &resp, sizeof(resp)); 1799d6b92ffaSHans Petter Selasky if (err) { 1800d6b92ffaSHans Petter Selasky free(xrcd); 1801d6b92ffaSHans Petter Selasky return NULL; 1802d6b92ffaSHans Petter Selasky } 1803d6b92ffaSHans Petter Selasky 1804d6b92ffaSHans Petter Selasky return &xrcd->xrcd; 1805d6b92ffaSHans Petter Selasky } 1806d6b92ffaSHans Petter Selasky 1807d6b92ffaSHans Petter Selasky int mlx5_close_xrcd(struct ibv_xrcd *ib_xrcd) 1808d6b92ffaSHans Petter Selasky { 1809d6b92ffaSHans Petter Selasky struct verbs_xrcd *xrcd = container_of(ib_xrcd, struct verbs_xrcd, xrcd); 1810d6b92ffaSHans Petter Selasky int ret; 1811d6b92ffaSHans Petter Selasky 1812d6b92ffaSHans Petter Selasky ret = ibv_cmd_close_xrcd(xrcd); 1813d6b92ffaSHans Petter Selasky if (!ret) 1814d6b92ffaSHans Petter Selasky free(xrcd); 1815d6b92ffaSHans Petter Selasky 1816d6b92ffaSHans Petter Selasky return ret; 1817d6b92ffaSHans Petter Selasky } 1818d6b92ffaSHans Petter Selasky 1819d6b92ffaSHans Petter Selasky static struct ibv_srq * 1820d6b92ffaSHans Petter Selasky mlx5_create_xrc_srq(struct ibv_context *context, 1821d6b92ffaSHans Petter Selasky struct ibv_srq_init_attr_ex *attr) 1822d6b92ffaSHans Petter Selasky { 1823d6b92ffaSHans Petter Selasky int err; 1824d6b92ffaSHans Petter Selasky struct mlx5_create_srq_ex cmd; 1825d6b92ffaSHans Petter Selasky struct mlx5_create_srq_resp resp; 1826d6b92ffaSHans Petter Selasky struct mlx5_srq *msrq; 1827d6b92ffaSHans Petter Selasky struct mlx5_context *ctx = to_mctx(context); 1828d6b92ffaSHans Petter Selasky int max_sge; 1829d6b92ffaSHans Petter Selasky struct ibv_srq *ibsrq; 1830d6b92ffaSHans Petter Selasky int uidx; 1831d6b92ffaSHans Petter Selasky FILE *fp = ctx->dbg_fp; 1832d6b92ffaSHans Petter Selasky 1833d6b92ffaSHans Petter Selasky msrq = calloc(1, sizeof(*msrq)); 1834d6b92ffaSHans Petter Selasky if (!msrq) 1835d6b92ffaSHans Petter Selasky return NULL; 1836d6b92ffaSHans Petter Selasky 1837d6b92ffaSHans Petter Selasky ibsrq = (struct ibv_srq *)&msrq->vsrq; 1838d6b92ffaSHans Petter Selasky 1839d6b92ffaSHans Petter Selasky memset(&cmd, 0, sizeof(cmd)); 1840d6b92ffaSHans Petter Selasky memset(&resp, 0, sizeof(resp)); 1841d6b92ffaSHans Petter Selasky 1842d6b92ffaSHans Petter Selasky if (mlx5_spinlock_init(&msrq->lock)) { 1843d6b92ffaSHans Petter Selasky fprintf(stderr, "%s-%d:\n", __func__, __LINE__); 1844d6b92ffaSHans Petter Selasky goto err; 1845d6b92ffaSHans Petter Selasky } 1846d6b92ffaSHans Petter Selasky 1847d6b92ffaSHans Petter Selasky if (attr->attr.max_wr > ctx->max_srq_recv_wr) { 1848d6b92ffaSHans Petter Selasky fprintf(stderr, "%s-%d:max_wr %d, max_srq_recv_wr %d\n", 1849d6b92ffaSHans Petter Selasky __func__, __LINE__, attr->attr.max_wr, 1850d6b92ffaSHans Petter Selasky ctx->max_srq_recv_wr); 1851d6b92ffaSHans Petter Selasky errno = EINVAL; 1852a687910fSSean Lim goto err_spl; 1853d6b92ffaSHans Petter Selasky } 1854d6b92ffaSHans Petter Selasky 1855d6b92ffaSHans Petter Selasky /* 1856d6b92ffaSHans Petter Selasky * this calculation does not consider required control segments. The 1857d6b92ffaSHans Petter Selasky * final calculation is done again later. This is done so to avoid 1858d6b92ffaSHans Petter Selasky * overflows of variables 1859d6b92ffaSHans Petter Selasky */ 1860d6b92ffaSHans Petter Selasky max_sge = ctx->max_recv_wr / sizeof(struct mlx5_wqe_data_seg); 1861d6b92ffaSHans Petter Selasky if (attr->attr.max_sge > max_sge) { 1862d6b92ffaSHans Petter Selasky fprintf(stderr, "%s-%d:max_wr %d, max_srq_recv_wr %d\n", 1863d6b92ffaSHans Petter Selasky __func__, __LINE__, attr->attr.max_wr, 1864d6b92ffaSHans Petter Selasky ctx->max_srq_recv_wr); 1865d6b92ffaSHans Petter Selasky errno = EINVAL; 1866a687910fSSean Lim goto err_spl; 1867d6b92ffaSHans Petter Selasky } 1868d6b92ffaSHans Petter Selasky 1869d6b92ffaSHans Petter Selasky msrq->max = align_queue_size(attr->attr.max_wr + 1); 1870d6b92ffaSHans Petter Selasky msrq->max_gs = attr->attr.max_sge; 1871d6b92ffaSHans Petter Selasky msrq->counter = 0; 1872d6b92ffaSHans Petter Selasky 1873d6b92ffaSHans Petter Selasky if (mlx5_alloc_srq_buf(context, msrq)) { 1874d6b92ffaSHans Petter Selasky fprintf(stderr, "%s-%d:\n", __func__, __LINE__); 1875a687910fSSean Lim goto err_spl; 1876d6b92ffaSHans Petter Selasky } 1877d6b92ffaSHans Petter Selasky 1878d6b92ffaSHans Petter Selasky msrq->db = mlx5_alloc_dbrec(ctx); 1879d6b92ffaSHans Petter Selasky if (!msrq->db) { 1880d6b92ffaSHans Petter Selasky fprintf(stderr, "%s-%d:\n", __func__, __LINE__); 1881d6b92ffaSHans Petter Selasky goto err_free; 1882d6b92ffaSHans Petter Selasky } 1883d6b92ffaSHans Petter Selasky 1884d6b92ffaSHans Petter Selasky *msrq->db = 0; 1885d6b92ffaSHans Petter Selasky 1886d6b92ffaSHans Petter Selasky cmd.buf_addr = (uintptr_t)msrq->buf.buf; 1887d6b92ffaSHans Petter Selasky cmd.db_addr = (uintptr_t)msrq->db; 1888d6b92ffaSHans Petter Selasky msrq->wq_sig = srq_sig_enabled(); 1889d6b92ffaSHans Petter Selasky if (msrq->wq_sig) 1890d6b92ffaSHans Petter Selasky cmd.flags = MLX5_SRQ_FLAG_SIGNATURE; 1891d6b92ffaSHans Petter Selasky 1892d6b92ffaSHans Petter Selasky attr->attr.max_sge = msrq->max_gs; 1893d6b92ffaSHans Petter Selasky if (ctx->cqe_version) { 1894d6b92ffaSHans Petter Selasky uidx = mlx5_store_uidx(ctx, msrq); 1895d6b92ffaSHans Petter Selasky if (uidx < 0) { 1896d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_QP, "Couldn't find free user index\n"); 1897d6b92ffaSHans Petter Selasky goto err_free_db; 1898d6b92ffaSHans Petter Selasky } 1899d6b92ffaSHans Petter Selasky cmd.uidx = uidx; 1900d6b92ffaSHans Petter Selasky } else { 1901d6b92ffaSHans Petter Selasky cmd.uidx = 0xffffff; 1902d6b92ffaSHans Petter Selasky pthread_mutex_lock(&ctx->srq_table_mutex); 1903d6b92ffaSHans Petter Selasky } 1904d6b92ffaSHans Petter Selasky 1905d6b92ffaSHans Petter Selasky err = ibv_cmd_create_srq_ex(context, &msrq->vsrq, sizeof(msrq->vsrq), 1906d6b92ffaSHans Petter Selasky attr, &cmd.ibv_cmd, sizeof(cmd), 1907d6b92ffaSHans Petter Selasky &resp.ibv_resp, sizeof(resp)); 1908d6b92ffaSHans Petter Selasky if (err) 1909d6b92ffaSHans Petter Selasky goto err_free_uidx; 1910d6b92ffaSHans Petter Selasky 1911d6b92ffaSHans Petter Selasky if (!ctx->cqe_version) { 1912d6b92ffaSHans Petter Selasky err = mlx5_store_srq(to_mctx(context), resp.srqn, msrq); 1913d6b92ffaSHans Petter Selasky if (err) 1914d6b92ffaSHans Petter Selasky goto err_destroy; 1915d6b92ffaSHans Petter Selasky 1916d6b92ffaSHans Petter Selasky pthread_mutex_unlock(&ctx->srq_table_mutex); 1917d6b92ffaSHans Petter Selasky } 1918d6b92ffaSHans Petter Selasky 1919d6b92ffaSHans Petter Selasky msrq->srqn = resp.srqn; 1920d6b92ffaSHans Petter Selasky msrq->rsc.type = MLX5_RSC_TYPE_XSRQ; 1921d6b92ffaSHans Petter Selasky msrq->rsc.rsn = ctx->cqe_version ? cmd.uidx : resp.srqn; 1922d6b92ffaSHans Petter Selasky 1923d6b92ffaSHans Petter Selasky return ibsrq; 1924d6b92ffaSHans Petter Selasky 1925d6b92ffaSHans Petter Selasky err_destroy: 1926d6b92ffaSHans Petter Selasky ibv_cmd_destroy_srq(ibsrq); 1927d6b92ffaSHans Petter Selasky 1928d6b92ffaSHans Petter Selasky err_free_uidx: 1929d6b92ffaSHans Petter Selasky if (ctx->cqe_version) 1930d6b92ffaSHans Petter Selasky mlx5_clear_uidx(ctx, cmd.uidx); 1931d6b92ffaSHans Petter Selasky else 1932d6b92ffaSHans Petter Selasky pthread_mutex_unlock(&ctx->srq_table_mutex); 1933d6b92ffaSHans Petter Selasky 1934d6b92ffaSHans Petter Selasky err_free_db: 1935d6b92ffaSHans Petter Selasky mlx5_free_db(ctx, msrq->db); 1936d6b92ffaSHans Petter Selasky 1937d6b92ffaSHans Petter Selasky err_free: 1938d6b92ffaSHans Petter Selasky free(msrq->wrid); 1939d6b92ffaSHans Petter Selasky mlx5_free_buf(&msrq->buf); 1940d6b92ffaSHans Petter Selasky 1941a687910fSSean Lim err_spl: 1942a687910fSSean Lim mlx5_spinlock_destroy(&msrq->lock); 1943a687910fSSean Lim 1944d6b92ffaSHans Petter Selasky err: 1945d6b92ffaSHans Petter Selasky free(msrq); 1946d6b92ffaSHans Petter Selasky 1947d6b92ffaSHans Petter Selasky return NULL; 1948d6b92ffaSHans Petter Selasky } 1949d6b92ffaSHans Petter Selasky 1950d6b92ffaSHans Petter Selasky struct ibv_srq *mlx5_create_srq_ex(struct ibv_context *context, 1951d6b92ffaSHans Petter Selasky struct ibv_srq_init_attr_ex *attr) 1952d6b92ffaSHans Petter Selasky { 1953d6b92ffaSHans Petter Selasky if (!(attr->comp_mask & IBV_SRQ_INIT_ATTR_TYPE) || 1954d6b92ffaSHans Petter Selasky (attr->srq_type == IBV_SRQT_BASIC)) 1955d6b92ffaSHans Petter Selasky return mlx5_create_srq(attr->pd, 1956d6b92ffaSHans Petter Selasky (struct ibv_srq_init_attr *)attr); 1957d6b92ffaSHans Petter Selasky else if (attr->srq_type == IBV_SRQT_XRC) 1958d6b92ffaSHans Petter Selasky return mlx5_create_xrc_srq(context, attr); 1959d6b92ffaSHans Petter Selasky 1960d6b92ffaSHans Petter Selasky return NULL; 1961d6b92ffaSHans Petter Selasky } 1962d6b92ffaSHans Petter Selasky 1963d6b92ffaSHans Petter Selasky int mlx5_query_device_ex(struct ibv_context *context, 1964d6b92ffaSHans Petter Selasky const struct ibv_query_device_ex_input *input, 1965d6b92ffaSHans Petter Selasky struct ibv_device_attr_ex *attr, 1966d6b92ffaSHans Petter Selasky size_t attr_size) 1967d6b92ffaSHans Petter Selasky { 1968d6b92ffaSHans Petter Selasky struct mlx5_context *mctx = to_mctx(context); 1969d6b92ffaSHans Petter Selasky struct mlx5_query_device_ex_resp resp; 1970d6b92ffaSHans Petter Selasky struct mlx5_query_device_ex cmd; 1971d6b92ffaSHans Petter Selasky struct ibv_device_attr *a; 1972d6b92ffaSHans Petter Selasky uint64_t raw_fw_ver; 1973d6b92ffaSHans Petter Selasky unsigned sub_minor; 1974d6b92ffaSHans Petter Selasky unsigned major; 1975d6b92ffaSHans Petter Selasky unsigned minor; 1976d6b92ffaSHans Petter Selasky int err; 1977d6b92ffaSHans Petter Selasky int cmd_supp_uhw = mctx->cmds_supp_uhw & 1978d6b92ffaSHans Petter Selasky MLX5_USER_CMDS_SUPP_UHW_QUERY_DEVICE; 1979d6b92ffaSHans Petter Selasky 1980d6b92ffaSHans Petter Selasky memset(&cmd, 0, sizeof(cmd)); 1981d6b92ffaSHans Petter Selasky memset(&resp, 0, sizeof(resp)); 1982d6b92ffaSHans Petter Selasky err = ibv_cmd_query_device_ex(context, input, attr, attr_size, 1983d6b92ffaSHans Petter Selasky &raw_fw_ver, 1984d6b92ffaSHans Petter Selasky &cmd.ibv_cmd, sizeof(cmd.ibv_cmd), sizeof(cmd), 1985d6b92ffaSHans Petter Selasky &resp.ibv_resp, sizeof(resp.ibv_resp), 1986d6b92ffaSHans Petter Selasky cmd_supp_uhw ? sizeof(resp) : sizeof(resp.ibv_resp)); 1987d6b92ffaSHans Petter Selasky if (err) 1988d6b92ffaSHans Petter Selasky return err; 1989d6b92ffaSHans Petter Selasky 1990d6b92ffaSHans Petter Selasky attr->tso_caps = resp.tso_caps; 1991d6b92ffaSHans Petter Selasky attr->rss_caps.rx_hash_fields_mask = resp.rss_caps.rx_hash_fields_mask; 1992d6b92ffaSHans Petter Selasky attr->rss_caps.rx_hash_function = resp.rss_caps.rx_hash_function; 1993d6b92ffaSHans Petter Selasky attr->packet_pacing_caps = resp.packet_pacing_caps.caps; 1994d6b92ffaSHans Petter Selasky 1995d6b92ffaSHans Petter Selasky if (resp.support_multi_pkt_send_wqe) 1996d6b92ffaSHans Petter Selasky mctx->vendor_cap_flags |= MLX5_VENDOR_CAP_FLAGS_MPW; 1997d6b92ffaSHans Petter Selasky 1998d6b92ffaSHans Petter Selasky mctx->cqe_comp_caps = resp.cqe_comp_caps; 1999d6b92ffaSHans Petter Selasky 2000d6b92ffaSHans Petter Selasky major = (raw_fw_ver >> 32) & 0xffff; 2001d6b92ffaSHans Petter Selasky minor = (raw_fw_ver >> 16) & 0xffff; 2002d6b92ffaSHans Petter Selasky sub_minor = raw_fw_ver & 0xffff; 2003d6b92ffaSHans Petter Selasky a = &attr->orig_attr; 2004d6b92ffaSHans Petter Selasky snprintf(a->fw_ver, sizeof(a->fw_ver), "%d.%d.%04d", 2005d6b92ffaSHans Petter Selasky major, minor, sub_minor); 2006d6b92ffaSHans Petter Selasky 2007d6b92ffaSHans Petter Selasky return 0; 2008d6b92ffaSHans Petter Selasky } 2009d6b92ffaSHans Petter Selasky 2010d6b92ffaSHans Petter Selasky static int rwq_sig_enabled(struct ibv_context *context) 2011d6b92ffaSHans Petter Selasky { 2012d6b92ffaSHans Petter Selasky char *env; 2013d6b92ffaSHans Petter Selasky 2014d6b92ffaSHans Petter Selasky env = getenv("MLX5_RWQ_SIGNATURE"); 2015d6b92ffaSHans Petter Selasky if (env) 2016d6b92ffaSHans Petter Selasky return 1; 2017d6b92ffaSHans Petter Selasky 2018d6b92ffaSHans Petter Selasky return 0; 2019d6b92ffaSHans Petter Selasky } 2020d6b92ffaSHans Petter Selasky 2021d6b92ffaSHans Petter Selasky static void mlx5_free_rwq_buf(struct mlx5_rwq *rwq, struct ibv_context *context) 2022d6b92ffaSHans Petter Selasky { 2023d6b92ffaSHans Petter Selasky struct mlx5_context *ctx = to_mctx(context); 2024d6b92ffaSHans Petter Selasky 2025d6b92ffaSHans Petter Selasky mlx5_free_actual_buf(ctx, &rwq->buf); 2026d6b92ffaSHans Petter Selasky free(rwq->rq.wrid); 2027d6b92ffaSHans Petter Selasky } 2028d6b92ffaSHans Petter Selasky 2029d6b92ffaSHans Petter Selasky static int mlx5_alloc_rwq_buf(struct ibv_context *context, 2030d6b92ffaSHans Petter Selasky struct mlx5_rwq *rwq, 2031d6b92ffaSHans Petter Selasky int size) 2032d6b92ffaSHans Petter Selasky { 2033d6b92ffaSHans Petter Selasky int err; 2034d6b92ffaSHans Petter Selasky enum mlx5_alloc_type default_alloc_type = MLX5_ALLOC_TYPE_PREFER_CONTIG; 2035d6b92ffaSHans Petter Selasky 2036d6b92ffaSHans Petter Selasky rwq->rq.wrid = malloc(rwq->rq.wqe_cnt * sizeof(uint64_t)); 2037d6b92ffaSHans Petter Selasky if (!rwq->rq.wrid) { 2038d6b92ffaSHans Petter Selasky errno = ENOMEM; 2039d6b92ffaSHans Petter Selasky return -1; 2040d6b92ffaSHans Petter Selasky } 2041d6b92ffaSHans Petter Selasky 2042d6b92ffaSHans Petter Selasky err = mlx5_alloc_prefered_buf(to_mctx(context), &rwq->buf, 2043d6b92ffaSHans Petter Selasky align(rwq->buf_size, to_mdev 2044d6b92ffaSHans Petter Selasky (context->device)->page_size), 2045d6b92ffaSHans Petter Selasky to_mdev(context->device)->page_size, 2046d6b92ffaSHans Petter Selasky default_alloc_type, 2047d6b92ffaSHans Petter Selasky MLX5_RWQ_PREFIX); 2048d6b92ffaSHans Petter Selasky 2049d6b92ffaSHans Petter Selasky if (err) { 2050d6b92ffaSHans Petter Selasky free(rwq->rq.wrid); 2051d6b92ffaSHans Petter Selasky errno = ENOMEM; 2052d6b92ffaSHans Petter Selasky return -1; 2053d6b92ffaSHans Petter Selasky } 2054d6b92ffaSHans Petter Selasky 2055d6b92ffaSHans Petter Selasky return 0; 2056d6b92ffaSHans Petter Selasky } 2057d6b92ffaSHans Petter Selasky 2058d6b92ffaSHans Petter Selasky struct ibv_wq *mlx5_create_wq(struct ibv_context *context, 2059d6b92ffaSHans Petter Selasky struct ibv_wq_init_attr *attr) 2060d6b92ffaSHans Petter Selasky { 2061d6b92ffaSHans Petter Selasky struct mlx5_create_wq cmd; 2062d6b92ffaSHans Petter Selasky struct mlx5_create_wq_resp resp; 2063d6b92ffaSHans Petter Selasky int err; 2064d6b92ffaSHans Petter Selasky struct mlx5_rwq *rwq; 2065d6b92ffaSHans Petter Selasky struct mlx5_context *ctx = to_mctx(context); 2066d6b92ffaSHans Petter Selasky int ret; 2067d6b92ffaSHans Petter Selasky int32_t usr_idx = 0; 2068d6b92ffaSHans Petter Selasky FILE *fp = ctx->dbg_fp; 2069d6b92ffaSHans Petter Selasky 2070d6b92ffaSHans Petter Selasky if (attr->wq_type != IBV_WQT_RQ) 2071d6b92ffaSHans Petter Selasky return NULL; 2072d6b92ffaSHans Petter Selasky 2073d6b92ffaSHans Petter Selasky memset(&cmd, 0, sizeof(cmd)); 2074d6b92ffaSHans Petter Selasky memset(&resp, 0, sizeof(resp)); 2075d6b92ffaSHans Petter Selasky 2076d6b92ffaSHans Petter Selasky rwq = calloc(1, sizeof(*rwq)); 2077d6b92ffaSHans Petter Selasky if (!rwq) 2078d6b92ffaSHans Petter Selasky return NULL; 2079d6b92ffaSHans Petter Selasky 2080*25ef056fSKa Ho Ng ret = ibv_init_wq(&rwq->wq); 2081*25ef056fSKa Ho Ng if (ret < 0) 2082*25ef056fSKa Ho Ng goto err; 2083*25ef056fSKa Ho Ng 2084d6b92ffaSHans Petter Selasky rwq->wq_sig = rwq_sig_enabled(context); 2085d6b92ffaSHans Petter Selasky if (rwq->wq_sig) 2086d6b92ffaSHans Petter Selasky cmd.drv.flags = MLX5_RWQ_FLAG_SIGNATURE; 2087d6b92ffaSHans Petter Selasky 2088d6b92ffaSHans Petter Selasky ret = mlx5_calc_rwq_size(ctx, rwq, attr); 2089d6b92ffaSHans Petter Selasky if (ret < 0) { 2090d6b92ffaSHans Petter Selasky errno = -ret; 2091*25ef056fSKa Ho Ng goto err_cleanup_wq; 2092d6b92ffaSHans Petter Selasky } 2093d6b92ffaSHans Petter Selasky 2094d6b92ffaSHans Petter Selasky rwq->buf_size = ret; 2095d6b92ffaSHans Petter Selasky if (mlx5_alloc_rwq_buf(context, rwq, ret)) 2096a687910fSSean Lim goto err_cleanup_wq; 2097d6b92ffaSHans Petter Selasky 2098d6b92ffaSHans Petter Selasky mlx5_init_rwq_indices(rwq); 2099d6b92ffaSHans Petter Selasky 2100d6b92ffaSHans Petter Selasky if (mlx5_spinlock_init(&rwq->rq.lock)) 2101d6b92ffaSHans Petter Selasky goto err_free_rwq_buf; 2102d6b92ffaSHans Petter Selasky 2103d6b92ffaSHans Petter Selasky rwq->db = mlx5_alloc_dbrec(ctx); 2104d6b92ffaSHans Petter Selasky if (!rwq->db) 2105a687910fSSean Lim goto err_spl; 2106d6b92ffaSHans Petter Selasky 2107d6b92ffaSHans Petter Selasky rwq->db[MLX5_RCV_DBR] = 0; 2108d6b92ffaSHans Petter Selasky rwq->db[MLX5_SND_DBR] = 0; 2109d6b92ffaSHans Petter Selasky rwq->pbuff = rwq->buf.buf + rwq->rq.offset; 2110d6b92ffaSHans Petter Selasky rwq->recv_db = &rwq->db[MLX5_RCV_DBR]; 2111d6b92ffaSHans Petter Selasky cmd.drv.buf_addr = (uintptr_t)rwq->buf.buf; 2112d6b92ffaSHans Petter Selasky cmd.drv.db_addr = (uintptr_t)rwq->db; 2113d6b92ffaSHans Petter Selasky cmd.drv.rq_wqe_count = rwq->rq.wqe_cnt; 2114d6b92ffaSHans Petter Selasky cmd.drv.rq_wqe_shift = rwq->rq.wqe_shift; 2115d6b92ffaSHans Petter Selasky usr_idx = mlx5_store_uidx(ctx, rwq); 2116d6b92ffaSHans Petter Selasky if (usr_idx < 0) { 2117d6b92ffaSHans Petter Selasky mlx5_dbg(fp, MLX5_DBG_QP, "Couldn't find free user index\n"); 2118d6b92ffaSHans Petter Selasky goto err_free_db_rec; 2119d6b92ffaSHans Petter Selasky } 2120d6b92ffaSHans Petter Selasky 2121d6b92ffaSHans Petter Selasky cmd.drv.user_index = usr_idx; 2122d6b92ffaSHans Petter Selasky err = ibv_cmd_create_wq(context, attr, &rwq->wq, &cmd.ibv_cmd, 2123d6b92ffaSHans Petter Selasky sizeof(cmd.ibv_cmd), 2124d6b92ffaSHans Petter Selasky sizeof(cmd), 2125d6b92ffaSHans Petter Selasky &resp.ibv_resp, sizeof(resp.ibv_resp), 2126d6b92ffaSHans Petter Selasky sizeof(resp)); 2127d6b92ffaSHans Petter Selasky if (err) 2128d6b92ffaSHans Petter Selasky goto err_create; 2129d6b92ffaSHans Petter Selasky 2130d6b92ffaSHans Petter Selasky rwq->rsc.type = MLX5_RSC_TYPE_RWQ; 2131d6b92ffaSHans Petter Selasky rwq->rsc.rsn = cmd.drv.user_index; 2132d6b92ffaSHans Petter Selasky 2133d6b92ffaSHans Petter Selasky rwq->wq.post_recv = mlx5_post_wq_recv; 2134d6b92ffaSHans Petter Selasky return &rwq->wq; 2135d6b92ffaSHans Petter Selasky 2136d6b92ffaSHans Petter Selasky err_create: 2137d6b92ffaSHans Petter Selasky mlx5_clear_uidx(ctx, cmd.drv.user_index); 2138d6b92ffaSHans Petter Selasky err_free_db_rec: 2139d6b92ffaSHans Petter Selasky mlx5_free_db(to_mctx(context), rwq->db); 2140a687910fSSean Lim err_spl: 2141a687910fSSean Lim mlx5_spinlock_destroy(&rwq->rq.lock); 2142d6b92ffaSHans Petter Selasky err_free_rwq_buf: 2143d6b92ffaSHans Petter Selasky mlx5_free_rwq_buf(rwq, context); 2144a687910fSSean Lim err_cleanup_wq: 2145a687910fSSean Lim ibv_cleanup_wq(&rwq->wq); 2146d6b92ffaSHans Petter Selasky err: 2147d6b92ffaSHans Petter Selasky free(rwq); 2148d6b92ffaSHans Petter Selasky return NULL; 2149d6b92ffaSHans Petter Selasky } 2150d6b92ffaSHans Petter Selasky 2151d6b92ffaSHans Petter Selasky int mlx5_modify_wq(struct ibv_wq *wq, struct ibv_wq_attr *attr) 2152d6b92ffaSHans Petter Selasky { 2153d6b92ffaSHans Petter Selasky struct mlx5_modify_wq cmd = {}; 2154d6b92ffaSHans Petter Selasky struct mlx5_rwq *rwq = to_mrwq(wq); 2155d6b92ffaSHans Petter Selasky 2156d6b92ffaSHans Petter Selasky if ((attr->attr_mask & IBV_WQ_ATTR_STATE) && 2157d6b92ffaSHans Petter Selasky attr->wq_state == IBV_WQS_RDY) { 2158d6b92ffaSHans Petter Selasky if ((attr->attr_mask & IBV_WQ_ATTR_CURR_STATE) && 2159d6b92ffaSHans Petter Selasky attr->curr_wq_state != wq->state) 2160d6b92ffaSHans Petter Selasky return -EINVAL; 2161d6b92ffaSHans Petter Selasky 2162d6b92ffaSHans Petter Selasky if (wq->state == IBV_WQS_RESET) { 2163d6b92ffaSHans Petter Selasky mlx5_spin_lock(&to_mcq(wq->cq)->lock); 2164d6b92ffaSHans Petter Selasky __mlx5_cq_clean(to_mcq(wq->cq), 2165d6b92ffaSHans Petter Selasky rwq->rsc.rsn, NULL); 2166d6b92ffaSHans Petter Selasky mlx5_spin_unlock(&to_mcq(wq->cq)->lock); 2167d6b92ffaSHans Petter Selasky mlx5_init_rwq_indices(rwq); 2168d6b92ffaSHans Petter Selasky rwq->db[MLX5_RCV_DBR] = 0; 2169d6b92ffaSHans Petter Selasky rwq->db[MLX5_SND_DBR] = 0; 2170d6b92ffaSHans Petter Selasky } 2171d6b92ffaSHans Petter Selasky } 2172d6b92ffaSHans Petter Selasky 2173d6b92ffaSHans Petter Selasky return ibv_cmd_modify_wq(wq, attr, &cmd.ibv_cmd, sizeof(cmd.ibv_cmd), sizeof(cmd)); 2174d6b92ffaSHans Petter Selasky } 2175d6b92ffaSHans Petter Selasky 2176d6b92ffaSHans Petter Selasky int mlx5_destroy_wq(struct ibv_wq *wq) 2177d6b92ffaSHans Petter Selasky { 2178d6b92ffaSHans Petter Selasky struct mlx5_rwq *rwq = to_mrwq(wq); 2179d6b92ffaSHans Petter Selasky int ret; 2180d6b92ffaSHans Petter Selasky 2181d6b92ffaSHans Petter Selasky ret = ibv_cmd_destroy_wq(wq); 2182d6b92ffaSHans Petter Selasky if (ret) 2183d6b92ffaSHans Petter Selasky return ret; 2184d6b92ffaSHans Petter Selasky 2185d6b92ffaSHans Petter Selasky mlx5_spin_lock(&to_mcq(wq->cq)->lock); 2186d6b92ffaSHans Petter Selasky __mlx5_cq_clean(to_mcq(wq->cq), rwq->rsc.rsn, NULL); 2187d6b92ffaSHans Petter Selasky mlx5_spin_unlock(&to_mcq(wq->cq)->lock); 2188d6b92ffaSHans Petter Selasky mlx5_clear_uidx(to_mctx(wq->context), rwq->rsc.rsn); 2189d6b92ffaSHans Petter Selasky mlx5_free_db(to_mctx(wq->context), rwq->db); 2190a687910fSSean Lim mlx5_spinlock_destroy(&rwq->rq.lock); 2191d6b92ffaSHans Petter Selasky mlx5_free_rwq_buf(rwq, wq->context); 2192a687910fSSean Lim ibv_cleanup_wq(&rwq->wq); 2193d6b92ffaSHans Petter Selasky free(rwq); 2194d6b92ffaSHans Petter Selasky 2195d6b92ffaSHans Petter Selasky return 0; 2196d6b92ffaSHans Petter Selasky } 2197d6b92ffaSHans Petter Selasky 2198d6b92ffaSHans Petter Selasky struct ibv_rwq_ind_table *mlx5_create_rwq_ind_table(struct ibv_context *context, 2199d6b92ffaSHans Petter Selasky struct ibv_rwq_ind_table_init_attr *init_attr) 2200d6b92ffaSHans Petter Selasky { 2201d6b92ffaSHans Petter Selasky struct ibv_create_rwq_ind_table *cmd; 2202d6b92ffaSHans Petter Selasky struct mlx5_create_rwq_ind_table_resp resp; 2203d6b92ffaSHans Petter Selasky struct ibv_rwq_ind_table *ind_table; 2204d6b92ffaSHans Petter Selasky uint32_t required_tbl_size; 2205d6b92ffaSHans Petter Selasky int num_tbl_entries; 2206d6b92ffaSHans Petter Selasky int cmd_size; 2207d6b92ffaSHans Petter Selasky int err; 2208d6b92ffaSHans Petter Selasky 2209d6b92ffaSHans Petter Selasky num_tbl_entries = 1 << init_attr->log_ind_tbl_size; 2210d6b92ffaSHans Petter Selasky /* Data must be u64 aligned */ 2211d6b92ffaSHans Petter Selasky required_tbl_size = (num_tbl_entries * sizeof(uint32_t)) < sizeof(uint64_t) ? 2212d6b92ffaSHans Petter Selasky sizeof(uint64_t) : (num_tbl_entries * sizeof(uint32_t)); 2213d6b92ffaSHans Petter Selasky 2214d6b92ffaSHans Petter Selasky cmd_size = required_tbl_size + sizeof(*cmd); 2215d6b92ffaSHans Petter Selasky cmd = calloc(1, cmd_size); 2216d6b92ffaSHans Petter Selasky if (!cmd) 2217d6b92ffaSHans Petter Selasky return NULL; 2218d6b92ffaSHans Petter Selasky 2219d6b92ffaSHans Petter Selasky memset(&resp, 0, sizeof(resp)); 2220d6b92ffaSHans Petter Selasky ind_table = calloc(1, sizeof(*ind_table)); 2221d6b92ffaSHans Petter Selasky if (!ind_table) 2222d6b92ffaSHans Petter Selasky goto free_cmd; 2223d6b92ffaSHans Petter Selasky 2224d6b92ffaSHans Petter Selasky err = ibv_cmd_create_rwq_ind_table(context, init_attr, ind_table, cmd, 2225d6b92ffaSHans Petter Selasky cmd_size, cmd_size, &resp.ibv_resp, sizeof(resp.ibv_resp), 2226d6b92ffaSHans Petter Selasky sizeof(resp)); 2227d6b92ffaSHans Petter Selasky if (err) 2228d6b92ffaSHans Petter Selasky goto err; 2229d6b92ffaSHans Petter Selasky 2230d6b92ffaSHans Petter Selasky free(cmd); 2231d6b92ffaSHans Petter Selasky return ind_table; 2232d6b92ffaSHans Petter Selasky 2233d6b92ffaSHans Petter Selasky err: 2234d6b92ffaSHans Petter Selasky free(ind_table); 2235d6b92ffaSHans Petter Selasky free_cmd: 2236d6b92ffaSHans Petter Selasky free(cmd); 2237d6b92ffaSHans Petter Selasky return NULL; 2238d6b92ffaSHans Petter Selasky } 2239d6b92ffaSHans Petter Selasky 2240d6b92ffaSHans Petter Selasky int mlx5_destroy_rwq_ind_table(struct ibv_rwq_ind_table *rwq_ind_table) 2241d6b92ffaSHans Petter Selasky { 2242d6b92ffaSHans Petter Selasky int ret; 2243d6b92ffaSHans Petter Selasky 2244d6b92ffaSHans Petter Selasky ret = ibv_cmd_destroy_rwq_ind_table(rwq_ind_table); 2245d6b92ffaSHans Petter Selasky 2246d6b92ffaSHans Petter Selasky if (ret) 2247d6b92ffaSHans Petter Selasky return ret; 2248d6b92ffaSHans Petter Selasky 2249d6b92ffaSHans Petter Selasky free(rwq_ind_table); 2250d6b92ffaSHans Petter Selasky return 0; 2251d6b92ffaSHans Petter Selasky } 2252