Function ata_sff_flush_pio_task use spin_lock_irq/spin_unlock_irq to protect shared data. spin_unlock_irq will enable interrupts. In the interrupt handler nv_swncq_interrupt (./drivers/ata/sata_nv.c), when ap->link.sactive is true, nv_swncq_host_interrupt was called. nv_swncq_hotplug is called when NV_SWNCQ_IRQ_HOTPLUG is set. Then it will follow this chain: nv_swncq_hotplug -> sata_scr_read (./dirvers/ata/libata-core.c) -> sata_pmp_scr_read (./drivers/ata/libata-pmp.c) -> sata_pmp_read -> ata_exec_internal -> ata_exec_internal_sg -> ata_sff_flush_pio_task Interrupts are enabled in interrupt handler. Use spin_lock_irqsave instead of spin_lock_irq to avoid this. Signed-off-by: Fuqian Huang <huangfq.daxian@xxxxxxxxx> --- drivers/ata/libata-sff.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/ata/libata-sff.c b/drivers/ata/libata-sff.c index 10aa27882142..d3143e7e6ec0 100644 --- a/drivers/ata/libata-sff.c +++ b/drivers/ata/libata-sff.c @@ -1241,6 +1241,7 @@ EXPORT_SYMBOL_GPL(ata_sff_queue_pio_task); void ata_sff_flush_pio_task(struct ata_port *ap) { + unsigned long flags; DPRINTK("ENTER\n"); cancel_delayed_work_sync(&ap->sff_pio_task); @@ -1253,9 +1254,9 @@ void ata_sff_flush_pio_task(struct ata_port *ap) * __ata_sff_port_intr() checks for HSM_ST_IDLE and before it calls * ata_sff_hsm_move() causing ata_sff_hsm_move() to BUG(). */ - spin_lock_irq(ap->lock); + spin_lock_irqsave(ap->lock, flags); ap->hsm_task_state = HSM_ST_IDLE; - spin_unlock_irq(ap->lock); + spin_unlock_irqrestore(ap->lock, flags); ap->sff_pio_task_link = NULL; -- 2.11.0