diff options
author | Maxim Levitsky <maximlevitsky@gmail.com> | 2010-02-27 02:04:02 +0200 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2010-03-08 18:31:18 -0800 |
commit | fb45d3232c641bfee5000c8a81e2005903734702 (patch) | |
tree | 726df94625464228e8aad7ad208552f6aa2f7672 /drivers/mtd/nand | |
parent | d4080cb32ee3d2ed18aa69ffde6010524bd686cd (diff) |
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@gmail.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/nand')
-rw-r--r-- | 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 218a42dadff..cb271167b4a 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; |