1 // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB
3 * Copyright (c) 2018, Mellanox Technologies inc. All rights reserved.
6 #include <rdma/uverbs_std_types.h>
9 #include <rdma/uverbs_ioctl.h>
10 #include <rdma/opa_addr.h>
13 * This ioctl method allows calling any defined write or write_ex
14 * handler. This essentially replaces the hdr/ex_hdr system with the ioctl
15 * marshalling, and brings the non-ex path into the same marshalling as the ex
18 static int UVERBS_HANDLER(UVERBS_METHOD_INVOKE_WRITE
)(
19 struct uverbs_attr_bundle
*attrs
)
21 struct uverbs_api
*uapi
= attrs
->ufile
->device
->uapi
;
22 const struct uverbs_api_write_method
*method_elm
;
26 rc
= uverbs_get_const(&cmd
, attrs
, UVERBS_ATTR_WRITE_CMD
);
30 method_elm
= uapi_get_method(uapi
, cmd
);
31 if (IS_ERR(method_elm
))
32 return PTR_ERR(method_elm
);
34 uverbs_fill_udata(attrs
, &attrs
->ucore
, UVERBS_ATTR_CORE_IN
,
35 UVERBS_ATTR_CORE_OUT
);
37 if (attrs
->ucore
.inlen
< method_elm
->req_size
||
38 attrs
->ucore
.outlen
< method_elm
->resp_size
)
41 attrs
->uobject
= NULL
;
42 rc
= method_elm
->handler(attrs
);
44 uverbs_finalize_object(attrs
->uobject
, UVERBS_ACCESS_NEW
, true,
49 DECLARE_UVERBS_NAMED_METHOD(UVERBS_METHOD_INVOKE_WRITE
,
50 UVERBS_ATTR_CONST_IN(UVERBS_ATTR_WRITE_CMD
,
51 enum ib_uverbs_write_cmds
,
53 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_CORE_IN
,
54 UVERBS_ATTR_MIN_SIZE(sizeof(u32
)),
56 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_CORE_OUT
,
57 UVERBS_ATTR_MIN_SIZE(0),
62 gather_objects_handle(struct ib_uverbs_file
*ufile
,
63 const struct uverbs_api_object
*uapi_object
,
64 struct uverbs_attr_bundle
*attrs
,
68 u64 max_count
= out_len
/ sizeof(u32
);
69 struct ib_uobject
*obj
;
73 /* Allocated memory that cannot page out where we gather
74 * all object ids under a spin_lock.
76 handles
= uverbs_zalloc(attrs
, out_len
);
80 spin_lock_irq(&ufile
->uobjects_lock
);
81 list_for_each_entry(obj
, &ufile
->uobjects
, list
) {
84 if (obj
->uapi_object
!= uapi_object
)
87 if (count
>= max_count
)
90 handles
[count
] = obj_id
;
93 spin_unlock_irq(&ufile
->uobjects_lock
);
99 static int UVERBS_HANDLER(UVERBS_METHOD_INFO_HANDLES
)(
100 struct uverbs_attr_bundle
*attrs
)
102 const struct uverbs_api_object
*uapi_object
;
109 out_len
= uverbs_attr_get_len(attrs
, UVERBS_ATTR_INFO_HANDLES_LIST
);
110 if (out_len
<= 0 || (out_len
% sizeof(u32
) != 0))
113 ret
= uverbs_get_const(&object_id
, attrs
, UVERBS_ATTR_INFO_OBJECT_ID
);
117 uapi_object
= uapi_get_object(attrs
->ufile
->device
->uapi
, object_id
);
121 handles
= gather_objects_handle(attrs
->ufile
, uapi_object
, attrs
,
124 return PTR_ERR(handles
);
126 ret
= uverbs_copy_to(attrs
, UVERBS_ATTR_INFO_HANDLES_LIST
, handles
,
127 sizeof(u32
) * total
);
131 ret
= uverbs_copy_to(attrs
, UVERBS_ATTR_INFO_TOTAL_HANDLES
, &total
,
137 void copy_port_attr_to_resp(struct ib_port_attr
*attr
,
138 struct ib_uverbs_query_port_resp
*resp
,
139 struct ib_device
*ib_dev
, u8 port_num
)
141 resp
->state
= attr
->state
;
142 resp
->max_mtu
= attr
->max_mtu
;
143 resp
->active_mtu
= attr
->active_mtu
;
144 resp
->gid_tbl_len
= attr
->gid_tbl_len
;
145 resp
->port_cap_flags
= make_port_cap_flags(attr
);
146 resp
->max_msg_sz
= attr
->max_msg_sz
;
147 resp
->bad_pkey_cntr
= attr
->bad_pkey_cntr
;
148 resp
->qkey_viol_cntr
= attr
->qkey_viol_cntr
;
149 resp
->pkey_tbl_len
= attr
->pkey_tbl_len
;
151 if (rdma_is_grh_required(ib_dev
, port_num
))
152 resp
->flags
|= IB_UVERBS_QPF_GRH_REQUIRED
;
154 if (rdma_cap_opa_ah(ib_dev
, port_num
)) {
155 resp
->lid
= OPA_TO_IB_UCAST_LID(attr
->lid
);
156 resp
->sm_lid
= OPA_TO_IB_UCAST_LID(attr
->sm_lid
);
158 resp
->lid
= ib_lid_cpu16(attr
->lid
);
159 resp
->sm_lid
= ib_lid_cpu16(attr
->sm_lid
);
162 resp
->lmc
= attr
->lmc
;
163 resp
->max_vl_num
= attr
->max_vl_num
;
164 resp
->sm_sl
= attr
->sm_sl
;
165 resp
->subnet_timeout
= attr
->subnet_timeout
;
166 resp
->init_type_reply
= attr
->init_type_reply
;
167 resp
->active_width
= attr
->active_width
;
168 resp
->active_speed
= attr
->active_speed
;
169 resp
->phys_state
= attr
->phys_state
;
170 resp
->link_layer
= rdma_port_get_link_layer(ib_dev
, port_num
);
173 static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_PORT
)(
174 struct uverbs_attr_bundle
*attrs
)
176 struct ib_device
*ib_dev
;
177 struct ib_port_attr attr
= {};
178 struct ib_uverbs_query_port_resp_ex resp
= {};
179 struct ib_ucontext
*ucontext
;
183 ucontext
= ib_uverbs_get_ucontext(attrs
);
184 if (IS_ERR(ucontext
))
185 return PTR_ERR(ucontext
);
186 ib_dev
= ucontext
->device
;
188 /* FIXME: Extend the UAPI_DEF_OBJ_NEEDS_FN stuff.. */
189 if (!ib_dev
->ops
.query_port
)
192 ret
= uverbs_get_const(&port_num
, attrs
,
193 UVERBS_ATTR_QUERY_PORT_PORT_NUM
);
197 ret
= ib_query_port(ib_dev
, port_num
, &attr
);
201 copy_port_attr_to_resp(&attr
, &resp
.legacy_resp
, ib_dev
, port_num
);
202 resp
.port_cap_flags2
= attr
.port_cap_flags2
;
204 return uverbs_copy_to_struct_or_zero(attrs
, UVERBS_ATTR_QUERY_PORT_RESP
,
205 &resp
, sizeof(resp
));
208 static int UVERBS_HANDLER(UVERBS_METHOD_GET_CONTEXT
)(
209 struct uverbs_attr_bundle
*attrs
)
211 u32 num_comp
= attrs
->ufile
->device
->num_comp_vectors
;
212 u64 core_support
= IB_UVERBS_CORE_SUPPORT_OPTIONAL_MR_ACCESS
;
215 ret
= uverbs_copy_to(attrs
, UVERBS_ATTR_GET_CONTEXT_NUM_COMP_VECTORS
,
216 &num_comp
, sizeof(num_comp
));
217 if (IS_UVERBS_COPY_ERR(ret
))
220 ret
= uverbs_copy_to(attrs
, UVERBS_ATTR_GET_CONTEXT_CORE_SUPPORT
,
221 &core_support
, sizeof(core_support
));
222 if (IS_UVERBS_COPY_ERR(ret
))
225 ret
= ib_alloc_ucontext(attrs
);
228 ret
= ib_init_ucontext(attrs
);
230 kfree(attrs
->context
);
231 attrs
->context
= NULL
;
237 static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_CONTEXT
)(
238 struct uverbs_attr_bundle
*attrs
)
240 u64 core_support
= IB_UVERBS_CORE_SUPPORT_OPTIONAL_MR_ACCESS
;
241 struct ib_ucontext
*ucontext
;
242 struct ib_device
*ib_dev
;
246 ucontext
= ib_uverbs_get_ucontext(attrs
);
247 if (IS_ERR(ucontext
))
248 return PTR_ERR(ucontext
);
249 ib_dev
= ucontext
->device
;
251 if (!ib_dev
->ops
.query_ucontext
)
254 num_comp
= attrs
->ufile
->device
->num_comp_vectors
;
255 ret
= uverbs_copy_to(attrs
, UVERBS_ATTR_QUERY_CONTEXT_NUM_COMP_VECTORS
,
256 &num_comp
, sizeof(num_comp
));
257 if (IS_UVERBS_COPY_ERR(ret
))
260 ret
= uverbs_copy_to(attrs
, UVERBS_ATTR_QUERY_CONTEXT_CORE_SUPPORT
,
261 &core_support
, sizeof(core_support
));
262 if (IS_UVERBS_COPY_ERR(ret
))
265 return ucontext
->device
->ops
.query_ucontext(ucontext
, attrs
);
268 DECLARE_UVERBS_NAMED_METHOD(
269 UVERBS_METHOD_GET_CONTEXT
,
270 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_GET_CONTEXT_NUM_COMP_VECTORS
,
271 UVERBS_ATTR_TYPE(u32
), UA_OPTIONAL
),
272 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_GET_CONTEXT_CORE_SUPPORT
,
273 UVERBS_ATTR_TYPE(u64
), UA_OPTIONAL
),
276 DECLARE_UVERBS_NAMED_METHOD(
277 UVERBS_METHOD_QUERY_CONTEXT
,
278 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_QUERY_CONTEXT_NUM_COMP_VECTORS
,
279 UVERBS_ATTR_TYPE(u32
), UA_OPTIONAL
),
280 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_QUERY_CONTEXT_CORE_SUPPORT
,
281 UVERBS_ATTR_TYPE(u64
), UA_OPTIONAL
));
283 DECLARE_UVERBS_NAMED_METHOD(
284 UVERBS_METHOD_INFO_HANDLES
,
285 /* Also includes any device specific object ids */
286 UVERBS_ATTR_CONST_IN(UVERBS_ATTR_INFO_OBJECT_ID
,
287 enum uverbs_default_objects
, UA_MANDATORY
),
288 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_INFO_TOTAL_HANDLES
,
289 UVERBS_ATTR_TYPE(u32
), UA_OPTIONAL
),
290 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_INFO_HANDLES_LIST
,
291 UVERBS_ATTR_MIN_SIZE(sizeof(u32
)), UA_OPTIONAL
));
293 DECLARE_UVERBS_NAMED_METHOD(
294 UVERBS_METHOD_QUERY_PORT
,
295 UVERBS_ATTR_CONST_IN(UVERBS_ATTR_QUERY_PORT_PORT_NUM
, u8
, UA_MANDATORY
),
297 UVERBS_ATTR_QUERY_PORT_RESP
,
298 UVERBS_ATTR_STRUCT(struct ib_uverbs_query_port_resp_ex
,
302 DECLARE_UVERBS_GLOBAL_METHODS(UVERBS_OBJECT_DEVICE
,
303 &UVERBS_METHOD(UVERBS_METHOD_GET_CONTEXT
),
304 &UVERBS_METHOD(UVERBS_METHOD_INVOKE_WRITE
),
305 &UVERBS_METHOD(UVERBS_METHOD_INFO_HANDLES
),
306 &UVERBS_METHOD(UVERBS_METHOD_QUERY_PORT
),
307 &UVERBS_METHOD(UVERBS_METHOD_QUERY_CONTEXT
));
309 const struct uapi_definition uverbs_def_obj_device
[] = {
310 UAPI_DEF_CHAIN_OBJ_TREE_NAMED(UVERBS_OBJECT_DEVICE
),