dmaengine Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH] dmaengine: dma-jz4780: Break descriptor chains on JZ4740
@ 2019-06-30 22:52 Paul Cercueil
  2019-07-14 21:32 ` Paul Cercueil
  0 siblings, 1 reply; 2+ messages in thread
From: Paul Cercueil @ 2019-06-30 22:52 UTC (permalink / raw)
  To: Vinod Koul; +Cc: Paul Burton, od, dmaengine, linux-kernel, Paul Cercueil

The current driver works perfectly fine on every generation of the
JZ47xx SoCs, except on the JZ4740.

There, when hardware descriptors are chained together (with the LINK
bit set), the next descriptor isn't automatically fetched as it should -
instead, an interrupt is raised, even if the TIE bit (Transfer Interrupt
Enable) bit is cleared. When it happens, the DMA transfer seems to be
stopped (it doesn't chain), and it's uncertain how many bytes have
actually been transferred.

Until somebody smarter than me can figure out how to make chained
descriptors work on the JZ4740, we now disable chained descriptors on
that particular SoC.

Signed-off-by: Paul Cercueil <paul@crapouillou.net>
---
 drivers/dma/dma-jz4780.c | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c
index 263bee76ef0d..aae83389cc10 100644
--- a/drivers/dma/dma-jz4780.c
+++ b/drivers/dma/dma-jz4780.c
@@ -92,6 +92,7 @@
 #define JZ_SOC_DATA_PROGRAMMABLE_DMA	BIT(1)
 #define JZ_SOC_DATA_PER_CHAN_PM		BIT(2)
 #define JZ_SOC_DATA_NO_DCKES_DCKEC	BIT(3)
+#define JZ_SOC_DATA_BREAK_LINKS		BIT(4)
 
 /**
  * struct jz4780_dma_hwdesc - descriptor structure read by the DMA controller.
@@ -356,6 +357,7 @@ static struct dma_async_tx_descriptor *jz4780_dma_prep_slave_sg(
 	void *context)
 {
 	struct jz4780_dma_chan *jzchan = to_jz4780_dma_chan(chan);
+	struct jz4780_dma_dev *jzdma = jz4780_dma_chan_parent(jzchan);
 	struct jz4780_dma_desc *desc;
 	unsigned int i;
 	int err;
@@ -376,7 +378,8 @@ static struct dma_async_tx_descriptor *jz4780_dma_prep_slave_sg(
 
 		desc->desc[i].dcm |= JZ_DMA_DCM_TIE;
 
-		if (i != (sg_len - 1)) {
+		if (i != (sg_len - 1) &&
+		    !(jzdma->soc_data->flags & JZ_SOC_DATA_BREAK_LINKS)) {
 			/* Automatically proceeed to the next descriptor. */
 			desc->desc[i].dcm |= JZ_DMA_DCM_LINK;
 
@@ -665,6 +668,7 @@ static enum dma_status jz4780_dma_tx_status(struct dma_chan *chan,
 static bool jz4780_dma_chan_irq(struct jz4780_dma_dev *jzdma,
 				struct jz4780_dma_chan *jzchan)
 {
+	struct jz4780_dma_desc *desc = jzchan->desc;
 	uint32_t dcs;
 	bool ack = true;
 
@@ -692,8 +696,10 @@ static bool jz4780_dma_chan_irq(struct jz4780_dma_dev *jzdma,
 
 				jz4780_dma_begin(jzchan);
 			} else if (dcs & JZ_DMA_DCS_TT) {
-				vchan_cookie_complete(&jzchan->desc->vdesc);
-				jzchan->desc = NULL;
+				if (jzchan->curr_hwdesc + 1 == desc->count) {
+					vchan_cookie_complete(&desc->vdesc);
+					jzchan->desc = NULL;
+				}
 
 				jz4780_dma_begin(jzchan);
 			} else {
@@ -994,6 +1000,7 @@ static int jz4780_dma_remove(struct platform_device *pdev)
 static const struct jz4780_dma_soc_data jz4740_dma_soc_data = {
 	.nb_channels = 6,
 	.transfer_ord_max = 5,
+	.flags = JZ_SOC_DATA_BREAK_LINKS,
 };
 
 static const struct jz4780_dma_soc_data jz4725b_dma_soc_data = {
-- 
2.21.0.593.g511ec345e18


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

* Re: [PATCH] dmaengine: dma-jz4780: Break descriptor chains on JZ4740
  2019-06-30 22:52 [PATCH] dmaengine: dma-jz4780: Break descriptor chains on JZ4740 Paul Cercueil
@ 2019-07-14 21:32 ` Paul Cercueil
  0 siblings, 0 replies; 2+ messages in thread
From: Paul Cercueil @ 2019-07-14 21:32 UTC (permalink / raw)
  To: Vinod Koul; +Cc: Paul Burton, od, dmaengine, linux-kernel

