linux-stable/drivers/pci
Rafael J. Wysocki 47d8aafcfe PCI/PM: Drain runtime-idle callbacks before driver removal
[ Upstream commit 9d5286d4e7 ]

A race condition between the .runtime_idle() callback and the .remove()
callback in the rtsx_pcr PCI driver leads to a kernel crash due to an
unhandled page fault [1].

The problem is that rtsx_pci_runtime_idle() is not expected to be running
after pm_runtime_get_sync() has been called, but the latter doesn't really
guarantee that.  It only guarantees that the suspend and resume callbacks
will not be running when it returns.

However, if a .runtime_idle() callback is already running when
pm_runtime_get_sync() is called, the latter will notice that the runtime PM
status of the device is RPM_ACTIVE and it will return right away without
waiting for the former to complete.  In fact, it cannot wait for
.runtime_idle() to complete because it may be called from that callback (it
arguably does not make much sense to do that, but it is not strictly
prohibited).

Thus in general, whoever is providing a .runtime_idle() callback needs
to protect it from running in parallel with whatever code runs after
pm_runtime_get_sync().  [Note that .runtime_idle() will not start after
pm_runtime_get_sync() has returned, but it may continue running then if it
has started earlier.]

One way to address that race condition is to call pm_runtime_barrier()
after pm_runtime_get_sync() (not before it, because a nonzero value of the
runtime PM usage counter is necessary to prevent runtime PM callbacks from
being invoked) to wait for the .runtime_idle() callback to complete should
it be running at that point.  A suitable place for doing that is in
pci_device_remove() which calls pm_runtime_get_sync() before removing the
driver, so it may as well call pm_runtime_barrier() subsequently, which
will prevent the race in question from occurring, not just in the rtsx_pcr
driver, but in any PCI drivers providing .runtime_idle() callbacks.

Link: https://lore.kernel.org/lkml/20240229062201.49500-1-kai.heng.feng@canonical.com/ # [1]
Link: https://lore.kernel.org/r/5761426.DvuYhMxLoT@kreacher
Reported-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
Tested-by: Ricky Wu <ricky_wu@realtek.com>
Acked-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
2024-04-13 12:51:25 +02:00
..
controller PCI: tegra: Fix OF node reference leak 2024-03-01 13:13:36 +01:00
endpoint
hotplug Revert "PCI: acpiphp: Reassign resources on bridge if necessary" 2023-12-20 15:41:19 +01:00
pcie PCI/DPC: Print all TLP Prefixes, not just the first 2024-03-26 18:22:19 -04:00
switch PCI: switchtec: Fix an error handling path in switchtec_pci_probe() 2024-03-26 18:22:20 -04:00
access.c
ats.c
bus.c
ecam.c
host-bridge.c
iov.c
irq.c PCI: Check for alloc failure in pci_request_irq() 2023-01-18 11:41:18 +01:00
Kconfig
Makefile
mmap.c
msi.c PCI/MSI: Prevent MSI hardware interrupt number truncation 2024-03-01 13:13:36 +01:00
of.c
p2pdma.c
pci-acpi.c PCI/sysfs: Protect driver's D3cold preference from user space 2023-11-28 16:50:18 +00:00
pci-bridge-emul.c
pci-bridge-emul.h
pci-driver.c PCI/PM: Drain runtime-idle callbacks before driver removal 2024-04-13 12:51:25 +02:00
pci-label.c
pci-mid.c
pci-pf-stub.c
pci-stub.c
pci-sysfs.c PCI/sysfs: Protect driver's D3cold preference from user space 2023-11-28 16:50:18 +00:00
pci.c PCI/PM: Avoid putting EloPOS E2/S2/H2 PCIe Ports in D3cold 2023-07-27 08:37:35 +02:00
pci.h PCI: Unify delay handling for reset and resume 2023-03-22 13:28:09 +01:00
probe.c
proc.c
quirks.c PCI: Mark 3ware-9650SE Root Port Extended Tags as broken 2024-03-26 18:22:21 -04:00
remove.c
rom.c
search.c
setup-bus.c
setup-irq.c
setup-res.c PCI: Sanitise firmware BAR assignments behind a PCI-PCI bridge 2022-10-26 13:22:16 +02:00
slot.c
syscall.c
vc.c
vpd.c
xen-pcifront.c