diff options
author | Maxim Levitsky <maximlevitsky@gmail.com> | 2010-06-02 09:01:46 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2010-06-02 09:53:40 -0400 |
commit | 9489be8ca234c07666e88a4472e4d5f2a2425aa5 (patch) | |
tree | c5bbb7a4b0926d830c6a5a275496284acd9efc3b /drivers/mtd | |
parent | cc1fed00c9ba84f38717a6cab84409cd48f340e3 (diff) |
mtd/r852: Fixes in case of DMA timeout
* Don't call complete on dma completion
* do a INIT_COMPLETE before using it each time
* Report DMA read error via ecc 'correct'
I finally managed to make my system do suspend to ram propertly, and I see that
if card was inserted during suspend (while system was off), I get dma timeouts
on resume. Simple card reinsert solves the issue.
This patch solves a crash that would happen otherwise
Signed-off-by: Maxim Levitsky <maximlevitsky@gmail.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd')
-rw-r--r-- | drivers/mtd/nand/r852.c | 14 |
1 files changed, 11 insertions, 3 deletions
diff --git a/drivers/mtd/nand/r852.c b/drivers/mtd/nand/r852.c index 20a654a94d30..3f219e61df7d 100644 --- a/drivers/mtd/nand/r852.c +++ b/drivers/mtd/nand/r852.c | |||
@@ -150,7 +150,6 @@ static void r852_dma_done(struct r852_device *dev, int error) | |||
150 | if (dev->phys_dma_addr && dev->phys_dma_addr != dev->phys_bounce_buffer) | 150 | if (dev->phys_dma_addr && dev->phys_dma_addr != dev->phys_bounce_buffer) |
151 | pci_unmap_single(dev->pci_dev, dev->phys_dma_addr, R852_DMA_LEN, | 151 | pci_unmap_single(dev->pci_dev, dev->phys_dma_addr, R852_DMA_LEN, |
152 | dev->dma_dir ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); | 152 | dev->dma_dir ? PCI_DMA_FROMDEVICE : PCI_DMA_TODEVICE); |
153 | complete(&dev->dma_done); | ||
154 | } | 153 | } |
155 | 154 | ||
156 | /* | 155 | /* |
@@ -182,6 +181,7 @@ static void r852_do_dma(struct r852_device *dev, uint8_t *buf, int do_read) | |||
182 | /* Set dma direction */ | 181 | /* Set dma direction */ |
183 | dev->dma_dir = do_read; | 182 | dev->dma_dir = do_read; |
184 | dev->dma_stage = 1; | 183 | dev->dma_stage = 1; |
184 | INIT_COMPLETION(dev->dma_done); | ||
185 | 185 | ||
186 | dbg_verbose("doing dma %s ", do_read ? "read" : "write"); | 186 | dbg_verbose("doing dma %s ", do_read ? "read" : "write"); |
187 | 187 | ||
@@ -494,6 +494,11 @@ int r852_ecc_correct(struct mtd_info *mtd, uint8_t *dat, | |||
494 | if (dev->card_unstable) | 494 | if (dev->card_unstable) |
495 | return 0; | 495 | return 0; |
496 | 496 | ||
497 | if (dev->dma_error) { | ||
498 | dev->dma_error = 0; | ||
499 | return -1; | ||
500 | } | ||
501 | |||
497 | r852_write_reg(dev, R852_CTL, dev->ctlreg | R852_CTL_ECC_ACCESS); | 502 | r852_write_reg(dev, R852_CTL, dev->ctlreg | R852_CTL_ECC_ACCESS); |
498 | ecc_reg = r852_read_reg_dword(dev, R852_DATALINE); | 503 | ecc_reg = r852_read_reg_dword(dev, R852_DATALINE); |
499 | r852_write_reg(dev, R852_CTL, dev->ctlreg); | 504 | r852_write_reg(dev, R852_CTL, dev->ctlreg); |
@@ -796,6 +801,7 @@ static irqreturn_t r852_irq(int irq, void *data) | |||
796 | if (dma_status & R852_DMA_IRQ_ERROR) { | 801 | if (dma_status & R852_DMA_IRQ_ERROR) { |
797 | dbg("recieved dma error IRQ"); | 802 | dbg("recieved dma error IRQ"); |
798 | r852_dma_done(dev, -EIO); | 803 | r852_dma_done(dev, -EIO); |
804 | complete(&dev->dma_done); | ||
799 | goto out; | 805 | goto out; |
800 | } | 806 | } |
801 | 807 | ||
@@ -825,8 +831,10 @@ static irqreturn_t r852_irq(int irq, void *data) | |||
825 | r852_dma_enable(dev); | 831 | r852_dma_enable(dev); |
826 | 832 | ||
827 | /* Operation done */ | 833 | /* Operation done */ |
828 | if (dev->dma_stage == 3) | 834 | if (dev->dma_stage == 3) { |
829 | r852_dma_done(dev, 0); | 835 | r852_dma_done(dev, 0); |
836 | complete(&dev->dma_done); | ||
837 | } | ||
830 | goto out; | 838 | goto out; |
831 | } | 839 | } |
832 | 840 | ||
@@ -1082,7 +1090,7 @@ int r852_resume(struct device *device) | |||
1082 | dev->card_detected ? "added" : "removed"); | 1090 | dev->card_detected ? "added" : "removed"); |
1083 | 1091 | ||
1084 | queue_delayed_work(dev->card_workqueue, | 1092 | queue_delayed_work(dev->card_workqueue, |
1085 | &dev->card_detect_work, 1000); | 1093 | &dev->card_detect_work, msecs_to_jiffies(1000)); |
1086 | return 0; | 1094 | return 0; |
1087 | } | 1095 | } |
1088 | 1096 | ||