Merge tag 'for-4.20-part2-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
[sfrench/cifs-2.6.git] / include / rdma / uverbs_ioctl.h
index 9e997c3c2f042350bdae131c490b9d56dbda24a3..84d3d15f1f38c75669f6985c08e558ab17dfa14d 100644 (file)
@@ -52,6 +52,7 @@ enum uverbs_attr_type {
        UVERBS_ATTR_TYPE_IDR,
        UVERBS_ATTR_TYPE_FD,
        UVERBS_ATTR_TYPE_ENUM_IN,
+       UVERBS_ATTR_TYPE_IDRS_ARRAY,
 };
 
 enum uverbs_obj_access {
@@ -101,7 +102,7 @@ struct uverbs_attr_spec {
                } enum_def;
        } u;
 
-       /* This weird split of the enum lets us remove some padding */
+       /* This weird split lets us remove some padding */
        union {
                struct {
                        /*
@@ -111,6 +112,17 @@ struct uverbs_attr_spec {
                         */
                        const struct uverbs_attr_spec *ids;
                } enum_def;
+
+               struct {
+                       /*
+                        * higher bits mean the namespace and lower bits mean
+                        * the type id within the namespace.
+                        */
+                       u16                             obj_type;
+                       u16                             min_len;
+                       u16                             max_len;
+                       u8                              access;
+               } objs_arr;
        } u2;
 };
 
@@ -251,6 +263,11 @@ static inline __attribute_const__ u32 uapi_bkey_attr(u32 attr_key)
        return attr_key - 1;
 }
 
+static inline __attribute_const__ u32 uapi_bkey_to_key_attr(u32 attr_bkey)
+{
+       return attr_bkey + 1;
+}
+
 /*
  * =======================================
  *     Verbs definitions
@@ -323,6 +340,27 @@ struct uverbs_object_tree_def {
 #define UA_MANDATORY .mandatory = 1
 #define UA_OPTIONAL .mandatory = 0
 
+/*
+ * min_len must be bigger than 0 and _max_len must be smaller than 4095.  Only
+ * READ\WRITE accesses are supported.
+ */
+#define UVERBS_ATTR_IDRS_ARR(_attr_id, _idr_type, _access, _min_len, _max_len, \
+                            ...)                                              \
+       (&(const struct uverbs_attr_def){                                      \
+               .id = (_attr_id) +                                             \
+                     BUILD_BUG_ON_ZERO((_min_len) == 0 ||                     \
+                                       (_max_len) >                           \
+                                               PAGE_SIZE / sizeof(void *) ||  \
+                                       (_min_len) > (_max_len) ||             \
+                                       (_access) == UVERBS_ACCESS_NEW ||      \
+                                       (_access) == UVERBS_ACCESS_DESTROY),   \
+               .attr = { .type = UVERBS_ATTR_TYPE_IDRS_ARRAY,                 \
+                         .u2.objs_arr.obj_type = _idr_type,                   \
+                         .u2.objs_arr.access = _access,                       \
+                         .u2.objs_arr.min_len = _min_len,                     \
+                         .u2.objs_arr.max_len = _max_len,                     \
+                         __VA_ARGS__ } })
+
 #define UVERBS_ATTR_IDR(_attr_id, _idr_type, _access, ...)                     \
        (&(const struct uverbs_attr_def){                                      \
                .id = _attr_id,                                                \
@@ -365,6 +403,15 @@ struct uverbs_object_tree_def {
                          __VA_ARGS__ },                                       \
        })
 
