From: Shao Mingyin ixp4xx_mmio_data_xfer() takes ap->lock, but the SFF state machine already holds that lock when it invokes ->sff_data_xfer(), both from interrupt context and from the PIO work item. The first data transfer, including IDENTIFY during probe, therefore recursively takes the same spinlock and can hang the CPU. Use the lock held by the caller while switching the expansion bus width and transferring data. Assert that the lock is held rather than acquiring it again. Fixes: 47adef20e67d ("pata: ixp4xx: Rewrite to use device tree") Cc: stable@vger.kernel.org Signed-off-by: Shao Mingyin --- Tested on 7.4.0-rc1-next-20261105 under QEMU/KVM (x86_64, 2 vCPUs), with lockdep, DEBUG_SPINLOCK and KASAN. Both kernels carry the same TEST-ONLY harness: a synthetic ATA host and RAM-backed registers feed the original SFF state machine and IXP4xx PIO callback. Only this fix differs between the two kernels. The unpatched kernel reports recursive locking of host->lock from ixp4xx_mmio_data_xfer() and stops in the first SFF transfer. With the fix, SFF calls with in_wq=0 and in_wq=1 each transfer 512 bytes and restore the 8-bit bus timing. Separate 513-byte read/write checks also pass, including the trailing byte and buffer sentinel. The patched guest shuts down normally without lockdep or KASAN reports. This tests the callback and SFF interaction, not IXP4xx hardware, probe, interrupt delivery or PIO worker scheduling. drivers/ata/pata_ixp4xx_cf.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/drivers/ata/pata_ixp4xx_cf.c b/drivers/ata/pata_ixp4xx_cf.c index 80f6a91acf..6ea671d218 100644 --- a/drivers/ata/pata_ixp4xx_cf.c +++ b/drivers/ata/pata_ixp4xx_cf.c @@ -131,11 +131,10 @@ static unsigned int ixp4xx_mmio_data_xfer(struct ata_queued_cmd *qc, struct ata_port *ap = qc->dev->link->ap; void __iomem *mmio = ap->ioaddr.data_addr; struct ixp4xx_pata *ixpp = ap->host->private_data; - unsigned long flags; ata_dev_dbg(adev, "%s %d bytes\n", (rw == READ) ? "READ" : "WRITE", buflen); - spin_lock_irqsave(ap->lock, flags); + lockdep_assert_held(ap->lock); /* set the expansion bus in 16bit mode and restore * 8 bit mode after the transaction. @@ -169,8 +168,6 @@ static unsigned int ixp4xx_mmio_data_xfer(struct ata_queued_cmd *qc, ixp4xx_set_8bit_timing(ixpp, adev->pio_mode); udelay(5); - spin_unlock_irqrestore(ap->lock, flags); - return words << 1; } -- 2.27.0