IB/mlx5: Introduce MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD
authorYishai Hadas <yishaih@mellanox.com>
Tue, 22 Jan 2019 06:29:56 +0000 (08:29 +0200)
committerJason Gunthorpe <jgg@mellanox.com>
Tue, 29 Jan 2019 20:32:43 +0000 (13:32 -0700)
Introduce MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD and its initial implementation.

This object is from type class FD and will be used to read DEVX async
commands completion.

The core layer should allow the driver to set object from type FD in a
safe mode, this option was added with a matching comment in place.

Signed-off-by: Yishai Hadas <yishaih@mellanox.com>
Signed-off-by: Leon Romanovsky <leonro@mellanox.com>
Signed-off-by: Jason Gunthorpe <jgg@mellanox.com>
drivers/infiniband/core/rdma_core.c
drivers/infiniband/core/uverbs_uapi.c
drivers/infiniband/hw/mlx5/devx.c
include/rdma/uverbs_types.h
include/uapi/rdma/mlx5_user_ioctl_cmds.h

index 6c4747e..a260d2f 100644 (file)
@@ -801,6 +801,7 @@ void uverbs_close_fd(struct file *f)
        /* Pairs with filp->private_data in alloc_begin_fd_uobject */
        uverbs_uobject_put(uobj);
 }
+EXPORT_SYMBOL(uverbs_close_fd);
 
 /*
  * Drop the ucontext off the ufile and completely disconnect it from the
index 9ae08e4..7a987ac 100644 (file)
@@ -188,13 +188,18 @@ static int uapi_merge_obj_tree(struct uverbs_api *uapi,
                obj_elm->type_attrs = obj->type_attrs;
                obj_elm->type_class = obj->type_attrs->type_class;
                /*
-                * Today drivers are only permitted to use idr_class
-                * types. They cannot use FD types because we currently have
-                * no way to revoke the fops pointer after device
-                * disassociation.
+                * Today drivers are only permitted to use idr_class and
+                * fd_class types. We can revoke the IDR types during
+                * disassociation, and the FD types require the driver to use
+                * struct file_operations.owner to prevent the driver module
+                * code from unloading while the file is open. This provides
+                * enough safety that uverbs_close_fd() will continue to work.
+                * Drivers using FD are responsible to handle disassociation of
+                * the device on their own.
                 */
                if (WARN_ON(is_driver &&
-                           obj->type_attrs->type_class != &uverbs_idr_class))
+                           obj->type_attrs->type_class != &uverbs_idr_class &&
+                           obj->type_attrs->type_class != &uverbs_fd_class))
                        return -EINVAL;
        }
 
index 5a588f3..9933bcf 100644 (file)
@@ -1168,6 +1168,38 @@ static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_OBJ_QUERY)(
                              cmd_out, cmd_out_len);
 }
 
+struct devx_async_event_queue {
+       spinlock_t              lock;
+       wait_queue_head_t       poll_wait;
+       struct list_head        event_list;
+};
+
+struct devx_async_cmd_event_file {
+       struct ib_uobject               uobj;
+       struct devx_async_event_queue   ev_queue;
+};
+
+static void devx_init_event_queue(struct devx_async_event_queue *ev_queue)
+{
+       spin_lock_init(&ev_queue->lock);
+       INIT_LIST_HEAD(&ev_queue->event_list);
+       init_waitqueue_head(&ev_queue->poll_wait);
+}
+
+static int UVERBS_HANDLER(MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC)(
+       struct uverbs_attr_bundle *attrs)
+{
+       struct devx_async_cmd_event_file *ev_file;
+
+       struct ib_uobject *uobj = uverbs_attr_get_uobject(
+               attrs, MLX5_IB_ATTR_DEVX_ASYNC_CMD_FD_ALLOC_HANDLE);
+
+       ev_file = container_of(uobj, struct devx_async_cmd_event_file,
+                              uobj);
+       devx_init_event_queue(&ev_file->ev_queue);
+       return 0;
+}
+
 static int devx_umem_get(struct mlx5_ib_dev *dev, struct ib_ucontext *ucontext,
                         struct uverbs_attr_bundle *attrs,
                         struct devx_umem *obj)
@@ -1313,6 +1345,38 @@ static int devx_umem_cleanup(struct ib_uobject *uobject,
        return 0;
 }
 
