[PATCH 1/2] ar6k: missed SDIO interrupt fix

Samuel Ortiz sameo at openedhand.com
Tue Jan 22 20:08:48 CET 2008


Hi Werner,

We have to be more careful about pending SDIO interrupts from the host
side. This patch fixes the iperf bug Nod has been reporting.

Signed-off-by: Samuel Ortiz <sameo at openedhand.com>
---
 drivers/sdio/function/wlan/ar6000/include/wmi.h |    2 
 drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.c          |   55 +++++++++++++-----------
 drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.h          |    1 
 drivers/sdio/stack/busdriver/sdio_bus_events.c  |    4 -
 4 files changed, 34 insertions(+), 28 deletions(-)

Index: linux-2.6.24-rc8-omoko-svn/drivers/sdio/function/wlan/ar6000/include/wmi.h
===================================================================
--- linux-2.6.24-rc8-omoko-svn.orig/drivers/sdio/function/wlan/ar6000/include/wmi.h	2008-01-22 19:48:32.000000000 +0100
+++ linux-2.6.24-rc8-omoko-svn/drivers/sdio/function/wlan/ar6000/include/wmi.h	2008-01-22 19:58:33.000000000 +0100
@@ -1103,7 +1103,7 @@
     A_UINT8     snr;
     A_INT16     rssi;
     A_UINT8     bssid[ATH_MAC_LEN];
-//    A_UINT32    ieMask;
+    A_UINT32    ieMask;
 } POSTPACK WMI_BSS_INFO_HDR;
 
 /*
Index: linux-2.6.24-rc8-omoko-svn/drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.c
===================================================================
--- linux-2.6.24-rc8-omoko-svn.orig/drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.c	2008-01-22 19:48:32.000000000 +0100
+++ linux-2.6.24-rc8-omoko-svn/drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.c	2008-01-22 20:02:09.000000000 +0100
@@ -563,14 +563,10 @@
 	PSDREQUEST req;
 	struct s3c24xx_hcd_context * context =
 		container_of(work, struct s3c24xx_hcd_context, io_work);
-	unsigned long flags;
-
-//	spin_lock_irqsave(&context->lock, flags);
 
 	req = GET_CURRENT_REQUEST(&context->hcd);
 	if (req == NULL) {
 		DBG_PRINT(SDDBG_ERROR, ("%s(): No current request\n", __FUNCTION__));
-//		enable_irq(context->io_irq);
 		return;
 	}
 
@@ -615,12 +611,12 @@
 		if (context->complete == S3C24XX_HCD_DATA_READ ||
 		    context->complete == S3C24XX_HCD_DATA_WRITE) {
 			if (context->dma_en) {
+				dma_sync_single(NULL, context->io_buffer_dma,
+						req->BlockCount * req->BlockLen, DMA_BIDIRECTIONAL);
 
 				s3c2410_dma_ctrl(context->dma_channel, S3C2410_DMAOP_START);
 
-//				spin_unlock_irqrestore(&context->lock, flags);
 				wait_for_completion(&context->dma_complete);
-//				spin_lock_irqsave(&context->lock, flags);
 
 				s3c24xx_hcd_dma_complete(context);
 			} else {
@@ -630,16 +626,12 @@
 	}
 
  out:
-//	spin_unlock_irqrestore(&context->lock, flags);
-
 	s3c24xx_hcd_clear_sta(context);
 	s3c24xx_hcd_clear_imask(context);
 
 	writel(0, context->base + S3C2410_SDICMDARG);
 	writel(0, context->base + S3C2410_SDICMDCON);
 
-//	spin_unlock_irqrestore(&context->lock, flags);
-
 	SDIO_HandleHcdEvent(&context->hcd, EVENT_HCD_TRANSFER_DONE);
 }
 
@@ -747,9 +739,19 @@
 			imask &= ~S3C2410_SDIIMSK_SDIOIRQ;
 			writel(imask, context->base + S3C2440_SDIIMSK);
 			SDIO_HandleHcdEvent(&context->hcd, EVENT_HCD_SDIO_IRQ_PENDING);
-		}
 
-		writel(S3C2410_SDIDSTA_SDIOIRQDETECT, context->base + S3C2410_SDIDSTA);
+			dsta = readl(context->base + S3C2410_SDIDSTA);
+			if (dsta & S3C2410_SDIDSTA_SDIOIRQDETECT) {
+				writel(S3C2410_SDIDSTA_SDIOIRQDETECT,
+				       context->base + S3C2410_SDIDSTA);
+				SDIO_HandleHcdEvent(&context->hcd,
+						    EVENT_HCD_SDIO_IRQ_PENDING);
+			}
+
+
+		} else {
+			context->int_pending = 1;
+		}
 	}
 
 	req = GET_CURRENT_REQUEST(&context->hcd);
@@ -787,8 +789,8 @@
 	}
 
 	if (cmdsta & S3C2410_SDICMDSTAT_RSPFIN ||
-		(IS_SDREQ_WRITE_DATA(req->Flags) && (fsta &  S3C2410_SDIFSTA_TFDET)) ||
-		(!IS_SDREQ_WRITE_DATA(req->Flags) && (fsta &  S3C2410_SDIFSTA_RFDET))) {
+	    (IS_SDREQ_WRITE_DATA(req->Flags) && (fsta &  S3C2410_SDIFSTA_TFDET)) ||
+	    (!IS_SDREQ_WRITE_DATA(req->Flags) && (fsta &  S3C2410_SDIFSTA_RFDET))) {
 
 		writel(S3C2410_SDICMDSTAT_RSPFIN, context->base + S3C2410_SDICMDSTAT);
 
@@ -904,6 +906,12 @@
 		DBG_PRINT(SDDBG_TRACE, ("config SDIO_REARM_INT\n"));
 		spin_lock_irqsave(&context->lock,flags);
 
+		if (context->int_pending) {
+			context->int_pending = 0;
+			SDIO_HandleHcdEvent(&context->hcd,
+					    EVENT_HCD_SDIO_IRQ_PENDING);
+		}
+
 		context->int_sdio = 1;
 		imsk = readl(context->base + S3C2440_SDIIMSK);
 		imsk |= S3C2410_SDIIMSK_SDIOIRQ;
@@ -951,8 +959,6 @@
 	struct s3c24xx_hcd_context * context =
 		(struct s3c24xx_hcd_context *)hcd->pContext;
 
-//	dump_request(context);
-
 	req = GET_CURRENT_REQUEST(hcd);
 	DBG_ASSERT(req != NULL);
 
@@ -968,7 +974,6 @@
 
 	/* Enabling irqs */
 	imask = S3C2410_SDIIMSK_READWAIT;
