All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/2] dmaengine: pl330: fix descriptor allocation fail
@ 2017-10-04 11:37 Alexander Kochetkov
  2017-10-04 11:37 ` [PATCH v2 1/2] " Alexander Kochetkov
  2017-10-04 11:37 ` [PATCH v2 2/2] !!! FOR TESTING ONLY !!! dmaengine: pl330: add verbose message and set NR_DEFAULT_DESC to 1 Alexander Kochetkov
  0 siblings, 2 replies; 7+ messages in thread
From: Alexander Kochetkov @ 2017-10-04 11:37 UTC (permalink / raw)
  To: dmaengine, linux-kernel
  Cc: Dan Williams, Vinod Koul, Marek Szyprowski, Krzysztof Kozlowski,
	Alexander Kochetkov

Here is the patch fixing descriptor allocation issue.

Could someone with pl330 hardware test it and confirm that
it doesn't brake current pl330 driver? I will be very grateful
to you!

Changes in v2:
- removed wrappers add_desc(), pluck_desc()
- fix code intendation 

Alexander Kochetkov (2):
  dmaengine: pl330: fix descriptor allocation fail
  !!! FOR TESTING ONLY !!! dmaengine: pl330: add verbose message and
    set NR_DEFAULT_DESC to 1

 drivers/dma/pl330.c |   44 ++++++++++++++++++++++++--------------------
 1 file changed, 24 insertions(+), 20 deletions(-)

-- 
1.7.9.5

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 1/2] dmaengine: pl330: fix descriptor allocation fail
  2017-10-04 11:37 [PATCH v2 0/2] dmaengine: pl330: fix descriptor allocation fail Alexander Kochetkov
@ 2017-10-04 11:37 ` Alexander Kochetkov
  2017-10-16  7:54   ` Alexander Kochetkov
                     ` (2 more replies)
  2017-10-04 11:37 ` [PATCH v2 2/2] !!! FOR TESTING ONLY !!! dmaengine: pl330: add verbose message and set NR_DEFAULT_DESC to 1 Alexander Kochetkov
  1 sibling, 3 replies; 7+ messages in thread
From: Alexander Kochetkov @ 2017-10-04 11:37 UTC (permalink / raw)
  To: dmaengine, linux-kernel
  Cc: Dan Williams, Vinod Koul, Marek Szyprowski, Krzysztof Kozlowski,
	Alexander Kochetkov

If two concurrent threads call pl330_get_desc() when DMAC descriptor
pool is empty it is possible that allocation for one of threads will fail
with message:

kernel: dma-pl330 20078000.dma-controller: pl330_get_desc:2469 ALERT!

Here how that can happen. Thread A calls pl330_get_desc() to get
descriptor. If DMAC descriptor pool is empty pl330_get_desc() allocates
new descriptor on shared pool using add_desc() and then get newly
allocated descriptor using pluck_desc(). At the same time thread B calls
pluck_desc() and take newly allocated descriptor. In that case descriptor
allocation for thread A will fail.

Using on-stack pool for new descriptor allow avoid the issue described.
The patch modify pl330_get_desc() to use on-stack pool for allocation
new descriptors.

Signed-off-by: Alexander Kochetkov <al.kochet@gmail.com>
---
 drivers/dma/pl330.c |   39 ++++++++++++++++++++-------------------
 1 file changed, 20 insertions(+), 19 deletions(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index b19ee04..deec4a4 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -2390,7 +2390,8 @@ static inline void _init_desc(struct dma_pl330_desc *desc)
 }
 
 /* Returns the number of descriptors added to the DMAC pool */
-static int add_desc(struct pl330_dmac *pl330, gfp_t flg, int count)
+static int add_desc(struct list_head *pool, spinlock_t *lock,
+		    gfp_t flg, int count)
 {
 	struct dma_pl330_desc *desc;
 	unsigned long flags;
@@ -2400,27 +2401,28 @@ static int add_desc(struct pl330_dmac *pl330, gfp_t flg, int count)
 	if (!desc)
 		return 0;
 
-	spin_lock_irqsave(&pl330->pool_lock, flags);
+	spin_lock_irqsave(lock, flags);
 
 	for (i = 0; i < count; i++) {
 		_init_desc(&desc[i]);
-		list_add_tail(&desc[i].node, &pl330->desc_pool);
+		list_add_tail(&desc[i].node, pool);
 	}
 
-	spin_unlock_irqrestore(&pl330->pool_lock, flags);
+	spin_unlock_irqrestore(lock, flags);
 
 	return count;
 }
 
