powerpc: use mm zones more sensibly
authorChristoph Hellwig <hch@lst.de>
Sun, 16 Dec 2018 16:53:49 +0000 (17:53 +0100)
committerMichael Ellerman <mpe@ellerman.id.au>
Thu, 20 Dec 2018 11:21:20 +0000 (22:21 +1100)
Powerpc has somewhat odd usage where ZONE_DMA is used for all memory on
common 64-bit configfs, and ZONE_DMA32 is used for 31-bit schemes.

Move to a scheme closer to what other architectures use (and I dare to
say the intent of the system):

 - ZONE_DMA: optionally for memory < 31-bit (64-bit embedded only)
 - ZONE_NORMAL: everything addressable by the kernel
 - ZONE_HIGHMEM: memory > 32-bit for 32-bit kernels

Also provide information on how ZONE_DMA is used by defining
ARCH_ZONE_DMA_BITS.

Contains various fixes from Benjamin Herrenschmidt.

Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/Kconfig
arch/powerpc/include/asm/page.h
arch/powerpc/include/asm/pgtable.h
arch/powerpc/kernel/dma-swiotlb.c
arch/powerpc/kernel/dma.c
arch/powerpc/mm/mem.c
arch/powerpc/platforms/85xx/corenet_generic.c
arch/powerpc/platforms/85xx/qemu_e500.c
include/linux/mmzone.h

index c446e377acd3f7a96ad989370db3255109bfaa83..6d6e1ffdafbaef29b6e228a4e4399009b58dcb92 100644 (file)
@@ -375,9 +375,9 @@ config PPC_ADV_DEBUG_DAC_RANGE
        depends on PPC_ADV_DEBUG_REGS && 44x
        default y
 
-config ZONE_DMA32
+config ZONE_DMA
        bool
-       default y if PPC64
+       default y if PPC_BOOK3E_64
 
 config PGTABLE_LEVELS
        int
@@ -870,10 +870,6 @@ config ISA
          have an IBM RS/6000 or pSeries machine, say Y.  If you have an
          embedded board, consult your board documentation.
 
-config ZONE_DMA
-       bool
-       default y
-
 config GENERIC_ISA_DMA
        bool
        depends on ISA_DMA_API
index a7624a3b14354f0e994276c1b6b3e2f22d8aa982..5c5ea24134133bcbb84f78a33ae1bfc304aedf8e 100644 (file)
@@ -340,4 +340,6 @@ struct vm_area_struct;
 #endif /* __ASSEMBLY__ */
 #include <asm/slice.h>
 
+#define ARCH_ZONE_DMA_BITS 31
+
 #endif /* _ASM_POWERPC_PAGE_H */
index f2bfaf6746743e4dcf2b484a64a243753d44fcd3..dad1d27e196d92f0e1a5ca5a2194e91af70197ed 100644 (file)
@@ -66,7 +66,6 @@ extern unsigned long empty_zero_page[];
 
 extern pgd_t swapper_pg_dir[];
 
-void limit_zone_pfn(enum zone_type zone, unsigned long max_pfn);
 int dma_pfn_limit_to_zone(u64 pfn_limit);
 extern void paging_init(void);
 
index 5fc335f4d9cd0f561dfa3a947e2502e7de88e658..678811abccfcd46fcfb95a93e8134609a1c35de3 100644 (file)
@@ -108,12 +108,8 @@ int __init swiotlb_setup_bus_notifier(void)
 
 void __init swiotlb_detect_4g(void)
 {
-       if ((memblock_end_of_DRAM() - 1) > 0xffffffff) {
+       if ((memblock_end_of_DRAM() - 1) > 0xffffffff)
                ppc_swiotlb_enable = 1;
-#ifdef CONFIG_ZONE_DMA32
-               limit_zone_pfn(ZONE_DMA32, (1ULL << 32) >> PAGE_SHIFT);
-#endif
-       }
 }
 
 static int __init check_swiotlb_enabled(void)
index e51ff967808c2ee1e1566ae1acbc0a6302af3925..b1903ebb2e9cf3f46bc0d5bb8f278f8791b43e74 100644 (file)
@@ -50,7 +50,8 @@ static int dma_nommu_dma_supported(struct device *dev, u64 mask)
                return 1;
 
 #ifdef CONFIG_FSL_SOC
-       /* Freescale gets another chance via ZONE_DMA/ZONE_DMA32, however
+       /*
+        * Freescale gets another chance via ZONE_DMA, however
         * that will have to be refined if/when they support iommus
         */
        return 1;
@@ -88,13 +89,10 @@ void *__dma_nommu_alloc_coherent(struct device *dev, size_t size,
        }
 
        switch (zone) {
+#ifdef CONFIG_ZONE_DMA
        case ZONE_DMA:
                flag |= GFP_DMA;
                break;
-#ifdef CONFIG_ZONE_DMA32
-       case ZONE_DMA32:
-               flag |= GFP_DMA32;
-               break;
 #endif
        };
 #endif /* CONFIG_FSL_SOC */
