[PATCH v7 1/6] platform/x86/amd/hsmp: Serialize ACPI HSMP probe and remove with an rwsem
Muralidhara M K <[email protected]>
| Newsgroups | org.kernel.vger.platform-driver-x86,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <[email protected]> |
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 <[email protected]> --- drivers/platform/x86/amd/hsmp/acpi.c | 22 ++++++++++++++++++++++ drivers/platform/x86/amd/hsmp/hsmp.c | 9 +++++++++ drivers/platform/x86/amd/hsmp/hsmp.h | 7 +++++++ 3 files changed, 38 insertions(+) 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 <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. 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 <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. 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 <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 */ -- 2.34.1