Skip to contentSkip to conversation

Minor DMA fixes

PATCH In review Adrian Hunter 6 participants 15 messages Nov 30, 2010 – Jan 20, 2011

Subsystems (2)
lore
Share & tools
lore
#0 lore raw

cover Minor DMA fixes

Hi

Adrian Hunter (2):
OMAP: DMA: prevent races while setting M idle mode to nostandby
OMAP: DMA: clear interrupt status correctly

 arch/arm/plat-omap/dma.c |   66 ++++++++++++++++++++++++++++++++-------------
 1 files changed, 47 insertions(+), 19 deletions(-)

Regards
Adrian

#1 lore raw

PATCH 1/2 OMAP: DMA: prevent races while setting M idle mode to nostandby

Quoted 1 line

From 8c0f4490d93b67326ff24f6ce1c7e925b08d96b3 Mon Sep 17 00:00:00 2001

From: Adrian Hunter <[email protected]>
Date: Mon, 22 Nov 2010 11:32:48 +0200
Subject: [PATCH 1/2] OMAP: DMA: prevent races while setting M idle mode to nostandby

In a couple of OMAP errata cases, sDMA M idle mode must be set temporarily to nostandby. If two DMA users were to do that at the same time, a race condition would arise. Prevent that by using a spin lock and counting up/down the number of times nostandby is set/reset.

---
 arch/arm/plat-omap/dma.c |   59 ++++++++++++++++++++++++++++++++++-----------
 1 files changed, 44 insertions(+), 15 deletions(-)
arch/arm/plat-omap/dma.c +44 -15
index a863f55..6158c99 100644
@@ -139,6 +139,9 @@ static spinlock_t dma_chan_lock;
 static struct omap_dma_lch *dma_chan;
 static void __iomem *omap_dma_base;
 
+static u32 midlemode_saved;
+static int midlemode_save_cnt;
+
 static const u8 omap1_dma_irq[OMAP1_LOGICAL_DMA_CH_COUNT] = {
 	INT_DMA_CH0_6, INT_DMA_CH1_7, INT_DMA_CH2_8, INT_DMA_CH3,
 	INT_DMA_CH4, INT_DMA_CH5, INT_1610_DMA_CH6, INT_1610_DMA_CH7,
@@ -1016,6 +1019,41 @@ void omap_start_dma(int lch)
 }
 EXPORT_SYMBOL(omap_start_dma);
 
