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
