Extend the cxl_sysram region to support N_MEMORY_PRIVATE hotplug
via add_private_memory_driver_managed(). When a caller passes
private=true to devm_cxl_add_sysram(), the memory is registered
as a private node, isolating it from normal allocations and reclaim.

Signed-off-by: Gregory Price <[email protected]>
---
 drivers/cxl/core/core.h          |  2 +-
 drivers/cxl/core/region_sysram.c | 50 +++++++++++++++++++++++++-------
 drivers/cxl/cxl.h                |  9 ++++--
 3 files changed, 48 insertions(+), 13 deletions(-)

diff --git a/drivers/cxl/core/core.h b/drivers/cxl/core/core.h
index 973bbcae43f7..8ca3d6d41fe4 100644
--- a/drivers/cxl/core/core.h
+++ b/drivers/cxl/core/core.h
@@ -56,7 +56,7 @@ u64 cxl_dpa_to_hpa(struct cxl_region *cxlr, const struct 
cxl_memdev *cxlmd,
                   u64 dpa);
 int devm_cxl_add_dax_region(struct cxl_region *cxlr, enum dax_driver_type);
 int devm_cxl_add_pmem_region(struct cxl_region *cxlr);
-int devm_cxl_add_sysram(struct cxl_region *cxlr, enum mmop online_type);
+int devm_cxl_add_sysram(struct cxl_region *cxlr, bool private, enum mmop 
online_type);
 
 #else
 static inline u64 cxl_dpa_to_hpa(struct cxl_region *cxlr,
diff --git a/drivers/cxl/core/region_sysram.c b/drivers/cxl/core/region_sysram.c
index 47a415deb352..77aaa52e7332 100644
--- a/drivers/cxl/core/region_sysram.c
+++ b/drivers/cxl/core/region_sysram.c
@@ -85,12 +85,23 @@ static int sysram_hotplug_add(struct cxl_sysram *sysram, 
enum mmop online_type)
        /*
         * Ensure that future kexec'd kernels will not treat
         * this as RAM automatically.
+        *
+        * For private regions, use add_private_memory_driver_managed()
+        * to register as N_MEMORY_PRIVATE which isolates the memory from
+        * normal allocations and reclaim.
         */
-       rc = __add_memory_driver_managed(sysram->mgid,
-                                        sysram->hpa_range.start,
-                                        range_len(&sysram->hpa_range),
-                                        sysram_res_name, mhp_flags,
-                                        online_type);
+       if (sysram->private)
+               rc = add_private_memory_driver_managed(sysram->mgid,
+                                                      sysram->hpa_range.start,
+                                                      
range_len(&sysram->hpa_range),
+                                                      sysram_res_name, 
mhp_flags,
+                                                      online_type, 
&sysram->np);
+       else
+               rc = __add_memory_driver_managed(sysram->mgid,
+                                                sysram->hpa_range.start,
+                                                range_len(&sysram->hpa_range),
+                                                sysram_res_name, mhp_flags,
+                                                online_type);
        if (rc) {
                remove_resource(res);
                kfree(res);
@@ -108,10 +119,23 @@ static int sysram_hotplug_remove(struct cxl_sysram 
*sysram)
        if (!sysram->res)
                return 0;
 
-       rc = offline_and_remove_memory(sysram->hpa_range.start,
-                                      range_len(&sysram->hpa_range));
-       if (rc)
-               return rc;
+       if (sysram->private) {
+               rc = offline_and_remove_private_memory(sysram->numa_node,
+                                                      sysram->hpa_range.start,
+                                                      
range_len(&sysram->hpa_range));
+               /*
+                * -EBUSY means memory was removed but node_private_unregister()
+                * could not complete because other regions share the node.
+                * Continue to resource cleanup since the memory is gone.
+                */
+               if (rc && rc != -EBUSY)
+                       return rc;
+       } else {
+               rc = offline_and_remove_memory(sysram->hpa_range.start,
+                                              range_len(&sysram->hpa_range));
+               if (rc)
+                       return rc;
+       }
 
        if (sysram->res) {
                remove_resource(sysram->res);
@@ -257,7 +281,8 @@ static void sysram_unregister(void *_sysram)
        device_unregister(&sysram->dev);
 }
 
-int devm_cxl_add_sysram(struct cxl_region *cxlr, enum mmop online_type)
+int devm_cxl_add_sysram(struct cxl_region *cxlr, bool private,
+                       enum mmop online_type)
 {
        struct cxl_sysram *sysram __free(put_cxl_sysram) = NULL;
        struct memory_dev_type *mtype;
@@ -291,6 +316,11 @@ int devm_cxl_add_sysram(struct cxl_region *cxlr, enum mmop 
online_type)
        if (online_type >= 0)
                sysram->online_type = online_type;
 
+       /* Set up private node registration if requested */
+       sysram->private = private;
+       if (private)
+               sysram->np.owner = sysram;
+
        dev = &sysram->dev;
 
        rc = dev_set_name(dev, "sysram_region%d", cxlr->id);
diff --git a/drivers/cxl/cxl.h b/drivers/cxl/cxl.h
index 8e8342fd4fde..54e5f9ac59dc 100644
--- a/drivers/cxl/cxl.h
+++ b/drivers/cxl/cxl.h
@@ -10,6 +10,7 @@
 #include <linux/bitops.h>
 #include <linux/log2.h>
 #include <linux/node.h>
+#include <linux/node_private.h>
 #include <linux/io.h>
 #include <linux/range.h>
 #include <linux/dax.h>
@@ -619,6 +620,8 @@ struct cxl_dax_region {
  * @mgid: Memory group id
  * @mtype: Memory tier type
  * @numa_node: NUMA node for this memory
+ * @private: true if this region uses N_MEMORY_PRIVATE hotplug
+ * @np: private node registration state (valid when @private is true)
  *
  * Device that directly performs memory hotplug for CXL RAM regions.
  */
@@ -633,6 +636,8 @@ struct cxl_sysram {
        int mgid;
        struct memory_dev_type *mtype;
        int numa_node;
+       bool private;
+       struct node_private np;
 };
 
 /**
@@ -987,7 +992,7 @@ int cxl_add_to_region(struct cxl_endpoint_decoder *cxled);
 struct cxl_dax_region *to_cxl_dax_region(struct device *dev);
 struct cxl_sysram *to_cxl_sysram(struct device *dev);
 struct device *cxl_sysram_dev(struct cxl_sysram *sysram);
-int devm_cxl_add_sysram(struct cxl_region *cxlr, enum mmop online_type);
+int devm_cxl_add_sysram(struct cxl_region *cxlr, bool private, enum mmop 
online_type);
 int cxl_sysram_offline_and_remove(struct cxl_sysram *sysram);
 u64 cxl_port_get_spa_cache_alias(struct cxl_port *endpoint, u64 spa);
 #else
@@ -1011,7 +1016,7 @@ static inline struct cxl_sysram *to_cxl_sysram(struct 
device *dev)
 {
        return NULL;
 }
-static inline int devm_cxl_add_sysram(struct cxl_region *cxlr,
+static inline int devm_cxl_add_sysram(struct cxl_region *cxlr, bool private,
                                      enum mmop online_type)
 {
        return -ENXIO;
-- 
2.53.0


Reply via email to