+static void midlemode_nostandby(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dma_chan_lock, flags);
+	if (!midlemode_save_cnt) {
+		u32 l;
+
+		midlemode_saved = dma_read(OCP_SYSCONFIG);
+		l = midlemode_saved;
+		l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK;
+		l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE);
+		dma_write(l, OCP_SYSCONFIG);
+	}
+	midlemode_save_cnt += 1;
+	spin_unlock_irqrestore(&dma_chan_lock, flags);
+}
+
+static void midlemode_restore(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dma_chan_lock, flags);
+	midlemode_save_cnt -= 1;
+	if (!midlemode_save_cnt) {
+		u32 l;
+
+		l = dma_read(OCP_SYSCONFIG);
+		l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK;
+		l |= midlemode_saved & DMA_SYSCONFIG_MIDLEMODE_MASK;
+		dma_write(l, OCP_SYSCONFIG);
+	}
+	spin_unlock_irqrestore(&dma_chan_lock, flags);
+}
+
 void omap_stop_dma(int lch)
 {
 	u32 l;
@@ -1028,16 +1066,10 @@ void omap_stop_dma(int lch)
 	/* OMAP3 Errata i541: sDMA FIFO draining does not finish */
 	if (cpu_is_omap34xx() && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
 		int i = 0;
-		u32 sys_cf;
 
 		/* Configure No-Standby */
-		l = dma_read(OCP_SYSCONFIG);
-		sys_cf = l;
-		l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK;
-		l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE);
-		dma_write(l , OCP_SYSCONFIG);
+		midlemode_nostandby();
 
-		l = dma_read(CCR(lch));
 		l &= ~OMAP_DMA_CCR_EN;
 		dma_write(l, CCR(lch));
 
@@ -1053,7 +1085,7 @@ void omap_stop_dma(int lch)
 			printk(KERN_ERR "DMA drain did not complete on "
 					"lch %d\n", lch);
 		/* Restore OCP_SYSCONFIG */
-		dma_write(sys_cf, OCP_SYSCONFIG);
+		midlemode_restore();
 	} else {
 		l &= ~OMAP_DMA_CCR_EN;
 		dma_write(l, CCR(lch));
@@ -1711,7 +1743,6 @@ int omap_stop_dma_chain_transfers(int chain_id)
 {
 	int *channels;
 	u32 l, i;
-	u32 sys_cf;
 
 	/* Check for input params */
 	if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
@@ -1730,11 +1761,9 @@ int omap_stop_dma_chain_transfers(int chain_id)
 	 * DMA Errata:
 	 * Special programming model needed to disable DMA before end of block
 	 */
-	sys_cf = dma_read(OCP_SYSCONFIG);
-	l = sys_cf;
-	/* Middle mode reg set no Standby */
-	l &= ~((1 << 12)|(1 << 13));
-	dma_write(l, OCP_SYSCONFIG);
+
+	/* M idle mode reg set no Standby */
+	midlemode_nostandby();
 
 	for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
 
@@ -1754,7 +1783,7 @@ int omap_stop_dma_chain_transfers(int chain_id)
 	OMAP_DMA_CHAIN_QINIT(chain_id);
 
 	/* Errata - put in the old value */
-	dma_write(sys_cf, OCP_SYSCONFIG);
+	midlemode_restore();
 
 	return 0;
 }
Signature · 1 line
1.7.0.4
Acked-by on v1 1/2
#2 lore raw

RE: [PATCH 1/2] OMAP: DMA: prevent races while setting M idle mode to nostandby

Quoted 7 lines

-----Original Message-----
From: Adrian Hunter [mailto:[email protected]]
Sent: Tuesday, November 30, 2010 6:54 PM
To: Tony Lindgren
Cc: Adrian Hunter; Manjunatha GK; Santosh Shilimkar; linux-omap Mailing List
Subject: [PATCH 1/2] OMAP: DMA: prevent races while setting M idle mode

to

Quoted 6 lines

nostandby

From 8c0f4490d93b67326ff24f6ce1c7e925b08d96b3 Mon Sep 17 00:00:00 2001
From: Adrian Hunter <[email protected]>
Date: Mon, 22 Nov 2010 11:32:48 +0200
Subject: [PATCH 1/2] OMAP: DMA: prevent races while setting M idle mode

to

Quoted 9 lines

nostandby

In a couple of OMAP errata cases, sDMA M idle mode must be set temporarily to nostandby. If two DMA users were to do that at the same time, a race condition would arise. Prevent that by using a spin lock and counting up/down the number of times nostandby is set/reset.

Quoted 2 lines
---
 arch/arm/plat-omap/dma.c |   59

++++++++++++++++++++++++++++++++++-------

Quoted 121 lines

----

 1 files changed, 44 insertions(+), 15 deletions(-)
arch/arm/plat-omap/dma.c +40 -9
index a863f55..6158c99 100644
@@ -139,6 +139,9 @@ static spinlock_t dma_chan_lock;
 static struct omap_dma_lch *dma_chan;
 static void __iomem *omap_dma_base;
 
+static u32 midlemode_saved;
+static int midlemode_save_cnt;
+
 static const u8 omap1_dma_irq[OMAP1_LOGICAL_DMA_CH_COUNT] = {
 	INT_DMA_CH0_6, INT_DMA_CH1_7, INT_DMA_CH2_8, INT_DMA_CH3,
 	INT_DMA_CH4, INT_DMA_CH5, INT_1610_DMA_CH6, INT_1610_DMA_CH7,
@@ -1016,6 +1019,41 @@ void omap_start_dma(int lch)
 }
 EXPORT_SYMBOL(omap_start_dma);
 
+static void midlemode_nostandby(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dma_chan_lock, flags);
+	if (!midlemode_save_cnt) {
+		u32 l;
+
+		midlemode_saved = dma_read(OCP_SYSCONFIG);
+		l = midlemode_saved;
+		l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK;
+		l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE);
+		dma_write(l, OCP_SYSCONFIG);
+	}
+	midlemode_save_cnt += 1;
+	spin_unlock_irqrestore(&dma_chan_lock, flags);
+}
+
+static void midlemode_restore(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dma_chan_lock, flags);
+	midlemode_save_cnt -= 1;
+	if (!midlemode_save_cnt) {
+		u32 l;
+
+		l = dma_read(OCP_SYSCONFIG);
+		l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK;
+		l |= midlemode_saved & DMA_SYSCONFIG_MIDLEMODE_MASK;
+		dma_write(l, OCP_SYSCONFIG);
+	}
+	spin_unlock_irqrestore(&dma_chan_lock, flags);
+}
+
 void omap_stop_dma(int lch)
 {
 	u32 l;
@@ -1028,16 +1066,10 @@ void omap_stop_dma(int lch)
 	/* OMAP3 Errata i541: sDMA FIFO draining does not finish */
 	if (cpu_is_omap34xx() && (l & OMAP_DMA_CCR_SEL_SRC_DST_SYNC)) {
 		int i = 0;
-		u32 sys_cf;
 
 		/* Configure No-Standby */
-		l = dma_read(OCP_SYSCONFIG);
-		sys_cf = l;
-		l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK;
-		l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE);
-		dma_write(l , OCP_SYSCONFIG);
+		midlemode_nostandby();
 
-		l = dma_read(CCR(lch));
 		l &= ~OMAP_DMA_CCR_EN;
 		dma_write(l, CCR(lch));
 
@@ -1053,7 +1085,7 @@ void omap_stop_dma(int lch)
 			printk(KERN_ERR "DMA drain did not complete on "
 					"lch %d\n", lch);
 		/* Restore OCP_SYSCONFIG */
-		dma_write(sys_cf, OCP_SYSCONFIG);
+		midlemode_restore();
 	} else {
 		l &= ~OMAP_DMA_CCR_EN;
 		dma_write(l, CCR(lch));
@@ -1711,7 +1743,6 @@ int omap_stop_dma_chain_transfers(int chain_id)
 {
 	int *channels;
 	u32 l, i;
-	u32 sys_cf;
 
 	/* Check for input params */
 	if (unlikely((chain_id < 0 || chain_id >= dma_lch_count))) {
@@ -1730,11 +1761,9 @@ int omap_stop_dma_chain_transfers(int chain_id)
 	 * DMA Errata:
 	 * Special programming model needed to disable DMA before end of

block

arch/arm/plat-omap/dma.c +4 -7
 	 */
-	sys_cf = dma_read(OCP_SYSCONFIG);
-	l = sys_cf;
-	/* Middle mode reg set no Standby */
-	l &= ~((1 << 12)|(1 << 13));
-	dma_write(l, OCP_SYSCONFIG);
+
+	/* M idle mode reg set no Standby */
+	midlemode_nostandby();
 
 	for (i = 0; i < dma_linked_lch[chain_id].no_of_lchs_linked; i++) {
@@ -1754,7 +1783,7 @@ int omap_stop_dma_chain_transfers(int chain_id)
 	OMAP_DMA_CHAIN_QINIT(chain_id);
 
 	/* Errata - put in the old value */
-	dma_write(sys_cf, OCP_SYSCONFIG);
+	midlemode_restore();
 
 	return 0;
 }
--

1.7.0.4

Acked-by on v1 1/2
#3 lore raw

Re: [PATCH 1/2] OMAP: DMA: prevent races while setting M idle mode to nostandby

In reply to Adrian Hunter
Quoted 6 lines · On Tuesday 30 November 2010 15:23:47 Hunter Adrian (Nokia-MS/Helsinki) wrote:

From 8c0f4490d93b67326ff24f6ce1c7e925b08d96b3 Mon Sep 17 00:00:00 2001
From: Adrian Hunter <[email protected]>
Date: Mon, 22 Nov 2010 11:32:48 +0200
Subject: [PATCH 1/2] OMAP: DMA: prevent races while setting M idle mode to nostandby

Quoted 7 lines

In a couple of OMAP errata cases, sDMA M idle mode must be set temporarily to nostandby. If two DMA users were to do that at the same time, a race condition would arise. Prevent that by using a spin lock and counting up/down the number of times nostandby is set/reset.

#4 lore raw

Re: [PATCH 1/2] OMAP: DMA: prevent races while setting M idle mode to nostandby

In reply to Adrian Hunter

Hi Adrian,

Quoted 40 lines · Adrian Hunter

From 8c0f4490d93b67326ff24f6ce1c7e925b08d96b3 Mon Sep 17 00:00:00 2001
From: Adrian Hunter <[email protected]>
Date: Mon, 22 Nov 2010 11:32:48 +0200
Subject: [PATCH 1/2] OMAP: DMA: prevent races while setting M idle mode to nostandby

In a couple of OMAP errata cases, sDMA M idle mode must be set temporarily to nostandby. If two DMA users were to do that at the same time, a race condition would arise. Prevent that by using a spin lock and counting up/down the number of times nostandby is set/reset.

---
 arch/arm/plat-omap/dma.c |   59 ++++++++++++++++++++++++++++++++++-----------
 1 files changed, 44 insertions(+), 15 deletions(-)
arch/arm/plat-omap/dma.c +9 -0
index a863f55..6158c99 100644
@@ -139,6 +139,9 @@ static spinlock_t dma_chan_lock;
 static struct omap_dma_lch *dma_chan;
 static void __iomem *omap_dma_base;
 
+static u32 midlemode_saved;
+static int midlemode_save_cnt;
+
 static const u8 omap1_dma_irq[OMAP1_LOGICAL_DMA_CH_COUNT] = {
 	INT_DMA_CH0_6, INT_DMA_CH1_7, INT_DMA_CH2_8, INT_DMA_CH3,
 	INT_DMA_CH4, INT_DMA_CH5, INT_1610_DMA_CH6, INT_1610_DMA_CH7,
@@ -1016,6 +1019,41 @@ void omap_start_dma(int lch)
 }
 EXPORT_SYMBOL(omap_start_dma);
 
+static void midlemode_nostandby(void)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&dma_chan_lock, flags);
+	if (!midlemode_save_cnt) {

arch/arm/plat-omap/dma.c void omap_start_dma(int lch) · line 1037

Quoted 10 lines
arch/arm/plat-omap/dma.c +10 -0
+		u32 l;
+
+		midlemode_saved = dma_read(OCP_SYSCONFIG);
+		l = midlemode_saved;
+		l &= ~DMA_SYSCONFIG_MIDLEMODE_MASK;
+		l |= DMA_SYSCONFIG_MIDLEMODE(DMA_IDLEMODE_NO_IDLE);
+		dma_write(l, OCP_SYSCONFIG);
+	}
+	midlemode_save_cnt += 1;
+	spin_unlock_irqrestore(&dma_chan_lock, flags);

The latest DMA hwmod patch series is already taken care of this issue through the API's:
https://patchwork.kernel.org/patch/372231/

-Manjunath
[...]

#5 lore raw

PATCH 2/2 OMAP: DMA: clear interrupt status correctly

In reply to Adrian Hunter
Quoted 1 line

From 85934ded48552fde84b083575ac2006f1542324b Mon Sep 17 00:00:00 2001

From: Adrian Hunter <[email protected]>
Date: Wed, 24 Nov 2010 13:23:21 +0200
Subject: [PATCH 2/2] OMAP: DMA: clear interrupt status correctly

When clearing the DMA channel, clear all status bits.

When handling a DMA interrupt, clear only the interrupt status bits that have been read and are passed to the channel's interrupt handler, not every status bit.

---
 arch/arm/plat-omap/dma.c |    7 +++----
 1 files changed, 3 insertions(+), 4 deletions(-)
arch/arm/plat-omap/dma.c +3 -4
index 6158c99..3300e67 100644
@@ -49,7 +49,7 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
 #endif
 
 #define OMAP_DMA_ACTIVE			0x01
-#define OMAP2_DMA_CSR_CLEAR_MASK	0xffe
+#define OMAP2_DMA_CSR_CLEAR_MASK	0xffffffff
 
 #define OMAP_FUNC_MUX_ARM_BASE		(0xfffe1000 + 0xec)
 
@@ -2010,7 +2010,7 @@ static int omap2_dma_handle_ch(int ch)
 		printk(KERN_INFO "DMA misaligned error with device %d\n",
 		       dma_chan[ch].dev_id);
 
-	dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(ch));
+	dma_write(status, CSR(ch));
 	dma_write(1 << ch, IRQSTATUS_L0);
 	/* read back the register to flush the write */
 	dma_read(IRQSTATUS_L0);
@@ -2030,10 +2030,9 @@ static int omap2_dma_handle_ch(int ch)
 			OMAP_DMA_CHAIN_INCQHEAD(chain_id);
 
 		status = dma_read(CSR(ch));
+		dma_write(status, CSR(ch));
 	}
 
