]> bbs.cooldavid.org Git - net-next-2.6.git/commitdiff
Blackfin: fix DMA/cache bug when resuming from suspend to RAM
authorMichael Hennerich <michael.hennerich@analog.com>
Wed, 16 Jun 2010 09:12:10 +0000 (09:12 +0000)
committerMike Frysinger <vapier@gentoo.org>
Fri, 6 Aug 2010 16:55:50 +0000 (12:55 -0400)
The dma_memcpy() function takes care of flushing different caches for us.
Normally this is what we want, but when resuming from mem, we don't yet
have caches enabled.  If these functions happen to be placed into L1 mem
(which is what we're trying to relocate), then things aren't going to
work.  So define a non-cache dma_memcpy() variant to utilize in situations
like this.

Signed-off-by: Michael Hennerich <michael.hennerich@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
arch/blackfin/include/asm/dma.h
arch/blackfin/kernel/bfin_dma_5xx.c
arch/blackfin/mach-common/pm.c

index 2c09b1d50ec99dbaae7afa7aad0d6caa623241ed..eedf3ca65ba22270e8405b47e914a891463917a0 100644 (file)
@@ -276,6 +276,7 @@ static inline void clear_dma_irqstat(unsigned int channel)
 }
 
 void *dma_memcpy(void *dest, const void *src, size_t count);
+void *dma_memcpy_nocache(void *dest, const void *src, size_t count);
 void *safe_dma_memcpy(void *dest, const void *src, size_t count);
 void blackfin_dma_early_init(void);
 void early_dma_memcpy(void *dest, const void *src, size_t count);
index 26403d1c9e6524949a421673b690d7d41bf0efa3..1e485dfdc9f2133a37d1d7d8b81af47b6bf53814 100644 (file)
@@ -450,7 +450,6 @@ void *dma_memcpy(void *pdst, const void *psrc, size_t size)
 {
        unsigned long dst = (unsigned long)pdst;
        unsigned long src = (unsigned long)psrc;
-       size_t bulk, rest;
 
        if (bfin_addr_dcacheable(src))
                blackfin_dcache_flush_range(src, src + size);
@@ -458,6 +457,22 @@ void *dma_memcpy(void *pdst, const void *psrc, size_t size)
        if (bfin_addr_dcacheable(dst))
                blackfin_dcache_invalidate_range(dst, dst + size);
 
+       return dma_memcpy_nocache(pdst, psrc, size);
+}
+EXPORT_SYMBOL(dma_memcpy);
+
+/**
+ *     dma_memcpy_nocache - DMA memcpy under mutex lock
+ *     - No cache flush/invalidate
+ *
+ * Do not check arguments before starting the DMA memcpy.  Break the transfer
+ * up into two pieces.  The first transfer is in multiples of 64k and the
+ * second transfer is the piece smaller than 64k.
+ */
+void *dma_memcpy_nocache(void *pdst, const void *psrc, size_t size)
+{
+       size_t bulk, rest;
+
        bulk = size & ~0xffff;
        rest = size - bulk;
        if (bulk)
@@ -465,7 +480,7 @@ void *dma_memcpy(void *pdst, const void *psrc, size_t size)
        _dma_memcpy(pdst + bulk, psrc + bulk, rest);
        return pdst;
 }
-EXPORT_SYMBOL(dma_memcpy);
+EXPORT_SYMBOL(dma_memcpy_nocache);
 
 /**
  *     safe_dma_memcpy - DMA memcpy w/argument checking
index ea7f95f6bb4c92b4cd779a3c158bce85c9694361..09c1fb410748436d096bc629805295acc086025f 100644 (file)
@@ -61,10 +61,11 @@ void bfin_pm_suspend_standby_enter(void)
 
 int bf53x_suspend_l1_mem(unsigned char *memptr)
 {
-       dma_memcpy(memptr, (const void *) L1_CODE_START, L1_CODE_LENGTH);
-       dma_memcpy(memptr + L1_CODE_LENGTH, (const void *) L1_DATA_A_START,
-                       L1_DATA_A_LENGTH);
-       dma_memcpy(memptr + L1_CODE_LENGTH + L1_DATA_A_LENGTH,
+       dma_memcpy_nocache(memptr, (const void *) L1_CODE_START,
+                       L1_CODE_LENGTH);
+       dma_memcpy_nocache(memptr + L1_CODE_LENGTH,
+                       (const void *) L1_DATA_A_START, L1_DATA_A_LENGTH);
+       dma_memcpy_nocache(memptr + L1_CODE_LENGTH + L1_DATA_A_LENGTH,
                        (const void *) L1_DATA_B_START, L1_DATA_B_LENGTH);
        memcpy(memptr + L1_CODE_LENGTH + L1_DATA_A_LENGTH +
                        L1_DATA_B_LENGTH, (const void *) L1_SCRATCH_START,
@@ -75,10 +76,10 @@ int bf53x_suspend_l1_mem(unsigned char *memptr)
 
 int bf53x_resume_l1_mem(unsigned char *memptr)
 {
-       dma_memcpy((void *) L1_CODE_START, memptr, L1_CODE_LENGTH);
-       dma_memcpy((void *) L1_DATA_A_START, memptr + L1_CODE_LENGTH,
+       dma_memcpy_nocache((void *) L1_CODE_START, memptr, L1_CODE_LENGTH);
+       dma_memcpy_nocache((void *) L1_DATA_A_START, memptr + L1_CODE_LENGTH,
                        L1_DATA_A_LENGTH);
-       dma_memcpy((void *) L1_DATA_B_START, memptr + L1_CODE_LENGTH +
+       dma_memcpy_nocache((void *) L1_DATA_B_START, memptr + L1_CODE_LENGTH +
                        L1_DATA_A_LENGTH, L1_DATA_B_LENGTH);
        memcpy((void *) L1_SCRATCH_START, memptr + L1_CODE_LENGTH +
                        L1_DATA_A_LENGTH + L1_DATA_B_LENGTH, L1_SCRATCH_LENGTH);
@@ -167,7 +168,7 @@ int bfin_pm_suspend_mem_enter(void)
        _disable_icplb();
        bf53x_suspend_l1_mem(memptr);
 
-       do_hibernate(wakeup | vr_wakeup);       /* Goodbye */
+       do_hibernate(wakeup | vr_wakeup);       /* See you later! */
 
        bf53x_resume_l1_mem(memptr);