2 * Copyright (c) 2013, Mellanox Technologies inc. All rights reserved.
4 * This software is available to you under a choice of one of two
5 * licenses. You may choose to be licensed under the terms of the GNU
6 * General Public License (GPL) Version 2, available from the file
7 * COPYING in the main directory of this source tree, or the
8 * OpenIB.org BSD license below:
10 * Redistribution and use in source and binary forms, with or
11 * without modification, are permitted provided that the following
14 * - Redistributions of source code must retain the above
15 * copyright notice, this list of conditions and the following
18 * - Redistributions in binary form must reproduce the above
19 * copyright notice, this list of conditions and the following
20 * disclaimer in the documentation and/or other materials
21 * provided with the distribution.
23 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
27 * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
28 * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
29 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
33 #include <linux/kernel.h>
34 #include <linux/module.h>
35 #include <linux/mlx5/driver.h>
36 #include <linux/mlx5/cmd.h>
37 #include <linux/mlx5/srq.h>
38 #include <rdma/ib_verbs.h>
39 #include "mlx5_core.h"
41 void mlx5_srq_event(struct mlx5_core_dev
*dev
, u32 srqn
, int event_type
)
43 struct mlx5_srq_table
*table
= &dev
->priv
.srq_table
;
44 struct mlx5_core_srq
*srq
;
46 spin_lock(&table
->lock
);
48 srq
= radix_tree_lookup(&table
->tree
, srqn
);
50 atomic_inc(&srq
->refcount
);
52 spin_unlock(&table
->lock
);
55 mlx5_core_warn(dev
, "Async event for bogus SRQ 0x%08x\n", srqn
);
59 srq
->event(srq
, event_type
);
61 if (atomic_dec_and_test(&srq
->refcount
))
65 struct mlx5_core_srq
*mlx5_core_get_srq(struct mlx5_core_dev
*dev
, u32 srqn
)
67 struct mlx5_srq_table
*table
= &dev
->priv
.srq_table
;
68 struct mlx5_core_srq
*srq
;
70 spin_lock(&table
->lock
);
72 srq
= radix_tree_lookup(&table
->tree
, srqn
);
74 atomic_inc(&srq
->refcount
);
76 spin_unlock(&table
->lock
);
80 EXPORT_SYMBOL(mlx5_core_get_srq
);
82 int mlx5_core_create_srq(struct mlx5_core_dev
*dev
, struct mlx5_core_srq
*srq
,
83 struct mlx5_create_srq_mbox_in
*in
, int inlen
)
85 struct mlx5_create_srq_mbox_out out
;
86 struct mlx5_srq_table
*table
= &dev
->priv
.srq_table
;
87 struct mlx5_destroy_srq_mbox_in din
;
88 struct mlx5_destroy_srq_mbox_out dout
;
91 memset(&out
, 0, sizeof(out
));
92 in
->hdr
.opcode
= cpu_to_be16(MLX5_CMD_OP_CREATE_SRQ
);
93 err
= mlx5_cmd_exec(dev
, in
, inlen
, &out
, sizeof(out
));
98 return mlx5_cmd_status_to_err(&out
.hdr
);
100 srq
->srqn
= be32_to_cpu(out
.srqn
) & 0xffffff;
102 atomic_set(&srq
->refcount
, 1);
103 init_completion(&srq
->free
);
105 spin_lock_irq(&table
->lock
);
106 err
= radix_tree_insert(&table
->tree
, srq
->srqn
, srq
);
107 spin_unlock_irq(&table
->lock
);
109 mlx5_core_warn(dev
, "err %d, srqn 0x%x\n", err
, srq
->srqn
);
116 memset(&din
, 0, sizeof(din
));
117 memset(&dout
, 0, sizeof(dout
));
118 din
.srqn
= cpu_to_be32(srq
->srqn
);
119 din
.hdr
.opcode
= cpu_to_be16(MLX5_CMD_OP_DESTROY_SRQ
);
120 mlx5_cmd_exec(dev
, &din
, sizeof(din
), &dout
, sizeof(dout
));
123 EXPORT_SYMBOL(mlx5_core_create_srq
);
125 int mlx5_core_destroy_srq(struct mlx5_core_dev
*dev
, struct mlx5_core_srq
*srq
)
127 struct mlx5_destroy_srq_mbox_in in
;
128 struct mlx5_destroy_srq_mbox_out out
;
129 struct mlx5_srq_table
*table
= &dev
->priv
.srq_table
;
130 struct mlx5_core_srq
*tmp
;
133 spin_lock_irq(&table
->lock
);
134 tmp
= radix_tree_delete(&table
->tree
, srq
->srqn
);
135 spin_unlock_irq(&table
->lock
);
137 mlx5_core_warn(dev
, "srq 0x%x not found in tree\n", srq
->srqn
);
141 mlx5_core_warn(dev
, "corruption on srqn 0x%x\n", srq
->srqn
);
145 memset(&in
, 0, sizeof(in
));
146 memset(&out
, 0, sizeof(out
));
147 in
.hdr
.opcode
= cpu_to_be16(MLX5_CMD_OP_DESTROY_SRQ
);
148 in
.srqn
= cpu_to_be32(srq
->srqn
);
149 err
= mlx5_cmd_exec(dev
, &in
, sizeof(in
), &out
, sizeof(out
));
154 return mlx5_cmd_status_to_err(&out
.hdr
);
156 if (atomic_dec_and_test(&srq
->refcount
))
157 complete(&srq
->free
);
158 wait_for_completion(&srq
->free
);
162 EXPORT_SYMBOL(mlx5_core_destroy_srq
);
164 int mlx5_core_query_srq(struct mlx5_core_dev
*dev
, struct mlx5_core_srq
*srq
,
165 struct mlx5_query_srq_mbox_out
*out
)
167 struct mlx5_query_srq_mbox_in in
;
170 memset(&in
, 0, sizeof(in
));
171 memset(out
, 0, sizeof(*out
));
173 in
.hdr
.opcode
= cpu_to_be16(MLX5_CMD_OP_QUERY_SRQ
);
174 in
.srqn
= cpu_to_be32(srq
->srqn
);
175 err
= mlx5_cmd_exec(dev
, &in
, sizeof(in
), out
, sizeof(*out
));
180 return mlx5_cmd_status_to_err(&out
->hdr
);
184 EXPORT_SYMBOL(mlx5_core_query_srq
);
186 int mlx5_core_arm_srq(struct mlx5_core_dev
*dev
, struct mlx5_core_srq
*srq
,
189 struct mlx5_arm_srq_mbox_in in
;
190 struct mlx5_arm_srq_mbox_out out
;
193 memset(&in
, 0, sizeof(in
));
194 memset(&out
, 0, sizeof(out
));
196 in
.hdr
.opcode
= cpu_to_be16(MLX5_CMD_OP_ARM_RQ
);
197 in
.hdr
.opmod
= cpu_to_be16(!!is_srq
);
198 in
.srqn
= cpu_to_be32(srq
->srqn
);
199 in
.lwm
= cpu_to_be16(lwm
);
201 err
= mlx5_cmd_exec(dev
, &in
, sizeof(in
), &out
, sizeof(out
));
206 return mlx5_cmd_status_to_err(&out
.hdr
);
210 EXPORT_SYMBOL(mlx5_core_arm_srq
);
212 void mlx5_init_srq_table(struct mlx5_core_dev
*dev
)
214 struct mlx5_srq_table
*table
= &dev
->priv
.srq_table
;
216 spin_lock_init(&table
->lock
);
217 INIT_RADIX_TREE(&table
->tree
, GFP_ATOMIC
);
220 void mlx5_cleanup_srq_table(struct mlx5_core_dev
*dev
)