-	dma_write(status, CSR(ch));
-
 	if (likely(dma_chan[ch].callback != NULL))
 		dma_chan[ch].callback(ch, status, dma_chan[ch].data);
 
Signature · 1 line
1.7.0.4
Acked-by on v1 2/2
#6 lore raw

RE: [PATCH 2/2] OMAP: DMA: clear interrupt status correctly

Quoted 13 lines

-----Original Message-----
From: Adrian Hunter [mailto:[email protected]]
Sent: Tuesday, November 30, 2010 6:54 PM
To: Tony Lindgren
Cc: Santosh Shilimkar; Manjunatha GK; Adrian Hunter; linux-omap Mailing List
Subject: [PATCH 2/2] OMAP: DMA: clear interrupt status correctly

From 85934ded48552fde84b083575ac2006f1542324b Mon Sep 17 00:00:00 2001
From: Adrian Hunter <[email protected]>
Date: Wed, 24 Nov 2010 13:23:21 +0200
Subject: [PATCH 2/2] OMAP: DMA: clear interrupt status correctly

Quoted 7 lines

When clearing the DMA channel, clear all status bits.

When handling a DMA interrupt, clear only the interrupt status bits that have been read and are passed to the channel's interrupt handler, not every status bit.

Quoted 40 lines
---
 arch/arm/plat-omap/dma.c |    7 +++----
 1 files changed, 3 insertions(+), 4 deletions(-)
