0001
0002
0003
0004
0005
0006 #ifndef _UVERBS_IOCTL_
0007 #define _UVERBS_IOCTL_
0008
0009 #include <rdma/uverbs_types.h>
0010 #include <linux/uaccess.h>
0011 #include <rdma/rdma_user_ioctl.h>
0012 #include <rdma/ib_user_ioctl_verbs.h>
0013 #include <rdma/ib_user_ioctl_cmds.h>
0014
0015
0016
0017
0018
0019
0020
0021 enum uverbs_attr_type {
0022 UVERBS_ATTR_TYPE_NA,
0023 UVERBS_ATTR_TYPE_PTR_IN,
0024 UVERBS_ATTR_TYPE_PTR_OUT,
0025 UVERBS_ATTR_TYPE_IDR,
0026 UVERBS_ATTR_TYPE_FD,
0027 UVERBS_ATTR_TYPE_ENUM_IN,
0028 UVERBS_ATTR_TYPE_IDRS_ARRAY,
0029 };
0030
0031 enum uverbs_obj_access {
0032 UVERBS_ACCESS_READ,
0033 UVERBS_ACCESS_WRITE,
0034 UVERBS_ACCESS_NEW,
0035 UVERBS_ACCESS_DESTROY
0036 };
0037
0038
0039
0040 struct uverbs_attr_spec {
0041 u8 type;
0042
0043
0044
0045
0046
0047
0048 u8 zero_trailing:1;
0049
0050
0051
0052
0053 u8 alloc_and_copy:1;
0054 u8 mandatory:1;
0055
0056 u8 is_udata:1;
0057
0058 union {
0059 struct {
0060
0061 u16 len;
0062
0063 u16 min_len;
0064 } ptr;
0065
0066 struct {
0067
0068
0069
0070
0071 u16 obj_type;
0072 u8 access;
0073 } obj;
0074
0075 struct {
0076 u8 num_elems;
0077 } enum_def;
0078 } u;
0079
0080
0081 union {
0082 struct {
0083
0084
0085
0086
0087
0088 const struct uverbs_attr_spec *ids;
0089 } enum_def;
0090
0091 struct {
0092
0093
0094
0095
0096 u16 obj_type;
0097 u16 min_len;
0098 u16 max_len;
0099 u8 access;
0100 } objs_arr;
0101 } u2;
0102 };
0103
0104
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126 enum uapi_radix_data {
0127 UVERBS_API_NS_FLAG = 1U << UVERBS_ID_NS_SHIFT,
0128
0129 UVERBS_API_ATTR_KEY_BITS = 6,
0130 UVERBS_API_ATTR_KEY_MASK = GENMASK(UVERBS_API_ATTR_KEY_BITS - 1, 0),
0131 UVERBS_API_ATTR_BKEY_LEN = (1 << UVERBS_API_ATTR_KEY_BITS) - 1,
0132 UVERBS_API_WRITE_KEY_NUM = 1 << UVERBS_API_ATTR_KEY_BITS,
0133
0134 UVERBS_API_METHOD_KEY_BITS = 5,
0135 UVERBS_API_METHOD_KEY_SHIFT = UVERBS_API_ATTR_KEY_BITS,
0136 UVERBS_API_METHOD_KEY_NUM_CORE = 22,
0137 UVERBS_API_METHOD_IS_WRITE = 30 << UVERBS_API_METHOD_KEY_SHIFT,
0138 UVERBS_API_METHOD_IS_WRITE_EX = 31 << UVERBS_API_METHOD_KEY_SHIFT,
0139 UVERBS_API_METHOD_KEY_NUM_DRIVER =
0140 (UVERBS_API_METHOD_IS_WRITE >> UVERBS_API_METHOD_KEY_SHIFT) -
0141 UVERBS_API_METHOD_KEY_NUM_CORE,
0142 UVERBS_API_METHOD_KEY_MASK = GENMASK(
0143 UVERBS_API_METHOD_KEY_BITS + UVERBS_API_METHOD_KEY_SHIFT - 1,
0144 UVERBS_API_METHOD_KEY_SHIFT),
0145
0146 UVERBS_API_OBJ_KEY_BITS = 5,
0147 UVERBS_API_OBJ_KEY_SHIFT =
0148 UVERBS_API_METHOD_KEY_BITS + UVERBS_API_METHOD_KEY_SHIFT,
0149 UVERBS_API_OBJ_KEY_NUM_CORE = 20,
0150 UVERBS_API_OBJ_KEY_NUM_DRIVER =
0151 (1 << UVERBS_API_OBJ_KEY_BITS) - UVERBS_API_OBJ_KEY_NUM_CORE,
0152 UVERBS_API_OBJ_KEY_MASK = GENMASK(31, UVERBS_API_OBJ_KEY_SHIFT),
0153
0154
0155 UVERBS_API_KEY_ERR = 0xFFFFFFFF,
0156 };
0157
0158 static inline __attribute_const__ u32 uapi_key_obj(u32 id)
0159 {
0160 if (id & UVERBS_API_NS_FLAG) {
0161 id &= ~UVERBS_API_NS_FLAG;
0162 if (id >= UVERBS_API_OBJ_KEY_NUM_DRIVER)
0163 return UVERBS_API_KEY_ERR;
0164 id = id + UVERBS_API_OBJ_KEY_NUM_CORE;
0165 } else {
0166 if (id >= UVERBS_API_OBJ_KEY_NUM_CORE)
0167 return UVERBS_API_KEY_ERR;
0168 }
0169
0170 return id << UVERBS_API_OBJ_KEY_SHIFT;
0171 }
0172
0173 static inline __attribute_const__ bool uapi_key_is_object(u32 key)
0174 {
0175 return (key & ~UVERBS_API_OBJ_KEY_MASK) == 0;
0176 }
0177
0178 static inline __attribute_const__ u32 uapi_key_ioctl_method(u32 id)
0179 {
0180 if (id & UVERBS_API_NS_FLAG) {
0181 id &= ~UVERBS_API_NS_FLAG;
0182 if (id >= UVERBS_API_METHOD_KEY_NUM_DRIVER)
0183 return UVERBS_API_KEY_ERR;
0184 id = id + UVERBS_API_METHOD_KEY_NUM_CORE;
0185 } else {
0186 id++;
0187 if (id >= UVERBS_API_METHOD_KEY_NUM_CORE)
0188 return UVERBS_API_KEY_ERR;
0189 }
0190
0191 return id << UVERBS_API_METHOD_KEY_SHIFT;
0192 }
0193
0194 static inline __attribute_const__ u32 uapi_key_write_method(u32 id)
0195 {
0196 if (id >= UVERBS_API_WRITE_KEY_NUM)
0197 return UVERBS_API_KEY_ERR;
0198 return UVERBS_API_METHOD_IS_WRITE | id;
0199 }
0200
0201 static inline __attribute_const__ u32 uapi_key_write_ex_method(u32 id)
0202 {
0203 if (id >= UVERBS_API_WRITE_KEY_NUM)
0204 return UVERBS_API_KEY_ERR;
0205 return UVERBS_API_METHOD_IS_WRITE_EX | id;
0206 }
0207
0208 static inline __attribute_const__ u32
0209 uapi_key_attr_to_ioctl_method(u32 attr_key)
0210 {
0211 return attr_key &
0212 (UVERBS_API_OBJ_KEY_MASK | UVERBS_API_METHOD_KEY_MASK);
0213 }
0214
0215 static inline __attribute_const__ bool uapi_key_is_ioctl_method(u32 key)
0216 {
0217 unsigned int method = key & UVERBS_API_METHOD_KEY_MASK;
0218
0219 return method != 0 && method < UVERBS_API_METHOD_IS_WRITE &&
0220 (key & UVERBS_API_ATTR_KEY_MASK) == 0;
0221 }
0222
0223 static inline __attribute_const__ bool uapi_key_is_write_method(u32 key)
0224 {
0225 return (key & UVERBS_API_METHOD_KEY_MASK) == UVERBS_API_METHOD_IS_WRITE;
0226 }
0227
0228 static inline __attribute_const__ bool uapi_key_is_write_ex_method(u32 key)
0229 {
0230 return (key & UVERBS_API_METHOD_KEY_MASK) ==
0231 UVERBS_API_METHOD_IS_WRITE_EX;
0232 }
0233
0234 static inline __attribute_const__ u32 uapi_key_attrs_start(u32 ioctl_method_key)
0235 {
0236
0237 return ioctl_method_key + 1;
0238 }
0239
0240 static inline __attribute_const__ u32 uapi_key_attr(u32 id)
0241 {
0242
0243
0244
0245
0246
0247
0248 if (id & UVERBS_API_NS_FLAG) {
0249 id &= ~UVERBS_API_NS_FLAG;
0250 id++;
0251 if (id >= 1 << (UVERBS_API_ATTR_KEY_BITS - 1))
0252 return UVERBS_API_KEY_ERR;
0253 id = (id << 1) | 0;
0254 } else {
0255 if (id >= 1 << (UVERBS_API_ATTR_KEY_BITS - 1))
0256 return UVERBS_API_KEY_ERR;
0257 id = (id << 1) | 1;
0258 }
0259
0260 return id;
0261 }
0262
0263
0264 static inline __attribute_const__ bool uapi_key_is_attr(u32 key)
0265 {
0266 unsigned int method = key & UVERBS_API_METHOD_KEY_MASK;
0267
0268 return method != 0 && method < UVERBS_API_METHOD_IS_WRITE &&
0269 (key & UVERBS_API_ATTR_KEY_MASK) != 0;
0270 }
0271
0272
0273
0274
0275
0276
0277
0278 static inline __attribute_const__ u32 uapi_bkey_attr(u32 attr_key)
0279 {
0280 return attr_key - 1;
0281 }
0282
0283 static inline __attribute_const__ u32 uapi_bkey_to_key_attr(u32 attr_bkey)
0284 {
0285 return attr_bkey + 1;
0286 }
0287
0288
0289
0290
0291
0292
0293
0294 struct uverbs_attr_def {
0295 u16 id;
0296 struct uverbs_attr_spec attr;
0297 };
0298
0299 struct uverbs_method_def {
0300 u16 id;
0301
0302 u32 flags;
0303 size_t num_attrs;
0304 const struct uverbs_attr_def * const (*attrs)[];
0305 int (*handler)(struct uverbs_attr_bundle *attrs);
0306 };
0307
0308 struct uverbs_object_def {
0309 u16 id;
0310 const struct uverbs_obj_type *type_attrs;
0311 size_t num_methods;
0312 const struct uverbs_method_def * const (*methods)[];
0313 };
0314
0315 enum uapi_definition_kind {
0316 UAPI_DEF_END = 0,
0317 UAPI_DEF_OBJECT_START,
0318 UAPI_DEF_WRITE,
0319 UAPI_DEF_CHAIN_OBJ_TREE,
0320 UAPI_DEF_CHAIN,
0321 UAPI_DEF_IS_SUPPORTED_FUNC,
0322 UAPI_DEF_IS_SUPPORTED_DEV_FN,
0323 };
0324
0325 enum uapi_definition_scope {
0326 UAPI_SCOPE_OBJECT = 1,
0327 UAPI_SCOPE_METHOD = 2,
0328 };
0329
0330 struct uapi_definition {
0331 u8 kind;
0332 u8 scope;
0333 union {
0334 struct {
0335 u16 object_id;
0336 } object_start;
0337 struct {
0338 u16 command_num;
0339 u8 is_ex:1;
0340 u8 has_udata:1;
0341 u8 has_resp:1;
0342 u8 req_size;
0343 u8 resp_size;
0344 } write;
0345 };
0346
0347 union {
0348 bool (*func_is_supported)(struct ib_device *device);
0349 int (*func_write)(struct uverbs_attr_bundle *attrs);
0350 const struct uapi_definition *chain;
0351 const struct uverbs_object_def *chain_obj_tree;
0352 size_t needs_fn_offset;
0353 };
0354 };
0355
0356
0357 #define DECLARE_UVERBS_OBJECT(_object_id, ...) \
0358 { \
0359 .kind = UAPI_DEF_OBJECT_START, \
0360 .object_start = { .object_id = _object_id }, \
0361 }, \
0362 ##__VA_ARGS__
0363
0364
0365 #define DECLARE_UVERBS_WRITE(_command_num, _func, _cmd_desc, ...) \
0366 { \
0367 .kind = UAPI_DEF_WRITE, \
0368 .scope = UAPI_SCOPE_OBJECT, \
0369 .write = { .is_ex = 0, .command_num = _command_num }, \
0370 .func_write = _func, \
0371 _cmd_desc, \
0372 }, \
0373 ##__VA_ARGS__
0374
0375
0376 #define DECLARE_UVERBS_WRITE_EX(_command_num, _func, _cmd_desc, ...) \
0377 { \
0378 .kind = UAPI_DEF_WRITE, \
0379 .scope = UAPI_SCOPE_OBJECT, \
0380 .write = { .is_ex = 1, .command_num = _command_num }, \
0381 .func_write = _func, \
0382 _cmd_desc, \
0383 }, \
0384 ##__VA_ARGS__
0385
0386
0387
0388
0389
0390 #define UAPI_DEF_OBJ_NEEDS_FN(ibdev_fn) \
0391 { \
0392 .kind = UAPI_DEF_IS_SUPPORTED_DEV_FN, \
0393 .scope = UAPI_SCOPE_OBJECT, \
0394 .needs_fn_offset = \
0395 offsetof(struct ib_device_ops, ibdev_fn) + \
0396 BUILD_BUG_ON_ZERO(sizeof_field(struct ib_device_ops, \
0397 ibdev_fn) != \
0398 sizeof(void *)), \
0399 }
0400
0401
0402
0403
0404
0405 #define UAPI_DEF_METHOD_NEEDS_FN(ibdev_fn) \
0406 { \
0407 .kind = UAPI_DEF_IS_SUPPORTED_DEV_FN, \
0408 .scope = UAPI_SCOPE_METHOD, \
0409 .needs_fn_offset = \
0410 offsetof(struct ib_device_ops, ibdev_fn) + \
0411 BUILD_BUG_ON_ZERO(sizeof_field(struct ib_device_ops, \
0412 ibdev_fn) != \
0413 sizeof(void *)), \
0414 }
0415
0416
0417 #define UAPI_DEF_IS_OBJ_SUPPORTED(_func) \
0418 { \
0419 .kind = UAPI_DEF_IS_SUPPORTED_FUNC, \
0420 .scope = UAPI_SCOPE_OBJECT, .func_is_supported = _func, \
0421 }
0422
0423
0424 #define UAPI_DEF_CHAIN(_def_var) \
0425 { \
0426 .kind = UAPI_DEF_CHAIN, .chain = _def_var, \
0427 }
0428
0429
0430 #define UAPI_DEF_CHAIN_OBJ_TREE(_object_enum, _object_ptr, ...) \
0431 { \
0432 .kind = UAPI_DEF_CHAIN_OBJ_TREE, \
0433 .object_start = { .object_id = _object_enum }, \
0434 .chain_obj_tree = _object_ptr, \
0435 }, \
0436 ##__VA_ARGS__
0437 #define UAPI_DEF_CHAIN_OBJ_TREE_NAMED(_object_enum, ...) \
0438 UAPI_DEF_CHAIN_OBJ_TREE(_object_enum, &UVERBS_OBJECT(_object_enum), \
0439 ##__VA_ARGS__)
0440
0441
0442
0443
0444
0445
0446
0447 #define UVERBS_ATTR_SIZE(_min_len, _len) \
0448 .u.ptr.min_len = _min_len, .u.ptr.len = _len
0449
0450 #define UVERBS_ATTR_NO_DATA() UVERBS_ATTR_SIZE(0, 0)
0451
0452
0453
0454
0455
0456
0457 #define UVERBS_ATTR_TYPE(_type) \
0458 .u.ptr.min_len = sizeof(_type), .u.ptr.len = sizeof(_type)
0459
0460
0461
0462
0463
0464
0465 #define UVERBS_ATTR_STRUCT(_type, _last) \
0466 .zero_trailing = 1, \
0467 UVERBS_ATTR_SIZE(offsetofend(_type, _last), sizeof(_type))
0468
0469
0470
0471
0472 #define UVERBS_ATTR_MIN_SIZE(_min_len) UVERBS_ATTR_SIZE(_min_len, USHRT_MAX)
0473
0474
0475 #define UA_ALLOC_AND_COPY .alloc_and_copy = 1
0476 #define UA_MANDATORY .mandatory = 1
0477 #define UA_OPTIONAL .mandatory = 0
0478
0479
0480
0481
0482
0483 #define UVERBS_ATTR_IDRS_ARR(_attr_id, _idr_type, _access, _min_len, _max_len, \
0484 ...) \
0485 (&(const struct uverbs_attr_def){ \
0486 .id = (_attr_id) + \
0487 BUILD_BUG_ON_ZERO((_min_len) == 0 || \
0488 (_max_len) > \
0489 PAGE_SIZE / sizeof(void *) || \
0490 (_min_len) > (_max_len) || \
0491 (_access) == UVERBS_ACCESS_NEW || \
0492 (_access) == UVERBS_ACCESS_DESTROY), \
0493 .attr = { .type = UVERBS_ATTR_TYPE_IDRS_ARRAY, \
0494 .u2.objs_arr.obj_type = _idr_type, \
0495 .u2.objs_arr.access = _access, \
0496 .u2.objs_arr.min_len = _min_len, \
0497 .u2.objs_arr.max_len = _max_len, \
0498 __VA_ARGS__ } })
0499
0500
0501
0502
0503
0504 #define UVERBS_IDR_ANY_OBJECT 0xFFFF
0505
0506 #define UVERBS_ATTR_IDR(_attr_id, _idr_type, _access, ...) \
0507 (&(const struct uverbs_attr_def){ \
0508 .id = _attr_id, \
0509 .attr = { .type = UVERBS_ATTR_TYPE_IDR, \
0510 .u.obj.obj_type = _idr_type, \
0511 .u.obj.access = _access, \
0512 __VA_ARGS__ } })
0513
0514 #define UVERBS_ATTR_FD(_attr_id, _fd_type, _access, ...) \
0515 (&(const struct uverbs_attr_def){ \
0516 .id = (_attr_id) + \
0517 BUILD_BUG_ON_ZERO((_access) != UVERBS_ACCESS_NEW && \
0518 (_access) != UVERBS_ACCESS_READ), \
0519 .attr = { .type = UVERBS_ATTR_TYPE_FD, \
0520 .u.obj.obj_type = _fd_type, \
0521 .u.obj.access = _access, \
0522 __VA_ARGS__ } })
0523
0524 #define UVERBS_ATTR_PTR_IN(_attr_id, _type, ...) \
0525 (&(const struct uverbs_attr_def){ \
0526 .id = _attr_id, \
0527 .attr = { .type = UVERBS_ATTR_TYPE_PTR_IN, \
0528 _type, \
0529 __VA_ARGS__ } })
0530
0531 #define UVERBS_ATTR_PTR_OUT(_attr_id, _type, ...) \
0532 (&(const struct uverbs_attr_def){ \
0533 .id = _attr_id, \
0534 .attr = { .type = UVERBS_ATTR_TYPE_PTR_OUT, \
0535 _type, \
0536 __VA_ARGS__ } })
0537
0538
0539 #define UVERBS_ATTR_ENUM_IN(_attr_id, _enum_arr, ...) \
0540 (&(const struct uverbs_attr_def){ \
0541 .id = _attr_id, \
0542 .attr = { .type = UVERBS_ATTR_TYPE_ENUM_IN, \
0543 .u2.enum_def.ids = _enum_arr, \
0544 .u.enum_def.num_elems = ARRAY_SIZE(_enum_arr), \
0545 __VA_ARGS__ }, \
0546 })
0547
0548
0549 #define UVERBS_ATTR_CONST_IN(_attr_id, _enum_type, ...) \
0550 UVERBS_ATTR_PTR_IN( \
0551 _attr_id, \
0552 UVERBS_ATTR_SIZE( \
0553 sizeof(u64) + BUILD_BUG_ON_ZERO(!sizeof(_enum_type)), \
0554 sizeof(u64)), \
0555 __VA_ARGS__)
0556
0557
0558
0559
0560
0561
0562 #define UVERBS_ATTR_FLAGS_IN(_attr_id, _enum_type, ...) \
0563 UVERBS_ATTR_PTR_IN( \
0564 _attr_id, \
0565 UVERBS_ATTR_SIZE(sizeof(u32) + BUILD_BUG_ON_ZERO( \
0566 !sizeof(_enum_type *)), \
0567 sizeof(u64)), \
0568 __VA_ARGS__)
0569
0570
0571
0572
0573
0574
0575 #define UVERBS_ATTR_UHW() \
0576 UVERBS_ATTR_PTR_IN(UVERBS_ATTR_UHW_IN, \
0577 UVERBS_ATTR_MIN_SIZE(0), \
0578 UA_OPTIONAL, \
0579 .is_udata = 1), \
0580 UVERBS_ATTR_PTR_OUT(UVERBS_ATTR_UHW_OUT, \
0581 UVERBS_ATTR_MIN_SIZE(0), \
0582 UA_OPTIONAL, \
0583 .is_udata = 1)
0584
0585
0586
0587
0588
0589
0590
0591 struct uverbs_ptr_attr {
0592
0593
0594
0595
0596 union {
0597 void *ptr;
0598 u64 data;
0599 };
0600 u16 len;
0601 u16 uattr_idx;
0602 u8 enum_id;
0603 };
0604
0605 struct uverbs_obj_attr {
0606 struct ib_uobject *uobject;
0607 const struct uverbs_api_attr *attr_elm;
0608 };
0609
0610 struct uverbs_objs_arr_attr {
0611 struct ib_uobject **uobjects;
0612 u16 len;
0613 };
0614
0615 struct uverbs_attr {
0616 union {
0617 struct uverbs_ptr_attr ptr_attr;
0618 struct uverbs_obj_attr obj_attr;
0619 struct uverbs_objs_arr_attr objs_arr_attr;
0620 };
0621 };
0622
0623 struct uverbs_attr_bundle {
0624 struct ib_udata driver_udata;
0625 struct ib_udata ucore;
0626 struct ib_uverbs_file *ufile;
0627 struct ib_ucontext *context;
0628 struct ib_uobject *uobject;
0629 DECLARE_BITMAP(attr_present, UVERBS_API_ATTR_BKEY_LEN);
0630 struct uverbs_attr attrs[];
0631 };
0632
0633 static inline bool uverbs_attr_is_valid(const struct uverbs_attr_bundle *attrs_bundle,
0634 unsigned int idx)
0635 {
0636 return test_bit(uapi_bkey_attr(uapi_key_attr(idx)),
0637 attrs_bundle->attr_present);
0638 }
0639
0640
0641
0642
0643
0644
0645
0646
0647
0648
0649
0650 static inline struct uverbs_attr_bundle *
0651 rdma_udata_to_uverbs_attr_bundle(struct ib_udata *udata)
0652 {
0653 return container_of(udata, struct uverbs_attr_bundle, driver_udata);
0654 }
0655
0656 #define rdma_udata_to_drv_context(udata, drv_dev_struct, member) \
0657 (udata ? container_of(rdma_udata_to_uverbs_attr_bundle(udata)->context, \
0658 drv_dev_struct, member) : (drv_dev_struct *)NULL)
0659
0660 #define IS_UVERBS_COPY_ERR(_ret) ((_ret) && (_ret) != -ENOENT)
0661
0662 static inline const struct uverbs_attr *uverbs_attr_get(const struct uverbs_attr_bundle *attrs_bundle,
0663 u16 idx)
0664 {
0665 if (!uverbs_attr_is_valid(attrs_bundle, idx))
0666 return ERR_PTR(-ENOENT);
0667
0668 return &attrs_bundle->attrs[uapi_bkey_attr(uapi_key_attr(idx))];
0669 }
0670
0671 static inline int uverbs_attr_get_enum_id(const struct uverbs_attr_bundle *attrs_bundle,
0672 u16 idx)
0673 {
0674 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
0675
0676 if (IS_ERR(attr))
0677 return PTR_ERR(attr);
0678
0679 return attr->ptr_attr.enum_id;
0680 }
0681
0682 static inline void *uverbs_attr_get_obj(const struct uverbs_attr_bundle *attrs_bundle,
0683 u16 idx)
0684 {
0685 const struct uverbs_attr *attr;
0686
0687 attr = uverbs_attr_get(attrs_bundle, idx);
0688 if (IS_ERR(attr))
0689 return ERR_CAST(attr);
0690
0691 return attr->obj_attr.uobject->object;
0692 }
0693
0694 static inline struct ib_uobject *uverbs_attr_get_uobject(const struct uverbs_attr_bundle *attrs_bundle,
0695 u16 idx)
0696 {
0697 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
0698
0699 if (IS_ERR(attr))
0700 return ERR_CAST(attr);
0701
0702 return attr->obj_attr.uobject;
0703 }
0704
0705 static inline int
0706 uverbs_attr_get_len(const struct uverbs_attr_bundle *attrs_bundle, u16 idx)
0707 {
0708 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
0709
0710 if (IS_ERR(attr))
0711 return PTR_ERR(attr);
0712
0713 return attr->ptr_attr.len;
0714 }
0715
0716 void uverbs_finalize_uobj_create(const struct uverbs_attr_bundle *attrs_bundle,
0717 u16 idx);
0718
0719
0720
0721
0722
0723
0724
0725
0726 static inline int
0727 uverbs_attr_ptr_get_array_size(struct uverbs_attr_bundle *attrs, u16 idx,
0728 size_t elem_size)
0729 {
0730 int size = uverbs_attr_get_len(attrs, idx);
0731
0732 if (size < 0)
0733 return size;
0734
0735 if (size % elem_size)
0736 return -EINVAL;
0737
0738 return size / elem_size;
0739 }
0740
0741
0742
0743
0744
0745
0746
0747
0748
0749 static inline int uverbs_attr_get_uobjs_arr(
0750 const struct uverbs_attr_bundle *attrs_bundle, u16 attr_idx,
0751 struct ib_uobject ***arr)
0752 {
0753 const struct uverbs_attr *attr =
0754 uverbs_attr_get(attrs_bundle, attr_idx);
0755
0756 if (IS_ERR(attr)) {
0757 *arr = NULL;
0758 return 0;
0759 }
0760
0761 *arr = attr->objs_arr_attr.uobjects;
0762
0763 return attr->objs_arr_attr.len;
0764 }
0765
0766 static inline bool uverbs_attr_ptr_is_inline(const struct uverbs_attr *attr)
0767 {
0768 return attr->ptr_attr.len <= sizeof(attr->ptr_attr.data);
0769 }
0770
0771 static inline void *uverbs_attr_get_alloced_ptr(
0772 const struct uverbs_attr_bundle *attrs_bundle, u16 idx)
0773 {
0774 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
0775
0776 if (IS_ERR(attr))
0777 return (void *)attr;
0778
0779 return uverbs_attr_ptr_is_inline(attr) ? (void *)&attr->ptr_attr.data :
0780 attr->ptr_attr.ptr;
0781 }
0782
0783 static inline int _uverbs_copy_from(void *to,
0784 const struct uverbs_attr_bundle *attrs_bundle,
0785 size_t idx,
0786 size_t size)
0787 {
0788 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
0789
0790 if (IS_ERR(attr))
0791 return PTR_ERR(attr);
0792
0793
0794
0795
0796
0797
0798 if (unlikely(size < attr->ptr_attr.len))
0799 return -EINVAL;
0800
0801 if (uverbs_attr_ptr_is_inline(attr))
0802 memcpy(to, &attr->ptr_attr.data, attr->ptr_attr.len);
0803 else if (copy_from_user(to, u64_to_user_ptr(attr->ptr_attr.data),
0804 attr->ptr_attr.len))
0805 return -EFAULT;
0806
0807 return 0;
0808 }
0809
0810 static inline int _uverbs_copy_from_or_zero(void *to,
0811 const struct uverbs_attr_bundle *attrs_bundle,
0812 size_t idx,
0813 size_t size)
0814 {
0815 const struct uverbs_attr *attr = uverbs_attr_get(attrs_bundle, idx);
0816 size_t min_size;
0817
0818 if (IS_ERR(attr))
0819 return PTR_ERR(attr);
0820
0821 min_size = min_t(size_t, size, attr->ptr_attr.len);
0822
0823 if (uverbs_attr_ptr_is_inline(attr))
0824 memcpy(to, &attr->ptr_attr.data, min_size);
0825 else if (copy_from_user(to, u64_to_user_ptr(attr->ptr_attr.data),
0826 min_size))
0827 return -EFAULT;
0828
0829 if (size > min_size)
0830 memset(to + min_size, 0, size - min_size);
0831
0832 return 0;
0833 }
0834
0835 #define uverbs_copy_from(to, attrs_bundle, idx) \
0836 _uverbs_copy_from(to, attrs_bundle, idx, sizeof(*to))
0837
0838 #define uverbs_copy_from_or_zero(to, attrs_bundle, idx) \
0839 _uverbs_copy_from_or_zero(to, attrs_bundle, idx, sizeof(*to))
0840
0841 static inline struct ib_ucontext *
0842 ib_uverbs_get_ucontext(const struct uverbs_attr_bundle *attrs)
0843 {
0844 return ib_uverbs_get_ucontext_file(attrs->ufile);
0845 }
0846
0847 #if IS_ENABLED(CONFIG_INFINIBAND_USER_ACCESS)
0848 int uverbs_get_flags64(u64 *to, const struct uverbs_attr_bundle *attrs_bundle,
0849 size_t idx, u64 allowed_bits);
0850 int uverbs_get_flags32(u32 *to, const struct uverbs_attr_bundle *attrs_bundle,
0851 size_t idx, u64 allowed_bits);
0852 int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle, size_t idx,
0853 const void *from, size_t size);
0854 __malloc void *_uverbs_alloc(struct uverbs_attr_bundle *bundle, size_t size,
0855 gfp_t flags);
0856
0857 static inline __malloc void *uverbs_alloc(struct uverbs_attr_bundle *bundle,
0858 size_t size)
0859 {
0860 return _uverbs_alloc(bundle, size, GFP_KERNEL);
0861 }
0862
0863 static inline __malloc void *uverbs_zalloc(struct uverbs_attr_bundle *bundle,
0864 size_t size)
0865 {
0866 return _uverbs_alloc(bundle, size, GFP_KERNEL | __GFP_ZERO);
0867 }
0868
0869 static inline __malloc void *uverbs_kcalloc(struct uverbs_attr_bundle *bundle,
0870 size_t n, size_t size)
0871 {
0872 size_t bytes;
0873
0874 if (unlikely(check_mul_overflow(n, size, &bytes)))
0875 return ERR_PTR(-EOVERFLOW);
0876 return uverbs_zalloc(bundle, bytes);
0877 }
0878
0879 int _uverbs_get_const_signed(s64 *to,
0880 const struct uverbs_attr_bundle *attrs_bundle,
0881 size_t idx, s64 lower_bound, u64 upper_bound,
0882 s64 *def_val);
0883 int _uverbs_get_const_unsigned(u64 *to,
0884 const struct uverbs_attr_bundle *attrs_bundle,
0885 size_t idx, u64 upper_bound, u64 *def_val);
0886 int uverbs_copy_to_struct_or_zero(const struct uverbs_attr_bundle *bundle,
0887 size_t idx, const void *from, size_t size);
0888 #else
0889 static inline int
0890 uverbs_get_flags64(u64 *to, const struct uverbs_attr_bundle *attrs_bundle,
0891 size_t idx, u64 allowed_bits)
0892 {
0893 return -EINVAL;
0894 }
0895 static inline int
0896 uverbs_get_flags32(u32 *to, const struct uverbs_attr_bundle *attrs_bundle,
0897 size_t idx, u64 allowed_bits)
0898 {
0899 return -EINVAL;
0900 }
0901 static inline int uverbs_copy_to(const struct uverbs_attr_bundle *attrs_bundle,
0902 size_t idx, const void *from, size_t size)
0903 {
0904 return -EINVAL;
0905 }
0906 static inline __malloc void *uverbs_alloc(struct uverbs_attr_bundle *bundle,
0907 size_t size)
0908 {
0909 return ERR_PTR(-EINVAL);
0910 }
0911 static inline __malloc void *uverbs_zalloc(struct uverbs_attr_bundle *bundle,
0912 size_t size)
0913 {
0914 return ERR_PTR(-EINVAL);
0915 }
0916 static inline int
0917 _uverbs_get_const(s64 *to, const struct uverbs_attr_bundle *attrs_bundle,
0918 size_t idx, s64 lower_bound, u64 upper_bound,
0919 s64 *def_val)
0920 {
0921 return -EINVAL;
0922 }
0923 static inline int
0924 uverbs_copy_to_struct_or_zero(const struct uverbs_attr_bundle *bundle,
0925 size_t idx, const void *from, size_t size)
0926 {
0927 return -EINVAL;
0928 }
0929 static inline int
0930 _uverbs_get_const_signed(s64 *to,
0931 const struct uverbs_attr_bundle *attrs_bundle,
0932 size_t idx, s64 lower_bound, u64 upper_bound,
0933 s64 *def_val)
0934 {
0935 return -EINVAL;
0936 }
0937 static inline int
0938 _uverbs_get_const_unsigned(u64 *to,
0939 const struct uverbs_attr_bundle *attrs_bundle,
0940 size_t idx, u64 upper_bound, u64 *def_val)
0941 {
0942 return -EINVAL;
0943 }
0944 #endif
0945
0946 #define uverbs_get_const_signed(_to, _attrs_bundle, _idx) \
0947 ({ \
0948 s64 _val; \
0949 int _ret = \
0950 _uverbs_get_const_signed(&_val, _attrs_bundle, _idx, \
0951 type_min(typeof(*(_to))), \
0952 type_max(typeof(*(_to))), NULL); \
0953 (*(_to)) = _val; \
0954 _ret; \
0955 })
0956
0957 #define uverbs_get_const_unsigned(_to, _attrs_bundle, _idx) \
0958 ({ \
0959 u64 _val; \
0960 int _ret = \
0961 _uverbs_get_const_unsigned(&_val, _attrs_bundle, _idx, \
0962 type_max(typeof(*(_to))), NULL); \
0963 (*(_to)) = _val; \
0964 _ret; \
0965 })
0966
0967 #define uverbs_get_const_default_signed(_to, _attrs_bundle, _idx, _default) \
0968 ({ \
0969 s64 _val; \
0970 s64 _def_val = _default; \
0971 int _ret = \
0972 _uverbs_get_const_signed(&_val, _attrs_bundle, _idx, \
0973 type_min(typeof(*(_to))), \
0974 type_max(typeof(*(_to))), &_def_val); \
0975 (*(_to)) = _val; \
0976 _ret; \
0977 })
0978
0979 #define uverbs_get_const_default_unsigned(_to, _attrs_bundle, _idx, _default) \
0980 ({ \
0981 u64 _val; \
0982 u64 _def_val = _default; \
0983 int _ret = \
0984 _uverbs_get_const_unsigned(&_val, _attrs_bundle, _idx, \
0985 type_max(typeof(*(_to))), &_def_val); \
0986 (*(_to)) = _val; \
0987 _ret; \
0988 })
0989
0990 #define uverbs_get_const(_to, _attrs_bundle, _idx) \
0991 (is_signed_type(typeof(*(_to))) ? \
0992 uverbs_get_const_signed(_to, _attrs_bundle, _idx) : \
0993 uverbs_get_const_unsigned(_to, _attrs_bundle, _idx)) \
0994
0995 #define uverbs_get_const_default(_to, _attrs_bundle, _idx, _default) \
0996 (is_signed_type(typeof(*(_to))) ? \
0997 uverbs_get_const_default_signed(_to, _attrs_bundle, _idx, \
0998 _default) : \
0999 uverbs_get_const_default_unsigned(_to, _attrs_bundle, _idx, \
1000 _default))
1001
1002 #endif