1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
2 /*
3 * Copyright (c) 2020, Mellanox Technologies inc. All rights reserved.
4 */
5
6 #include <rdma/uverbs_std_types.h>
7 #include "rdma_core.h"
8 #include "uverbs.h"
9
uverbs_free_srq(struct ib_uobject * uobject,enum rdma_remove_reason why,struct uverbs_attr_bundle * attrs)10 static int uverbs_free_srq(struct ib_uobject *uobject,
11 enum rdma_remove_reason why,
12 struct uverbs_attr_bundle *attrs)
13 {
14 struct ib_srq *srq = uobject->object;
15 struct ib_uevent_object *uevent =
16 container_of(uobject, struct ib_uevent_object, uobject);
17 enum ib_srq_type srq_type = srq->srq_type;
18 int ret;
19
20 ret = ib_destroy_srq_user(srq, &attrs->driver_udata);
21 if (ret)
22 return ret;
23
24 if (srq_type == IB_SRQT_XRC) {
25 struct ib_usrq_object *us =
26 container_of(uobject, struct ib_usrq_object,
27 uevent.uobject);
28
29 atomic_dec(&us->uxrcd->refcnt);
30 }
31
32 ib_uverbs_release_uevent(uevent);
33 return 0;
34 }
35
UVERBS_HANDLER(UVERBS_METHOD_SRQ_CREATE)36 static int UVERBS_HANDLER(UVERBS_METHOD_SRQ_CREATE)(
37 struct uverbs_attr_bundle *attrs)
38 {
39 struct ib_usrq_object *obj = container_of(
40 uverbs_attr_get_uobject(attrs, UVERBS_ATTR_CREATE_SRQ_HANDLE),
41 typeof(*obj), uevent.uobject);
42 struct ib_pd *pd =
43 uverbs_attr_get_obj(attrs, UVERBS_ATTR_CREATE_SRQ_PD_HANDLE);
44 struct ib_srq_init_attr attr = {};
45 struct ib_uobject *xrcd_uobj;
46 struct ib_srq *srq;
47 u64 user_handle;
48 int ret;
49
50 ret = uverbs_copy_from(&attr.attr.max_sge, attrs,
51 UVERBS_ATTR_CREATE_SRQ_MAX_SGE);
52 if (!ret)
53 ret = uverbs_copy_from(&attr.attr.max_wr, attrs,
54 UVERBS_ATTR_CREATE_SRQ_MAX_WR);
55 if (!ret)
56 ret = uverbs_copy_from(&attr.attr.srq_limit, attrs,
57 UVERBS_ATTR_CREATE_SRQ_LIMIT);
58 if (!ret)
59 ret = uverbs_copy_from(&user_handle, attrs,
60 UVERBS_ATTR_CREATE_SRQ_USER_HANDLE);
61 if (!ret)
62 ret = uverbs_get_const(&attr.srq_type, attrs,
63 UVERBS_ATTR_CREATE_SRQ_TYPE);
64 if (ret)
65 return ret;
66
67 if (ib_srq_has_cq(attr.srq_type)) {
68 attr.ext.cq = uverbs_attr_get_obj(attrs,
69 UVERBS_ATTR_CREATE_SRQ_CQ_HANDLE);
70 if (IS_ERR(attr.ext.cq))
71 return PTR_ERR(attr.ext.cq);
72 }
73
74 switch (attr.srq_type) {
75 case IB_UVERBS_SRQT_XRC:
76 xrcd_uobj = uverbs_attr_get_uobject(attrs,
77 UVERBS_ATTR_CREATE_SRQ_XRCD_HANDLE);
78 if (IS_ERR(xrcd_uobj))
79 return PTR_ERR(xrcd_uobj);
80
81 attr.ext.xrc.xrcd = (struct ib_xrcd *)xrcd_uobj->object;
82 if (!attr.ext.xrc.xrcd)
83 return -EINVAL;
84 obj->uxrcd = container_of(xrcd_uobj, struct ib_uxrcd_object,
85 uobject);
86 atomic_inc(&obj->uxrcd->refcnt);
87 break;
88 case IB_UVERBS_SRQT_TM:
89 ret = uverbs_copy_from(&attr.ext.tag_matching.max_num_tags,
90 attrs,
91 UVERBS_ATTR_CREATE_SRQ_MAX_NUM_TAGS);
92 if (ret)
93 return ret;
94 break;
95 case IB_UVERBS_SRQT_BASIC:
96 break;
97 default:
98 return -EINVAL;
99 }
100
101 obj->uevent.event_file = ib_uverbs_get_async_event(attrs,
102 UVERBS_ATTR_CREATE_SRQ_EVENT_FD);
103 INIT_LIST_HEAD(&obj->uevent.event_list);
104 attr.event_handler = ib_uverbs_srq_event_handler;
105 obj->uevent.uobject.user_handle = user_handle;
106
107 srq = ib_create_srq_user(pd, &attr, obj, &attrs->driver_udata);
108 if (IS_ERR(srq)) {
109 ret = PTR_ERR(srq);
110 goto err;
111 }
112
113 obj->uevent.uobject.object = srq;
114 uverbs_finalize_uobj_create(attrs, UVERBS_ATTR_CREATE_SRQ_HANDLE);
115
116 ret = uverbs_copy_to(attrs, UVERBS_ATTR_CREATE_SRQ_RESP_MAX_WR,
117 &attr.attr.max_wr,
118 sizeof(attr.attr.max_wr));
119 if (ret)
120 return ret;
121
122 ret = uverbs_copy_to(attrs, UVERBS_ATTR_CREATE_SRQ_RESP_MAX_SGE,
123 &attr.attr.max_sge,
124 sizeof(attr.attr.max_sge));
125 if (ret)
126 return ret;
127
128 if (attr.srq_type == IB_SRQT_XRC) {
129 ret = uverbs_copy_to(attrs,
130 UVERBS_ATTR_CREATE_SRQ_RESP_SRQ_NUM,
131 &srq->ext.xrc.srq_num,
132 sizeof(srq->ext.xrc.srq_num));
133 if (ret)
134 return ret;
135 }
136
137 return 0;
138 err:
139 if (obj->uevent.event_file)
140 uverbs_uobject_put(&obj->uevent.event_file->uobj);
141 if (attr.srq_type == IB_SRQT_XRC)
142 atomic_dec(&obj->uxrcd->refcnt);
143 return ret;
144 };
145
146 DECLARE_UVERBS_NAMED_METHOD(
147 UVERBS_METHOD_SRQ_CREATE,
148 UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_SRQ_HANDLE,
149 UVERBS_OBJECT_SRQ,
150 UVERBS_ACCESS_NEW,
151 UA_MANDATORY),
152 UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_SRQ_PD_HANDLE,
153 UVERBS_OBJECT_PD,
154 UVERBS_ACCESS_READ,
155 UA_MANDATORY),
156 UVERBS_ATTR_CONST_IN(UVERBS_ATTR_CREATE_SRQ_TYPE,
157 enum ib_uverbs_srq_type,
158 UA_MANDATORY),
159 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_SRQ_USER_HANDLE,
160 UVERBS_ATTR_TYPE(u64),
161 UA_MANDATORY),
162 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_SRQ_MAX_WR,
163 UVERBS_ATTR_TYPE(u32),
164 UA_MANDATORY),
165 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_SRQ_MAX_SGE,
166 UVERBS_ATTR_TYPE(u32),
167 UA_MANDATORY),
168 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_SRQ_LIMIT,
169 UVERBS_ATTR_TYPE(u32),
170 UA_MANDATORY),
171 UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_SRQ_XRCD_HANDLE,
172 UVERBS_OBJECT_XRCD,
173 UVERBS_ACCESS_READ,
174 UA_OPTIONAL),
175 UVERBS_ATTR_IDR(UVERBS_ATTR_CREATE_SRQ_CQ_HANDLE,
176 UVERBS_OBJECT_CQ,
177 UVERBS_ACCESS_READ,
178 UA_OPTIONAL),
179 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CREATE_SRQ_MAX_NUM_TAGS,
180 UVERBS_ATTR_TYPE(u32),
181 UA_OPTIONAL),
182 UVERBS_ATTR_FD(UVERBS_ATTR_CREATE_SRQ_EVENT_FD,
183 UVERBS_OBJECT_ASYNC_EVENT,
184 UVERBS_ACCESS_READ,
185 UA_OPTIONAL),
186 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CREATE_SRQ_RESP_MAX_WR,
187 UVERBS_ATTR_TYPE(u32),
188 UA_MANDATORY),
189 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CREATE_SRQ_RESP_MAX_SGE,
190 UVERBS_ATTR_TYPE(u32),
191 UA_MANDATORY),
192 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CREATE_SRQ_RESP_SRQ_NUM,
193 UVERBS_ATTR_TYPE(u32),
194 UA_OPTIONAL),
195 UVERBS_ATTR_UHW());
196
UVERBS_HANDLER(UVERBS_METHOD_SRQ_DESTROY)197 static int UVERBS_HANDLER(UVERBS_METHOD_SRQ_DESTROY)(
198 struct uverbs_attr_bundle *attrs)
199 {
200 struct ib_uobject *uobj =
201 uverbs_attr_get_uobject(attrs, UVERBS_ATTR_DESTROY_SRQ_HANDLE);
202 struct ib_usrq_object *obj =
203 container_of(uobj, struct ib_usrq_object, uevent.uobject);
204 struct ib_uverbs_destroy_srq_resp resp = {
205 .events_reported = obj->uevent.events_reported
206 };
207
208 return uverbs_copy_to(attrs, UVERBS_ATTR_DESTROY_SRQ_RESP, &resp,
209 sizeof(resp));
210 }
211
212 DECLARE_UVERBS_NAMED_METHOD(
213 UVERBS_METHOD_SRQ_DESTROY,
214 UVERBS_ATTR_IDR(UVERBS_ATTR_DESTROY_SRQ_HANDLE,
215 UVERBS_OBJECT_SRQ,
216 UVERBS_ACCESS_DESTROY,
217 UA_MANDATORY),
218 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_DESTROY_SRQ_RESP,
219 UVERBS_ATTR_TYPE(struct ib_uverbs_destroy_srq_resp),
220 UA_MANDATORY));
221
222 DECLARE_UVERBS_NAMED_OBJECT(
223 UVERBS_OBJECT_SRQ,
224 UVERBS_TYPE_ALLOC_IDR_SZ(sizeof(struct ib_usrq_object),
225 uverbs_free_srq),
226 &UVERBS_METHOD(UVERBS_METHOD_SRQ_CREATE),
227 &UVERBS_METHOD(UVERBS_METHOD_SRQ_DESTROY)
228 );
229
230 const struct uapi_definition uverbs_def_obj_srq[] = {
231 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_SRQ,
232 UAPI_DEF_OBJ_NEEDS_FN(destroy_srq)),
233 {}
234 };
235