arch/arm/plat-omap/dma.c +3 -5
index 6158c99..3300e67 100644
@@ -49,7 +49,7 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
 #endif
 
 #define OMAP_DMA_ACTIVE			0x01
-#define OMAP2_DMA_CSR_CLEAR_MASK	0xffe
+#define OMAP2_DMA_CSR_CLEAR_MASK	0xffffffff
 
 #define OMAP_FUNC_MUX_ARM_BASE		(0xfffe1000 + 0xec)
 
@@ -2010,7 +2010,7 @@ static int omap2_dma_handle_ch(int ch)
 		printk(KERN_INFO "DMA misaligned error with device %d\n",
 		       dma_chan[ch].dev_id);
 
-	dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR(ch));
+	dma_write(status, CSR(ch));
 	dma_write(1 << ch, IRQSTATUS_L0);
 	/* read back the register to flush the write */
 	dma_read(IRQSTATUS_L0);
@@ -2030,10 +2030,9 @@ static int omap2_dma_handle_ch(int ch)
 			OMAP_DMA_CHAIN_INCQHEAD(chain_id);
 
 		status = dma_read(CSR(ch));
+		dma_write(status, CSR(ch));
 	}
 
-	dma_write(status, CSR(ch));
-
 	if (likely(dma_chan[ch].callback != NULL))
 		dma_chan[ch].callback(ch, status, dma_chan[ch].data);
 
