[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