@@ -1330,10 +1330,24 @@ EXPORT_SYMBOL_GPL(ata_sff_queue_pio_task);
void ata_sff_flush_pio_task(struct ata_port *ap)
{
+ struct Scsi_Host *host = ap->scsi_host;
+ unsigned long flags;
+
DPRINTK("ENTER\n");
cancel_delayed_work_sync(&ap->sff_pio_task);
+
+ /*
+ Without grabbing the host_lock, it is possible for
+ ata_sff_flush_pio_task() to set ap->hsm_task_state
+ to HSM_ST_IDLE in between the time __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_irqsave(host->host_lock, flags);
ap->hsm_task_state = HSM_ST_IDLE;
+ spin_unlock_irqrestore(host->host_lock, flags);
+
ap->sff_pio_task_link = NULL;
if (ata_msg_ctl(ap))