platform/x86/amd/hsmp: Serialize ACPI HSMP probe and remove with an rwsem

Add hsmp_sock_rwsem and export it, then hold it for write across ACPI
probe, remove and init_acpi() so concurrent per-socket platform probes
cannot race the is_probed handshake or the one-time socket-array
allocation. Use lockdep_assert_held_write() in init_acpi() to catch
incorrect locking under lockdep.

An rw_semaphore is used rather than a plain mutex because an upcoming
change adds a read side so data-plane messages run concurrently with each
other while probe/remove hold it for write to drain in-flight messages.
Introducing it as an rwsem now keeps the lock type stable across that
change.

Signed-off-by: Muralidhara M K <muralidhara.mk@amd.com>
Link: https://patch.msgid.link/20260723094656.3806028-2-muralidhara.mk@amd.com
Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
This commit is contained in:
Muralidhara M K 2026-07-23 15:16:51 +05:30 committed by Ilpo Järvinen
parent 5029bff09e
commit 9c40a57258
No known key found for this signature in database
GPG Key ID: 59AC4F6153E5CE31
3 changed files with 38 additions and 0 deletions

View File

@ -15,12 +15,15 @@
#include <linux/array_size.h>
#include <linux/bits.h>
#include <linux/bitfield.h>
#include <linux/cleanup.h>
#include <linux/device.h>
#include <linux/dev_printk.h>
#include <linux/ioport.h>
#include <linux/kstrtox.h>
#include <linux/lockdep.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/rwsem.h>
#include <linux/string.h>
#include <linux/sysfs.h>
#include <linux/topology.h>
@ -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.

View File

@ -12,6 +12,7 @@
#include <linux/acpi.h>
#include <linux/delay.h>
#include <linux/device.h>
#include <linux/rwsem.h>
#include <linux/semaphore.h>
#include <linux/sysfs.h>
@ -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.

View File

@ -16,6 +16,7 @@
#include <linux/kconfig.h>
#include <linux/miscdevice.h>
#include <linux/pci.h>
#include <linux/rwsem.h>
#include <linux/semaphore.h>
#include <linux/sysfs.h>
@ -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 */