This patch makes the driver work on JZ4740 but fail on other SoCs.
Please ignore this patch, I'll make a V2.

Thanks,
-Paul



Le dim. 30 juin 2019 à 18:52, Paul Cercueil <paul@crapouillou.net> a 
écrit :
> The current driver works perfectly fine on every generation of the
> JZ47xx SoCs, except on the JZ4740.
> 
> There, when hardware descriptors are chained together (with the LINK
> bit set), the next descriptor isn't automatically fetched as it 
> should -
> instead, an interrupt is raised, even if the TIE bit (Transfer 
> Interrupt
> Enable) bit is cleared. When it happens, the DMA transfer seems to be
> stopped (it doesn't chain), and it's uncertain how many bytes have
> actually been transferred.
> 
> Until somebody smarter than me can figure out how to make chained
> descriptors work on the JZ4740, we now disable chained descriptors on
> that particular SoC.
> 
> Signed-off-by: Paul Cercueil <paul@crapouillou.net>
> ---
>  drivers/dma/dma-jz4780.c | 13 ++++++++++---
>  1 file changed, 10 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/dma/dma-jz4780.c b/drivers/dma/dma-jz4780.c
> index 263bee76ef0d..aae83389cc10 100644
> --- a/drivers/dma/dma-jz4780.c
> +++ b/drivers/dma/dma-jz4780.c
> @@ -92,6 +92,7 @@
>  #define JZ_SOC_DATA_PROGRAMMABLE_DMA	BIT(1)
>  #define JZ_SOC_DATA_PER_CHAN_PM		BIT(2)
>  #define JZ_SOC_DATA_NO_DCKES_DCKEC	BIT(3)
> +#define JZ_SOC_DATA_BREAK_LINKS		BIT(4)
> 
>  /**
>   * struct jz4780_dma_hwdesc - descriptor structure read by the DMA 
> controller.
> @@ -356,6 +357,7 @@ static struct dma_async_tx_descriptor 
> *jz4780_dma_prep_slave_sg(
>  	void *context)
>  {
>  	struct jz4780_dma_chan *jzchan = to_jz4780_dma_chan(chan);
> +	struct jz4780_dma_dev *jzdma = jz4780_dma_chan_parent(jzchan);
>  	struct jz4780_dma_desc *desc;
>  	unsigned int i;
>  	int err;
> @@ -376,7 +378,8 @@ static struct dma_async_tx_descriptor 
> *jz4780_dma_prep_slave_sg(
> 
>  		desc->desc[i].dcm |= JZ_DMA_DCM_TIE;
> 
> -		if (i != (sg_len - 1)) {
> +		if (i != (sg_len - 1) &&
> +		    !(jzdma->soc_data->flags & JZ_SOC_DATA_BREAK_LINKS)) {
>  			/* Automatically proceeed to the next descriptor. */
>  			desc->desc[i].dcm |= JZ_DMA_DCM_LINK;
> 
> @@ -665,6 +668,7 @@ static enum dma_status 
> jz4780_dma_tx_status(struct dma_chan *chan,
>  static bool jz4780_dma_chan_irq(struct jz4780_dma_dev *jzdma,
>  				struct jz4780_dma_chan *jzchan)
>  {
> +	struct jz4780_dma_desc *desc = jzchan->desc;
>  	uint32_t dcs;
>  	bool ack = true;
> 
> @@ -692,8 +696,10 @@ static bool jz4780_dma_chan_irq(struct 
> jz4780_dma_dev *jzdma,
> 
>  				jz4780_dma_begin(jzchan);
>  			} else if (dcs & JZ_DMA_DCS_TT) {
> -				vchan_cookie_complete(&jzchan->desc->vdesc);
> -				jzchan->desc = NULL;
> +				if (jzchan->curr_hwdesc + 1 == desc->count) {
> +					vchan_cookie_complete(&desc->vdesc);
> +					jzchan->desc = NULL;
> +				}
> 
>  				jz4780_dma_begin(jzchan);
>  			} else {
> @@ -994,6 +1000,7 @@ static int jz4780_dma_remove(struct 
> platform_device *pdev)
>  static const struct jz4780_dma_soc_data jz4740_dma_soc_data = {
>  	.nb_channels = 6,
>  	.transfer_ord_max = 5,
> +	.flags = JZ_SOC_DATA_BREAK_LINKS,
>  };
> 
>  static const struct jz4780_dma_soc_data jz4725b_dma_soc_data = {
> --
> 2.21.0.593.g511ec345e18
> 



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

end of thread, back to index

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-06-30 22:52 [PATCH] dmaengine: dma-jz4780: Break descriptor chains on JZ4740 Paul Cercueil
2019-07-14 21:32 ` Paul Cercueil

dmaengine Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/dmaengine/0 dmaengine/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 dmaengine dmaengine/ https://lore.kernel.org/dmaengine \
		dmaengine@vger.kernel.org
	public-inbox-index dmaengine

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.kernel.vger.dmaengine


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git