mtd: pxa3xx-nand: handle PIO in threaded interrupt

Linux-MTD Mailing List linux-mtd at lists.infradead.org
Wed Apr 22 10:59:02 PDT 2015


Gitweb:     http://git.infradead.org/?p=mtd-2.6.git;a=commit;h=24542257a3b987025d4b998ec2d15e556c98ad3f
Commit:     24542257a3b987025d4b998ec2d15e556c98ad3f
Parent:     adf716d2f3e62820cc86cdb08c277516c7012352
Author:     Robert Jarzmik <robert.jarzmik at free.fr>
AuthorDate: Fri Feb 20 19:36:43 2015 +0100
Committer:  Brian Norris <computersforpeace at gmail.com>
CommitDate: Sat Feb 28 01:08:36 2015 -0800

    mtd: pxa3xx-nand: handle PIO in threaded interrupt
    
    Change the handling of the data stage in the driver : don't pump data in
    the top-half interrupt, but rather schedule a thread for non dma cases.
    
    This will enable latencies in the data pumping, especially if delays are
    required. Moreover platform shall be more reactive as other interrupts
    can be served while pumping data.
    
    No throughput degradation was observed, at least on the zylonite
    platform, while a slight degradation was being expected.
    
    Signed-off-by: Robert Jarzmik <robert.jarzmik at free.fr>
    Tested-by: Maxime Ripard <maxime.ripard at free-electrons.com>
    Signed-off-by: Brian Norris <computersforpeace at gmail.com>
---
 drivers/mtd/nand/pxa3xx_nand.c | 22 +++++++++++++++++++---
 1 file changed, 19 insertions(+), 3 deletions(-)

diff --git a/drivers/mtd/nand/pxa3xx_nand.c b/drivers/mtd/nand/pxa3xx_nand.c
index bc67736..3f09f2e 100644
--- a/drivers/mtd/nand/pxa3xx_nand.c
+++ b/drivers/mtd/nand/pxa3xx_nand.c
@@ -605,11 +605,24 @@ static void start_data_dma(struct pxa3xx_nand_info *info)
 {}
 #endif
 
+static irqreturn_t pxa3xx_nand_irq_thread(int irq, void *data)
+{
+	struct pxa3xx_nand_info *info = data;
+
+	handle_data_pio(info);
+
+	info->state = STATE_CMD_DONE;
+	nand_writel(info, NDSR, NDSR_WRDREQ | NDSR_RDDREQ);
+
+	return IRQ_HANDLED;
+}
+
 static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 {
 	struct pxa3xx_nand_info *info = devid;
 	unsigned int status, is_completed = 0, is_ready = 0;
 	unsigned int ready, cmd_done;
+	irqreturn_t ret = IRQ_HANDLED;
 
 	if (info->cs == 0) {
 		ready           = NDSR_FLASH_RDY;
@@ -651,7 +664,8 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 		} else {
 			info->state = (status & NDSR_RDDREQ) ?
 				      STATE_PIO_READING : STATE_PIO_WRITING;
-			handle_data_pio(info);
+			ret = IRQ_WAKE_THREAD;
+			goto NORMAL_IRQ_EXIT;
 		}
 	}
 	if (status & cmd_done) {
@@ -692,7 +706,7 @@ static irqreturn_t pxa3xx_nand_irq(int irq, void *devid)
 	if (is_ready)
 		complete(&info->dev_ready);
 NORMAL_IRQ_EXIT:
-	return IRQ_HANDLED;
+	return ret;
 }
 
 static inline int is_buf_blank(uint8_t *buf, size_t len)
@@ -1708,7 +1722,9 @@ static int alloc_nand_resource(struct platform_device *pdev)
 	/* initialize all interrupts to be disabled */
 	disable_int(info, NDSR_MASK);
 
-	ret = request_irq(irq, pxa3xx_nand_irq, 0, pdev->name, info);
+	ret = request_threaded_irq(irq, pxa3xx_nand_irq,
+				   pxa3xx_nand_irq_thread, IRQF_ONESHOT,
+				   pdev->name, info);
 	if (ret < 0) {
 		dev_err(&pdev->dev, "failed to request IRQ\n");
 		goto fail_free_buf;



More information about the linux-mtd-cvs mailing list