Skip to content

Commit

Permalink
mtd: r852: Few fixes for problems that occur when card is rapidly ins…
Browse files Browse the repository at this point in the history
…erted/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>
  • Loading branch information
Maxim Levitsky authored and David Woodhouse committed Mar 9, 2010
1 parent d4080cb commit fb45d32
Showing 1 changed file with 17 additions and 4 deletions.
21 changes: 17 additions & 4 deletions drivers/mtd/nand/r852.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand All @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand Down

0 comments on commit fb45d32

Please sign in to comment.