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 | |
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, udata: &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(v: &us->uxrcd->refcnt); |
30 | } |
31 | |
32 | ib_uverbs_release_uevent(uobj: uevent); |
33 | return 0; |
34 | } |
35 | |
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_bundle: attrs, idx: 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(srq_type: attr.srq_type)) { |
68 | attr.ext.cq = uverbs_attr_get_obj(attrs_bundle: attrs, |
69 | idx: UVERBS_ATTR_CREATE_SRQ_CQ_HANDLE); |
70 | if (IS_ERR(ptr: attr.ext.cq)) |
71 | return PTR_ERR(ptr: attr.ext.cq); |
72 | } |
73 | |
74 | switch (attr.srq_type) { |
75 | case IB_UVERBS_SRQT_XRC: |
76 | xrcd_uobj = uverbs_attr_get_uobject(attrs_bundle: attrs, |
77 | idx: UVERBS_ATTR_CREATE_SRQ_XRCD_HANDLE); |
78 | if (IS_ERR(ptr: xrcd_uobj)) |
79 | return PTR_ERR(ptr: 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(v: &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 | id: UVERBS_ATTR_CREATE_SRQ_EVENT_FD); |
103 | INIT_LIST_HEAD(list: &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, srq_init_attr: &attr, uobject: obj, udata: &attrs->driver_udata); |
108 | if (IS_ERR(ptr: srq)) { |
109 | ret = PTR_ERR(ptr: srq); |
110 | goto err; |
111 | } |
112 | |
113 | obj->uevent.uobject.object = srq; |
114 | uverbs_finalize_uobj_create(attrs_bundle: attrs, idx: UVERBS_ATTR_CREATE_SRQ_HANDLE); |
115 | |
116 | ret = uverbs_copy_to(attrs_bundle: attrs, idx: UVERBS_ATTR_CREATE_SRQ_RESP_MAX_WR, |
117 | from: &attr.attr.max_wr, |
118 | size: sizeof(attr.attr.max_wr)); |
119 | if (ret) |
120 | return ret; |
121 | |
122 | ret = uverbs_copy_to(attrs_bundle: attrs, idx: UVERBS_ATTR_CREATE_SRQ_RESP_MAX_SGE, |
123 | from: &attr.attr.max_sge, |
124 | size: 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_bundle: attrs, |
130 | idx: UVERBS_ATTR_CREATE_SRQ_RESP_SRQ_NUM, |
131 | from: &srq->ext.xrc.srq_num, |
132 | size: 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(uobject: &obj->uevent.event_file->uobj); |
141 | if (attr.srq_type == IB_SRQT_XRC) |
142 | atomic_dec(v: &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 | |
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_bundle: attrs, idx: 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_bundle: attrs, idx: UVERBS_ATTR_DESTROY_SRQ_RESP, from: &resp, |
209 | size: 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 | |