Home Home > GIT Browse > SLE12-SP4
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Kirjanov <dkirjanov@suse.com>2019-07-31 15:15:48 +0300
committerDenis Kirjanov <dkirjanov@suse.com>2019-07-31 15:15:48 +0300
commit2f3e5bacedbc4ef6df7a52916dd6fa6ef48ccbe6 (patch)
treee25258fbb7b4565a2978a9f6b3c4d6fe537163d3
parent6eb755b2e7728e4e5902f74febf325096509b2aa (diff)
parenta43049c4d37dbce6c2f9b096c056a701e9ca4016 (diff)
Merge 'users/mhocko/SLE12-SP5/for-next' into SLE12-SP5
Pull dax and mm fixes from Michal Hocko Conflicts: blacklist.conf patches.arch/powerpc-tm-Fix-oops-on-sigreturn-on-systems-without-.patch series.conf
-rw-r--r--blacklist.conf1
-rw-r--r--config/ppc64le/default2
-rw-r--r--config/x86_64/default2
-rw-r--r--patches.drivers/0001-EDAC-i10nm-Add-Intel-additional-Ice-Lake-support.patch38
-rw-r--r--patches.drivers/0001-EDAC-i10nm-Check-ECC-enabling-status-per-channel.patch45
-rw-r--r--patches.drivers/0001-EDAC-skx-i10nm-Fix-source-ID-register-offset.patch82
-rw-r--r--patches.drivers/edac-i10nm-add-a-driver-for-intel-10nm-server-processors.patch2
-rw-r--r--patches.drivers/edac-skx-i10nm-make-skx_common-c-a-pure-library.patch2
-rw-r--r--patches.drivers/edac-skx_common-add-code-to-recognise-new-compound-error-code.patch2
-rw-r--r--patches.drivers/edac-skx_common-separate-common-code-out-from-skx_edac.patch2
-rw-r--r--patches.drivers/edac-skx_edac-delete-duplicated-code.patch2
-rw-r--r--patches.fixes/0001-device-dax-fix-memory-and-resource-leak-if-hotplug-f.patch106
-rw-r--r--patches.fixes/0001-x86-respect-memory-size-limiting-via-mem-parameter.patch35
-rw-r--r--patches.fixes/drivers-base-introduce-kill_device.patch3
-rw-r--r--patches.fixes/libnvdimm-bus-prevent-duplicate-device_unregister-calls.patch3
-rw-r--r--patches.suse/0001-acpi-nfit-device-dax-Identify-differentiated-memory-.patch302
-rw-r--r--patches.suse/0001-device-dax-Add-a-modalias-attribute-to-DAX-bus-devic.patch61
-rw-r--r--patches.suse/0001-device-dax-Add-a-target_node-attribute.patch76
-rw-r--r--patches.suse/0001-device-dax-Add-support-for-a-dax-override-driver.patch278
-rw-r--r--patches.suse/0001-device-dax-Add-sys-class-dax-backwards-compatibility.patch583
-rw-r--r--patches.suse/0001-device-dax-Auto-bind-device-after-successful-new_id.patch91
-rw-r--r--patches.suse/0001-device-dax-Hotplug-persistent-memory-for-use-like-no.patch259
-rw-r--r--patches.suse/0001-device-dax-Introduce-bus-driver-model.patch467
-rw-r--r--patches.suse/0001-device-dax-Kill-dax_region-base.patch94
-rw-r--r--patches.suse/0001-device-dax-Kill-dax_region-ida.patch114
-rw-r--r--patches.suse/0001-device-dax-Move-resource-pinning-mapping-into-the-co.patch310
-rw-r--r--patches.suse/0001-device-dax-Remove-multi-resource-infrastructure.patch185
-rw-r--r--patches.suse/0001-device-dax-Start-defining-a-dax-bus-model.patch555
-rw-r--r--patches.suse/0001-mm-devm_memremap_pages-fix-shutdown-handling.patch262
-rw-r--r--patches.suse/0001-mm-devm_memremap_pages-kill-mapping-System-RAM-suppo.patch64
-rw-r--r--patches.suse/0001-mm-memory-hotplug-Allow-memory-resources-to-be-child.patch122
-rw-r--r--patches.suse/0001-mm-resource-Let-walk_system_ram_range-search-child-r.patch77
-rw-r--r--patches.suse/0001-mm-resource-Move-HMM-pr_debug-deeper-into-resource-c.patch95
-rw-r--r--patches.suse/0001-mm-resource-Return-real-error-codes-from-walk-failur.patch77
-rw-r--r--series.conf29
-rw-r--r--supported.conf3
36 files changed, 4397 insertions, 34 deletions
diff --git a/blacklist.conf b/blacklist.conf
index 15c9d5d6c6..e928fe62ec 100644
--- a/blacklist.conf
+++ b/blacklist.conf
@@ -1211,3 +1211,4 @@ ad408a1596b45868e38d0504f2ec1d5fb06f17d4 # cosmetic change
7a625549ea8c14be70bc7cfaf30215401bba6da0 # breaks kABI
5c14a4d05f68415af9e41a4e667d1748d41d1baf # optimization
b4c3fbe6360178dc2181b7b43b7ae793a192b282 # optimization, breaks kABI
+67476656febd7ec5f1fe1aeec3c441fcf53b1e45 # we are not interested in dax kmem to be built in
diff --git a/config/ppc64le/default b/config/ppc64le/default
index a8c6b976f9..5e2c8e207e 100644
--- a/config/ppc64le/default
+++ b/config/ppc64le/default
@@ -4516,6 +4516,8 @@ CONFIG_DAX_DRIVER=y
CONFIG_DAX=y
CONFIG_DEV_DAX=m
CONFIG_DEV_DAX_PMEM=m
+# CONFIG_DEV_DAX_KMEM is not set
+CONFIG_DEV_DAX_PMEM_COMPAT=m
CONFIG_NVMEM=m
CONFIG_STM=m
CONFIG_STM_DUMMY=m
diff --git a/config/x86_64/default b/config/x86_64/default
index f9db54ee9c..b9aea82497 100644
--- a/config/x86_64/default
+++ b/config/x86_64/default
@@ -7030,6 +7030,8 @@ CONFIG_DAX_DRIVER=y
CONFIG_DAX=y
CONFIG_DEV_DAX=m
CONFIG_DEV_DAX_PMEM=m
+CONFIG_DEV_DAX_KMEM=m
+CONFIG_DEV_DAX_PMEM_COMPAT=m
CONFIG_NVMEM=m
CONFIG_STM=m
CONFIG_STM_DUMMY=m
diff --git a/patches.drivers/0001-EDAC-i10nm-Add-Intel-additional-Ice-Lake-support.patch b/patches.drivers/0001-EDAC-i10nm-Add-Intel-additional-Ice-Lake-support.patch
new file mode 100644
index 0000000000..fe8f57e308
--- /dev/null
+++ b/patches.drivers/0001-EDAC-i10nm-Add-Intel-additional-Ice-Lake-support.patch
@@ -0,0 +1,38 @@
+From 5c5d3ac2064ae2466c81d40186bcc09b2d5b7892 Mon Sep 17 00:00:00 2001
+From: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
+Date: Thu, 13 Jun 2019 16:40:27 +0800
+Subject: [PATCH] EDAC, i10nm: Add Intel additional Ice-Lake support
+Git-commit: 5c5d3ac2064ae2466c81d40186bcc09b2d5b7892
+Patch-mainline: 5.3-rc1
+References: fate#327452, jsc#SLE-5322
+
+Two new CPU models share the same memory controller
+architecture with Jacobsville/Tremont, so can use the
+same i10nm EDAC driver.
+
+Add ICX and ICX-D CPU model numbers for EDAC support.
+
+Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
+Signed-off-by: Tony Luck <tony.luck@intel.com>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ drivers/edac/i10nm_base.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/drivers/edac/i10nm_base.c b/drivers/edac/i10nm_base.c
+index 6f06aec4877c..48c6cecc9683 100644
+--- a/drivers/edac/i10nm_base.c
++++ b/drivers/edac/i10nm_base.c
+@@ -124,6 +124,8 @@ static int i10nm_get_all_munits(void)
+
+ static const struct x86_cpu_id i10nm_cpuids[] = {
+ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ATOM_TREMONT_X, 0, 0 },
++ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ICELAKE_X, 0, 0 },
++ { X86_VENDOR_INTEL, 6, INTEL_FAM6_ICELAKE_XEON_D, 0, 0 },
+ { }
+ };
+ MODULE_DEVICE_TABLE(x86cpu, i10nm_cpuids);
+--
+2.12.3
+
diff --git a/patches.drivers/0001-EDAC-i10nm-Check-ECC-enabling-status-per-channel.patch b/patches.drivers/0001-EDAC-i10nm-Check-ECC-enabling-status-per-channel.patch
new file mode 100644
index 0000000000..b7968f93cc
--- /dev/null
+++ b/patches.drivers/0001-EDAC-i10nm-Check-ECC-enabling-status-per-channel.patch
@@ -0,0 +1,45 @@
+From c4a1dd9e83ceceef6ffba82b8b274ab9b929ea14 Mon Sep 17 00:00:00 2001
+From: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
+Date: Wed, 26 Jun 2019 14:16:38 +0800
+Subject: [PATCH] EDAC, i10nm: Check ECC enabling status per channel
+Git-commit: c4a1dd9e83ceceef6ffba82b8b274ab9b929ea14
+Patch-mainline: 5.3-rc1
+References: fate#327452, jsc#SLE-5322
+
+The i10nm_edac only checks the ECC enabling status for the first
+channel of the memory controller. If there aren't memory DIMMs
+populated on the first channel, but at least one DIMM populated
+on the second channel, it will wrongly report that the ECC for
+the memory controller is disabled that fails to load the i10nm_edac
+driver. Fix it by checking ECC enabling status per channel.
+
+[tony: Also report which channel has ECC disabled]
+
+Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
+Signed-off-by: Tony Luck <tony.luck@intel.com>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ drivers/edac/i10nm_base.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/edac/i10nm_base.c b/drivers/edac/i10nm_base.c
+index 48c6cecc9683..72cc20a90ac1 100644
+--- a/drivers/edac/i10nm_base.c
++++ b/drivers/edac/i10nm_base.c
+@@ -168,9 +168,9 @@ static int i10nm_get_dimm_config(struct mem_ctl_info *mci)
+ ndimms += skx_get_nvdimm_info(dimm, imc, i, j,
+ EDAC_MOD_STR);
+ }
+- if (ndimms && !i10nm_check_ecc(imc, 0)) {
+- i10nm_printk(KERN_ERR, "ECC is disabled on imc %d\n",
+- imc->mc);
++ if (ndimms && !i10nm_check_ecc(imc, i)) {
++ i10nm_printk(KERN_ERR, "ECC is disabled on imc %d channel %d\n",
++ imc->mc, i);
+ return -ENODEV;
+ }
+ }
+--
+2.12.3
+
diff --git a/patches.drivers/0001-EDAC-skx-i10nm-Fix-source-ID-register-offset.patch b/patches.drivers/0001-EDAC-skx-i10nm-Fix-source-ID-register-offset.patch
new file mode 100644
index 0000000000..799001b272
--- /dev/null
+++ b/patches.drivers/0001-EDAC-skx-i10nm-Fix-source-ID-register-offset.patch
@@ -0,0 +1,82 @@
+From 1dc78f1ffa3a386b986b659884952d816021f38f Mon Sep 17 00:00:00 2001
+From: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
+Date: Wed, 26 Jun 2019 14:16:55 +0800
+Subject: [PATCH] EDAC, skx, i10nm: Fix source ID register offset
+Git-commit: 1dc78f1ffa3a386b986b659884952d816021f38f
+Patch-mainline: 5.3-rc1
+References: fate#327452, jsc#SLE-5322
+
+The source ID register offset for Skylake server is 0xf0, while for
+Icelake server is 0xf8. Pass the correct offset to get the source ID.
+
+Signed-off-by: Qiuxu Zhuo <qiuxu.zhuo@intel.com>
+Signed-off-by: Tony Luck <tony.luck@intel.com>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ drivers/edac/i10nm_base.c | 2 +-
+ drivers/edac/skx_base.c | 2 +-
+ drivers/edac/skx_common.c | 4 ++--
+ drivers/edac/skx_common.h | 2 +-
+ 4 files changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/drivers/edac/i10nm_base.c b/drivers/edac/i10nm_base.c
+index 72cc20a90ac1..83392f2841de 100644
+--- a/drivers/edac/i10nm_base.c
++++ b/drivers/edac/i10nm_base.c
+@@ -267,7 +267,7 @@ static int __init i10nm_init(void)
+ goto fail;
+
+ list_for_each_entry(d, i10nm_edac_list, list) {
+- rc = skx_get_src_id(d, &src_id);
++ rc = skx_get_src_id(d, 0xf8, &src_id);
+ if (rc < 0)
+ goto fail;
+
+diff --git a/drivers/edac/skx_base.c b/drivers/edac/skx_base.c
+index a5c8fa3a249a..0fcf3785e8f3 100644
+--- a/drivers/edac/skx_base.c
++++ b/drivers/edac/skx_base.c
+@@ -639,7 +639,7 @@ static int __init skx_init(void)
+ }
+
+ list_for_each_entry(d, skx_edac_list, list) {
+- rc = skx_get_src_id(d, &src_id);
++ rc = skx_get_src_id(d, 0xf0, &src_id);
+ if (rc < 0)
+ goto fail;
+ rc = skx_get_node_id(d, &node_id);
+diff --git a/drivers/edac/skx_common.c b/drivers/edac/skx_common.c
+index b0dddcfa9baa..d8ff63d91b86 100644
+--- a/drivers/edac/skx_common.c
++++ b/drivers/edac/skx_common.c
+@@ -136,11 +136,11 @@ void skx_set_decode(skx_decode_f decode)
+ skx_decode = decode;
+ }
+
+-int skx_get_src_id(struct skx_dev *d, u8 *id)
++int skx_get_src_id(struct skx_dev *d, int off, u8 *id)
+ {
+ u32 reg;
+
+- if (pci_read_config_dword(d->util_all, 0xf0, &reg)) {
++ if (pci_read_config_dword(d->util_all, off, &reg)) {
+ skx_printk(KERN_ERR, "Failed to read src id\n");
+ return -ENODEV;
+ }
+diff --git a/drivers/edac/skx_common.h b/drivers/edac/skx_common.h
+index d18fa98669af..08cc971a50ea 100644
+--- a/drivers/edac/skx_common.h
++++ b/drivers/edac/skx_common.h
+@@ -118,7 +118,7 @@ int __init skx_adxl_get(void);
+ void __exit skx_adxl_put(void);
+ void skx_set_decode(skx_decode_f decode);
+
+-int skx_get_src_id(struct skx_dev *d, u8 *id);
++int skx_get_src_id(struct skx_dev *d, int off, u8 *id);
+ int skx_get_node_id(struct skx_dev *d, u8 *id);
+
+ int skx_get_all_bus_mappings(unsigned int did, int off, enum type,
+--
+2.12.3
+
diff --git a/patches.drivers/edac-i10nm-add-a-driver-for-intel-10nm-server-processors.patch b/patches.drivers/edac-i10nm-add-a-driver-for-intel-10nm-server-processors.patch
index 8a6da632c3..507bba1f1d 100644
--- a/patches.drivers/edac-i10nm-add-a-driver-for-intel-10nm-server-processors.patch
+++ b/patches.drivers/edac-i10nm-add-a-driver-for-intel-10nm-server-processors.patch
@@ -3,7 +3,7 @@ Date: Wed, 30 Jan 2019 11:15:19 -0800
Subject: EDAC, i10nm: Add a driver for Intel 10nm server processors
Git-commit: d4dc89d069aab9074e2493a4c2f3969a0a0b91c1
Patch-mainline: v5.1-rc1
-References: fate#327452
+References: fate#327452, jsc#SLE-5322
This driver supports the Intel 10nm series server integrated memory
controller. It gets the memory capacity and topology information by
diff --git a/patches.drivers/edac-skx-i10nm-make-skx_common-c-a-pure-library.patch b/patches.drivers/edac-skx-i10nm-make-skx_common-c-a-pure-library.patch
index 8ff0c9f211..7a2e46521e 100644
--- a/patches.drivers/edac-skx-i10nm-make-skx_common-c-a-pure-library.patch
+++ b/patches.drivers/edac-skx-i10nm-make-skx_common-c-a-pure-library.patch
@@ -3,7 +3,7 @@ Date: Thu, 21 Mar 2019 15:13:39 -0700
Subject: EDAC, skx, i10nm: Make skx_common.c a pure library
Git-commit: fe783516e3016652b74ac92fb8b3fc2b1c0e9d5b
Patch-mainline: v5.2-rc1
-References: fate#327452
+References: fate#327452, jsc#SLE-5322
The following Kconfig constellations fail randconfig builds:
diff --git a/patches.drivers/edac-skx_common-add-code-to-recognise-new-compound-error-code.patch b/patches.drivers/edac-skx_common-add-code-to-recognise-new-compound-error-code.patch
index 70b333b73c..8b402bb7b4 100644
--- a/patches.drivers/edac-skx_common-add-code-to-recognise-new-compound-error-code.patch
+++ b/patches.drivers/edac-skx_common-add-code-to-recognise-new-compound-error-code.patch
@@ -3,7 +3,7 @@ Date: Tue, 5 Feb 2019 10:21:09 -0800
Subject: EDAC, skx_common: Add code to recognise new compound error code
Git-commit: cbfa482f7e2becbb774dd30117efac48819252f8
Patch-mainline: v5.1-rc1
-References: fate#327452
+References: fate#327452, jsc#SLE-5322
A new error code for systems that use DRAM as an extra level of cache
looks like:
diff --git a/patches.drivers/edac-skx_common-separate-common-code-out-from-skx_edac.patch b/patches.drivers/edac-skx_common-separate-common-code-out-from-skx_edac.patch
index 2e25281389..64a7784d2e 100644
--- a/patches.drivers/edac-skx_common-separate-common-code-out-from-skx_edac.patch
+++ b/patches.drivers/edac-skx_common-separate-common-code-out-from-skx_edac.patch
@@ -3,7 +3,7 @@ Date: Wed, 30 Jan 2019 11:15:17 -0800
Subject: EDAC, skx_common: Separate common code out from skx_edac
Git-commit: 88a242c9874044740ab990d4fccba8bb90cb924b
Patch-mainline: v5.1-rc1
-References: fate#327452
+References: fate#327452, jsc#SLE-5322
Parts of skx_edac can be shared with the Intel 10nm server EDAC driver.
diff --git a/patches.drivers/edac-skx_edac-delete-duplicated-code.patch b/patches.drivers/edac-skx_edac-delete-duplicated-code.patch
index c02f529580..1c2f11a2a7 100644
--- a/patches.drivers/edac-skx_edac-delete-duplicated-code.patch
+++ b/patches.drivers/edac-skx_edac-delete-duplicated-code.patch
@@ -3,7 +3,7 @@ Date: Wed, 30 Jan 2019 11:15:18 -0800
Subject: EDAC, skx_edac: Delete duplicated code
Git-commit: 98f2fc829e3b55a0ff1b82753fc1e10941535cb9
Patch-mainline: v5.1-rc1
-References: fate#327452
+References: fate#327452, jsc#SLE-5322
Delete the duplicated code from skx_edac.c and rename skx_edac.c to
skx_base.c. Update the Makefile to build the skx_edac driver from
diff --git a/patches.fixes/0001-device-dax-fix-memory-and-resource-leak-if-hotplug-f.patch b/patches.fixes/0001-device-dax-fix-memory-and-resource-leak-if-hotplug-f.patch
new file mode 100644
index 0000000000..216c254c05
--- /dev/null
+++ b/patches.fixes/0001-device-dax-fix-memory-and-resource-leak-if-hotplug-f.patch
@@ -0,0 +1,106 @@
+From 31e4ca92a7dd4cdebd7fe1456b3b0b6ace9a816f Mon Sep 17 00:00:00 2001
+From: Pavel Tatashin <pasha.tatashin@soleen.com>
+Date: Tue, 16 Jul 2019 16:30:27 -0700
+Subject: [PATCH] device-dax: fix memory and resource leak if hotplug fails
+Mime-version: 1.0
+Content-type: text/plain; charset=UTF-8
+Content-transfer-encoding: 8bit
+Git-commit: 31e4ca92a7dd4cdebd7fe1456b3b0b6ace9a816f
+Patch-mainline: v5.3-rc1
+References: jsc#SLE-5340, git-fixes
+
+Patch series ""Hotremove" persistent memory", v6.
+
+Recently, adding a persistent memory to be used like a regular RAM was
+added to Linux. This work extends this functionality to also allow hot
+removing persistent memory.
+
+We (Microsoft) have an important use case for this functionality.
+
+The requirement is for physical machines with small amount of RAM (~8G)
+to be able to reboot in a very short period of time (<1s). Yet, there
+is a userland state that is expensive to recreate (~2G).
+
+The solution is to boot machines with 2G preserved for persistent
+memory.
+
+Copy the state, and hotadd the persistent memory so machine still has
+all 8G available for runtime. Before reboot, offline and hotremove
+device-dax 2G, copy the memory that is needed to be preserved to pmem0
+device, and reboot.
+
+The series of operations look like this:
+
+1. After boot restore /dev/pmem0 to ramdisk to be consumed by apps.
+ and free ramdisk.
+2. Convert raw pmem0 to devdax
+ ndctl create-namespace --mode devdax --map mem -e namespace0.0 -f
+3. Hotadd to System RAM
+ echo dax0.0 > /sys/bus/dax/drivers/device_dax/unbind
+ echo dax0.0 > /sys/bus/dax/drivers/kmem/new_id
+ echo online_movable > /sys/devices/system/memoryXXX/state
+4. Before reboot hotremove device-dax memory from System RAM
+ echo offline > /sys/devices/system/memoryXXX/state
+ echo dax0.0 > /sys/bus/dax/drivers/kmem/unbind
+5. Create raw pmem0 device
+ ndctl create-namespace --mode raw -e namespace0.0 -f
+6. Copy the state that was stored by apps to ramdisk to pmem device
+7. Do kexec reboot or reboot through firmware if firmware does not
+ zero memory in pmem0 region (These machines have only regular
+ volatile memory). So to have pmem0 device either memmap kernel
+ parameter is used, or devices nodes in dtb are specified.
+
+This patch (of 3):
+
+When add_memory() fails, the resource and the memory should be freed.
+
+Link: http://lkml.kernel.org/r/20190517215438.6487-2-pasha.tatashin@soleen.com
+Fixes: c221c0b0308f ("device-dax: "Hotplug" persistent memory for use like normal RAM")
+Signed-off-by: Pavel Tatashin <pasha.tatashin@soleen.com>
+Reviewed-by: Dave Hansen <dave.hansen@intel.com>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Borislav Petkov <bp@suse.de>
+Cc: Dan Williams <dan.j.williams@intel.com>
+Cc: Dave Hansen <dave.hansen@linux.intel.com>
+Cc: Dave Jiang <dave.jiang@intel.com>
+Cc: David Hildenbrand <david@redhat.com>
+Cc: Fengguang Wu <fengguang.wu@intel.com>
+Cc: Huang Ying <ying.huang@intel.com>
+Cc: James Morris <jmorris@namei.org>
+Cc: Jérôme Glisse <jglisse@redhat.com>
+Cc: Keith Busch <keith.busch@intel.com>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Ross Zwisler <zwisler@kernel.org>
+Cc: Sasha Levin <sashal@kernel.org>
+Cc: Takashi Iwai <tiwai@suse.de>
+Cc: Tom Lendacky <thomas.lendacky@amd.com>
+Cc: Vishal Verma <vishal.l.verma@intel.com>
+Cc: Yaowei Bai <baiyaowei@cmss.chinamobile.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ drivers/dax/kmem.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/dax/kmem.c b/drivers/dax/kmem.c
+index a02318c6d28a..4c0131857133 100644
+--- a/drivers/dax/kmem.c
++++ b/drivers/dax/kmem.c
+@@ -66,8 +66,11 @@ int dev_dax_kmem_probe(struct device *dev)
+ new_res->name = dev_name(dev);
+
+ rc = add_memory(numa_node, new_res->start, resource_size(new_res));
+- if (rc)
++ if (rc) {
++ release_resource(new_res);
++ kfree(new_res);
+ return rc;
++ }
+
+ return 0;
+ }
+--
+2.12.3
+
diff --git a/patches.fixes/0001-x86-respect-memory-size-limiting-via-mem-parameter.patch b/patches.fixes/0001-x86-respect-memory-size-limiting-via-mem-parameter.patch
index cb9ef11660..98b069d277 100644
--- a/patches.fixes/0001-x86-respect-memory-size-limiting-via-mem-parameter.patch
+++ b/patches.fixes/0001-x86-respect-memory-size-limiting-via-mem-parameter.patch
@@ -22,13 +22,11 @@ Acked-by: Ingo Molnar <mingo@kernel.org>
Reviewed-by: William Kucharski <william.kucharski@oracle.com>
Signed-off-by: Juergen Gross <jgross@suse.com>
---
- arch/x86/kernel/e820.c | 5 +++++
- include/linux/memory_hotplug.h | 2 ++
- mm/memory_hotplug.c | 6 ++++++
- 3 files changed, 13 insertions(+)
+ arch/x86/kernel/e820.c | 5 +++++
+ include/linux/memory_hotplug.h | 2 ++
+ mm/memory_hotplug.c | 5 +++++
+ 3 files changed, 12 insertions(+)
-diff --git a/arch/x86/kernel/e820.c b/arch/x86/kernel/e820.c
-index 50895c2f937d..e67513e2cbbb 100644
--- a/arch/x86/kernel/e820.c
+++ b/arch/x86/kernel/e820.c
@@ -15,6 +15,7 @@
@@ -39,7 +37,7 @@ index 50895c2f937d..e67513e2cbbb 100644
#include <asm/e820/api.h>
#include <asm/setup.h>
-@@ -859,6 +860,10 @@ static int __init parse_memopt(char *p)
+@@ -880,6 +881,10 @@ static int __init parse_memopt(char *p)
e820__range_remove(mem_size, ULLONG_MAX - mem_size, E820_TYPE_RAM, 1);
@@ -50,11 +48,9 @@ index 50895c2f937d..e67513e2cbbb 100644
return 0;
}
early_param("mem", parse_memopt);
-diff --git a/include/linux/memory_hotplug.h b/include/linux/memory_hotplug.h
-index 368267c1b71b..cfd12078172a 100644
--- a/include/linux/memory_hotplug.h
+++ b/include/linux/memory_hotplug.h
-@@ -114,6 +114,8 @@ extern void __online_page_free(struct page *page);
+@@ -115,6 +115,8 @@ extern void __online_page_free(struct pa
extern int try_online_node(int nid);
@@ -63,11 +59,9 @@ index 368267c1b71b..cfd12078172a 100644
extern bool memhp_auto_online;
#ifdef CONFIG_MEMORY_HOTREMOVE
-diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
-index 124e794867c5..519f9db063ff 100644
--- a/mm/memory_hotplug.c
+++ b/mm/memory_hotplug.c
-@@ -156,10 +156,16 @@ void mem_hotplug_done(void)
+@@ -154,6 +154,8 @@ void mem_hotplug_done(void)
mutex_unlock(&memory_add_remove_lock);
}
@@ -76,14 +70,13 @@ index 124e794867c5..519f9db063ff 100644
/* add this memory to iomem resource */
static struct resource *register_memory_resource(u64 start, u64 size)
{
- struct resource *res, *conflict;
-+
+@@ -161,6 +163,9 @@ static struct resource *register_memory_
+ unsigned long flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
+ char *resource_name = "System RAM";
+
+ if (start + size > max_mem_size)
+ return ERR_PTR(-E2BIG);
+
- res = kzalloc(sizeof(struct resource), GFP_KERNEL);
- if (!res)
- return ERR_PTR(-ENOMEM);
---
-2.16.4
-
+ /*
+ * Request ownership of the new memory range. This might be
+ * a child of an existing resource that was present but
diff --git a/patches.fixes/drivers-base-introduce-kill_device.patch b/patches.fixes/drivers-base-introduce-kill_device.patch
index 84045dee33..a5a8777193 100644
--- a/patches.fixes/drivers-base-introduce-kill_device.patch
+++ b/patches.fixes/drivers-base-introduce-kill_device.patch
@@ -1,8 +1,7 @@
From: Dan Williams <dan.j.williams@intel.com>
Date: Wed, 17 Jul 2019 18:07:53 -0700
Subject: drivers/base: Introduce kill_device()
-Patch-mainline: Queued in subsystem maintainer repository
-Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm.git
+Patch-mainline: v5.3-rc2
Git-commit: 00289cd87676e14913d2d8492d1ce05c4baafdae
References: bsc#1139865
diff --git a/patches.fixes/libnvdimm-bus-prevent-duplicate-device_unregister-calls.patch b/patches.fixes/libnvdimm-bus-prevent-duplicate-device_unregister-calls.patch
index 998b29f711..c4b470d1f2 100644
--- a/patches.fixes/libnvdimm-bus-prevent-duplicate-device_unregister-calls.patch
+++ b/patches.fixes/libnvdimm-bus-prevent-duplicate-device_unregister-calls.patch
@@ -1,8 +1,7 @@
From: Dan Williams <dan.j.williams@intel.com>
Date: Wed, 17 Jul 2019 18:07:58 -0700
Subject: libnvdimm/bus: Prevent duplicate device_unregister() calls
-Patch-mainline: Queued in subsystem maintainer repository
-Git-repo: git://git.kernel.org/pub/scm/linux/kernel/git/nvdimm/nvdimm.git
+Patch-mainline: v5.3-rc2
Git-commit: 8aac0e2338916e273ccbd438a2b7a1e8c61749f5
References: bsc#1139865
diff --git a/patches.suse/0001-acpi-nfit-device-dax-Identify-differentiated-memory-.patch b/patches.suse/0001-acpi-nfit-device-dax-Identify-differentiated-memory-.patch
new file mode 100644
index 0000000000..2063a9b31e
--- /dev/null
+++ b/patches.suse/0001-acpi-nfit-device-dax-Identify-differentiated-memory-.patch
@@ -0,0 +1,302 @@
+From 8fc5c73554db0ac18c0c6ac5b2099ab917f83bdf Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Fri, 9 Nov 2018 12:43:07 -0800
+Subject: [PATCH] acpi/nfit, device-dax: Identify differentiated memory with a
+ unique numa-node
+Mime-version: 1.0
+Content-type: text/plain; charset=UTF-8
+Content-transfer-encoding: 8bit
+Git-commit: 8fc5c73554db0ac18c0c6ac5b2099ab917f83bdf
+Patch-mainline: v5.1-rc1
+References: jsc#SLE-5340
+
+Persistent memory, as described by the ACPI NFIT (NVDIMM Firmware
+Interface Table), is the first known instance of a memory range
+described by a unique "target" proximity domain. Where "initiator" and
+"target" proximity domains is an approach that the ACPI HMAT
+(Heterogeneous Memory Attributes Table) uses to described the unique
+performance properties of a memory range relative to a given initiator
+(e.g. CPU or DMA device).
+
+Currently the numa-node for a /dev/pmemX block-device or /dev/daxX.Y
+char-device follows the traditional notion of 'numa-node' where the
+attribute conveys the closest online numa-node. That numa-node attribute
+is useful for cpu-binding and memory-binding processes *near* the
+device. However, when the memory range backing a 'pmem', or 'dax' device
+is onlined (memory hot-add) the memory-only-numa-node representing that
+address needs to be differentiated from the set of online nodes. In
+other words, the numa-node association of the device depends on whether
+you can bind processes *near* the cpu-numa-node in the offline
+device-case, or bind process *on* the memory-range directly after the
+backing address range is onlined.
+
+Allow for the case that platform firmware describes persistent memory
+with a unique proximity domain, i.e. when it is distinct from the
+proximity of DRAM and CPUs that are on the same socket. Plumb the Linux
+numa-node translation of that proximity through the libnvdimm region
+device to namespaces that are in device-dax mode. With this in place the
+proposed kmem driver [1] can optionally discover a unique numa-node
+number for the address range as it transitions the memory from an
+offline state managed by a device-driver to an online memory range
+managed by the core-mm.
+
+[1]: https://lore.kernel.org/lkml/20181022201317.8558C1D8@viggo.jf.intel.com
+
+Reported-by: Fan Du <fan.du@intel.com>
+Cc: Michael Ellerman <mpe@ellerman.id.au>
+Cc: "Oliver O'Halloran" <oohall@gmail.com>
+Cc: Dave Hansen <dave.hansen@linux.intel.com>
+Cc: Jérôme Glisse <jglisse@redhat.com>
+Reviewed-by: Yang Shi <yang.shi@linux.alibaba.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ arch/powerpc/platforms/pseries/papr_scm.c | 1 +
+ drivers/acpi/nfit/core.c | 8 ++++++--
+ drivers/acpi/numa.c | 1 +
+ drivers/dax/bus.c | 4 +++-
+ drivers/dax/bus.h | 3 ++-
+ drivers/dax/dax-private.h | 4 ++++
+ drivers/dax/pmem/core.c | 4 +++-
+ drivers/nvdimm/e820.c | 1 +
+ drivers/nvdimm/nd.h | 2 +-
+ drivers/nvdimm/of_pmem.c | 1 +
+ drivers/nvdimm/region_devs.c | 1 +
+ include/linux/acpi.h | 5 +++++
+ include/linux/libnvdimm.h | 1 +
+ 13 files changed, 30 insertions(+), 6 deletions(-)
+
+diff --git a/arch/powerpc/platforms/pseries/papr_scm.c b/arch/powerpc/platforms/pseries/papr_scm.c
+index 7d6457ab5d34..8806ac822627 100644
+--- a/arch/powerpc/platforms/pseries/papr_scm.c
++++ b/arch/powerpc/platforms/pseries/papr_scm.c
+@@ -236,6 +236,7 @@ static int papr_scm_nvdimm_init(struct papr_scm_priv *p)
+ memset(&ndr_desc, 0, sizeof(ndr_desc));
+ ndr_desc.attr_groups = region_attr_groups;
+ ndr_desc.numa_node = dev_to_node(&p->pdev->dev);
++ ndr_desc.target_node = ndr_desc.numa_node;
+ ndr_desc.res = &p->res;
+ ndr_desc.of_node = p->dn;
+ ndr_desc.provider_data = p;
+diff --git a/drivers/acpi/nfit/core.c b/drivers/acpi/nfit/core.c
+index 011d3db19c80..475899974c70 100644
+--- a/drivers/acpi/nfit/core.c
++++ b/drivers/acpi/nfit/core.c
+@@ -2869,11 +2869,15 @@ static int acpi_nfit_register_region(struct acpi_nfit_desc *acpi_desc,
+ ndr_desc->res = &res;
+ ndr_desc->provider_data = nfit_spa;
+ ndr_desc->attr_groups = acpi_nfit_region_attribute_groups;
+- if (spa->flags & ACPI_NFIT_PROXIMITY_VALID)
++ if (spa->flags & ACPI_NFIT_PROXIMITY_VALID) {
+ ndr_desc->numa_node = acpi_map_pxm_to_online_node(
+ spa->proximity_domain);
+- else
++ ndr_desc->target_node = acpi_map_pxm_to_node(
++ spa->proximity_domain);
++ } else {
+ ndr_desc->numa_node = NUMA_NO_NODE;
++ ndr_desc->target_node = NUMA_NO_NODE;
++ }
+
+ /*
+ * Persistence domain bits are hierarchical, if
+diff --git a/drivers/acpi/numa.c b/drivers/acpi/numa.c
+index 274699463b4f..b9d86babb13a 100644
+--- a/drivers/acpi/numa.c
++++ b/drivers/acpi/numa.c
+@@ -84,6 +84,7 @@ int acpi_map_pxm_to_node(int pxm)
+
+ return node;
+ }
++EXPORT_SYMBOL(acpi_map_pxm_to_node);
+
+ /**
+ * acpi_map_pxm_to_online_node - Map proximity ID to online node
+diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
+index 568168500217..c620ad52d7e5 100644
+--- a/drivers/dax/bus.c
++++ b/drivers/dax/bus.c
+@@ -214,7 +214,7 @@ static void dax_region_unregister(void *region)
+ }
+
+ struct dax_region *alloc_dax_region(struct device *parent, int region_id,
+- struct resource *res, unsigned int align,
++ struct resource *res, int target_node, unsigned int align,
+ unsigned long pfn_flags)
+ {
+ struct dax_region *dax_region;
+@@ -244,6 +244,7 @@ struct dax_region *alloc_dax_region(struct device *parent, int region_id,
+ dax_region->id = region_id;
+ dax_region->align = align;
+ dax_region->dev = parent;
++ dax_region->target_node = target_node;
+ if (sysfs_create_groups(&parent->kobj, dax_region_attribute_groups)) {
+ kfree(dax_region);
+ return NULL;
+@@ -348,6 +349,7 @@ struct dev_dax *__devm_create_dev_dax(struct dax_region *dax_region, int id,
+
+ dev_dax->dax_dev = dax_dev;
+ dev_dax->region = dax_region;
++ dev_dax->target_node = dax_region->target_node;
+ kref_get(&dax_region->kref);
+
+ inode = dax_inode(dax_dev);
+diff --git a/drivers/dax/bus.h b/drivers/dax/bus.h
+index ce977552ffb5..8619e3299943 100644
+--- a/drivers/dax/bus.h
++++ b/drivers/dax/bus.h
+@@ -10,7 +10,8 @@ struct dax_device;
+ struct dax_region;
+ void dax_region_put(struct dax_region *dax_region);
+ struct dax_region *alloc_dax_region(struct device *parent, int region_id,
+- struct resource *res, unsigned int align, unsigned long flags);
++ struct resource *res, int target_node, unsigned int align,
++ unsigned long flags);
+
+ enum dev_dax_subsys {
+ DEV_DAX_BUS,
+diff --git a/drivers/dax/dax-private.h b/drivers/dax/dax-private.h
+index a82ce48f5884..a45612148ca0 100644
+--- a/drivers/dax/dax-private.h
++++ b/drivers/dax/dax-private.h
+@@ -26,6 +26,7 @@ void dax_bus_exit(void);
+ /**
+ * struct dax_region - mapping infrastructure for dax devices
+ * @id: kernel-wide unique region for a memory range
++ * @target_node: effective numa node if this memory range is onlined
+ * @kref: to pin while other agents have a need to do lookups
+ * @dev: parent device backing this region
+ * @align: allocation and mapping alignment for child dax devices
+@@ -34,6 +35,7 @@ void dax_bus_exit(void);
+ */
+ struct dax_region {
+ int id;
++ int target_node;
+ struct kref kref;
+ struct device *dev;
+ unsigned int align;
+@@ -46,6 +48,7 @@ struct dax_region {
+ * data while the device is activated in the driver.
+ * @region - parent region
+ * @dax_dev - core dax functionality
++ * @target_node: effective numa node if dev_dax memory range is onlined
+ * @dev - device core
+ * @pgmap - pgmap for memmap setup / lifetime (driver owned)
+ * @ref: pgmap reference count (driver owned)
+@@ -54,6 +57,7 @@ struct dax_region {
+ struct dev_dax {
+ struct dax_region *region;
+ struct dax_device *dax_dev;
++ int target_node;
+ struct device dev;
+ struct dev_pagemap pgmap;
+ struct percpu_ref ref;
+diff --git a/drivers/dax/pmem/core.c b/drivers/dax/pmem/core.c
+index bdcff1b14e95..f71019ce0647 100644
+--- a/drivers/dax/pmem/core.c
++++ b/drivers/dax/pmem/core.c
+@@ -20,6 +20,7 @@ struct dev_dax *__dax_pmem_probe(struct device *dev, enum dev_dax_subsys subsys)
+ struct nd_namespace_common *ndns;
+ struct nd_dax *nd_dax = to_nd_dax(dev);
+ struct nd_pfn *nd_pfn = &nd_dax->nd_pfn;
++ struct nd_region *nd_region = to_nd_region(dev->parent);
+
+ ndns = nvdimm_namespace_common_probe(dev);
+ if (IS_ERR(ndns))
+@@ -52,7 +53,8 @@ struct dev_dax *__dax_pmem_probe(struct device *dev, enum dev_dax_subsys subsys)
+ memcpy(&res, &pgmap.res, sizeof(res));
+ res.start += offset;
+ dax_region = alloc_dax_region(dev, region_id, &res,
+- le32_to_cpu(pfn_sb->align), PFN_DEV|PFN_MAP);
++ nd_region->target_node, le32_to_cpu(pfn_sb->align),
++ PFN_DEV|PFN_MAP);
+ if (!dax_region)
+ return ERR_PTR(-ENOMEM);
+
+diff --git a/drivers/nvdimm/e820.c b/drivers/nvdimm/e820.c
+index 521eaf53a52a..36be9b619187 100644
+--- a/drivers/nvdimm/e820.c
++++ b/drivers/nvdimm/e820.c
+@@ -47,6 +47,7 @@ static int e820_register_one(struct resource *res, void *data)
+ ndr_desc.res = res;
+ ndr_desc.attr_groups = e820_pmem_region_attribute_groups;
+ ndr_desc.numa_node = e820_range_to_nid(res->start);
++ ndr_desc.target_node = ndr_desc.numa_node;
+ set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
+ if (!nvdimm_pmem_region_create(nvdimm_bus, &ndr_desc))
+ return -ENXIO;
+diff --git a/drivers/nvdimm/nd.h b/drivers/nvdimm/nd.h
+index cfde992684e7..0b3d7595b3cb 100644
+--- a/drivers/nvdimm/nd.h
++++ b/drivers/nvdimm/nd.h
+@@ -153,7 +153,7 @@ struct nd_region {
+ u16 ndr_mappings;
+ u64 ndr_size;
+ u64 ndr_start;
+- int id, num_lanes, ro, numa_node;
++ int id, num_lanes, ro, numa_node, target_node;
+ void *provider_data;
+ struct kernfs_node *bb_state;
+ struct badblocks bb;
+diff --git a/drivers/nvdimm/of_pmem.c b/drivers/nvdimm/of_pmem.c
+index 0a701837dfc0..ecaaa27438e2 100644
+--- a/drivers/nvdimm/of_pmem.c
++++ b/drivers/nvdimm/of_pmem.c
+@@ -68,6 +68,7 @@ static int of_pmem_region_probe(struct platform_device *pdev)
+ memset(&ndr_desc, 0, sizeof(ndr_desc));
+ ndr_desc.attr_groups = region_attr_groups;
+ ndr_desc.numa_node = dev_to_node(&pdev->dev);
++ ndr_desc.target_node = ndr_desc.numa_node;
+ ndr_desc.res = &pdev->resource[i];
+ ndr_desc.of_node = np;
+ set_bit(ND_REGION_PAGEMAP, &ndr_desc.flags);
+diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c
+index e2818f94f292..caf2f3129ccd 100644
+--- a/drivers/nvdimm/region_devs.c
++++ b/drivers/nvdimm/region_devs.c
+@@ -1065,6 +1065,7 @@ static struct nd_region *nd_region_create(struct nvdimm_bus *nvdimm_bus,
+ nd_region->flags = ndr_desc->flags;
+ nd_region->ro = ro;
+ nd_region->numa_node = ndr_desc->numa_node;
++ nd_region->target_node = ndr_desc->target_node;
+ ida_init(&nd_region->ns_ida);
+ ida_init(&nd_region->btt_ida);
+ ida_init(&nd_region->pfn_ida);
+diff --git a/include/linux/acpi.h b/include/linux/acpi.h
+index 87715f20b69a..eddf2736e5a6 100644
+--- a/include/linux/acpi.h
++++ b/include/linux/acpi.h
+@@ -400,12 +400,17 @@ extern bool acpi_osi_is_win8(void);
+
+ #ifdef CONFIG_ACPI_NUMA
+ int acpi_map_pxm_to_online_node(int pxm);
++int acpi_map_pxm_to_node(int pxm);
+ int acpi_get_node(acpi_handle handle);
+ #else
+ static inline int acpi_map_pxm_to_online_node(int pxm)
+ {
+ return 0;
+ }
++static inline int acpi_map_pxm_to_node(int pxm)
++{
++ return 0;
++}
+ static inline int acpi_get_node(acpi_handle handle)
+ {
+ return 0;
+diff --git a/include/linux/libnvdimm.h b/include/linux/libnvdimm.h
+index 5440f11b0907..56bc545ad3b2 100644
+--- a/include/linux/libnvdimm.h
++++ b/include/linux/libnvdimm.h
+@@ -128,6 +128,7 @@ struct nd_region_desc {
+ void *provider_data;
+ int num_lanes;
+ int numa_node;
++ int target_node;
+ unsigned long flags;
+ struct device_node *of_node;
+ };
+--
+2.12.3
+
diff --git a/patches.suse/0001-device-dax-Add-a-modalias-attribute-to-DAX-bus-devic.patch b/patches.suse/0001-device-dax-Add-a-modalias-attribute-to-DAX-bus-devic.patch
new file mode 100644
index 0000000000..d8fa586200
--- /dev/null
+++ b/patches.suse/0001-device-dax-Add-a-modalias-attribute-to-DAX-bus-devic.patch
@@ -0,0 +1,61 @@
+From c347bd71dcdb2d0ac8b3a771486584dca8c8dd80 Mon Sep 17 00:00:00 2001
+From: Vishal Verma <vishal.l.verma@intel.com>
+Date: Fri, 22 Feb 2019 16:58:54 -0700
+Subject: [PATCH] device-dax: Add a 'modalias' attribute to DAX 'bus' devices
+Git-commit: c347bd71dcdb2d0ac8b3a771486584dca8c8dd80
+Patch-mainline: v5.1-rc1
+References: jsc#SLE-5340
+
+Add a 'modalias' attribute to devices under the DAX bus so that userspace
+is able to dynamically load modules as needed.
+
+Normally, udev can get the modalias from 'uevent', and that is correctly
+set up by the DAX bus. However other tooling such as 'libndctl' for
+interacting with drivers/nvdimm/, and 'libdaxctl' for drivers/dax/ can
+also use the modalias to dynamically load modules via libkmod lookups.
+
+The 'nd' bus set up by the libnvdimm subsystem exports a modalias
+attribute. Imitate this to export the same for the 'dax' bus.
+
+Cc: Dave Hansen <dave.hansen@linux.intel.com>
+Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ drivers/dax/bus.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
+index 28c3324271ac..2109cfe80219 100644
+--- a/drivers/dax/bus.c
++++ b/drivers/dax/bus.c
+@@ -295,6 +295,17 @@ static ssize_t target_node_show(struct device *dev,
+ }
+ static DEVICE_ATTR_RO(target_node);
+
++static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
++ char *buf)
++{
++ /*
++ * We only ever expect to handle device-dax instances, i.e. the
++ * @type argument to MODULE_ALIAS_DAX_DEVICE() is always zero
++ */
++ return sprintf(buf, DAX_DEVICE_MODALIAS_FMT "\n", 0);
++}
++static DEVICE_ATTR_RO(modalias);
++
+ static umode_t dev_dax_visible(struct kobject *kobj, struct attribute *a, int n)
+ {
+ struct device *dev = container_of(kobj, struct device, kobj);
+@@ -306,6 +317,7 @@ static umode_t dev_dax_visible(struct kobject *kobj, struct attribute *a, int n)
+ }
+
+ static struct attribute *dev_dax_attributes[] = {
++ &dev_attr_modalias.attr,
+ &dev_attr_size.attr,
+ &dev_attr_target_node.attr,
+ NULL,
+--
+2.12.3
+
diff --git a/patches.suse/0001-device-dax-Add-a-target_node-attribute.patch b/patches.suse/0001-device-dax-Add-a-target_node-attribute.patch
new file mode 100644
index 0000000000..4110166275
--- /dev/null
+++ b/patches.suse/0001-device-dax-Add-a-target_node-attribute.patch
@@ -0,0 +1,76 @@
+From 21c75763a3ae18679e5c4e2260aa9379b073566b Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Wed, 20 Feb 2019 11:39:36 -0800
+Subject: [PATCH] device-dax: Add a 'target_node' attribute
+Git-commit: 21c75763a3ae18679e5c4e2260aa9379b073566b
+Patch-mainline: v5.1-rc1
+References: jsc#SLE-5340
+
+The target-node attribute is the Linux numa-node that a device-dax
+instance may create when it is online. Prior to being online the
+device's 'numa_node' property reflects the closest online cpu node which
+is the typical expectation of a device 'numa_node'. Once it is online it
+becomes its own distinct numa node, i.e. 'target_node'.
+
+Export the 'target_node' property to give userspace tooling the ability
+to predict the effective numa-node from a device-dax instance configured
+to provide 'System RAM' capacity.
+
+Cc: Vishal Verma <vishal.l.verma@intel.com>
+Reported-by: Dave Hansen <dave.hansen@linux.intel.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ drivers/dax/bus.c | 28 ++++++++++++++++++++++++++++
+ 1 file changed, 28 insertions(+)
+
+diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
+index a410154d75fb..28c3324271ac 100644
+--- a/drivers/dax/bus.c
++++ b/drivers/dax/bus.c
+@@ -279,13 +279,41 @@ static ssize_t size_show(struct device *dev,
+ }
+ static DEVICE_ATTR_RO(size);
+
++static int dev_dax_target_node(struct dev_dax *dev_dax)
++{
++ struct dax_region *dax_region = dev_dax->region;
++
++ return dax_region->target_node;
++}
++
++static ssize_t target_node_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct dev_dax *dev_dax = to_dev_dax(dev);
++
++ return sprintf(buf, "%d\n", dev_dax_target_node(dev_dax));
++}
++static DEVICE_ATTR_RO(target_node);
++
++static umode_t dev_dax_visible(struct kobject *kobj, struct attribute *a, int n)
++{
++ struct device *dev = container_of(kobj, struct device, kobj);
++ struct dev_dax *dev_dax = to_dev_dax(dev);
++
++ if (a == &dev_attr_target_node.attr && dev_dax_target_node(dev_dax) < 0)
++ return 0;
++ return a->mode;
++}
++
+ static struct attribute *dev_dax_attributes[] = {
+ &dev_attr_size.attr,
++ &dev_attr_target_node.attr,
+ NULL,
+ };
+
+ static const struct attribute_group dev_dax_attribute_group = {
+ .attrs = dev_dax_attributes,
++ .is_visible = dev_dax_visible,
+ };
+
+ static const struct attribute_group *dax_attribute_groups[] = {
+--
+2.12.3
+
diff --git a/patches.suse/0001-device-dax-Add-support-for-a-dax-override-driver.patch b/patches.suse/0001-device-dax-Add-support-for-a-dax-override-driver.patch
new file mode 100644
index 0000000000..c6e0a186a3
--- /dev/null
+++ b/patches.suse/0001-device-dax-Add-support-for-a-dax-override-driver.patch
@@ -0,0 +1,278 @@
+From d200781ef237a354d918ceff5cee350d88a93d42 Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Wed, 7 Nov 2018 15:31:23 -0800
+Subject: [PATCH] device-dax: Add support for a dax override driver
+Git-commit: d200781ef237a354d918ceff5cee350d88a93d42
+Patch-mainline: v5.1-rc1
+References: jsc#SLE-5340
+
+Introduce the 'new_id' concept for enabling a custom device-driver attach
+policy for dax-bus drivers. The intended use is to have a mechanism for
+hot-plugging device-dax ranges into the page allocator on-demand. With
+this in place the default policy of using device-dax for performance
+differentiated memory can be overridden by user-space policy that can
+arrange for the memory range to be managed as 'System RAM' with
+user-defined NUMA and other performance attributes.
+
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ drivers/dax/bus.c | 145 +++++++++++++++++++++++++++++++++++++++++++++++++--
+ drivers/dax/bus.h | 10 +++-
+ drivers/dax/device.c | 11 ++--
+ 3 files changed, 156 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
+index 69aae2cbd45f..17af6fbc3be5 100644
+--- a/drivers/dax/bus.c
++++ b/drivers/dax/bus.c
+@@ -2,11 +2,21 @@
+ /* Copyright(c) 2017-2018 Intel Corporation. All rights reserved. */
+ #include <linux/memremap.h>
+ #include <linux/device.h>
++#include <linux/mutex.h>
++#include <linux/list.h>
+ #include <linux/slab.h>
+ #include <linux/dax.h>
+ #include "dax-private.h"
+ #include "bus.h"
+
++static DEFINE_MUTEX(dax_bus_lock);
++
++#define DAX_NAME_LEN 30
++struct dax_id {
++ struct list_head list;
++ char dev_name[DAX_NAME_LEN];
++};
++
+ static int dax_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
+ {
+ /*
+@@ -16,22 +26,115 @@ static int dax_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
+ return add_uevent_var(env, "MODALIAS=" DAX_DEVICE_MODALIAS_FMT, 0);
+ }
+
++static struct dax_device_driver *to_dax_drv(struct device_driver *drv)
++{
++ return container_of(drv, struct dax_device_driver, drv);
++}
++
++static struct dax_id *__dax_match_id(struct dax_device_driver *dax_drv,
++ const char *dev_name)
++{
++ struct dax_id *dax_id;
++
++ lockdep_assert_held(&dax_bus_lock);
++
++ list_for_each_entry(dax_id, &dax_drv->ids, list)
++ if (sysfs_streq(dax_id->dev_name, dev_name))
++ return dax_id;
++ return NULL;
++}
++
++static int dax_match_id(struct dax_device_driver *dax_drv, struct device *dev)
++{
++ int match;
++
++ mutex_lock(&dax_bus_lock);
++ match = !!__dax_match_id(dax_drv, dev_name(dev));
++ mutex_unlock(&dax_bus_lock);
++
++ return match;
++}
++
++static ssize_t do_id_store(struct device_driver *drv, const char *buf,
++ size_t count, bool add)
++{
++ struct dax_device_driver *dax_drv = to_dax_drv(drv);
++ unsigned int region_id, id;
++ char devname[DAX_NAME_LEN];
++ struct dax_id *dax_id;
++ ssize_t rc = count;
++ int fields;
++
++ fields = sscanf(buf, "dax%d.%d", &region_id, &id);
++ if (fields != 2)
++ return -EINVAL;
++ sprintf(devname, "dax%d.%d", region_id, id);
++ if (!sysfs_streq(buf, devname))
++ return -EINVAL;
++
++ mutex_lock(&dax_bus_lock);
++ dax_id = __dax_match_id(dax_drv, buf);
++ if (!dax_id) {
++ if (add) {
++ dax_id = kzalloc(sizeof(*dax_id), GFP_KERNEL);
++ if (dax_id) {
++ strncpy(dax_id->dev_name, buf, DAX_NAME_LEN);
++ list_add(&dax_id->list, &dax_drv->ids);
++ } else
++ rc = -ENOMEM;
++ } else
++ /* nothing to remove */;
++ } else if (!add) {
++ list_del(&dax_id->list);
++ kfree(dax_id);
++ } else
++ /* dax_id already added */;
++ mutex_unlock(&dax_bus_lock);
++ return rc;
++}
++
++static ssize_t new_id_store(struct device_driver *drv, const char *buf,
++ size_t count)
++{
++ return do_id_store(drv, buf, count, true);
++}
++static DRIVER_ATTR_WO(new_id);
++
++static ssize_t remove_id_store(struct device_driver *drv, const char *buf,
++ size_t count)
++{
++ return do_id_store(drv, buf, count, false);
++}
++static DRIVER_ATTR_WO(remove_id);
++
++static struct attribute *dax_drv_attrs[] = {
++ &driver_attr_new_id.attr,
++ &driver_attr_remove_id.attr,
++ NULL,
++};
++ATTRIBUTE_GROUPS(dax_drv);
++
+ static int dax_bus_match(struct device *dev, struct device_driver *drv);
+
+ static struct bus_type dax_bus_type = {
+ .name = "dax",
+ .uevent = dax_bus_uevent,
+ .match = dax_bus_match,
++ .drv_groups = dax_drv_groups,
+ };
+
+ static int dax_bus_match(struct device *dev, struct device_driver *drv)
+ {
++ struct dax_device_driver *dax_drv = to_dax_drv(drv);
++
+ /*
+- * The drivers that can register on the 'dax' bus are private to
+- * drivers/dax/ so any device and driver on the bus always
+- * match.
++ * All but the 'device-dax' driver, which has 'match_always'
++ * set, requires an exact id match.
+ */
+- return 1;
++ if (dax_drv->match_always)
++ return 1;
++
++ return dax_match_id(dax_drv, dev);
+ }
+
+ /*
+@@ -273,17 +376,49 @@ struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id,
+ }
+ EXPORT_SYMBOL_GPL(devm_create_dev_dax);
+
+-int __dax_driver_register(struct device_driver *drv,
++static int match_always_count;
++
++int __dax_driver_register(struct dax_device_driver *dax_drv,
+ struct module *module, const char *mod_name)
+ {
++ struct device_driver *drv = &dax_drv->drv;
++ int rc = 0;
++
++ INIT_LIST_HEAD(&dax_drv->ids);
+ drv->owner = module;
+ drv->name = mod_name;
+ drv->mod_name = mod_name;
+ drv->bus = &dax_bus_type;
++
++ /* there can only be one default driver */
++ mutex_lock(&dax_bus_lock);
++ match_always_count += dax_drv->match_always;
++ if (match_always_count > 1) {
++ match_always_count--;
++ WARN_ON(1);
++ rc = -EINVAL;
++ }
++ mutex_unlock(&dax_bus_lock);
++ if (rc)
++ return rc;
+ return driver_register(drv);
+ }
+ EXPORT_SYMBOL_GPL(__dax_driver_register);
+
++void dax_driver_unregister(struct dax_device_driver *dax_drv)
++{
++ struct dax_id *dax_id, *_id;
++
++ mutex_lock(&dax_bus_lock);
++ match_always_count -= dax_drv->match_always;
++ list_for_each_entry_safe(dax_id, _id, &dax_drv->ids, list) {
++ list_del(&dax_id->list);
++ kfree(dax_id);
++ }
++ mutex_unlock(&dax_bus_lock);
++}
++EXPORT_SYMBOL_GPL(dax_driver_unregister);
++
+ int __init dax_bus_init(void)
+ {
+ return bus_register(&dax_bus_type);
+diff --git a/drivers/dax/bus.h b/drivers/dax/bus.h
+index e08e0c394983..395ab812367c 100644
+--- a/drivers/dax/bus.h
++++ b/drivers/dax/bus.h
+@@ -12,10 +12,18 @@ struct dax_region *alloc_dax_region(struct device *parent, int region_id,
+ struct resource *res, unsigned int align, unsigned long flags);
+ struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id,
+ struct dev_pagemap *pgmap);
+-int __dax_driver_register(struct device_driver *drv,
++
++struct dax_device_driver {
++ struct device_driver drv;
++ struct list_head ids;
++ int match_always;
++};
++
++int __dax_driver_register(struct dax_device_driver *dax_drv,
+ struct module *module, const char *mod_name);
+ #define dax_driver_register(driver) \
+ __dax_driver_register(driver, THIS_MODULE, KBUILD_MODNAME)
++void dax_driver_unregister(struct dax_device_driver *dax_drv);
+ void kill_dev_dax(struct dev_dax *dev_dax);
+
+ /*
+diff --git a/drivers/dax/device.c b/drivers/dax/device.c
+index 6ad964d7b077..ad3120395f7a 100644
+--- a/drivers/dax/device.c
++++ b/drivers/dax/device.c
+@@ -504,9 +504,12 @@ static int dev_dax_remove(struct device *dev)
+ return 0;
+ }
+
+-static struct device_driver device_dax_driver = {
+- .probe = dev_dax_probe,
+- .remove = dev_dax_remove,
++static struct dax_device_driver device_dax_driver = {
++ .drv = {
++ .probe = dev_dax_probe,
++ .remove = dev_dax_remove,
++ },
++ .match_always = 1,
+ };
+
+ static int __init dax_init(void)
+@@ -516,7 +519,7 @@ static int __init dax_init(void)
+
+ static void __exit dax_exit(void)
+ {
+- driver_unregister(&device_dax_driver);
++ dax_driver_unregister(&device_dax_driver);
+ }
+
+ MODULE_AUTHOR("Intel Corporation");
+--
+2.12.3
+
diff --git a/patches.suse/0001-device-dax-Add-sys-class-dax-backwards-compatibility.patch b/patches.suse/0001-device-dax-Add-sys-class-dax-backwards-compatibility.patch
new file mode 100644
index 0000000000..b54106d832
--- /dev/null
+++ b/patches.suse/0001-device-dax-Add-sys-class-dax-backwards-compatibility.patch
@@ -0,0 +1,583 @@
+From 730926c3b0998943654019f00296cf8e3b02277e Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Sun, 16 Jul 2017 13:51:53 -0700
+Subject: [PATCH] device-dax: Add /sys/class/dax backwards compatibility
+Git-commit: 730926c3b0998943654019f00296cf8e3b02277e
+Patch-mainline: v5.1-rc1
+References: jsc#SLE-5340
+
+On the expectation that some environments may not upgrade libdaxctl
+(userspace component that depends on the /sys/class/dax hierarchy),
+provide a default / legacy dax_pmem_compat driver. The dax_pmem_compat
+driver implements the original /sys/class/dax sysfs layout rather than
+/sys/bus/dax. When userspace is upgraded it can blacklist this module
+and switch to the dax_pmem driver going forward.
+
+CONFIG_DEV_DAX_PMEM_COMPAT and supporting code will be deleted according
+to the dax_pmem entry in Documentation/ABI/obsolete/.
+
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ Documentation/ABI/obsolete/sysfs-class-dax | 22 +++++++
+ drivers/dax/Kconfig | 12 +++
+ drivers/dax/Makefile | 4 -
+ drivers/dax/bus.c | 29 +++++++--
+ drivers/dax/bus.h | 26 +++++++-
+ drivers/dax/device.c | 9 ++
+ drivers/dax/pmem.c | 90 -----------------------------
+ drivers/dax/pmem/Makefile | 7 ++
+ drivers/dax/pmem/compat.c | 73 +++++++++++++++++++++++
+ drivers/dax/pmem/core.c | 69 ++++++++++++++++++++++
+ drivers/dax/pmem/pmem.c | 40 ++++++++++++
+ tools/testing/nvdimm/Kbuild | 6 +
+ 12 files changed, 283 insertions(+), 104 deletions(-)
+ create mode 100644 Documentation/ABI/obsolete/sysfs-class-dax
+ create mode 100644 drivers/dax/pmem/Makefile
+ create mode 100644 drivers/dax/pmem/compat.c
+ rename drivers/dax/{pmem.c => pmem/core.c} (57%)
+ create mode 100644 drivers/dax/pmem/pmem.c
+
+--- /dev/null
++++ b/Documentation/ABI/obsolete/sysfs-class-dax
+@@ -0,0 +1,22 @@
++What: /sys/class/dax/
++Date: May, 2016
++KernelVersion: v4.7
++Contact: linux-nvdimm@lists.01.org
++Description: Device DAX is the device-centric analogue of Filesystem
++ DAX (CONFIG_FS_DAX). It allows memory ranges to be
++ allocated and mapped without need of an intervening file
++ system. Device DAX is strict, precise and predictable.
++ Specifically this interface:
++
++ 1/ Guarantees fault granularity with respect to a given
++ page size (pte, pmd, or pud) set at configuration time.
++
++ 2/ Enforces deterministic behavior by being strict about
++ what fault scenarios are supported.
++
++ The /sys/class/dax/ interface enumerates all the
++ device-dax instances in the system. The ABI is
++ deprecated and will be removed after 2020. It is
++ replaced with the DAX bus interface /sys/bus/dax/ where
++ device-dax instances can be found under
++ /sys/bus/dax/devices/
+--- a/drivers/dax/Kconfig
++++ b/drivers/dax/Kconfig
+@@ -23,12 +23,22 @@ config DEV_DAX
+ config DEV_DAX_PMEM
+ tristate "PMEM DAX: direct access to persistent memory"
+ depends on LIBNVDIMM && NVDIMM_DAX && DEV_DAX
++ depends on m # until we can kill DEV_DAX_PMEM_COMPAT
+ default DEV_DAX
+ help
+ Support raw access to persistent memory. Note that this
+ driver consumes memory ranges allocated and exported by the
+ libnvdimm sub-system.
+
+- Say Y if unsure
++ Say M if unsure
++
++config DEV_DAX_PMEM_COMPAT
++ tristate "PMEM DAX: support the deprecated /sys/class/dax interface"
++ depends on DEV_DAX_PMEM
++ default DEV_DAX_PMEM
++ help
++ Older versions of the libdaxctl library expect to find all
++ device-dax instances under /sys/class/dax. If libdaxctl in
++ your distribution is older than v58 say M, otherwise say N.
+
+ endif
+--- a/drivers/dax/Makefile
++++ b/drivers/dax/Makefile
+@@ -1,8 +1,8 @@
+ obj-$(CONFIG_DAX) += dax.o
+ obj-$(CONFIG_DEV_DAX) += device_dax.o
+-obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem.o
+
+ dax-y := super.o
+ dax-y += bus.o
+-dax_pmem-y := pmem.o
+ device_dax-y := device.o
++
++obj-y += pmem/
+--- a/drivers/dax/bus.c
++++ b/drivers/dax/bus.c
+@@ -9,6 +9,8 @@
+ #include "dax-private.h"
+ #include "bus.h"
+
++static struct class *dax_class;
++
+ static DEFINE_MUTEX(dax_bus_lock);
+
+ #define DAX_NAME_LEN 30
+@@ -310,8 +312,8 @@ static void unregister_dev_dax(void *dev
+ put_device(dev);
+ }
+
+-struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id,
+- struct dev_pagemap *pgmap)
++struct dev_dax *__devm_create_dev_dax(struct dax_region *dax_region, int id,
++ struct dev_pagemap *pgmap, enum dev_dax_subsys subsys)
+ {
+ struct device *parent = dax_region->dev;
+ struct dax_device *dax_dev;
+@@ -350,7 +352,10 @@ struct dev_dax *devm_create_dev_dax(stru
+
+ inode = dax_inode(dax_dev);
+ dev->devt = inode->i_rdev;
+- dev->bus = &dax_bus_type;
++ if (subsys == DEV_DAX_BUS)
++ dev->bus = &dax_bus_type;
++ else
++ dev->class = dax_class;
+ dev->parent = parent;
+ dev->groups = dax_attribute_groups;
+ dev->release = dev_dax_release;
+@@ -374,7 +379,7 @@ struct dev_dax *devm_create_dev_dax(stru
+
+ return ERR_PTR(rc);
+ }
+-EXPORT_SYMBOL_GPL(devm_create_dev_dax);
++EXPORT_SYMBOL_GPL(__devm_create_dev_dax);
+
+ static int match_always_count;
+
+@@ -407,6 +412,7 @@ EXPORT_SYMBOL_GPL(__dax_driver_register)
+
+ void dax_driver_unregister(struct dax_device_driver *dax_drv)
+ {
++ struct device_driver *drv = &dax_drv->drv;
+ struct dax_id *dax_id, *_id;
+
+ mutex_lock(&dax_bus_lock);
+@@ -416,15 +422,28 @@ void dax_driver_unregister(struct dax_de
+ kfree(dax_id);
+ }
+ mutex_unlock(&dax_bus_lock);
++ driver_unregister(drv);
+ }
+ EXPORT_SYMBOL_GPL(dax_driver_unregister);
+
+ int __init dax_bus_init(void)
+ {
+- return bus_register(&dax_bus_type);
++ int rc;
++
++ if (IS_ENABLED(CONFIG_DEV_DAX_PMEM_COMPAT)) {
++ dax_class = class_create(THIS_MODULE, "dax");
++ if (IS_ERR(dax_class))
++ return PTR_ERR(dax_class);
++ }
++
++ rc = bus_register(&dax_bus_type);
++ if (rc)
++ class_destroy(dax_class);
++ return rc;
+ }
+
+ void __exit dax_bus_exit(void)
+ {
+ bus_unregister(&dax_bus_type);
++ class_destroy(dax_class);
+ }
+--- a/drivers/dax/bus.h
++++ b/drivers/dax/bus.h
+@@ -2,7 +2,8 @@
+ /* Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved. */
+ #ifndef __DAX_BUS_H__
+ #define __DAX_BUS_H__
+-struct device;
++#include <linux/device.h>
++
+ struct dev_dax;
+ struct resource;
+ struct dax_device;
+@@ -10,8 +11,23 @@ struct dax_region;
+ void dax_region_put(struct dax_region *dax_region);
+ struct dax_region *alloc_dax_region(struct device *parent, int region_id,
+ struct resource *res, unsigned int align, unsigned long flags);
+-struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id,
+- struct dev_pagemap *pgmap);
++
++enum dev_dax_subsys {
++ DEV_DAX_BUS,
++ DEV_DAX_CLASS,
++};
++
++struct dev_dax *__devm_create_dev_dax(struct dax_region *dax_region, int id,
++ struct dev_pagemap *pgmap, enum dev_dax_subsys subsys);
++
++static inline struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region,
++ int id, struct dev_pagemap *pgmap)
++{
++ return __devm_create_dev_dax(dax_region, id, pgmap, DEV_DAX_BUS);
++}
++
++/* to be deleted when DEV_DAX_CLASS is removed */
++struct dev_dax *__dax_pmem_probe(struct device *dev, enum dev_dax_subsys subsys);
+
+ struct dax_device_driver {
+ struct device_driver drv;
+@@ -26,6 +42,10 @@ int __dax_driver_register(struct dax_dev
+ void dax_driver_unregister(struct dax_device_driver *dax_drv);
+ void kill_dev_dax(struct dev_dax *dev_dax);
+
++#if IS_ENABLED(CONFIG_DEV_DAX_PMEM_COMPAT)
++int dev_dax_probe(struct device *dev);
++#endif
++
+ /*
+ * While run_dax() is potentially a generic operation that could be
+ * defined in include/linux/dax.h we don't want to grow any users
+--- a/drivers/dax/device.c
++++ b/drivers/dax/device.c
+@@ -456,7 +456,7 @@ static void dev_dax_kill(void *dev_dax)
+ kill_dev_dax(dev_dax);
+ }
+
+-static int dev_dax_probe(struct device *dev)
++int dev_dax_probe(struct device *dev)
+ {
+ struct dev_dax *dev_dax = to_dev_dax(dev);
+ struct dax_device *dax_dev = dev_dax->dax_dev;
+@@ -496,7 +496,11 @@ static int dev_dax_probe(struct device *
+ cdev = inode->i_cdev;
+ cdev_init(cdev, &dax_fops);
+
+- cdev->owner = dev->driver->owner;
++ if (dev->class) {
++ /* for the CONFIG_DEV_DAX_PMEM_COMPAT case */
++ cdev->owner = dev->parent->driver->owner;
++ } else
++ cdev->owner = dev->driver->owner;
+ cdev_set_parent(cdev, &dev->kobj);
+ rc = cdev_add(cdev, dev->devt, 1);
+ if (rc)
+@@ -509,6 +513,7 @@ static int dev_dax_probe(struct device *
+ run_dax(dax_dev);
+ return devm_add_action_or_reset(dev, dev_dax_kill, dev_dax);
+ }
++EXPORT_SYMBOL_GPL(dev_dax_probe);
+
+ static int dev_dax_remove(struct device *dev)
+ {
+--- a/drivers/dax/pmem.c
++++ /dev/null
+@@ -1,90 +0,0 @@
+-/*
+- * Copyright(c) 2016 Intel Corporation. All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of version 2 of the GNU General Public License as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * General Public License for more details.
+- */
+-#include <linux/percpu-refcount.h>
+-#include <linux/memremap.h>
+-#include <linux/module.h>
+-#include <linux/pfn_t.h>
+-#include "../nvdimm/pfn.h"
+-#include "../nvdimm/nd.h"
+-#include "bus.h"
+-
+-static int dax_pmem_probe(struct device *dev)
+-{
+- struct resource res;
+- int rc, id, region_id;
+- resource_size_t offset;
+- struct nd_pfn_sb *pfn_sb;
+- struct dev_dax *dev_dax;
+- struct nd_namespace_io *nsio;
+- struct dax_region *dax_region;
+- struct dev_pagemap pgmap = { 0 };
+- struct nd_namespace_common *ndns;
+- struct nd_dax *nd_dax = to_nd_dax(dev);
+- struct nd_pfn *nd_pfn = &nd_dax->nd_pfn;
+-
+- ndns = nvdimm_namespace_common_probe(dev);
+- if (IS_ERR(ndns))
+- return PTR_ERR(ndns);
+- nsio = to_nd_namespace_io(&ndns->dev);
+-
+- /* parse the 'pfn' info block via ->rw_bytes */
+- rc = devm_nsio_enable(dev, nsio);
+- if (rc)
+- return rc;
+- rc = nvdimm_setup_pfn(nd_pfn, &pgmap);
+- if (rc)
+- return rc;
+- devm_nsio_disable(dev, nsio);
+-
+- /* reserve the metadata area, device-dax will reserve the data */
+- pfn_sb = nd_pfn->pfn_sb;
+- offset = le64_to_cpu(pfn_sb->dataoff);
+- if (!devm_request_mem_region(dev, nsio->res.start, offset,
+- dev_name(&ndns->dev))) {
+- dev_warn(dev, "could not reserve metadata\n");
+- return -EBUSY;
+- }
+-
+- rc = sscanf(dev_name(&ndns->dev), "namespace%d.%d", &region_id, &id);
+- if (rc != 2)
+- return -EINVAL;
+-
+- /* adjust the dax_region resource to the start of data */
+- memcpy(&res, &pgmap.res, sizeof(res));
+- res.start += offset;
+- dax_region = alloc_dax_region(dev, region_id, &res,
+- le32_to_cpu(pfn_sb->align), PFN_DEV|PFN_MAP);
+- if (!dax_region)
+- return -ENOMEM;
+-
+- dev_dax = devm_create_dev_dax(dax_region, id, &pgmap);
+-
+- /* child dev_dax instances now own the lifetime of the dax_region */
+- dax_region_put(dax_region);
+-
+- return PTR_ERR_OR_ZERO(dev_dax);
+-}
+-
+-static struct nd_device_driver dax_pmem_driver = {
+- .probe = dax_pmem_probe,
+- .drv = {
+- .name = "dax_pmem",
+- },
+- .type = ND_DRIVER_DAX_PMEM,
+-};
+-
+-module_nd_driver(dax_pmem_driver);
+-
+-MODULE_LICENSE("GPL v2");
+-MODULE_AUTHOR("Intel Corporation");
+-MODULE_ALIAS_ND_DEVICE(ND_DEVICE_DAX_PMEM);
+--- /dev/null
++++ b/drivers/dax/pmem/Makefile
+@@ -0,0 +1,7 @@
++obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem.o
++obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem_core.o
++obj-$(CONFIG_DEV_DAX_PMEM_COMPAT) += dax_pmem_compat.o
++
++dax_pmem-y := pmem.o
++dax_pmem_core-y := core.o
++dax_pmem_compat-y := compat.o
+--- /dev/null
++++ b/drivers/dax/pmem/compat.c
+@@ -0,0 +1,73 @@
++// SPDX-License-Identifier: GPL-2.0
++/* Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved. */
++#include <linux/percpu-refcount.h>
++#include <linux/memremap.h>
++#include <linux/module.h>
++#include <linux/pfn_t.h>
++#include <linux/nd.h>
++#include "../bus.h"
++
++/* we need the private definitions to implement compat suport */
++#include "../dax-private.h"
++
++static int dax_pmem_compat_probe(struct device *dev)
++{
++ struct dev_dax *dev_dax = __dax_pmem_probe(dev, DEV_DAX_CLASS);
++ int rc;
++
++ if (IS_ERR(dev_dax))
++ return PTR_ERR(dev_dax);
++
++ if (!devres_open_group(&dev_dax->dev, dev_dax, GFP_KERNEL))
++ return -ENOMEM;
++
++ device_lock(&dev_dax->dev);
++ rc = dev_dax_probe(&dev_dax->dev);
++ device_unlock(&dev_dax->dev);
++
++ devres_close_group(&dev_dax->dev, dev_dax);
++ if (rc)
++ devres_release_group(&dev_dax->dev, dev_dax);
++
++ return rc;
++}
++
++static int dax_pmem_compat_release(struct device *dev, void *data)
++{
++ device_lock(dev);
++ devres_release_group(dev, to_dev_dax(dev));
++ device_unlock(dev);
++
++ return 0;
++}
++
++static int dax_pmem_compat_remove(struct device *dev)
++{
++ device_for_each_child(dev, NULL, dax_pmem_compat_release);
++ return 0;
++}
++
++static struct nd_device_driver dax_pmem_compat_driver = {
++ .probe = dax_pmem_compat_probe,
++ .remove = dax_pmem_compat_remove,
++ .drv = {
++ .name = "dax_pmem_compat",
++ },
++ .type = ND_DRIVER_DAX_PMEM,
++};
++
++static int __init dax_pmem_compat_init(void)
++{
++ return nd_driver_register(&dax_pmem_compat_driver);
++}
++module_init(dax_pmem_compat_init);
++
++static void __exit dax_pmem_compat_exit(void)
++{
++ driver_unregister(&dax_pmem_compat_driver.drv);
++}
++module_exit(dax_pmem_compat_exit);
++
++MODULE_LICENSE("GPL v2");
++MODULE_AUTHOR("Intel Corporation");
++MODULE_ALIAS_ND_DEVICE(ND_DEVICE_DAX_PMEM);
+--- /dev/null
++++ b/drivers/dax/pmem/core.c
+@@ -0,0 +1,69 @@
++// SPDX-License-Identifier: GPL-2.0
++/* Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved. */
++#include <linux/memremap.h>
++#include <linux/module.h>
++#include <linux/pfn_t.h>
++#include "../../nvdimm/pfn.h"
++#include "../../nvdimm/nd.h"
++#include "../bus.h"
++
++struct dev_dax *__dax_pmem_probe(struct device *dev, enum dev_dax_subsys subsys)
++{
++ struct resource res;
++ int rc, id, region_id;
++ resource_size_t offset;
++ struct nd_pfn_sb *pfn_sb;
++ struct dev_dax *dev_dax;
++ struct nd_namespace_io *nsio;
++ struct dax_region *dax_region;
++ struct dev_pagemap pgmap = { 0 };
++ struct nd_namespace_common *ndns;
++ struct nd_dax *nd_dax = to_nd_dax(dev);
++ struct nd_pfn *nd_pfn = &nd_dax->nd_pfn;
++
++ ndns = nvdimm_namespace_common_probe(dev);
++ if (IS_ERR(ndns))
++ return ERR_CAST(ndns);
++ nsio = to_nd_namespace_io(&ndns->dev);
++
++ /* parse the 'pfn' info block via ->rw_bytes */
++ rc = devm_nsio_enable(dev, nsio);
++ if (rc)
++ return ERR_PTR(rc);
++ rc = nvdimm_setup_pfn(nd_pfn, &pgmap);
++ if (rc)
++ return ERR_PTR(rc);
++ devm_nsio_disable(dev, nsio);
++
++ /* reserve the metadata area, device-dax will reserve the data */
++ pfn_sb = nd_pfn->pfn_sb;
++ offset = le64_to_cpu(pfn_sb->dataoff);
++ if (!devm_request_mem_region(dev, nsio->res.start, offset,
++ dev_name(&ndns->dev))) {
++ dev_warn(dev, "could not reserve metadata\n");
++ return ERR_PTR(-EBUSY);
++ }
++
++ rc = sscanf(dev_name(&ndns->dev), "namespace%d.%d", &region_id, &id);
++ if (rc != 2)
++ return ERR_PTR(-EINVAL);
++
++ /* adjust the dax_region resource to the start of data */
++ memcpy(&res, &pgmap.res, sizeof(res));
++ res.start += offset;
++ dax_region = alloc_dax_region(dev, region_id, &res,
++ le32_to_cpu(pfn_sb->align), PFN_DEV|PFN_MAP);
++ if (!dax_region)
++ return ERR_PTR(-ENOMEM);
++
++ dev_dax = __devm_create_dev_dax(dax_region, id, &pgmap, subsys);
++
++ /* child dev_dax instances now own the lifetime of the dax_region */
++ dax_region_put(dax_region);
++
++ return dev_dax;
++}
++EXPORT_SYMBOL_GPL(__dax_pmem_probe);
++
++MODULE_LICENSE("GPL v2");
++MODULE_AUTHOR("Intel Corporation");
+--- /dev/null
++++ b/drivers/dax/pmem/pmem.c
+@@ -0,0 +1,40 @@
++// SPDX-License-Identifier: GPL-2.0
++/* Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved. */
++#include <linux/percpu-refcount.h>
++#include <linux/memremap.h>
++#include <linux/module.h>
++#include <linux/pfn_t.h>
++#include <linux/nd.h>
++#include "../bus.h"
++
++static int dax_pmem_probe(struct device *dev)
++{
++ return PTR_ERR_OR_ZERO(__dax_pmem_probe(dev, DEV_DAX_BUS));
++}
++
++static struct nd_device_driver dax_pmem_driver = {
++ .probe = dax_pmem_probe,
++ .drv = {
++ .name = "dax_pmem",
++ },
++ .type = ND_DRIVER_DAX_PMEM,
++};
++
++static int __init dax_pmem_init(void)
++{
++ return nd_driver_register(&dax_pmem_driver);
++}
++module_init(dax_pmem_init);
++
++static void __exit dax_pmem_exit(void)
++{
++ driver_unregister(&dax_pmem_driver.drv);
++}
++module_exit(dax_pmem_exit);
++
++MODULE_LICENSE("GPL v2");
++MODULE_AUTHOR("Intel Corporation");
++#if !IS_ENABLED(CONFIG_DEV_DAX_PMEM_COMPAT)
++/* For compat builds, don't load this module by default */
++MODULE_ALIAS_ND_DEVICE(ND_DEVICE_DAX_PMEM);
++#endif
+--- a/tools/testing/nvdimm/Kbuild
++++ b/tools/testing/nvdimm/Kbuild
+@@ -34,6 +34,8 @@ obj-$(CONFIG_DAX) += dax.o
+ endif
+ obj-$(CONFIG_DEV_DAX) += device_dax.o
+ obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem.o
++obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem_core.o
++obj-$(CONFIG_DEV_DAX_PMEM_COMPAT) += dax_pmem_compat.o
+
+ nfit-y := $(ACPI_SRC)/core.o
+ nfit-y += $(ACPI_SRC)/intel.o
+@@ -64,7 +66,9 @@ device_dax-y += dax-dev.o
+ device_dax-y += device_dax_test.o
+ device_dax-y += config_check.o
+
+-dax_pmem-y := $(DAX_SRC)/pmem.o
++dax_pmem-y := $(DAX_SRC)/pmem/pmem.o
++dax_pmem_core-y := $(DAX_SRC)/pmem/core.o
++dax_pmem_compat-y := $(DAX_SRC)/pmem/compat.o
+ dax_pmem-y += config_check.o
+
+ libnvdimm-y := $(NVDIMM_SRC)/core.o
diff --git a/patches.suse/0001-device-dax-Auto-bind-device-after-successful-new_id.patch b/patches.suse/0001-device-dax-Auto-bind-device-after-successful-new_id.patch
new file mode 100644
index 0000000000..9ac702ed05
--- /dev/null
+++ b/patches.suse/0001-device-dax-Auto-bind-device-after-successful-new_id.patch
@@ -0,0 +1,91 @@
+From 664525b2d84abca1074c9546654ae9689de8a818 Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Thu, 24 Jan 2019 13:12:04 -0800
+Subject: [PATCH] device-dax: Auto-bind device after successful new_id
+Git-commit: 664525b2d84abca1074c9546654ae9689de8a818
+Patch-mainline: v5.1-rc1
+References: jsc#SLE-5340
+
+The typical 'new_id' attribute behavior is to immediately attach a
+device to its driver after a new device-id is added. Implement this
+behavior for the dax bus.
+
+Reported-by: Alexander Duyck <alexander.h.duyck@linux.intel.com>
+Reported-by: Brice Goglin <Brice.Goglin@inria.fr>
+Cc: Dave Hansen <dave.hansen@linux.intel.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ drivers/dax/bus.c | 24 ++++++++++++++++++------
+ 1 file changed, 18 insertions(+), 6 deletions(-)
+
+diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c
+index c620ad52d7e5..a410154d75fb 100644
+--- a/drivers/dax/bus.c
++++ b/drivers/dax/bus.c
+@@ -57,8 +57,13 @@ static int dax_match_id(struct dax_device_driver *dax_drv, struct device *dev)
+ return match;
+ }
+
++enum id_action {
++ ID_REMOVE,
++ ID_ADD,
++};
++
+ static ssize_t do_id_store(struct device_driver *drv, const char *buf,
+- size_t count, bool add)
++ size_t count, enum id_action action)
+ {
+ struct dax_device_driver *dax_drv = to_dax_drv(drv);
+ unsigned int region_id, id;
+@@ -77,7 +82,7 @@ static ssize_t do_id_store(struct device_driver *drv, const char *buf,
+ mutex_lock(&dax_bus_lock);
+ dax_id = __dax_match_id(dax_drv, buf);
+ if (!dax_id) {
+- if (add) {
++ if (action == ID_ADD) {
+ dax_id = kzalloc(sizeof(*dax_id), GFP_KERNEL);
+ if (dax_id) {
+ strncpy(dax_id->dev_name, buf, DAX_NAME_LEN);
+@@ -86,26 +91,33 @@ static ssize_t do_id_store(struct device_driver *drv, const char *buf,
+ rc = -ENOMEM;
+ } else
+ /* nothing to remove */;
+- } else if (!add) {
++ } else if (action == ID_REMOVE) {
+ list_del(&dax_id->list);
+ kfree(dax_id);
+ } else
+ /* dax_id already added */;
+ mutex_unlock(&dax_bus_lock);
+- return rc;
++
++ if (rc < 0)
++ return rc;
++ if (action == ID_ADD)
++ rc = driver_attach(drv);
++ if (rc)
++ return rc;
++ return count;
+ }
+
+ static ssize_t new_id_store(struct device_driver *drv, const char *buf,
+ size_t count)
+ {
+- return do_id_store(drv, buf, count, true);
++ return do_id_store(drv, buf, count, ID_ADD);
+ }
+ static DRIVER_ATTR_WO(new_id);
+
+ static ssize_t remove_id_store(struct device_driver *drv, const char *buf,
+ size_t count)
+ {
+- return do_id_store(drv, buf, count, false);
++ return do_id_store(drv, buf, count, ID_REMOVE);
+ }
+ static DRIVER_ATTR_WO(remove_id);
+
+--
+2.12.3
+
diff --git a/patches.suse/0001-device-dax-Hotplug-persistent-memory-for-use-like-no.patch b/patches.suse/0001-device-dax-Hotplug-persistent-memory-for-use-like-no.patch
new file mode 100644
index 0000000000..6e2ebbcfdd
--- /dev/null
+++ b/patches.suse/0001-device-dax-Hotplug-persistent-memory-for-use-like-no.patch
@@ -0,0 +1,259 @@
+From c221c0b0308fd01d9fb33a16f64d2fd95f8830a4 Mon Sep 17 00:00:00 2001
+From: Dave Hansen <dave.hansen@linux.intel.com>
+Date: Mon, 25 Feb 2019 10:57:40 -0800
+Subject: [PATCH] device-dax: "Hotplug" persistent memory for use like normal
+ RAM
+Git-commit: c221c0b0308fd01d9fb33a16f64d2fd95f8830a4
+Patch-mainline: v5.1-rc1
+References: jsc#SLE-5340
+
+This is intended for use with NVDIMMs that are physically persistent
+(physically like flash) so that they can be used as a cost-effective
+RAM replacement. Intel Optane DC persistent memory is one
+implementation of this kind of NVDIMM.
+
+Currently, a persistent memory region is "owned" by a device driver,
+either the "Direct DAX" or "Filesystem DAX" drivers. These drivers
+allow applications to explicitly use persistent memory, generally
+by being modified to use special, new libraries. (DIMM-based
+persistent memory hardware/software is described in great detail
+Here: Documentation/nvdimm/nvdimm.txt).
+
+However, this limits persistent memory use to applications which
+*have* been modified. To make it more broadly usable, this driver
+"hotplugs" memory into the kernel, to be managed and used just like
+normal RAM would be.
+
+To make this work, management software must remove the device from
+being controlled by the "Device DAX" infrastructure:
+
+ echo dax0.0 > /sys/bus/dax/drivers/device_dax/unbind
+
+and then tell the new driver that it can bind to the device:
+
+ echo dax0.0 > /sys/bus/dax/drivers/kmem/new_id
+
+After this, there will be a number of new memory sections visible
+in sysfs that can be onlined, or that may get onlined by existing
+udev-initiated memory hotplug rules.
+
+This rebinding procedure is currently a one-way trip. Once memory
+is bound to "kmem", it's there permanently and can not be
+unbound and assigned back to device_dax.
+
+The kmem driver will never bind to a dax device unless the device
+is *explicitly* bound to the driver. There are two reasons for
+This: One, since it is a one-way trip, it can not be undone if
+bound incorrectly. Two, the kmem driver destroys data on the
+device. Think of if you had good data on a pmem device. It
+would be catastrophic if you compile-in "kmem", but leave out
+the "device_dax" driver. kmem would take over the device and
+write volatile data all over your good data.
+
+This inherits any existing NUMA information for the newly-added
+memory from the persistent memory device that came from the
+firmware. On Intel platforms, the firmware has guarantees that
+require each socket's persistent memory to be in a separate
+memory-only NUMA node. That means that this patch is not expected
+to create NUMA nodes, but will simply hotplug memory into existing
+nodes.
+
+Because NUMA nodes are created, the existing NUMA APIs and tools
+are sufficient to create policies for applications or memory areas
+to have affinity for or an aversion to using this memory.
+
+There is currently some metadata at the beginning of pmem regions.
+The section-size memory hotplug restrictions, plus this small
+reserved area can cause the "loss" of a section or two of capacity.
+This should be fixable in follow-on patches. But, as a first step,
+losing 256MB of memory (worst case) out of hundreds of gigabytes
+is a good tradeoff vs. the required code to fix this up precisely.
+This calculation is also the reason we export
+memory_block_size_bytes().
+
+Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
+Reviewed-by: Dan Williams <dan.j.williams@intel.com>
+Reviewed-by: Keith Busch <keith.busch@intel.com>
+Cc: Dave Jiang <dave.jiang@intel.com>
+Cc: Ross Zwisler <zwisler@kernel.org>
+Cc: Vishal Verma <vishal.l.verma@intel.com>
+Cc: Tom Lendacky <thomas.lendacky@amd.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: linux-nvdimm@lists.01.org
+Cc: linux-kernel@vger.kernel.org
+Cc: linux-mm@kvack.org
+Cc: Huang Ying <ying.huang@intel.com>
+Cc: Fengguang Wu <fengguang.wu@intel.com>
+Cc: Borislav Petkov <bp@suse.de>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Yaowei Bai <baiyaowei@cmss.chinamobile.com>
+Cc: Takashi Iwai <tiwai@suse.de>
+Cc: Jerome Glisse <jglisse@redhat.com>
+Reviewed-by: Vishal Verma <vishal.l.verma@intel.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ drivers/base/memory.c | 1
+ drivers/dax/Kconfig | 16 +++++++
+ drivers/dax/Makefile | 1
+ drivers/dax/kmem.c | 108 ++++++++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 126 insertions(+)
+ create mode 100644 drivers/dax/kmem.c
+
+--- a/drivers/base/memory.c
++++ b/drivers/base/memory.c
+@@ -87,6 +87,7 @@ unsigned long __weak memory_block_size_b
+ {
+ return MIN_MEMORY_BLOCK_SIZE;
+ }
++EXPORT_SYMBOL_GPL(memory_block_size_bytes);
+
+ static unsigned long get_memory_block_size(void)
+ {
+--- a/drivers/dax/Kconfig
++++ b/drivers/dax/Kconfig
+@@ -32,6 +32,22 @@ config DEV_DAX_PMEM
+
+ Say M if unsure
+
++config DEV_DAX_KMEM
++ tristate "KMEM DAX: volatile-use of persistent memory"
++ default DEV_DAX
++ depends on DEV_DAX
++ depends on MEMORY_HOTPLUG # for add_memory() and friends
++ help
++ Support access to persistent memory as if it were RAM. This
++ allows easier use of persistent memory by unmodified
++ applications.
++
++ To use this feature, a DAX device must be unbound from the
++ device_dax driver (PMEM DAX) and bound to this kmem driver
++ on each boot.
++
++ Say N if unsure.
++
+ config DEV_DAX_PMEM_COMPAT
+ tristate "PMEM DAX: support the deprecated /sys/class/dax interface"
+ depends on DEV_DAX_PMEM
+--- a/drivers/dax/Makefile
++++ b/drivers/dax/Makefile
+@@ -1,5 +1,6 @@
+ obj-$(CONFIG_DAX) += dax.o
+ obj-$(CONFIG_DEV_DAX) += device_dax.o
++obj-$(CONFIG_DEV_DAX_KMEM) += kmem.o
+
+ dax-y := super.o
+ dax-y += bus.o
+--- /dev/null
++++ b/drivers/dax/kmem.c
+@@ -0,0 +1,108 @@
++// SPDX-License-Identifier: GPL-2.0
++/* Copyright(c) 2016-2019 Intel Corporation. All rights reserved. */
++#include <linux/memremap.h>
++#include <linux/pagemap.h>
++#include <linux/memory.h>
++#include <linux/module.h>
++#include <linux/device.h>
++#include <linux/pfn_t.h>
++#include <linux/slab.h>
++#include <linux/dax.h>
++#include <linux/fs.h>
++#include <linux/mm.h>
++#include <linux/mman.h>
++#include "dax-private.h"
++#include "bus.h"
++
++int dev_dax_kmem_probe(struct device *dev)
++{
++ struct dev_dax *dev_dax = to_dev_dax(dev);
++ struct resource *res = &dev_dax->region->res;
++ resource_size_t kmem_start;
++ resource_size_t kmem_size;
++ resource_size_t kmem_end;
++ struct resource *new_res;
++ int numa_node;
++ int rc;
++
++ /*
++ * Ensure good NUMA information for the persistent memory.
++ * Without this check, there is a risk that slow memory
++ * could be mixed in a node with faster memory, causing
++ * unavoidable performance issues.
++ */
++ numa_node = dev_dax->target_node;
++ if (numa_node < 0) {
++ dev_warn(dev, "rejecting DAX region %pR with invalid node: %d\n",
++ res, numa_node);
++ return -EINVAL;
++ }
++
++ /* Hotplug starting at the beginning of the next block: */
++ kmem_start = ALIGN(res->start, memory_block_size_bytes());
++
++ kmem_size = resource_size(res);
++ /* Adjust the size down to compensate for moving up kmem_start: */
++ kmem_size -= kmem_start - res->start;
++ /* Align the size down to cover only complete blocks: */
++ kmem_size &= ~(memory_block_size_bytes() - 1);
++ kmem_end = kmem_start + kmem_size;
++
++ /* Region is permanently reserved. Hot-remove not yet implemented. */
++ new_res = request_mem_region(kmem_start, kmem_size, dev_name(dev));
++ if (!new_res) {
++ dev_warn(dev, "could not reserve region [%pa-%pa]\n",
++ &kmem_start, &kmem_end);
++ return -EBUSY;
++ }
++
++ /*
++ * Set flags appropriate for System RAM. Leave ..._BUSY clear
++ * so that add_memory() can add a child resource. Do not
++ * inherit flags from the parent since it may set new flags
++ * unknown to us that will break add_memory() below.
++ */
++ new_res->flags = IORESOURCE_SYSTEM_RAM;
++ new_res->name = dev_name(dev);
++
++ rc = add_memory(numa_node, new_res->start, resource_size(new_res));
++ if (rc)
++ return rc;
++
++ return 0;
++}
++
++static int dev_dax_kmem_remove(struct device *dev)
++{
++ /*
++ * Purposely leak the request_mem_region() for the device-dax
++ * range and return '0' to ->remove() attempts. The removal of
++ * the device from the driver always succeeds, but the region
++ * is permanently pinned as reserved by the unreleased
++ * request_mem_region().
++ */
++ return 0;
++}
++
++static struct dax_device_driver device_dax_kmem_driver = {
++ .drv = {
++ .probe = dev_dax_kmem_probe,
++ .remove = dev_dax_kmem_remove,
++ },
++};
++
++static int __init dax_kmem_init(void)
++{
++ return dax_driver_register(&device_dax_kmem_driver);
++}
++
++static void __exit dax_kmem_exit(void)
++{
++ dax_driver_unregister(&device_dax_kmem_driver);
++}
++
++MODULE_AUTHOR("Intel Corporation");
++MODULE_LICENSE("GPL v2");
++module_init(dax_kmem_init);
++module_exit(dax_kmem_exit);
++MODULE_ALIAS_DAX_DEVICE(0);
diff --git a/patches.suse/0001-device-dax-Introduce-bus-driver-model.patch b/patches.suse/0001-device-dax-Introduce-bus-driver-model.patch
new file mode 100644
index 0000000000..76d53276eb
--- /dev/null
+++ b/patches.suse/0001-device-dax-Introduce-bus-driver-model.patch
@@ -0,0 +1,467 @@
+From 9567da0b408a2553d32ca83cba4f1fc5a8aad459 Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Wed, 12 Jul 2017 17:58:21 -0700
+Subject: [PATCH] device-dax: Introduce bus + driver model
+Git-commit: 9567da0b408a2553d32ca83cba4f1fc5a8aad459
+Patch-mainline: v5.1-rc1
+References: jsc#SLE-5340
+
+In support of multiple device-dax instances per device-dax-region and
+allowing the 'kmem' driver to attach to dax-instances instead of the
+current device-node access, convert the dax sub-system from a class to a
+bus. Recall that the kmem driver takes reserved / special purpose
+memories and assigns them to be managed by the core-mm.
+
+Aside from the fact the device-dax instances are registered and probed
+on a bus, two other lifetime-management changes are made:
+
+1/ Delay attaching a cdev until driver probe time
+
+2/ A new run_dax() helper is introduced to allow restoring dax-operation
+ after a kill_dax() event. So, at driver ->probe() time we run_dax()
+ and at ->remove() time we kill_dax() and invalidate all mappings.
+
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ drivers/dax/bus.c | 133 +++++++++++++++++++++++++++++++++++++++++++---
+ drivers/dax/bus.h | 16 +++++
+ drivers/dax/dax-private.h | 6 --
+ drivers/dax/device.c | 95 +++++++++++---------------------
+ drivers/dax/super.c | 40 +++++++++----
+ 5 files changed, 204 insertions(+), 86 deletions(-)
+
+--- a/drivers/dax/bus.c
++++ b/drivers/dax/bus.c
+@@ -6,6 +6,33 @@
+ #include "dax-private.h"
+ #include "bus.h"
+
++static int dax_bus_uevent(struct device *dev, struct kobj_uevent_env *env)
++{
++ /*
++ * We only ever expect to handle device-dax instances, i.e. the
++ * @type argument to MODULE_ALIAS_DAX_DEVICE() is always zero
++ */
++ return add_uevent_var(env, "MODALIAS=" DAX_DEVICE_MODALIAS_FMT, 0);
++}
++
++static int dax_bus_match(struct device *dev, struct device_driver *drv);
++
++static struct bus_type dax_bus_type = {
++ .name = "dax",
++ .uevent = dax_bus_uevent,
++ .match = dax_bus_match,
++};
++
++static int dax_bus_match(struct device *dev, struct device_driver *drv)
++{
++ /*
++ * The drivers that can register on the 'dax' bus are private to
++ * drivers/dax/ so any device and driver on the bus always
++ * match.
++ */
++ return 1;
++}
++
+ /*
+ * Rely on the fact that drvdata is set before the attributes are
+ * registered, and that the attributes are unregistered before drvdata
+@@ -142,11 +169,10 @@ static const struct attribute_group dev_
+ .attrs = dev_dax_attributes,
+ };
+
+-const struct attribute_group *dax_attribute_groups[] = {
++static const struct attribute_group *dax_attribute_groups[] = {
+ &dev_dax_attribute_group,
+ NULL,
+ };
+-EXPORT_SYMBOL_GPL(dax_attribute_groups);
+
+ void kill_dev_dax(struct dev_dax *dev_dax)
+ {
+@@ -158,17 +184,108 @@ void kill_dev_dax(struct dev_dax *dev_da
+ }
+ EXPORT_SYMBOL_GPL(kill_dev_dax);
+
+-void unregister_dev_dax(void *dev)
++static void dev_dax_release(struct device *dev)
+ {
+ struct dev_dax *dev_dax = to_dev_dax(dev);
++ struct dax_region *dax_region = dev_dax->region;
+ struct dax_device *dax_dev = dev_dax->dax_dev;
+- struct inode *inode = dax_inode(dax_dev);
+- struct cdev *cdev = inode->i_cdev;
+
+- dev_dbg(dev, "trace\n");
++ dax_region_put(dax_region);
++ put_dax(dax_dev);
++ kfree(dev_dax);
++}
++
++static void unregister_dev_dax(void *dev)
++{
++ struct dev_dax *dev_dax = to_dev_dax(dev);
++
++ dev_dbg(dev, "%s\n", __func__);
+
+ kill_dev_dax(dev_dax);
+- cdev_device_del(cdev, dev);
++ device_del(dev);
+ put_device(dev);
+ }
+-EXPORT_SYMBOL_GPL(unregister_dev_dax);
++
++struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id)
++{
++ struct device *parent = dax_region->dev;
++ struct dax_device *dax_dev;
++ struct dev_dax *dev_dax;
++ struct inode *inode;
++ struct device *dev;
++ int rc = -ENOMEM;
++
++ if (id < 0)
++ return ERR_PTR(-EINVAL);
++
++ dev_dax = kzalloc(sizeof(*dev_dax), GFP_KERNEL);
++ if (!dev_dax)
++ return ERR_PTR(-ENOMEM);
++
++ /*
++ * No 'host' or dax_operations since there is no access to this
++ * device outside of mmap of the resulting character device.
++ */
++ dax_dev = alloc_dax(dev_dax, NULL, NULL);
++ if (!dax_dev)
++ goto err;
++
++ /* a device_dax instance is dead while the driver is not attached */
++ kill_dax(dax_dev);
++
++ /* from here on we're committed to teardown via dax_dev_release() */
++ dev = &dev_dax->dev;
++ device_initialize(dev);
++
++ dev_dax->dax_dev = dax_dev;
++ dev_dax->region = dax_region;
++ kref_get(&dax_region->kref);
++
++ inode = dax_inode(dax_dev);
++ dev->devt = inode->i_rdev;
++ dev->bus = &dax_bus_type;
++ dev->parent = parent;
++ dev->groups = dax_attribute_groups;
++ dev->release = dev_dax_release;
++ dev_set_name(dev, "dax%d.%d", dax_region->id, id);
++
++ rc = device_add(dev);
++ if (rc) {
++ kill_dev_dax(dev_dax);
++ put_device(dev);
++ return ERR_PTR(rc);
++ }
++
++ rc = devm_add_action_or_reset(dax_region->dev, unregister_dev_dax, dev);
++ if (rc)
++ return ERR_PTR(rc);
++
++ return dev_dax;
++
++ err:
++ kfree(dev_dax);
++
++ return ERR_PTR(rc);
++}
++EXPORT_SYMBOL_GPL(devm_create_dev_dax);
++
++int __dax_driver_register(struct device_driver *drv,
++ struct module *module, const char *mod_name)
++{
++ drv->owner = module;
++ drv->name = mod_name;
++ drv->mod_name = mod_name;
++ drv->bus = &dax_bus_type;
++ return driver_register(drv);
++}
++EXPORT_SYMBOL_GPL(__dax_driver_register);
++
++int __init dax_bus_init(void)
++{
++ return bus_register(&dax_bus_type);
++}
++
++void __exit dax_bus_exit(void)
++{
++ bus_unregister(&dax_bus_type);
++}
+--- a/drivers/dax/bus.h
++++ b/drivers/dax/bus.h
+@@ -11,5 +11,21 @@ void dax_region_put(struct dax_region *d
+ struct dax_region *alloc_dax_region(struct device *parent, int region_id,
+ struct resource *res, unsigned int align, unsigned long flags);
+ struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id);
++int __dax_driver_register(struct device_driver *drv,
++ struct module *module, const char *mod_name);
++#define dax_driver_register(driver) \
++ __dax_driver_register(driver, THIS_MODULE, KBUILD_MODNAME)
+ void kill_dev_dax(struct dev_dax *dev_dax);
++
++/*
++ * While run_dax() is potentially a generic operation that could be
++ * defined in include/linux/dax.h we don't want to grow any users
++ * outside of drivers/dax/
++ */
++void run_dax(struct dax_device *dax_dev);
++
++#define MODULE_ALIAS_DAX_DEVICE(type) \
++ MODULE_ALIAS("dax:t" __stringify(type) "*")
++#define DAX_DEVICE_MODALIAS_FMT "dax:t%d"
++
+ #endif /* __DAX_BUS_H__ */
+--- a/drivers/dax/dax-private.h
++++ b/drivers/dax/dax-private.h
+@@ -20,10 +20,8 @@
+ struct dax_device;
+ struct dax_device *inode_dax(struct inode *inode);
+ struct inode *dax_inode(struct dax_device *dax_dev);
+-
+-/* temporary until devm_create_dax_dev moves to bus.c */
+-extern const struct attribute_group *dax_attribute_groups[];
+-void unregister_dev_dax(void *dev);
++int dax_bus_init(void);
++void dax_bus_exit(void);
+
+ /**
+ * struct dax_region - mapping infrastructure for dax devices
+--- a/drivers/dax/device.c
++++ b/drivers/dax/device.c
+@@ -13,8 +13,6 @@
+ #include "dax-private.h"
+ #include "bus.h"
+
+-static struct class *dax_class;
+-
+ static int check_vma(struct dev_dax *dev_dax, struct vm_area_struct *vma,
+ const char *func)
+ {
+@@ -415,92 +413,65 @@ static const struct file_operations dax_
+ .mmap_supported_flags = MAP_SYNC,
+ };
+
+-static void dev_dax_release(struct device *dev)
++static void dev_dax_cdev_del(void *cdev)
+ {
+- struct dev_dax *dev_dax = to_dev_dax(dev);
+- struct dax_region *dax_region = dev_dax->region;
+- struct dax_device *dax_dev = dev_dax->dax_dev;
++ cdev_del(cdev);
++}
+
+- dax_region_put(dax_region);
+- put_dax(dax_dev);
+- kfree(dev_dax);
++static void dev_dax_kill(void *dev_dax)
++{
++ kill_dev_dax(dev_dax);
+ }
+
+-struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id)
++static int dev_dax_probe(struct device *dev)
+ {
+- struct device *parent = dax_region->dev;
+- struct dax_device *dax_dev;
+- struct dev_dax *dev_dax;
++ struct dev_dax *dev_dax = to_dev_dax(dev);
++ struct dax_device *dax_dev = dev_dax->dax_dev;
+ struct inode *inode;
+- struct device *dev;
+ struct cdev *cdev;
+-
+- dev_dax = kzalloc(sizeof(*dev_dax), GFP_KERNEL);
+- if (!dev_dax)
+- return ERR_PTR(-ENOMEM);
+-
+- /*
+- * No 'host' or dax_operations since there is no access to this
+- * device outside of mmap of the resulting character device.
+- */
+- dax_dev = alloc_dax(dev_dax, NULL, NULL);
+- if (!dax_dev) {
+- rc = -ENOMEM;
+- goto err;
+- }
+-
+- /* from here on we're committed to teardown via dax_dev_release() */
+- dev = &dev_dax->dev;
+- device_initialize(dev);
++ int rc;
+
+ inode = dax_inode(dax_dev);
+ cdev = inode->i_cdev;
+ cdev_init(cdev, &dax_fops);
+- cdev->owner = parent->driver->owner;
+-
+- dev_dax->dax_dev = dax_dev;
+- dev_dax->region = dax_region;
+- kref_get(&dax_region->kref);
+-
+- dev->devt = inode->i_rdev;
+- dev->class = dax_class;
+- dev->parent = parent;
+- dev->groups = dax_attribute_groups;
+- dev->release = dev_dax_release;
+- dev_set_name(dev, "dax%d.%d", dax_region->id, id);
+-
+- rc = cdev_device_add(cdev, dev);
+- if (rc) {
+- kill_dev_dax(dev_dax);
+- put_device(dev);
+- return ERR_PTR(rc);
+- }
+
+- rc = devm_add_action_or_reset(dax_region->dev, unregister_dev_dax, dev);
++ cdev->owner = dev->driver->owner;
++ cdev_set_parent(cdev, &dev->kobj);
++ rc = cdev_add(cdev, dev->devt, 1);
+ if (rc)
+- return ERR_PTR(rc);
++ return rc;
+
+- return dev_dax;
++ rc = devm_add_action_or_reset(dev, dev_dax_cdev_del, cdev);
++ if (rc)
++ return rc;
+
+- err:
+- kfree(dev_dax);
++ run_dax(dax_dev);
++ return devm_add_action_or_reset(dev, dev_dax_kill, dev_dax);
++}
+
+- return ERR_PTR(rc);
++static int dev_dax_remove(struct device *dev)
++{
++ /* all probe actions are unwound by devm */
++ return 0;
+ }
+-EXPORT_SYMBOL_GPL(devm_create_dev_dax);
++
++static struct device_driver device_dax_driver = {
++ .probe = dev_dax_probe,
++ .remove = dev_dax_remove,
++};
+
+ static int __init dax_init(void)
+ {
+- dax_class = class_create(THIS_MODULE, "dax");
+- return PTR_ERR_OR_ZERO(dax_class);
++ return dax_driver_register(&device_dax_driver);
+ }
+
+ static void __exit dax_exit(void)
+ {
+- class_destroy(dax_class);
++ driver_unregister(&device_dax_driver);
+ }
+
+ MODULE_AUTHOR("Intel Corporation");
+ MODULE_LICENSE("GPL v2");
+-subsys_initcall(dax_init);
++module_init(dax_init);
+ module_exit(dax_exit);
++MODULE_ALIAS_DAX_DEVICE(0);
+--- a/drivers/dax/super.c
++++ b/drivers/dax/super.c
+@@ -367,11 +367,15 @@ void kill_dax(struct dax_device *dax_dev
+ spin_lock(&dax_host_lock);
+ hlist_del_init(&dax_dev->list);
+ spin_unlock(&dax_host_lock);
+-
+- dax_dev->private = NULL;
+ }
+ EXPORT_SYMBOL_GPL(kill_dax);
+
++void run_dax(struct dax_device *dax_dev)
++{
++ set_bit(DAXDEV_ALIVE, &dax_dev->flags);
++}
++EXPORT_SYMBOL_GPL(run_dax);
++
+ static struct inode *dax_alloc_inode(struct super_block *sb)
+ {
+ struct dax_device *dax_dev;
+@@ -586,6 +590,8 @@ EXPORT_SYMBOL_GPL(dax_inode);
+
+ void *dax_get_private(struct dax_device *dax_dev)
+ {
++ if (!test_bit(DAXDEV_ALIVE, &dax_dev->flags))
++ return NULL;
+ return dax_dev->private;
+ }
+ EXPORT_SYMBOL_GPL(dax_get_private);
+@@ -599,7 +605,7 @@ static void init_once(void *_dax_dev)
+ inode_init_once(inode);
+ }
+
+-static int __dax_fs_init(void)
++static int dax_fs_init(void)
+ {
+ int rc;
+
+@@ -631,35 +637,45 @@ static int __dax_fs_init(void)
+ return rc;
+ }
+
+-static void __dax_fs_exit(void)
++static void dax_fs_exit(void)
+ {
+ kern_unmount(dax_mnt);
+ unregister_filesystem(&dax_fs_type);
+ kmem_cache_destroy(dax_cache);
+ }
+
+-static int __init dax_fs_init(void)
++static int __init dax_core_init(void)
+ {
+ int rc;
+
+- rc = __dax_fs_init();
++ rc = dax_fs_init();
+ if (rc)
+ return rc;
+
+ rc = alloc_chrdev_region(&dax_devt, 0, MINORMASK+1, "dax");
+ if (rc)
+- __dax_fs_exit();
+- return rc;
++ goto err_chrdev;
++
++ rc = dax_bus_init();
++ if (rc)
++ goto err_bus;
++ return 0;
++
++err_bus:
++ unregister_chrdev_region(dax_devt, MINORMASK+1);
++err_chrdev:
++ dax_fs_exit();
++ return 0;
+ }
+
+-static void __exit dax_fs_exit(void)
++static void __exit dax_core_exit(void)
+ {
+ unregister_chrdev_region(dax_devt, MINORMASK+1);
+ ida_destroy(&dax_minor_ida);
+- __dax_fs_exit();
++ dax_fs_exit();
+ }
+
+ MODULE_AUTHOR("Intel Corporation");
+ MODULE_LICENSE("GPL v2");
+-subsys_initcall(dax_fs_init);
+-module_exit(dax_fs_exit);
++subsys_initcall(dax_core_init);
++module_exit(dax_core_exit);
diff --git a/patches.suse/0001-device-dax-Kill-dax_region-base.patch b/patches.suse/0001-device-dax-Kill-dax_region-base.patch
new file mode 100644
index 0000000000..ae75270f0a
--- /dev/null
+++ b/patches.suse/0001-device-dax-Kill-dax_region-base.patch
@@ -0,0 +1,94 @@
+From 93694f9630b0ed29cda61df58e480dcb34ef52fd Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Wed, 19 Jul 2017 15:57:44 -0700
+Subject: [PATCH] device-dax: Kill dax_region base
+Git-commit: 93694f9630b0ed29cda61df58e480dcb34ef52fd
+Patch-mainline: v5.1-rc1
+References: jsc#SLE-5340
+
+Nothing consumes this attribute of a region and devres otherwise
+remembers the value for de-allocation purposes.
+
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ drivers/dax/dax-private.h | 2 --
+ drivers/dax/device-dax.h | 5 ++---
+ drivers/dax/device.c | 3 +--
+ drivers/dax/pmem.c | 2 +-
+ 4 files changed, 4 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/dax/dax-private.h b/drivers/dax/dax-private.h
+index d1b36a42132f..9b393c218fe4 100644
+--- a/drivers/dax/dax-private.h
++++ b/drivers/dax/dax-private.h
+@@ -19,7 +19,6 @@
+ /**
+ * struct dax_region - mapping infrastructure for dax devices
+ * @id: kernel-wide unique region for a memory range
+- * @base: linear address corresponding to @res
+ * @kref: to pin while other agents have a need to do lookups
+ * @dev: parent device backing this region
+ * @align: allocation and mapping alignment for child dax devices
+@@ -28,7 +27,6 @@
+ */
+ struct dax_region {
+ int id;
+- void *base;
+ struct kref kref;
+ struct device *dev;
+ unsigned int align;
+diff --git a/drivers/dax/device-dax.h b/drivers/dax/device-dax.h
+index 688b051750bd..4f1c69e1b3a2 100644
+--- a/drivers/dax/device-dax.h
++++ b/drivers/dax/device-dax.h
+@@ -17,9 +17,8 @@ struct dev_dax;
+ struct resource;
+ struct dax_region;
+ void dax_region_put(struct dax_region *dax_region);
+-struct dax_region *alloc_dax_region(struct device *parent,
+- int region_id, struct resource *res, unsigned int align,
+- void *addr, unsigned long flags);
++struct dax_region *alloc_dax_region(struct device *parent, int region_id,
++ struct resource *res, unsigned int align, unsigned long flags);
+ struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region,
+ int id, struct resource *res, int count);
+ #endif /* __DEVICE_DAX_H__ */
+diff --git a/drivers/dax/device.c b/drivers/dax/device.c
+index a5a670c1cd58..811c1015194c 100644
+--- a/drivers/dax/device.c
++++ b/drivers/dax/device.c
+@@ -100,7 +100,7 @@ static void dax_region_unregister(void *region)
+ }
+
+ struct dax_region *alloc_dax_region(struct device *parent, int region_id,
+- struct resource *res, unsigned int align, void *addr,
++ struct resource *res, unsigned int align,
+ unsigned long pfn_flags)
+ {
+ struct dax_region *dax_region;
+@@ -130,7 +130,6 @@ struct dax_region *alloc_dax_region(struct device *parent, int region_id,
+ dax_region->id = region_id;
+ dax_region->align = align;
+ dax_region->dev = parent;
+- dax_region->base = addr;
+ if (sysfs_create_groups(&parent->kobj, dax_region_attribute_groups)) {
+ kfree(dax_region);
+ return NULL;
+diff --git a/drivers/dax/pmem.c b/drivers/dax/pmem.c
+index 2c1f459c0c63..72a76105eb02 100644
+--- a/drivers/dax/pmem.c
++++ b/drivers/dax/pmem.c
+@@ -125,7 +125,7 @@ static int dax_pmem_probe(struct device *dev)
+ return -EINVAL;
+
+ dax_region = alloc_dax_region(dev, region_id, &res,
+- le32_to_cpu(pfn_sb->align), addr, PFN_DEV|PFN_MAP);
++ le32_to_cpu(pfn_sb->align), PFN_DEV|PFN_MAP);
+ if (!dax_region)
+ return -ENOMEM;
+
+--
+2.12.3
+
diff --git a/patches.suse/0001-device-dax-Kill-dax_region-ida.patch b/patches.suse/0001-device-dax-Kill-dax_region-ida.patch
new file mode 100644
index 0000000000..a2d0864aad
--- /dev/null
+++ b/patches.suse/0001-device-dax-Kill-dax_region-ida.patch
@@ -0,0 +1,114 @@
+From 21b9e979501fdb5f6797193d70428a2b00bd5247 Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Wed, 19 Jul 2017 14:55:26 -0700
+Subject: [PATCH] device-dax: Kill dax_region ida
+Git-commit: 21b9e979501fdb5f6797193d70428a2b00bd5247
+Patch-mainline: v5.1-rc1
+References: jsc#SLE-5340
+
+Commit bbb3be170ac2 "device-dax: fix sysfs duplicate warnings" arranged
+for passing a dax instance-id to devm_create_dax_dev(), rather than
+generating one internally. Remove the dax_region ida and related code.
+
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ drivers/dax/dax-private.h | 3 ---
+ drivers/dax/device.c | 24 +++---------------------
+ 2 files changed, 3 insertions(+), 24 deletions(-)
+
+diff --git a/drivers/dax/dax-private.h b/drivers/dax/dax-private.h
+index b6fc4f04636d..d1b36a42132f 100644
+--- a/drivers/dax/dax-private.h
++++ b/drivers/dax/dax-private.h
+@@ -28,7 +28,6 @@
+ */
+ struct dax_region {
+ int id;
+- struct ida ida;
+ void *base;
+ struct kref kref;
+ struct device *dev;
+@@ -42,7 +41,6 @@ struct dax_region {
+ * @region - parent region
+ * @dax_dev - core dax functionality
+ * @dev - device core
+- * @id - child id in the region
+ * @num_resources - number of physical address extents in this device
+ * @res - array of physical address ranges
+ */
+@@ -50,7 +48,6 @@ struct dev_dax {
+ struct dax_region *region;
+ struct dax_device *dax_dev;
+ struct device dev;
+- int id;
+ int num_resources;
+ struct resource res[0];
+ };
+diff --git a/drivers/dax/device.c b/drivers/dax/device.c
+index 948806e57cee..a5a670c1cd58 100644
+--- a/drivers/dax/device.c
++++ b/drivers/dax/device.c
+@@ -128,7 +128,6 @@ struct dax_region *alloc_dax_region(struct device *parent, int region_id,
+ dax_region->pfn_flags = pfn_flags;
+ kref_init(&dax_region->kref);
+ dax_region->id = region_id;
+- ida_init(&dax_region->ida);
+ dax_region->align = align;
+ dax_region->dev = parent;
+ dax_region->base = addr;
+@@ -582,8 +581,6 @@ static void dev_dax_release(struct device *dev)
+ struct dax_region *dax_region = dev_dax->region;
+ struct dax_device *dax_dev = dev_dax->dax_dev;
+
+- if (dev_dax->id >= 0)
+- ida_simple_remove(&dax_region->ida, dev_dax->id);
+ dax_region_put(dax_region);
+ put_dax(dax_dev);
+ kfree(dev_dax);
+@@ -642,19 +639,7 @@ struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region,
+ }
+
+ if (i < count)
+- goto err_id;
+-
+- if (id < 0) {
+- id = ida_simple_get(&dax_region->ida, 0, 0, GFP_KERNEL);
+- dev_dax->id = id;
+- if (id < 0) {
+- rc = id;
+- goto err_id;
+- }
+- } else {
+- /* region provider owns @id lifetime */
+- dev_dax->id = -1;
+- }
++ goto err;
+
+ /*
+ * No 'host' or dax_operations since there is no access to this
+@@ -663,7 +648,7 @@ struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region,
+ dax_dev = alloc_dax(dev_dax, NULL, NULL);
+ if (!dax_dev) {
+ rc = -ENOMEM;
+- goto err_dax;
++ goto err;
+ }
+
+ /* from here on we're committed to teardown via dax_dev_release() */
+@@ -700,10 +685,7 @@ struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region,
+
+ return dev_dax;
+
+- err_dax:
+- if (dev_dax->id >= 0)
+- ida_simple_remove(&dax_region->ida, dev_dax->id);
+- err_id:
++ err:
+ kfree(dev_dax);
+
+ return ERR_PTR(rc);
+--
+2.12.3
+
diff --git a/patches.suse/0001-device-dax-Move-resource-pinning-mapping-into-the-co.patch b/patches.suse/0001-device-dax-Move-resource-pinning-mapping-into-the-co.patch
new file mode 100644
index 0000000000..fc583c61a0
--- /dev/null
+++ b/patches.suse/0001-device-dax-Move-resource-pinning-mapping-into-the-co.patch
@@ -0,0 +1,310 @@
+From 89ec9f2cfa36cc5fca2fb445ed221bb9add7b536 Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Mon, 29 Oct 2018 15:52:42 -0700
+Subject: [PATCH] device-dax: Move resource pinning+mapping into the common
+ driver
+Git-commit: 89ec9f2cfa36cc5fca2fb445ed221bb9add7b536
+Patch-mainline: v5.1-rc1
+References: jsc#SLE-5340
+
+Move the responsibility of calling devm_request_resource() and
+devm_memremap_pages() into the common device-dax driver. This is another
+preparatory step to allowing an alternate personality driver for a
+device-dax range.
+
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+---
+ drivers/dax/bus.c | 6 ++-
+ drivers/dax/bus.h | 3 +
+ drivers/dax/dax-private.h | 9 ++++
+ drivers/dax/device.c | 61 +++++++++++++++++++++++++++++++
+ drivers/dax/pmem.c | 90 +++++++---------------------------------------
+ 5 files changed, 90 insertions(+), 79 deletions(-)
+
+--- a/drivers/dax/bus.c
++++ b/drivers/dax/bus.c
+@@ -1,5 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /* Copyright(c) 2017-2018 Intel Corporation. All rights reserved. */
++#include <linux/memremap.h>
+ #include <linux/device.h>
+ #include <linux/slab.h>
+ #include <linux/dax.h>
+@@ -206,7 +207,8 @@ static void unregister_dev_dax(void *dev
+ put_device(dev);
+ }
+
+-struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id)
++struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id,
++ struct dev_pagemap *pgmap)
+ {
+ struct device *parent = dax_region->dev;
+ struct dax_device *dax_dev;
+@@ -222,6 +224,8 @@ struct dev_dax *devm_create_dev_dax(stru
+ if (!dev_dax)
+ return ERR_PTR(-ENOMEM);
+
++ memcpy(&dev_dax->pgmap, pgmap, sizeof(*pgmap));
++
+ /*
+ * No 'host' or dax_operations since there is no access to this
+ * device outside of mmap of the resulting character device.
+--- a/drivers/dax/bus.h
++++ b/drivers/dax/bus.h
+@@ -10,7 +10,8 @@ struct dax_region;
+ void dax_region_put(struct dax_region *dax_region);
+ struct dax_region *alloc_dax_region(struct device *parent, int region_id,
+ struct resource *res, unsigned int align, unsigned long flags);
+-struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id);
++struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id,
++ struct dev_pagemap *pgmap);
+ int __dax_driver_register(struct device_driver *drv,
+ struct module *module, const char *mod_name);
+ #define dax_driver_register(driver) \
+--- a/drivers/dax/dax-private.h
++++ b/drivers/dax/dax-private.h
+@@ -42,15 +42,22 @@ struct dax_region {
+ };
+
+ /**
+- * struct dev_dax - instance data for a subdivision of a dax region
++ * struct dev_dax - instance data for a subdivision of a dax region, and
++ * data while the device is activated in the driver.
+ * @region - parent region
+ * @dax_dev - core dax functionality
+ * @dev - device core
++ * @pgmap - pgmap for memmap setup / lifetime (driver owned)
++ * @ref: pgmap reference count (driver owned)
++ * @cmp: @ref final put completion (driver owned)
+ */
+ struct dev_dax {
+ struct dax_region *region;
+ struct dax_device *dax_dev;
+ struct device dev;
++ struct dev_pagemap pgmap;
++ struct percpu_ref ref;
++ struct completion cmp;
+ };
+
+ static inline struct dev_dax *to_dev_dax(struct device *dev)
+--- a/drivers/dax/device.c
++++ b/drivers/dax/device.c
+@@ -1,5 +1,6 @@
+ // SPDX-License-Identifier: GPL-2.0
+ /* Copyright(c) 2016-2018 Intel Corporation. All rights reserved. */
++#include <linux/memremap.h>
+ #include <linux/pagemap.h>
+ #include <linux/module.h>
+ #include <linux/device.h>
+@@ -13,6 +14,38 @@
+ #include "dax-private.h"
+ #include "bus.h"
+
++static struct dev_dax *ref_to_dev_dax(struct percpu_ref *ref)
++{
++ return container_of(ref, struct dev_dax, ref);
++}
++
++static void dev_dax_percpu_release(struct percpu_ref *ref)
++{
++ struct dev_dax *dev_dax = ref_to_dev_dax(ref);
++
++ dev_dbg(&dev_dax->dev, "%s\n", __func__);
++ complete(&dev_dax->cmp);
++}
++
++static void dev_dax_percpu_exit(void *data)
++{
++ struct percpu_ref *ref = data;
++ struct dev_dax *dev_dax = ref_to_dev_dax(ref);
++
++ dev_dbg(&dev_dax->dev, "%s\n", __func__);
++ wait_for_completion(&dev_dax->cmp);
++ percpu_ref_exit(ref);
++}
++
++static void dev_dax_percpu_kill(struct percpu_ref *data)
++{
++ struct percpu_ref *ref = data;
++ struct dev_dax *dev_dax = ref_to_dev_dax(ref);
++
++ dev_dbg(&dev_dax->dev, "%s\n", __func__);
++ percpu_ref_kill(ref);
++}
++
+ static int check_vma(struct dev_dax *dev_dax, struct vm_area_struct *vma,
+ const char *func)
+ {
+@@ -427,10 +460,38 @@ static int dev_dax_probe(struct device *
+ {
+ struct dev_dax *dev_dax = to_dev_dax(dev);
+ struct dax_device *dax_dev = dev_dax->dax_dev;
++ struct resource *res = &dev_dax->region->res;
+ struct inode *inode;
+ struct cdev *cdev;
++ void *addr;
+ int rc;
+
++ /* 1:1 map region resource range to device-dax instance range */
++ if (!devm_request_mem_region(dev, res->start, resource_size(res),
++ dev_name(dev))) {
++ dev_warn(dev, "could not reserve region %pR\n", res);
++ return -EBUSY;
++ }
++
++ init_completion(&dev_dax->cmp);
++ rc = percpu_ref_init(&dev_dax->ref, dev_dax_percpu_release, 0,
++ GFP_KERNEL);
++ if (rc)
++ return rc;
++
++ rc = devm_add_action_or_reset(dev, dev_dax_percpu_exit, &dev_dax->ref);
++ if (rc)
++ return rc;
++
++ dev_dax->pgmap.ref = &dev_dax->ref;
++ dev_dax->pgmap.kill = dev_dax_percpu_kill;
++ addr = devm_memremap_pages(dev, &dev_dax->pgmap);
++ if (IS_ERR(addr)) {
++ devm_remove_action(dev, dev_dax_percpu_exit, &dev_dax->ref);
++ percpu_ref_exit(&dev_dax->ref);
++ return PTR_ERR(addr);
++ }
++
+ inode = dax_inode(dax_dev);
+ cdev = inode->i_cdev;
+ cdev_init(cdev, &dax_fops);
+--- a/drivers/dax/pmem.c
++++ b/drivers/dax/pmem.c
+@@ -18,54 +18,16 @@
+ #include "../nvdimm/nd.h"
+ #include "bus.h"
+
+-struct dax_pmem {
+- struct device *dev;
+- struct percpu_ref ref;
+- struct dev_pagemap pgmap;
+- struct completion cmp;
+-};
+-
+-static struct dax_pmem *to_dax_pmem(struct percpu_ref *ref)
+-{
+- return container_of(ref, struct dax_pmem, ref);
+-}
+-
+-static void dax_pmem_percpu_release(struct percpu_ref *ref)
+-{
+- struct dax_pmem *dax_pmem = to_dax_pmem(ref);
+-
+- dev_dbg(dax_pmem->dev, "%s\n", __func__);
+- complete(&dax_pmem->cmp);
+-}
+-
+-static void dax_pmem_percpu_exit(void *data)
+-{
+- struct percpu_ref *ref = data;
+- struct dax_pmem *dax_pmem = to_dax_pmem(ref);
+-
+- dev_dbg(dax_pmem->dev, "%s\n", __func__);
+- wait_for_completion(&dax_pmem->cmp);
+- percpu_ref_exit(ref);
+-}
+-
+-static void dax_pmem_percpu_kill(struct percpu_ref *ref)
+-{
+- struct dax_pmem *dax_pmem = to_dax_pmem(ref);
+-
+- dev_dbg(dax_pmem->dev, "%s\n", __func__);
+- percpu_ref_kill(ref);
+-}
+-
+ static int dax_pmem_probe(struct device *dev)
+ {
+- void *addr;
+ struct resource res;
+ int rc, id, region_id;
++ resource_size_t offset;
+ struct nd_pfn_sb *pfn_sb;
+ struct dev_dax *dev_dax;
+- struct dax_pmem *dax_pmem;
+ struct nd_namespace_io *nsio;
+ struct dax_region *dax_region;
++ struct dev_pagemap pgmap = { 0 };
+ struct nd_namespace_common *ndns;
+ struct nd_dax *nd_dax = to_nd_dax(dev);
+ struct nd_pfn *nd_pfn = &nd_dax->nd_pfn;
+@@ -75,61 +37,37 @@ static int dax_pmem_probe(struct device
+ return PTR_ERR(ndns);
+ nsio = to_nd_namespace_io(&ndns->dev);
+
+- dax_pmem = devm_kzalloc(dev, sizeof(*dax_pmem), GFP_KERNEL);
+- if (!dax_pmem)
+- return -ENOMEM;
+-
+ /* parse the 'pfn' info block via ->rw_bytes */
+ rc = devm_nsio_enable(dev, nsio);
+ if (rc)
+ return rc;
+- rc = nvdimm_setup_pfn(nd_pfn, &dax_pmem->pgmap);
++ rc = nvdimm_setup_pfn(nd_pfn, &pgmap);
+ if (rc)
+ return rc;
+ devm_nsio_disable(dev, nsio);
+
+- pfn_sb = nd_pfn->pfn_sb;
+-
+- if (!devm_request_mem_region(dev, nsio->res.start,
+- resource_size(&nsio->res),
++ /* reserve the metadata area, device-dax will reserve the data */
++ pfn_sb = nd_pfn->pfn_sb;
++ offset = le64_to_cpu(pfn_sb->dataoff);
++ if (!devm_request_mem_region(dev, nsio->res.start, offset,
+ dev_name(&ndns->dev))) {
+- dev_warn(dev, "could not reserve region %pR\n", &nsio->res);
+- return -EBUSY;
+- }
+-
+- dax_pmem->dev = dev;
+- init_completion(&dax_pmem->cmp);
+- rc = percpu_ref_init(&dax_pmem->ref, dax_pmem_percpu_release, 0,
+- GFP_KERNEL);
+- if (rc)
+- return rc;
+-
+- rc = devm_add_action(dev, dax_pmem_percpu_exit, &dax_pmem->ref);
+- if (rc) {
+- percpu_ref_exit(&dax_pmem->ref);
+- return rc;
+- }
+-
+- dax_pmem->pgmap.ref = &dax_pmem->ref;
+- dax_pmem->pgmap.kill = dax_pmem_percpu_kill;
+- addr = devm_memremap_pages(dev, &dax_pmem->pgmap);
+- if (IS_ERR(addr))
+- return PTR_ERR(addr);
+-
+- /* adjust the dax_region resource to the start of data */
+- memcpy(&res, &dax_pmem->pgmap.res, sizeof(res));
+- res.start += le64_to_cpu(pfn_sb->dataoff);
++ dev_warn(dev, "could not reserve metadata\n");
++ return -EBUSY;
++ }
+
+ rc = sscanf(dev_name(&ndns->dev), "namespace%d.%d", &region_id, &id);
+ if (rc != 2)
+ return -EINVAL;
+
++ /* adjust the dax_region resource to the start of data */
++ memcpy(&res, &pgmap.res, sizeof(res));
++ res.start += offset;
+ dax_region = alloc_dax_region(dev, region_id, &res,
+ le32_to_cpu(pfn_sb->align), PFN_DEV|PFN_MAP);
+ if (!dax_region)
+ return -ENOMEM;
+
+- dev_dax = devm_create_dev_dax(dax_region, id);
++ dev_dax = devm_create_dev_dax(dax_region, id, &pgmap);
+
+ /* child dev_dax instances now own the lifetime of the dax_region */
+ dax_region_put(dax_region);
diff --git a/patches.suse/0001-device-dax-Remove-multi-resource-infrastructure.patch b/patches.suse/0001-device-dax-Remove-multi-resource-infrastructure.patch
new file mode 100644
index 0000000000..a9c9db043b
--- /dev/null
+++ b/patches.suse/0001-device-dax-Remove-multi-resource-infrastructure.patch
@@ -0,0 +1,185 @@
+From 753a0850e707e9a8c5861356222f9b9e4eba7945 Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Fri, 14 Jul 2017 13:54:50 -0700
+Subject: [PATCH] device-dax: Remove multi-resource infrastructure
+Git-commit: 753a0850e707e9a8c5861356222f9b9e4eba7945
+Patch-mainline: v5.1-rc1
+References: jsc#SLE-5340
+
+The multi-resource implementation anticipated discontiguous sub-division
+support. That has not yet materialized, delete the infrastructure and
+related code.
+
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ drivers/dax/dax-private.h | 4 ---
+ drivers/dax/device-dax.h | 3 --
+ drivers/dax/device.c | 48 +++++------------------------------------
+ drivers/dax/pmem.c | 3 --
+ tools/testing/nvdimm/dax-dev.c | 16 ++-----------
+ 5 files changed, 12 insertions(+), 62 deletions(-)
+
+--- a/drivers/dax/dax-private.h
++++ b/drivers/dax/dax-private.h
+@@ -39,14 +39,10 @@ struct dax_region {
+ * @region - parent region
+ * @dax_dev - core dax functionality
+ * @dev - device core
+- * @num_resources - number of physical address extents in this device
+- * @res - array of physical address ranges
+ */
+ struct dev_dax {
+ struct dax_region *region;
+ struct dax_device *dax_dev;
+ struct device dev;
+- int num_resources;
+- struct resource res[0];
+ };
+ #endif
+--- a/drivers/dax/device-dax.h
++++ b/drivers/dax/device-dax.h
+@@ -19,6 +19,5 @@ struct dax_region;
+ void dax_region_put(struct dax_region *dax_region);
+ struct dax_region *alloc_dax_region(struct device *parent, int region_id,
+ struct resource *res, unsigned int align, unsigned long flags);
+-struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region,
+- int id, struct resource *res, int count);
++struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id);
+ #endif /* __DEVICE_DAX_H__ */
+--- a/drivers/dax/device.c
++++ b/drivers/dax/device.c
+@@ -151,11 +151,7 @@ static ssize_t size_show(struct device *
+ struct device_attribute *attr, char *buf)
+ {
+ struct dev_dax *dev_dax = to_dev_dax(dev);
+- unsigned long long size = 0;
+- int i;
+-
+- for (i = 0; i < dev_dax->num_resources; i++)
+- size += resource_size(&dev_dax->res[i]);
++ unsigned long long size = resource_size(&dev_dax->region->res);
+
+ return sprintf(buf, "%llu\n", size);
+ }
+@@ -224,21 +220,11 @@ static int check_vma(struct dev_dax *dev
+ __weak phys_addr_t dax_pgoff_to_phys(struct dev_dax *dev_dax, pgoff_t pgoff,
+ unsigned long size)
+ {
+- struct resource *res;
+- /* gcc-4.6.3-nolibc for i386 complains that this is uninitialized */
+- phys_addr_t uninitialized_var(phys);
+- int i;
+-
+- for (i = 0; i < dev_dax->num_resources; i++) {
+- res = &dev_dax->res[i];
+- phys = pgoff * PAGE_SIZE + res->start;
+- if (phys >= res->start && phys <= res->end)
+- break;
+- pgoff -= PHYS_PFN(resource_size(res));
+- }
++ struct resource *res = &dev_dax->region->res;
++ phys_addr_t phys;
+
+- if (i < dev_dax->num_resources) {
+- res = &dev_dax->res[i];
++ phys = pgoff * PAGE_SIZE + res->start;
++ if (phys >= res->start && phys <= res->end) {
+ if (phys + size - 1 <= res->end)
+ return phys;
+ }
+@@ -619,8 +605,7 @@ static void unregister_dev_dax(void *dev
+ put_device(dev);
+ }
+
+-struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region,
+- int id, struct resource *res, int count)
++struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id)
+ {
+ struct device *parent = dax_region->dev;
+ struct dax_device *dax_dev;
+@@ -628,29 +613,11 @@ struct dev_dax *devm_create_dev_dax(stru
+ struct inode *inode;
+ struct device *dev;
+ struct cdev *cdev;
+- int rc, i;
+
+- if (!count)
+- return ERR_PTR(-EINVAL);
+-
+- dev_dax = kzalloc(sizeof(*dev_dax) + sizeof(*res) * count, GFP_KERNEL);
++ dev_dax = kzalloc(sizeof(*dev_dax), GFP_KERNEL);
+ if (!dev_dax)
+ return ERR_PTR(-ENOMEM);
+
+- for (i = 0; i < count; i++) {
+- if (!IS_ALIGNED(res[i].start, dax_region->align)
+- || !IS_ALIGNED(resource_size(&res[i]),
+- dax_region->align)) {
+- rc = -EINVAL;
+- break;
+- }
+- dev_dax->res[i].start = res[i].start;
+- dev_dax->res[i].end = res[i].end;
+- }
+-
+- if (i < count)
+- goto err;
+-
+ /*
+ * No 'host' or dax_operations since there is no access to this
+ * device outside of mmap of the resulting character device.
+@@ -670,7 +637,6 @@ struct dev_dax *devm_create_dev_dax(stru
+ cdev_init(cdev, &dax_fops);
+ cdev->owner = parent->driver->owner;
+
+- dev_dax->num_resources = count;
+ dev_dax->dax_dev = dax_dev;
+ dev_dax->region = dax_region;
+ kref_get(&dax_region->kref);
+--- a/drivers/dax/pmem.c
++++ b/drivers/dax/pmem.c
+@@ -137,8 +137,7 @@ static int dax_pmem_probe(struct device
+ if (!dax_region)
+ return -ENOMEM;
+
+- /* TODO: support for subdividing a dax region... */
+- dev_dax = devm_create_dev_dax(dax_region, id, &res, 1);
++ dev_dax = devm_create_dev_dax(dax_region, id);
+
+ /* child dev_dax instances now own the lifetime of the dax_region */
+ dax_region_put(dax_region);
+--- a/tools/testing/nvdimm/dax-dev.c
++++ b/tools/testing/nvdimm/dax-dev.c
+@@ -17,20 +17,11 @@
+ phys_addr_t dax_pgoff_to_phys(struct dev_dax *dev_dax, pgoff_t pgoff,
+ unsigned long size)
+ {
+- struct resource *res;
++ struct resource *res = &dev_dax->region->res;
+ phys_addr_t addr;
+- int i;
+
+- for (i = 0; i < dev_dax->num_resources; i++) {
+- res = &dev_dax->res[i];
+- addr = pgoff * PAGE_SIZE + res->start;
+- if (addr >= res->start && addr <= res->end)
+- break;
+- pgoff -= PHYS_PFN(resource_size(res));
+- }
+-
+- if (i < dev_dax->num_resources) {
+- res = &dev_dax->res[i];
++ addr = pgoff * PAGE_SIZE + res->start;
++ if (addr >= res->start && addr <= res->end) {
+ if (addr + size - 1 <= res->end) {
+ if (get_nfit_res(addr)) {
+ struct page *page;
+@@ -44,6 +35,5 @@ phys_addr_t dax_pgoff_to_phys(struct dev
+ return addr;
+ }
+ }
+-
+ return -1;
+ }
diff --git a/patches.suse/0001-device-dax-Start-defining-a-dax-bus-model.patch b/patches.suse/0001-device-dax-Start-defining-a-dax-bus-model.patch
new file mode 100644
index 0000000000..96c50b2820
--- /dev/null
+++ b/patches.suse/0001-device-dax-Start-defining-a-dax-bus-model.patch
@@ -0,0 +1,555 @@
+From 51cf784c42d07fbd62cb604836a9270cf3361509 Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Wed, 12 Jul 2017 17:58:21 -0700
+Subject: [PATCH] device-dax: Start defining a dax bus model
+Git-commit: 51cf784c42d07fbd62cb604836a9270cf3361509
+Patch-mainline: v5.1-rc1
+References: jsc#SLE-5340
+
+Towards eliminating the dax_class, move the dax-device-attribute
+enabling to a new bus.c file in the core. The amount of code
+thrash of sub-sequent patches is reduced as no logic changes are made,
+just pure code movement.
+
+A temporary export of unregister_dex_dax() and dax_attribute_groups is
+needed to preserve compilation, but those symbols become static again in
+a follow-on patch.
+
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ drivers/dax/Makefile | 1
+ drivers/dax/bus.c | 174 +++++++++++++++++++++++++++++++++++++++++
+ drivers/dax/bus.h | 15 +++
+ drivers/dax/dax-private.h | 14 +++
+ drivers/dax/dax.h | 18 ----
+ drivers/dax/device-dax.h | 23 -----
+ drivers/dax/device.c | 185 --------------------------------------------
+ drivers/dax/pmem.c | 2
+ drivers/dax/super.c | 1
+ tools/testing/nvdimm/Kbuild | 1
+ 10 files changed, 210 insertions(+), 224 deletions(-)
+ create mode 100644 drivers/dax/bus.c
+ create mode 100644 drivers/dax/bus.h
+ delete mode 100644 drivers/dax/dax.h
+ delete mode 100644 drivers/dax/device-dax.h
+
+--- a/drivers/dax/Makefile
++++ b/drivers/dax/Makefile
+@@ -3,5 +3,6 @@ obj-$(CONFIG_DEV_DAX) += device_dax.o
+ obj-$(CONFIG_DEV_DAX_PMEM) += dax_pmem.o
+
+ dax-y := super.o
++dax-y += bus.o
+ dax_pmem-y := pmem.o
+ device_dax-y := device.o
+--- /dev/null
++++ b/drivers/dax/bus.c
+@@ -0,0 +1,174 @@
++// SPDX-License-Identifier: GPL-2.0
++/* Copyright(c) 2017-2018 Intel Corporation. All rights reserved. */
++#include <linux/device.h>
++#include <linux/slab.h>
++#include <linux/dax.h>
++#include "dax-private.h"
++#include "bus.h"
++
++/*
++ * Rely on the fact that drvdata is set before the attributes are
++ * registered, and that the attributes are unregistered before drvdata
++ * is cleared to assume that drvdata is always valid.
++ */
++static ssize_t id_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct dax_region *dax_region = dev_get_drvdata(dev);
++
++ return sprintf(buf, "%d\n", dax_region->id);
++}
++static DEVICE_ATTR_RO(id);
++
++static ssize_t region_size_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct dax_region *dax_region = dev_get_drvdata(dev);
++
++ return sprintf(buf, "%llu\n", (unsigned long long)
++ resource_size(&dax_region->res));
++}
++static struct device_attribute dev_attr_region_size = __ATTR(size, 0444,
++ region_size_show, NULL);
++
++static ssize_t align_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct dax_region *dax_region = dev_get_drvdata(dev);
++
++ return sprintf(buf, "%u\n", dax_region->align);
++}
++static DEVICE_ATTR_RO(align);
++
++static struct attribute *dax_region_attributes[] = {
++ &dev_attr_region_size.attr,
++ &dev_attr_align.attr,
++ &dev_attr_id.attr,
++ NULL,
++};
++
++static const struct attribute_group dax_region_attribute_group = {
++ .name = "dax_region",
++ .attrs = dax_region_attributes,
++};
++
++static const struct attribute_group *dax_region_attribute_groups[] = {
++ &dax_region_attribute_group,
++ NULL,
++};
++
++static void dax_region_free(struct kref *kref)
++{
++ struct dax_region *dax_region;
++
++ dax_region = container_of(kref, struct dax_region, kref);
++ kfree(dax_region);
++}
++
++void dax_region_put(struct dax_region *dax_region)
++{
++ kref_put(&dax_region->kref, dax_region_free);
++}
++EXPORT_SYMBOL_GPL(dax_region_put);
++
++static void dax_region_unregister(void *region)
++{
++ struct dax_region *dax_region = region;
++
++ sysfs_remove_groups(&dax_region->dev->kobj,
++ dax_region_attribute_groups);
++ dax_region_put(dax_region);
++}
++
++struct dax_region *alloc_dax_region(struct device *parent, int region_id,
++ struct resource *res, unsigned int align,
++ unsigned long pfn_flags)
++{
++ struct dax_region *dax_region;
++
++ /*
++ * The DAX core assumes that it can store its private data in
++ * parent->driver_data. This WARN is a reminder / safeguard for
++ * developers of device-dax drivers.
++ */
++ if (dev_get_drvdata(parent)) {
++ dev_WARN(parent, "dax core failed to setup private data\n");
++ return NULL;
++ }
++
++ if (!IS_ALIGNED(res->start, align)
++ || !IS_ALIGNED(resource_size(res), align))
++ return NULL;
++
++ dax_region = kzalloc(sizeof(*dax_region), GFP_KERNEL);
++ if (!dax_region)
++ return NULL;
++
++ dev_set_drvdata(parent, dax_region);
++ memcpy(&dax_region->res, res, sizeof(*res));
++ dax_region->pfn_flags = pfn_flags;
++ kref_init(&dax_region->kref);
++ dax_region->id = region_id;
++ dax_region->align = align;
++ dax_region->dev = parent;
++ if (sysfs_create_groups(&parent->kobj, dax_region_attribute_groups)) {
++ kfree(dax_region);
++ return NULL;
++ }
++
++ kref_get(&dax_region->kref);
++ if (devm_add_action_or_reset(parent, dax_region_unregister, dax_region))
++ return NULL;
++ return dax_region;
++}
++EXPORT_SYMBOL_GPL(alloc_dax_region);
++
++static ssize_t size_show(struct device *dev,
++ struct device_attribute *attr, char *buf)
++{
++ struct dev_dax *dev_dax = to_dev_dax(dev);
++ unsigned long long size = resource_size(&dev_dax->region->res);
++
++ return sprintf(buf, "%llu\n", size);
++}
++static DEVICE_ATTR_RO(size);
++
++static struct attribute *dev_dax_attributes[] = {
++ &dev_attr_size.attr,
++ NULL,
++};
++
++static const struct attribute_group dev_dax_attribute_group = {
++ .attrs = dev_dax_attributes,
++};
++
++const struct attribute_group *dax_attribute_groups[] = {
++ &dev_dax_attribute_group,
++ NULL,
++};
++EXPORT_SYMBOL_GPL(dax_attribute_groups);
++
++void kill_dev_dax(struct dev_dax *dev_dax)
++{
++ struct dax_device *dax_dev = dev_dax->dax_dev;
++ struct inode *inode = dax_inode(dax_dev);
++
++ kill_dax(dax_dev);
++ unmap_mapping_range(inode->i_mapping, 0, 0, 1);
++}
++EXPORT_SYMBOL_GPL(kill_dev_dax);
++
++void unregister_dev_dax(void *dev)
++{
++ struct dev_dax *dev_dax = to_dev_dax(dev);
++ struct dax_device *dax_dev = dev_dax->dax_dev;
++ struct inode *inode = dax_inode(dax_dev);
++ struct cdev *cdev = inode->i_cdev;
++
++ dev_dbg(dev, "trace\n");
++
++ kill_dev_dax(dev_dax);
++ cdev_device_del(cdev, dev);
++ put_device(dev);
++}
++EXPORT_SYMBOL_GPL(unregister_dev_dax);
+--- /dev/null
++++ b/drivers/dax/bus.h
+@@ -0,0 +1,15 @@
++// SPDX-License-Identifier: GPL-2.0
++/* Copyright(c) 2016 - 2018 Intel Corporation. All rights reserved. */
++#ifndef __DAX_BUS_H__
++#define __DAX_BUS_H__
++struct device;
++struct dev_dax;
++struct resource;
++struct dax_device;
++struct dax_region;
++void dax_region_put(struct dax_region *dax_region);
++struct dax_region *alloc_dax_region(struct device *parent, int region_id,
++ struct resource *res, unsigned int align, unsigned long flags);
++struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id);
++void kill_dev_dax(struct dev_dax *dev_dax);
++#endif /* __DAX_BUS_H__ */
+--- a/drivers/dax/dax-private.h
++++ b/drivers/dax/dax-private.h
+@@ -16,6 +16,15 @@
+ #include <linux/device.h>
+ #include <linux/cdev.h>
+
++/* private routines between core files */
++struct dax_device;
++struct dax_device *inode_dax(struct inode *inode);
++struct inode *dax_inode(struct dax_device *dax_dev);
++
++/* temporary until devm_create_dax_dev moves to bus.c */
++extern const struct attribute_group *dax_attribute_groups[];
++void unregister_dev_dax(void *dev);
++
+ /**
+ * struct dax_region - mapping infrastructure for dax devices
+ * @id: kernel-wide unique region for a memory range
+@@ -45,4 +54,9 @@ struct dev_dax {
+ struct dax_device *dax_dev;
+ struct device dev;
+ };
++
++static inline struct dev_dax *to_dev_dax(struct device *dev)
++{
++ return container_of(dev, struct dev_dax, dev);
++}
+ #endif
+--- a/drivers/dax/dax.h
++++ /dev/null
+@@ -1,18 +0,0 @@
+-/*
+- * Copyright(c) 2016 - 2017 Intel Corporation. All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of version 2 of the GNU General Public License as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * General Public License for more details.
+- */
+-#ifndef __DAX_H__
+-#define __DAX_H__
+-struct dax_device;
+-struct dax_device *inode_dax(struct inode *inode);
+-struct inode *dax_inode(struct dax_device *dax_dev);
+-#endif /* __DAX_H__ */
+--- a/drivers/dax/device-dax.h
++++ /dev/null
+@@ -1,23 +0,0 @@
+-/*
+- * Copyright(c) 2016 Intel Corporation. All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of version 2 of the GNU General Public License as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * General Public License for more details.
+- */
+-#ifndef __DEVICE_DAX_H__
+-#define __DEVICE_DAX_H__
+-struct device;
+-struct dev_dax;
+-struct resource;
+-struct dax_region;
+-void dax_region_put(struct dax_region *dax_region);
+-struct dax_region *alloc_dax_region(struct device *parent, int region_id,
+- struct resource *res, unsigned int align, unsigned long flags);
+-struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id);
+-#endif /* __DEVICE_DAX_H__ */
+--- a/drivers/dax/device.c
++++ b/drivers/dax/device.c
+@@ -1,15 +1,5 @@
+-/*
+- * Copyright(c) 2016 - 2017 Intel Corporation. All rights reserved.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of version 2 of the GNU General Public License as
+- * published by the Free Software Foundation.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * General Public License for more details.
+- */
++// SPDX-License-Identifier: GPL-2.0
++/* Copyright(c) 2016-2018 Intel Corporation. All rights reserved. */
+ #include <linux/pagemap.h>
+ #include <linux/module.h>
+ #include <linux/device.h>
+@@ -21,156 +11,10 @@
+ #include <linux/mm.h>
+ #include <linux/mman.h>
+ #include "dax-private.h"
+-#include "dax.h"
++#include "bus.h"
+
+ static struct class *dax_class;
+
+-/*
+- * Rely on the fact that drvdata is set before the attributes are
+- * registered, and that the attributes are unregistered before drvdata
+- * is cleared to assume that drvdata is always valid.
+- */
+-static ssize_t id_show(struct device *dev,
+- struct device_attribute *attr, char *buf)
+-{
+- struct dax_region *dax_region = dev_get_drvdata(dev);
+-
+- return sprintf(buf, "%d\n", dax_region->id);
+-}
+-static DEVICE_ATTR_RO(id);
+-
+-static ssize_t region_size_show(struct device *dev,
+- struct device_attribute *attr, char *buf)
+-{
+- struct dax_region *dax_region = dev_get_drvdata(dev);
+-
+- return sprintf(buf, "%llu\n", (unsigned long long)
+- resource_size(&dax_region->res));
+-}
+-static struct device_attribute dev_attr_region_size = __ATTR(size, 0444,
+- region_size_show, NULL);
+-
+-static ssize_t align_show(struct device *dev,
+- struct device_attribute *attr, char *buf)
+-{
+- struct dax_region *dax_region = dev_get_drvdata(dev);
+-
+- return sprintf(buf, "%u\n", dax_region->align);
+-}
+-static DEVICE_ATTR_RO(align);
+-
+-static struct attribute *dax_region_attributes[] = {
+- &dev_attr_region_size.attr,
+- &dev_attr_align.attr,
+- &dev_attr_id.attr,
+- NULL,
+-};
+-
+-static const struct attribute_group dax_region_attribute_group = {
+- .name = "dax_region",
+- .attrs = dax_region_attributes,
+-};
+-
+-static const struct attribute_group *dax_region_attribute_groups[] = {
+- &dax_region_attribute_group,
+- NULL,
+-};
+-
+-static void dax_region_free(struct kref *kref)
+-{
+- struct dax_region *dax_region;
+-
+- dax_region = container_of(kref, struct dax_region, kref);
+- kfree(dax_region);
+-}
+-
+-void dax_region_put(struct dax_region *dax_region)
+-{
+- kref_put(&dax_region->kref, dax_region_free);
+-}
+-EXPORT_SYMBOL_GPL(dax_region_put);
+-
+-static void dax_region_unregister(void *region)
+-{
+- struct dax_region *dax_region = region;
+-
+- sysfs_remove_groups(&dax_region->dev->kobj,
+- dax_region_attribute_groups);
+- dax_region_put(dax_region);
+-}
+-
+-struct dax_region *alloc_dax_region(struct device *parent, int region_id,
+- struct resource *res, unsigned int align,
+- unsigned long pfn_flags)
+-{
+- struct dax_region *dax_region;
+-
+- /*
+- * The DAX core assumes that it can store its private data in
+- * parent->driver_data. This WARN is a reminder / safeguard for
+- * developers of device-dax drivers.
+- */
+- if (dev_get_drvdata(parent)) {
+- dev_WARN(parent, "dax core failed to setup private data\n");
+- return NULL;
+- }
+-
+- if (!IS_ALIGNED(res->start, align)
+- || !IS_ALIGNED(resource_size(res), align))
+- return NULL;
+-
+- dax_region = kzalloc(sizeof(*dax_region), GFP_KERNEL);
+- if (!dax_region)
+- return NULL;
+-
+- dev_set_drvdata(parent, dax_region);
+- memcpy(&dax_region->res, res, sizeof(*res));
+- dax_region->pfn_flags = pfn_flags;
+- kref_init(&dax_region->kref);
+- dax_region->id = region_id;
+- dax_region->align = align;
+- dax_region->dev = parent;
+- if (sysfs_create_groups(&parent->kobj, dax_region_attribute_groups)) {
+- kfree(dax_region);
+- return NULL;
+- }
+-
+- kref_get(&dax_region->kref);
+- if (devm_add_action_or_reset(parent, dax_region_unregister, dax_region))
+- return NULL;
+- return dax_region;
+-}
+-EXPORT_SYMBOL_GPL(alloc_dax_region);
+-
+-static struct dev_dax *to_dev_dax(struct device *dev)
+-{
+- return container_of(dev, struct dev_dax, dev);
+-}
+-
+-static ssize_t size_show(struct device *dev,
+- struct device_attribute *attr, char *buf)
+-{
+- struct dev_dax *dev_dax = to_dev_dax(dev);
+- unsigned long long size = resource_size(&dev_dax->region->res);
+-
+- return sprintf(buf, "%llu\n", size);
+-}
+-static DEVICE_ATTR_RO(size);
+-
+-static struct attribute *dev_dax_attributes[] = {
+- &dev_attr_size.attr,
+- NULL,
+-};
+-
+-static const struct attribute_group dev_dax_attribute_group = {
+- .attrs = dev_dax_attributes,
+-};
+-
+-static const struct attribute_group *dax_attribute_groups[] = {
+- &dev_dax_attribute_group,
+- NULL,
+-};
+-
+ static int check_vma(struct dev_dax *dev_dax, struct vm_area_struct *vma,
+ const char *func)
+ {
+@@ -582,29 +426,6 @@ static void dev_dax_release(struct devic
+ kfree(dev_dax);
+ }
+
+-static void kill_dev_dax(struct dev_dax *dev_dax)
+-{
+- struct dax_device *dax_dev = dev_dax->dax_dev;
+- struct inode *inode = dax_inode(dax_dev);
+-
+- kill_dax(dax_dev);
+- unmap_mapping_range(inode->i_mapping, 0, 0, 1);
+-}
+-
+-static void unregister_dev_dax(void *dev)
+-{
+- struct dev_dax *dev_dax = to_dev_dax(dev);
+- struct dax_device *dax_dev = dev_dax->dax_dev;
+- struct inode *inode = dax_inode(dax_dev);
+- struct cdev *cdev = inode->i_cdev;
+-
+- dev_dbg(dev, "%s\n", __func__);
+-
+- kill_dev_dax(dev_dax);
+- cdev_device_del(cdev, dev);
+- put_device(dev);
+-}
+-
+ struct dev_dax *devm_create_dev_dax(struct dax_region *dax_region, int id)
+ {
+ struct device *parent = dax_region->dev;
+--- a/drivers/dax/pmem.c
++++ b/drivers/dax/pmem.c
+@@ -16,7 +16,7 @@
+ #include <linux/pfn_t.h>
+ #include "../nvdimm/pfn.h"
+ #include "../nvdimm/nd.h"
+-#include "device-dax.h"
++#include "bus.h"
+
+ struct dax_pmem {
+ struct device *dev;
+--- a/drivers/dax/super.c
++++ b/drivers/dax/super.c
+@@ -22,6 +22,7 @@
+ #include <linux/uio.h>
+ #include <linux/dax.h>
+ #include <linux/fs.h>
++#include "dax-private.h"
+
+ static dev_t dax_devt;
+ DEFINE_STATIC_SRCU(dax_srcu);
+--- a/tools/testing/nvdimm/Kbuild
++++ b/tools/testing/nvdimm/Kbuild
+@@ -56,6 +56,7 @@ nd_e820-y := $(NVDIMM_SRC)/e820.o
+ nd_e820-y += config_check.o
+
+ dax-y := $(DAX_SRC)/super.o
++dax-y += $(DAX_SRC)/bus.o
+ dax-y += config_check.o
+
+ device_dax-y := $(DAX_SRC)/device.o
diff --git a/patches.suse/0001-mm-devm_memremap_pages-fix-shutdown-handling.patch b/patches.suse/0001-mm-devm_memremap_pages-fix-shutdown-handling.patch
new file mode 100644
index 0000000000..264d1beec4
--- /dev/null
+++ b/patches.suse/0001-mm-devm_memremap_pages-fix-shutdown-handling.patch
@@ -0,0 +1,262 @@
+From a95c90f1e2c253b280385ecf3d4ebfe476926b28 Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Fri, 28 Dec 2018 00:34:57 -0800
+Subject: [PATCH] mm, devm_memremap_pages: fix shutdown handling
+Mime-version: 1.0
+Content-type: text/plain; charset=UTF-8
+Content-transfer-encoding: 8bit
+Git-commit: a95c90f1e2c253b280385ecf3d4ebfe476926b28
+Patch-mainline: v5.0-rc1
+References: jsc#SLE-5340
+
+The last step before devm_memremap_pages() returns success is to allocate
+a release action, devm_memremap_pages_release(), to tear the entire setup
+down. However, the result from devm_add_action() is not checked.
+
+Checking the error from devm_add_action() is not enough. The api
+currently relies on the fact that the percpu_ref it is using is killed by
+the time the devm_memremap_pages_release() is run. Rather than continue
+this awkward situation, offload the responsibility of killing the
+percpu_ref to devm_memremap_pages_release() directly. This allows
+devm_memremap_pages() to do the right thing relative to init failures and
+shutdown.
+
+Without this change we could fail to register the teardown of
+devm_memremap_pages(). The likelihood of hitting this failure is tiny as
+small memory allocations almost always succeed. However, the impact of
+the failure is large given any future reconfiguration, or disable/enable,
+of an nvdimm namespace will fail forever as subsequent calls to
+devm_memremap_pages() will fail to setup the pgmap_radix since there will
+be stale entries for the physical address range.
+
+An argument could be made to require that the ->kill() operation be set in
+the @pgmap arg rather than passed in separately. However, it helps code
+readability, tracking the lifetime of a given instance, to be able to grep
+the kill routine directly at the devm_memremap_pages() call site.
+
+Link: http://lkml.kernel.org/r/154275558526.76910.7535251937849268605.stgit@dwillia2-desk3.amr.corp.intel.com
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Fixes: e8d513483300 ("memremap: change devm_memremap_pages interface...")
+Reviewed-by: "Jérôme Glisse" <jglisse@redhat.com>
+Reported-by: Logan Gunthorpe <logang@deltatee.com>
+Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Cc: Balbir Singh <bsingharora@gmail.com>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ drivers/dax/pmem.c | 14 +++-----------
+ drivers/nvdimm/pmem.c | 13 +++++--------
+ include/linux/memremap.h | 2 ++
+ kernel/memremap.c | 30 ++++++++++++++----------------
+ tools/testing/nvdimm/test/iomap.c | 15 ++++++++++++++-
+ 5 files changed, 38 insertions(+), 36 deletions(-)
+
+--- a/drivers/dax/pmem.c
++++ b/drivers/dax/pmem.c
+@@ -48,9 +48,8 @@ static void dax_pmem_percpu_exit(void *d
+ percpu_ref_exit(ref);
+ }
+
+-static void dax_pmem_percpu_kill(void *data)
++static void dax_pmem_percpu_kill(struct percpu_ref *ref)
+ {
+- struct percpu_ref *ref = data;
+ struct dax_pmem *dax_pmem = to_dax_pmem(ref);
+
+ dev_dbg(dax_pmem->dev, "%s\n", __func__);
+@@ -112,17 +111,10 @@ static int dax_pmem_probe(struct device
+ }
+
+ dax_pmem->pgmap.ref = &dax_pmem->ref;
++ dax_pmem->pgmap.kill = dax_pmem_percpu_kill;
+ addr = devm_memremap_pages(dev, &dax_pmem->pgmap);
+- if (IS_ERR(addr)) {
+- devm_remove_action(dev, dax_pmem_percpu_exit, &dax_pmem->ref);
+- percpu_ref_exit(&dax_pmem->ref);
++ if (IS_ERR(addr))
+ return PTR_ERR(addr);
+- }
+-
+- rc = devm_add_action_or_reset(dev, dax_pmem_percpu_kill,
+- &dax_pmem->ref);
+- if (rc)
+- return rc;
+
+ /* adjust the dax_region resource to the start of data */
+ memcpy(&res, &dax_pmem->pgmap.res, sizeof(res));
+--- a/drivers/nvdimm/pmem.c
++++ b/drivers/nvdimm/pmem.c
+@@ -309,8 +309,11 @@ static void pmem_release_queue(void *q)
+ blk_cleanup_queue(q);
+ }
+
+-static void pmem_freeze_queue(void *q)
++static void pmem_freeze_queue(struct percpu_ref *ref)
+ {
++ struct request_queue *q;
++
++ q = container_of(ref, typeof(*q), q_usage_counter);
+ blk_freeze_queue_start(q);
+ }
+
+@@ -402,6 +405,7 @@ static int pmem_attach_disk(struct devic
+
+ pmem->pfn_flags = PFN_DEV;
+ pmem->pgmap.ref = &q->q_usage_counter;
++ pmem->pgmap.kill = pmem_freeze_queue;
+ if (is_nd_pfn(dev)) {
+ if (setup_pagemap_fsdax(dev, &pmem->pgmap))
+ return -ENOMEM;
+@@ -427,13 +431,6 @@ static int pmem_attach_disk(struct devic
+ memcpy(&bb_res, &nsio->res, sizeof(bb_res));
+ }
+
+- /*
+- * At release time the queue must be frozen before
+- * devm_memremap_pages is unwound
+- */
+- if (devm_add_action_or_reset(dev, pmem_freeze_queue, q))
+- return -ENOMEM;
+-
+ if (IS_ERR(addr))
+ return PTR_ERR(addr);
+ pmem->virt_addr = addr;
+--- a/include/linux/memremap.h
++++ b/include/linux/memremap.h
+@@ -110,6 +110,7 @@ typedef void (*dev_page_free_t)(struct p
+ * @altmap: pre-allocated/reserved memory for vmemmap allocations
+ * @res: physical address range covered by @ref
+ * @ref: reference count that pins the devm_memremap_pages() mapping
++ * @kill: callback to transition @ref to the dead state
+ * @dev: host device of the mapping for debug
+ * @data: private data pointer for page_free()
+ * @type: memory type: see MEMORY_* in memory_hotplug.h
+@@ -121,6 +122,7 @@ struct dev_pagemap {
+ bool altmap_valid;
+ struct resource res;
+ struct percpu_ref *ref;
++ void (*kill)(struct percpu_ref *ref);
+ struct device *dev;
+ void *data;
+ enum memory_type type;
+--- a/kernel/memremap.c
++++ b/kernel/memremap.c
+@@ -294,14 +294,10 @@ static void devm_memremap_pages_release(
+ resource_size_t align_start, align_size;
+ unsigned long pfn;
+
++ pgmap->kill(pgmap->ref);
+ for_each_device_pfn(pfn, pgmap)
+ put_page(pfn_to_page(pfn));
+
+- if (percpu_ref_tryget_live(pgmap->ref)) {
+- dev_WARN(dev, "%s: page mapping is still live!\n", __func__);
+- percpu_ref_put(pgmap->ref);
+- }
+-
+ /* pages are dead and unused, undo the arch mapping */
+ align_start = res->start & ~(SECTION_SIZE - 1);
+ align_size = ALIGN(res->start + resource_size(res), SECTION_SIZE)
+@@ -321,7 +317,7 @@ static void devm_memremap_pages_release(
+ /**
+ * devm_memremap_pages - remap and provide memmap backing for the given resource
+ * @dev: hosting device for @res
+- * @pgmap: pointer to a struct dev_pgmap
++ * @pgmap: pointer to a struct dev_pagemap
+ *
+ * Notes:
+ * 1/ At a minimum the res, ref and type members of @pgmap must be initialized
+@@ -330,11 +326,8 @@ static void devm_memremap_pages_release(
+ * 2/ The altmap field may optionally be initialized, in which case altmap_valid
+ * must be set to true
+ *
+- * 3/ pgmap.ref must be 'live' on entry and 'dead' before devm_memunmap_pages()
+- * time (or devm release event). The expected order of events is that ref has
+- * been through percpu_ref_kill() before devm_memremap_pages_release(). The
+- * wait for the completion of all references being dropped and
+- * percpu_ref_exit() must occur after devm_memremap_pages_release().
++ * 3/ pgmap->ref must be 'live' on entry and will be killed at
++ * devm_memremap_pages_release() time, or if this routine fails.
+ *
+ * 4/ res is expected to be a host memory range that could feasibly be
+ * treated as a "System RAM" range, i.e. not a device mmio range, but
+@@ -350,6 +343,9 @@ void *devm_memremap_pages(struct device
+ int error, nid, is_ram;
+ struct resource *res = &pgmap->res;
+
++ if (!pgmap->ref || !pgmap->kill)
++ return ERR_PTR(-EINVAL);
++
+ align_start = res->start & ~(SECTION_SIZE - 1);
+ align_size = ALIGN(res->start + resource_size(res), SECTION_SIZE)
+ - align_start;
+@@ -359,12 +355,10 @@ void *devm_memremap_pages(struct device
+ if (is_ram != REGION_DISJOINT) {
+ WARN_ONCE(1, "%s attempted on %s region %pr\n", __func__,
+ is_ram == REGION_MIXED ? "mixed" : "ram", res);
+- return ERR_PTR(-ENXIO);
++ error = -ENXIO;
++ goto err_radix;
+ }
+
+- if (!pgmap->ref)
+- return ERR_PTR(-EINVAL);
+-
+ pgmap->dev = dev;
+
+ mutex_lock(&pgmap_lock);
+@@ -411,7 +405,10 @@ void *devm_memremap_pages(struct device
+ align_size >> PAGE_SHIFT, pgmap);
+ percpu_ref_get_many(pgmap->ref, pfn_end(pgmap) - pfn_first(pgmap));
+
+- devm_add_action(dev, devm_memremap_pages_release, pgmap);
++ error = devm_add_action_or_reset(dev, devm_memremap_pages_release,
++ pgmap);
++ if (error)
++ return ERR_PTR(error);
+
+ return __va(res->start);
+
+@@ -420,6 +417,7 @@ void *devm_memremap_pages(struct device
+ err_pfn_remap:
+ err_radix:
+ pgmap_radix_release(res, pgoff);
++ pgmap->kill(pgmap->ref);
+ return ERR_PTR(error);
+ }
+ EXPORT_SYMBOL(devm_memremap_pages);
+--- a/tools/testing/nvdimm/test/iomap.c
++++ b/tools/testing/nvdimm/test/iomap.c
+@@ -104,13 +104,26 @@ void *__wrap_devm_memremap(struct device
+ }
+ EXPORT_SYMBOL(__wrap_devm_memremap);
+
++static void nfit_test_kill(void *_pgmap)
++{
++ struct dev_pagemap *pgmap = _pgmap;
++
++ pgmap->kill(pgmap->ref);
++}
++
+ void *__wrap_devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap)
+ {
+ resource_size_t offset = pgmap->res.start;
+ struct nfit_test_resource *nfit_res = get_nfit_res(offset);
+
+- if (nfit_res)
++ if (nfit_res) {
++ int rc;
++
++ rc = devm_add_action_or_reset(dev, nfit_test_kill, pgmap);
++ if (rc)
++ return ERR_PTR(rc);
+ return nfit_res->buf + offset - nfit_res->res.start;
++ }
+ return devm_memremap_pages(dev, pgmap);
+ }
+ EXPORT_SYMBOL(__wrap_devm_memremap_pages);
diff --git a/patches.suse/0001-mm-devm_memremap_pages-kill-mapping-System-RAM-suppo.patch b/patches.suse/0001-mm-devm_memremap_pages-kill-mapping-System-RAM-suppo.patch
new file mode 100644
index 0000000000..9b16a774e8
--- /dev/null
+++ b/patches.suse/0001-mm-devm_memremap_pages-kill-mapping-System-RAM-suppo.patch
@@ -0,0 +1,64 @@
+From 06489cfbd915ff36c8e36df27f1c2dc60f97ca56 Mon Sep 17 00:00:00 2001
+From: Dan Williams <dan.j.williams@intel.com>
+Date: Fri, 28 Dec 2018 00:34:54 -0800
+Subject: [PATCH] mm, devm_memremap_pages: kill mapping "System RAM" support
+Mime-version: 1.0
+Content-type: text/plain; charset=UTF-8
+Content-transfer-encoding: 8bit
+Git-commit: 06489cfbd915ff36c8e36df27f1c2dc60f97ca56
+Patch-mainline: v5.0-rc1
+References: jsc#SLE-5340
+
+Given the fact that devm_memremap_pages() requires a percpu_ref that is
+torn down by devm_memremap_pages_release() the current support for mapping
+RAM is broken.
+
+Support for remapping "System RAM" has been broken since the beginning and
+there is no existing user of this this code path, so just kill the support
+and make it an explicit error.
+
+This cleanup also simplifies a follow-on patch to fix the error path when
+setting a devm release action for devm_memremap_pages_release() fails.
+
+Link: http://lkml.kernel.org/r/154275557997.76910.14689813630968180480.stgit@dwillia2-desk3.amr.corp.intel.com
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Reviewed-by: "Jérôme Glisse" <jglisse@redhat.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Reviewed-by: Logan Gunthorpe <logang@deltatee.com>
+Cc: Balbir Singh <bsingharora@gmail.com>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ kernel/memremap.c | 9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+diff --git a/kernel/memremap.c b/kernel/memremap.c
+index 61dbcaa95530..99d14940acfa 100644
+--- a/kernel/memremap.c
++++ b/kernel/memremap.c
+@@ -167,15 +167,12 @@ void *devm_memremap_pages(struct device *dev, struct dev_pagemap *pgmap)
+ is_ram = region_intersects(align_start, align_size,
+ IORESOURCE_SYSTEM_RAM, IORES_DESC_NONE);
+
+- if (is_ram == REGION_MIXED) {
+- WARN_ONCE(1, "%s attempted on mixed region %pr\n",
+- __func__, res);
++ if (is_ram != REGION_DISJOINT) {
++ WARN_ONCE(1, "%s attempted on %s region %pr\n", __func__,
++ is_ram == REGION_MIXED ? "mixed" : "ram", res);
+ return ERR_PTR(-ENXIO);
+ }
+
+- if (is_ram == REGION_INTERSECTS)
+- return __va(res->start);
+-
+ if (!pgmap->ref)
+ return ERR_PTR(-EINVAL);
+
+--
+2.12.3
+
diff --git a/patches.suse/0001-mm-memory-hotplug-Allow-memory-resources-to-be-child.patch b/patches.suse/0001-mm-memory-hotplug-Allow-memory-resources-to-be-child.patch
new file mode 100644
index 0000000000..6b71b651f6
--- /dev/null
+++ b/patches.suse/0001-mm-memory-hotplug-Allow-memory-resources-to-be-child.patch
@@ -0,0 +1,122 @@
+From 2794129e902d8eb69413d884dc6404b8716ed9ed Mon Sep 17 00:00:00 2001
+From: Dave Hansen <dave.hansen@linux.intel.com>
+Date: Mon, 25 Feb 2019 10:57:36 -0800
+Subject: [PATCH] mm/memory-hotplug: Allow memory resources to be children
+Git-commit: 2794129e902d8eb69413d884dc6404b8716ed9ed
+Patch-mainline: v5.1-rc1
+References: jsc#SLE-5340
+
+The mm/resource.c code is used to manage the physical address
+space. The current resource configuration can be viewed in
+/proc/iomem. An example of this is at the bottom of this
+description.
+
+The nvdimm subsystem "owns" the physical address resources which
+map to persistent memory and has resources inserted for them as
+"Persistent Memory". The best way to repurpose this for volatile
+use is to leave the existing resource in place, but add a "System
+RAM" resource underneath it. This clearly communicates the
+ownership relationship of this memory.
+
+The request_resource_conflict() API only deals with the
+top-level resources. Replace it with __request_region() which
+will search for !IORESOURCE_BUSY areas lower in the resource
+tree than the top level.
+
+We *could* also simply truncate the existing top-level
+"Persistent Memory" resource and take over the released address
+space. But, this means that if we ever decide to hot-unplug the
+"RAM" and give it back, we need to recreate the original setup,
+which may mean going back to the BIOS tables.
+
+This should have no real effect on the existing collision
+detection because the areas that truly conflict should be marked
+IORESOURCE_BUSY.
+
+00000000-00000fff : Reserved
+00001000-0009fbff : System RAM
+0009fc00-0009ffff : Reserved
+000a0000-000bffff : PCI Bus 0000:00
+000c0000-000c97ff : Video ROM
+000c9800-000ca5ff : Adapter ROM
+000f0000-000fffff : Reserved
+ 000f0000-000fffff : System ROM
+00100000-9fffffff : System RAM
+ 01000000-01e071d0 : Kernel code
+ 01e071d1-027dfdff : Kernel data
+ 02dc6000-0305dfff : Kernel bss
+a0000000-afffffff : Persistent Memory (legacy)
+ a0000000-a7ffffff : System RAM
+b0000000-bffdffff : System RAM
+bffe0000-bfffffff : Reserved
+c0000000-febfffff : PCI Bus 0000:00
+
+Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
+Reviewed-by: Dan Williams <dan.j.williams@intel.com>
+Reviewed-by: Vishal Verma <vishal.l.verma@intel.com>
+Cc: Dave Jiang <dave.jiang@intel.com>
+Cc: Ross Zwisler <zwisler@kernel.org>
+Cc: Vishal Verma <vishal.l.verma@intel.com>
+Cc: Tom Lendacky <thomas.lendacky@amd.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: linux-nvdimm@lists.01.org
+Cc: linux-kernel@vger.kernel.org
+Cc: linux-mm@kvack.org
+Cc: Huang Ying <ying.huang@intel.com>
+Cc: Fengguang Wu <fengguang.wu@intel.com>
+Cc: Borislav Petkov <bp@suse.de>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Yaowei Bai <baiyaowei@cmss.chinamobile.com>
+Cc: Takashi Iwai <tiwai@suse.de>
+Cc: Jerome Glisse <jglisse@redhat.com>
+Cc: Keith Busch <keith.busch@intel.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ mm/memory_hotplug.c | 28 +++++++++++++++-------------
+ 1 file changed, 15 insertions(+), 13 deletions(-)
+
+diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
+index e198974c968d..b37f3a5c4833 100644
+--- a/mm/memory_hotplug.c
++++ b/mm/memory_hotplug.c
+@@ -99,19 +99,21 @@ void mem_hotplug_done(void)
+ /* add this memory to iomem resource */
+ static struct resource *register_memory_resource(u64 start, u64 size)
+ {
+- struct resource *res, *conflict;
+- res = kzalloc(sizeof(struct resource), GFP_KERNEL);
+- if (!res)
+- return ERR_PTR(-ENOMEM);
+-
+- res->name = "System RAM";
+- res->start = start;
+- res->end = start + size - 1;
+- res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
+- conflict = request_resource_conflict(&iomem_resource, res);
+- if (conflict) {
+- pr_debug("System RAM resource %pR cannot be added\n", res);
+- kfree(res);
++ struct resource *res;
++ unsigned long flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
++ char *resource_name = "System RAM";
++
++ /*
++ * Request ownership of the new memory range. This might be
++ * a child of an existing resource that was present but
++ * not marked as busy.
++ */
++ res = __request_region(&iomem_resource, start, size,
++ resource_name, flags);
++
++ if (!res) {
++ pr_debug("Unable to reserve System RAM region: %016llx->%016llx\n",
++ start, start + size);
+ return ERR_PTR(-EEXIST);
+ }
+ return res;
+--
+2.12.3
+
diff --git a/patches.suse/0001-mm-resource-Let-walk_system_ram_range-search-child-r.patch b/patches.suse/0001-mm-resource-Let-walk_system_ram_range-search-child-r.patch
new file mode 100644
index 0000000000..ba6744b678
--- /dev/null
+++ b/patches.suse/0001-mm-resource-Let-walk_system_ram_range-search-child-r.patch
@@ -0,0 +1,77 @@
+From 2b539aefe9e48e3908cff02699aa63a8b9bd268e Mon Sep 17 00:00:00 2001
+From: Dave Hansen <dave.hansen@linux.intel.com>
+Date: Mon, 25 Feb 2019 10:57:38 -0800
+Subject: [PATCH] mm/resource: Let walk_system_ram_range() search child
+ resources
+Git-commit: 2b539aefe9e48e3908cff02699aa63a8b9bd268e
+Patch-mainline: v5.1-rc1
+References: jsc#SLE-5340
+
+mhocko@suse.cz:
+we are missing 010a93bf97c72 and co. which restructured the code quite.
+I haven't pulled those in as they do not seem to be directly related
+and I am not aware of bug reports about issues mentioned in those commits.
+
+In the process of onlining memory, we use walk_system_ram_range()
+to find the actual RAM areas inside of the area being onlined.
+
+However, it currently only finds memory resources which are
+"top-level" iomem_resources. Children are not currently
+searched which causes it to skip System RAM in areas like this
+(in the format of /proc/iomem):
+
+a0000000-bfffffff : Persistent Memory (legacy)
+ a0000000-afffffff : System RAM
+
+Changing the true->false here allows children to be searched
+as well. We need this because we add a new "System RAM"
+resource underneath the "persistent memory" resource when
+we use persistent memory in a volatile mode.
+
+Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
+Cc: Keith Busch <keith.busch@intel.com>
+Cc: Dan Williams <dan.j.williams@intel.com>
+Cc: Dave Jiang <dave.jiang@intel.com>
+Cc: Ross Zwisler <zwisler@kernel.org>
+Cc: Vishal Verma <vishal.l.verma@intel.com>
+Cc: Tom Lendacky <thomas.lendacky@amd.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: linux-nvdimm@lists.01.org
+Cc: linux-kernel@vger.kernel.org
+Cc: linux-mm@kvack.org
+Cc: Huang Ying <ying.huang@intel.com>
+Cc: Fengguang Wu <fengguang.wu@intel.com>
+Cc: Borislav Petkov <bp@suse.de>
+Cc: Bjorn Helgaas <bhelgaas@google.com>
+Cc: Yaowei Bai <baiyaowei@cmss.chinamobile.com>
+Cc: Takashi Iwai <tiwai@suse.de>
+Cc: Jerome Glisse <jglisse@redhat.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ kernel/resource.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+--- a/kernel/resource.c
++++ b/kernel/resource.c
+@@ -493,6 +493,9 @@ int walk_mem_res(u64 start, u64 end, voi
+ * This function calls the @func callback against all memory ranges of type
+ * System RAM which are marked as IORESOURCE_SYSTEM_RAM and IORESOUCE_BUSY.
+ * It is to be used only for System RAM.
++ *
++ * This will find System RAM ranges that are children of top-level resources
++ * in addition to top-level System RAM resources.
+ */
+ int walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
+ void *arg, int (*func)(unsigned long, unsigned long, void *))
+@@ -507,7 +510,7 @@ int walk_system_ram_range(unsigned long
+ res.flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
+ orig_end = res.end;
+ while ((res.start < res.end) &&
+- (find_next_iomem_res(&res, IORES_DESC_NONE, true) >= 0)) {
++ (find_next_iomem_res(&res, IORES_DESC_NONE, false) >= 0)) {
+ pfn = (res.start + PAGE_SIZE - 1) >> PAGE_SHIFT;
+ end_pfn = (res.end + 1) >> PAGE_SHIFT;
+ if (end_pfn > pfn)
diff --git a/patches.suse/0001-mm-resource-Move-HMM-pr_debug-deeper-into-resource-c.patch b/patches.suse/0001-mm-resource-Move-HMM-pr_debug-deeper-into-resource-c.patch
new file mode 100644
index 0000000000..0ef8f10d47
--- /dev/null
+++ b/patches.suse/0001-mm-resource-Move-HMM-pr_debug-deeper-into-resource-c.patch
@@ -0,0 +1,95 @@
+From b926b7f3baecb2a855db629e6822e1a85212e91c Mon Sep 17 00:00:00 2001
+From: Dave Hansen <dave.hansen@linux.intel.com>
+Date: Mon, 25 Feb 2019 10:57:33 -0800
+Subject: [PATCH] mm/resource: Move HMM pr_debug() deeper into resource code
+Git-commit: b926b7f3baecb2a855db629e6822e1a85212e91c
+Patch-mainline: v5.1-rc1
+References: jsc#SLE-5340
+
+HMM consumes physical address space for its own use, even
+though nothing is mapped or accessible there. It uses a
+special resource description (IORES_DESC_DEVICE_PRIVATE_MEMORY)
+to uniquely identify these areas.
+
+When HMM consumes address space, it makes a best guess about
+what to consume. However, it is possible that a future memory
+or device hotplug can collide with the reserved area. In the
+case of these conflicts, there is an error message in
+register_memory_resource().
+
+Later patches in this series move register_memory_resource()
+from using request_resource_conflict() to __request_region().
+Unfortunately, __request_region() does not return the conflict
+like the previous function did, which makes it impossible to
+check for IORES_DESC_DEVICE_PRIVATE_MEMORY in a conflicting
+resource.
+
+Instead of warning in register_memory_resource(), move the
+check into the core resource code itself (__request_region())
+where the conflicting resource _is_ available. This has the
+added bonus of producing a warning in case of HMM conflicts
+with devices *or* RAM address space, as opposed to the RAM-
+only warnings that were there previously.
+
+Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
+Reviewed-by: Jerome Glisse <jglisse@redhat.com>
+Cc: Dan Williams <dan.j.williams@intel.com>
+Cc: Dave Jiang <dave.jiang@intel.com>
+Cc: Ross Zwisler <zwisler@kernel.org>
+Cc: Vishal Verma <vishal.l.verma@intel.com>
+Cc: Tom Lendacky <thomas.lendacky@amd.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: linux-nvdimm@lists.01.org
+Cc: linux-kernel@vger.kernel.org
+Cc: linux-mm@kvack.org
+Cc: Huang Ying <ying.huang@intel.com>
+Cc: Fengguang Wu <fengguang.wu@intel.com>
+Cc: Keith Busch <keith.busch@intel.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ kernel/resource.c | 9 +++++++++
+ mm/memory_hotplug.c | 5 -----
+ 2 files changed, 9 insertions(+), 5 deletions(-)
+
+diff --git a/kernel/resource.c b/kernel/resource.c
+index ca7ed5158cff..35fe105d581e 100644
+--- a/kernel/resource.c
++++ b/kernel/resource.c
+@@ -1132,6 +1132,15 @@ struct resource * __request_region(struct resource *parent,
+ conflict = __request_resource(parent, res);
+ if (!conflict)
+ break;
++ /*
++ * mm/hmm.c reserves physical addresses which then
++ * become unavailable to other users. Conflicts are
++ * not expected. Warn to aid debugging if encountered.
++ */
++ if (conflict->desc == IORES_DESC_DEVICE_PRIVATE_MEMORY) {
++ pr_warn("Unaddressable device %s %pR conflicts with %pR",
++ conflict->name, conflict, res);
++ }
+ if (conflict != parent) {
+ if (!(conflict->flags & IORESOURCE_BUSY)) {
+ parent = conflict;
+diff --git a/mm/memory_hotplug.c b/mm/memory_hotplug.c
+index b9a667d36c55..e198974c968d 100644
+--- a/mm/memory_hotplug.c
++++ b/mm/memory_hotplug.c
+@@ -110,11 +110,6 @@ static struct resource *register_memory_resource(u64 start, u64 size)
+ res->flags = IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY;
+ conflict = request_resource_conflict(&iomem_resource, res);
+ if (conflict) {
+- if (conflict->desc == IORES_DESC_DEVICE_PRIVATE_MEMORY) {
+- pr_debug("Device unaddressable memory block "
+- "memory hotplug at %#010llx !\n",
+- (unsigned long long)start);
+- }
+ pr_debug("System RAM resource %pR cannot be added\n", res);
+ kfree(res);
+ return ERR_PTR(-EEXIST);
+--
+2.12.3
+
diff --git a/patches.suse/0001-mm-resource-Return-real-error-codes-from-walk-failur.patch b/patches.suse/0001-mm-resource-Return-real-error-codes-from-walk-failur.patch
new file mode 100644
index 0000000000..eb6a71afa2
--- /dev/null
+++ b/patches.suse/0001-mm-resource-Return-real-error-codes-from-walk-failur.patch
@@ -0,0 +1,77 @@
+From 5cd401ace914dc68556c6d2fcae0c349444d5f86 Mon Sep 17 00:00:00 2001
+From: Dave Hansen <dave.hansen@linux.intel.com>
+Date: Mon, 25 Feb 2019 10:57:30 -0800
+Subject: [PATCH] mm/resource: Return real error codes from walk failures
+Git-commit: 5cd401ace914dc68556c6d2fcae0c349444d5f86
+Patch-mainline: v5.1-rc1
+References: jsc#SLE-5340
+
+walk_system_ram_range() can return an error code either becuase
+*it* failed, or because the 'func' that it calls returned an
+error. The memory hotplug does the following:
+
+ ret = walk_system_ram_range(..., func);
+ if (ret)
+ return ret;
+
+and 'ret' makes it out to userspace, eventually. The problem
+s, walk_system_ram_range() failues that result from *it* failing
+(as opposed to 'func') return -1. That leads to a very odd
+-EPERM (-1) return code out to userspace.
+
+Make walk_system_ram_range() return -EINVAL for internal
+failures to keep userspace less confused.
+
+This return code is compatible with all the callers that I
+audited.
+
+Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com>
+Reviewed-by: Bjorn Helgaas <bhelgaas@google.com>
+Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)
+Cc: Dan Williams <dan.j.williams@intel.com>
+Cc: Dave Jiang <dave.jiang@intel.com>
+Cc: Ross Zwisler <zwisler@kernel.org>
+Cc: Vishal Verma <vishal.l.verma@intel.com>
+Cc: Tom Lendacky <thomas.lendacky@amd.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: linux-nvdimm@lists.01.org
+Cc: linux-kernel@vger.kernel.org
+Cc: linux-mm@kvack.org
+Cc: Huang Ying <ying.huang@intel.com>
+Cc: Fengguang Wu <fengguang.wu@intel.com>
+Cc: Borislav Petkov <bp@suse.de>
+Cc: Yaowei Bai <baiyaowei@cmss.chinamobile.com>
+Cc: Takashi Iwai <tiwai@suse.de>
+Cc: Jerome Glisse <jglisse@redhat.com>
+Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org>
+Cc: Paul Mackerras <paulus@samba.org>
+Cc: linuxppc-dev@lists.ozlabs.org
+Cc: Keith Busch <keith.busch@intel.com>
+Signed-off-by: Dan Williams <dan.j.williams@intel.com>
+Signed-off-by: Michal Hocko <mhocko@suse.com>
+
+---
+ kernel/resource.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/kernel/resource.c
++++ b/kernel/resource.c
+@@ -408,7 +408,7 @@ static int __walk_iomem_res_desc(struct
+ int (*func)(struct resource *, void *))
+ {
+ u64 orig_end = res->end;
+- int ret = -1;
++ int ret = -EINVAL;
+
+ while ((res->start < res->end) &&
+ !find_next_iomem_res(res, desc, first_level_children_only)) {
+@@ -500,7 +500,7 @@ int walk_system_ram_range(unsigned long
+ struct resource res;
+ unsigned long pfn, end_pfn;
+ u64 orig_end;
+- int ret = -1;
++ int ret = -EINVAL;
+
+ res.start = (u64) start_pfn << PAGE_SHIFT;
+ res.end = ((u64)(start_pfn + nr_pages) << PAGE_SHIFT) - 1;
diff --git a/series.conf b/series.conf
index ba81d6e75a..fe80372ae6 100644
--- a/series.conf
+++ b/series.conf
@@ -44427,6 +44427,8 @@
patches.fixes/0004-mm-memory_hotplug-print-reason-for-the-offlining-fai.patch
patches.fixes/0005-mm-memory_hotplug-be-more-verbose-for-memory-offline.patch
patches.fixes/0001-mm-only-report-isolation-failures-when-offlining-mem.patch
+ patches.suse/0001-mm-devm_memremap_pages-kill-mapping-System-RAM-suppo.patch
+ patches.suse/0001-mm-devm_memremap_pages-fix-shutdown-handling.patch
patches.suse/mm-page_alloc-spread-allocations-across-zones-before-introducing-fragmentation.patch
patches.suse/mm-move-zone-watermark-accesses-behind-an-accessor.patch
patches.suse/mm-use-alloc_flags-to-record-if-kswapd-can-wake.patch
@@ -46257,6 +46259,23 @@
patches.drivers/scsi-hisi_sas-set-phy-linkrate-when-disconnected
patches.drivers/scsi-hisi_sas-send-hard-reset-to-clear-the-previous-affiliation-of-stp-target-port
patches.drivers/scsi-lpfc-Fix-error-codes-in-lpfc_sli4_pci_mem_setup.patch
+ patches.suse/0001-device-dax-Kill-dax_region-ida.patch
+ patches.suse/0001-device-dax-Kill-dax_region-base.patch
+ patches.suse/0001-device-dax-Remove-multi-resource-infrastructure.patch
+ patches.suse/0001-device-dax-Start-defining-a-dax-bus-model.patch
+ patches.suse/0001-device-dax-Introduce-bus-driver-model.patch
+ patches.suse/0001-device-dax-Move-resource-pinning-mapping-into-the-co.patch
+ patches.suse/0001-device-dax-Add-support-for-a-dax-override-driver.patch
+ patches.suse/0001-device-dax-Add-sys-class-dax-backwards-compatibility.patch
+ patches.suse/0001-acpi-nfit-device-dax-Identify-differentiated-memory-.patch
+ patches.suse/0001-device-dax-Auto-bind-device-after-successful-new_id.patch
+ patches.suse/0001-device-dax-Add-a-target_node-attribute.patch
+ patches.suse/0001-device-dax-Add-a-modalias-attribute-to-DAX-bus-devic.patch
+ patches.suse/0001-mm-resource-Return-real-error-codes-from-walk-failur.patch
+ patches.suse/0001-mm-resource-Move-HMM-pr_debug-deeper-into-resource-c.patch
+ patches.suse/0001-mm-memory-hotplug-Allow-memory-resources-to-be-child.patch
+ patches.suse/0001-mm-resource-Let-walk_system_ram_range-search-child-r.patch
+ patches.suse/0001-device-dax-Hotplug-persistent-memory-for-use-like-no.patch
patches.fixes/9p-use-inode-i_lock-to-protect-i_size_write-under-32.patch
patches.fixes/9p-net-fix-memory-leak-in-p9_client_create.patch
patches.fixes/perf-x86-intel-fix-memory-corruption.patch
@@ -48030,6 +48049,9 @@
patches.drivers/iommu-vt-d-handle-pci-bridge-rmrr-device-scopes-in-intel_iommu_get_resv_regions
patches.drivers/iommu-amd-make-iommu_disable-safer
patches.drivers/iommu-use-right-function-to-get-group-for-device
+ patches.drivers/0001-EDAC-i10nm-Add-Intel-additional-Ice-Lake-support.patch
+ patches.drivers/0001-EDAC-i10nm-Check-ECC-enabling-status-per-channel.patch
+ patches.drivers/0001-EDAC-skx-i10nm-Fix-source-ID-register-offset.patch
patches.drivers/media-marvell-ccic-fix-DMA-s-g-desc-number-calculati.patch
patches.fixes/0001-media-cpia2_usb-first-wake-up-then-free-in-disconnec.patch
patches.drivers/media-vivid-fix-incorrect-assignment-operation-when-.patch
@@ -48284,6 +48306,7 @@
patches.drivers/PCI-Return-error-if-cannot-probe-VF.patch
patches.drivers/PCI-Always-allow-probing-with-driver_override.patch
patches.fixes/PCI-P2PDMA-Fix-missing-check-for-dma_virt_ops.patch
+ patches.fixes/0001-device-dax-fix-memory-and-resource-leak-if-hotplug-f.patch
patches.drivers/dmaengine-hsu-Revert-set-HSU_CH_MTSR-to-memory-width.patch
patches.drivers/clk-qcom-Fix-Wunused-const-variable.patch
patches.drivers/clk-tegra210-fix-PLLU-and-PLLU_OUT1.patch
@@ -48316,6 +48339,8 @@
patches.drivers/ALSA-hda-Optimize-resume-for-codecs-without-jack-det.patch
patches.drivers/ALSA-hda-Fix-intermittent-CORB-RIRB-stall-on-Intel-c.patch
patches.drivers/scsi-ibmvfc-fix-WARN_ON-during-event-pool-release.patch
+ patches.fixes/drivers-base-introduce-kill_device.patch
+ patches.fixes/libnvdimm-bus-prevent-duplicate-device_unregister-calls.patch
# davem/net
patches.fixes/bonding-Force-slave-speed-check-after-link-state-rec.patch
@@ -48328,10 +48353,6 @@
patches.suse/0005-MODSIGN-Allow-the-db-UEFI-variable-to-be-suppressed.patch
patches.suse/0006-modsign-Use-secondary-trust-keyring-for-module-signi.patch
- # nvdimm/nvdimm libnvdimm-fixes
- patches.fixes/drivers-base-introduce-kill_device.patch
- patches.fixes/libnvdimm-bus-prevent-duplicate-device_unregister-calls.patch
-
# out-of-tree patches
patches.drivers/firmware-arm_sdei-fix-wrong-of_node_put-in-init-function.patch
patches.drivers/net-mvpp2-fix-condition-for-setting-up-link-interrup.patch
diff --git a/supported.conf b/supported.conf
index 3fab6c9f8f..31e1aae51b 100644
--- a/supported.conf
+++ b/supported.conf
@@ -461,6 +461,9 @@
- drivers/crypto/s5p-sss
drivers/crypto/vmx/vmx-crypto # fate#319564
drivers/crypto/virtio/virtio_crypto
+ drivers/dax/kmem.ko
+ drivers/dax/pmem/dax_pmem_compat.ko
+ drivers/dax/pmem/dax_pmem_core.ko
drivers/dca/dca
drivers/devfreq/governor_passive
drivers/devfreq/governor_performance