xref: /freebsd/contrib/ofed/libmlx4/srq.c (revision a687910f)
1d6b92ffaSHans Petter Selasky /*
2d6b92ffaSHans Petter Selasky  * Copyright (c) 2007 Cisco, Inc.  All rights reserved.
3d6b92ffaSHans Petter Selasky  *
4d6b92ffaSHans Petter Selasky  * This software is available to you under a choice of one of two
5d6b92ffaSHans Petter Selasky  * licenses.  You may choose to be licensed under the terms of the GNU
6d6b92ffaSHans Petter Selasky  * General Public License (GPL) Version 2, available from the file
7d6b92ffaSHans Petter Selasky  * COPYING in the main directory of this source tree, or the
8d6b92ffaSHans Petter Selasky  * OpenIB.org BSD license below:
9d6b92ffaSHans Petter Selasky  *
10d6b92ffaSHans Petter Selasky  *     Redistribution and use in source and binary forms, with or
11d6b92ffaSHans Petter Selasky  *     without modification, are permitted provided that the following
12d6b92ffaSHans Petter Selasky  *     conditions are met:
13d6b92ffaSHans Petter Selasky  *
14d6b92ffaSHans Petter Selasky  *      - Redistributions of source code must retain the above
15d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
16d6b92ffaSHans Petter Selasky  *        disclaimer.
17d6b92ffaSHans Petter Selasky  *
18d6b92ffaSHans Petter Selasky  *      - Redistributions in binary form must reproduce the above
19d6b92ffaSHans Petter Selasky  *        copyright notice, this list of conditions and the following
20d6b92ffaSHans Petter Selasky  *        disclaimer in the documentation and/or other materials
21d6b92ffaSHans Petter Selasky  *        provided with the distribution.
22d6b92ffaSHans Petter Selasky  *
23d6b92ffaSHans Petter Selasky  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24d6b92ffaSHans Petter Selasky  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25d6b92ffaSHans Petter Selasky  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26d6b92ffaSHans Petter Selasky  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27d6b92ffaSHans Petter Selasky  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28d6b92ffaSHans Petter Selasky  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29d6b92ffaSHans Petter Selasky  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30d6b92ffaSHans Petter Selasky  * SOFTWARE.
31d6b92ffaSHans Petter Selasky  */
32d6b92ffaSHans Petter Selasky 
33d6b92ffaSHans Petter Selasky #include <config.h>
34d6b92ffaSHans Petter Selasky 
35d6b92ffaSHans Petter Selasky #include <stdlib.h>
36d6b92ffaSHans Petter Selasky #include <pthread.h>
37d6b92ffaSHans Petter Selasky #include <string.h>
38d6b92ffaSHans Petter Selasky 
39d6b92ffaSHans Petter Selasky #include "mlx4.h"
40d6b92ffaSHans Petter Selasky #include "doorbell.h"
41d6b92ffaSHans Petter Selasky #include "wqe.h"
42d6b92ffaSHans Petter Selasky #include "mlx4-abi.h"
43d6b92ffaSHans Petter Selasky 
get_wqe(struct mlx4_srq * srq,int n)44d6b92ffaSHans Petter Selasky static void *get_wqe(struct mlx4_srq *srq, int n)
45d6b92ffaSHans Petter Selasky {
46d6b92ffaSHans Petter Selasky 	return srq->buf.buf + (n << srq->wqe_shift);
47d6b92ffaSHans Petter Selasky }
48d6b92ffaSHans Petter Selasky 
mlx4_free_srq_wqe(struct mlx4_srq * srq,int ind)49d6b92ffaSHans Petter Selasky void mlx4_free_srq_wqe(struct mlx4_srq *srq, int ind)
50d6b92ffaSHans Petter Selasky {
51d6b92ffaSHans Petter Selasky 	struct mlx4_wqe_srq_next_seg *next;
52d6b92ffaSHans Petter Selasky 
53d6b92ffaSHans Petter Selasky 	pthread_spin_lock(&srq->lock);
54d6b92ffaSHans Petter Selasky 
55d6b92ffaSHans Petter Selasky 	next = get_wqe(srq, srq->tail);
56d6b92ffaSHans Petter Selasky 	next->next_wqe_index = htobe16(ind);
57d6b92ffaSHans Petter Selasky 	srq->tail = ind;
58d6b92ffaSHans Petter Selasky 
59d6b92ffaSHans Petter Selasky 	pthread_spin_unlock(&srq->lock);
60d6b92ffaSHans Petter Selasky }
61d6b92ffaSHans Petter Selasky 
mlx4_post_srq_recv(struct ibv_srq * ibsrq,struct ibv_recv_wr * wr,struct ibv_recv_wr ** bad_wr)62d6b92ffaSHans Petter Selasky int mlx4_post_srq_recv(struct ibv_srq *ibsrq,
63d6b92ffaSHans Petter Selasky 		       struct ibv_recv_wr *wr,
64d6b92ffaSHans Petter Selasky 		       struct ibv_recv_wr **bad_wr)
65d6b92ffaSHans Petter Selasky {
66d6b92ffaSHans Petter Selasky 	struct mlx4_srq *srq = to_msrq(ibsrq);
67d6b92ffaSHans Petter Selasky 	struct mlx4_wqe_srq_next_seg *next;
68d6b92ffaSHans Petter Selasky 	struct mlx4_wqe_data_seg *scat;
69d6b92ffaSHans Petter Selasky 	int err = 0;
70d6b92ffaSHans Petter Selasky 	int nreq;
71d6b92ffaSHans Petter Selasky 	int i;
72d6b92ffaSHans Petter Selasky 
73d6b92ffaSHans Petter Selasky 	pthread_spin_lock(&srq->lock);
74d6b92ffaSHans Petter Selasky 
75d6b92ffaSHans Petter Selasky 	for (nreq = 0; wr; ++nreq, wr = wr->next) {
76d6b92ffaSHans Petter Selasky 		if (wr->num_sge > srq->max_gs) {
77d6b92ffaSHans Petter Selasky 			err = -1;
78d6b92ffaSHans Petter Selasky 			*bad_wr = wr;
79d6b92ffaSHans Petter Selasky 			break;
80d6b92ffaSHans Petter Selasky 		}
81d6b92ffaSHans Petter Selasky 
82d6b92ffaSHans Petter Selasky 		if (srq->head == srq->tail) {
83d6b92ffaSHans Petter Selasky 			/* SRQ is full*/
84d6b92ffaSHans Petter Selasky 			err = -1;
85d6b92ffaSHans Petter Selasky 			*bad_wr = wr;
86d6b92ffaSHans Petter Selasky 			break;
87d6b92ffaSHans Petter Selasky 		}
88d6b92ffaSHans Petter Selasky 
89d6b92ffaSHans Petter Selasky 		srq->wrid[srq->head] = wr->wr_id;
90d6b92ffaSHans Petter Selasky 
91d6b92ffaSHans Petter Selasky 		next      = get_wqe(srq, srq->head);
92d6b92ffaSHans Petter Selasky 		srq->head = be16toh(next->next_wqe_index);
93d6b92ffaSHans Petter Selasky 		scat      = (struct mlx4_wqe_data_seg *) (next + 1);
94d6b92ffaSHans Petter Selasky 
95d6b92ffaSHans Petter Selasky 		for (i = 0; i < wr->num_sge; ++i) {
96d6b92ffaSHans Petter Selasky 			scat[i].byte_count = htobe32(wr->sg_list[i].length);
97d6b92ffaSHans Petter Selasky 			scat[i].lkey       = htobe32(wr->sg_list[i].lkey);
98d6b92ffaSHans Petter Selasky 			scat[i].addr       = htobe64(wr->sg_list[i].addr);
99d6b92ffaSHans Petter Selasky 		}
100d6b92ffaSHans Petter Selasky 
101d6b92ffaSHans Petter Selasky 		if (i < srq->max_gs) {
102d6b92ffaSHans Petter Selasky 			scat[i].byte_count = 0;
103d6b92ffaSHans Petter Selasky 			scat[i].lkey       = htobe32(MLX4_INVALID_LKEY);
104d6b92ffaSHans Petter Selasky 			scat[i].addr       = 0;
105d6b92ffaSHans Petter Selasky 		}
106d6b92ffaSHans Petter Selasky 	}
107d6b92ffaSHans Petter Selasky 
108d6b92ffaSHans Petter Selasky 	if (nreq) {
109d6b92ffaSHans Petter Selasky 		srq->counter += nreq;
110d6b92ffaSHans Petter Selasky 
111d6b92ffaSHans Petter Selasky 		/*
112d6b92ffaSHans Petter Selasky 		 * Make sure that descriptors are written before
113d6b92ffaSHans Petter Selasky 		 * we write doorbell record.
114d6b92ffaSHans Petter Selasky 		 */
115d6b92ffaSHans Petter Selasky 		udma_to_device_barrier();
116d6b92ffaSHans Petter Selasky 
117d6b92ffaSHans Petter Selasky 		*srq->db = htobe32(srq->counter);
118d6b92ffaSHans Petter Selasky 	}
119d6b92ffaSHans Petter Selasky 
120d6b92ffaSHans Petter Selasky 	pthread_spin_unlock(&srq->lock);
121d6b92ffaSHans Petter Selasky 
122d6b92ffaSHans Petter Selasky 	return err;
123d6b92ffaSHans Petter Selasky }
124d6b92ffaSHans Petter Selasky 
mlx4_alloc_srq_buf(struct ibv_pd * pd,struct ibv_srq_attr * attr,struct mlx4_srq * srq)125d6b92ffaSHans Petter Selasky int mlx4_alloc_srq_buf(struct ibv_pd *pd, struct ibv_srq_attr *attr,
126d6b92ffaSHans Petter Selasky 		       struct mlx4_srq *srq)
127d6b92ffaSHans Petter Selasky {
128d6b92ffaSHans Petter Selasky 	struct mlx4_wqe_srq_next_seg *next;
129d6b92ffaSHans Petter Selasky 	struct mlx4_wqe_data_seg *scatter;
130d6b92ffaSHans Petter Selasky 	int size;
131d6b92ffaSHans Petter Selasky 	int buf_size;
132d6b92ffaSHans Petter Selasky 	int i;
133d6b92ffaSHans Petter Selasky 
134d6b92ffaSHans Petter Selasky 	srq->wrid = malloc(srq->max * sizeof (uint64_t));
135d6b92ffaSHans Petter Selasky 	if (!srq->wrid)
136d6b92ffaSHans Petter Selasky 		return -1;
137d6b92ffaSHans Petter Selasky 
138d6b92ffaSHans Petter Selasky 	size = sizeof (struct mlx4_wqe_srq_next_seg) +
139d6b92ffaSHans Petter Selasky 		srq->max_gs * sizeof (struct mlx4_wqe_data_seg);
140d6b92ffaSHans Petter Selasky 
141d6b92ffaSHans Petter Selasky 	for (srq->wqe_shift = 5; 1 << srq->wqe_shift < size; ++srq->wqe_shift)
142d6b92ffaSHans Petter Selasky 		; /* nothing */
143d6b92ffaSHans Petter Selasky 
144d6b92ffaSHans Petter Selasky 	buf_size = srq->max << srq->wqe_shift;
145d6b92ffaSHans Petter Selasky 
146d6b92ffaSHans Petter Selasky 	if (mlx4_alloc_buf(&srq->buf, buf_size,
147d6b92ffaSHans Petter Selasky 			   to_mdev(pd->context->device)->page_size)) {
148d6b92ffaSHans Petter Selasky 		free(srq->wrid);
149d6b92ffaSHans Petter Selasky 		return -1;
150d6b92ffaSHans Petter Selasky 	}
151d6b92ffaSHans Petter Selasky 
152d6b92ffaSHans Petter Selasky 	memset(srq->buf.buf, 0, buf_size);
153d6b92ffaSHans Petter Selasky 
154d6b92ffaSHans Petter Selasky 	/*
155d6b92ffaSHans Petter Selasky 	 * Now initialize the SRQ buffer so that all of the WQEs are
156d6b92ffaSHans Petter Selasky 	 * linked into the list of free WQEs.
157d6b92ffaSHans Petter Selasky 	 */
158d6b92ffaSHans Petter Selasky 
159d6b92ffaSHans Petter Selasky 	for (i = 0; i < srq->max; ++i) {
160d6b92ffaSHans Petter Selasky 		next = get_wqe(srq, i);
161d6b92ffaSHans Petter Selasky 		next->next_wqe_index = htobe16((i + 1) & (srq->max - 1));
162d6b92ffaSHans Petter Selasky 
163d6b92ffaSHans Petter Selasky 		for (scatter = (void *) (next + 1);
164d6b92ffaSHans Petter Selasky 		     (void *) scatter < (void *) next + (1 << srq->wqe_shift);
165d6b92ffaSHans Petter Selasky 		     ++scatter)
166d6b92ffaSHans Petter Selasky 			scatter->lkey = htobe32(MLX4_INVALID_LKEY);
167d6b92ffaSHans Petter Selasky 	}
168d6b92ffaSHans Petter Selasky 
169d6b92ffaSHans Petter Selasky 	srq->head = 0;
170d6b92ffaSHans Petter Selasky 	srq->tail = srq->max - 1;
171d6b92ffaSHans Petter Selasky 
172d6b92ffaSHans Petter Selasky 	return 0;
173d6b92ffaSHans Petter Selasky }
174d6b92ffaSHans Petter Selasky 
mlx4_cleanup_xsrq_table(struct mlx4_xsrq_table * xsrq_table)175a687910fSSean Lim void mlx4_cleanup_xsrq_table(struct mlx4_xsrq_table *xsrq_table)
176d6b92ffaSHans Petter Selasky {
177a687910fSSean Lim 	pthread_mutex_destroy(&xsrq_table->mutex);
178a687910fSSean Lim }
179a687910fSSean Lim 
mlx4_init_xsrq_table(struct mlx4_xsrq_table * xsrq_table,int size)180a687910fSSean Lim int mlx4_init_xsrq_table(struct mlx4_xsrq_table *xsrq_table, int size)
181a687910fSSean Lim {
182a687910fSSean Lim 	int				ret;
183d6b92ffaSHans Petter Selasky 	memset(xsrq_table, 0, sizeof *xsrq_table);
184d6b92ffaSHans Petter Selasky 	xsrq_table->num_xsrq = size;
185d6b92ffaSHans Petter Selasky 	xsrq_table->shift = ffs(size) - 1 - MLX4_XSRQ_TABLE_BITS;
186d6b92ffaSHans Petter Selasky 	xsrq_table->mask = (1 << xsrq_table->shift) - 1;
187d6b92ffaSHans Petter Selasky 
188a687910fSSean Lim 	return pthread_mutex_init(&xsrq_table->mutex, NULL);
189d6b92ffaSHans Petter Selasky }
190d6b92ffaSHans Petter Selasky 
mlx4_find_xsrq(struct mlx4_xsrq_table * xsrq_table,uint32_t srqn)191d6b92ffaSHans Petter Selasky struct mlx4_srq *mlx4_find_xsrq(struct mlx4_xsrq_table *xsrq_table, uint32_t srqn)
192d6b92ffaSHans Petter Selasky {
193d6b92ffaSHans Petter Selasky 	int index;
194d6b92ffaSHans Petter Selasky 
195d6b92ffaSHans Petter Selasky 	index = (srqn & (xsrq_table->num_xsrq - 1)) >> xsrq_table->shift;
196d6b92ffaSHans Petter Selasky 	if (xsrq_table->xsrq_table[index].refcnt)
197d6b92ffaSHans Petter Selasky 		return xsrq_table->xsrq_table[index].table[srqn & xsrq_table->mask];
198d6b92ffaSHans Petter Selasky 
199d6b92ffaSHans Petter Selasky 	return NULL;
200d6b92ffaSHans Petter Selasky }
201d6b92ffaSHans Petter Selasky 
mlx4_store_xsrq(struct mlx4_xsrq_table * xsrq_table,uint32_t srqn,struct mlx4_srq * srq)202d6b92ffaSHans Petter Selasky int mlx4_store_xsrq(struct mlx4_xsrq_table *xsrq_table, uint32_t srqn,
203d6b92ffaSHans Petter Selasky 		    struct mlx4_srq *srq)
204d6b92ffaSHans Petter Selasky {
205d6b92ffaSHans Petter Selasky 	int index, ret = 0;
206d6b92ffaSHans Petter Selasky 
207d6b92ffaSHans Petter Selasky 	index = (srqn & (xsrq_table->num_xsrq - 1)) >> xsrq_table->shift;
208d6b92ffaSHans Petter Selasky 	pthread_mutex_lock(&xsrq_table->mutex);
209d6b92ffaSHans Petter Selasky 	if (!xsrq_table->xsrq_table[index].refcnt) {
210d6b92ffaSHans Petter Selasky 		xsrq_table->xsrq_table[index].table = calloc(xsrq_table->mask + 1,
211d6b92ffaSHans Petter Selasky 							     sizeof(struct mlx4_srq *));
212d6b92ffaSHans Petter Selasky 		if (!xsrq_table->xsrq_table[index].table) {
213d6b92ffaSHans Petter Selasky 			ret = -1;
214d6b92ffaSHans Petter Selasky 			goto out;
215d6b92ffaSHans Petter Selasky 		}
216d6b92ffaSHans Petter Selasky 	}
217d6b92ffaSHans Petter Selasky 
218d6b92ffaSHans Petter Selasky 	xsrq_table->xsrq_table[index].refcnt++;
219d6b92ffaSHans Petter Selasky 	xsrq_table->xsrq_table[index].table[srqn & xsrq_table->mask] = srq;
220d6b92ffaSHans Petter Selasky 
221d6b92ffaSHans Petter Selasky out:
222d6b92ffaSHans Petter Selasky 	pthread_mutex_unlock(&xsrq_table->mutex);
223d6b92ffaSHans Petter Selasky 	return ret;
224d6b92ffaSHans Petter Selasky }
225d6b92ffaSHans Petter Selasky 
mlx4_clear_xsrq(struct mlx4_xsrq_table * xsrq_table,uint32_t srqn)226d6b92ffaSHans Petter Selasky void mlx4_clear_xsrq(struct mlx4_xsrq_table *xsrq_table, uint32_t srqn)
227d6b92ffaSHans Petter Selasky {
228d6b92ffaSHans Petter Selasky 	int index;
229d6b92ffaSHans Petter Selasky 
230d6b92ffaSHans Petter Selasky 	index = (srqn & (xsrq_table->num_xsrq - 1)) >> xsrq_table->shift;
231d6b92ffaSHans Petter Selasky 	pthread_mutex_lock(&xsrq_table->mutex);
232d6b92ffaSHans Petter Selasky 
233d6b92ffaSHans Petter Selasky 	if (--xsrq_table->xsrq_table[index].refcnt)
234d6b92ffaSHans Petter Selasky 		xsrq_table->xsrq_table[index].table[srqn & xsrq_table->mask] = NULL;
235d6b92ffaSHans Petter Selasky 	else
236d6b92ffaSHans Petter Selasky 		free(xsrq_table->xsrq_table[index].table);
237d6b92ffaSHans Petter Selasky 
238d6b92ffaSHans Petter Selasky 	pthread_mutex_unlock(&xsrq_table->mutex);
239d6b92ffaSHans Petter Selasky }
240d6b92ffaSHans Petter Selasky 
mlx4_create_xrc_srq(struct ibv_context * context,struct ibv_srq_init_attr_ex * attr_ex)241d6b92ffaSHans Petter Selasky struct ibv_srq *mlx4_create_xrc_srq(struct ibv_context *context,
242d6b92ffaSHans Petter Selasky 				    struct ibv_srq_init_attr_ex *attr_ex)
243d6b92ffaSHans Petter Selasky {
244d6b92ffaSHans Petter Selasky 	struct mlx4_create_xsrq cmd;
245d6b92ffaSHans Petter Selasky 	struct mlx4_create_srq_resp resp;
246d6b92ffaSHans Petter Selasky 	struct mlx4_srq *srq;
247d6b92ffaSHans Petter Selasky 	int ret;
248d6b92ffaSHans Petter Selasky 
249d6b92ffaSHans Petter Selasky 	/* Sanity check SRQ size before proceeding */
250d6b92ffaSHans Petter Selasky 	if (attr_ex->attr.max_wr > 1 << 16 || attr_ex->attr.max_sge > 64)
251d6b92ffaSHans Petter Selasky 		return NULL;
252d6b92ffaSHans Petter Selasky 
253d6b92ffaSHans Petter Selasky 	srq = calloc(1, sizeof *srq);
254d6b92ffaSHans Petter Selasky 	if (!srq)
255d6b92ffaSHans Petter Selasky 		return NULL;
256d6b92ffaSHans Petter Selasky 
257d6b92ffaSHans Petter Selasky 	if (pthread_spin_init(&srq->lock, PTHREAD_PROCESS_PRIVATE))
258d6b92ffaSHans Petter Selasky 		goto err;
259d6b92ffaSHans Petter Selasky 
260d6b92ffaSHans Petter Selasky 	srq->max     = align_queue_size(attr_ex->attr.max_wr + 1);
261d6b92ffaSHans Petter Selasky 	srq->max_gs  = attr_ex->attr.max_sge;
262d6b92ffaSHans Petter Selasky 	srq->counter = 0;
263d6b92ffaSHans Petter Selasky 	srq->ext_srq = 1;
264d6b92ffaSHans Petter Selasky 
265d6b92ffaSHans Petter Selasky 	if (mlx4_alloc_srq_buf(attr_ex->pd, &attr_ex->attr, srq))
266a687910fSSean Lim 		goto err_spl;
267d6b92ffaSHans Petter Selasky 
268d6b92ffaSHans Petter Selasky 	srq->db = mlx4_alloc_db(to_mctx(context), MLX4_DB_TYPE_RQ);
269d6b92ffaSHans Petter Selasky 	if (!srq->db)
270d6b92ffaSHans Petter Selasky 		goto err_free;
271d6b92ffaSHans Petter Selasky 
272d6b92ffaSHans Petter Selasky 	*srq->db = 0;
273d6b92ffaSHans Petter Selasky 
274d6b92ffaSHans Petter Selasky 	cmd.buf_addr = (uintptr_t) srq->buf.buf;
275d6b92ffaSHans Petter Selasky 	cmd.db_addr  = (uintptr_t) srq->db;
276d6b92ffaSHans Petter Selasky 
277d6b92ffaSHans Petter Selasky 	ret = ibv_cmd_create_srq_ex(context, &srq->verbs_srq,
278d6b92ffaSHans Petter Selasky 				    sizeof(srq->verbs_srq),
279d6b92ffaSHans Petter Selasky 				    attr_ex,
280d6b92ffaSHans Petter Selasky 				    &cmd.ibv_cmd, sizeof cmd,
281d6b92ffaSHans Petter Selasky 				    &resp.ibv_resp, sizeof resp);
282d6b92ffaSHans Petter Selasky 	if (ret)
283d6b92ffaSHans Petter Selasky 		goto err_db;
284d6b92ffaSHans Petter Selasky 
285d6b92ffaSHans Petter Selasky 	ret = mlx4_store_xsrq(&to_mctx(context)->xsrq_table,
286d6b92ffaSHans Petter Selasky 			      srq->verbs_srq.srq_num, srq);
287d6b92ffaSHans Petter Selasky 	if (ret)
288d6b92ffaSHans Petter Selasky 		goto err_destroy;
289d6b92ffaSHans Petter Selasky 
290d6b92ffaSHans Petter Selasky 	return &srq->verbs_srq.srq;
291d6b92ffaSHans Petter Selasky 
292d6b92ffaSHans Petter Selasky err_destroy:
293d6b92ffaSHans Petter Selasky 	ibv_cmd_destroy_srq(&srq->verbs_srq.srq);
294d6b92ffaSHans Petter Selasky err_db:
295d6b92ffaSHans Petter Selasky 	mlx4_free_db(to_mctx(context), MLX4_DB_TYPE_RQ, srq->db);
296d6b92ffaSHans Petter Selasky err_free:
297d6b92ffaSHans Petter Selasky 	free(srq->wrid);
298d6b92ffaSHans Petter Selasky 	mlx4_free_buf(&srq->buf);
299a687910fSSean Lim err_spl:
300a687910fSSean Lim 	pthread_spin_destroy(&srq->lock);
301d6b92ffaSHans Petter Selasky err:
302d6b92ffaSHans Petter Selasky 	free(srq);
303d6b92ffaSHans Petter Selasky 	return NULL;
304d6b92ffaSHans Petter Selasky }
305d6b92ffaSHans Petter Selasky 
mlx4_destroy_xrc_srq(struct ibv_srq * srq)306d6b92ffaSHans Petter Selasky int mlx4_destroy_xrc_srq(struct ibv_srq *srq)
307d6b92ffaSHans Petter Selasky {
308d6b92ffaSHans Petter Selasky 	struct mlx4_context *mctx = to_mctx(srq->context);
309d6b92ffaSHans Petter Selasky 	struct mlx4_srq *msrq = to_msrq(srq);
310d6b92ffaSHans Petter Selasky 	struct mlx4_cq *mcq;
311d6b92ffaSHans Petter Selasky 	int ret;
312d6b92ffaSHans Petter Selasky 
313d6b92ffaSHans Petter Selasky 	mcq = to_mcq(msrq->verbs_srq.cq);
314d6b92ffaSHans Petter Selasky 	mlx4_cq_clean(mcq, 0, msrq);
315d6b92ffaSHans Petter Selasky 	pthread_spin_lock(&mcq->lock);
316d6b92ffaSHans Petter Selasky 	mlx4_clear_xsrq(&mctx->xsrq_table, msrq->verbs_srq.srq_num);
317d6b92ffaSHans Petter Selasky 	pthread_spin_unlock(&mcq->lock);
318d6b92ffaSHans Petter Selasky 
319d6b92ffaSHans Petter Selasky 	ret = ibv_cmd_destroy_srq(srq);
320d6b92ffaSHans Petter Selasky 	if (ret) {
321d6b92ffaSHans Petter Selasky 		pthread_spin_lock(&mcq->lock);
322d6b92ffaSHans Petter Selasky 		mlx4_store_xsrq(&mctx->xsrq_table, msrq->verbs_srq.srq_num, msrq);
323d6b92ffaSHans Petter Selasky 		pthread_spin_unlock(&mcq->lock);
324d6b92ffaSHans Petter Selasky 		return ret;
325d6b92ffaSHans Petter Selasky 	}
326d6b92ffaSHans Petter Selasky 
327d6b92ffaSHans Petter Selasky 	mlx4_free_db(mctx, MLX4_DB_TYPE_RQ, msrq->db);
328d6b92ffaSHans Petter Selasky 	mlx4_free_buf(&msrq->buf);
329d6b92ffaSHans Petter Selasky 	free(msrq->wrid);
330a687910fSSean Lim 	pthread_spin_destroy(&msrq->lock);
331d6b92ffaSHans Petter Selasky 	free(msrq);
332d6b92ffaSHans Petter Selasky 
333d6b92ffaSHans Petter Selasky 	return 0;
334d6b92ffaSHans Petter Selasky }
335