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