Merge tag 'amd-drm-fixes-5.9-2020-08-20' of git://people.freedesktop.org/~agd5f/linux...
[linux-2.6-microblaze.git] / mm / memremap.c
index 09b5b7a..03e38b7 100644 (file)
@@ -7,6 +7,7 @@
 #include <linux/mm.h>
 #include <linux/pfn_t.h>
 #include <linux/swap.h>
+#include <linux/mmzone.h>
 #include <linux/swapops.h>
 #include <linux/types.h>
 #include <linux/wait_bit.h>
 
 static DEFINE_XARRAY(pgmap_array);
 
+/*
+ * The memremap() and memremap_pages() interfaces are alternately used
+ * to map persistent memory namespaces. These interfaces place different
+ * constraints on the alignment and size of the mapping (namespace).
+ * memremap() can map individual PAGE_SIZE pages. memremap_pages() can
+ * only map subsections (2MB), and at least one architecture (PowerPC)
+ * the minimum mapping granularity of memremap_pages() is 16MB.
+ *
+ * The role of memremap_compat_align() is to communicate the minimum
+ * arch supported alignment of a namespace such that it can freely
+ * switch modes without violating the arch constraint. Namely, do not
+ * allow a namespace to be PAGE_SIZE aligned since that namespace may be
+ * reconfigured into a mode that requires SUBSECTION_SIZE alignment.
+ */
+#ifndef CONFIG_ARCH_HAS_MEMREMAP_COMPAT_ALIGN
+unsigned long memremap_compat_align(void)
+{
+       return SUBSECTION_SIZE;
+}
+EXPORT_SYMBOL_GPL(memremap_compat_align);
+#endif
+
 #ifdef CONFIG_DEV_PAGEMAP_OPS
 DEFINE_STATIC_KEY_FALSE(devmap_managed_key);
 EXPORT_SYMBOL(devmap_managed_key);
@@ -161,13 +184,13 @@ void *memremap_pages(struct dev_pagemap *pgmap, int nid)
 {
        struct resource *res = &pgmap->res;
        struct dev_pagemap *conflict_pgmap;
-       struct mhp_restrictions restrictions = {
+       struct mhp_params params = {
                /*
                 * We do not want any optional features only our own memmap
                 */
                .altmap = pgmap_altmap(pgmap),
+               .pgprot = PAGE_KERNEL,
        };
-       pgprot_t pgprot = PAGE_KERNEL;
        int error, is_ram;
        bool need_devmap_managed = true;
 
@@ -181,6 +204,10 @@ void *memremap_pages(struct dev_pagemap *pgmap, int nid)
                        WARN(1, "Missing migrate_to_ram method\n");
                        return ERR_PTR(-EINVAL);
                }
+               if (!pgmap->owner) {
+                       WARN(1, "Missing owner\n");
+                       return ERR_PTR(-EINVAL);
+               }
                break;
        case MEMORY_DEVICE_FS_DAX:
                if (!IS_ENABLED(CONFIG_ZONE_DEVICE) ||
@@ -190,7 +217,10 @@ void *memremap_pages(struct dev_pagemap *pgmap, int nid)
                }
                break;
        case MEMORY_DEVICE_DEVDAX:
+               need_devmap_managed = false;
+               break;
        case MEMORY_DEVICE_PCI_P2PDMA:
+               params.pgprot = pgprot_noncached(params.pgprot);
                need_devmap_managed = false;
                break;
        default:
@@ -255,8 +285,8 @@ void *memremap_pages(struct dev_pagemap *pgmap, int nid)
        if (nid < 0)
                nid = numa_mem_id();
 
-       error = track_pfn_remap(NULL, &pgprot, PHYS_PFN(res->start), 0,
-                       resource_size(res));
+       error = track_pfn_remap(NULL, &params.pgprot, PHYS_PFN(res->start),
+                               0, resource_size(res));
        if (error)
                goto err_pfn_remap;
 
@@ -275,7 +305,7 @@ void *memremap_pages(struct dev_pagemap *pgmap, int nid)
         */
        if (pgmap->type == MEMORY_DEVICE_PRIVATE) {
                error = add_pages(nid, PHYS_PFN(res->start),
-                               PHYS_PFN(resource_size(res)), &restrictions);
+                               PHYS_PFN(resource_size(res)), &params);
        } else {
                error = kasan_add_zero_shadow(__va(res->start), resource_size(res));
                if (error) {
@@ -284,7 +314,7 @@ void *memremap_pages(struct dev_pagemap *pgmap, int nid)
                }
 
                error = arch_add_memory(nid, res->start, resource_size(res),
-                                       &restrictions);
+                                       &params);
        }
 
        if (!error) {
@@ -292,7 +322,7 @@ void *memremap_pages(struct dev_pagemap *pgmap, int nid)
 
                zone = &NODE_DATA(nid)->node_zones[ZONE_DEVICE];
                move_pfn_range_to_zone(zone, PHYS_PFN(res->start),
-                               PHYS_PFN(resource_size(res)), restrictions.altmap);
+                               PHYS_PFN(resource_size(res)), params.altmap);
        }
 
        mem_hotplug_done();