mlx5_srq.c revision 331580
1290650Shselasky/*-
2290650Shselasky * Copyright (c) 2013-2015, Mellanox Technologies, Ltd.  All rights reserved.
3290650Shselasky *
4290650Shselasky * Redistribution and use in source and binary forms, with or without
5290650Shselasky * modification, are permitted provided that the following conditions
6290650Shselasky * are met:
7290650Shselasky * 1. Redistributions of source code must retain the above copyright
8290650Shselasky *    notice, this list of conditions and the following disclaimer.
9290650Shselasky * 2. Redistributions in binary form must reproduce the above copyright
10290650Shselasky *    notice, this list of conditions and the following disclaimer in the
11290650Shselasky *    documentation and/or other materials provided with the distribution.
12290650Shselasky *
13290650Shselasky * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS `AS IS' AND
14290650Shselasky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15290650Shselasky * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16290650Shselasky * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17290650Shselasky * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18290650Shselasky * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19290650Shselasky * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20290650Shselasky * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21290650Shselasky * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22290650Shselasky * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23290650Shselasky * SUCH DAMAGE.
24290650Shselasky *
25290650Shselasky * $FreeBSD: stable/11/sys/dev/mlx5/mlx5_core/mlx5_srq.c 331580 2018-03-26 20:33:31Z hselasky $
26290650Shselasky */
27290650Shselasky
28290650Shselasky#include <linux/kernel.h>
29290650Shselasky#include <linux/module.h>
30290650Shselasky#include <dev/mlx5/driver.h>
31290650Shselasky#include <dev/mlx5/srq.h>
32290650Shselasky#include <rdma/ib_verbs.h>
33290650Shselasky#include "mlx5_core.h"
34290650Shselasky#include "transobj.h"
35290650Shselasky
36290650Shselaskyvoid mlx5_srq_event(struct mlx5_core_dev *dev, u32 srqn, int event_type)
37290650Shselasky{
38290650Shselasky	struct mlx5_srq_table *table = &dev->priv.srq_table;
39290650Shselasky	struct mlx5_core_srq *srq;
40290650Shselasky
41290650Shselasky	spin_lock(&table->lock);
42290650Shselasky
43290650Shselasky	srq = radix_tree_lookup(&table->tree, srqn);
44290650Shselasky	if (srq)
45290650Shselasky		atomic_inc(&srq->refcount);
46290650Shselasky
47290650Shselasky	spin_unlock(&table->lock);
48290650Shselasky
49290650Shselasky	if (!srq) {
50290650Shselasky		mlx5_core_warn(dev, "Async event for bogus SRQ 0x%08x\n", srqn);
51290650Shselasky		return;
52290650Shselasky	}
53290650Shselasky
54290650Shselasky	srq->event(srq, event_type);
55290650Shselasky
56290650Shselasky	if (atomic_dec_and_test(&srq->refcount))
57290650Shselasky		complete(&srq->free);
58290650Shselasky}
59290650Shselasky
60290650Shselaskystatic void rmpc_srqc_reformat(void *srqc, void *rmpc, bool srqc_to_rmpc)
61290650Shselasky{
62290650Shselasky	void *wq = MLX5_ADDR_OF(rmpc, rmpc, wq);
63290650Shselasky
64290650Shselasky	if (srqc_to_rmpc) {
65290650Shselasky		switch (MLX5_GET(srqc, srqc, state)) {
66290650Shselasky		case MLX5_SRQC_STATE_GOOD:
67290650Shselasky			MLX5_SET(rmpc, rmpc, state, MLX5_RMPC_STATE_RDY);
68290650Shselasky			break;
69290650Shselasky		case MLX5_SRQC_STATE_ERROR:
70290650Shselasky			MLX5_SET(rmpc, rmpc, state, MLX5_RMPC_STATE_ERR);
71290650Shselasky			break;
72290650Shselasky		default:
73290650Shselasky			printf("mlx5_core: WARN: ""%s: %d: Unknown srq state = 0x%x\n", __func__, __LINE__, MLX5_GET(srqc, srqc, state));
74290650Shselasky		}
75290650Shselasky
76290650Shselasky		MLX5_SET(wq,   wq, wq_signature,  MLX5_GET(srqc, srqc, wq_signature));
77290650Shselasky		MLX5_SET(wq,   wq, log_wq_pg_sz,  MLX5_GET(srqc, srqc, log_page_size));
78290650Shselasky		MLX5_SET(wq,   wq, log_wq_stride, MLX5_GET(srqc, srqc, log_rq_stride) + 4);
79290650Shselasky		MLX5_SET(wq,   wq, log_wq_sz,     MLX5_GET(srqc, srqc, log_srq_size));
80290650Shselasky		MLX5_SET(wq,   wq, page_offset,   MLX5_GET(srqc, srqc, page_offset));
81290650Shselasky		MLX5_SET(wq,   wq, lwm,           MLX5_GET(srqc, srqc, lwm));
82290650Shselasky		MLX5_SET(wq,   wq, pd,            MLX5_GET(srqc, srqc, pd));
83290650Shselasky		MLX5_SET64(wq, wq, dbr_addr,
84290650Shselasky			   ((u64)MLX5_GET(srqc, srqc, db_record_addr_h)) << 32 |
85290650Shselasky			   ((u64)MLX5_GET(srqc, srqc, db_record_addr_l)) << 2);
86290650Shselasky	} else {
87290650Shselasky		switch (MLX5_GET(rmpc, rmpc, state)) {
88290650Shselasky		case MLX5_RMPC_STATE_RDY:
89290650Shselasky			MLX5_SET(srqc, srqc, state, MLX5_SRQC_STATE_GOOD);
90290650Shselasky			break;
91290650Shselasky		case MLX5_RMPC_STATE_ERR:
92290650Shselasky			MLX5_SET(srqc, srqc, state, MLX5_SRQC_STATE_ERROR);
93290650Shselasky			break;
94290650Shselasky		default:
95290650Shselasky			printf("mlx5_core: WARN: ""%s: %d: Unknown rmp state = 0x%x\n", __func__, __LINE__, MLX5_GET(rmpc, rmpc, state));
96290650Shselasky		}
97290650Shselasky
98290650Shselasky		MLX5_SET(srqc, srqc, wq_signature,     MLX5_GET(wq,   wq, wq_signature));
99290650Shselasky		MLX5_SET(srqc, srqc, log_page_size,    MLX5_GET(wq,   wq, log_wq_pg_sz));
100290650Shselasky		MLX5_SET(srqc, srqc, log_rq_stride,    MLX5_GET(wq,   wq, log_wq_stride) - 4);
101290650Shselasky		MLX5_SET(srqc, srqc, log_srq_size,     MLX5_GET(wq,   wq, log_wq_sz));
102290650Shselasky		MLX5_SET(srqc, srqc, page_offset,      MLX5_GET(wq,   wq, page_offset));
103290650Shselasky		MLX5_SET(srqc, srqc, lwm,	       MLX5_GET(wq,   wq, lwm));
104290650Shselasky		MLX5_SET(srqc, srqc, pd,	       MLX5_GET(wq,   wq, pd));
105290650Shselasky		MLX5_SET(srqc, srqc, db_record_addr_h, MLX5_GET64(wq, wq, dbr_addr) >> 32);
106290650Shselasky		MLX5_SET(srqc, srqc, db_record_addr_l, (MLX5_GET64(wq, wq, dbr_addr) >> 2) & 0x3fffffff);
107290650Shselasky	}
108290650Shselasky}
109290650Shselasky
110290650Shselaskystruct mlx5_core_srq *mlx5_core_get_srq(struct mlx5_core_dev *dev, u32 srqn)
111290650Shselasky{
112290650Shselasky	struct mlx5_srq_table *table = &dev->priv.srq_table;
113290650Shselasky	struct mlx5_core_srq *srq;
114290650Shselasky
115290650Shselasky	spin_lock(&table->lock);
116290650Shselasky
117290650Shselasky	srq = radix_tree_lookup(&table->tree, srqn);
118290650Shselasky	if (srq)
119290650Shselasky		atomic_inc(&srq->refcount);
120290650Shselasky
121290650Shselasky	spin_unlock(&table->lock);
122290650Shselasky
123290650Shselasky	return srq;
124290650Shselasky}
125290650ShselaskyEXPORT_SYMBOL(mlx5_core_get_srq);
126290650Shselasky
127290650Shselaskystatic int get_pas_size(void *srqc)
128290650Shselasky{
129290650Shselasky	u32 log_page_size = MLX5_GET(srqc, srqc, log_page_size) + 12;
130290650Shselasky	u32 log_srq_size  = MLX5_GET(srqc, srqc, log_srq_size);
131290650Shselasky	u32 log_rq_stride = MLX5_GET(srqc, srqc, log_rq_stride);
132290650Shselasky	u32 page_offset   = MLX5_GET(srqc, srqc, page_offset);
133290650Shselasky	u32 po_quanta	  = 1 << (log_page_size - 6);
134290650Shselasky	u32 rq_sz	  = 1 << (log_srq_size + 4 + log_rq_stride);
135290650Shselasky	u32 page_size	  = 1 << log_page_size;
136290650Shselasky	u32 rq_sz_po      = rq_sz + (page_offset * po_quanta);
137290650Shselasky	u32 rq_num_pas	  = (rq_sz_po + page_size - 1) / page_size;
138290650Shselasky
139290650Shselasky	return rq_num_pas * sizeof(u64);
140290650Shselasky
141290650Shselasky}
142290650Shselasky
143290650Shselaskystatic int create_rmp_cmd(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
144290650Shselasky			  struct mlx5_create_srq_mbox_in *in, int srq_inlen)
145290650Shselasky{
146290650Shselasky	void *create_in;
147290650Shselasky	void *rmpc;
148290650Shselasky	void *srqc;
149290650Shselasky	int pas_size;
150290650Shselasky	int inlen;
151290650Shselasky	int err;
152290650Shselasky
153290650Shselasky	srqc = MLX5_ADDR_OF(create_srq_in, in, srq_context_entry);
154290650Shselasky	pas_size = get_pas_size(srqc);
155290650Shselasky	inlen = MLX5_ST_SZ_BYTES(create_rmp_in) + pas_size;
156290650Shselasky	create_in = mlx5_vzalloc(inlen);
157290650Shselasky	if (!create_in)
158290650Shselasky		return -ENOMEM;
159290650Shselasky
160290650Shselasky	rmpc = MLX5_ADDR_OF(create_rmp_in, create_in, ctx);
161290650Shselasky
162290650Shselasky	memcpy(MLX5_ADDR_OF(rmpc, rmpc, wq.pas), in->pas, pas_size);
163290650Shselasky	rmpc_srqc_reformat(srqc, rmpc, true);
164290650Shselasky
165290650Shselasky	err = mlx5_core_create_rmp(dev, create_in, inlen, &srq->srqn);
166290650Shselasky
167290650Shselasky	kvfree(create_in);
168290650Shselasky	return err;
169290650Shselasky}
170290650Shselasky
171290650Shselaskystatic int destroy_rmp_cmd(struct mlx5_core_dev *dev,
172290650Shselasky			    struct mlx5_core_srq *srq)
173290650Shselasky{
174290650Shselasky	return mlx5_core_destroy_rmp(dev, srq->srqn);
175290650Shselasky}
176290650Shselasky
177290650Shselaskystatic int query_rmp_cmd(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
178290650Shselasky			 struct mlx5_query_srq_mbox_out *out)
179290650Shselasky{
180290650Shselasky	u32 *rmp_out;
181290650Shselasky	void *rmpc;
182290650Shselasky	void *srqc;
183290650Shselasky	int err;
184290650Shselasky
185290650Shselasky	rmp_out =  mlx5_vzalloc(MLX5_ST_SZ_BYTES(query_rmp_out));
186290650Shselasky	if (!rmp_out)
187290650Shselasky		return -ENOMEM;
188290650Shselasky
189290650Shselasky	err = mlx5_core_query_rmp(dev, srq->srqn, rmp_out);
190290650Shselasky	if (err)
191290650Shselasky		goto out;
192290650Shselasky
193290650Shselasky	srqc = MLX5_ADDR_OF(query_srq_out, out,	    srq_context_entry);
194290650Shselasky	rmpc = MLX5_ADDR_OF(query_rmp_out, rmp_out, rmp_context);
195290650Shselasky	rmpc_srqc_reformat(srqc, rmpc, false);
196290650Shselasky
197290650Shselaskyout:
198290650Shselasky	kvfree(rmp_out);
199290650Shselasky	return 0;
200290650Shselasky}
201290650Shselasky
202290650Shselaskystatic int arm_rmp_cmd(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq, u16 lwm)
203290650Shselasky{
204290650Shselasky	return mlx5_core_arm_rmp(dev, srq->srqn, lwm);
205290650Shselasky}
206290650Shselasky
207290650Shselaskystatic int create_xrc_srq_cmd(struct mlx5_core_dev *dev,
208290650Shselasky			      struct mlx5_core_srq *srq,
209290650Shselasky			      struct mlx5_create_srq_mbox_in *in,
210290650Shselasky			      int srq_inlen)
211290650Shselasky{
212290650Shselasky	void *create_in;
213290650Shselasky	void *srqc;
214290650Shselasky	void *xrc_srqc;
215290650Shselasky	void *pas;
216290650Shselasky	int pas_size;
217290650Shselasky	int inlen;
218290650Shselasky	int err;
219290650Shselasky
220290650Shselasky	srqc	  = MLX5_ADDR_OF(create_srq_in, in, srq_context_entry);
221290650Shselasky	pas_size  = get_pas_size(srqc);
222290650Shselasky	inlen	  = MLX5_ST_SZ_BYTES(create_xrc_srq_in) + pas_size;
223290650Shselasky	create_in = mlx5_vzalloc(inlen);
224290650Shselasky	if (!create_in)
225290650Shselasky		return -ENOMEM;
226290650Shselasky
227290650Shselasky	xrc_srqc = MLX5_ADDR_OF(create_xrc_srq_in, create_in, xrc_srq_context_entry);
228290650Shselasky	pas	 = MLX5_ADDR_OF(create_xrc_srq_in, create_in, pas);
229290650Shselasky
230290650Shselasky	memcpy(xrc_srqc, srqc, MLX5_ST_SZ_BYTES(srqc));
231290650Shselasky	memcpy(pas, in->pas, pas_size);
232290650Shselasky
233290650Shselasky	err = mlx5_core_create_xsrq(dev, create_in, inlen, &srq->srqn);
234290650Shselasky	if (err)
235290650Shselasky		goto out;
236290650Shselasky
237290650Shselaskyout:
238290650Shselasky	kvfree(create_in);
239290650Shselasky	return err;
240290650Shselasky}
241290650Shselasky
242290650Shselaskystatic int destroy_xrc_srq_cmd(struct mlx5_core_dev *dev,
243290650Shselasky			       struct mlx5_core_srq *srq)
244290650Shselasky{
245290650Shselasky	return mlx5_core_destroy_xsrq(dev, srq->srqn);
246290650Shselasky}
247290650Shselasky
248290650Shselaskystatic int query_xrc_srq_cmd(struct mlx5_core_dev *dev,
249290650Shselasky			     struct mlx5_core_srq *srq,
250290650Shselasky			     struct mlx5_query_srq_mbox_out *out)
251290650Shselasky{
252290650Shselasky	u32 *xrcsrq_out;
253290650Shselasky	int err;
254290650Shselasky
255290650Shselasky	xrcsrq_out = mlx5_vzalloc(MLX5_ST_SZ_BYTES(query_xrc_srq_out));
256290650Shselasky	if (!xrcsrq_out)
257290650Shselasky		return -ENOMEM;
258290650Shselasky
259290650Shselasky	err = mlx5_core_query_xsrq(dev, srq->srqn, xrcsrq_out);
260290650Shselasky	if (err)
261290650Shselasky		goto out;
262290650Shselasky
263290650Shselaskyout:
264290650Shselasky	kvfree(xrcsrq_out);
265290650Shselasky	return err;
266290650Shselasky}
267290650Shselasky
268290650Shselaskystatic int arm_xrc_srq_cmd(struct mlx5_core_dev *dev,
269290650Shselasky			   struct mlx5_core_srq *srq, u16 lwm)
270290650Shselasky{
271290650Shselasky	return mlx5_core_arm_xsrq(dev, srq->srqn, lwm);
272290650Shselasky}
273290650Shselasky
274290650Shselaskystatic int create_srq_cmd(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
275290650Shselasky			  struct mlx5_create_srq_mbox_in *in, int inlen)
276290650Shselasky{
277290650Shselasky	struct mlx5_create_srq_mbox_out out;
278290650Shselasky	int err;
279290650Shselasky
280290650Shselasky	memset(&out, 0, sizeof(out));
281290650Shselasky
282290650Shselasky	in->hdr.opcode = cpu_to_be16(MLX5_CMD_OP_CREATE_SRQ);
283290650Shselasky
284290650Shselasky	err = mlx5_cmd_exec_check_status(dev, (u32 *)in, inlen, (u32 *)(&out), sizeof(out));
285290650Shselasky
286290650Shselasky	srq->srqn = be32_to_cpu(out.srqn) & 0xffffff;
287290650Shselasky
288290650Shselasky	return err;
289290650Shselasky}
290290650Shselasky
291290650Shselaskystatic int destroy_srq_cmd(struct mlx5_core_dev *dev,
292290650Shselasky			   struct mlx5_core_srq *srq)
293290650Shselasky{
294290650Shselasky	struct mlx5_destroy_srq_mbox_in in;
295290650Shselasky	struct mlx5_destroy_srq_mbox_out out;
296290650Shselasky
297290650Shselasky	memset(&in, 0, sizeof(in));
298290650Shselasky	memset(&out, 0, sizeof(out));
299290650Shselasky	in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_DESTROY_SRQ);
300290650Shselasky	in.srqn = cpu_to_be32(srq->srqn);
301290650Shselasky
302290650Shselasky	return mlx5_cmd_exec_check_status(dev, (u32 *)(&in), sizeof(in), (u32 *)(&out), sizeof(out));
303290650Shselasky}
304290650Shselasky
305290650Shselaskystatic int query_srq_cmd(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
306290650Shselasky			 struct mlx5_query_srq_mbox_out *out)
307290650Shselasky{
308290650Shselasky	struct mlx5_query_srq_mbox_in in;
309290650Shselasky
310290650Shselasky	memset(&in, 0, sizeof(in));
311290650Shselasky
312290650Shselasky	in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_QUERY_SRQ);
313290650Shselasky	in.srqn = cpu_to_be32(srq->srqn);
314290650Shselasky
315290650Shselasky	return mlx5_cmd_exec_check_status(dev, (u32 *)(&in), sizeof(in), (u32 *)out, sizeof(*out));
316290650Shselasky}
317290650Shselasky
318290650Shselaskystatic int arm_srq_cmd(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
319290650Shselasky		       u16 lwm, int is_srq)
320290650Shselasky{
321290650Shselasky	struct mlx5_arm_srq_mbox_in	in;
322290650Shselasky	struct mlx5_arm_srq_mbox_out	out;
323290650Shselasky
324290650Shselasky	memset(&in, 0, sizeof(in));
325290650Shselasky	memset(&out, 0, sizeof(out));
326290650Shselasky
327290650Shselasky	in.hdr.opcode = cpu_to_be16(MLX5_CMD_OP_ARM_RQ);
328290650Shselasky	in.hdr.opmod = cpu_to_be16(!!is_srq);
329290650Shselasky	in.srqn = cpu_to_be32(srq->srqn);
330290650Shselasky	in.lwm = cpu_to_be16(lwm);
331290650Shselasky
332290650Shselasky	return mlx5_cmd_exec_check_status(dev, (u32 *)(&in), sizeof(in), (u32 *)(&out), sizeof(out));
333290650Shselasky}
334290650Shselasky
335290650Shselaskystatic int create_srq_split(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
336290650Shselasky			    struct mlx5_create_srq_mbox_in *in, int inlen,
337290650Shselasky			    int is_xrc)
338290650Shselasky{
339290650Shselasky	if (!dev->issi)
340290650Shselasky		return create_srq_cmd(dev, srq, in, inlen);
341290650Shselasky	else if (srq->common.res == MLX5_RES_XSRQ)
342290650Shselasky		return create_xrc_srq_cmd(dev, srq, in, inlen);
343290650Shselasky	else
344290650Shselasky		return create_rmp_cmd(dev, srq, in, inlen);
345290650Shselasky}
346290650Shselasky
347290650Shselaskystatic int destroy_srq_split(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq)
348290650Shselasky{
349290650Shselasky	if (!dev->issi)
350290650Shselasky		return destroy_srq_cmd(dev, srq);
351290650Shselasky	else if (srq->common.res == MLX5_RES_XSRQ)
352290650Shselasky		return destroy_xrc_srq_cmd(dev, srq);
353290650Shselasky	else
354290650Shselasky		return destroy_rmp_cmd(dev, srq);
355290650Shselasky}
356290650Shselasky
357290650Shselaskyint mlx5_core_create_srq(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
358290650Shselasky			 struct mlx5_create_srq_mbox_in *in, int inlen,
359290650Shselasky			 int is_xrc)
360290650Shselasky{
361290650Shselasky	int err;
362290650Shselasky	struct mlx5_srq_table *table = &dev->priv.srq_table;
363290650Shselasky
364290650Shselasky	srq->common.res = is_xrc ? MLX5_RES_XSRQ : MLX5_RES_SRQ;
365290650Shselasky
366290650Shselasky	err = create_srq_split(dev, srq, in, inlen, is_xrc);
367290650Shselasky	if (err)
368290650Shselasky		return err;
369290650Shselasky
370290650Shselasky	atomic_set(&srq->refcount, 1);
371290650Shselasky	init_completion(&srq->free);
372290650Shselasky
373290650Shselasky	spin_lock_irq(&table->lock);
374290650Shselasky	err = radix_tree_insert(&table->tree, srq->srqn, srq);
375290650Shselasky	spin_unlock_irq(&table->lock);
376290650Shselasky	if (err) {
377290650Shselasky		mlx5_core_warn(dev, "err %d, srqn 0x%x\n", err, srq->srqn);
378290650Shselasky		goto err_destroy_srq_split;
379290650Shselasky	}
380290650Shselasky
381290650Shselasky	return 0;
382290650Shselasky
383290650Shselaskyerr_destroy_srq_split:
384290650Shselasky	destroy_srq_split(dev, srq);
385290650Shselasky
386290650Shselasky	return err;
387290650Shselasky}
388290650ShselaskyEXPORT_SYMBOL(mlx5_core_create_srq);
389290650Shselasky
390290650Shselaskyint mlx5_core_destroy_srq(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq)
391290650Shselasky{
392290650Shselasky	struct mlx5_srq_table *table = &dev->priv.srq_table;
393290650Shselasky	struct mlx5_core_srq *tmp;
394290650Shselasky	int err;
395290650Shselasky
396290650Shselasky	spin_lock_irq(&table->lock);
397290650Shselasky	tmp = radix_tree_delete(&table->tree, srq->srqn);
398290650Shselasky	spin_unlock_irq(&table->lock);
399290650Shselasky	if (!tmp) {
400290650Shselasky		mlx5_core_warn(dev, "srq 0x%x not found in tree\n", srq->srqn);
401290650Shselasky		return -EINVAL;
402290650Shselasky	}
403290650Shselasky	if (tmp != srq) {
404290650Shselasky		mlx5_core_warn(dev, "corruption on srqn 0x%x\n", srq->srqn);
405290650Shselasky		return -EINVAL;
406290650Shselasky	}
407290650Shselasky
408290650Shselasky	err = destroy_srq_split(dev, srq);
409290650Shselasky	if (err)
410290650Shselasky		return err;
411290650Shselasky
412290650Shselasky	if (atomic_dec_and_test(&srq->refcount))
413290650Shselasky		complete(&srq->free);
414290650Shselasky	wait_for_completion(&srq->free);
415290650Shselasky
416290650Shselasky	return 0;
417290650Shselasky}
418290650ShselaskyEXPORT_SYMBOL(mlx5_core_destroy_srq);
419290650Shselasky
420290650Shselaskyint mlx5_core_query_srq(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
421290650Shselasky			struct mlx5_query_srq_mbox_out *out)
422290650Shselasky{
423290650Shselasky	if (!dev->issi)
424290650Shselasky		return query_srq_cmd(dev, srq, out);
425290650Shselasky	else if (srq->common.res == MLX5_RES_XSRQ)
426290650Shselasky		return query_xrc_srq_cmd(dev, srq, out);
427290650Shselasky	else
428290650Shselasky		return query_rmp_cmd(dev, srq, out);
429290650Shselasky}
430290650ShselaskyEXPORT_SYMBOL(mlx5_core_query_srq);
431290650Shselasky
432290650Shselaskyint mlx5_core_arm_srq(struct mlx5_core_dev *dev, struct mlx5_core_srq *srq,
433290650Shselasky		      u16 lwm, int is_srq)
434290650Shselasky{
435290650Shselasky	if (!dev->issi)
436290650Shselasky		return arm_srq_cmd(dev, srq, lwm, is_srq);
437290650Shselasky	else if (srq->common.res == MLX5_RES_XSRQ)
438290650Shselasky		return arm_xrc_srq_cmd(dev, srq, lwm);
439290650Shselasky	else
440290650Shselasky		return arm_rmp_cmd(dev, srq, lwm);
441290650Shselasky}
442290650ShselaskyEXPORT_SYMBOL(mlx5_core_arm_srq);
443290650Shselasky
444290650Shselaskyvoid mlx5_init_srq_table(struct mlx5_core_dev *dev)
445290650Shselasky{
446290650Shselasky	struct mlx5_srq_table *table = &dev->priv.srq_table;
447290650Shselasky
448331580Shselasky	memset(table, 0, sizeof(*table));
449290650Shselasky	spin_lock_init(&table->lock);
450290650Shselasky	INIT_RADIX_TREE(&table->tree, GFP_ATOMIC);
451290650Shselasky}
452290650Shselasky
453290650Shselaskyvoid mlx5_cleanup_srq_table(struct mlx5_core_dev *dev)
454290650Shselasky{
455290650Shselasky	/* nothing */
456290650Shselasky}
457