[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