acpi/hmat: hmat_register_target() refactor to address lockdep warning
Subsystems (2)
Dave Jiang
maintainerv4 cover acpi/hmat: hmat_register_target() refactor to address lockdep warning
v4:
- Refactor hmat_hotplug_target() (Jonathan)
- Fix fixes tag. (Jonathan)
This series has changes that refactor the hmat_register_target() function to clean up a lockdep warning.
Dave Jiang (2):
acpi/hmat: Return when generic target is updated acpi/hmat: Fix lockdep warning for hmem_register_resource()
drivers/acpi/numa/hmat.c | 60 ++++++++++++++++++++++------------------ 1 file changed, 33 insertions(+), 27 deletions(-)
base-commit: 6146a0f1dfae5d37442a9ddcba012add260bceb0
Signature · 1 line
2.51.1
Dave Jiang
maintainerPATCH RESEND v4 1/2 acpi/hmat: Return when generic target is updated
With the current code flow, once the generic target is updated target->registered is set and the remaining code is skipped. So return immediately instead of going through the checks and then skip.
---
no changes
--- drivers/acpi/numa/hmat.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)
drivers/acpi/numa/hmat.c +6 -5
@@ -888,12 +888,13 @@ static void hmat_register_target(struct memory_target *target)* Register generic port perf numbers. The nid may not be * initialized and is still NUMA_NO_NODE. */ -mutex_lock (&target_lock); -if (*(u16 *)target->gen_port_device_handle) { -hmat_update_generic_target (target); - target->registered = true; + scoped_guard(mutex, &target_lock) { +if (*(u16 *)target->gen_port_device_handle) { +hmat_update_generic_target (target); + target->registered = true; +return ; + } } -mutex_unlock (&target_lock);/* * Skip offline nodes. This can happen when memory
Signature · 1 line
2.51.1
Re: [RESEND PATCH v4 1/2] acpi/hmat: Return when generic target is updated
Quoted 7 lines · Dave Jiang
With the current code flow, once the generic target is updated
target->registeredis set and the remaining code is skipped. So return immediately instead of going through the checks and then skip.Reviewed-by Jonathan Cameron <[email protected]>Signed-off-by Dave Jiang <[email protected]>
Applied to cxl/next15e14267889bde30b7b82bc03432483222b4b42c
Quoted 29 lines
---
no changes--- drivers/acpi/numa/hmat.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-)drivers/acpi/numa/hmat.c +6
-5@@ -888,12 +888,13 @@ static void hmat_register_target(struct memory_target *target)* Register generic port perf numbers. The nid may not be * initialized and is still NUMA_NO_NODE. */ -mutex_lock (&target_lock); -if (*(u16 *)target->gen_port_device_handle) { -hmat_update_generic_target (target); - target->registered = true; + scoped_guard(mutex, &target_lock) { +if (*(u16 *)target->gen_port_device_handle) { +hmat_update_generic_target (target); + target->registered = true; +return ; + } } -mutex_unlock (&target_lock);/* * Skip offline nodes. This can happen when memory
Dave Jiang
maintainerPATCH RESEND v4 2/2 acpi/hmat: Fix lockdep warning for hmem_register_resource()
In reply to Dave JiangThe following lockdep splat was observed while kernel auto-online a CXL memory region:
======================================================
WARNING: possible circular locking dependency detected
6.17.0djtest+ #53 Tainted: G W
------------------------------------------------------
systemd-udevd/3334 is trying to acquire lock:ffffffff90346188 (hmem_resource_lock){+.+.}-{4:4}, at: hmem_register_resource+0x31/0x50
but task is already holding lock:ffffffff90338890 ((node_chain).rwsem){++++}-{4:4}, at: blocking_notifier_call_chain+0x2e/0x70
which lock already depends on the new lock.
[..]
Chain exists of: hmem_resource_lock --> mem_hotplug_lock --> (node_chain).rwsem Possible unsafe locking scenario:
CPU0 CPU1
---- ----
rlock((node_chain).rwsem);
lock(mem_hotplug_lock);
lock((node_chain).rwsem); lock(hmem_resource_lock);
The lock ordering can cause potential deadlock. There are instances where hmem_resource_lock is taken after (node_chain).rwsem, and vice versa.
Split out the target update section of hmat_register_target() so that hmat_callback() only envokes that section instead of attempt to register hmem devices that it does not need to.
---
v4:
- Fix fixes tag. (Jonathan)
- Refactor hmat_hotplug_target(). (Jonathan)
--- drivers/acpi/numa/hmat.c | 47 ++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 21 deletions(-)
drivers/acpi/numa/hmat.c +26 -21
@@ -874,10 +874,33 @@ static void hmat_register_target_devices(struct memory_target *target) } } -static void hmat_register_target (struct memory_target *target) +static void hmat_hotplug_target (struct memory_target *target) {int nid =pxm_to_node (target->memory_pxm); +/* +* Skip offline nodes. This can happen when memory +* marked EFI_MEMORY_SP, "specific purpose", is applied +* to all the memory in a proximity domain leading to +* the node being marked offline / unplugged, or if +* memory-only "hotplug" node is offline. +*/ +if (nid ==NUMA_NO_NODE || !node_online (nid)) +return ; + +guard (mutex)(&target_lock); +if (target->registered) +return ; + +hmat_register_target_initiators (target); +hmat_register_target_cache (target); +hmat_register_target_perf (target,ACCESS_COORDINATE_LOCAL ); +hmat_register_target_perf (target,ACCESS_COORDINATE_CPU ); + target->registered = true; +} + +static void hmat_register_target (struct memory_target *target) +{/* * Devices may belong to either an offline or online * node, so unconditionally add them.
@@ -896,25 +919,7 @@ static void hmat_register_target(struct memory_target *target) } } -/* -* Skip offline nodes. This can happen when memory -* marked EFI_MEMORY_SP, "specific purpose", is applied -* to all the memory in a proximity domain leading to -* the node being marked offline / unplugged, or if -* memory-only "hotplug" node is offline. -*/ -if (nid ==NUMA_NO_NODE || !node_online (nid)) -return ; - -mutex_lock (&target_lock); -if (!target->registered) { -hmat_register_target_initiators (target); -hmat_register_target_cache (target); -hmat_register_target_perf (target,ACCESS_COORDINATE_LOCAL ); -hmat_register_target_perf (target,ACCESS_COORDINATE_CPU ); - target->registered = true; - } -mutex_unlock (&target_lock); +hmat_hotplug_target (target); }static void hmat_register_targets (void )
@@ -940,7 +945,7 @@ static int hmat_callback(struct notifier_block *self,if (!target)return NOTIFY_OK ; -hmat_register_target (target); +hmat_hotplug_target (target);return NOTIFY_OK ; }
Signature · 1 line
2.51.1
Re: [RESEND PATCH v4 2/2] acpi/hmat: Fix lockdep warning for hmem_register_resource()
Quoted 25 lines · Dave Jiang
The following lockdep splat was observed while kernel auto-online a CXL memory region:
======================================================
WARNING: possible circular locking dependency detected
6.17.0djtest+ #53 Tainted: G W
------------------------------------------------------
systemd-udevd/3334 is trying to acquire lock:ffffffff90346188(hmem_resource_lock){+.+.}-{4:4}, at:hmem_register_resource+0x31/0x50but task is already holding lock:
ffffffff90338890((node_chain).rwsem){++++}-{4:4}, at:blocking_notifier_call_chain+0x2e/0x70which lock already depends on the new lock.
[..]Chain exists of: hmem_resource_lock --> mem_hotplug_lock --> (node_chain).rwsem Possible unsafe locking scenario:CPU0 CPU1 ---- ---- rlock((node_chain).rwsem); lock(mem_hotplug_lock); lock((node_chain).rwsem);
Quoted 8 lines
lock(hmem_resource_lock);The lock ordering can cause potential deadlock. There are instances where
hmem_resource_lockis taken after (node_chain).rwsem, and vice versa.Split out the target update section of
hmat_register_target()so thathmat_callback()only envokes that section instead of attempt to register
s/envokes/invokes/
Quoted 17 lines
hmem devices that it does not need to.
Fixes cf8741ac57ed ("ACPI: NUMA: HMAT: Register "soft reserved" memory as an "hmem" device")Signed-off-by Dave Jiang <[email protected]>---
v4:
- Fix fixes tag. (Jonathan)
- Refactorhmat_hotplug_target(). (Jonathan)--- drivers/acpi/numa/hmat.c | 47 ++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 21 deletions(-)drivers/acpi/numa/hmat.c +0
-0
drivers/acpi/numa/hmat.c static void hmat_register_target_devices(struct memory_target *target) · line 877
Quoted 5 lines
drivers/acpi/numa/hmat.c +1
-1@@ -874,10 +874,33 @@ static void hmat_register_target_devices(struct memory_target *target) } } -static void hmat_register_target (struct memory_target *target) +static void hmat_hotplug_target (struct memory_target *target)
Ah, this makes sense, but is quite a bit of churn with the new indentation and new function name which is a slightly odd fit since initial setup is not "hotplug". Is the following equivalent / easier to follow?
Either way,
drivers/acpi/numa/hmat.c +5 -11
@@ -878,22 +878,16 @@ static void hmat_register_target(struct memory_target *target) {int nid =pxm_to_node (target->memory_pxm); -/* -* Devices may belong to either an offline or online -* node, so unconditionally add them. -*/ -hmat_register_target_devices (target); -/* * Register generic port perf numbers. The nid may not be * initialized and is still NUMA_NO_NODE. */ -mutex_lock (&target_lock); +guard (mutex)(&target_lock);if (*(u16 *)target->gen_port_device_handle) {hmat_update_generic_target (target); target->registered = true; +return ; } -mutex_unlock (&target_lock);/* * Skip offline nodes. This can happen when memory
@@ -905,7 +899,6 @@ static void hmat_register_target(struct memory_target *target)if (nid ==NUMA_NO_NODE || !node_online (nid))return ; -mutex_lock (&target_lock);if (!target->registered) {hmat_register_target_initiators (target);hmat_register_target_cache (target);
@@ -913,15 +906,16 @@ static void hmat_register_target(struct memory_target *target)hmat_register_target_perf (target,ACCESS_COORDINATE_CPU ); target->registered = true; } -mutex_unlock (&target_lock); }static void hmat_register_targets (void ) {struct memory_target *target; -list_for_each_entry (target, &targets, node) +list_for_each_entry (target, &targets, node) { +hmat_register_target_devices (target);hmat_register_target (target); + } } static int hmat_callback(struct notifier_block *self,
Dave Jiang
maintainerRe: [RESEND PATCH v4 2/2] acpi/hmat: Fix lockdep warning for hmem_register_resource()
Quoted 57 lines · On 11/7/25 6:06 PM, [email protected] wrote:
Quoted 25 lines · Dave Jiang
The following lockdep splat was observed while kernel auto-online a CXL memory region:
======================================================
WARNING: possible circular locking dependency detected
6.17.0djtest+ #53 Tainted: G W
------------------------------------------------------
systemd-udevd/3334 is trying to acquire lock:ffffffff90346188(hmem_resource_lock){+.+.}-{4:4}, at:hmem_register_resource+0x31/0x50but task is already holding lock:
ffffffff90338890((node_chain).rwsem){++++}-{4:4}, at:blocking_notifier_call_chain+0x2e/0x70which lock already depends on the new lock.
[..]Chain exists of: hmem_resource_lock --> mem_hotplug_lock --> (node_chain).rwsem Possible unsafe locking scenario:CPU0 CPU1 ---- ---- rlock((node_chain).rwsem); lock(mem_hotplug_lock); lock((node_chain).rwsem);Quoted 8 lines
lock(hmem_resource_lock);The lock ordering can cause potential deadlock. There are instances where
hmem_resource_lockis taken after (node_chain).rwsem, and vice versa.Split out the target update section of
hmat_register_target()so thathmat_callback()only envokes that section instead of attempt to registers/envokes/invokes/
Quoted 20 lines
hmem devices that it does not need to.
Fixes cf8741ac57ed ("ACPI: NUMA: HMAT: Register "soft reserved" memory as an "hmem" device")Signed-off-by Dave Jiang <[email protected]>---
v4:
- Fix fixes tag. (Jonathan)
- Refactorhmat_hotplug_target(). (Jonathan)--- drivers/acpi/numa/hmat.c | 47 ++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 21 deletions(-)drivers/acpi/numa/hmat.c +0
-0@@ -874,10 +874,33 @@ static void hmat_register_target_devices(struct memory_target *target) } }
Quoted 7 lines
drivers/acpi/numa/hmat.c static void hmat_register_target_devices(struct memory_target *target) · line 877
Quoted 2 lines
drivers/acpi/numa/hmat.c +1
-1-static void hmat_register_target (struct memory_target *target) +static void hmat_hotplug_target (struct memory_target *target)Ah, this makes sense, but is quite a bit of churn with the new indentation and new function name which is a slightly odd fit since initial setup is not "hotplug". Is the following equivalent / easier to follow?
Yes and no. We also need to remove the generic target block out of the hotplug path. So I'll just keep the original version.
DJ
Quoted 61 lines
Either way,
Reviewed-by Dan Williams <[email protected]>drivers/acpi/numa/hmat.c +5
-11@@ -878,22 +878,16 @@ static void hmat_register_target(struct memory_target *target) {int nid =pxm_to_node (target->memory_pxm); -/* -* Devices may belong to either an offline or online -* node, so unconditionally add them. -*/ -hmat_register_target_devices (target); -/* * Register generic port perf numbers. The nid may not be * initialized and is still NUMA_NO_NODE. */ -mutex_lock (&target_lock); +guard (mutex)(&target_lock);if (*(u16 *)target->gen_port_device_handle) {hmat_update_generic_target (target); target->registered = true; +return ; } -mutex_unlock (&target_lock);/* * Skip offline nodes. This can happen when memory @@ -905,7 +899,6 @@ static void hmat_register_target(struct memory_target *target)if (nid ==NUMA_NO_NODE || !node_online (nid))return ; -mutex_lock (&target_lock);if (!target->registered) {hmat_register_target_initiators (target);hmat_register_target_cache (target);@@ -913,15 +906,16 @@ static void hmat_register_target(struct memory_target *target)hmat_register_target_perf (target,ACCESS_COORDINATE_CPU ); target->registered = true; } -mutex_unlock (&target_lock); }static void hmat_register_targets (void ) {struct memory_target *target; -list_for_each_entry (target, &targets, node) +list_for_each_entry (target, &targets, node) { +hmat_register_target_devices (target);hmat_register_target (target); + } } static int hmat_callback(struct notifier_block *self,
Re: [RESEND PATCH v4 2/2] acpi/hmat: Fix lockdep warning for hmem_register_resource()
In reply to Dave JiangQuoted 31 lines · On Wed, 5 Nov 2025 16:51:15 -0700 Dave Jiang <[email protected]> wrote:
The following lockdep splat was observed while kernel auto-online a CXL memory region:
======================================================
WARNING: possible circular locking dependency detected
6.17.0djtest+ #53 Tainted: G W
------------------------------------------------------
systemd-udevd/3334 is trying to acquire lock:ffffffff90346188(hmem_resource_lock){+.+.}-{4:4}, at:hmem_register_resource+0x31/0x50but task is already holding lock:
ffffffff90338890((node_chain).rwsem){++++}-{4:4}, at:blocking_notifier_call_chain+0x2e/0x70which lock already depends on the new lock.
[..]Chain exists of: hmem_resource_lock --> mem_hotplug_lock --> (node_chain).rwsem Possible unsafe locking scenario:CPU0 CPU1 ---- ---- rlock((node_chain).rwsem); lock(mem_hotplug_lock); lock((node_chain).rwsem);
lock(hmem_resource_lock);The lock ordering can cause potential deadlock. There are instances where
hmem_resource_lockis taken after (node_chain).rwsem, and vice versa.
Quoted 6 lines
Split out the target update section of
hmat_register_target()so thathmat_callback()only envokes that section instead of attempt to register hmem devices that it does not need to.Fixes cf8741ac57ed ("ACPI: NUMA: HMAT: Register "soft reserved" memory as an "hmem" device")Signed-off-by Dave Jiang <[email protected]>
Trivial inline. I'm also fine with the version Dan posted.
Quoted 17 lines
---
v4:
- Fix fixes tag. (Jonathan)
- Refactorhmat_hotplug_target(). (Jonathan)--- drivers/acpi/numa/hmat.c | 47 ++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 21 deletions(-)drivers/acpi/numa/hmat.c +0
-1@@ -874,10 +874,33 @@ static void hmat_register_target_devices(struct memory_target *target) } } -static void hmat_register_target (struct memory_target *target)
drivers/acpi/numa/hmat.c static void hmat_register_target_devices(struct memory_target *target) · line 886
Quoted 10 lines
drivers/acpi/numa/hmat.c +7
-0+static void hmat_hotplug_target (struct memory_target *target) {int nid =pxm_to_node (target->memory_pxm); +/* +* Skip offline nodes. This can happen when memory +* marked EFI_MEMORY_SP, "specific purpose", is applied +* to all the memory in a proximity domain leading to +* the node being marked offline / unplugged, or if +* memory-only "hotplug" node is offline.
If this version goes forwards, rewrap closer to 80 chars. I guess it ended up short in some previous refactor.
Quoted 56 lines
drivers/acpi/numa/hmat.c +19
-20+*/ +if (nid ==NUMA_NO_NODE || !node_online (nid)) +return ; + +guard (mutex)(&target_lock); +if (target->registered) +return ; + +hmat_register_target_initiators (target); +hmat_register_target_cache (target); +hmat_register_target_perf (target,ACCESS_COORDINATE_LOCAL ); +hmat_register_target_perf (target,ACCESS_COORDINATE_CPU ); + target->registered = true; +} + +static void hmat_register_target (struct memory_target *target) +{/* * Devices may belong to either an offline or online * node, so unconditionally add them. @@ -896,25 +919,7 @@ static void hmat_register_target(struct memory_target *target) } } -/* -* Skip offline nodes. This can happen when memory -* marked EFI_MEMORY_SP, "specific purpose", is applied -* to all the memory in a proximity domain leading to -* the node being marked offline / unplugged, or if -* memory-only "hotplug" node is offline. -*/ -if (nid ==NUMA_NO_NODE || !node_online (nid)) -return ; - -mutex_lock (&target_lock); -if (!target->registered) { -hmat_register_target_initiators (target); -hmat_register_target_cache (target); -hmat_register_target_perf (target,ACCESS_COORDINATE_LOCAL ); -hmat_register_target_perf (target,ACCESS_COORDINATE_CPU ); - target->registered = true; - } -mutex_unlock (&target_lock); +hmat_hotplug_target (target); }static void hmat_register_targets (void )@@ -940,7 +945,7 @@ static int hmat_callback(struct notifier_block *self,if (!target)return NOTIFY_OK ; -hmat_register_target (target); +hmat_hotplug_target (target);return NOTIFY_OK ; }
Re: [RESEND PATCH v4 2/2] acpi/hmat: Fix lockdep warning for hmem_register_resource()
In reply to Dave JiangQuoted 31 lines · Dave Jiang
The following lockdep splat was observed while kernel auto-online a CXL memory region:
======================================================
WARNING: possible circular locking dependency detected
6.17.0djtest+ #53 Tainted: G W
------------------------------------------------------
systemd-udevd/3334 is trying to acquire lock:ffffffff90346188(hmem_resource_lock){+.+.}-{4:4}, at:hmem_register_resource+0x31/0x50but task is already holding lock:
ffffffff90338890((node_chain).rwsem){++++}-{4:4}, at:blocking_notifier_call_chain+0x2e/0x70which lock already depends on the new lock.
[..]Chain exists of: hmem_resource_lock --> mem_hotplug_lock --> (node_chain).rwsem Possible unsafe locking scenario:CPU0 CPU1 ---- ---- rlock((node_chain).rwsem); lock(mem_hotplug_lock); lock((node_chain).rwsem);
lock(hmem_resource_lock);The lock ordering can cause potential deadlock. There are instances where
hmem_resource_lockis taken after (node_chain).rwsem, and vice versa.
Quoted 6 lines
Split out the target update section of
hmat_register_target()so thathmat_callback()only envokes that section instead of attempt to register hmem devices that it does not need to.Fixes cf8741ac57ed ("ACPI: NUMA: HMAT: Register "soft reserved" memory as an "hmem" device")Signed-off-by Dave Jiang <[email protected]>
Applied to cxl/fixes71cd75e2b101a31d09f031e132a6ad04c911e164
Quoted 83 lines
---
v4:
- Fix fixes tag. (Jonathan)
- Refactorhmat_hotplug_target(). (Jonathan)--- drivers/acpi/numa/hmat.c | 47 ++++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 21 deletions(-)drivers/acpi/numa/hmat.c +26
-21@@ -874,10 +874,33 @@ static void hmat_register_target_devices(struct memory_target *target) } } -static void hmat_register_target (struct memory_target *target) +static void hmat_hotplug_target (struct memory_target *target) {int nid =pxm_to_node (target->memory_pxm); +/* +* Skip offline nodes. This can happen when memory +* marked EFI_MEMORY_SP, "specific purpose", is applied +* to all the memory in a proximity domain leading to +* the node being marked offline / unplugged, or if +* memory-only "hotplug" node is offline. +*/ +if (nid ==NUMA_NO_NODE || !node_online (nid)) +return ; + +guard (mutex)(&target_lock); +if (target->registered) +return ; + +hmat_register_target_initiators (target); +hmat_register_target_cache (target); +hmat_register_target_perf (target,ACCESS_COORDINATE_LOCAL ); +hmat_register_target_perf (target,ACCESS_COORDINATE_CPU ); + target->registered = true; +} + +static void hmat_register_target (struct memory_target *target) +{/* * Devices may belong to either an offline or online * node, so unconditionally add them. @@ -896,25 +919,7 @@ static void hmat_register_target(struct memory_target *target) } } -/* -* Skip offline nodes. This can happen when memory -* marked EFI_MEMORY_SP, "specific purpose", is applied -* to all the memory in a proximity domain leading to -* the node being marked offline / unplugged, or if -* memory-only "hotplug" node is offline. -*/ -if (nid ==NUMA_NO_NODE || !node_online (nid)) -return ; - -mutex_lock (&target_lock); -if (!target->registered) { -hmat_register_target_initiators (target); -hmat_register_target_cache (target); -hmat_register_target_perf (target,ACCESS_COORDINATE_LOCAL ); -hmat_register_target_perf (target,ACCESS_COORDINATE_CPU ); - target->registered = true; - } -mutex_unlock (&target_lock); +hmat_hotplug_target (target); }static void hmat_register_targets (void )@@ -940,7 +945,7 @@ static int hmat_callback(struct notifier_block *self,if (!target)return NOTIFY_OK ; -hmat_register_target (target); +hmat_hotplug_target (target);return NOTIFY_OK ; }