summaryrefslogtreecommitdiff
path: root/drivers/base
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2021-07-30 00:51:47 +0300
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2021-08-18 09:59:17 +0300
commit312730cd15e097c11c4d0a0b8583a89a9ffd3d96 (patch)
tree9c644bf1d82279c78c5d876cff9cdbca3bc2e3ed /drivers/base
parent724d0a9850866ce2cc7df71b1497f49066535ccc (diff)
downloadlinux-312730cd15e097c11c4d0a0b8583a89a9ffd3d96.tar.xz
PCI/MSI: Protect msi_desc::masked for multi-MSI
commit 77e89afc25f30abd56e76a809ee2884d7c1b63ce upstream. Multi-MSI uses a single MSI descriptor and there is a single mask register when the device supports per vector masking. To avoid reading back the mask register the value is cached in the MSI descriptor and updates are done by clearing and setting bits in the cache and writing it to the device. But nothing protects msi_desc::masked and the mask register from being modified concurrently on two different CPUs for two different Linux interrupts which belong to the same multi-MSI descriptor. Add a lock to struct device and protect any operation on the mask and the mask register with it. This makes the update of msi_desc::masked unconditional, but there is no place which requires a modification of the hardware register without updating the masked cache. msi_mask_irq() is now an empty wrapper which will be cleaned up in follow up changes. The problem goes way back to the initial support of multi-MSI, but picking the commit which introduced the mask cache is a valid cut off point (2.6.30). Fixes: f2440d9acbe8 ("PCI MSI: Refactor interrupt masking code") Signed-off-by: Thomas Gleixner <tglx@linutronix.de> Tested-by: Marc Zyngier <maz@kernel.org> Reviewed-by: Marc Zyngier <maz@kernel.org> Cc: stable@vger.kernel.org Link: https://lore.kernel.org/r/20210729222542.726833414@linutronix.de Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/core.c1
1 files changed, 1 insertions, 0 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c
index 1157f9aea9c0..a364fe565007 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -2452,6 +2452,7 @@ void device_initialize(struct device *dev)
device_pm_init(dev);
set_dev_node(dev, -1);
#ifdef CONFIG_GENERIC_MSI_IRQ
+ raw_spin_lock_init(&dev->msi_lock);
INIT_LIST_HEAD(&dev->msi_list);
#endif
INIT_LIST_HEAD(&dev->links.consumers);