Skip to content

Commit

Permalink
dmaengine: add support to dynamic register/unregister of channels
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
davejiang authored and vinodkoul committed Jan 24, 2020
1 parent d2fb0a0 commit e81274c
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 8 deletions.
34 changes: 26 additions & 8 deletions drivers/dma/dmaengine.c
Original file line number Diff line number Diff line change
Expand Up @@ -986,19 +986,43 @@ 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)
{
WARN_ONCE(!device->device_release && chan->client_count,
"%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
Expand Down Expand Up @@ -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))
Expand Down Expand Up @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions include/linux/dmaengine.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down

0 comments on commit e81274c

Please sign in to comment.