mtd: r852: Few fixes for problems that occur when card is rapidly inserted/removed.

Linux-MTD Mailing List linux-mtd at lists.infradead.org
Mon Mar 8 21:59:02 EST 2010


Gitweb:     http://git.infradead.org/?p=mtd-2.6.git;a=commit;h=fb45d3232c641bfee5000c8a81e2005903734702
Commit:     fb45d3232c641bfee5000c8a81e2005903734702
Parent:     d4080cb32ee3d2ed18aa69ffde6010524bd686cd
Author:     Maxim Levitsky <maximlevitsky at gmail.com>
AuthorDate: Sat Feb 27 02:04:02 2010 +0200
Committer:  David Woodhouse <David.Woodhouse at intel.com>
CommitDate: Mon Mar 8 18:31:18 2010 -0800

    mtd: r852: Few fixes for problems that occur when card is rapidly inserted/removed.
    
    First don't enable card detection logic to early. Second be very careful with
    DMA engine, to be sure it doesn't write to kernel memory driver doesn't own.
    
    Signed-off-by: Maxim Levitsky <maximlevitsky at gmail.com>
    Signed-off-by: David Woodhouse <David.Woodhouse at intel.com>
---
 drivers/mtd/nand/r852.c |   21 +++++++++++++++++----
 1 files changed, 17 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c
index 218a42d..cb27116 100644
--- a/drivers/mtd/nand/r852.c
+++ b/drivers/mtd/nand/r852.c
@@ -96,14 +96,21 @@ static void r852_dma_enable(struct r852_device *dev)
 	if (dev->dma_dir)
 		dma_reg |= R852_DMA_READ;
 
-	if (dev->dma_state == DMA_INTERNAL)
+	if (dev->dma_state == DMA_INTERNAL) {
 		dma_reg |= R852_DMA_INTERNAL;
-	else {
+		/* Precaution to make sure HW doesn't write */
+			/* to random kernel memory */
+		r852_write_reg_dword(dev, R852_DMA_ADDR,
+			cpu_to_le32(dev->phys_bounce_buffer));
+	} else {
 		dma_reg |= R852_DMA_MEMORY;
 		r852_write_reg_dword(dev, R852_DMA_ADDR,
 			cpu_to_le32(dev->phys_dma_addr));
 	}
 
+	/* Precaution: make sure write reached the device */
+	r852_read_reg_dword(dev, R852_DMA_ADDR);
+
 	r852_write_reg_dword(dev, R852_DMA_SETTINGS, dma_reg);
 
 	/* Set dma irq */
@@ -129,6 +136,11 @@ static void r852_dma_done(struct r852_device *dev, int error)
 	r852_write_reg_dword(dev, R852_DMA_SETTINGS, 0);
 	r852_write_reg_dword(dev, R852_DMA_IRQ_ENABLE, 0);
 
+	/* Precaution to make sure HW doesn't write to random kernel memory */
+	r852_write_reg_dword(dev, R852_DMA_ADDR,
+		cpu_to_le32(dev->phys_bounce_buffer));
+	r852_read_reg_dword(dev, R852_DMA_ADDR);
+
 	dev->dma_error = error;
 	dev->dma_stage = 0;
 
@@ -579,6 +591,7 @@ void r852_card_update_present(struct r852_device *dev)
 void r852_update_card_detect(struct r852_device *dev)
 {
 	int card_detect_reg = r852_read_reg(dev, R852_CARD_IRQ_ENABLE);
+	dev->card_unstable = 0;
 
 	card_detect_reg &= ~(R852_CARD_IRQ_REMOVE | R852_CARD_IRQ_INSERT);
 	card_detect_reg |= R852_CARD_IRQ_GENABLE;
@@ -690,10 +703,10 @@ void r852_card_detect_work(struct work_struct *work)
 	struct r852_device *dev =
 		container_of(work, struct r852_device, card_detect_work.work);
 
-	r852_update_card_detect(dev);
+	r852_card_update_present(dev);
 	dev->card_unstable = 0;
 
-	/* false alarm */
+	/* False alarm */
 	if (dev->card_detected == dev->card_registred)
 		goto exit;
 



More information about the linux-mtd-cvs mailing list