[PATCH 1/3] ar6k: Asynchronous SDIO IRQ handling
Samuel Ortiz
sameo at openedhand.com
Wed Jan 30 01:15:20 CET 2008
Hi Werner,
We now notify the SDIO stack asynchronously when we receive an SDIO
interrupt.
By doing so we make sure the notification is atomic, and that allows
us to get rid of the ugly dsta double checking.
Signed-off-by: Samuel Ortiz <sameo at openedhand.com>
---
drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.c | 44 ++++++++++++++++++++-------------
drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.h | 1
2 files changed, 28 insertions(+), 17 deletions(-)
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-30 00:03:35.000000000 +0100
+++ linux-2.6.24-rc8-omoko-svn/drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.c 2008-01-30 00:45:44.000000000 +0100
@@ -561,6 +561,7 @@
static void s3c24xx_hcd_io_work(struct work_struct *work)
{
PSDREQUEST req;
+ SDIO_STATUS status = SDIO_STATUS_SUCCESS;
struct s3c24xx_hcd_context * context =
container_of(work, struct s3c24xx_hcd_context, io_work);
@@ -610,6 +611,15 @@
/* There is a data stage */
if (context->complete == S3C24XX_HCD_DATA_READ ||
context->complete == S3C24XX_HCD_DATA_WRITE) {
+ status = SDIO_CheckResponse(&context->hcd, req,
+ SDHCD_CHECK_DATA_TRANS_OK);
+
+ if (!SDIO_SUCCESS(status)) {
+ DBG_PRINT(SDDBG_ERROR,
+ ("Target not ready for data xfer\n"));
+ return;
+ }
+
if (context->dma_en) {
dma_sync_single(NULL, context->io_buffer_dma,
req->BlockCount * req->BlockLen, DMA_BIDIRECTIONAL);
@@ -635,6 +645,20 @@
SDIO_HandleHcdEvent(&context->hcd, EVENT_HCD_TRANSFER_DONE);
}
+static void s3c24xx_hcd_irq_work(struct work_struct *work)
+{
+ struct s3c24xx_hcd_context * context =
+ container_of(work, struct s3c24xx_hcd_context, irq_work);
+
+ disable_irq(context->io_irq);
+
+ writel(S3C2410_SDIDSTA_SDIOIRQDETECT, context->base + S3C2410_SDIDSTA);
+
+ SDIO_HandleHcdEvent(&context->hcd, EVENT_HCD_SDIO_IRQ_PENDING);
+
+ enable_irq(context->io_irq);
+}
+
void s3c24xx_hcd_dma_done(struct s3c2410_dma_chan *dma_ch, void *buf_id,
int size, enum s3c2410_dma_buffresult result)
{
@@ -738,17 +762,7 @@
imask = readl(context->base + S3C2440_SDIIMSK);
imask &= ~S3C2410_SDIIMSK_SDIOIRQ;
writel(imask, context->base + S3C2440_SDIIMSK);
- SDIO_HandleHcdEvent(&context->hcd, EVENT_HCD_SDIO_IRQ_PENDING);
-
- 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);
- }
-
-
+ schedule_work(&context->irq_work);
} else {
context->int_pending = 1;
}
@@ -849,7 +863,6 @@
SDIO_STATUS s3c24xx_hcd_config(PSDHCD hcd, PSDCONFIG config)
{
u32 con, imsk;
- unsigned long flags;
SDIO_STATUS status = SDIO_STATUS_SUCCESS;
PSDCONFIG_SDIO_INT_CTRL_DATA int_data;
struct s3c24xx_hcd_context * context = (struct s3c24xx_hcd_context *)hcd->pContext;
@@ -904,12 +917,10 @@
break;
case SDCONFIG_SDIO_REARM_INT:
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);
+ schedule_work(&context->irq_work);
}
context->int_sdio = 1;
@@ -917,8 +928,6 @@
imsk |= S3C2410_SDIIMSK_SDIOIRQ;
writel(imsk, context->base + S3C2440_SDIIMSK);
- spin_unlock_irqrestore(&context->lock,flags);
-
status = SDIO_STATUS_SUCCESS;
break;
case SDCONFIG_FUNC_CHANGE_BUS_MODE:
@@ -1340,6 +1349,7 @@
init_completion(&hcd_context.xfer_complete);
INIT_WORK(&hcd_context.io_work, s3c24xx_hcd_io_work);
+ INIT_WORK(&hcd_context.irq_work, s3c24xx_hcd_irq_work);
mdelay(100);
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-30 00:03:35.000000000 +0100
+++ linux-2.6.24-rc8-omoko-svn/drivers/sdio/hcd/s3c24xx/s3c24xx_hcd.h 2008-01-30 00:45:44.000000000 +0100
@@ -57,6 +57,7 @@
spinlock_t lock;
struct work_struct io_work;
+ struct work_struct irq_work;
};
SDIO_STATUS s3c24xx_hcd_config(PSDHCD hcd, PSDCONFIG config);
More information about the openmoko-kernel
mailing list