+/* An input value that is a member in the enum _enum_type. */
+#define UVERBS_ATTR_CONST_IN(_attr_id, _enum_type, ...)                        \
+       UVERBS_ATTR_PTR_IN(                                                    \
+               _attr_id,                                                      \
+               UVERBS_ATTR_SIZE(                                              \
+                       sizeof(u64) + BUILD_BUG_ON_ZERO(!sizeof(_enum_type)),  \
+                       sizeof(u64)),                                          \
+               __VA_ARGS__)
+
 /*
  * An input value that is a bitwise combination of values of _enum_type.
  * This permits the flag value to be passed as either a u32 or u64, it must
@@ -431,10 +478,16 @@ struct uverbs_obj_attr {
        const struct uverbs_api_attr    *attr_elm;
 };
 
+struct uverbs_objs_arr_attr {
+       struct ib_uobject **uobjects;
+       u16 len;
+};
+
 struct uverbs_attr {
        union {
                struct uverbs_ptr_attr  ptr_attr;
                struct uverbs_obj_attr  obj_attr;
+               struct uverbs_objs_arr_attr objs_arr_attr;
        };
 };
 
@@ -507,6 +560,31 @@ uverbs_attr_get_len(const struct uverbs_attr_bundle *attrs_bundle, u16 idx)
        return attr->ptr_attr.len;
 }
 
+/**
+ * uverbs_attr_get_uobjs_arr() - Provides array's properties for attribute for
+ * UVERBS_ATTR_TYPE_IDRS_ARRAY.
+ * @arr: Returned pointer to array of pointers for uobjects or NULL if
+ *       the attribute isn't provided.
+ *
+ * Return: The array length or 0 if no attribute was provided.
+ */
+static inline int uverbs_attr_get_uobjs_arr(
+       const struct uverbs_attr_bundle *attrs_bundle, u16 attr_idx,
+       struct ib_uobject ***arr)
+{
+       const struct uverbs_attr *attr =
+                       uverbs_attr_get(attrs_bundle, attr_idx);
+
+       if (IS_ERR(attr)) {
+               *arr = NULL;
+               return 0;
+       }
+
+       *arr = attr->objs_arr_attr.uobjects;
+
+       return attr->objs_arr_attr.len;
+}
+
 static inline bool uverbs_attr_ptr_is_inline(const struct uverbs_attr *attr)
 {
        return attr->ptr_attr.len <= sizeof(attr->ptr_attr.data);
@@ -603,6 +681,9 @@ static inline __malloc void *uverbs_zalloc(struct uverbs_attr_bundle *bundle,
 {
        return _uverbs_alloc(bundle, size, GFP_KERNEL | __GFP_ZERO);
 }
+int _uverbs_get_const(s64 *to, const struct uverbs_attr_bundle *attrs_bundle,
+                     size_t idx, s64 lower_bound, u64 upper_bound,
+                     s64 *def_val);
 #else
 static inline int
 uverbs_get_flags64(u64 *to, const struct uverbs_attr_bundle *attrs_bundle,
@@ -631,6 +712,34 @@ static inline __malloc void *uverbs_zalloc(struct uverbs_attr_bundle *bundle,
 {
        return ERR_PTR(-EINVAL);
 }
+static inline int
+_uverbs_get_const(s64 *to, const struct uverbs_attr_bundle *attrs_bundle,
+                 size_t idx, s64 lower_bound, u64 upper_bound,
+                 s64 *def_val)
+{
+       return -EINVAL;
+}
 #endif
 
+#define uverbs_get_const(_to, _attrs_bundle, _idx)                             \
+       ({                                                                     \
+               s64 _val;                                                      \
+               int _ret = _uverbs_get_const(&_val, _attrs_bundle, _idx,       \
+                                            type_min(typeof(*_to)),           \
+                                            type_max(typeof(*_to)), NULL);    \
+               (*_to) = _val;                                                 \
+               _ret;                                                          \
+       })
+
+#define uverbs_get_const_default(_to, _attrs_bundle, _idx, _default)           \
+       ({                                                                     \
+               s64 _val;                                                      \
+               s64 _def_val = _default;                                       \
+               int _ret =                                                     \
+                       _uverbs_get_const(&_val, _attrs_bundle, _idx,          \
+                                         type_min(typeof(*_to)),              \
+                                         type_max(typeof(*_to)), &_def_val);  \
+               (*_to) = _val;                                                 \
+               _ret;                                                          \
+       })
 #endif