--

1.7.0.4

#7 lore raw

Re: [PATCH 2/2] OMAP: DMA: clear interrupt status correctly

Quoted 13 lines · Santosh Shilimkar
Quoted 13 lines

-----Original Message-----
From: Adrian Hunter [mailto:[email protected]]
Sent: Tuesday, November 30, 2010 6:54 PM
To: Tony Lindgren
Cc: Santosh Shilimkar; Manjunatha GK; Adrian Hunter; linux-omap Mailing List
Subject: [PATCH 2/2] OMAP: DMA: clear interrupt status correctly

From 85934ded48552fde84b083575ac2006f1542324b Mon Sep 17 00:00:00 2001
From: Adrian Hunter <[email protected]>
Date: Wed, 24 Nov 2010 13:23:21 +0200
Subject: [PATCH 2/2] OMAP: DMA: clear interrupt status correctly

Quoted 8 lines
Quoted 7 lines

When clearing the DMA channel, clear all status bits.

When handling a DMA interrupt, clear only the interrupt status bits that have been read and are passed to the channel's interrupt handler, not every status bit.

Adrian, care to refresh this one against the devel-dma branch that has the hwmod changes?

Looks like at least the CSR_CLEAR_MASK is still wrong in the current code.

Regards,

Tony

author Acked-by Santosh Shilimkar
#8 lore raw

