As dma_get_any_slave_channel is used to request a channel which will later on be released through dma_release_channel it needs to maintain the privatecnt just as __dma_request_channel does. Do this by refactoring the privatenct handling into a helper function which is used from __dma_request_channel as well as dma_get_any_slave_channel. Signed-off-by: Julian Scheel <julian@xxxxxxxx> --- drivers/dma/dmaengine.c | 30 +++++++++++++++++++++--------- 1 file changed, 21 insertions(+), 9 deletions(-) diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index 24bfaf0..0215db4 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -535,6 +535,24 @@ struct dma_chan *dma_get_slave_channel(struct dma_chan *chan) } EXPORT_SYMBOL_GPL(dma_get_slave_channel); + +static int dma_get_channel_private(struct dma_device *device, struct dma_chan *chan) +{ + int err; + + /* We first set DMA_PRIVATE to disable + * balance_ref_count as this channel will not be + * published in the general-purpose allocator + */ + dma_cap_set(DMA_PRIVATE, device->cap_mask); + device->privatecnt++; + + err = dma_chan_get(chan); + if (err && --device->privatecnt == 0) + dma_cap_clear(DMA_PRIVATE, device->cap_mask); + return err; +} + struct dma_chan *dma_get_any_slave_channel(struct dma_device *device) { dma_cap_mask_t mask; @@ -549,7 +567,7 @@ struct dma_chan *dma_get_any_slave_channel(struct dma_device *device) chan = private_candidate(&mask, device, NULL, NULL); if (chan) { - err = dma_chan_get(chan); + err = dma_get_channel_private(device, chan); if (err) { pr_debug("%s: failed to get %s: (%d)\n", __func__, dma_chan_name(chan), err); @@ -584,13 +602,9 @@ struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask, chan = private_candidate(mask, device, fn, fn_param); if (chan) { /* Found a suitable channel, try to grab, prep, and - * return it. We first set DMA_PRIVATE to disable - * balance_ref_count as this channel will not be - * published in the general-purpose allocator + * return it. */ - dma_cap_set(DMA_PRIVATE, device->cap_mask); - device->privatecnt++; - err = dma_chan_get(chan); + err = dma_get_channel_private(device, chan); if (err == -ENODEV) { pr_debug("%s: %s module removed\n", @@ -601,8 +615,6 @@ struct dma_chan *__dma_request_channel(const dma_cap_mask_t *mask, __func__, dma_chan_name(chan), err); else break; - if (--device->privatecnt == 0) - dma_cap_clear(DMA_PRIVATE, device->cap_mask); chan = NULL; } } -- 2.1.3 -- To unsubscribe from this list: send the line "unsubscribe dmaengine" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html