+static ssize_t devx_async_cmd_event_read(struct file *filp, char __user *buf,
+                                        size_t count, loff_t *pos)
+{
+       return -EINVAL;
+}
+
+static int devx_async_cmd_event_close(struct inode *inode, struct file *filp)
+{
+       uverbs_close_fd(filp);
+       return 0;
+}
+
+static __poll_t devx_async_cmd_event_poll(struct file *filp,
+                                             struct poll_table_struct *wait)
+{
+       return 0;
+}
+
+const struct file_operations devx_async_cmd_event_fops = {
+       .owner   = THIS_MODULE,
+       .read    = devx_async_cmd_event_read,
+       .poll    = devx_async_cmd_event_poll,
+       .release = devx_async_cmd_event_close,
+       .llseek  = no_llseek,
+};
+
+static int devx_hot_unplug_async_cmd_event_file(struct ib_uobject *uobj,
+                                                  enum rdma_remove_reason why)
+{
+       return 0;
+};
+
 DECLARE_UVERBS_NAMED_METHOD(
        MLX5_IB_METHOD_DEVX_UMEM_REG,
        UVERBS_ATTR_IDR(MLX5_IB_ATTR_DEVX_UMEM_REG_HANDLE,
@@ -1440,6 +1504,22 @@ DECLARE_UVERBS_NAMED_OBJECT(MLX5_IB_OBJECT_DEVX_UMEM,
                            &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_REG),
                            &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_UMEM_DEREG));
 
+
+DECLARE_UVERBS_NAMED_METHOD(
+       MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC,
+       UVERBS_ATTR_FD(MLX5_IB_ATTR_DEVX_ASYNC_CMD_FD_ALLOC_HANDLE,
+                       MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
+                       UVERBS_ACCESS_NEW,
+                       UA_MANDATORY));
+
+DECLARE_UVERBS_NAMED_OBJECT(
+       MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
+       UVERBS_TYPE_ALLOC_FD(sizeof(struct devx_async_cmd_event_file),
+                            devx_hot_unplug_async_cmd_event_file,
+                            &devx_async_cmd_event_fops, "[devx_async_cmd]",
+                            O_RDONLY),
+       &UVERBS_METHOD(MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC));
+
 static bool devx_is_supported(struct ib_device *device)
 {
        struct mlx5_ib_dev *dev = to_mdev(device);
@@ -1457,5 +1537,8 @@ const struct uapi_definition mlx5_ib_devx_defs[] = {
        UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
                MLX5_IB_OBJECT_DEVX_UMEM,
                UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
+       UAPI_DEF_CHAIN_OBJ_TREE_NAMED(
+               MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
+               UAPI_DEF_IS_OBJ_SUPPORTED(devx_is_supported)),
        {},
 };
index acb1bfa..175d761 100644 (file)
@@ -157,6 +157,7 @@ struct uverbs_obj_fd_type {
 
 extern const struct uverbs_obj_type_class uverbs_idr_class;
 extern const struct uverbs_obj_type_class uverbs_fd_class;
+void uverbs_close_fd(struct file *f);
 
 #define UVERBS_BUILD_BUG_ON(cond) (sizeof(char[1 - 2 * !!(cond)]) -    \
                                   sizeof(char))
index b8d121d..6ceae29 100644 (file)
@@ -113,11 +113,20 @@ enum mlx5_ib_devx_umem_methods {
        MLX5_IB_METHOD_DEVX_UMEM_DEREG,
 };
 
+enum mlx5_ib_devx_async_cmd_fd_alloc_attrs {
+       MLX5_IB_ATTR_DEVX_ASYNC_CMD_FD_ALLOC_HANDLE = (1U << UVERBS_ID_NS_SHIFT),
+};
+
+enum mlx5_ib_devx_async_cmd_fd_methods {
+       MLX5_IB_METHOD_DEVX_ASYNC_CMD_FD_ALLOC = (1U << UVERBS_ID_NS_SHIFT),
+};
+
 enum mlx5_ib_objects {
        MLX5_IB_OBJECT_DEVX = (1U << UVERBS_ID_NS_SHIFT),
        MLX5_IB_OBJECT_DEVX_OBJ,
        MLX5_IB_OBJECT_DEVX_UMEM,
        MLX5_IB_OBJECT_FLOW_MATCHER,
+       MLX5_IB_OBJECT_DEVX_ASYNC_CMD_FD,
 };
 
 enum mlx5_ib_flow_matcher_create_attrs {