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>
This commit is contained in:
Maxim Levitsky 2010-02-27 02:04:02 +02:00 committed by David Woodhouse
parent d4080cb32e
commit fb45d3232c

View File

@ -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;