]> asedeno.scripts.mit.edu Git - linux.git/commitdiff
dmaengine: add support to dynamic register/unregister of channels
authorDave Jiang <dave.jiang@intel.com>
Tue, 21 Jan 2020 23:43:53 +0000 (16:43 -0700)
committerVinod Koul <vkoul@kernel.org>
Fri, 24 Jan 2020 05:48:45 +0000 (11:18 +0530)
With the channel registration routines broken out, now add support code to
allow independent registering and unregistering of channels in a hotplug fashion.

Signed-off-by: Dave Jiang <dave.jiang@intel.com>
Link: https://lore.kernel.org/r/157965023364.73301.7821862091077299040.stgit@djiang5-desk3.ch.intel.com
Signed-off-by: Vinod Koul <vkoul@kernel.org>
drivers/dma/dmaengine.c
include/linux/dmaengine.h

index 2daf2ee9bebd3e3abd91e278aa643a85b77ec383..51a2f2b1b2dea45c6c462f419ee3b623b3491885 100644 (file)
@@ -986,6 +986,20 @@ static int __dma_async_device_channel_register(struct dma_device *device,
        return rc;
 }
 
+int dma_async_device_channel_register(struct dma_device *device,
+                                     struct dma_chan *chan)
+{
+       int rc;
+
+       rc = __dma_async_device_channel_register(device, chan, -1);
+       if (rc < 0)
+               return rc;
+
+       dma_channel_rebalance();
+       return 0;
+}
+EXPORT_SYMBOL_GPL(dma_async_device_channel_register);
+
 static void __dma_async_device_channel_unregister(struct dma_device *device,
                                                  struct dma_chan *chan)
 {
@@ -993,12 +1007,22 @@ static void __dma_async_device_channel_unregister(struct dma_device *device,
                  "%s called while %d clients hold a reference\n",
                  __func__, chan->client_count);
        mutex_lock(&dma_list_mutex);
+       list_del(&chan->device_node);
+       device->chancnt--;
        chan->dev->chan = NULL;
        mutex_unlock(&dma_list_mutex);
        device_unregister(&chan->dev->device);
        free_percpu(chan->local);
 }
 
+void dma_async_device_channel_unregister(struct dma_device *device,
+                                        struct dma_chan *chan)
+{
+       __dma_async_device_channel_unregister(device, chan);
+       dma_channel_rebalance();
+}
+EXPORT_SYMBOL_GPL(dma_async_device_channel_unregister);
+
 /**
  * dma_async_device_register - registers DMA devices found
  * @device: &dma_device
@@ -1121,12 +1145,6 @@ int dma_async_device_register(struct dma_device *device)
                        goto err_out;
        }
 
-       if (!device->chancnt) {
-               dev_err(device->dev, "%s: device has no channels!\n", __func__);
-               rc = -ENODEV;
-               goto err_out;
-       }
-
        mutex_lock(&dma_list_mutex);
        /* take references on public channels */
        if (dmaengine_ref_count && !dma_has_cap(DMA_PRIVATE, device->cap_mask))
@@ -1181,9 +1199,9 @@ EXPORT_SYMBOL(dma_async_device_register);
  */
 void dma_async_device_unregister(struct dma_device *device)
 {
-       struct dma_chan *chan;
+       struct dma_chan *chan, *n;
 
-       list_for_each_entry(chan, &device->channels, device_node)
+       list_for_each_entry_safe(chan, n, &device->channels, device_node)
                __dma_async_device_channel_unregister(device, chan);
 
        mutex_lock(&dma_list_mutex);
index 9cc0e70e7c3543a93b8779aba92abbc70e44f2bf..f52f274773edc5edbf6e4e041152a08b987babd4 100644 (file)
@@ -1521,6 +1521,10 @@ static inline int dmaengine_desc_free(struct dma_async_tx_descriptor *desc)
 int dma_async_device_register(struct dma_device *device);
 int dmaenginem_async_device_register(struct dma_device *device);
 void dma_async_device_unregister(struct dma_device *device);
+int dma_async_device_channel_register(struct dma_device *device,
+                                     struct dma_chan *chan);
+void dma_async_device_channel_unregister(struct dma_device *device,
+                                        struct dma_chan *chan);
 void dma_run_dependencies(struct dma_async_tx_descriptor *tx);
 #define dma_request_channel(mask, x, y) \
        __dma_request_channel(&(mask), x, y, NULL)