[PATCH v2] platform/x86/intel/tpmi: Clean up CPU mappings on offline

From: lirongqing

Date: Sat Nov 14 2026 - 09:29:57 EST


From: Li RongQing <lirongqing@xxxxxxxxx>

The driver adds each online CPU to tpmi_cpu_hash and to its power domain
mask. Neither entry is removed when the CPU goes offline, so the next
online transition calls hash_add() on an hlist node that is still
linked, corrupting the hash list.

Register an offline callback that removes the hash entry and clears the
CPU from its power domain mask.

The TPMI feature does not depend on CPU online/offline and can update the
MMIO area while a CPU is offline. There is currently no consumer that
reads the mapping data of an offlined CPU; if such a use case appears,
retaining the offline mapping can be added on top.

Fixes: 17ca2780458c ("platform/x86/intel: TPMI domain id and CPU mapping")
Signed-off-by: Li RongQing <lirongqing@xxxxxxxxx>
Acked-by: Srinivas Pandruvada <srinivas.pandruvada@xxxxxxxxxxxxxxx>
---
Changes in v2:

- Add Acked-by from Srinivas Pandruvada
- Rename the title
- Add a new line after guard()

drivers/platform/x86/intel/tpmi_power_domains.c | 20 +++++++++++++++++++-
1 file changed, 19 insertions(+), 1 deletion(-)

diff --git a/drivers/platform/x86/intel/tpmi_power_domains.c b/drivers/platform/x86/intel/tpmi_power_domains.c
index ebe052c..457abac 100644
--- a/drivers/platform/x86/intel/tpmi_power_domains.c
+++ b/drivers/platform/x86/intel/tpmi_power_domains.c
@@ -220,6 +220,24 @@ static int tpmi_cpu_online(unsigned int cpu)
return 0;
}

+static int tpmi_cpu_offline(unsigned int cpu)
+{
+ struct tpmi_cpu_info *info = &per_cpu(tpmi_cpu_info, cpu);
+ int index;
+
+ if (hlist_unhashed(&info->hnode) || !tpmi_domain_is_valid(info))
+ return 0;
+
+ index = info->pkg_id * MAX_POWER_DOMAINS + info->punit_domain_id;
+
+ guard(mutex)(&tpmi_lock);
+
+ cpumask_clear_cpu(cpu, &tpmi_power_domain_mask[index]);
+ hash_del(&info->hnode);
+
+ return 0;
+}
+
static int __init tpmi_init(void)
{
const struct x86_cpu_id *id;
@@ -249,7 +267,7 @@ static int __init tpmi_init(void)

ret = cpuhp_setup_state(CPUHP_AP_ONLINE_DYN,
"platform/x86/tpmi_power_domains:online",
- tpmi_cpu_online, NULL);
+ tpmi_cpu_online, tpmi_cpu_offline);
if (ret < 0)
goto free_domain_map;

--
2.9.4