[SCSI] pm8001: Fix for sata io circular lock dependency.

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@usish.com>
Signed-off-by: Lindar Liu <lindar_liu@usish.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
jack wang 2009-12-07 17:22:36 +08:00 committed by James Bottomley
parent edd163687e
commit 9e79e12554

View File

@ -1901,7 +1901,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
{ {
struct sas_task *t; struct sas_task *t;
struct pm8001_ccb_info *ccb; struct pm8001_ccb_info *ccb;
unsigned long flags; unsigned long flags = 0;
u32 param; u32 param;
u32 status; u32 status;
u32 tag; u32 tag;
@ -2040,7 +2040,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
ts->stat = SAS_QUEUE_FULL; ts->stat = SAS_QUEUE_FULL;
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
mb();/*in order to force CPU ordering*/ mb();/*in order to force CPU ordering*/
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
t->task_done(t); t->task_done(t);
spin_lock_irqsave(&pm8001_ha->lock, flags);
return; return;
} }
break; break;
@ -2058,7 +2060,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
ts->stat = SAS_QUEUE_FULL; ts->stat = SAS_QUEUE_FULL;
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
mb();/*ditto*/ mb();/*ditto*/
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
t->task_done(t); t->task_done(t);
spin_lock_irqsave(&pm8001_ha->lock, flags);
return; return;
} }
break; break;
@ -2084,7 +2088,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
ts->stat = SAS_QUEUE_FULL; ts->stat = SAS_QUEUE_FULL;
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
mb();/* ditto*/ mb();/* ditto*/
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
t->task_done(t); t->task_done(t);
spin_lock_irqsave(&pm8001_ha->lock, flags);
return; return;
} }
break; break;
@ -2149,7 +2155,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
ts->stat = SAS_QUEUE_FULL; ts->stat = SAS_QUEUE_FULL;
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
mb();/*ditto*/ mb();/*ditto*/
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
t->task_done(t); t->task_done(t);
spin_lock_irqsave(&pm8001_ha->lock, flags);
return; return;
} }
break; break;
@ -2171,7 +2179,9 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb)
ts->stat = SAS_QUEUE_FULL; ts->stat = SAS_QUEUE_FULL;
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
mb();/*ditto*/ mb();/*ditto*/
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
t->task_done(t); t->task_done(t);
spin_lock_irqsave(&pm8001_ha->lock, flags);
return; return;
} }
break; 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", " resp 0x%x stat 0x%x but aborted by upper layer!\n",
t, status, ts->resp, ts->stat)); t, status, ts->resp, ts->stat));
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
} else { } else if (t->uldd_task) {
spin_unlock_irqrestore(&t->task_state_lock, flags); spin_unlock_irqrestore(&t->task_state_lock, flags);
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
mb();/* ditto */ mb();/* ditto */
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
t->task_done(t); 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) static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb)
{ {
struct sas_task *t; struct sas_task *t;
unsigned long flags; unsigned long flags = 0;
struct task_status_struct *ts; struct task_status_struct *ts;
struct pm8001_ccb_info *ccb; struct pm8001_ccb_info *ccb;
struct pm8001_device *pm8001_dev; 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; ts->stat = SAS_QUEUE_FULL;
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
mb();/*ditto*/ mb();/*ditto*/
spin_unlock_irqrestore(&pm8001_ha->lock, flags);
t->task_done(t); t->task_done(t);
spin_lock_irqsave(&pm8001_ha->lock, flags);
return; return;
} }
break; 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", " resp 0x%x stat 0x%x but aborted by upper layer!\n",
t, event, ts->resp, ts->stat)); t, event, ts->resp, ts->stat));
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); pm8001_ccb_task_free(pm8001_ha, t, ccb, tag);
} else { } else if (t->uldd_task) {
spin_unlock_irqrestore(&t->task_state_lock, flags); spin_unlock_irqrestore(&t->task_state_lock, flags);
pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); 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); 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);
} }
} }