index 065c37d54b4973550b0a567ed564f776012568cf..20394e52fe272836e7e21e3e495cb50206c02c97 100644 (file)
@@ -246,35 +246,19 @@ static int __init mark_nonram_nosave(void)
 }
 #endif
 
-static bool zone_limits_final;
-
 /*
- * The memory zones past TOP_ZONE are managed by generic mm code.
- * These should be set to zero since that's what every other
- * architecture does.
+ * Zones usage:
+ *
+ * We setup ZONE_DMA to be 31-bits on all platforms and ZONE_NORMAL to be
+ * everything else. GFP_DMA32 page allocations automatically fall back to
+ * ZONE_DMA.
+ *
+ * By using 31-bit unconditionally, we can exploit ARCH_ZONE_DMA_BITS to
+ * inform the generic DMA mapping code.  32-bit only devices (if not handled
+ * by an IOMMU anyway) will take a first dip into ZONE_NORMAL and get
+ * otherwise served by ZONE_DMA.
  */
-static unsigned long max_zone_pfns[MAX_NR_ZONES] = {
-       [0            ... TOP_ZONE        ] = ~0UL,
-       [TOP_ZONE + 1 ... MAX_NR_ZONES - 1] = 0
-};
-
-/*
- * Restrict the specified zone and all more restrictive zones
- * to be below the specified pfn.  May not be called after
- * paging_init().
- */
-void __init limit_zone_pfn(enum zone_type zone, unsigned long pfn_limit)
-{
-       int i;
-
-       if (WARN_ON(zone_limits_final))
-               return;
-
-       for (i = zone; i >= 0; i--) {
-               if (max_zone_pfns[i] > pfn_limit)
-                       max_zone_pfns[i] = pfn_limit;
-       }
-}
+static unsigned long max_zone_pfns[MAX_NR_ZONES];
 
 /*
  * Find the least restrictive zone that is entirely below the
@@ -324,11 +308,14 @@ void __init paging_init(void)
        printk(KERN_DEBUG "Memory hole size: %ldMB\n",
               (long int)((top_of_ram - total_ram) >> 20));
 
+#ifdef CONFIG_ZONE_DMA
+       max_zone_pfns[ZONE_DMA] = min(max_low_pfn, 0x7fffffffUL >> PAGE_SHIFT);
+#endif
+       max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
 #ifdef CONFIG_HIGHMEM
-       limit_zone_pfn(ZONE_NORMAL, lowmem_end_addr >> PAGE_SHIFT);
+       max_zone_pfns[ZONE_HIGHMEM] = max_pfn;
 #endif
-       limit_zone_pfn(TOP_ZONE, top_of_ram >> PAGE_SHIFT);
-       zone_limits_final = true;
+
        free_area_init_nodes(max_zone_pfns);
 
        mark_nonram_nosave();
index ac191a7a133701cc2faf289edd59402c5cc8700b..b0dac307bebf9cb96d30bfd38c84a38113498548 100644 (file)
@@ -68,16 +68,6 @@ void __init corenet_gen_setup_arch(void)
 
        swiotlb_detect_4g();
 
-#if defined(CONFIG_FSL_PCI) && defined(CONFIG_ZONE_DMA32)
-       /*
-        * Inbound windows don't cover the full lower 4 GiB
-        * due to conflicts with PCICSRBAR and outbound windows,
-        * so limit the DMA32 zone to 2 GiB, to allow consistent
-        * allocations to succeed.
-        */
-       limit_zone_pfn(ZONE_DMA32, 1UL << (31 - PAGE_SHIFT));
-#endif
-
        pr_info("%s board\n", ppc_md.name);
 
        mpc85xx_qe_init();
index b63a8548366f8d6e3218624784e7875edad01ee5..27631c607f3d9a48308593ecfd4fceec873e57b6 100644 (file)
@@ -45,15 +45,6 @@ static void __init qemu_e500_setup_arch(void)
 
        fsl_pci_assign_primary();
        swiotlb_detect_4g();
-#if defined(CONFIG_FSL_PCI) && defined(CONFIG_ZONE_DMA32)
-       /*
-        * Inbound windows don't cover the full lower 4 GiB
-        * due to conflicts with PCICSRBAR and outbound windows,
-        * so limit the DMA32 zone to 2 GiB, to allow consistent
-        * allocations to succeed.
-        */
-       limit_zone_pfn(ZONE_DMA32, 1UL << (31 - PAGE_SHIFT));
-#endif
        mpc85xx_smp_init();
 }
 
index 847705a6d0ec2dba2a82ca87bba54c797bb0b956..e2d01ccd071deb35ab6876d1635e7c19eb964ebe 100644 (file)
@@ -314,7 +314,7 @@ enum zone_type {
         * Architecture         Limit
         * ---------------------------
         * parisc, ia64, sparc  <4G
-        * s390                 <2G
+        * s390, powerpc        <2G
         * arm                  Various
         * alpha                Unlimited or 0-16MB.
         *