diff options
author | Maxim Levitsky <maximlevitsky@gmail.com> | 2010-02-26 19:04:02 -0500 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2010-03-08 21:31:18 -0500 |
commit | fb45d3232c641bfee5000c8a81e2005903734702 (patch) | |
tree | 726df94625464228e8aad7ad208552f6aa2f7672 /drivers | |
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')
-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 218a42dadff1..cb271167b4a5 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) | |||
96 | if (dev->dma_dir) | 96 | if (dev->dma_dir) |
97 | dma_reg |= R852_DMA_READ; | 97 | dma_reg |= R852_DMA_READ; |
98 | 98 | ||
99 | if (dev->dma_state == DMA_INTERNAL) | 99 | if (dev->dma_state == DMA_INTERNAL) { |
100 | dma_reg |= R852_DMA_INTERNAL; | 100 | dma_reg |= R852_DMA_INTERNAL; |
101 | else { | 101 | /* Precaution to make sure HW doesn't write */ |
102 | /* to random kernel memory */ | ||
103 | r852_write_reg_dword(dev, R852_DMA_ADDR, | ||
104 | cpu_to_le32(dev->phys_bounce_buffer)); | ||
105 | } else { | ||
102 | dma_reg |= R852_DMA_MEMORY; | 106 | dma_reg |= R852_DMA_MEMORY; |
103 | r852_write_reg_dword(dev, R852_DMA_ADDR, | 107 | r852_write_reg_dword(dev, R852_DMA_ADDR, |
104 | cpu_to_le32(dev->phys_dma_addr)); | 108 | cpu_to_le32(dev->phys_dma_addr)); |
105 | } | 109 | } |
106 | 110 | ||
111 | /* Precaution: make sure write reached the device */ | ||
112 | r852_read_reg_dword(dev, R852_DMA_ADDR); | ||
113 | |||
107 | r852_write_reg_dword(dev, R852_DMA_SETTINGS, dma_reg); | 114 | r852_write_reg_dword(dev, R852_DMA_SETTINGS, dma_reg); |
108 | 115 | ||
109 | /* Set dma irq */ | 116 | /* Set dma irq */ |
@@ -129,6 +136,11 @@ static void r852_dma_done(struct r852_device *dev, int error) | |||
129 | r852_write_reg_dword(dev, R852_DMA_SETTINGS, 0); | 136 | r852_write_reg_dword(dev, R852_DMA_SETTINGS, 0); |
130 | r852_write_reg_dword(dev, R852_DMA_IRQ_ENABLE, 0); | 137 | r852_write_reg_dword(dev, R852_DMA_IRQ_ENABLE, 0); |
131 | 138 | ||
139 | /* Precaution to make sure HW doesn't write to random kernel memory */ | ||
140 | r852_write_reg_dword(dev, R852_DMA_ADDR, | ||
141 | cpu_to_le32(dev->phys_bounce_buffer)); | ||
142 | r852_read_reg_dword(dev, R852_DMA_ADDR); | ||
143 | |||
132 | dev->dma_error = error; | 144 | dev->dma_error = error; |
133 | dev->dma_stage = 0; | 145 | dev->dma_stage = 0; |
134 | 146 | ||
@@ -579,6 +591,7 @@ void r852_card_update_present(struct r852_device *dev) | |||
579 | void r852_update_card_detect(struct r852_device *dev) | 591 | void r852_update_card_detect(struct r852_device *dev) |
580 | { | 592 | { |
581 | int card_detect_reg = r852_read_reg(dev, R852_CARD_IRQ_ENABLE); | 593 | int card_detect_reg = r852_read_reg(dev, R852_CARD_IRQ_ENABLE); |
594 | dev->card_unstable = 0; | ||
582 | 595 | ||
583 | card_detect_reg &= ~(R852_CARD_IRQ_REMOVE | R852_CARD_IRQ_INSERT); | 596 | card_detect_reg &= ~(R852_CARD_IRQ_REMOVE | R852_CARD_IRQ_INSERT); |
584 | card_detect_reg |= R852_CARD_IRQ_GENABLE; | 597 | card_detect_reg |= R852_CARD_IRQ_GENABLE; |
@@ -690,10 +703,10 @@ void r852_card_detect_work(struct work_struct *work) | |||
690 | struct r852_device *dev = | 703 | struct r852_device *dev = |
691 | container_of(work, struct r852_device, card_detect_work.work); | 704 | container_of(work, struct r852_device, card_detect_work.work); |
692 | 705 | ||
693 | r852_update_card_detect(dev); | 706 | r852_card_update_present(dev); |
694 | dev->card_unstable = 0; | 707 | dev->card_unstable = 0; |
695 | 708 | ||
696 | /* false alarm */ | 709 | /* False alarm */ |
697 | if (dev->card_detected == dev->card_registred) | 710 | if (dev->card_detected == dev->card_registred) |
698 | goto exit; | 711 | goto exit; |
699 | 712 | ||