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 #define _GNU_SOURCE 33d6b92ffaSHans Petter Selasky #include <config.h> 34d6b92ffaSHans Petter Selasky 35d6b92ffaSHans Petter Selasky #include <stdio.h> 36d6b92ffaSHans Petter Selasky #include <stdlib.h> 37d6b92ffaSHans Petter Selasky #include <unistd.h> 38d6b92ffaSHans Petter Selasky #include <errno.h> 39d6b92ffaSHans Petter Selasky #include <sys/mman.h> 40d6b92ffaSHans Petter Selasky #include <pthread.h> 41d6b92ffaSHans Petter Selasky #include <string.h> 42d6b92ffaSHans Petter Selasky #include <sched.h> 43d6b92ffaSHans Petter Selasky #include <sys/param.h> 44d6b92ffaSHans Petter Selasky #include <sys/cpuset.h> 45d6b92ffaSHans Petter Selasky 46d6b92ffaSHans Petter Selasky #include "mlx5.h" 47d6b92ffaSHans Petter Selasky #include "mlx5-abi.h" 48d6b92ffaSHans Petter Selasky 49d6b92ffaSHans Petter Selasky #ifndef PCI_VENDOR_ID_MELLANOX 50d6b92ffaSHans Petter Selasky #define PCI_VENDOR_ID_MELLANOX 0x15b3 51d6b92ffaSHans Petter Selasky #endif 52d6b92ffaSHans Petter Selasky 53d6b92ffaSHans Petter Selasky #ifndef CPU_OR 54d6b92ffaSHans Petter Selasky #define CPU_OR(x, y, z) do {} while (0) 55d6b92ffaSHans Petter Selasky #endif 56d6b92ffaSHans Petter Selasky 57d6b92ffaSHans Petter Selasky #ifndef CPU_EQUAL 58d6b92ffaSHans Petter Selasky #define CPU_EQUAL(x, y) 1 59d6b92ffaSHans Petter Selasky #endif 60d6b92ffaSHans Petter Selasky 61d6b92ffaSHans Petter Selasky 62d6b92ffaSHans Petter Selasky #define HCA(v, d) \ 63d6b92ffaSHans Petter Selasky { .vendor = PCI_VENDOR_ID_##v, \ 64d6b92ffaSHans Petter Selasky .device = d } 65d6b92ffaSHans Petter Selasky 66d6b92ffaSHans Petter Selasky static struct { 67d6b92ffaSHans Petter Selasky unsigned vendor; 68d6b92ffaSHans Petter Selasky unsigned device; 69d6b92ffaSHans Petter Selasky } hca_table[] = { 70d6b92ffaSHans Petter Selasky HCA(MELLANOX, 4113), /* MT4113 Connect-IB */ 71d6b92ffaSHans Petter Selasky HCA(MELLANOX, 4114), /* Connect-IB Virtual Function */ 72d6b92ffaSHans Petter Selasky HCA(MELLANOX, 4115), /* ConnectX-4 */ 73d6b92ffaSHans Petter Selasky HCA(MELLANOX, 4116), /* ConnectX-4 Virtual Function */ 74d6b92ffaSHans Petter Selasky HCA(MELLANOX, 4117), /* ConnectX-4LX */ 75d6b92ffaSHans Petter Selasky HCA(MELLANOX, 4118), /* ConnectX-4LX Virtual Function */ 76d6b92ffaSHans Petter Selasky HCA(MELLANOX, 4119), /* ConnectX-5, PCIe 3.0 */ 77d6b92ffaSHans Petter Selasky HCA(MELLANOX, 4120), /* ConnectX-5 Virtual Function */ 78d6b92ffaSHans Petter Selasky HCA(MELLANOX, 4121), /* ConnectX-5 Ex */ 79d6b92ffaSHans Petter Selasky HCA(MELLANOX, 4122), /* ConnectX-5 Ex VF */ 80d6b92ffaSHans Petter Selasky HCA(MELLANOX, 4123), /* ConnectX-6 */ 81d6b92ffaSHans Petter Selasky HCA(MELLANOX, 4124), /* ConnectX-6 VF */ 82*13a2290cSHans Petter Selasky HCA(MELLANOX, 4125), /* ConnectX-6 DX */ 83*13a2290cSHans Petter Selasky HCA(MELLANOX, 4126), /* ConnectX family mlx5Gen Virtual Function */ 84d6b92ffaSHans Petter Selasky HCA(MELLANOX, 41682), /* BlueField integrated ConnectX-5 network controller */ 85d6b92ffaSHans Petter Selasky HCA(MELLANOX, 41683), /* BlueField integrated ConnectX-5 network controller VF */ 86d6b92ffaSHans Petter Selasky }; 87d6b92ffaSHans Petter Selasky 88d6b92ffaSHans Petter Selasky uint32_t mlx5_debug_mask = 0; 89d6b92ffaSHans Petter Selasky int mlx5_freeze_on_error_cqe; 90d6b92ffaSHans Petter Selasky 91d6b92ffaSHans Petter Selasky static struct ibv_context_ops mlx5_ctx_ops = { 92d6b92ffaSHans Petter Selasky .query_device = mlx5_query_device, 93d6b92ffaSHans Petter Selasky .query_port = mlx5_query_port, 94d6b92ffaSHans Petter Selasky .alloc_pd = mlx5_alloc_pd, 95d6b92ffaSHans Petter Selasky .dealloc_pd = mlx5_free_pd, 96d6b92ffaSHans Petter Selasky .reg_mr = mlx5_reg_mr, 97d6b92ffaSHans Petter Selasky .rereg_mr = mlx5_rereg_mr, 98d6b92ffaSHans Petter Selasky .dereg_mr = mlx5_dereg_mr, 99d6b92ffaSHans Petter Selasky .alloc_mw = mlx5_alloc_mw, 100d6b92ffaSHans Petter Selasky .dealloc_mw = mlx5_dealloc_mw, 101d6b92ffaSHans Petter Selasky .bind_mw = mlx5_bind_mw, 102d6b92ffaSHans Petter Selasky .create_cq = mlx5_create_cq, 103d6b92ffaSHans Petter Selasky .poll_cq = mlx5_poll_cq, 104d6b92ffaSHans Petter Selasky .req_notify_cq = mlx5_arm_cq, 105d6b92ffaSHans Petter Selasky .cq_event = mlx5_cq_event, 106d6b92ffaSHans Petter Selasky .resize_cq = mlx5_resize_cq, 107d6b92ffaSHans Petter Selasky .destroy_cq = mlx5_destroy_cq, 108d6b92ffaSHans Petter Selasky .create_srq = mlx5_create_srq, 109d6b92ffaSHans Petter Selasky .modify_srq = mlx5_modify_srq, 110d6b92ffaSHans Petter Selasky .query_srq = mlx5_query_srq, 111d6b92ffaSHans Petter Selasky .destroy_srq = mlx5_destroy_srq, 112d6b92ffaSHans Petter Selasky .post_srq_recv = mlx5_post_srq_recv, 113d6b92ffaSHans Petter Selasky .create_qp = mlx5_create_qp, 114d6b92ffaSHans Petter Selasky .query_qp = mlx5_query_qp, 115d6b92ffaSHans Petter Selasky .modify_qp = mlx5_modify_qp, 116d6b92ffaSHans Petter Selasky .destroy_qp = mlx5_destroy_qp, 117d6b92ffaSHans Petter Selasky .post_send = mlx5_post_send, 118d6b92ffaSHans Petter Selasky .post_recv = mlx5_post_recv, 119d6b92ffaSHans Petter Selasky .create_ah = mlx5_create_ah, 120d6b92ffaSHans Petter Selasky .destroy_ah = mlx5_destroy_ah, 121d6b92ffaSHans Petter Selasky .attach_mcast = mlx5_attach_mcast, 122d6b92ffaSHans Petter Selasky .detach_mcast = mlx5_detach_mcast 123d6b92ffaSHans Petter Selasky }; 124d6b92ffaSHans Petter Selasky 125d6b92ffaSHans Petter Selasky static int read_number_from_line(const char *line, int *value) 126d6b92ffaSHans Petter Selasky { 127d6b92ffaSHans Petter Selasky const char *ptr; 128d6b92ffaSHans Petter Selasky 129d6b92ffaSHans Petter Selasky ptr = strchr(line, ':'); 130d6b92ffaSHans Petter Selasky if (!ptr) 131d6b92ffaSHans Petter Selasky return 1; 132d6b92ffaSHans Petter Selasky 133d6b92ffaSHans Petter Selasky ++ptr; 134d6b92ffaSHans Petter Selasky 135d6b92ffaSHans Petter Selasky *value = atoi(ptr); 136d6b92ffaSHans Petter Selasky return 0; 137d6b92ffaSHans Petter Selasky } 138d6b92ffaSHans Petter Selasky /** 139d6b92ffaSHans Petter Selasky * The function looks for the first free user-index in all the 140d6b92ffaSHans Petter Selasky * user-index tables. If all are used, returns -1, otherwise 141d6b92ffaSHans Petter Selasky * a valid user-index. 142d6b92ffaSHans Petter Selasky * In case the reference count of the table is zero, it means the 143d6b92ffaSHans Petter Selasky * table is not in use and wasn't allocated yet, therefore the 144d6b92ffaSHans Petter Selasky * mlx5_store_uidx allocates the table, and increment the reference 145d6b92ffaSHans Petter Selasky * count on the table. 146d6b92ffaSHans Petter Selasky */ 147d6b92ffaSHans Petter Selasky static int32_t get_free_uidx(struct mlx5_context *ctx) 148d6b92ffaSHans Petter Selasky { 149d6b92ffaSHans Petter Selasky int32_t tind; 150d6b92ffaSHans Petter Selasky int32_t i; 151d6b92ffaSHans Petter Selasky 152d6b92ffaSHans Petter Selasky for (tind = 0; tind < MLX5_UIDX_TABLE_SIZE; tind++) { 153d6b92ffaSHans Petter Selasky if (ctx->uidx_table[tind].refcnt < MLX5_UIDX_TABLE_MASK) 154d6b92ffaSHans Petter Selasky break; 155d6b92ffaSHans Petter Selasky } 156d6b92ffaSHans Petter Selasky 157d6b92ffaSHans Petter Selasky if (tind == MLX5_UIDX_TABLE_SIZE) 158d6b92ffaSHans Petter Selasky return -1; 159d6b92ffaSHans Petter Selasky 160d6b92ffaSHans Petter Selasky if (!ctx->uidx_table[tind].refcnt) 161d6b92ffaSHans Petter Selasky return tind << MLX5_UIDX_TABLE_SHIFT; 162d6b92ffaSHans Petter Selasky 163d6b92ffaSHans Petter Selasky for (i = 0; i < MLX5_UIDX_TABLE_MASK + 1; i++) { 164d6b92ffaSHans Petter Selasky if (!ctx->uidx_table[tind].table[i]) 165d6b92ffaSHans Petter Selasky break; 166d6b92ffaSHans Petter Selasky } 167d6b92ffaSHans Petter Selasky 168d6b92ffaSHans Petter Selasky return (tind << MLX5_UIDX_TABLE_SHIFT) | i; 169d6b92ffaSHans Petter Selasky } 170d6b92ffaSHans Petter Selasky 171d6b92ffaSHans Petter Selasky int32_t mlx5_store_uidx(struct mlx5_context *ctx, void *rsc) 172d6b92ffaSHans Petter Selasky { 173d6b92ffaSHans Petter Selasky int32_t tind; 174d6b92ffaSHans Petter Selasky int32_t ret = -1; 175d6b92ffaSHans Petter Selasky int32_t uidx; 176d6b92ffaSHans Petter Selasky 177d6b92ffaSHans Petter Selasky pthread_mutex_lock(&ctx->uidx_table_mutex); 178d6b92ffaSHans Petter Selasky uidx = get_free_uidx(ctx); 179d6b92ffaSHans Petter Selasky if (uidx < 0) 180d6b92ffaSHans Petter Selasky goto out; 181d6b92ffaSHans Petter Selasky 182d6b92ffaSHans Petter Selasky tind = uidx >> MLX5_UIDX_TABLE_SHIFT; 183d6b92ffaSHans Petter Selasky 184d6b92ffaSHans Petter Selasky if (!ctx->uidx_table[tind].refcnt) { 185d6b92ffaSHans Petter Selasky ctx->uidx_table[tind].table = calloc(MLX5_UIDX_TABLE_MASK + 1, 186d6b92ffaSHans Petter Selasky sizeof(struct mlx5_resource *)); 187d6b92ffaSHans Petter Selasky if (!ctx->uidx_table[tind].table) 188d6b92ffaSHans Petter Selasky goto out; 189d6b92ffaSHans Petter Selasky } 190d6b92ffaSHans Petter Selasky 191d6b92ffaSHans Petter Selasky ++ctx->uidx_table[tind].refcnt; 192d6b92ffaSHans Petter Selasky ctx->uidx_table[tind].table[uidx & MLX5_UIDX_TABLE_MASK] = rsc; 193d6b92ffaSHans Petter Selasky ret = uidx; 194d6b92ffaSHans Petter Selasky 195d6b92ffaSHans Petter Selasky out: 196d6b92ffaSHans Petter Selasky pthread_mutex_unlock(&ctx->uidx_table_mutex); 197d6b92ffaSHans Petter Selasky return ret; 198d6b92ffaSHans Petter Selasky } 199d6b92ffaSHans Petter Selasky 200d6b92ffaSHans Petter Selasky void mlx5_clear_uidx(struct mlx5_context *ctx, uint32_t uidx) 201d6b92ffaSHans Petter Selasky { 202d6b92ffaSHans Petter Selasky int tind = uidx >> MLX5_UIDX_TABLE_SHIFT; 203d6b92ffaSHans Petter Selasky 204d6b92ffaSHans Petter Selasky pthread_mutex_lock(&ctx->uidx_table_mutex); 205d6b92ffaSHans Petter Selasky 206d6b92ffaSHans Petter Selasky if (!--ctx->uidx_table[tind].refcnt) 207d6b92ffaSHans Petter Selasky free(ctx->uidx_table[tind].table); 208d6b92ffaSHans Petter Selasky else 209d6b92ffaSHans Petter Selasky ctx->uidx_table[tind].table[uidx & MLX5_UIDX_TABLE_MASK] = NULL; 210d6b92ffaSHans Petter Selasky 211d6b92ffaSHans Petter Selasky pthread_mutex_unlock(&ctx->uidx_table_mutex); 212d6b92ffaSHans Petter Selasky } 213d6b92ffaSHans Petter Selasky 214d6b92ffaSHans Petter Selasky static int mlx5_is_sandy_bridge(int *num_cores) 215d6b92ffaSHans Petter Selasky { 216d6b92ffaSHans Petter Selasky char line[128]; 217d6b92ffaSHans Petter Selasky FILE *fd; 218d6b92ffaSHans Petter Selasky int rc = 0; 219d6b92ffaSHans Petter Selasky int cur_cpu_family = -1; 220d6b92ffaSHans Petter Selasky int cur_cpu_model = -1; 221d6b92ffaSHans Petter Selasky 222d6b92ffaSHans Petter Selasky fd = fopen("/proc/cpuinfo", "r"); 223d6b92ffaSHans Petter Selasky if (!fd) 224d6b92ffaSHans Petter Selasky return 0; 225d6b92ffaSHans Petter Selasky 226d6b92ffaSHans Petter Selasky *num_cores = 0; 227d6b92ffaSHans Petter Selasky 228d6b92ffaSHans Petter Selasky while (fgets(line, 128, fd)) { 229d6b92ffaSHans Petter Selasky int value; 230d6b92ffaSHans Petter Selasky 231d6b92ffaSHans Petter Selasky /* if this is information on new processor */ 232d6b92ffaSHans Petter Selasky if (!strncmp(line, "processor", 9)) { 233d6b92ffaSHans Petter Selasky ++*num_cores; 234d6b92ffaSHans Petter Selasky 235d6b92ffaSHans Petter Selasky cur_cpu_family = -1; 236d6b92ffaSHans Petter Selasky cur_cpu_model = -1; 237d6b92ffaSHans Petter Selasky } else if (!strncmp(line, "cpu family", 10)) { 238d6b92ffaSHans Petter Selasky if ((cur_cpu_family < 0) && (!read_number_from_line(line, &value))) 239d6b92ffaSHans Petter Selasky cur_cpu_family = value; 240d6b92ffaSHans Petter Selasky } else if (!strncmp(line, "model", 5)) { 241d6b92ffaSHans Petter Selasky if ((cur_cpu_model < 0) && (!read_number_from_line(line, &value))) 242d6b92ffaSHans Petter Selasky cur_cpu_model = value; 243d6b92ffaSHans Petter Selasky } 244d6b92ffaSHans Petter Selasky 245d6b92ffaSHans Petter Selasky /* if this is a Sandy Bridge CPU */ 246d6b92ffaSHans Petter Selasky if ((cur_cpu_family == 6) && 247d6b92ffaSHans Petter Selasky (cur_cpu_model == 0x2A || (cur_cpu_model == 0x2D) )) 248d6b92ffaSHans Petter Selasky rc = 1; 249d6b92ffaSHans Petter Selasky } 250d6b92ffaSHans Petter Selasky 251d6b92ffaSHans Petter Selasky fclose(fd); 252d6b92ffaSHans Petter Selasky return rc; 253d6b92ffaSHans Petter Selasky } 254d6b92ffaSHans Petter Selasky 255d6b92ffaSHans Petter Selasky /* 256d6b92ffaSHans Petter Selasky man cpuset 257d6b92ffaSHans Petter Selasky 258d6b92ffaSHans Petter Selasky This format displays each 32-bit word in hexadecimal (using ASCII characters "0" - "9" and "a" - "f"); words 259d6b92ffaSHans Petter Selasky are filled with leading zeros, if required. For masks longer than one word, a comma separator is used between 260d6b92ffaSHans Petter Selasky words. Words are displayed in big-endian order, which has the most significant bit first. The hex digits 261d6b92ffaSHans Petter Selasky within a word are also in big-endian order. 262d6b92ffaSHans Petter Selasky 263d6b92ffaSHans Petter Selasky The number of 32-bit words displayed is the minimum number needed to display all bits of the bitmask, based on 264d6b92ffaSHans Petter Selasky the size of the bitmask. 265d6b92ffaSHans Petter Selasky 266d6b92ffaSHans Petter Selasky Examples of the Mask Format: 267d6b92ffaSHans Petter Selasky 268d6b92ffaSHans Petter Selasky 00000001 # just bit 0 set 269d6b92ffaSHans Petter Selasky 40000000,00000000,00000000 # just bit 94 set 270d6b92ffaSHans Petter Selasky 000000ff,00000000 # bits 32-39 set 271d6b92ffaSHans Petter Selasky 00000000,000E3862 # 1,5,6,11-13,17-19 set 272d6b92ffaSHans Petter Selasky 273d6b92ffaSHans Petter Selasky A mask with bits 0, 1, 2, 4, 8, 16, 32, and 64 set displays as: 274d6b92ffaSHans Petter Selasky 275d6b92ffaSHans Petter Selasky 00000001,00000001,00010117 276d6b92ffaSHans Petter Selasky 277d6b92ffaSHans Petter Selasky The first "1" is for bit 64, the second for bit 32, the third for bit 16, the fourth for bit 8, the fifth for 278d6b92ffaSHans Petter Selasky bit 4, and the "7" is for bits 2, 1, and 0. 279d6b92ffaSHans Petter Selasky */ 280d6b92ffaSHans Petter Selasky static void mlx5_local_cpu_set(struct ibv_device *ibdev, cpuset_t *cpu_set) 281d6b92ffaSHans Petter Selasky { 282d6b92ffaSHans Petter Selasky char *p, buf[1024]; 283d6b92ffaSHans Petter Selasky char *env_value; 284d6b92ffaSHans Petter Selasky uint32_t word; 285d6b92ffaSHans Petter Selasky int i, k; 286d6b92ffaSHans Petter Selasky 287d6b92ffaSHans Petter Selasky env_value = getenv("MLX5_LOCAL_CPUS"); 288d6b92ffaSHans Petter Selasky if (env_value) 289d6b92ffaSHans Petter Selasky strncpy(buf, env_value, sizeof(buf)); 290d6b92ffaSHans Petter Selasky else { 291d6b92ffaSHans Petter Selasky char fname[MAXPATHLEN]; 292d6b92ffaSHans Petter Selasky 293d6b92ffaSHans Petter Selasky snprintf(fname, MAXPATHLEN, "/sys/class/infiniband/%s", 294d6b92ffaSHans Petter Selasky ibv_get_device_name(ibdev)); 295d6b92ffaSHans Petter Selasky 296d6b92ffaSHans Petter Selasky if (ibv_read_sysfs_file(fname, "device/local_cpus", buf, sizeof(buf))) { 297d6b92ffaSHans Petter Selasky fprintf(stderr, PFX "Warning: can not get local cpu set: failed to open %s\n", fname); 298d6b92ffaSHans Petter Selasky return; 299d6b92ffaSHans Petter Selasky } 300d6b92ffaSHans Petter Selasky } 301d6b92ffaSHans Petter Selasky 302d6b92ffaSHans Petter Selasky p = strrchr(buf, ','); 303d6b92ffaSHans Petter Selasky if (!p) 304d6b92ffaSHans Petter Selasky p = buf; 305d6b92ffaSHans Petter Selasky 306d6b92ffaSHans Petter Selasky i = 0; 307d6b92ffaSHans Petter Selasky do { 308d6b92ffaSHans Petter Selasky if (*p == ',') { 309d6b92ffaSHans Petter Selasky *p = 0; 310d6b92ffaSHans Petter Selasky p ++; 311d6b92ffaSHans Petter Selasky } 312d6b92ffaSHans Petter Selasky 313d6b92ffaSHans Petter Selasky word = strtoul(p, NULL, 16); 314d6b92ffaSHans Petter Selasky 315d6b92ffaSHans Petter Selasky for (k = 0; word; ++k, word >>= 1) 316d6b92ffaSHans Petter Selasky if (word & 1) 317d6b92ffaSHans Petter Selasky CPU_SET(k+i, cpu_set); 318d6b92ffaSHans Petter Selasky 319d6b92ffaSHans Petter Selasky if (p == buf) 320d6b92ffaSHans Petter Selasky break; 321d6b92ffaSHans Petter Selasky 322d6b92ffaSHans Petter Selasky p = strrchr(buf, ','); 323d6b92ffaSHans Petter Selasky if (!p) 324d6b92ffaSHans Petter Selasky p = buf; 325d6b92ffaSHans Petter Selasky 326d6b92ffaSHans Petter Selasky i += 32; 327d6b92ffaSHans Petter Selasky } while (i < CPU_SETSIZE); 328d6b92ffaSHans Petter Selasky } 329d6b92ffaSHans Petter Selasky 330d6b92ffaSHans Petter Selasky static int mlx5_enable_sandy_bridge_fix(struct ibv_device *ibdev) 331d6b92ffaSHans Petter Selasky { 332d6b92ffaSHans Petter Selasky cpuset_t my_cpus, dev_local_cpus, result_set; 333d6b92ffaSHans Petter Selasky int stall_enable; 334d6b92ffaSHans Petter Selasky int ret; 335d6b92ffaSHans Petter Selasky int num_cores; 336d6b92ffaSHans Petter Selasky 337d6b92ffaSHans Petter Selasky if (!mlx5_is_sandy_bridge(&num_cores)) 338d6b92ffaSHans Petter Selasky return 0; 339d6b92ffaSHans Petter Selasky 340d6b92ffaSHans Petter Selasky /* by default enable stall on sandy bridge arch */ 341d6b92ffaSHans Petter Selasky stall_enable = 1; 342d6b92ffaSHans Petter Selasky 343d6b92ffaSHans Petter Selasky /* 344d6b92ffaSHans Petter Selasky * check if app is bound to cpu set that is inside 345d6b92ffaSHans Petter Selasky * of device local cpu set. Disable stalling if true 346d6b92ffaSHans Petter Selasky */ 347d6b92ffaSHans Petter Selasky 348d6b92ffaSHans Petter Selasky /* use static cpu set - up to CPU_SETSIZE (1024) cpus/node */ 349d6b92ffaSHans Petter Selasky CPU_ZERO(&my_cpus); 350d6b92ffaSHans Petter Selasky CPU_ZERO(&dev_local_cpus); 351d6b92ffaSHans Petter Selasky CPU_ZERO(&result_set); 352d6b92ffaSHans Petter Selasky ret = cpuset_getaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1, 353d6b92ffaSHans Petter Selasky sizeof(my_cpus), &my_cpus); 354d6b92ffaSHans Petter Selasky if (ret == -1) { 355d6b92ffaSHans Petter Selasky if (errno == EINVAL) 356d6b92ffaSHans Petter Selasky fprintf(stderr, PFX "Warning: my cpu set is too small\n"); 357d6b92ffaSHans Petter Selasky else 358d6b92ffaSHans Petter Selasky fprintf(stderr, PFX "Warning: failed to get my cpu set\n"); 359d6b92ffaSHans Petter Selasky goto out; 360d6b92ffaSHans Petter Selasky } 361d6b92ffaSHans Petter Selasky 362d6b92ffaSHans Petter Selasky /* get device local cpu set */ 363d6b92ffaSHans Petter Selasky mlx5_local_cpu_set(ibdev, &dev_local_cpus); 364d6b92ffaSHans Petter Selasky 365d6b92ffaSHans Petter Selasky /* check if my cpu set is in dev cpu */ 366d6b92ffaSHans Petter Selasky CPU_OR(&result_set, &my_cpus); 367d6b92ffaSHans Petter Selasky CPU_OR(&result_set, &dev_local_cpus); 368d6b92ffaSHans Petter Selasky stall_enable = CPU_EQUAL(&result_set, &dev_local_cpus) ? 0 : 1; 369d6b92ffaSHans Petter Selasky 370d6b92ffaSHans Petter Selasky out: 371d6b92ffaSHans Petter Selasky return stall_enable; 372d6b92ffaSHans Petter Selasky } 373d6b92ffaSHans Petter Selasky 374d6b92ffaSHans Petter Selasky static void mlx5_read_env(struct ibv_device *ibdev, struct mlx5_context *ctx) 375d6b92ffaSHans Petter Selasky { 376d6b92ffaSHans Petter Selasky char *env_value; 377d6b92ffaSHans Petter Selasky 378d6b92ffaSHans Petter Selasky env_value = getenv("MLX5_STALL_CQ_POLL"); 379d6b92ffaSHans Petter Selasky if (env_value) 380d6b92ffaSHans Petter Selasky /* check if cq stall is enforced by user */ 381d6b92ffaSHans Petter Selasky ctx->stall_enable = (strcmp(env_value, "0")) ? 1 : 0; 382d6b92ffaSHans Petter Selasky else 383d6b92ffaSHans Petter Selasky /* autodetect if we need to do cq polling */ 384d6b92ffaSHans Petter Selasky ctx->stall_enable = mlx5_enable_sandy_bridge_fix(ibdev); 385d6b92ffaSHans Petter Selasky 386d6b92ffaSHans Petter Selasky env_value = getenv("MLX5_STALL_NUM_LOOP"); 387d6b92ffaSHans Petter Selasky if (env_value) 388d6b92ffaSHans Petter Selasky mlx5_stall_num_loop = atoi(env_value); 389d6b92ffaSHans Petter Selasky 390d6b92ffaSHans Petter Selasky env_value = getenv("MLX5_STALL_CQ_POLL_MIN"); 391d6b92ffaSHans Petter Selasky if (env_value) 392d6b92ffaSHans Petter Selasky mlx5_stall_cq_poll_min = atoi(env_value); 393d6b92ffaSHans Petter Selasky 394d6b92ffaSHans Petter Selasky env_value = getenv("MLX5_STALL_CQ_POLL_MAX"); 395d6b92ffaSHans Petter Selasky if (env_value) 396d6b92ffaSHans Petter Selasky mlx5_stall_cq_poll_max = atoi(env_value); 397d6b92ffaSHans Petter Selasky 398d6b92ffaSHans Petter Selasky env_value = getenv("MLX5_STALL_CQ_INC_STEP"); 399d6b92ffaSHans Petter Selasky if (env_value) 400d6b92ffaSHans Petter Selasky mlx5_stall_cq_inc_step = atoi(env_value); 401d6b92ffaSHans Petter Selasky 402d6b92ffaSHans Petter Selasky env_value = getenv("MLX5_STALL_CQ_DEC_STEP"); 403d6b92ffaSHans Petter Selasky if (env_value) 404d6b92ffaSHans Petter Selasky mlx5_stall_cq_dec_step = atoi(env_value); 405d6b92ffaSHans Petter Selasky 406d6b92ffaSHans Petter Selasky ctx->stall_adaptive_enable = 0; 407d6b92ffaSHans Petter Selasky ctx->stall_cycles = 0; 408d6b92ffaSHans Petter Selasky 409d6b92ffaSHans Petter Selasky if (mlx5_stall_num_loop < 0) { 410d6b92ffaSHans Petter Selasky ctx->stall_adaptive_enable = 1; 411d6b92ffaSHans Petter Selasky ctx->stall_cycles = mlx5_stall_cq_poll_min; 412d6b92ffaSHans Petter Selasky } 413d6b92ffaSHans Petter Selasky 414d6b92ffaSHans Petter Selasky } 415d6b92ffaSHans Petter Selasky 416d6b92ffaSHans Petter Selasky static int get_total_uuars(int page_size) 417d6b92ffaSHans Petter Selasky { 418d6b92ffaSHans Petter Selasky int size = MLX5_DEF_TOT_UUARS; 419d6b92ffaSHans Petter Selasky int uuars_in_page; 420d6b92ffaSHans Petter Selasky char *env; 421d6b92ffaSHans Petter Selasky 422d6b92ffaSHans Petter Selasky env = getenv("MLX5_TOTAL_UUARS"); 423d6b92ffaSHans Petter Selasky if (env) 424d6b92ffaSHans Petter Selasky size = atoi(env); 425d6b92ffaSHans Petter Selasky 426d6b92ffaSHans Petter Selasky if (size < 1) 427d6b92ffaSHans Petter Selasky return -EINVAL; 428d6b92ffaSHans Petter Selasky 429d6b92ffaSHans Petter Selasky uuars_in_page = page_size / MLX5_ADAPTER_PAGE_SIZE * MLX5_NUM_NON_FP_BFREGS_PER_UAR; 430d6b92ffaSHans Petter Selasky size = max(uuars_in_page, size); 431d6b92ffaSHans Petter Selasky size = align(size, MLX5_NUM_NON_FP_BFREGS_PER_UAR); 432d6b92ffaSHans Petter Selasky if (size > MLX5_MAX_BFREGS) 433d6b92ffaSHans Petter Selasky return -ENOMEM; 434d6b92ffaSHans Petter Selasky 435d6b92ffaSHans Petter Selasky return size; 436d6b92ffaSHans Petter Selasky } 437d6b92ffaSHans Petter Selasky 438d6b92ffaSHans Petter Selasky static void open_debug_file(struct mlx5_context *ctx) 439d6b92ffaSHans Petter Selasky { 440d6b92ffaSHans Petter Selasky char *env; 441d6b92ffaSHans Petter Selasky 442d6b92ffaSHans Petter Selasky env = getenv("MLX5_DEBUG_FILE"); 443d6b92ffaSHans Petter Selasky if (!env) { 444d6b92ffaSHans Petter Selasky ctx->dbg_fp = stderr; 445d6b92ffaSHans Petter Selasky return; 446d6b92ffaSHans Petter Selasky } 447d6b92ffaSHans Petter Selasky 448d6b92ffaSHans Petter Selasky ctx->dbg_fp = fopen(env, "aw+"); 449d6b92ffaSHans Petter Selasky if (!ctx->dbg_fp) { 450d6b92ffaSHans Petter Selasky fprintf(stderr, "Failed opening debug file %s, using stderr\n", env); 451d6b92ffaSHans Petter Selasky ctx->dbg_fp = stderr; 452d6b92ffaSHans Petter Selasky return; 453d6b92ffaSHans Petter Selasky } 454d6b92ffaSHans Petter Selasky } 455d6b92ffaSHans Petter Selasky 456d6b92ffaSHans Petter Selasky static void close_debug_file(struct mlx5_context *ctx) 457d6b92ffaSHans Petter Selasky { 458d6b92ffaSHans Petter Selasky if (ctx->dbg_fp && ctx->dbg_fp != stderr) 459d6b92ffaSHans Petter Selasky fclose(ctx->dbg_fp); 460d6b92ffaSHans Petter Selasky } 461d6b92ffaSHans Petter Selasky 462d6b92ffaSHans Petter Selasky static void set_debug_mask(void) 463d6b92ffaSHans Petter Selasky { 464d6b92ffaSHans Petter Selasky char *env; 465d6b92ffaSHans Petter Selasky 466d6b92ffaSHans Petter Selasky env = getenv("MLX5_DEBUG_MASK"); 467d6b92ffaSHans Petter Selasky if (env) 468d6b92ffaSHans Petter Selasky mlx5_debug_mask = strtol(env, NULL, 0); 469d6b92ffaSHans Petter Selasky } 470d6b92ffaSHans Petter Selasky 471d6b92ffaSHans Petter Selasky static void set_freeze_on_error(void) 472d6b92ffaSHans Petter Selasky { 473d6b92ffaSHans Petter Selasky char *env; 474d6b92ffaSHans Petter Selasky 475d6b92ffaSHans Petter Selasky env = getenv("MLX5_FREEZE_ON_ERROR_CQE"); 476d6b92ffaSHans Petter Selasky if (env) 477d6b92ffaSHans Petter Selasky mlx5_freeze_on_error_cqe = strtol(env, NULL, 0); 478d6b92ffaSHans Petter Selasky } 479d6b92ffaSHans Petter Selasky 480d6b92ffaSHans Petter Selasky static int get_always_bf(void) 481d6b92ffaSHans Petter Selasky { 482d6b92ffaSHans Petter Selasky char *env; 483d6b92ffaSHans Petter Selasky 484d6b92ffaSHans Petter Selasky env = getenv("MLX5_POST_SEND_PREFER_BF"); 485d6b92ffaSHans Petter Selasky if (!env) 486d6b92ffaSHans Petter Selasky return 1; 487d6b92ffaSHans Petter Selasky 488d6b92ffaSHans Petter Selasky return strcmp(env, "0") ? 1 : 0; 489d6b92ffaSHans Petter Selasky } 490d6b92ffaSHans Petter Selasky 491d6b92ffaSHans Petter Selasky static int get_shut_up_bf(void) 492d6b92ffaSHans Petter Selasky { 493d6b92ffaSHans Petter Selasky char *env; 494d6b92ffaSHans Petter Selasky 495d6b92ffaSHans Petter Selasky env = getenv("MLX5_SHUT_UP_BF"); 496d6b92ffaSHans Petter Selasky if (!env) 497d6b92ffaSHans Petter Selasky return 0; 498d6b92ffaSHans Petter Selasky 499d6b92ffaSHans Petter Selasky return strcmp(env, "0") ? 1 : 0; 500d6b92ffaSHans Petter Selasky } 501d6b92ffaSHans Petter Selasky 502d6b92ffaSHans Petter Selasky static int get_num_low_lat_uuars(int tot_uuars) 503d6b92ffaSHans Petter Selasky { 504d6b92ffaSHans Petter Selasky char *env; 505d6b92ffaSHans Petter Selasky int num = 4; 506d6b92ffaSHans Petter Selasky 507d6b92ffaSHans Petter Selasky env = getenv("MLX5_NUM_LOW_LAT_UUARS"); 508d6b92ffaSHans Petter Selasky if (env) 509d6b92ffaSHans Petter Selasky num = atoi(env); 510d6b92ffaSHans Petter Selasky 511d6b92ffaSHans Petter Selasky if (num < 0) 512d6b92ffaSHans Petter Selasky return -EINVAL; 513d6b92ffaSHans Petter Selasky 514d6b92ffaSHans Petter Selasky num = max(num, tot_uuars - MLX5_MED_BFREGS_TSHOLD); 515d6b92ffaSHans Petter Selasky return num; 516d6b92ffaSHans Petter Selasky } 517d6b92ffaSHans Petter Selasky 518d6b92ffaSHans Petter Selasky /* The library allocates an array of uuar contexts. The one in index zero does 519d6b92ffaSHans Petter Selasky * not to execersize odd/even policy so it can avoid a lock but it may not use 520d6b92ffaSHans Petter Selasky * blue flame. The upper ones, low_lat_uuars can use blue flame with no lock 521d6b92ffaSHans Petter Selasky * since they are assigned to one QP only. The rest can use blue flame but since 522d6b92ffaSHans Petter Selasky * they are shared they need a lock 523d6b92ffaSHans Petter Selasky */ 524d6b92ffaSHans Petter Selasky static int need_uuar_lock(struct mlx5_context *ctx, int uuarn) 525d6b92ffaSHans Petter Selasky { 526d6b92ffaSHans Petter Selasky if (uuarn == 0 || mlx5_single_threaded) 527d6b92ffaSHans Petter Selasky return 0; 528d6b92ffaSHans Petter Selasky 529d6b92ffaSHans Petter Selasky if (uuarn >= (ctx->tot_uuars - ctx->low_lat_uuars) * 2) 530d6b92ffaSHans Petter Selasky return 0; 531d6b92ffaSHans Petter Selasky 532d6b92ffaSHans Petter Selasky return 1; 533d6b92ffaSHans Petter Selasky } 534d6b92ffaSHans Petter Selasky 535d6b92ffaSHans Petter Selasky static int single_threaded_app(void) 536d6b92ffaSHans Petter Selasky { 537d6b92ffaSHans Petter Selasky 538d6b92ffaSHans Petter Selasky char *env; 539d6b92ffaSHans Petter Selasky 540d6b92ffaSHans Petter Selasky env = getenv("MLX5_SINGLE_THREADED"); 541d6b92ffaSHans Petter Selasky if (env) 542d6b92ffaSHans Petter Selasky return strcmp(env, "1") ? 0 : 1; 543d6b92ffaSHans Petter Selasky 544d6b92ffaSHans Petter Selasky return 0; 545d6b92ffaSHans Petter Selasky } 546d6b92ffaSHans Petter Selasky 547d6b92ffaSHans Petter Selasky static int mlx5_cmd_get_context(struct mlx5_context *context, 548d6b92ffaSHans Petter Selasky struct mlx5_alloc_ucontext *req, 549d6b92ffaSHans Petter Selasky size_t req_len, 550d6b92ffaSHans Petter Selasky struct mlx5_alloc_ucontext_resp *resp, 551d6b92ffaSHans Petter Selasky size_t resp_len) 552d6b92ffaSHans Petter Selasky { 553d6b92ffaSHans Petter Selasky if (!ibv_cmd_get_context(&context->ibv_ctx, &req->ibv_req, 554d6b92ffaSHans Petter Selasky req_len, &resp->ibv_resp, resp_len)) 555d6b92ffaSHans Petter Selasky return 0; 556d6b92ffaSHans Petter Selasky 557d6b92ffaSHans Petter Selasky /* The ibv_cmd_get_context fails in older kernels when passing 558d6b92ffaSHans Petter Selasky * a request length that the kernel doesn't know. 559d6b92ffaSHans Petter Selasky * To avoid breaking compatibility of new libmlx5 and older 560d6b92ffaSHans Petter Selasky * kernels, when ibv_cmd_get_context fails with the full 561d6b92ffaSHans Petter Selasky * request length, we try once again with the legacy length. 562d6b92ffaSHans Petter Selasky * We repeat this process while reducing requested size based 563d6b92ffaSHans Petter Selasky * on the feature input size. To avoid this in the future, we 564d6b92ffaSHans Petter Selasky * will remove the check in kernel that requires fields unknown 565d6b92ffaSHans Petter Selasky * to the kernel to be cleared. This will require that any new 566d6b92ffaSHans Petter Selasky * feature that involves extending struct mlx5_alloc_ucontext 567d6b92ffaSHans Petter Selasky * will be accompanied by an indication in the form of one or 568d6b92ffaSHans Petter Selasky * more fields in struct mlx5_alloc_ucontext_resp. If the 569d6b92ffaSHans Petter Selasky * response value can be interpreted as feature not supported 570d6b92ffaSHans Petter Selasky * when the returned value is zero, this will suffice to 571d6b92ffaSHans Petter Selasky * indicate to the library that the request was ignored by the 572d6b92ffaSHans Petter Selasky * kernel, either because it is unaware or because it decided 573d6b92ffaSHans Petter Selasky * to do so. If zero is a valid response, we will add a new 574d6b92ffaSHans Petter Selasky * field that indicates whether the request was handled. 575d6b92ffaSHans Petter Selasky */ 576d6b92ffaSHans Petter Selasky if (!ibv_cmd_get_context(&context->ibv_ctx, &req->ibv_req, 577d6b92ffaSHans Petter Selasky offsetof(struct mlx5_alloc_ucontext, lib_caps), 578d6b92ffaSHans Petter Selasky &resp->ibv_resp, resp_len)) 579d6b92ffaSHans Petter Selasky return 0; 580d6b92ffaSHans Petter Selasky 581d6b92ffaSHans Petter Selasky return ibv_cmd_get_context(&context->ibv_ctx, &req->ibv_req, 582d6b92ffaSHans Petter Selasky offsetof(struct mlx5_alloc_ucontext, 583d6b92ffaSHans Petter Selasky cqe_version), 584d6b92ffaSHans Petter Selasky &resp->ibv_resp, resp_len); 585d6b92ffaSHans Petter Selasky } 586d6b92ffaSHans Petter Selasky 587d6b92ffaSHans Petter Selasky static int mlx5_map_internal_clock(struct mlx5_device *mdev, 588d6b92ffaSHans Petter Selasky struct ibv_context *ibv_ctx) 589d6b92ffaSHans Petter Selasky { 590d6b92ffaSHans Petter Selasky struct mlx5_context *context = to_mctx(ibv_ctx); 591d6b92ffaSHans Petter Selasky void *hca_clock_page; 592d6b92ffaSHans Petter Selasky off_t offset = 0; 593d6b92ffaSHans Petter Selasky 594d6b92ffaSHans Petter Selasky set_command(MLX5_MMAP_GET_CORE_CLOCK_CMD, &offset); 595d6b92ffaSHans Petter Selasky hca_clock_page = mmap(NULL, mdev->page_size, 596d6b92ffaSHans Petter Selasky PROT_READ, MAP_SHARED, ibv_ctx->cmd_fd, 597d6b92ffaSHans Petter Selasky mdev->page_size * offset); 598d6b92ffaSHans Petter Selasky 599d6b92ffaSHans Petter Selasky if (hca_clock_page == MAP_FAILED) { 600d6b92ffaSHans Petter Selasky fprintf(stderr, PFX 601d6b92ffaSHans Petter Selasky "Warning: Timestamp available,\n" 602d6b92ffaSHans Petter Selasky "but failed to mmap() hca core clock page.\n"); 603d6b92ffaSHans Petter Selasky return -1; 604d6b92ffaSHans Petter Selasky } 605d6b92ffaSHans Petter Selasky 606d6b92ffaSHans Petter Selasky context->hca_core_clock = hca_clock_page + 607d6b92ffaSHans Petter Selasky (context->core_clock.offset & (mdev->page_size - 1)); 608d6b92ffaSHans Petter Selasky return 0; 609d6b92ffaSHans Petter Selasky } 610d6b92ffaSHans Petter Selasky 611d6b92ffaSHans Petter Selasky int mlx5dv_query_device(struct ibv_context *ctx_in, 612d6b92ffaSHans Petter Selasky struct mlx5dv_context *attrs_out) 613d6b92ffaSHans Petter Selasky { 614d6b92ffaSHans Petter Selasky struct mlx5_context *mctx = to_mctx(ctx_in); 615d6b92ffaSHans Petter Selasky uint64_t comp_mask_out = 0; 616d6b92ffaSHans Petter Selasky 617d6b92ffaSHans Petter Selasky attrs_out->version = 0; 618d6b92ffaSHans Petter Selasky attrs_out->flags = 0; 619d6b92ffaSHans Petter Selasky 620d6b92ffaSHans Petter Selasky if (mctx->cqe_version == MLX5_CQE_VERSION_V1) 621d6b92ffaSHans Petter Selasky attrs_out->flags |= MLX5DV_CONTEXT_FLAGS_CQE_V1; 622d6b92ffaSHans Petter Selasky 623d6b92ffaSHans Petter Selasky if (mctx->vendor_cap_flags & MLX5_VENDOR_CAP_FLAGS_MPW) 624d6b92ffaSHans Petter Selasky attrs_out->flags |= MLX5DV_CONTEXT_FLAGS_MPW; 625d6b92ffaSHans Petter Selasky 626d6b92ffaSHans Petter Selasky if (attrs_out->comp_mask & MLX5DV_CONTEXT_MASK_CQE_COMPRESION) { 627d6b92ffaSHans Petter Selasky attrs_out->cqe_comp_caps = mctx->cqe_comp_caps; 628d6b92ffaSHans Petter Selasky comp_mask_out |= MLX5DV_CONTEXT_MASK_CQE_COMPRESION; 629d6b92ffaSHans Petter Selasky } 630d6b92ffaSHans Petter Selasky 631d6b92ffaSHans Petter Selasky attrs_out->comp_mask = comp_mask_out; 632d6b92ffaSHans Petter Selasky 633d6b92ffaSHans Petter Selasky return 0; 634d6b92ffaSHans Petter Selasky } 635d6b92ffaSHans Petter Selasky 636d6b92ffaSHans Petter Selasky static int mlx5dv_get_qp(struct ibv_qp *qp_in, 637d6b92ffaSHans Petter Selasky struct mlx5dv_qp *qp_out) 638d6b92ffaSHans Petter Selasky { 639d6b92ffaSHans Petter Selasky struct mlx5_qp *mqp = to_mqp(qp_in); 640d6b92ffaSHans Petter Selasky 641d6b92ffaSHans Petter Selasky qp_out->comp_mask = 0; 642d6b92ffaSHans Petter Selasky qp_out->dbrec = mqp->db; 643d6b92ffaSHans Petter Selasky 644d6b92ffaSHans Petter Selasky if (mqp->sq_buf_size) 645d6b92ffaSHans Petter Selasky /* IBV_QPT_RAW_PACKET */ 646d6b92ffaSHans Petter Selasky qp_out->sq.buf = (void *)((uintptr_t)mqp->sq_buf.buf); 647d6b92ffaSHans Petter Selasky else 648d6b92ffaSHans Petter Selasky qp_out->sq.buf = (void *)((uintptr_t)mqp->buf.buf + mqp->sq.offset); 649d6b92ffaSHans Petter Selasky qp_out->sq.wqe_cnt = mqp->sq.wqe_cnt; 650d6b92ffaSHans Petter Selasky qp_out->sq.stride = 1 << mqp->sq.wqe_shift; 651d6b92ffaSHans Petter Selasky 652d6b92ffaSHans Petter Selasky qp_out->rq.buf = (void *)((uintptr_t)mqp->buf.buf + mqp->rq.offset); 653d6b92ffaSHans Petter Selasky qp_out->rq.wqe_cnt = mqp->rq.wqe_cnt; 654d6b92ffaSHans Petter Selasky qp_out->rq.stride = 1 << mqp->rq.wqe_shift; 655d6b92ffaSHans Petter Selasky 656d6b92ffaSHans Petter Selasky qp_out->bf.reg = mqp->bf->reg; 657d6b92ffaSHans Petter Selasky 658d6b92ffaSHans Petter Selasky if (mqp->bf->uuarn > 0) 659d6b92ffaSHans Petter Selasky qp_out->bf.size = mqp->bf->buf_size; 660d6b92ffaSHans Petter Selasky else 661d6b92ffaSHans Petter Selasky qp_out->bf.size = 0; 662d6b92ffaSHans Petter Selasky 663d6b92ffaSHans Petter Selasky return 0; 664d6b92ffaSHans Petter Selasky } 665d6b92ffaSHans Petter Selasky 666d6b92ffaSHans Petter Selasky static int mlx5dv_get_cq(struct ibv_cq *cq_in, 667d6b92ffaSHans Petter Selasky struct mlx5dv_cq *cq_out) 668d6b92ffaSHans Petter Selasky { 669d6b92ffaSHans Petter Selasky struct mlx5_cq *mcq = to_mcq(cq_in); 670d6b92ffaSHans Petter Selasky struct mlx5_context *mctx = to_mctx(cq_in->context); 671d6b92ffaSHans Petter Selasky 672d6b92ffaSHans Petter Selasky cq_out->comp_mask = 0; 673d6b92ffaSHans Petter Selasky cq_out->cqn = mcq->cqn; 674d6b92ffaSHans Petter Selasky cq_out->cqe_cnt = mcq->ibv_cq.cqe + 1; 675d6b92ffaSHans Petter Selasky cq_out->cqe_size = mcq->cqe_sz; 676d6b92ffaSHans Petter Selasky cq_out->buf = mcq->active_buf->buf; 677d6b92ffaSHans Petter Selasky cq_out->dbrec = mcq->dbrec; 678d6b92ffaSHans Petter Selasky cq_out->uar = mctx->uar; 679d6b92ffaSHans Petter Selasky 680d6b92ffaSHans Petter Selasky mcq->flags |= MLX5_CQ_FLAGS_DV_OWNED; 681d6b92ffaSHans Petter Selasky 682d6b92ffaSHans Petter Selasky return 0; 683d6b92ffaSHans Petter Selasky } 684d6b92ffaSHans Petter Selasky 685d6b92ffaSHans Petter Selasky static int mlx5dv_get_rwq(struct ibv_wq *wq_in, 686d6b92ffaSHans Petter Selasky struct mlx5dv_rwq *rwq_out) 687d6b92ffaSHans Petter Selasky { 688d6b92ffaSHans Petter Selasky struct mlx5_rwq *mrwq = to_mrwq(wq_in); 689d6b92ffaSHans Petter Selasky 690d6b92ffaSHans Petter Selasky rwq_out->comp_mask = 0; 691d6b92ffaSHans Petter Selasky rwq_out->buf = mrwq->pbuff; 692d6b92ffaSHans Petter Selasky rwq_out->dbrec = mrwq->recv_db; 693d6b92ffaSHans Petter Selasky rwq_out->wqe_cnt = mrwq->rq.wqe_cnt; 694d6b92ffaSHans Petter Selasky rwq_out->stride = 1 << mrwq->rq.wqe_shift; 695d6b92ffaSHans Petter Selasky 696d6b92ffaSHans Petter Selasky return 0; 697d6b92ffaSHans Petter Selasky } 698d6b92ffaSHans Petter Selasky 699d6b92ffaSHans Petter Selasky static int mlx5dv_get_srq(struct ibv_srq *srq_in, 700d6b92ffaSHans Petter Selasky struct mlx5dv_srq *srq_out) 701d6b92ffaSHans Petter Selasky { 702d6b92ffaSHans Petter Selasky struct mlx5_srq *msrq; 703d6b92ffaSHans Petter Selasky 704d6b92ffaSHans Petter Selasky msrq = container_of(srq_in, struct mlx5_srq, vsrq.srq); 705d6b92ffaSHans Petter Selasky 706d6b92ffaSHans Petter Selasky srq_out->comp_mask = 0; 707d6b92ffaSHans Petter Selasky srq_out->buf = msrq->buf.buf; 708d6b92ffaSHans Petter Selasky srq_out->dbrec = msrq->db; 709d6b92ffaSHans Petter Selasky srq_out->stride = 1 << msrq->wqe_shift; 710d6b92ffaSHans Petter Selasky srq_out->head = msrq->head; 711d6b92ffaSHans Petter Selasky srq_out->tail = msrq->tail; 712d6b92ffaSHans Petter Selasky 713d6b92ffaSHans Petter Selasky return 0; 714d6b92ffaSHans Petter Selasky } 715d6b92ffaSHans Petter Selasky 716d6b92ffaSHans Petter Selasky int mlx5dv_init_obj(struct mlx5dv_obj *obj, uint64_t obj_type) 717d6b92ffaSHans Petter Selasky { 718d6b92ffaSHans Petter Selasky int ret = 0; 719d6b92ffaSHans Petter Selasky 720d6b92ffaSHans Petter Selasky if (obj_type & MLX5DV_OBJ_QP) 721d6b92ffaSHans Petter Selasky ret = mlx5dv_get_qp(obj->qp.in, obj->qp.out); 722d6b92ffaSHans Petter Selasky if (!ret && (obj_type & MLX5DV_OBJ_CQ)) 723d6b92ffaSHans Petter Selasky ret = mlx5dv_get_cq(obj->cq.in, obj->cq.out); 724d6b92ffaSHans Petter Selasky if (!ret && (obj_type & MLX5DV_OBJ_SRQ)) 725d6b92ffaSHans Petter Selasky ret = mlx5dv_get_srq(obj->srq.in, obj->srq.out); 726d6b92ffaSHans Petter Selasky if (!ret && (obj_type & MLX5DV_OBJ_RWQ)) 727d6b92ffaSHans Petter Selasky ret = mlx5dv_get_rwq(obj->rwq.in, obj->rwq.out); 728d6b92ffaSHans Petter Selasky 729d6b92ffaSHans Petter Selasky return ret; 730d6b92ffaSHans Petter Selasky } 731d6b92ffaSHans Petter Selasky 732d6b92ffaSHans Petter Selasky static void adjust_uar_info(struct mlx5_device *mdev, 733d6b92ffaSHans Petter Selasky struct mlx5_context *context, 734d6b92ffaSHans Petter Selasky struct mlx5_alloc_ucontext_resp resp) 735d6b92ffaSHans Petter Selasky { 736d6b92ffaSHans Petter Selasky if (!resp.log_uar_size && !resp.num_uars_per_page) { 737d6b92ffaSHans Petter Selasky /* old kernel */ 738d6b92ffaSHans Petter Selasky context->uar_size = mdev->page_size; 739d6b92ffaSHans Petter Selasky context->num_uars_per_page = 1; 740d6b92ffaSHans Petter Selasky return; 741d6b92ffaSHans Petter Selasky } 742d6b92ffaSHans Petter Selasky 743d6b92ffaSHans Petter Selasky context->uar_size = 1 << resp.log_uar_size; 744d6b92ffaSHans Petter Selasky context->num_uars_per_page = resp.num_uars_per_page; 745d6b92ffaSHans Petter Selasky } 746d6b92ffaSHans Petter Selasky 747d6b92ffaSHans Petter Selasky static int mlx5_init_context(struct verbs_device *vdev, 748d6b92ffaSHans Petter Selasky struct ibv_context *ctx, int cmd_fd) 749d6b92ffaSHans Petter Selasky { 750d6b92ffaSHans Petter Selasky struct mlx5_context *context; 751d6b92ffaSHans Petter Selasky struct mlx5_alloc_ucontext req; 752d6b92ffaSHans Petter Selasky struct mlx5_alloc_ucontext_resp resp; 753d6b92ffaSHans Petter Selasky int i; 754d6b92ffaSHans Petter Selasky int page_size; 755d6b92ffaSHans Petter Selasky int tot_uuars; 756d6b92ffaSHans Petter Selasky int low_lat_uuars; 757d6b92ffaSHans Petter Selasky int gross_uuars; 758d6b92ffaSHans Petter Selasky int j; 759d6b92ffaSHans Petter Selasky off_t offset; 760d6b92ffaSHans Petter Selasky struct mlx5_device *mdev; 761d6b92ffaSHans Petter Selasky struct verbs_context *v_ctx; 762d6b92ffaSHans Petter Selasky struct ibv_port_attr port_attr; 763d6b92ffaSHans Petter Selasky struct ibv_device_attr_ex device_attr; 764d6b92ffaSHans Petter Selasky int k; 765d6b92ffaSHans Petter Selasky int bfi; 766d6b92ffaSHans Petter Selasky int num_sys_page_map; 767d6b92ffaSHans Petter Selasky 768d6b92ffaSHans Petter Selasky mdev = to_mdev(&vdev->device); 769d6b92ffaSHans Petter Selasky v_ctx = verbs_get_ctx(ctx); 770d6b92ffaSHans Petter Selasky page_size = mdev->page_size; 771d6b92ffaSHans Petter Selasky mlx5_single_threaded = single_threaded_app(); 772d6b92ffaSHans Petter Selasky 773d6b92ffaSHans Petter Selasky context = to_mctx(ctx); 774d6b92ffaSHans Petter Selasky context->ibv_ctx.cmd_fd = cmd_fd; 775d6b92ffaSHans Petter Selasky 776d6b92ffaSHans Petter Selasky open_debug_file(context); 777d6b92ffaSHans Petter Selasky set_debug_mask(); 778d6b92ffaSHans Petter Selasky set_freeze_on_error(); 779d6b92ffaSHans Petter Selasky if (gethostname(context->hostname, sizeof(context->hostname))) 780d6b92ffaSHans Petter Selasky strcpy(context->hostname, "host_unknown"); 781d6b92ffaSHans Petter Selasky 782d6b92ffaSHans Petter Selasky tot_uuars = get_total_uuars(page_size); 783d6b92ffaSHans Petter Selasky if (tot_uuars < 0) { 784d6b92ffaSHans Petter Selasky errno = -tot_uuars; 785d6b92ffaSHans Petter Selasky goto err_free; 786d6b92ffaSHans Petter Selasky } 787d6b92ffaSHans Petter Selasky 788d6b92ffaSHans Petter Selasky low_lat_uuars = get_num_low_lat_uuars(tot_uuars); 789d6b92ffaSHans Petter Selasky if (low_lat_uuars < 0) { 790d6b92ffaSHans Petter Selasky errno = -low_lat_uuars; 791d6b92ffaSHans Petter Selasky goto err_free; 792d6b92ffaSHans Petter Selasky } 793d6b92ffaSHans Petter Selasky 794d6b92ffaSHans Petter Selasky if (low_lat_uuars > tot_uuars - 1) { 795d6b92ffaSHans Petter Selasky errno = ENOMEM; 796d6b92ffaSHans Petter Selasky goto err_free; 797d6b92ffaSHans Petter Selasky } 798d6b92ffaSHans Petter Selasky 799d6b92ffaSHans Petter Selasky memset(&req, 0, sizeof(req)); 800d6b92ffaSHans Petter Selasky memset(&resp, 0, sizeof(resp)); 801d6b92ffaSHans Petter Selasky 802d6b92ffaSHans Petter Selasky req.total_num_uuars = tot_uuars; 803d6b92ffaSHans Petter Selasky req.num_low_latency_uuars = low_lat_uuars; 804d6b92ffaSHans Petter Selasky req.cqe_version = MLX5_CQE_VERSION_V1; 805d6b92ffaSHans Petter Selasky req.lib_caps |= MLX5_LIB_CAP_4K_UAR; 806d6b92ffaSHans Petter Selasky 807d6b92ffaSHans Petter Selasky if (mlx5_cmd_get_context(context, &req, sizeof(req), &resp, 808d6b92ffaSHans Petter Selasky sizeof(resp))) 809d6b92ffaSHans Petter Selasky goto err_free; 810d6b92ffaSHans Petter Selasky 811d6b92ffaSHans Petter Selasky context->max_num_qps = resp.qp_tab_size; 812d6b92ffaSHans Petter Selasky context->bf_reg_size = resp.bf_reg_size; 813d6b92ffaSHans Petter Selasky context->tot_uuars = resp.tot_uuars; 814d6b92ffaSHans Petter Selasky context->low_lat_uuars = low_lat_uuars; 815d6b92ffaSHans Petter Selasky context->cache_line_size = resp.cache_line_size; 816d6b92ffaSHans Petter Selasky context->max_sq_desc_sz = resp.max_sq_desc_sz; 817d6b92ffaSHans Petter Selasky context->max_rq_desc_sz = resp.max_rq_desc_sz; 818d6b92ffaSHans Petter Selasky context->max_send_wqebb = resp.max_send_wqebb; 819d6b92ffaSHans Petter Selasky context->num_ports = resp.num_ports; 820d6b92ffaSHans Petter Selasky context->max_recv_wr = resp.max_recv_wr; 821d6b92ffaSHans Petter Selasky context->max_srq_recv_wr = resp.max_srq_recv_wr; 822d6b92ffaSHans Petter Selasky 823d6b92ffaSHans Petter Selasky context->cqe_version = resp.cqe_version; 824d6b92ffaSHans Petter Selasky if (context->cqe_version) { 825d6b92ffaSHans Petter Selasky if (context->cqe_version == MLX5_CQE_VERSION_V1) 826d6b92ffaSHans Petter Selasky mlx5_ctx_ops.poll_cq = mlx5_poll_cq_v1; 827d6b92ffaSHans Petter Selasky else 828d6b92ffaSHans Petter Selasky goto err_free; 829d6b92ffaSHans Petter Selasky } 830d6b92ffaSHans Petter Selasky 831d6b92ffaSHans Petter Selasky adjust_uar_info(mdev, context, resp); 832d6b92ffaSHans Petter Selasky 833d6b92ffaSHans Petter Selasky gross_uuars = context->tot_uuars / MLX5_NUM_NON_FP_BFREGS_PER_UAR * NUM_BFREGS_PER_UAR; 834d6b92ffaSHans Petter Selasky context->bfs = calloc(gross_uuars, sizeof(*context->bfs)); 835d6b92ffaSHans Petter Selasky if (!context->bfs) { 836d6b92ffaSHans Petter Selasky errno = ENOMEM; 837d6b92ffaSHans Petter Selasky goto err_free; 838d6b92ffaSHans Petter Selasky } 839d6b92ffaSHans Petter Selasky 840d6b92ffaSHans Petter Selasky context->cmds_supp_uhw = resp.cmds_supp_uhw; 841d6b92ffaSHans Petter Selasky context->vendor_cap_flags = 0; 842d6b92ffaSHans Petter Selasky 843d6b92ffaSHans Petter Selasky pthread_mutex_init(&context->qp_table_mutex, NULL); 844d6b92ffaSHans Petter Selasky pthread_mutex_init(&context->srq_table_mutex, NULL); 845d6b92ffaSHans Petter Selasky pthread_mutex_init(&context->uidx_table_mutex, NULL); 846d6b92ffaSHans Petter Selasky for (i = 0; i < MLX5_QP_TABLE_SIZE; ++i) 847d6b92ffaSHans Petter Selasky context->qp_table[i].refcnt = 0; 848d6b92ffaSHans Petter Selasky 849d6b92ffaSHans Petter Selasky for (i = 0; i < MLX5_QP_TABLE_SIZE; ++i) 850d6b92ffaSHans Petter Selasky context->uidx_table[i].refcnt = 0; 851d6b92ffaSHans Petter Selasky 852d6b92ffaSHans Petter Selasky context->db_list = NULL; 853d6b92ffaSHans Petter Selasky 854d6b92ffaSHans Petter Selasky pthread_mutex_init(&context->db_list_mutex, NULL); 855d6b92ffaSHans Petter Selasky 856d6b92ffaSHans Petter Selasky num_sys_page_map = context->tot_uuars / (context->num_uars_per_page * MLX5_NUM_NON_FP_BFREGS_PER_UAR); 857d6b92ffaSHans Petter Selasky for (i = 0; i < num_sys_page_map; ++i) { 858d6b92ffaSHans Petter Selasky offset = 0; 859d6b92ffaSHans Petter Selasky set_command(MLX5_MMAP_GET_REGULAR_PAGES_CMD, &offset); 860d6b92ffaSHans Petter Selasky set_index(i, &offset); 861d6b92ffaSHans Petter Selasky context->uar[i] = mmap(NULL, page_size, PROT_WRITE, MAP_SHARED, 862d6b92ffaSHans Petter Selasky cmd_fd, page_size * offset); 863d6b92ffaSHans Petter Selasky if (context->uar[i] == MAP_FAILED) { 864d6b92ffaSHans Petter Selasky context->uar[i] = NULL; 865d6b92ffaSHans Petter Selasky goto err_free_bf; 866d6b92ffaSHans Petter Selasky } 867d6b92ffaSHans Petter Selasky } 868d6b92ffaSHans Petter Selasky 869d6b92ffaSHans Petter Selasky for (i = 0; i < num_sys_page_map; i++) { 870d6b92ffaSHans Petter Selasky for (j = 0; j < context->num_uars_per_page; j++) { 871d6b92ffaSHans Petter Selasky for (k = 0; k < NUM_BFREGS_PER_UAR; k++) { 872d6b92ffaSHans Petter Selasky bfi = (i * context->num_uars_per_page + j) * NUM_BFREGS_PER_UAR + k; 873d6b92ffaSHans Petter Selasky context->bfs[bfi].reg = context->uar[i] + MLX5_ADAPTER_PAGE_SIZE * j + 874d6b92ffaSHans Petter Selasky MLX5_BF_OFFSET + k * context->bf_reg_size; 875d6b92ffaSHans Petter Selasky context->bfs[bfi].need_lock = need_uuar_lock(context, bfi); 876d6b92ffaSHans Petter Selasky mlx5_spinlock_init(&context->bfs[bfi].lock); 877d6b92ffaSHans Petter Selasky context->bfs[bfi].offset = 0; 878d6b92ffaSHans Petter Selasky if (bfi) 879d6b92ffaSHans Petter Selasky context->bfs[bfi].buf_size = context->bf_reg_size / 2; 880d6b92ffaSHans Petter Selasky context->bfs[bfi].uuarn = bfi; 881d6b92ffaSHans Petter Selasky } 882d6b92ffaSHans Petter Selasky } 883d6b92ffaSHans Petter Selasky } 884d6b92ffaSHans Petter Selasky context->hca_core_clock = NULL; 885d6b92ffaSHans Petter Selasky if (resp.response_length + sizeof(resp.ibv_resp) >= 886d6b92ffaSHans Petter Selasky offsetof(struct mlx5_alloc_ucontext_resp, hca_core_clock_offset) + 887d6b92ffaSHans Petter Selasky sizeof(resp.hca_core_clock_offset) && 888d6b92ffaSHans Petter Selasky resp.comp_mask & MLX5_IB_ALLOC_UCONTEXT_RESP_MASK_CORE_CLOCK_OFFSET) { 889d6b92ffaSHans Petter Selasky context->core_clock.offset = resp.hca_core_clock_offset; 890d6b92ffaSHans Petter Selasky mlx5_map_internal_clock(mdev, ctx); 891d6b92ffaSHans Petter Selasky } 892d6b92ffaSHans Petter Selasky 893d6b92ffaSHans Petter Selasky mlx5_spinlock_init(&context->lock32); 894d6b92ffaSHans Petter Selasky 895d6b92ffaSHans Petter Selasky context->prefer_bf = get_always_bf(); 896d6b92ffaSHans Petter Selasky context->shut_up_bf = get_shut_up_bf(); 897d6b92ffaSHans Petter Selasky mlx5_read_env(&vdev->device, context); 898d6b92ffaSHans Petter Selasky 899d6b92ffaSHans Petter Selasky mlx5_spinlock_init(&context->hugetlb_lock); 900d6b92ffaSHans Petter Selasky TAILQ_INIT(&context->hugetlb_list); 901d6b92ffaSHans Petter Selasky 902d6b92ffaSHans Petter Selasky context->ibv_ctx.ops = mlx5_ctx_ops; 903d6b92ffaSHans Petter Selasky 904d6b92ffaSHans Petter Selasky verbs_set_ctx_op(v_ctx, create_qp_ex, mlx5_create_qp_ex); 905d6b92ffaSHans Petter Selasky verbs_set_ctx_op(v_ctx, open_xrcd, mlx5_open_xrcd); 906d6b92ffaSHans Petter Selasky verbs_set_ctx_op(v_ctx, close_xrcd, mlx5_close_xrcd); 907d6b92ffaSHans Petter Selasky verbs_set_ctx_op(v_ctx, create_srq_ex, mlx5_create_srq_ex); 908d6b92ffaSHans Petter Selasky verbs_set_ctx_op(v_ctx, get_srq_num, mlx5_get_srq_num); 909d6b92ffaSHans Petter Selasky verbs_set_ctx_op(v_ctx, query_device_ex, mlx5_query_device_ex); 910d6b92ffaSHans Petter Selasky verbs_set_ctx_op(v_ctx, query_rt_values, mlx5_query_rt_values); 911d6b92ffaSHans Petter Selasky verbs_set_ctx_op(v_ctx, ibv_create_flow, ibv_cmd_create_flow); 912d6b92ffaSHans Petter Selasky verbs_set_ctx_op(v_ctx, ibv_destroy_flow, ibv_cmd_destroy_flow); 913d6b92ffaSHans Petter Selasky verbs_set_ctx_op(v_ctx, create_cq_ex, mlx5_create_cq_ex); 914d6b92ffaSHans Petter Selasky verbs_set_ctx_op(v_ctx, create_wq, mlx5_create_wq); 915d6b92ffaSHans Petter Selasky verbs_set_ctx_op(v_ctx, modify_wq, mlx5_modify_wq); 916d6b92ffaSHans Petter Selasky verbs_set_ctx_op(v_ctx, destroy_wq, mlx5_destroy_wq); 917d6b92ffaSHans Petter Selasky verbs_set_ctx_op(v_ctx, create_rwq_ind_table, mlx5_create_rwq_ind_table); 918d6b92ffaSHans Petter Selasky verbs_set_ctx_op(v_ctx, destroy_rwq_ind_table, mlx5_destroy_rwq_ind_table); 919d6b92ffaSHans Petter Selasky 920d6b92ffaSHans Petter Selasky memset(&device_attr, 0, sizeof(device_attr)); 921d6b92ffaSHans Petter Selasky if (!mlx5_query_device_ex(ctx, NULL, &device_attr, 922d6b92ffaSHans Petter Selasky sizeof(struct ibv_device_attr_ex))) { 923d6b92ffaSHans Petter Selasky context->cached_device_cap_flags = 924d6b92ffaSHans Petter Selasky device_attr.orig_attr.device_cap_flags; 925d6b92ffaSHans Petter Selasky context->atomic_cap = device_attr.orig_attr.atomic_cap; 926d6b92ffaSHans Petter Selasky context->cached_tso_caps = device_attr.tso_caps; 927d6b92ffaSHans Petter Selasky } 928d6b92ffaSHans Petter Selasky 929d6b92ffaSHans Petter Selasky for (j = 0; j < min(MLX5_MAX_PORTS_NUM, context->num_ports); ++j) { 930d6b92ffaSHans Petter Selasky memset(&port_attr, 0, sizeof(port_attr)); 931d6b92ffaSHans Petter Selasky if (!mlx5_query_port(ctx, j + 1, &port_attr)) 932d6b92ffaSHans Petter Selasky context->cached_link_layer[j] = port_attr.link_layer; 933d6b92ffaSHans Petter Selasky } 934d6b92ffaSHans Petter Selasky 935d6b92ffaSHans Petter Selasky return 0; 936d6b92ffaSHans Petter Selasky 937d6b92ffaSHans Petter Selasky err_free_bf: 938d6b92ffaSHans Petter Selasky free(context->bfs); 939d6b92ffaSHans Petter Selasky 940d6b92ffaSHans Petter Selasky err_free: 941d6b92ffaSHans Petter Selasky for (i = 0; i < MLX5_MAX_UARS; ++i) { 942d6b92ffaSHans Petter Selasky if (context->uar[i]) 943d6b92ffaSHans Petter Selasky munmap(context->uar[i], page_size); 944d6b92ffaSHans Petter Selasky } 945d6b92ffaSHans Petter Selasky close_debug_file(context); 946d6b92ffaSHans Petter Selasky return errno; 947d6b92ffaSHans Petter Selasky } 948d6b92ffaSHans Petter Selasky 949d6b92ffaSHans Petter Selasky static void mlx5_cleanup_context(struct verbs_device *device, 950d6b92ffaSHans Petter Selasky struct ibv_context *ibctx) 951d6b92ffaSHans Petter Selasky { 952d6b92ffaSHans Petter Selasky struct mlx5_context *context = to_mctx(ibctx); 953d6b92ffaSHans Petter Selasky int page_size = to_mdev(ibctx->device)->page_size; 954d6b92ffaSHans Petter Selasky int i; 955d6b92ffaSHans Petter Selasky 956d6b92ffaSHans Petter Selasky free(context->bfs); 957d6b92ffaSHans Petter Selasky for (i = 0; i < MLX5_MAX_UARS; ++i) { 958d6b92ffaSHans Petter Selasky if (context->uar[i]) 959d6b92ffaSHans Petter Selasky munmap(context->uar[i], page_size); 960d6b92ffaSHans Petter Selasky } 961d6b92ffaSHans Petter Selasky if (context->hca_core_clock) 962d6b92ffaSHans Petter Selasky munmap(context->hca_core_clock - context->core_clock.offset, 963d6b92ffaSHans Petter Selasky page_size); 964d6b92ffaSHans Petter Selasky close_debug_file(context); 965d6b92ffaSHans Petter Selasky } 966d6b92ffaSHans Petter Selasky 967d6b92ffaSHans Petter Selasky static struct verbs_device_ops mlx5_dev_ops = { 968d6b92ffaSHans Petter Selasky .init_context = mlx5_init_context, 969d6b92ffaSHans Petter Selasky .uninit_context = mlx5_cleanup_context, 970d6b92ffaSHans Petter Selasky }; 971d6b92ffaSHans Petter Selasky 972d6b92ffaSHans Petter Selasky static struct verbs_device *mlx5_driver_init(const char *uverbs_sys_path, 973d6b92ffaSHans Petter Selasky int abi_version) 974d6b92ffaSHans Petter Selasky { 975d6b92ffaSHans Petter Selasky char value[8]; 976d6b92ffaSHans Petter Selasky struct mlx5_device *dev; 977d6b92ffaSHans Petter Selasky unsigned vendor, device; 978d6b92ffaSHans Petter Selasky int i; 979d6b92ffaSHans Petter Selasky 980d6b92ffaSHans Petter Selasky if (ibv_read_sysfs_file(uverbs_sys_path, "device/vendor", 981d6b92ffaSHans Petter Selasky value, sizeof value) < 0) 982d6b92ffaSHans Petter Selasky return NULL; 983d6b92ffaSHans Petter Selasky sscanf(value, "%i", &vendor); 984d6b92ffaSHans Petter Selasky 985d6b92ffaSHans Petter Selasky if (ibv_read_sysfs_file(uverbs_sys_path, "device/device", 986d6b92ffaSHans Petter Selasky value, sizeof value) < 0) 987d6b92ffaSHans Petter Selasky return NULL; 988d6b92ffaSHans Petter Selasky sscanf(value, "%i", &device); 989d6b92ffaSHans Petter Selasky 990d6b92ffaSHans Petter Selasky for (i = 0; i < sizeof hca_table / sizeof hca_table[0]; ++i) 991d6b92ffaSHans Petter Selasky if (vendor == hca_table[i].vendor && 992d6b92ffaSHans Petter Selasky device == hca_table[i].device) 993d6b92ffaSHans Petter Selasky goto found; 994d6b92ffaSHans Petter Selasky 995d6b92ffaSHans Petter Selasky return NULL; 996d6b92ffaSHans Petter Selasky 997d6b92ffaSHans Petter Selasky found: 998d6b92ffaSHans Petter Selasky if (abi_version < MLX5_UVERBS_MIN_ABI_VERSION || 999d6b92ffaSHans Petter Selasky abi_version > MLX5_UVERBS_MAX_ABI_VERSION) { 1000d6b92ffaSHans Petter Selasky fprintf(stderr, PFX "Fatal: ABI version %d of %s is not supported " 1001d6b92ffaSHans Petter Selasky "(min supported %d, max supported %d)\n", 1002d6b92ffaSHans Petter Selasky abi_version, uverbs_sys_path, 1003d6b92ffaSHans Petter Selasky MLX5_UVERBS_MIN_ABI_VERSION, 1004d6b92ffaSHans Petter Selasky MLX5_UVERBS_MAX_ABI_VERSION); 1005d6b92ffaSHans Petter Selasky return NULL; 1006d6b92ffaSHans Petter Selasky } 1007d6b92ffaSHans Petter Selasky 1008d6b92ffaSHans Petter Selasky dev = calloc(1, sizeof *dev); 1009d6b92ffaSHans Petter Selasky if (!dev) { 1010d6b92ffaSHans Petter Selasky fprintf(stderr, PFX "Fatal: couldn't allocate device for %s\n", 1011d6b92ffaSHans Petter Selasky uverbs_sys_path); 1012d6b92ffaSHans Petter Selasky return NULL; 1013d6b92ffaSHans Petter Selasky } 1014d6b92ffaSHans Petter Selasky 1015d6b92ffaSHans Petter Selasky dev->page_size = sysconf(_SC_PAGESIZE); 1016d6b92ffaSHans Petter Selasky dev->driver_abi_ver = abi_version; 1017d6b92ffaSHans Petter Selasky 1018d6b92ffaSHans Petter Selasky dev->verbs_dev.ops = &mlx5_dev_ops; 1019d6b92ffaSHans Petter Selasky dev->verbs_dev.sz = sizeof(*dev); 1020d6b92ffaSHans Petter Selasky dev->verbs_dev.size_of_context = sizeof(struct mlx5_context) - 1021d6b92ffaSHans Petter Selasky sizeof(struct ibv_context); 1022d6b92ffaSHans Petter Selasky 1023d6b92ffaSHans Petter Selasky return &dev->verbs_dev; 1024d6b92ffaSHans Petter Selasky } 1025d6b92ffaSHans Petter Selasky 1026d6b92ffaSHans Petter Selasky static __attribute__((constructor)) void mlx5_register_driver(void) 1027d6b92ffaSHans Petter Selasky { 1028d6b92ffaSHans Petter Selasky verbs_register_driver("mlx5", mlx5_driver_init); 1029d6b92ffaSHans Petter Selasky } 1030