[PATCH 2/2] Workaround MUSB DMA_INTR sometimes reads zero

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



MUSB DMA_INTR register may sometimes read zero when infact there
was a pending interrupt. Workaround this by reading the DMA_COUNT
values for all enabled channels when this condition occurs.
Flag these channels as the ones needing to be serviced.

Signed-off-by: Anand Gadiyar <gadiyar@xxxxxx>
Cc: Ajay Kumar Gupta <ajay.gupta@xxxxxx>
Cc: Felipe Balbi <felipe.balbi@xxxxxxxxx>
Cc: David Brownell <dbrownell@xxxxxxxxxxxxxxxxxxxxx>
Cc: Sergei Shtylyov <sshtylyov@xxxxxxxxxxxxx>
---
This issue exists on versions of the controller newer than 1.8.
The first version of this patch checked for this version
before acting. However to keep the code clean, I felt that
it is acceptable to do this unconditionally on all versions.

Also, the absence of the debug print meant that we would
never catch a spurious DMA interrupt on the older versions,
so adding the prints helps there.

 drivers/usb/musb/musbhsdma.c |   24 ++++++++++++++++++++++--
 1 files changed, 22 insertions(+), 2 deletions(-)

Index: linux-omap-2.6/drivers/usb/musb/musbhsdma.c
===================================================================
--- linux-omap-2.6.orig/drivers/usb/musb/musbhsdma.c
+++ linux-omap-2.6/drivers/usb/musb/musbhsdma.c
@@ -256,14 +256,34 @@ static irqreturn_t dma_controller_irq(in
 	spin_lock_irqsave(&musb->lock, flags);
 
 	int_hsdma = musb_readb(mbase, MUSB_HSDMA_INTR);
-	if (!int_hsdma)
-		goto done;
 
 #ifdef CONFIG_BLACKFIN
 	/* Clear DMA interrupt flags */
 	musb_writeb(mbase, MUSB_HSDMA_INTR, int_hsdma);
 #endif
 
+	if (!int_hsdma) {
+		DBG(2, "spurious DMA irq\n");
+
+		for (bchannel = 0; bchannel < MUSB_HSDMA_CHANNELS; bchannel++) {
+			musb_channel = (struct musb_dma_channel *)
+					&(controller->channel[bchannel]);
+			channel = &musb_channel->channel;
+			if (channel->status == MUSB_DMA_STATUS_BUSY) {
+				csr = musb_readw(mbase,
+					MUSB_HSDMA_CHANNEL_OFFSET(bchannel,
+							MUSB_HSDMA_COUNT));
+				if (csr == 0)
+					int_hsdma |= (1 << bchannel);
+			}
+		}
+
+		DBG(2, "int_hsdma = 0x%x\n", int_hsdma);
+
+		if (!int_hsdma)
+			goto done;
+	}
+
 	for (bchannel = 0; bchannel < MUSB_HSDMA_CHANNELS; bchannel++) {
 		if (int_hsdma & (1 << bchannel)) {
 			musb_channel = (struct musb_dma_channel *)
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux