[PATCH 5/6] cxl: add CXL_REGION_SYSRAM_DEFAULT_* build options

Gregory Price posted 6 patches 4 weeks ago
[PATCH 5/6] cxl: add CXL_REGION_SYSRAM_DEFAULT_* build options
Posted by Gregory Price 4 weeks ago
DEFAULT_OFFLINE: Blocks will be offline after being created.
DEFAULT_ONLINE:  Blocks will be onlined in ZONE_MOVABLE
DEFAULT_ONLINE_NORMAL: Blocks will be onliend in ZONE_NORMAL.

This prevents users from having to use the MHP auto-online build config,
which may cause misbehaviors with other devices hotplugging memory.

Signed-off-by: Gregory Price <gourry@gourry.net>
---
 drivers/cxl/Kconfig                      | 40 ++++++++++
 drivers/cxl/core/memctrl/sysram_region.c | 94 ++++++++++++++++++------
 2 files changed, 110 insertions(+), 24 deletions(-)

diff --git a/drivers/cxl/Kconfig b/drivers/cxl/Kconfig
index 5aed1524f8f1..3e087c9d5ea7 100644
--- a/drivers/cxl/Kconfig
+++ b/drivers/cxl/Kconfig
@@ -243,6 +243,46 @@ config CXL_REGION_CTRL_AUTO_SYSRAM
 
 endchoice
 
+choice
+	prompt "CXL SYSRAM Auto Online Mode"
+	depends on CXL_REGION
+	default CXL_REGION_SYSRAM_DEFAULT_OFFLINE
+	help
+	  Select whether CXL memory hotplugged as System RAM should be
+	  automatically onlined and in which zone. This applies when the
+	  region controller is set to SYSRAM (either explicitly or via
+	  the auto control mode).
+
+config CXL_REGION_SYSRAM_DEFAULT_OFFLINE
+	bool "Offline"
+	help
+	  Leave the memory offline after hotplug. The memory must be
+	  manually onlined via sysfs or other mechanisms before it can
+	  be used by the system.
+
+	  This is the default and most conservative option.
+
+config CXL_REGION_SYSRAM_DEFAULT_ONLINE
+	bool "Online (Movable)"
+	help
+	  Automatically online the memory as ZONE_MOVABLE after hotplug.
+	  ZONE_MOVABLE memory can be used for user pages and is eligible
+	  for memory hotremove, but cannot be used for kernel allocations.
+
+	  Select this for memory that may need to be hotremoved later.
+
+config CXL_REGION_SYSRAM_DEFAULT_ONLINE_NORMAL
+	bool "Online (Normal)"
+	help
+	  Automatically online the memory as ZONE_NORMAL after hotplug.
+	  ZONE_NORMAL memory can be used for all allocations including
+	  kernel allocations, but may not be hotremovable.
+
+	  Select this for maximum memory utilization when hotremove is
+	  not required.
+
+endchoice
+
 config CXL_REGION_INVALIDATION_TEST
 	bool "CXL: Region Cache Management Bypass (TEST)"
 	depends on CXL_REGION
diff --git a/drivers/cxl/core/memctrl/sysram_region.c b/drivers/cxl/core/memctrl/sysram_region.c
index a7570c8a54e1..2e2d9b59a725 100644
--- a/drivers/cxl/core/memctrl/sysram_region.c
+++ b/drivers/cxl/core/memctrl/sysram_region.c
@@ -129,12 +129,69 @@ static int offline_memory_block_cb(struct memory_block *mem, void *arg)
 	return *rc;
 }
 
+static int cxl_sysram_online_memory(struct range *range, int online_type)
+{
+	struct online_memory_cb_arg cb_arg = {
+		.online_type = online_type,
+		.rc = 0,
+	};
+	int rc;
+
+	rc = walk_memory_blocks(range->start, range_len(range),
+				&cb_arg, online_memory_block_cb);
+	if (!rc)
+		rc = cb_arg.rc;
+
+	return rc;
+}
+
+static int cxl_sysram_offline_memory(struct range *range)
+{
+	int offline_rc = 0;
+	int rc;
+
+	rc = walk_memory_blocks(range->start, range_len(range),
+				&offline_rc, offline_memory_block_cb);
+	if (!rc)
+		rc = offline_rc;
+
+	return rc;
+}
+
+static int cxl_sysram_auto_online(struct device *dev, struct range *range)
+{
+	int online_type;
+	int rc;
+
+	if (IS_ENABLED(CONFIG_CXL_REGION_SYSRAM_DEFAULT_OFFLINE))
+		return 0;
+
+	if (IS_ENABLED(CONFIG_CXL_REGION_SYSRAM_DEFAULT_ONLINE))
+		online_type = MMOP_ONLINE_MOVABLE;
+	else if (IS_ENABLED(CONFIG_CXL_REGION_SYSRAM_DEFAULT_ONLINE_NORMAL))
+		online_type = MMOP_ONLINE_KERNEL;
+	else
+		online_type = MMOP_ONLINE_MOVABLE;
+
+	rc = lock_device_hotplug_sysfs();
+	if (rc)
+		return rc;
+
+	rc = cxl_sysram_online_memory(range, online_type);
+
+	unlock_device_hotplug();
+
+	if (rc)
+		dev_warn(dev, "auto-online failed: %d\n", rc);
+
+	return rc;
+}
+
 static ssize_t state_store(struct device *dev,
 			   struct device_attribute *attr,
 			   const char *buf, size_t len)
 {
 	struct cxl_region *cxlr = to_cxl_region(dev);
-	struct online_memory_cb_arg cb_arg;
 	struct range range;
 	int rc;
 
@@ -149,30 +206,14 @@ static ssize_t state_store(struct device *dev,
 	if (rc)
 		return rc;
 
-	if (sysfs_streq(buf, "online")) {
-		cb_arg.online_type = MMOP_ONLINE_MOVABLE;
-		cb_arg.rc = 0;
-		rc = walk_memory_blocks(range.start, range_len(&range),
-					&cb_arg, online_memory_block_cb);
-		if (!rc)
-			rc = cb_arg.rc;
-	} else if (sysfs_streq(buf, "online_normal")) {
-		cb_arg.online_type = MMOP_ONLINE;
-		cb_arg.rc = 0;
-		rc = walk_memory_blocks(range.start, range_len(&range),
-					&cb_arg, online_memory_block_cb);
-		if (!rc)
-			rc = cb_arg.rc;
-	} else if (sysfs_streq(buf, "offline")) {
-		int offline_rc = 0;
-
-		rc = walk_memory_blocks(range.start, range_len(&range),
-					&offline_rc, offline_memory_block_cb);
-		if (!rc)
-			rc = offline_rc;
-	} else {
+	if (sysfs_streq(buf, "online"))
+		rc = cxl_sysram_online_memory(&range, MMOP_ONLINE_MOVABLE);
+	else if (sysfs_streq(buf, "online_normal"))
+		rc = cxl_sysram_online_memory(&range, MMOP_ONLINE);
+	else if (sysfs_streq(buf, "offline"))
+		rc = cxl_sysram_offline_memory(&range);
+	else
 		rc = -EINVAL;
-	}
 
 	unlock_device_hotplug();
 
@@ -332,6 +373,10 @@ int devm_cxl_add_sysram_region(struct cxl_region *cxlr)
 	dev_dbg(dev, "%s: added %llu bytes as System RAM\n", dev_name(dev),
 		(unsigned long long)total_len);
 
+	rc = cxl_sysram_auto_online(dev, &range);
+	if (rc)
+		goto err_auto_online;
+
 	dev_set_drvdata(dev, data);
 	rc = devm_device_add_group(dev, &cxl_sysram_region_group);
 	if (rc)
@@ -341,6 +386,7 @@ int devm_cxl_add_sysram_region(struct cxl_region *cxlr)
 
 err_add_group:
 	dev_set_drvdata(dev, NULL);
+err_auto_online:
 	/* if this fails, memory cannot be removed from the system until reboot */
 	remove_memory(range.start, range_len(&range));
 err_add_memory:
-- 
2.52.0
Re: [PATCH 5/6] cxl: add CXL_REGION_SYSRAM_DEFAULT_* build options
Posted by Cheatham, Benjamin 4 weeks ago
On 1/12/2026 10:35 AM, Gregory Price wrote:
> DEFAULT_OFFLINE: Blocks will be offline after being created.
> DEFAULT_ONLINE:  Blocks will be onlined in ZONE_MOVABLE
> DEFAULT_ONLINE_NORMAL: Blocks will be onliend in ZONE_NORMAL.
> 
> This prevents users from having to use the MHP auto-online build config,
> which may cause misbehaviors with other devices hotplugging memory.

Isn't the MHP auto-online build config still used in some flows? A quick note on
when that option will still be used would be nice.
> 
> Signed-off-by: Gregory Price <gourry@gourry.net>
> ---
>  drivers/cxl/Kconfig                      | 40 ++++++++++
>  drivers/cxl/core/memctrl/sysram_region.c | 94 ++++++++++++++++++------
>  2 files changed, 110 insertions(+), 24 deletions(-)
> 
> diff --git a/drivers/cxl/Kconfig b/drivers/cxl/Kconfig
> index 5aed1524f8f1..3e087c9d5ea7 100644
> --- a/drivers/cxl/Kconfig
> +++ b/drivers/cxl/Kconfig
> @@ -243,6 +243,46 @@ config CXL_REGION_CTRL_AUTO_SYSRAM
>  
>  endchoice
>  
> +choice
> +	prompt "CXL SYSRAM Auto Online Mode"
> +	depends on CXL_REGION
> +	default CXL_REGION_SYSRAM_DEFAULT_OFFLINE
> +	help
> +	  Select whether CXL memory hotplugged as System RAM should be
> +	  automatically onlined and in which zone. This applies when the
> +	  region controller is set to SYSRAM (either explicitly or via
> +	  the auto control mode).
> +
> +config CXL_REGION_SYSRAM_DEFAULT_OFFLINE
> +	bool "Offline"
> +	help
> +	  Leave the memory offline after hotplug. The memory must be
> +	  manually onlined via sysfs or other mechanisms before it can
> +	  be used by the system.
> +
> +	  This is the default and most conservative option.
> +
> +config CXL_REGION_SYSRAM_DEFAULT_ONLINE
> +	bool "Online (Movable)"
> +	help
> +	  Automatically online the memory as ZONE_MOVABLE after hotplug.
> +	  ZONE_MOVABLE memory can be used for user pages and is eligible
> +	  for memory hotremove, but cannot be used for kernel allocations.
> +
> +	  Select this for memory that may need to be hotremoved later.
> +
> +config CXL_REGION_SYSRAM_DEFAULT_ONLINE_NORMAL
> +	bool "Online (Normal)"
> +	help
> +	  Automatically online the memory as ZONE_NORMAL after hotplug.
> +	  ZONE_NORMAL memory can be used for all allocations including
> +	  kernel allocations, but may not be hotremovable.
> +
> +	  Select this for maximum memory utilization when hotremove is
> +	  not required.
> +
> +endchoice
> +
>  config CXL_REGION_INVALIDATION_TEST
>  	bool "CXL: Region Cache Management Bypass (TEST)"
>  	depends on CXL_REGION
> diff --git a/drivers/cxl/core/memctrl/sysram_region.c b/drivers/cxl/core/memctrl/sysram_region.c
> index a7570c8a54e1..2e2d9b59a725 100644
> --- a/drivers/cxl/core/memctrl/sysram_region.c
> +++ b/drivers/cxl/core/memctrl/sysram_region.c
> @@ -129,12 +129,69 @@ static int offline_memory_block_cb(struct memory_block *mem, void *arg)
>  	return *rc;
>  }
>  
> +static int cxl_sysram_online_memory(struct range *range, int online_type)
> +{
> +	struct online_memory_cb_arg cb_arg = {
> +		.online_type = online_type,
> +		.rc = 0,
> +	};
> +	int rc;
> +
> +	rc = walk_memory_blocks(range->start, range_len(range),
> +				&cb_arg, online_memory_block_cb);
> +	if (!rc)
> +		rc = cb_arg.rc;
> +
> +	return rc;
> +}
> +
> +static int cxl_sysram_offline_memory(struct range *range)
> +{
> +	int offline_rc = 0;
> +	int rc;
> +
> +	rc = walk_memory_blocks(range->start, range_len(range),
> +				&offline_rc, offline_memory_block_cb);
> +	if (!rc)
> +		rc = offline_rc;
> +
> +	return rc;
> +}

I think these two helpers can get moved into patch 2/6 when the 'store' attribute was defined. I don't
see anything that requires they're in this patch and it would help reduce churn.

> +
> +static int cxl_sysram_auto_online(struct device *dev, struct range *range)
> +{
> +	int online_type;
> +	int rc;
> +
> +	if (IS_ENABLED(CONFIG_CXL_REGION_SYSRAM_DEFAULT_OFFLINE))
> +		return 0;
> +
> +	if (IS_ENABLED(CONFIG_CXL_REGION_SYSRAM_DEFAULT_ONLINE))
> +		online_type = MMOP_ONLINE_MOVABLE;
> +	else if (IS_ENABLED(CONFIG_CXL_REGION_SYSRAM_DEFAULT_ONLINE_NORMAL))
> +		online_type = MMOP_ONLINE_KERNEL;
> +	else
> +		online_type = MMOP_ONLINE_MOVABLE;
> +
> +	rc = lock_device_hotplug_sysfs();
> +	if (rc)
> +		return rc;
> +
> +	rc = cxl_sysram_online_memory(range, online_type);
> +
> +	unlock_device_hotplug();
> +
> +	if (rc)
> +		dev_warn(dev, "auto-online failed: %d\n", rc);
> +
> +	return rc;
> +}
> +
>  static ssize_t state_store(struct device *dev,
>  			   struct device_attribute *attr,
>  			   const char *buf, size_t len)
>  {
>  	struct cxl_region *cxlr = to_cxl_region(dev);
> -	struct online_memory_cb_arg cb_arg;
>  	struct range range;
>  	int rc;
>  
> @@ -149,30 +206,14 @@ static ssize_t state_store(struct device *dev,
>  	if (rc)
>  		return rc;
>  
> -	if (sysfs_streq(buf, "online")) {
> -		cb_arg.online_type = MMOP_ONLINE_MOVABLE;
> -		cb_arg.rc = 0;
> -		rc = walk_memory_blocks(range.start, range_len(&range),
> -					&cb_arg, online_memory_block_cb);
> -		if (!rc)
> -			rc = cb_arg.rc;
> -	} else if (sysfs_streq(buf, "online_normal")) {
> -		cb_arg.online_type = MMOP_ONLINE;
> -		cb_arg.rc = 0;
> -		rc = walk_memory_blocks(range.start, range_len(&range),
> -					&cb_arg, online_memory_block_cb);
> -		if (!rc)
> -			rc = cb_arg.rc;
> -	} else if (sysfs_streq(buf, "offline")) {
> -		int offline_rc = 0;
> -
> -		rc = walk_memory_blocks(range.start, range_len(&range),
> -					&offline_rc, offline_memory_block_cb);
> -		if (!rc)
> -			rc = offline_rc;
> -	} else {
> +	if (sysfs_streq(buf, "online"))
> +		rc = cxl_sysram_online_memory(&range, MMOP_ONLINE_MOVABLE);
> +	else if (sysfs_streq(buf, "online_normal"))
> +		rc = cxl_sysram_online_memory(&range, MMOP_ONLINE);
> +	else if (sysfs_streq(buf, "offline"))
> +		rc = cxl_sysram_offline_memory(&range);
> +	else
>  		rc = -EINVAL;
> -	}
>  
>  	unlock_device_hotplug();
>  
> @@ -332,6 +373,10 @@ int devm_cxl_add_sysram_region(struct cxl_region *cxlr)
>  	dev_dbg(dev, "%s: added %llu bytes as System RAM\n", dev_name(dev),
>  		(unsigned long long)total_len);
>  
> +	rc = cxl_sysram_auto_online(dev, &range);
> +	if (rc)
> +		goto err_auto_online;
> +
>  	dev_set_drvdata(dev, data);
>  	rc = devm_device_add_group(dev, &cxl_sysram_region_group);
>  	if (rc)
> @@ -341,6 +386,7 @@ int devm_cxl_add_sysram_region(struct cxl_region *cxlr)
>  
>  err_add_group:
>  	dev_set_drvdata(dev, NULL);
> +err_auto_online:
>  	/* if this fails, memory cannot be removed from the system until reboot */
>  	remove_memory(range.start, range_len(&range));
>  err_add_memory:
Re: [PATCH 5/6] cxl: add CXL_REGION_SYSRAM_DEFAULT_* build options
Posted by Gregory Price 4 weeks ago
On Mon, Jan 12, 2026 at 03:11:00PM -0600, Cheatham, Benjamin wrote:
> On 1/12/2026 10:35 AM, Gregory Price wrote:
> > DEFAULT_OFFLINE: Blocks will be offline after being created.
> > DEFAULT_ONLINE:  Blocks will be onlined in ZONE_MOVABLE
> > DEFAULT_ONLINE_NORMAL: Blocks will be onliend in ZONE_NORMAL.
> > 
> > This prevents users from having to use the MHP auto-online build config,
> > which may cause misbehaviors with other devices hotplugging memory.
> 
> Isn't the MHP auto-online build config still used in some flows? A quick note on
> when that option will still be used would be nice.

It's definitely still in use, and in fact we use it to manage many
systems with BIOS configured decoders.

That option super-cedes this option, which... is probably problematic,
and David might want to chime in on whether improving the hotplug+online
pattern to include the intended zone should dictate its removal.

~Gregory

> > +static int cxl_sysram_offline_memory(struct range *range)
> > +{
> > +	int offline_rc = 0;
> > +	int rc;
> > +
> > +	rc = walk_memory_blocks(range->start, range_len(range),
> > +				&offline_rc, offline_memory_block_cb);
> > +	if (!rc)
> > +		rc = offline_rc;
> > +
> > +	return rc;
> > +}
> 
> I think these two helpers can get moved into patch 2/6 when the 'store' attribute was defined. I don't
> see anything that requires they're in this patch and it would help reduce churn.
> 

Yeah this'll get reworked with the interface rework.

Thanks again,
Gregory