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