diff --git a/drivers/platform/x86/amd/hsmp/acpi.c b/drivers/platform/x86/amd/hsmp/acpi.c index 72f68cef1297..a23797bd1dd5 100644 --- a/drivers/platform/x86/amd/hsmp/acpi.c +++ b/drivers/platform/x86/amd/hsmp/acpi.c @@ -15,12 +15,15 @@ #include #include #include +#include #include #include #include #include +#include #include #include +#include #include #include #include @@ -482,11 +485,20 @@ static ssize_t hsmp_freq_limit_source_show(struct device *dev, struct device_att return len; } +/* + * Bring up one ACPI HSMP socket: parse its ACPI table, run the mailbox + * handshake and register its sysfs/hwmon interfaces. + * + * Called with hsmp_sock_rwsem held for write by hsmp_acpi_probe(), so the + * per-socket bring-up cannot race a concurrent probe or remove. + */ static int init_acpi(struct device *dev) { u16 sock_ind; int ret; + lockdep_assert_held_write(&hsmp_sock_rwsem); + ret = hsmp_get_uid(dev, &sock_ind); if (ret) return ret; @@ -607,6 +619,14 @@ static int hsmp_acpi_probe(struct platform_device *pdev) if (!hsmp_pdev) return -ENOMEM; + /* + * Multiple ACPI socket devices probe in parallel, but the is_probed + * handshake and the one-time socket-array allocation below must run + * exactly once. Serialize the whole bring-up against concurrent + * probe/remove by holding the socket rwsem for write. + */ + guard(rwsem_write)(&hsmp_sock_rwsem); + if (!hsmp_pdev->is_probed) { hsmp_pdev->num_sockets = topology_max_packages(); if (!hsmp_pdev->num_sockets) { @@ -642,6 +662,8 @@ static int hsmp_acpi_probe(struct platform_device *pdev) static void hsmp_acpi_remove(struct platform_device *pdev) { + guard(rwsem_write)(&hsmp_sock_rwsem); + /* * We register only one misc_device even on multi-socket system. * So, deregister should happen only once. diff --git a/drivers/platform/x86/amd/hsmp/hsmp.c b/drivers/platform/x86/amd/hsmp/hsmp.c index 1a87931136fd..e9c17698983c 100644 --- a/drivers/platform/x86/amd/hsmp/hsmp.c +++ b/drivers/platform/x86/amd/hsmp/hsmp.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include @@ -40,6 +41,14 @@ static struct hsmp_plat_device hsmp_pdev; +/* + * Serializes AMD HSMP socket bring-up and teardown: ACPI probe and remove take + * it for write so concurrent per-socket probes cannot race the is_probed + * handshake or the one-time socket-array allocation. + */ +DECLARE_RWSEM(hsmp_sock_rwsem); +EXPORT_SYMBOL_NS_GPL(hsmp_sock_rwsem, "AMD_HSMP"); + /* * Send a message to the HSMP port via PCI-e config space registers * or by writing to MMIO space. diff --git a/drivers/platform/x86/amd/hsmp/hsmp.h b/drivers/platform/x86/amd/hsmp/hsmp.h index 0509a442eaae..129200d0cf81 100644 --- a/drivers/platform/x86/amd/hsmp/hsmp.h +++ b/drivers/platform/x86/amd/hsmp/hsmp.h @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -71,4 +72,10 @@ int hsmp_create_sensor(struct device *dev, u16 sock_ind); static inline int hsmp_create_sensor(struct device *dev, u16 sock_ind) { return 0; } #endif int hsmp_msg_get_nargs(u16 sock_ind, u32 msg_id, u32 *data, u8 num_args); + +/* + * Serializes HSMP socket bring-up and teardown. ACPI probe and remove take it + * for write. + */ +extern struct rw_semaphore hsmp_sock_rwsem; #endif /* HSMP_H */