Introduce the UVERBS_IDR_ANY_OBJECT type to match any IDR object.
Once used, the infrastructure skips checking for the IDR type, it
becomes the driver handler responsibility.
This enables drivers to get in a given method an object from various of
types.
Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Doug Ledford <dledford@redhat.com>
        struct ib_uobject *uobj;
        int ret;
 
-       if (!obj)
-               return ERR_PTR(-EINVAL);
+       if (IS_ERR(obj) && PTR_ERR(obj) == -ENOMSG) {
+               /* must be UVERBS_IDR_ANY_OBJECT, see uapi_get_object() */
+               uobj = lookup_get_idr_uobject(NULL, ufile, id, mode);
+               if (IS_ERR(uobj))
+                       return uobj;
+       } else {
+               if (IS_ERR(obj))
+                       return ERR_PTR(-EINVAL);
 
-       uobj = obj->type_class->lookup_get(obj, ufile, id, mode);
-       if (IS_ERR(uobj))
-               return uobj;
+               uobj = obj->type_class->lookup_get(obj, ufile, id, mode);
+               if (IS_ERR(uobj))
+                       return uobj;
 
-       if (uobj->uapi_object != obj) {
-               ret = -EINVAL;
-               goto free;
+               if (uobj->uapi_object != obj) {
+                       ret = -EINVAL;
+                       goto free;
+               }
        }
 
        /*
 
        return uobj;
 free:
-       obj->type_class->lookup_put(uobj, mode);
+       uobj->uapi_object->type_class->lookup_put(uobj, mode);
        uverbs_uobject_put(uobj);
        return ERR_PTR(ret);
 }
 {
        struct ib_uobject *ret;
 
-       if (!obj)
+       if (IS_ERR(obj))
                return ERR_PTR(-EINVAL);
 
        /*
 
        const struct uverbs_api_write_method **write_ex_methods;
 };
 
+/*
+ * Get an uverbs_api_object that corresponds to the given object_id.
+ * Note:
+ * -ENOMSG means that any object is allowed to match during lookup.
+ */
 static inline const struct uverbs_api_object *
 uapi_get_object(struct uverbs_api *uapi, u16 object_id)
 {
-       return radix_tree_lookup(&uapi->radix, uapi_key_obj(object_id));
+       const struct uverbs_api_object *res;
+
+       if (object_id == UVERBS_IDR_ANY_OBJECT)
+               return ERR_PTR(-ENOMSG);
+
+       res = radix_tree_lookup(&uapi->radix, uapi_key_obj(object_id));
+       if (!res)
+               return ERR_PTR(-ENOENT);
+
+       return res;
 }
 
 char *uapi_key_format(char *S, unsigned int key);
 
                        if (obj_key == UVERBS_API_KEY_ERR)
                                continue;
                        tmp_obj = uapi_get_object(uapi, obj_key);
-                       if (tmp_obj && !tmp_obj->disabled)
-                               continue;
+                       if (IS_ERR(tmp_obj)) {
+                               if (PTR_ERR(tmp_obj) == -ENOMSG)
+                                       continue;
+                       } else {
+                               if (!tmp_obj->disabled)
+                                       continue;
+                       }
 
                        starting_key = iter.index;
                        uapi_remove_method(
 
                          .u2.objs_arr.max_len = _max_len,                     \
                          __VA_ARGS__ } })
 
+/*
+ * Only for use with UVERBS_ATTR_IDR, allows any uobject type to be accepted,
+ * the user must validate the type of the uobject instead.
+ */
+#define UVERBS_IDR_ANY_OBJECT 0xFFFF
+
 #define UVERBS_ATTR_IDR(_attr_id, _idr_type, _access, ...)                     \
        (&(const struct uverbs_attr_def){                                      \
                .id = _attr_id,                                                \