diff options
author | Jason Gunthorpe <jgg@mellanox.com> | 2018-07-04 07:50:25 +0200 |
---|---|---|
committer | Jason Gunthorpe <jgg@mellanox.com> | 2018-07-04 21:47:01 +0200 |
commit | d108dac08085b6fe3947df9625c76fc9f66c1bbb (patch) | |
tree | a0bac15e73129dbb54ddf5bf0e9b5653e79d488e /include/rdma/uverbs_ioctl.h | |
parent | RDMA/uverbs: Split UVERBS_ATTR_FLOW_ACTION_ESP_HANDLE (diff) | |
download | linux-d108dac08085b6fe3947df9625c76fc9f66c1bbb.tar.xz linux-d108dac08085b6fe3947df9625c76fc9f66c1bbb.zip |
RDMA/uverbs: Simplify UVERBS_ATTR family of macros
Instead of using a complex cascade of macros, just directly provide the
initializer list each of the declarations is trying to create.
Now that the macros are simplified this also reworks the uverbs_attr_spec
to be friendly to older compilers by eliminating any unnamed
structures/unions inside, and removing the duplication of some fields. The
structure size remains at 16 bytes which was the original motivation for
some of this oddness.
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Diffstat (limited to 'include/rdma/uverbs_ioctl.h')
-rw-r--r-- | include/rdma/uverbs_ioctl.h | 172 |
1 files changed, 74 insertions, 98 deletions
diff --git a/include/rdma/uverbs_ioctl.h b/include/rdma/uverbs_ioctl.h index 90a4947ff548..a7246e9cb148 100644 --- a/include/rdma/uverbs_ioctl.h +++ b/include/rdma/uverbs_ioctl.h @@ -73,46 +73,42 @@ enum { /* Specification of a single attribute inside the ioctl message */ struct uverbs_attr_spec { + u8 type; + u8 flags; + union { - /* Header shared by all following union members - to reduce space. */ - struct { - enum uverbs_attr_type type; - /* Combination of bits from enum UVERBS_ATTR_SPEC_F_XXXX */ - u8 flags; - }; struct { - enum uverbs_attr_type type; - /* Combination of bits from enum UVERBS_ATTR_SPEC_F_XXXX */ - u8 flags; /* Current known size to kernel */ - u16 len; + u16 len; /* User isn't allowed to provide something < min_len */ - u16 min_len; + u16 min_len; } ptr; + struct { - enum uverbs_attr_type type; - /* Combination of bits from enum UVERBS_ATTR_SPEC_F_XXXX */ - u8 flags; /* * higher bits mean the namespace and lower bits mean * the type id within the namespace. */ - u16 obj_type; - u8 access; + u16 obj_type; + u8 access; } obj; + + struct { + u8 num_elems; + } enum_def; + } u; + + /* This weird split of the enum lets us remove some padding */ + union { struct { - enum uverbs_attr_type type; - /* Combination of bits from enum UVERBS_ATTR_SPEC_F_XXXX */ - u8 flags; - u8 num_elems; /* * The enum attribute can select one of the attributes * contained in the ids array. Currently only PTR_IN * attributes are supported in the ids array. */ - const struct uverbs_attr_spec *ids; + const struct uverbs_attr_spec *ids; } enum_def; - }; + } u2; }; struct uverbs_attr_spec_hash { @@ -196,92 +192,72 @@ struct uverbs_object_tree_def { const struct uverbs_object_def * const (*objects)[]; }; -#define UA_FLAGS(_flags) .flags = _flags -#define __UVERBS_ATTR0(_id, _type, _fld, _attr, ...) \ - ((const struct uverbs_attr_def) \ - {.id = _id, .attr = {{._fld = {.type = _type, _attr, .flags = 0, } }, } }) -#define __UVERBS_ATTR1(_id, _type, _fld, _attr, _extra1, ...) \ - ((const struct uverbs_attr_def) \ - {.id = _id, .attr = {{._fld = {.type = _type, _attr, _extra1 } },} }) -#define __UVERBS_ATTR2(_id, _type, _fld, _attr, _extra1, _extra2) \ - ((const struct uverbs_attr_def) \ - {.id = _id, .attr = {{._fld = {.type = _type, _attr, _extra1, _extra2 } },} }) -#define __UVERBS_ATTR(_id, _type, _fld, _attr, _extra1, _extra2, _n, ...) \ - __UVERBS_ATTR##_n(_id, _type, _fld, _attr, _extra1, _extra2) +/* + * ======================================= + * Attribute Specifications + * ======================================= + */ +/* Use in the _type parameter for attribute specifications */ #define UVERBS_ATTR_TYPE(_type) \ - .min_len = sizeof(_type), .len = sizeof(_type) + .u.ptr.min_len = sizeof(_type), .u.ptr.len = sizeof(_type) #define UVERBS_ATTR_STRUCT(_type, _last) \ - .min_len = ((uintptr_t)(&((_type *)0)->_last + 1)), .len = sizeof(_type) + .u.ptr.min_len = ((uintptr_t)(&((_type *)0)->_last + 1)), .u.ptr.len = sizeof(_type) #define UVERBS_ATTR_SIZE(_min_len, _len) \ - .min_len = _min_len, .len = _len + .u.ptr.min_len = _min_len, .u.ptr.len = _len #define UVERBS_ATTR_MIN_SIZE(_min_len) \ UVERBS_ATTR_SIZE(_min_len, USHRT_MAX) -/* - * In new compiler, UVERBS_ATTR could be simplified by declaring it as - * [_id] = {.type = _type, .len = _len, ##__VA_ARGS__} - * But since we support older compilers too, we need the more complex code. - */ -#define UVERBS_ATTR(_id, _type, _fld, _attr, ...) \ - __UVERBS_ATTR(_id, _type, _fld, _attr, ##__VA_ARGS__, 2, 1, 0) -#define UVERBS_ATTR_PTR_IN_SZ(_id, _len, ...) \ - UVERBS_ATTR(_id, UVERBS_ATTR_TYPE_PTR_IN, ptr, _len, ##__VA_ARGS__) -/* If sizeof(_type) <= sizeof(u64), this will be inlined rather than a pointer */ -#define UVERBS_ATTR_PTR_IN(_id, _type, ...) \ - UVERBS_ATTR_PTR_IN_SZ(_id, _type, ##__VA_ARGS__) -#define UVERBS_ATTR_PTR_OUT_SZ(_id, _len, ...) \ - UVERBS_ATTR(_id, UVERBS_ATTR_TYPE_PTR_OUT, ptr, _len, ##__VA_ARGS__) -#define UVERBS_ATTR_PTR_OUT(_id, _type, ...) \ - UVERBS_ATTR_PTR_OUT_SZ(_id, _type, ##__VA_ARGS__) -#define UVERBS_ATTR_ENUM_IN(_id, _enum_arr, ...) \ - UVERBS_ATTR(_id, UVERBS_ATTR_TYPE_ENUM_IN, enum_def, \ - .ids = (_enum_arr), \ - .num_elems = ARRAY_SIZE(_enum_arr), ##__VA_ARGS__) +/* Must be used in the '...' of any UVERBS_ATTR */ +#define UA_FLAGS(_flags) .flags = _flags + +#define UVERBS_ATTR_IDR(_attr_id, _idr_type, _access, ...) \ + ((const struct uverbs_attr_def){ \ + .id = _attr_id, \ + .attr = { .type = UVERBS_ATTR_TYPE_IDR, \ + .u.obj.obj_type = _idr_type, \ + .u.obj.access = _access, \ + __VA_ARGS__ } }) + +#define UVERBS_ATTR_FD(_attr_id, _fd_type, _access, ...) \ + ((const struct uverbs_attr_def){ \ + .id = (_attr_id) + \ + BUILD_BUG_ON_ZERO((_access) != UVERBS_ACCESS_NEW && \ + (_access) != UVERBS_ACCESS_READ), \ + .attr = { .type = UVERBS_ATTR_TYPE_FD, \ + .u.obj.obj_type = _fd_type, \ + .u.obj.access = _access, \ + __VA_ARGS__ } }) + +#define UVERBS_ATTR_PTR_IN(_attr_id, _type, ...) \ + ((const struct uverbs_attr_def){ \ + .id = _attr_id, \ + .attr = { .type = UVERBS_ATTR_TYPE_PTR_IN, \ + _type, \ + __VA_ARGS__ } }) + +#define UVERBS_ATTR_PTR_OUT(_attr_id, _type, ...) \ + ((const struct uverbs_attr_def){ \ + .id = _attr_id, \ + .attr = { .type = UVERBS_ATTR_TYPE_PTR_OUT, \ + _type, \ + __VA_ARGS__ } }) + +/* _enum_arry should be a 'static const union uverbs_attr_spec[]' */ +#define UVERBS_ATTR_ENUM_IN(_attr_id, _enum_arr, ...) \ + ((const struct uverbs_attr_def){ \ + .id = _attr_id, \ + .attr = { .type = UVERBS_ATTR_TYPE_ENUM_IN, \ + .u2.enum_def.ids = _enum_arr, \ + .u.enum_def.num_elems = ARRAY_SIZE(_enum_arr), \ + __VA_ARGS__ }, \ + }) /* - * In new compiler, UVERBS_ATTR_IDR (and FD) could be simplified by declaring - * it as - * {.id = _id, \ - * .attr {.type = __obj_class, \ - * .obj = {.obj_type = _idr_type, \ - * .access = _access \ - * }, ##__VA_ARGS__ } } - * But since we support older compilers too, we need the more complex code. + * ======================================= + * Declaration helpers + * ======================================= */ -#define ___UVERBS_ATTR_OBJ0(_id, _obj_class, _obj_type, _access, ...)\ - ((const struct uverbs_attr_def) \ - {.id = _id, \ - .attr = { {.obj = {.type = _obj_class, .obj_type = _obj_type, \ - .access = _access, .flags = 0 } }, } }) -#define ___UVERBS_ATTR_OBJ1(_id, _obj_class, _obj_type, _access, _flags)\ - ((const struct uverbs_attr_def) \ - {.id = _id, \ - .attr = { {.obj = {.type = _obj_class, .obj_type = _obj_type, \ - .access = _access, _flags} }, } }) -#define ___UVERBS_ATTR_OBJ(_id, _obj_class, _obj_type, _access, _flags, \ - _n, ...) \ - ___UVERBS_ATTR_OBJ##_n(_id, _obj_class, _obj_type, _access, _flags) -#define __UVERBS_ATTR_OBJ(_id, _obj_class, _obj_type, _access, ...) \ - ___UVERBS_ATTR_OBJ(_id, _obj_class, _obj_type, _access, \ - ##__VA_ARGS__, 1, 0) -#define UVERBS_ATTR_IDR(_id, _idr_type, _access, ...) \ - __UVERBS_ATTR_OBJ(_id, UVERBS_ATTR_TYPE_IDR, _idr_type, _access,\ - ##__VA_ARGS__) -#define UVERBS_ATTR_FD(_id, _fd_type, _access, ...) \ - __UVERBS_ATTR_OBJ(_id, UVERBS_ATTR_TYPE_FD, _fd_type, \ - (_access) + BUILD_BUG_ON_ZERO( \ - (_access) != UVERBS_ACCESS_NEW && \ - (_access) != UVERBS_ACCESS_READ), \ - ##__VA_ARGS__) -#define DECLARE_UVERBS_ATTR_SPEC(_name, ...) \ - const struct uverbs_attr_def _name = __VA_ARGS__ - -#define DECLARE_UVERBS_ENUM(_name, ...) \ - const struct uverbs_enum_spec _name = { \ - .len = ARRAY_SIZE(((struct uverbs_attr_spec[]){__VA_ARGS__})),\ - .ids = {__VA_ARGS__}, \ - } #define _UVERBS_METHOD_ATTRS_SZ(...) \ (sizeof((const struct uverbs_attr_def * const []){__VA_ARGS__}) /\ sizeof(const struct uverbs_attr_def *)) |