[PATCH] scsi: vmw_pvscsi: only free a requested IRQ

From: Runyu Xiao

Date: Mon Sep 21 2026 - 11:41:21 EST


pvscsi_shutdown_intr() is used by both normal teardown and probe failure
paths. It unconditionally calls free_irq(), even when probe fails before
request_irq() or pci_alloc_irq_vectors() has succeeded. That passes an
unregistered IRQ to free_irq(), which reports an already-free IRQ.

Track successful request_irq() registration and only free the IRQ on that
path. Clear the state after freeing so repeated shutdown paths remain safe.

Reproducer:

Build an x86_64 kernel with CONFIG_PCI=y, CONFIG_SCSI=y,
CONFIG_SCSI_LOWLEVEL=y, CONFIG_VMWARE_PVSCSI=m,
CONFIG_FUNCTION_ERROR_INJECTION=y, CONFIG_FAULT_INJECTION=y,
CONFIG_FAULT_INJECTION_DEBUG_FS=y, and CONFIG_FAIL_FUNCTION=y. For
testing, add ALLOW_ERROR_INJECTION(scsi_host_alloc, NULL) to
drivers/scsi/hosts.c, then boot QEMU with a PVSCSI device:

qemu-system-x86_64 -machine pc -m 1G -smp 2 -nodefaults \
-no-reboot -display none -serial file:console.log \
-kernel arch/x86/boot/bzImage -initrd test.cpio.gz \
-append 'console=ttyS0 rdinit=/init loglevel=7 panic=1' \
-device pvscsi,id=scsi0

In the guest, mount debugfs and inject one NULL return from
scsi_host_alloc() before loading vmw_pvscsi:

mount -t debugfs none /sys/kernel/debug
echo 100 > /sys/kernel/debug/fail_function/probability
echo 1 > /sys/kernel/debug/fail_function/times
echo scsi_host_alloc > /sys/kernel/debug/fail_function/inject
echo 0 > /sys/kernel/debug/fail_function/scsi_host_alloc/retval
insmod vmw_pvscsi.ko

On the unfixed kernel, the probe reaches pvscsi_shutdown_intr() before
request_irq() and prints "Trying to free already-free IRQ 10" followed
by a warning from __free_irq(). The fixed kernel reaches the same
failure path without the unmatched free_irq() warning. The injection
is deliberate and is not expected during ordinary probing.

Fixes: 2e48e3491189 ("scsi: vmw_pvscsi: switch to pci_alloc_irq_vectors")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: LLM Codex
Signed-off-by: Runyu Xiao <runyu.xiao@xxxxxxxxxx>
---
drivers/scsi/vmw_pvscsi.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/drivers/scsi/vmw_pvscsi.c b/drivers/scsi/vmw_pvscsi.c
index 151cac9f9..7babef882 100644
--- a/drivers/scsi/vmw_pvscsi.c
+++ b/drivers/scsi/vmw_pvscsi.c
@@ -69,6 +69,7 @@ struct pvscsi_adapter {
u8 rev;
bool use_msg;
bool use_req_threshold;
+ bool irq_requested;

spinlock_t hw_lock;

@@ -1212,7 +1213,10 @@ static void pvscsi_free_sgls(const struct pvscsi_adapter *adapter)

static void pvscsi_shutdown_intr(struct pvscsi_adapter *adapter)
{
- free_irq(pci_irq_vector(adapter->dev, 0), adapter);
+ if (adapter->irq_requested) {
+ free_irq(pci_irq_vector(adapter->dev, 0), adapter);
+ adapter->irq_requested = false;
+ }
pci_free_irq_vectors(adapter->dev);
}

@@ -1526,6 +1530,7 @@ static int pvscsi_probe(struct pci_dev *pdev, const struct pci_device_id *id)
"vmw_pvscsi: unable to request IRQ: %d\n", error);
goto out_reset_adapter;
}
+ adapter->irq_requested = true;

error = scsi_add_host(host, &pdev->dev);
if (error) {
--
2.34.1