Re: [PATCH 2/2] OMAP: DMA: clear interrupt status correctly

From fffa19df17d73c1ed2e8c65c0b6604ee1dddff84 Mon Sep 17 00:00:00 2001
From: Adrian Hunter <[email protected]>
Date: Wed, 24 Nov 2010 13:23:21 +0200
Subject: [PATCH] OMAP: DMA: clear interrupt status correctly

When clearing the DMA channel, clear all status bits.

When handling a DMA interrupt, clear only the interrupt status bits that have been read and are passed to the channel's interrupt handler, not every status bit.

---
 arch/arm/plat-omap/dma.c |    7 +++----
 1 files changed, 3 insertions(+), 4 deletions(-)
arch/arm/plat-omap/dma.c +3 -4
index c4b2b47..8536308 100644
@@ -53,7 +53,7 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
 #endif
 
 #define OMAP_DMA_ACTIVE			0x01
-#define OMAP2_DMA_CSR_CLEAR_MASK	0xffe
+#define OMAP2_DMA_CSR_CLEAR_MASK	0xffffffff
 
 #define OMAP_FUNC_MUX_ARM_BASE		(0xfffe1000 + 0xec)
 
@@ -1873,7 +1873,7 @@ static int omap2_dma_handle_ch(int ch)
 		printk(KERN_INFO "DMA misaligned error with device %d\n",
 		       dma_chan[ch].dev_id);
 
-	p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, ch);
+	p->dma_write(status, CSR, ch);
 	p->dma_write(1 << ch, IRQSTATUS_L0, ch);
 	/* read back the register to flush the write */
 	p->dma_read(IRQSTATUS_L0, ch);
@@ -1893,10 +1893,9 @@ static int omap2_dma_handle_ch(int ch)
 			OMAP_DMA_CHAIN_INCQHEAD(chain_id);
 
 		status = p->dma_read(CSR, ch);
+		p->dma_write(status, CSR, ch);
 	}
 
-	p->dma_write(status, CSR, ch);
-
 	if (likely(dma_chan[ch].callback != NULL))
 		dma_chan[ch].callback(ch, status, dma_chan[ch].data);
 
Signature · 1 line
1.7.0.4
#9 lore raw

Re: [PATCH 2/2] OMAP: DMA: clear interrupt status correctly

Quoted 5 lines · Adrian Hunter

From fffa19df17d73c1ed2e8c65c0b6604ee1dddff84 Mon Sep 17 00:00:00 2001
From: Adrian Hunter <[email protected]>
Date: Wed, 24 Nov 2010 13:23:21 +0200
Subject: [PATCH] OMAP: DMA: clear interrupt status correctly

Quoted 8 lines

