summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorJason Gunthorpe <jgg@mellanox.com>2018-07-04 08:50:25 +0300
committerJason Gunthorpe <jgg@mellanox.com>2018-07-04 22:47:01 +0300
commitd108dac08085b6fe3947df9625c76fc9f66c1bbb (patch)
treea0bac15e73129dbb54ddf5bf0e9b5653e79d488e /include
parentad544cfe54cbd1b0b68c620a371ebcde6a3264eb (diff)
downloadlinux-d108dac08085b6fe3947df9625c76fc9f66c1bbb.tar.xz
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')
-rw-r--r--include/rdma/uverbs_ioctl.h172
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 *))