Merge tag 'acpi-5.15-rc1-3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael...
[linux-2.6-microblaze.git] / drivers / dma / idxd / cdev.c
index e9def57..b9b2b4a 100644 (file)
@@ -41,7 +41,7 @@ struct idxd_user_context {
 
 static void idxd_cdev_dev_release(struct device *dev)
 {
-       struct idxd_cdev *idxd_cdev = container_of(dev, struct idxd_cdev, dev);
+       struct idxd_cdev *idxd_cdev = dev_to_cdev(dev);
        struct idxd_cdev_context *cdev_ctx;
        struct idxd_wq *wq = idxd_cdev->wq;
 
@@ -218,14 +218,13 @@ static __poll_t idxd_cdev_poll(struct file *filp,
        struct idxd_user_context *ctx = filp->private_data;
        struct idxd_wq *wq = ctx->wq;
        struct idxd_device *idxd = wq->idxd;
-       unsigned long flags;
        __poll_t out = 0;
 
        poll_wait(filp, &wq->err_queue, wait);
-       spin_lock_irqsave(&idxd->dev_lock, flags);
+       spin_lock(&idxd->dev_lock);
        if (idxd->sw_err.valid)
                out = EPOLLIN | EPOLLRDNORM;
-       spin_unlock_irqrestore(&idxd->dev_lock, flags);
+       spin_unlock(&idxd->dev_lock);
 
        return out;
 }
@@ -256,9 +255,10 @@ int idxd_wq_add_cdev(struct idxd_wq *wq)
        if (!idxd_cdev)
                return -ENOMEM;
 
+       idxd_cdev->idxd_dev.type = IDXD_DEV_CDEV;
        idxd_cdev->wq = wq;
        cdev = &idxd_cdev->cdev;
-       dev = &idxd_cdev->dev;
+       dev = cdev_dev(idxd_cdev);
        cdev_ctx = &ictx[wq->idxd->data->type];
        minor = ida_simple_get(&cdev_ctx->minor_ida, 0, MINORMASK, GFP_KERNEL);
        if (minor < 0) {
@@ -268,7 +268,7 @@ int idxd_wq_add_cdev(struct idxd_wq *wq)
        idxd_cdev->minor = minor;
 
        device_initialize(dev);
-       dev->parent = &wq->conf_dev;
+       dev->parent = wq_confdev(wq);
        dev->bus = &dsa_bus_type;
        dev->type = &idxd_cdev_device_type;
        dev->devt = MKDEV(MAJOR(cdev_ctx->devt), minor);
@@ -299,10 +299,67 @@ void idxd_wq_del_cdev(struct idxd_wq *wq)
 
        idxd_cdev = wq->idxd_cdev;
        wq->idxd_cdev = NULL;
-       cdev_device_del(&idxd_cdev->cdev, &idxd_cdev->dev);
-       put_device(&idxd_cdev->dev);
+       cdev_device_del(&idxd_cdev->cdev, cdev_dev(idxd_cdev));
+       put_device(cdev_dev(idxd_cdev));
 }
 
+static int idxd_user_drv_probe(struct idxd_dev *idxd_dev)
+{
+       struct idxd_wq *wq = idxd_dev_to_wq(idxd_dev);
+       struct idxd_device *idxd = wq->idxd;
+       int rc;
+
+       if (idxd->state != IDXD_DEV_ENABLED)
+               return -ENXIO;
+
+       mutex_lock(&wq->wq_lock);
+       wq->type = IDXD_WQT_USER;
+       rc = __drv_enable_wq(wq);
+       if (rc < 0)
+               goto err;
+
+       rc = idxd_wq_add_cdev(wq);
+       if (rc < 0) {
+               idxd->cmd_status = IDXD_SCMD_CDEV_ERR;
+               goto err_cdev;
+       }
+
+       idxd->cmd_status = 0;
+       mutex_unlock(&wq->wq_lock);
+       return 0;
+
+err_cdev:
+       __drv_disable_wq(wq);
+err:
+       wq->type = IDXD_WQT_NONE;
+       mutex_unlock(&wq->wq_lock);
+       return rc;
+}
+
+static void idxd_user_drv_remove(struct idxd_dev *idxd_dev)
+{
+       struct idxd_wq *wq = idxd_dev_to_wq(idxd_dev);
+
+       mutex_lock(&wq->wq_lock);
+       idxd_wq_del_cdev(wq);
+       __drv_disable_wq(wq);
+       wq->type = IDXD_WQT_NONE;
+       mutex_unlock(&wq->wq_lock);
+}
+
+static enum idxd_dev_type dev_types[] = {
+       IDXD_DEV_WQ,
+       IDXD_DEV_NONE,
+};
+
+struct idxd_device_driver idxd_user_drv = {
+       .probe = idxd_user_drv_probe,
+       .remove = idxd_user_drv_remove,
+       .name = "user",
+       .type = dev_types,
+};
+EXPORT_SYMBOL_GPL(idxd_user_drv);
+
 int idxd_cdev_register(void)
 {
        int rc, i;