diff mbox

dmaengine: increment privatecnt when using dma_get_any_slave_channel

Message ID 1425460618-26454-1-git-send-email-cfreeman@nvidia.com (mailing list archive)
State Accepted
Headers show

Commit Message

Christopher Freeman March 4, 2015, 9:16 a.m. UTC
Channels allocated via dma_get_any_slave_channel were not increasing
the counter tracking private allocations.  When these channels were
released, privatecnt may erroneously fall to zero.  The DMA device
would then lose its DMA_PRIVATE cap and fail to allocate future private
channels (via private_candidate) as any allocations still outstanding
would incorrectly be seen as public allocations.

Signed-off-by: Christopher Freeman <cfreeman@nvidia.com>
---
 drivers/dma/dmaengine.c | 4 ++++
 1 file changed, 4 insertions(+)

Comments

Christopher Freeman April 29, 2015, 12:15 a.m. UTC | #1
Ping.

Jon Hunter (CC'd) sent a similar patch more recently.  This is an issue
on Tegra for devices using our DMA driver (high speed serial, etc.)

On 03-04 01:16 AM, Christopher Freeman wrote:
> Channels allocated via dma_get_any_slave_channel were not increasing
> the counter tracking private allocations.  When these channels were
> released, privatecnt may erroneously fall to zero.  The DMA device
> would then lose its DMA_PRIVATE cap and fail to allocate future private
> channels (via private_candidate) as any allocations still outstanding
> would incorrectly be seen as public allocations.
> 
> Signed-off-by: Christopher Freeman <cfreeman@nvidia.com>
> 
> ---
> drivers/dma/dmaengine.c | 4 ++++
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
> index f15712f..a225e2b 100644
> --- a/drivers/dma/dmaengine.c
> +++ b/drivers/dma/dmaengine.c
> @@ -589,11 +589,15 @@ struct dma_chan *dma_get_any_slave_channel(struct dma_device *device)
>  
>  	chan = private_candidate(&mask, device, NULL, NULL);
>  	if (chan) {
> +		dma_cap_set(DMA_PRIVATE, device->cap_mask);
> +		device->privatecnt++;
>  		err = dma_chan_get(chan);
>  		if (err) {
>  			pr_debug("%s: failed to get %s: (%d)\n",
>  				__func__, dma_chan_name(chan), err);
>  			chan = NULL;
> +			if (--device->privatecnt == 0)
> +				dma_cap_clear(DMA_PRIVATE, device->cap_mask);
>  		}
>  	}
>  

-----------------------------------------------------------------------------------
This email message is for the sole use of the intended recipient(s) and may contain
confidential information.  Any unauthorized review, use, disclosure or distribution
is prohibited.  If you are not the intended recipient, please contact the sender by
reply email and destroy all copies of the original message.
-----------------------------------------------------------------------------------
--
To unsubscribe from this list: send the line "unsubscribe dmaengine" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Vinod Koul April 29, 2015, 11:17 a.m. UTC | #2
On Tue, Apr 28, 2015 at 05:15:16PM -0700, Christopher Freeman wrote:
> Ping.
> 
> Jon Hunter (CC'd) sent a similar patch more recently.  This is an issue
> on Tegra for devices using our DMA driver (high speed serial, etc.)

oops, looks like this slipped thru. I am applying this now and discarding the
one from Jon
diff mbox

Patch

diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index f15712f..a225e2b 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -589,11 +589,15 @@  struct dma_chan *dma_get_any_slave_channel(struct dma_device *device)
 
 	chan = private_candidate(&mask, device, NULL, NULL);
 	if (chan) {
+		dma_cap_set(DMA_PRIVATE, device->cap_mask);
+		device->privatecnt++;
 		err = dma_chan_get(chan);
 		if (err) {
 			pr_debug("%s: failed to get %s: (%d)\n",
 				__func__, dma_chan_name(chan), err);
 			chan = NULL;
+			if (--device->privatecnt == 0)
+				dma_cap_clear(DMA_PRIVATE, device->cap_mask);
 		}
 	}