-//	imask = S3C2410_SDIIMSK_READWAIT | S3C2410_SDIIMSK_SDIOIRQ;
 
 	cmdcon = readl(context->base + S3C2410_SDICMDCON);
 
@@ -1023,10 +1028,10 @@
 		req->DataRemaining = req->BlockCount * req->BlockLen;
 
 		/* Set data size, and start the transfer */
+		dcon |= S3C2410_SDIDCON_IRQPERIOD;
 		if (!(req->DataRemaining % 4)) {
 			context->data_size = 4;
 			dcon |= S3C2440_SDIDCON_DS_WORD;
-			dcon |= (1 << 24);
 		} else if (!(req->DataRemaining % 2)) {
 			context->data_size = 2;
 			dcon |= S3C2440_SDIDCON_DS_HALFWORD;
@@ -1036,12 +1041,15 @@
 		}
 
 #ifdef CONFIG_SDIO_S3C24XX_DMA
-		context->dma_en = 1;
-#else
-		context->dma_en = 0;
-		context->data_size = 1;
-		dcon |= S3C2440_SDIDCON_DS_BYTE;
+		if (req->DataRemaining > 16) {
+			context->dma_en = 1;
+		} else
 #endif
+		{
+			context->dma_en = 0;
+			context->data_size = 1;
+			dcon |= S3C2440_SDIDCON_DS_BYTE;
+		}
 
 		if (context->dma_en) {
 			dcon |= S3C2410_SDIDCON_DMAEN;
@@ -1324,6 +1332,7 @@
 	hcd_context.dma_en = 0;
 
 	hcd_context.int_sdio = 0;
+	hcd_context.int_pending = 0;
 
 	spin_lock_init(&hcd_context.lock);
 
Index: linux-2.6.24-rc8-omoko-svn/drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.h
===================================================================
--- linux-2.6.24-rc8-omoko-svn.orig/drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.h	2008-01-22 19:48:32.000000000 +0100
+++ linux-2.6.24-rc8-omoko-svn/drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.h	2008-01-22 19:58:33.000000000 +0100
@@ -46,6 +46,7 @@
 
 	UINT32		  	  int_mask;
 	UINT32		  	  int_sdio;            /* Do we have SDIO interrupt on ? */
+	UINT32		  	  int_pending;
 
 	UINT32		  	  complete;
 
Index: linux-2.6.24-rc8-omoko-svn/drivers/sdio/stack/busdriver/sdio_bus_events.c
===================================================================
--- linux-2.6.24-rc8-omoko-svn.orig/drivers/sdio/stack/busdriver/sdio_bus_events.c	2008-01-22 19:48:32.000000000 +0100
+++ linux-2.6.24-rc8-omoko-svn/drivers/sdio/stack/busdriver/sdio_bus_events.c	2008-01-22 19:58:33.000000000 +0100
@@ -712,8 +712,6 @@
                 return status;
             }
             if (pHcd->IrqProcState != SDHCD_IDLE) {
-                DBG_PRINT(SDDBG_ERROR, ("-SDIO Bus Driver: Already processing interrupts! (state = %d) \n",
-                                    pHcd->IrqProcState));
                 status = SDIO_STATUS_ERROR;
                 status2 = _ReleaseHcdLock(pHcd);
             } else {
@@ -746,8 +744,6 @@
         }
 
         if (pHcd->IrqProcState != SDHCD_IDLE) {
-            DBG_PRINT(SDDBG_ERROR, ("-SDIO Bus Driver: Already processing interrupts! (state = %d) \n",
-                                    pHcd->IrqProcState));
             status = SDIO_STATUS_ERROR;
         } else {
                 /* mark that we are processing */





More information about the openmoko-kernel mailing list