[PATCH RFC 0/3] pci_hp: fix surprise removal hang during safe removal

Abhin Parekadan Jose <[email protected]>
Newsgroups dev.linux.lists.virtualization,org.kernel.vger.linux-kernel,org.kernel.vger.linux-pci
Message-ID <[email protected]>
This series is based on top of MST's RFC v5
([email protected]) and tries to address the architectural
gap identified by Lukas Wunner in that thread.

Context:

MST's RFC v5 adds disconnect_work infrastructure so drivers can be
notified of surprise removal. Lukas identified a race that the
series cannot address: if safe removal is already in progress when the
device is yanked, pciehp_ist() is blocked and cannot deliver the
disconnect event.

Potential fix:

I reproduced this with a simple edu device driver (patch 1) that blocks
in remove() waiting for an interrupt. Same as blk_mq_freeze_queue_wait().

deadlock in pciehp_ist() is avoided by adding a workaround in pciehp_isr() (patch 3)
where a disconnect_work is scheduled and as this is a different thread it runs and
dispatches the disconnect event to the driver. The driver can then unblock and complete
the remove() and thus breaking the deadlock and also overcoming the problem of
not waiting in pciehp_isr().This is only schduled if the PDS is set to 0
indicating that there is no card attached at this slot in pciehp_isr().

Tested using qemu:
- Hacked the edu device to raise a delayed interrupt.
- Hacked qemu to actually act like suprise removal by adding a simple monitor cmd
  `pcie_surprise_del` to remove the device and genrate PDC=1, DLLSC = 1 and PDS=0.
1. Launched qemu with the edu device:
    `-device pcie-root-port,id=rp1,chassis=1,slot=1   -device edu,bus=rp1,id=edu0`
2. Ran `echo 1 > /sys/bus/pci/devices/0000:01:00.0/remove` to start safe removal
3. Ran `pcie_surprise_del edu0` to surprise remove the device while safe removal
    is in progress.
4. Verified that `edu_remove()` and `edu_disconnect()` are called.

Without the fix: remove() hangs permanently.
With the fix: pciehp_isr() fires, pciehp_disconnect_work() schedules
pci_dev_set_disconnected(), edu_disconnect() completes the wait, remove()
proceeds.

Would this be a viable approach?

Assisted-by: Claude:claude-sonnet-4-6

Abhin Parekadan Jose (3):
  misc: add edu_srpoc surprise removal POC driver
  pciehp: add disconnect_work work_struct
  pciehp_hpc: workaround to not wait in pciehp_isr on surprise removal

 drivers/misc/Makefile            |   1 +
 drivers/misc/edu_srpoc.c         | 180 +++++++++++++++++++++++++++++++
 drivers/pci/hotplug/pciehp.h     |   1 +
 drivers/pci/hotplug/pciehp_hpc.c |  47 ++++++++
 4 files changed, 229 insertions(+)
 create mode 100644 drivers/misc/edu_srpoc.c

--
2.51.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.