-static struct dma_pl330_desc *pluck_desc(struct pl330_dmac *pl330)
+static struct dma_pl330_desc *pluck_desc(struct list_head *pool,
+					 spinlock_t *lock)
 {
 	struct dma_pl330_desc *desc = NULL;
 	unsigned long flags;
 
-	spin_lock_irqsave(&pl330->pool_lock, flags);
+	spin_lock_irqsave(lock, flags);
 
-	if (!list_empty(&pl330->desc_pool)) {
-		desc = list_entry(pl330->desc_pool.next,
+	if (!list_empty(pool)) {
+		desc = list_entry(pool->next,
 				struct dma_pl330_desc, node);
 
 		list_del_init(&desc->node);
@@ -2429,7 +2431,7 @@ static struct dma_pl330_desc *pluck_desc(struct pl330_dmac *pl330)
 		desc->txd.callback = NULL;
 	}
 
-	spin_unlock_irqrestore(&pl330->pool_lock, flags);
+	spin_unlock_irqrestore(lock, flags);
 
 	return desc;
 }
@@ -2441,20 +2443,18 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
 	struct dma_pl330_desc *desc;
 
 	/* Pluck one desc from the pool of DMAC */
-	desc = pluck_desc(pl330);
+	desc = pluck_desc(&pl330->desc_pool, &pl330->pool_lock);
 
 	/* If the DMAC pool is empty, alloc new */
 	if (!desc) {
-		if (!add_desc(pl330, GFP_ATOMIC, 1))
-			return NULL;
+		DEFINE_SPINLOCK(lock);
+		LIST_HEAD(pool);
 
-		/* Try again */
-		desc = pluck_desc(pl330);
-		if (!desc) {
-			dev_err(pch->dmac->ddma.dev,
-				"%s:%d ALERT!\n", __func__, __LINE__);
+		if (!add_desc(&pool, &lock, GFP_ATOMIC, 1))
 			return NULL;
-		}
+
+		desc = pluck_desc(&pool, &lock);
+		WARN_ON(!desc || !list_empty(&pool));
 	}
 
 	/* Initialize the descriptor */
@@ -2868,7 +2868,8 @@ static int __maybe_unused pl330_resume(struct device *dev)
 	spin_lock_init(&pl330->pool_lock);
 
 	/* Create a descriptor pool of default size */
-	if (!add_desc(pl330, GFP_KERNEL, NR_DEFAULT_DESC))
+	if (!add_desc(&pl330->desc_pool, &pl330->pool_lock,
+		      GFP_KERNEL, NR_DEFAULT_DESC))
 		dev_warn(&adev->dev, "unable to allocate desc\n");
 
 	INIT_LIST_HEAD(&pd->channels);
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 2/2] !!! FOR TESTING ONLY !!! dmaengine: pl330: add verbose message and set NR_DEFAULT_DESC to 1
  2017-10-04 11:37 [PATCH v2 0/2] dmaengine: pl330: fix descriptor allocation fail Alexander Kochetkov
  2017-10-04 11:37 ` [PATCH v2 1/2] " Alexander Kochetkov
@ 2017-10-04 11:37 ` Alexander Kochetkov
  2017-10-17 11:27   ` Marek Szyprowski
  1 sibling, 1 reply; 7+ messages in thread
From: Alexander Kochetkov @ 2017-10-04 11:37 UTC (permalink / raw)
  To: dmaengine, linux-kernel
  Cc: Dan Williams, Vinod Koul, Marek Szyprowski, Krzysztof Kozlowski,
	Alexander Kochetkov

Commit add verbose output to pl330 showing what changes introduced by
commit 1/2 from series work as expected. You should see similar output
running modified kernel:

The patch tested on rk3188 radxdarock. Could someone else test it on
other hardware with pl330 DMA?

root@host:~# dmesg | grep pl330
[    0.277520] dma-pl330 20018000.dma-controller: Loaded driver for PL330 DMAC-241330
[    0.277538] dma-pl330 20018000.dma-controller: 	DBUFF-32x8bytes Num_Chans-6 Num_Peri-12 Num_Events-12
[    0.279894] dma-pl330 20078000.dma-controller: Loaded driver for PL330 DMAC-241330
[    0.279910] dma-pl330 20078000.dma-controller: 	DBUFF-64x8bytes Num_Chans-7 Num_Peri-20 Num_Events-14
[    1.344804] dma-pl330 20078000.dma-controller: pl330_get_desc:2458 Allocated one more descriptor
[    1.344832] dma-pl330 20078000.dma-controller: pl330_get_desc:2458 Allocated one more descriptor
[    1.344853] dma-pl330 20078000.dma-controller: pl330_get_desc:2458 Allocated one more descriptor
[    1.344873] dma-pl330 20078000.dma-controller: pl330_get_desc:2458 Allocated one more descriptor
[    1.344893] dma-pl330 20078000.dma-controller: pl330_get_desc:2458 Allocated one more descriptor
[    1.344912] dma-pl330 20078000.dma-controller: pl330_get_desc:2458 Allocated one more descriptor
--- rest of similar lines omitted ---

Signed-off-by: Alexander Kochetkov <al.kochet@gmail.com>
---
 drivers/dma/pl330.c |    5 ++++-
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
index deec4a4..3441c16 100644
--- a/drivers/dma/pl330.c
+++ b/drivers/dma/pl330.c
@@ -266,7 +266,7 @@ enum pl330_byteswap {
 
 /* The number of default descriptors */
 
-#define NR_DEFAULT_DESC	16
+#define NR_DEFAULT_DESC	1
 
 /* Delay for runtime PM autosuspend, ms */
 #define PL330_AUTOSUSPEND_DELAY 20
@@ -2455,6 +2455,9 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
 
 		desc = pluck_desc(&pool, &lock);
 		WARN_ON(!desc || !list_empty(&pool));
+
+		dev_err(pch->dmac->ddma.dev, "%s:%d Allocated one more descriptor\n",
+			__func__, __LINE__);
 	}
 
 	/* Initialize the descriptor */
-- 
1.7.9.5

^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 1/2] dmaengine: pl330: fix descriptor allocation fail
  2017-10-04 11:37 ` [PATCH v2 1/2] " Alexander Kochetkov
@ 2017-10-16  7:54   ` Alexander Kochetkov
  2017-10-17 11:26   ` Marek Szyprowski
  2017-10-20  6:17   ` Vinod Koul
  2 siblings, 0 replies; 7+ messages in thread
From: Alexander Kochetkov @ 2017-10-16  7:54 UTC (permalink / raw)
  To: dmaengine, linux-kernel
  Cc: Dan Williams, Vinod Koul, Marek Szyprowski, Krzysztof Kozlowski

Hello Vinod!

It looks like the patch did not get enough attention. If no one except me will test the patch,
how do we proceed? This patch does not depend on the SOC implementation and the
runtime environment. For me the patch looks fine and will not do harm if it will be committed.

Regards,
Alexander.

> 4 окт. 2017 г., в 14:37, Alexander Kochetkov <al.kochet@gmail.com> написал(а):
> 
> If two concurrent threads call pl330_get_desc() when DMAC descriptor
> pool is empty it is possible that allocation for one of threads will fail
> with message:
> 
> kernel: dma-pl330 20078000.dma-controller: pl330_get_desc:2469 ALERT!
> 
> Here how that can happen. Thread A calls pl330_get_desc() to get
> descriptor. If DMAC descriptor pool is empty pl330_get_desc() allocates
> new descriptor on shared pool using add_desc() and then get newly
> allocated descriptor using pluck_desc(). At the same time thread B calls
> pluck_desc() and take newly allocated descriptor. In that case descriptor
> allocation for thread A will fail.
> 
> Using on-stack pool for new descriptor allow avoid the issue described.
> The patch modify pl330_get_desc() to use on-stack pool for allocation
> new descriptors.
> 
> Signed-off-by: Alexander Kochetkov <al.kochet@gmail.com>
> ---
> drivers/dma/pl330.c |   39 ++++++++++++++++++++-------------------
> 1 file changed, 20 insertions(+), 19 deletions(-)
> 
> diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> index b19ee04..deec4a4 100644
> --- a/drivers/dma/pl330.c
> +++ b/drivers/dma/pl330.c
> @@ -2390,7 +2390,8 @@ static inline void _init_desc(struct dma_pl330_desc *desc)
> }
> 
> /* Returns the number of descriptors added to the DMAC pool */
> -static int add_desc(struct pl330_dmac *pl330, gfp_t flg, int count)
> +static int add_desc(struct list_head *pool, spinlock_t *lock,
> +		    gfp_t flg, int count)
> {
> 	struct dma_pl330_desc *desc;
> 	unsigned long flags;
> @@ -2400,27 +2401,28 @@ static int add_desc(struct pl330_dmac *pl330, gfp_t flg, int count)
> 	if (!desc)
> 		return 0;
> 
> -	spin_lock_irqsave(&pl330->pool_lock, flags);
> +	spin_lock_irqsave(lock, flags);
> 
> 	for (i = 0; i < count; i++) {
> 		_init_desc(&desc[i]);
> -		list_add_tail(&desc[i].node, &pl330->desc_pool);
> +		list_add_tail(&desc[i].node, pool);
> 	}
> 
> -	spin_unlock_irqrestore(&pl330->pool_lock, flags);
> +	spin_unlock_irqrestore(lock, flags);
> 
> 	return count;
> }
> 
> -static struct dma_pl330_desc *pluck_desc(struct pl330_dmac *pl330)
> +static struct dma_pl330_desc *pluck_desc(struct list_head *pool,
> +					 spinlock_t *lock)
> {
> 	struct dma_pl330_desc *desc = NULL;
> 	unsigned long flags;
> 
> -	spin_lock_irqsave(&pl330->pool_lock, flags);
> +	spin_lock_irqsave(lock, flags);
> 
> -	if (!list_empty(&pl330->desc_pool)) {
> -		desc = list_entry(pl330->desc_pool.next,
> +	if (!list_empty(pool)) {
> +		desc = list_entry(pool->next,
> 				struct dma_pl330_desc, node);
> 
> 		list_del_init(&desc->node);
> @@ -2429,7 +2431,7 @@ static struct dma_pl330_desc *pluck_desc(struct pl330_dmac *pl330)
> 		desc->txd.callback = NULL;
> 	}
> 
> -	spin_unlock_irqrestore(&pl330->pool_lock, flags);
> +	spin_unlock_irqrestore(lock, flags);
> 
> 	return desc;
> }
> @@ -2441,20 +2443,18 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
> 	struct dma_pl330_desc *desc;
> 
> 	/* Pluck one desc from the pool of DMAC */
> -	desc = pluck_desc(pl330);
> +	desc = pluck_desc(&pl330->desc_pool, &pl330->pool_lock);
> 
> 	/* If the DMAC pool is empty, alloc new */
> 	if (!desc) {
> -		if (!add_desc(pl330, GFP_ATOMIC, 1))
> -			return NULL;
> +		DEFINE_SPINLOCK(lock);
> +		LIST_HEAD(pool);
> 
> -		/* Try again */
> -		desc = pluck_desc(pl330);
> -		if (!desc) {
> -			dev_err(pch->dmac->ddma.dev,
> -				"%s:%d ALERT!\n", __func__, __LINE__);
> +		if (!add_desc(&pool, &lock, GFP_ATOMIC, 1))
> 			return NULL;
> -		}
> +
> +		desc = pluck_desc(&pool, &lock);
> +		WARN_ON(!desc || !list_empty(&pool));
> 	}
> 
> 	/* Initialize the descriptor */
> @@ -2868,7 +2868,8 @@ static int __maybe_unused pl330_resume(struct device *dev)
> 	spin_lock_init(&pl330->pool_lock);
> 
> 	/* Create a descriptor pool of default size */
> -	if (!add_desc(pl330, GFP_KERNEL, NR_DEFAULT_DESC))
> +	if (!add_desc(&pl330->desc_pool, &pl330->pool_lock,
> +		      GFP_KERNEL, NR_DEFAULT_DESC))
> 		dev_warn(&adev->dev, "unable to allocate desc\n");
> 
> 	INIT_LIST_HEAD(&pd->channels);
> -- 
> 1.7.9.5
> 

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 1/2] dmaengine: pl330: fix descriptor allocation fail
  2017-10-04 11:37 ` [PATCH v2 1/2] " Alexander Kochetkov
  2017-10-16  7:54   ` Alexander Kochetkov
@ 2017-10-17 11:26   ` Marek Szyprowski
  2017-10-20  6:17   ` Vinod Koul
  2 siblings, 0 replies; 7+ messages in thread
From: Marek Szyprowski @ 2017-10-17 11:26 UTC (permalink / raw)
  To: Alexander Kochetkov, dmaengine, linux-kernel
  Cc: Dan Williams, Vinod Koul, Krzysztof Kozlowski

Hi Alexander,

It took me a while to test this patch, I've been busy with other stuff...

On 2017-10-04 13:37, Alexander Kochetkov wrote:
> If two concurrent threads call pl330_get_desc() when DMAC descriptor
> pool is empty it is possible that allocation for one of threads will fail
> with message:
>
> kernel: dma-pl330 20078000.dma-controller: pl330_get_desc:2469 ALERT!
>
> Here how that can happen. Thread A calls pl330_get_desc() to get
> descriptor. If DMAC descriptor pool is empty pl330_get_desc() allocates
> new descriptor on shared pool using add_desc() and then get newly
> allocated descriptor using pluck_desc(). At the same time thread B calls
> pluck_desc() and take newly allocated descriptor. In that case descriptor
> allocation for thread A will fail.
>
> Using on-stack pool for new descriptor allow avoid the issue described.
> The patch modify pl330_get_desc() to use on-stack pool for allocation
> new descriptors.
>
> Signed-off-by: Alexander Kochetkov <al.kochet@gmail.com>

Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>

> ---
>   drivers/dma/pl330.c |   39 ++++++++++++++++++++-------------------
>   1 file changed, 20 insertions(+), 19 deletions(-)
>
> diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> index b19ee04..deec4a4 100644
> --- a/drivers/dma/pl330.c
> +++ b/drivers/dma/pl330.c
> @@ -2390,7 +2390,8 @@ static inline void _init_desc(struct dma_pl330_desc *desc)
>   }
>   
>   /* Returns the number of descriptors added to the DMAC pool */
> -static int add_desc(struct pl330_dmac *pl330, gfp_t flg, int count)
> +static int add_desc(struct list_head *pool, spinlock_t *lock,
> +		    gfp_t flg, int count)
>   {
>   	struct dma_pl330_desc *desc;
>   	unsigned long flags;
> @@ -2400,27 +2401,28 @@ static int add_desc(struct pl330_dmac *pl330, gfp_t flg, int count)
>   	if (!desc)
>   		return 0;
>   
> -	spin_lock_irqsave(&pl330->pool_lock, flags);
> +	spin_lock_irqsave(lock, flags);
>   
>   	for (i = 0; i < count; i++) {
>   		_init_desc(&desc[i]);
> -		list_add_tail(&desc[i].node, &pl330->desc_pool);
> +		list_add_tail(&desc[i].node, pool);
>   	}
>   
> -	spin_unlock_irqrestore(&pl330->pool_lock, flags);
> +	spin_unlock_irqrestore(lock, flags);
>   
>   	return count;
>   }
>   
> -static struct dma_pl330_desc *pluck_desc(struct pl330_dmac *pl330)
> +static struct dma_pl330_desc *pluck_desc(struct list_head *pool,
> +					 spinlock_t *lock)
>   {
>   	struct dma_pl330_desc *desc = NULL;
>   	unsigned long flags;
>   
> -	spin_lock_irqsave(&pl330->pool_lock, flags);
> +	spin_lock_irqsave(lock, flags);
>   
> -	if (!list_empty(&pl330->desc_pool)) {
> -		desc = list_entry(pl330->desc_pool.next,
> +	if (!list_empty(pool)) {
> +		desc = list_entry(pool->next,
>   				struct dma_pl330_desc, node);
>   
>   		list_del_init(&desc->node);
> @@ -2429,7 +2431,7 @@ static struct dma_pl330_desc *pluck_desc(struct pl330_dmac *pl330)
>   		desc->txd.callback = NULL;
>   	}
>   
> -	spin_unlock_irqrestore(&pl330->pool_lock, flags);
> +	spin_unlock_irqrestore(lock, flags);
>   
>   	return desc;
>   }
> @@ -2441,20 +2443,18 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
>   	struct dma_pl330_desc *desc;
>   
>   	/* Pluck one desc from the pool of DMAC */
> -	desc = pluck_desc(pl330);
> +	desc = pluck_desc(&pl330->desc_pool, &pl330->pool_lock);
>   
>   	/* If the DMAC pool is empty, alloc new */
>   	if (!desc) {
> -		if (!add_desc(pl330, GFP_ATOMIC, 1))
> -			return NULL;
> +		DEFINE_SPINLOCK(lock);
> +		LIST_HEAD(pool);
>   
> -		/* Try again */
> -		desc = pluck_desc(pl330);
> -		if (!desc) {
> -			dev_err(pch->dmac->ddma.dev,
> -				"%s:%d ALERT!\n", __func__, __LINE__);
> +		if (!add_desc(&pool, &lock, GFP_ATOMIC, 1))
>   			return NULL;
> -		}
> +
> +		desc = pluck_desc(&pool, &lock);
> +		WARN_ON(!desc || !list_empty(&pool));
>   	}
>   
>   	/* Initialize the descriptor */
> @@ -2868,7 +2868,8 @@ static int __maybe_unused pl330_resume(struct device *dev)
>   	spin_lock_init(&pl330->pool_lock);
>   
>   	/* Create a descriptor pool of default size */
> -	if (!add_desc(pl330, GFP_KERNEL, NR_DEFAULT_DESC))
> +	if (!add_desc(&pl330->desc_pool, &pl330->pool_lock,
> +		      GFP_KERNEL, NR_DEFAULT_DESC))
>   		dev_warn(&adev->dev, "unable to allocate desc\n");
>   
>   	INIT_LIST_HEAD(&pd->channels);

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 2/2] !!! FOR TESTING ONLY !!! dmaengine: pl330: add verbose message and set NR_DEFAULT_DESC to 1
  2017-10-04 11:37 ` [PATCH v2 2/2] !!! FOR TESTING ONLY !!! dmaengine: pl330: add verbose message and set NR_DEFAULT_DESC to 1 Alexander Kochetkov
@ 2017-10-17 11:27   ` Marek Szyprowski
  0 siblings, 0 replies; 7+ messages in thread
From: Marek Szyprowski @ 2017-10-17 11:27 UTC (permalink / raw)
  To: Alexander Kochetkov, dmaengine, linux-kernel
  Cc: Dan Williams, Vinod Koul, Krzysztof Kozlowski

Hi Alexander,

On 2017-10-04 13:37, Alexander Kochetkov wrote:
> Commit add verbose output to pl330 showing what changes introduced by
> commit 1/2 from series work as expected. You should see similar output
> running modified kernel:
>
> The patch tested on rk3188 radxdarock. Could someone else test it on
> other hardware with pl330 DMA?
>
> root@host:~# dmesg | grep pl330
> [    0.277520] dma-pl330 20018000.dma-controller: Loaded driver for PL330 DMAC-241330
> [    0.277538] dma-pl330 20018000.dma-controller: 	DBUFF-32x8bytes Num_Chans-6 Num_Peri-12 Num_Events-12
> [    0.279894] dma-pl330 20078000.dma-controller: Loaded driver for PL330 DMAC-241330
> [    0.279910] dma-pl330 20078000.dma-controller: 	DBUFF-64x8bytes Num_Chans-7 Num_Peri-20 Num_Events-14
> [    1.344804] dma-pl330 20078000.dma-controller: pl330_get_desc:2458 Allocated one more descriptor
> [    1.344832] dma-pl330 20078000.dma-controller: pl330_get_desc:2458 Allocated one more descriptor
> [    1.344853] dma-pl330 20078000.dma-controller: pl330_get_desc:2458 Allocated one more descriptor
> [    1.344873] dma-pl330 20078000.dma-controller: pl330_get_desc:2458 Allocated one more descriptor
> [    1.344893] dma-pl330 20078000.dma-controller: pl330_get_desc:2458 Allocated one more descriptor
> [    1.344912] dma-pl330 20078000.dma-controller: pl330_get_desc:2458 Allocated one more descriptor
> --- rest of similar lines omitted ---
>
> Signed-off-by: Alexander Kochetkov <al.kochet@gmail.com>

Tested-by: Marek Szyprowski <m.szyprowski@samsung.com>

Seems to be working fine on Exynos4412 OdroidU3 board:

# dmesg | grep pl330
[    0.725608] dma-pl330 12680000.pdma: Loaded driver for PL330 DMAC-141330
[    0.725629] dma-pl330 12680000.pdma:         DBUFF-32x4bytes 
Num_Chans-8 Num_Peri-32 Num_Events-32
[    0.731338] dma-pl330 12690000.pdma: Loaded driver for PL330 DMAC-141330
[    0.731357] dma-pl330 12690000.pdma:         DBUFF-32x4bytes 
Num_Chans-8 Num_Peri-32 Num_Events-32
[    0.733097] dma-pl330 12850000.mdma: Loaded driver for PL330 DMAC-141330
[    0.733115] dma-pl330 12850000.mdma:         DBUFF-64x8bytes 
Num_Chans-8 Num_Peri-1 Num_Events-32
[   98.353073] dma-pl330 12680000.pdma: pl330_get_desc:2460 Allocated 
one more descriptor
[   98.360970] dma-pl330 12680000.pdma: pl330_get_desc:2460 Allocated 
one more descriptor
[   98.368867] dma-pl330 12680000.pdma: pl330_get_desc:2460 Allocated 
one more descriptor

> ---
>   drivers/dma/pl330.c |    5 ++++-
>   1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/dma/pl330.c b/drivers/dma/pl330.c
> index deec4a4..3441c16 100644
> --- a/drivers/dma/pl330.c
> +++ b/drivers/dma/pl330.c
> @@ -266,7 +266,7 @@ enum pl330_byteswap {
>   
>   /* The number of default descriptors */
>   
> -#define NR_DEFAULT_DESC	16
> +#define NR_DEFAULT_DESC	1
>   
>   /* Delay for runtime PM autosuspend, ms */
>   #define PL330_AUTOSUSPEND_DELAY 20
> @@ -2455,6 +2455,9 @@ static struct dma_pl330_desc *pl330_get_desc(struct dma_pl330_chan *pch)
>   
>   		desc = pluck_desc(&pool, &lock);
>   		WARN_ON(!desc || !list_empty(&pool));
> +
> +		dev_err(pch->dmac->ddma.dev, "%s:%d Allocated one more descriptor\n",
> +			__func__, __LINE__);
>   	}
>   
>   	/* Initialize the descriptor */

Best regards
-- 
Marek Szyprowski, PhD
Samsung R&D Institute Poland

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH v2 1/2] dmaengine: pl330: fix descriptor allocation fail
  2017-10-04 11:37 ` [PATCH v2 1/2] " Alexander Kochetkov
  2017-10-16  7:54   ` Alexander Kochetkov
  2017-10-17 11:26   ` Marek Szyprowski
@ 2017-10-20  6:17   ` Vinod Koul
  2 siblings, 0 replies; 7+ messages in thread
From: Vinod Koul @ 2017-10-20  6:17 UTC (permalink / raw)
  To: Alexander Kochetkov
  Cc: dmaengine, linux-kernel, Dan Williams, Marek Szyprowski,
	Krzysztof Kozlowski

On Wed, Oct 04, 2017 at 02:37:23PM +0300, Alexander Kochetkov wrote:
> If two concurrent threads call pl330_get_desc() when DMAC descriptor
> pool is empty it is possible that allocation for one of threads will fail
> with message:
> 
> kernel: dma-pl330 20078000.dma-controller: pl330_get_desc:2469 ALERT!
> 
> Here how that can happen. Thread A calls pl330_get_desc() to get
> descriptor. If DMAC descriptor pool is empty pl330_get_desc() allocates
> new descriptor on shared pool using add_desc() and then get newly
> allocated descriptor using pluck_desc(). At the same time thread B calls
> pluck_desc() and take newly allocated descriptor. In that case descriptor
> allocation for thread A will fail.
> 
> Using on-stack pool for new descriptor allow avoid the issue described.
> The patch modify pl330_get_desc() to use on-stack pool for allocation
> new descriptors.

Applied, thanks

-- 
~Vinod

^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2017-10-20  6:13 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-10-04 11:37 [PATCH v2 0/2] dmaengine: pl330: fix descriptor allocation fail Alexander Kochetkov
2017-10-04 11:37 ` [PATCH v2 1/2] " Alexander Kochetkov
2017-10-16  7:54   ` Alexander Kochetkov
2017-10-17 11:26   ` Marek Szyprowski
2017-10-20  6:17   ` Vinod Koul
2017-10-04 11:37 ` [PATCH v2 2/2] !!! FOR TESTING ONLY !!! dmaengine: pl330: add verbose message and set NR_DEFAULT_DESC to 1 Alexander Kochetkov
2017-10-17 11:27   ` Marek Szyprowski

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.