Blackfin: flush caches on SMP when one core calls another via IPI
authorYi Li <yi.li@analog.com>
Fri, 4 Dec 2009 06:56:21 +0000 (06:56 +0000)
committerMike Frysinger <vapier@gentoo.org>
Tue, 9 Mar 2010 05:30:45 +0000 (00:30 -0500)
Sometimes a SMP system will randomly panic at boot.  This is due to caches
being out of sync when one core tries to signal the other.  So when one
core calls another via IPI, flush the data caches.

Signed-off-by: Yi Li <yi.li@analog.com>
Signed-off-by: Mike Frysinger <vapier@gentoo.org>
arch/blackfin/mach-common/smp.c

index 369e687582b7da4a86a3fab7a537a6740839ad1f..eddb720c718e1130e7f26a02e98840de9740f84b 100644 (file)
@@ -122,9 +122,17 @@ static void ipi_call_function(unsigned int cpu, struct ipi_message *msg)
        wait = msg->call_struct.wait;
        cpu_clear(cpu, msg->call_struct.pending);
        func(info);
-       if (wait)
+       if (wait) {
+#ifdef __ARCH_SYNC_CORE_DCACHE
+               /*
+                * 'wait' usually means synchronization between CPUs.
+                * Invalidate D cache in case shared data was changed
+                * by func() to ensure cache coherence.
+                */
+               resync_core_dcache();
+#endif
                cpu_clear(cpu, msg->call_struct.waitmask);
-       else
+       else
                kfree(msg);
 }
 
@@ -219,6 +227,13 @@ int smp_call_function(void (*func)(void *info), void *info, int wait)
                        blackfin_dcache_invalidate_range(
                                (unsigned long)(&msg->call_struct.waitmask),
                                (unsigned long)(&msg->call_struct.waitmask));
+#ifdef __ARCH_SYNC_CORE_DCACHE
+               /*
+                * Invalidate D cache in case shared data was changed by
+                * other processors to ensure cache coherence.
+                */
+               resync_core_dcache();
+#endif
                kfree(msg);
        }
        return 0;
@@ -261,6 +276,13 @@ int smp_call_function_single(int cpuid, void (*func) (void *info), void *info,
                        blackfin_dcache_invalidate_range(
                                (unsigned long)(&msg->call_struct.waitmask),
                                (unsigned long)(&msg->call_struct.waitmask));
+#ifdef __ARCH_SYNC_CORE_DCACHE
+               /*
+                * Invalidate D cache in case shared data was changed by
+                * other processors to ensure cache coherence.
+                */
+               resync_core_dcache();
+#endif
                kfree(msg);
        }
        return 0;