@@ -1130,7 +1130,7 @@ int idxd_device_load_config(struct idxd_device *idxd)
return 0;
}
-static int __drv_enable_wq(struct idxd_wq *wq)
+int __drv_enable_wq(struct idxd_wq *wq)
{
struct idxd_device *idxd = wq->idxd;
struct device *dev = &idxd->pdev->dev;
@@ -1178,12 +1178,7 @@ static int __drv_enable_wq(struct idxd_wq *wq)
}
}
- rc = idxd_wq_alloc_resources(wq);
- if (rc < 0) {
- dev_dbg(dev, "wq resource alloc failed\n");
- goto err;
- }
-
+ rc = 0;
spin_lock_irqsave(&idxd->dev_lock, flags);
if (test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags))
rc = idxd_device_config(idxd);
@@ -1207,21 +1202,7 @@ static int __drv_enable_wq(struct idxd_wq *wq)
wq->client_count = 0;
- if (wq->type == IDXD_WQT_KERNEL) {
- rc = idxd_wq_init_percpu_ref(wq);
- if (rc < 0) {
- dev_dbg(dev, "wq %d percpu_ref setup failed\n", wq->id);
- goto err_cpu_ref;
- }
- }
-
- if (is_idxd_wq_dmaengine(wq)) {
- rc = idxd_register_dma_channel(wq);
- if (rc < 0) {
- dev_dbg(dev, "wq %d DMA channel register failed\n", wq->id);
- goto err_client;
- }
- } else if (is_idxd_wq_cdev(wq)) {
+ if (is_idxd_wq_cdev(wq)) {
rc = idxd_wq_add_cdev(wq);
if (rc < 0) {
dev_dbg(dev, "wq %d cdev creation failed\n", wq->id);
@@ -1229,12 +1210,9 @@ static int __drv_enable_wq(struct idxd_wq *wq)
}
}
- dev_info(dev, "wq %s enabled\n", dev_name(wq_confdev(wq)));
return 0;
err_client:
- idxd_wq_quiesce(wq);
-err_cpu_ref:
idxd_wq_unmap_portal(wq);
err_map_portal:
rc = idxd_wq_disable(wq, false);
@@ -1254,19 +1232,14 @@ int drv_enable_wq(struct idxd_wq *wq)
return rc;
}
-static void __drv_disable_wq(struct idxd_wq *wq)
+void __drv_disable_wq(struct idxd_wq *wq)
{
struct idxd_device *idxd = wq->idxd;
struct device *dev = &idxd->pdev->dev;
lockdep_assert_held(&wq->wq_lock);
- if (wq->type == IDXD_WQT_KERNEL)
- idxd_wq_quiesce(wq);
-
- if (is_idxd_wq_dmaengine(wq))
- idxd_unregister_dma_channel(wq);
- else if (is_idxd_wq_cdev(wq))
+ if (is_idxd_wq_cdev(wq))
idxd_wq_del_cdev(wq);
if (idxd_wq_refcount(wq))
@@ -1278,10 +1251,7 @@ static void __drv_disable_wq(struct idxd_wq *wq)
idxd_wq_drain(wq);
idxd_wq_reset(wq);
- idxd_wq_free_resources(wq);
wq->client_count = 0;
-
- dev_info(dev, "wq %s disabled\n", dev_name(wq_confdev(wq)));
}
void drv_disable_wq(struct idxd_wq *wq)
@@ -262,3 +262,80 @@ void idxd_unregister_dma_channel(struct idxd_wq *wq)
wq->idxd_chan = NULL;
put_device(wq_confdev(wq));
}
+
+static int idxd_dmaengine_drv_probe(struct idxd_dev *idxd_dev)
+{
+ struct device *dev = &idxd_dev->conf_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_KERNEL;
+ rc = __drv_enable_wq(wq);
+ if (rc < 0) {
+ dev_dbg(dev, "Enable wq %d failed: %d\n", wq->id, rc);
+ rc = -ENXIO;
+ goto err;
+ }
+
+ rc = idxd_wq_alloc_resources(wq);
+ if (rc < 0) {
+ dev_dbg(dev, "WQ resource alloc failed\n");
+ goto err_res_alloc;
+ }
+
+ rc = idxd_wq_init_percpu_ref(wq);
+ if (rc < 0) {
+ dev_dbg(dev, "percpu_ref setup failed\n");
+ goto err_ref;
+ }
+
+ rc = idxd_register_dma_channel(wq);
+ if (rc < 0) {
+ dev_dbg(dev, "Failed to register dma channel\n");
+ goto err_dma;
+ }
+
+ mutex_unlock(&wq->wq_lock);
+ return 0;
+
+err_dma:
+ idxd_wq_quiesce(wq);
+err_ref:
+ idxd_wq_free_resources(wq);
+err_res_alloc:
+ __drv_disable_wq(wq);
+err:
+ wq->type = IDXD_WQT_NONE;
+ mutex_unlock(&wq->wq_lock);
+ return rc;
+}
+
+static void idxd_dmaengine_drv_remove(struct idxd_dev *idxd_dev)
+{
+ struct idxd_wq *wq = idxd_dev_to_wq(idxd_dev);
+
+ mutex_lock(&wq->wq_lock);
+ idxd_wq_quiesce(wq);
+ idxd_unregister_dma_channel(wq);
+ __drv_disable_wq(wq);
+ idxd_wq_free_resources(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_dmaengine_drv = {
+ .probe = idxd_dmaengine_drv_probe,
+ .remove = idxd_dmaengine_drv_remove,
+ .name = "dmaengine",
+ .type = dev_types,
+};
@@ -59,6 +59,7 @@ struct idxd_device_driver {
extern struct idxd_device_driver dsa_drv;
extern struct idxd_device_driver idxd_drv;
+extern struct idxd_device_driver idxd_dmaengine_drv;
struct idxd_irq_entry {
struct idxd_device *idxd;
@@ -499,7 +500,9 @@ void idxd_unregister_idxd_drv(void);
int idxd_device_drv_probe(struct idxd_dev *idxd_dev);
void idxd_device_drv_remove(struct idxd_dev *idxd_dev);
int drv_enable_wq(struct idxd_wq *wq);
+int __drv_enable_wq(struct idxd_wq *wq);
void drv_disable_wq(struct idxd_wq *wq);
+void __drv_disable_wq(struct idxd_wq *wq);
int idxd_device_init_reset(struct idxd_device *idxd);
int idxd_device_enable(struct idxd_device *idxd);
int idxd_device_disable(struct idxd_device *idxd);
@@ -836,6 +836,10 @@ static int __init idxd_init_module(void)
if (err < 0)
goto err_idxd_driver_register;
+ err = idxd_driver_register(&idxd_dmaengine_drv);
+ if (err < 0)
+ goto err_idxd_dmaengine_driver_register;
+
err = idxd_driver_register(&dsa_drv);
if (err < 0)
goto err_dsa_driver_register;
@@ -855,6 +859,8 @@ static int __init idxd_init_module(void)
err_cdev_register:
idxd_driver_unregister(&dsa_drv);
err_dsa_driver_register:
+ idxd_driver_unregister(&idxd_dmaengine_drv);
+err_idxd_dmaengine_driver_register:
idxd_driver_unregister(&idxd_drv);
err_idxd_driver_register:
idxd_unregister_bus_type();
@@ -864,6 +870,7 @@ module_init(idxd_init_module);
static void __exit idxd_exit_module(void)
{
+ idxd_driver_unregister(&idxd_dmaengine_drv);
idxd_driver_unregister(&idxd_drv);
idxd_driver_unregister(&dsa_drv);
pci_unregister_driver(&idxd_pci_driver);