xref: /freebsd/contrib/ofed/libmlx5/mlx5.c (revision a687910fc4352117413b8e0275383e4c687d4c4c)
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