When clearing the DMA channel, clear all status bits.

When handling a DMA interrupt, clear only the interrupt status bits that have been read and are passed to the channel's interrupt handler, not every status bit.

Looks like a fix that should go into 2.6.38-rc2. Can you repost and Cc linux-arm-kernel as well?

Thanks,

Kevin

Quoted 37 lines
---
 arch/arm/plat-omap/dma.c |    7 +++----
 1 files changed, 3 insertions(+), 4 deletions(-)
arch/arm/plat-omap/dma.c +1 -1
index c4b2b47..8536308 100644
@@ -53,7 +53,7 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
 #endif
 #define OMAP_DMA_ACTIVE			0x01
-#define OMAP2_DMA_CSR_CLEAR_MASK	0xffe
+#define OMAP2_DMA_CSR_CLEAR_MASK	0xffffffff
 #define OMAP_FUNC_MUX_ARM_BASE		(0xfffe1000 + 0xec)
 @@ -1873,7 +1873,7 @@ static int omap2_dma_handle_ch(int ch)
 		printk(KERN_INFO "DMA misaligned error with device %d\n",
 		       dma_chan[ch].dev_id);

- p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, ch);

arch/arm/plat-omap/dma.c +2 -1
+	p->dma_write(status, CSR, ch);
 	p->dma_write(1 << ch, IRQSTATUS_L0, ch);
 	/* read back the register to flush the write */
 	p->dma_read(IRQSTATUS_L0, ch);
@@ -1893,10 +1893,9 @@ static int omap2_dma_handle_ch(int ch)
 			OMAP_DMA_CHAIN_INCQHEAD(chain_id);
 		status = p->dma_read(CSR, ch);
+		p->dma_write(status, CSR, ch);
 	}
 -	p->dma_write(status, CSR, ch);
-
 	if (likely(dma_chan[ch].callback != NULL))
 		dma_chan[ch].callback(ch, status, dma_chan[ch].data);
 -- 

1.7.0.4
--
To unsubscribe from this list: send the line "unsubscribe linux-omap" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html

#10 lore raw

PATCH 1/1 OMAP: DMA: clear interrupt status correctly

From fffa19df17d73c1ed2e8c65c0b6604ee1dddff84 Mon Sep 17 00:00:00 2001
From: Adrian Hunter <[email protected]>
Date: Wed, 24 Nov 2010 13:23:21 +0200
Subject: [PATCH] OMAP: DMA: clear interrupt status correctly

When clearing the DMA channel, clear all status bits.

When handling a DMA interrupt, clear only the interrupt status bits that have been read and are passed to the channel's interrupt handler, not every status bit.

---
  arch/arm/plat-omap/dma.c |    7 +++----
  1 files changed, 3 insertions(+), 4 deletions(-)
arch/arm/plat-omap/dma.c +3 -4
index c4b2b47..8536308 100644
@@ -53,7 +53,7 @@ enum { DMA_CHAIN_STARTED, DMA_CHAIN_NOTSTARTED };
  #endif
  
  #define OMAP_DMA_ACTIVE			0x01
-#define OMAP2_DMA_CSR_CLEAR_MASK	0xffe
+#define OMAP2_DMA_CSR_CLEAR_MASK	0xffffffff
  
  #define OMAP_FUNC_MUX_ARM_BASE		(0xfffe1000 + 0xec)
  
@@ -1873,7 +1873,7 @@ static int omap2_dma_handle_ch(int ch)
  		printk(KERN_INFO "DMA misaligned error with device %d\n",
  		       dma_chan[ch].dev_id);
  
-	p->dma_write(OMAP2_DMA_CSR_CLEAR_MASK, CSR, ch);
+	p->dma_write(status, CSR, ch);
  	p->dma_write(1 << ch, IRQSTATUS_L0, ch);
  	/* read back the register to flush the write */
  	p->dma_read(IRQSTATUS_L0, ch);
@@ -1893,10 +1893,9 @@ static int omap2_dma_handle_ch(int ch)
  			OMAP_DMA_CHAIN_INCQHEAD(chain_id);
  
  		status = p->dma_read(CSR, ch);
