diff options
author | Matan Barak <matanb@mellanox.com> | 2017-08-03 09:07:04 -0400 |
---|---|---|
committer | Doug Ledford <dledford@redhat.com> | 2017-08-31 08:35:13 -0400 |
commit | d70724f149b107f8e4062320270d3d8b6713a1bb (patch) | |
tree | 8424166e2e28c3f99666db14f7afd20e290b1fa1 | |
parent | 64b19e1323e96c34af7ca90d1954e70890c7a98e (diff) |
IB/core: Add legacy driver's user-data
In this phase, we don't want to change all the drivers to use
flexible driver's specific attributes. Therefore, we add two default
attributes: UHW_IN and UHW_OUT. These attributes are optional in some
methods and they encode the driver specific command data. We add
a function that extract this data and creates the legacy udata over
it.
Driver's data should start from UVERBS_UDATA_DRIVER_DATA_FLAG. This
turns on the first bit of the namespace, indicating this attribute
belongs to the driver's namespace.
Signed-off-by: Matan Barak <matanb@mellanox.com>
Reviewed-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
-rw-r--r-- | drivers/infiniband/core/uverbs_std_types.c | 40 | ||||
-rw-r--r-- | include/rdma/uverbs_ioctl.h | 46 | ||||
-rw-r--r-- | include/uapi/rdma/ib_user_ioctl_verbs.h | 10 |
3 files changed, 96 insertions, 0 deletions
diff --git a/drivers/infiniband/core/uverbs_std_types.c b/drivers/infiniband/core/uverbs_std_types.c index 5f90978bda8d..db66c18857e4 100644 --- a/drivers/infiniband/core/uverbs_std_types.c +++ b/drivers/infiniband/core/uverbs_std_types.c | |||
@@ -209,6 +209,46 @@ static int uverbs_hot_unplug_completion_event_file(struct ib_uobject_file *uobj_ | |||
209 | return 0; | 209 | return 0; |
210 | }; | 210 | }; |
211 | 211 | ||
212 | /* | ||
213 | * This spec is used in order to pass information to the hardware driver in a | ||
214 | * legacy way. Every verb that could get driver specific data should get this | ||
215 | * spec. | ||
216 | */ | ||
217 | static const struct uverbs_attr_def uverbs_uhw_compat_in = | ||
218 | UVERBS_ATTR_PTR_IN_SZ(UVERBS_UHW_IN, 0, UA_FLAGS(UVERBS_ATTR_SPEC_F_MIN_SZ)); | ||
219 | static const struct uverbs_attr_def uverbs_uhw_compat_out = | ||
220 | UVERBS_ATTR_PTR_OUT_SZ(UVERBS_UHW_OUT, 0, UA_FLAGS(UVERBS_ATTR_SPEC_F_MIN_SZ)); | ||
221 | |||
222 | static void create_udata(struct uverbs_attr_bundle *ctx, | ||
223 | struct ib_udata *udata) | ||
224 | { | ||
225 | /* | ||
226 | * This is for ease of conversion. The purpose is to convert all drivers | ||
227 | * to use uverbs_attr_bundle instead of ib_udata. | ||
228 | * Assume attr == 0 is input and attr == 1 is output. | ||
229 | */ | ||
230 | void __user *inbuf; | ||
231 | size_t inbuf_len = 0; | ||
232 | void __user *outbuf; | ||
233 | size_t outbuf_len = 0; | ||
234 | const struct uverbs_attr *uhw_in = | ||
235 | uverbs_attr_get(ctx, UVERBS_UHW_IN); | ||
236 | const struct uverbs_attr *uhw_out = | ||
237 | uverbs_attr_get(ctx, UVERBS_UHW_OUT); | ||
238 | |||
239 | if (!IS_ERR(uhw_in)) { | ||
240 | inbuf = uhw_in->ptr_attr.ptr; | ||
241 | inbuf_len = uhw_in->ptr_attr.len; | ||
242 | } | ||
243 | |||
244 | if (!IS_ERR(uhw_out)) { | ||
245 | outbuf = uhw_out->ptr_attr.ptr; | ||
246 | outbuf_len = uhw_out->ptr_attr.len; | ||
247 | } | ||
248 | |||
249 | INIT_UDATA_BUF_OR_NULL(udata, inbuf, outbuf, inbuf_len, outbuf_len); | ||
250 | } | ||
251 | |||
212 | DECLARE_UVERBS_OBJECT(uverbs_object_comp_channel, | 252 | DECLARE_UVERBS_OBJECT(uverbs_object_comp_channel, |
213 | UVERBS_OBJECT_COMP_CHANNEL, | 253 | UVERBS_OBJECT_COMP_CHANNEL, |
214 | &UVERBS_TYPE_ALLOC_FD(0, | 254 | &UVERBS_TYPE_ALLOC_FD(0, |
diff --git a/include/rdma/uverbs_ioctl.h b/include/rdma/uverbs_ioctl.h index 9a8d217cdc1d..759afa0621ea 100644 --- a/include/rdma/uverbs_ioctl.h +++ b/include/rdma/uverbs_ioctl.h | |||
@@ -36,6 +36,7 @@ | |||
36 | #include <rdma/uverbs_types.h> | 36 | #include <rdma/uverbs_types.h> |
37 | #include <linux/uaccess.h> | 37 | #include <linux/uaccess.h> |
38 | #include <rdma/rdma_user_ioctl.h> | 38 | #include <rdma/rdma_user_ioctl.h> |
39 | #include <rdma/ib_user_ioctl_verbs.h> | ||
39 | 40 | ||
40 | /* | 41 | /* |
41 | * ======================================= | 42 | * ======================================= |
@@ -338,6 +339,51 @@ static inline bool uverbs_attr_is_valid(const struct uverbs_attr_bundle *attrs_b | |||
338 | idx & ~UVERBS_ID_NS_MASK); | 339 | idx & ~UVERBS_ID_NS_MASK); |
339 | } | 340 | } |
340 | 341 | ||
342 | static inline const struct uverbs_attr *uverbs_attr_get(const struct uverbs_attr_bundle *attrs_bundle, | ||
343 | u16 idx) | ||
344 | { | ||
345 | u16 idx_bucket = idx >> UVERBS_ID_NS_SHIFT; | ||
346 | |||
347 | if (!uverbs_attr_is_valid(attrs_bundle, idx)) | ||
348 | return ERR_PTR(-ENOENT); | ||
349 | |||
350 | return &attrs_bundle->hash[idx_bucket].attrs[idx & ~UVERBS_ID_NS_MASK]; | ||
351 | } | ||
352 | |||
353 | static inline int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle, | ||
354 | size_t idx, const void *from) | ||
355 | { | ||
356 | const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx); | ||
357 | u16 flags; | ||
358 | |||
359 | if (IS_ERR(attr)) | ||
360 | return PTR_ERR(attr); | ||
361 | |||
362 | flags = attr->ptr_attr.flags | UVERBS_ATTR_F_VALID_OUTPUT; | ||
363 | return (!copy_to_user(attr->ptr_attr.ptr, from, attr->ptr_attr.len) && | ||
364 | !put_user(flags, &attr->uattr->flags)) ? 0 : -EFAULT; | ||
365 | } | ||
366 | |||
367 | static inline int _uverbs_copy_from(void *to, size_t to_size, | ||
368 | const struct uverbs_attr_bundle *attrs_bundle, | ||
369 | size_t idx) | ||
370 | { | ||
371 | const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx); | ||
372 | |||
373 | if (IS_ERR(attr)) | ||
374 | return PTR_ERR(attr); | ||
375 | |||
376 | if (to_size <= sizeof(((struct ib_uverbs_attr *)0)->data)) | ||
377 | memcpy(to, &attr->ptr_attr.data, attr->ptr_attr.len); | ||
378 | else if (copy_from_user(to, attr->ptr_attr.ptr, attr->ptr_attr.len)) | ||
379 | return -EFAULT; | ||
380 | |||
381 | return 0; | ||
382 | } | ||
383 | |||
384 | #define uverbs_copy_from(to, attrs_bundle, idx) \ | ||
385 | _uverbs_copy_from(to, sizeof(*(to)), attrs_bundle, idx) | ||
386 | |||
341 | /* ================================================= | 387 | /* ================================================= |
342 | * Definitions -> Specs infrastructure | 388 | * Definitions -> Specs infrastructure |
343 | * ================================================= | 389 | * ================================================= |
diff --git a/include/uapi/rdma/ib_user_ioctl_verbs.h b/include/uapi/rdma/ib_user_ioctl_verbs.h index 78a2e5be4d6e..90f81eeca35b 100644 --- a/include/uapi/rdma/ib_user_ioctl_verbs.h +++ b/include/uapi/rdma/ib_user_ioctl_verbs.h | |||
@@ -33,6 +33,11 @@ | |||
33 | #ifndef IB_USER_IOCTL_VERBS_H | 33 | #ifndef IB_USER_IOCTL_VERBS_H |
34 | #define IB_USER_IOCTL_VERBS_H | 34 | #define IB_USER_IOCTL_VERBS_H |
35 | 35 | ||
36 | #include <rdma/rdma_user_ioctl.h> | ||
37 | |||
38 | #define UVERBS_UDATA_DRIVER_DATA_NS 1 | ||
39 | #define UVERBS_UDATA_DRIVER_DATA_FLAG (1UL << UVERBS_ID_NS_SHIFT) | ||
40 | |||
36 | enum uverbs_default_objects { | 41 | enum uverbs_default_objects { |
37 | UVERBS_OBJECT_DEVICE, /* No instances of DEVICE are allowed */ | 42 | UVERBS_OBJECT_DEVICE, /* No instances of DEVICE are allowed */ |
38 | UVERBS_OBJECT_PD, | 43 | UVERBS_OBJECT_PD, |
@@ -50,5 +55,10 @@ enum uverbs_default_objects { | |||
50 | UVERBS_OBJECT_LAST, | 55 | UVERBS_OBJECT_LAST, |
51 | }; | 56 | }; |
52 | 57 | ||
58 | enum { | ||
59 | UVERBS_UHW_IN = UVERBS_UDATA_DRIVER_DATA_FLAG, | ||
60 | UVERBS_UHW_OUT, | ||
61 | }; | ||
62 | |||
53 | #endif | 63 | #endif |
54 | 64 | ||