This patch fix for sata IO circular lock dependency. When we call task_done for SATA IO, we have got pm8001_ha->lock ,and in sas_ata_task_done, it will get (dev->sata_dev.ap->lock. then cause circular lock dependency .So we should drop pm8001_ha->lock when we call task_done for SATA task. Signed-off-by: Jack Wang <jack_wang@xxxxxxxxx> Signed-off-by: Lindar Liu <lindar_liu@xxxxxxxxx> --- drivers/scsi/pm8001/pm8001_hwi.c | 40 +++++++++++++++++++++++++++++++++---- 1 files changed, 35 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index a3de306..68695b7 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -1901,7 +1901,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) { struct sas_task *t; struct pm8001_ccb_info *ccb; - unsigned long flags; + unsigned long flags = 0; u32 param; u32 status; u32 tag; @@ -2040,7 +2040,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->stat = SAS_QUEUE_FULL; pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); mb();/*in order to force CPU ordering*/ + spin_unlock_irqrestore(&pm8001_ha->lock, flags); t->task_done(t); + spin_lock_irqsave(&pm8001_ha->lock, flags); return; } break; @@ -2058,7 +2060,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->stat = SAS_QUEUE_FULL; pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); mb();/*ditto*/ + spin_unlock_irqrestore(&pm8001_ha->lock, flags); t->task_done(t); + spin_lock_irqsave(&pm8001_ha->lock, flags); return; } break; @@ -2084,7 +2088,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->stat = SAS_QUEUE_FULL; pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); mb();/* ditto*/ + spin_unlock_irqrestore(&pm8001_ha->lock, flags); t->task_done(t); + spin_lock_irqsave(&pm8001_ha->lock, flags); return; } break; @@ -2149,7 +2155,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->stat = SAS_QUEUE_FULL; pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); mb();/*ditto*/ + spin_unlock_irqrestore(&pm8001_ha->lock, flags); t->task_done(t); + spin_lock_irqsave(&pm8001_ha->lock, flags); return; } break; @@ -2171,7 +2179,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) ts->stat = SAS_QUEUE_FULL; pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); mb();/*ditto*/ + spin_unlock_irqrestore(&pm8001_ha->lock, flags); t->task_done(t); + spin_lock_irqsave(&pm8001_ha->lock, flags); return; } break; @@ -2200,11 +2210,20 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) " resp 0x%x stat 0x%x but aborted by upper layer!\n", t, status, ts->resp, ts->stat)); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); - } else { + } else if (t->uldd_task) { spin_unlock_irqrestore(&t->task_state_lock, flags); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); mb();/* ditto */ + spin_unlock_irqrestore(&pm8001_ha->lock, flags); + t->task_done(t); + spin_lock_irqsave(&pm8001_ha->lock, flags); + } else if (!t->uldd_task) { + spin_unlock_irqrestore(&t->task_state_lock, flags); + pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); + mb();/*ditto*/ + spin_unlock_irqrestore(&pm8001_ha->lock, flags); t->task_done(t); + spin_lock_irqsave(&pm8001_ha->lock, flags); } } @@ -2212,7 +2231,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) { struct sas_task *t; - unsigned long flags; + unsigned long flags = 0; struct task_status_struct *ts; struct pm8001_ccb_info *ccb; struct pm8001_device *pm8001_dev; @@ -2292,7 +2311,9 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) ts->stat = SAS_QUEUE_FULL; pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); mb();/*ditto*/ + spin_unlock_irqrestore(&pm8001_ha->lock, flags); t->task_done(t); + spin_lock_irqsave(&pm8001_ha->lock, flags); return; } break; @@ -2401,11 +2422,20 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) " resp 0x%x stat 0x%x but aborted by upper layer!\n", t, event, ts->resp, ts->stat)); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); - } else { + } else if (t->uldd_task) { spin_unlock_irqrestore(&t->task_state_lock, flags); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); - mb();/* in order to force CPU ordering */ + mb();/* ditto */ + spin_unlock_irqrestore(&pm8001_ha->lock, flags); + t->task_done(t); + spin_lock_irqsave(&pm8001_ha->lock, flags); + } else if (!t->uldd_task) { + spin_unlock_irqrestore(&t->task_state_lock, flags); + pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); + mb();/*ditto*/ + spin_unlock_irqrestore(&pm8001_ha->lock, flags); t->task_done(t); + spin_lock_irqsave(&pm8001_ha->lock, flags); } } -- 1.6.5.1.1367.gcd48
Attachment:
0001-Fix-sata-circular-lock-dependency.patch
Description: Binary data