+		p->dma_write(status, CSR, ch);
  	}
  
-	p->dma_write(status, CSR, ch);
-
  	if (likely(dma_chan[ch].callback != NULL))
  		dma_chan[ch].callback(ch, status, dma_chan[ch].data);
  
Signature · 1 line
1.7.0.4
#11 lore raw

PATCH 1/1 OMAP: DMA: clear interrupt status correctly

Quoted 6 lines · Adrian Hunter

From fffa19df17d73c1ed2e8c65c0b6604ee1dddff84 Mon Sep 17 00:00:00 2001
From: Adrian Hunter <[email protected]>
Date: Wed, 24 Nov 2010 13:23:21 +0200
Subject: [PATCH] OMAP: DMA: clear interrupt status correctly

Quoted 7 lines

When clearing the DMA channel, clear all status bits.

When handling a DMA interrupt, clear only the interrupt status bits that have been read and are passed to the channel's interrupt handler, not every status bit.

Thanks, will queue as a fix.

Tony

#12 lore raw

PATCH 1/1 OMAP: DMA: clear interrupt status correctly

Quoted 9 lines · Tony Lindgren
Quoted 8 lines · Adrian Hunter

From fffa19df17d73c1ed2e8c65c0b6604ee1dddff84 Mon Sep 17 00:00:00 2001
From: Adrian Hunter <[email protected]>
Date: Wed, 24 Nov 2010 13:23:21 +0200
Subject: [PATCH] OMAP: DMA: clear interrupt status correctly

When clearing the DMA channel, clear all status bits.

Quoted 7 lines
Quoted 5 lines

When handling a DMA interrupt, clear only the interrupt status bits that have been read and are passed to the channel's interrupt handler, not every status bit.

Thanks, will queue as a fix.

This did not apply for some reason, I've applied it manually. Please check that I got it right in omap-fixes branch soonish. Let me know if it needs updating.

Tony

#13 lore raw

PATCH 1/1 OMAP: DMA: clear interrupt status correctly

Quoted 14 lines · Tony Lindgren
Quoted 13 lines · Tony Lindgren
Quoted 12 lines · Adrian Hunter

From fffa19df17d73c1ed2e8c65c0b6604ee1dddff84 Mon Sep 17 00:00:00 2001
From: Adrian Hunter <[email protected]>
Date: Wed, 24 Nov 2010 13:23:21 +0200
Subject: [PATCH] OMAP: DMA: clear interrupt status correctly

When clearing the DMA channel, clear all status bits.

When handling a DMA interrupt, clear only the interrupt status bits that have been read and are passed to the channel's interrupt handler, not every status bit.

Quoted 7 lines
Quoted 3 lines
Quoted 1 line

Thanks, will queue as a fix.

This did not apply for some reason, I've applied it manually. Please check that I got it right in omap-fixes branch soonish. Let me know if it needs updating.

Looks like the commit message is missing:

you can also add:

-Manjunath

#14 lore raw

PATCH 1/1 OMAP: DMA: clear interrupt status correctly

In reply to Tony Lindgren
Quoted 14 lines · Tony Lindgren
Quoted 13 lines · Tony Lindgren
Quoted 12 lines · Adrian Hunter

From fffa19df17d73c1ed2e8c65c0b6604ee1dddff84 Mon Sep 17 00:00:00 2001
From: Adrian Hunter<[email protected]>
Date: Wed, 24 Nov 2010 13:23:21 +0200
Subject: [PATCH] OMAP: DMA: clear interrupt status correctly

When clearing the DMA channel, clear all status bits.

When handling a DMA interrupt, clear only the interrupt status bits that have been read and are passed to the channel's interrupt handler, not every status bit.

Quoted 7 lines
Quoted 3 lines
Quoted 1 line

Thanks, will queue as a fix.

This did not apply for some reason, I've applied it manually. Please check that I got it right in omap-fixes branch soonish. Let me know if it needs updating.

Looks fine

Quoted 3 lines

Tony