OSDN Git Service

ARM: mvebu: disable I/O coherency on non-SMP situations on Armada 370/375/38x/XP
[android-x86/kernel.git] / arch / arm / mach-mvebu / coherency.c
index 044b511..c31f4c0 100644 (file)
@@ -361,25 +361,41 @@ static int coherency_type(void)
 {
        struct device_node *np;
        const struct of_device_id *match;
+       int type;
 
-       np = of_find_matching_node_and_match(NULL, of_coherency_table, &match);
-       if (np) {
-               int type = (int) match->data;
+       /*
+        * The coherency fabric is needed:
+        * - For coherency between processors on Armada XP, so only
+        *   when SMP is enabled.
+        * - For coherency between the processor and I/O devices, but
+        *   this coherency requires many pre-requisites (write
+        *   allocate cache policy, shareable pages, SMP bit set) that
+        *   are only meant in SMP situations.
+        *
+        * Note that this means that on Armada 370, there is currently
+        * no way to use hardware I/O coherency, because even when
+        * CONFIG_SMP is enabled, is_smp() returns false due to the
+        * Armada 370 being a single-core processor. To lift this
+        * limitation, we would have to find a way to make the cache
+        * policy set to write-allocate (on all Armada SoCs), and to
+        * set the shareable attribute in page tables (on all Armada
+        * SoCs except the Armada 370). Unfortunately, such decisions
+        * are taken very early in the kernel boot process, at a point
+        * where we don't know yet on which SoC we are running.
 
-               /* Armada 370/XP coherency works in both UP and SMP */
-               if (type == COHERENCY_FABRIC_TYPE_ARMADA_370_XP)
-                       return type;
+        */
+       if (!is_smp())
+               return COHERENCY_FABRIC_TYPE_NONE;
 
-               /* Armada 375 coherency works only on SMP */
-               else if (type == COHERENCY_FABRIC_TYPE_ARMADA_375 && is_smp())
-                       return type;
+       np = of_find_matching_node_and_match(NULL, of_coherency_table, &match);
+       if (!np)
+               return COHERENCY_FABRIC_TYPE_NONE;
 
-               /* Armada 380 coherency works only on SMP */
-               else if (type == COHERENCY_FABRIC_TYPE_ARMADA_380 && is_smp())
-                       return type;
-       }
+       type = (int) match->data;
+
+       of_node_put(np);
 
-       return COHERENCY_FABRIC_TYPE_NONE;
+       return type;
 }
 
 int coherency_available(void)