diff options
author | Suresh Thiagarajan <Suresh.Thiagarajan@pmcs.com> | 2014-01-16 15:26:21 +0530 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2014-03-15 10:19:01 -0700 |
commit | 2b01d816f5f884d5ea16ab2498736b1221bc027c (patch) | |
tree | 5adfe6415c09702b8ae1a7d32adc28533d267459 /drivers/scsi/pm8001/pm80xx_hwi.c | |
parent | eee0f03a547f50ca81a8d01ee9f1c84fecd1f64c (diff) |
[SCSI] pm80xx: Spinlock fix
spin_lock_irqsave for the HBA lock is called in one function where flag
is local to that function. Another function is called from the first
function where lock has to be released using spin_unlock_irqrestore for
calling task_done of libsas. In the second function also flag is declared
and used. For calling task_done there is no need to enable the irq. So
instead of using spin_lock_irqsave and spin_unlock_irqrestore, spin_lock
and spin_unlock is used now. This also avoids passing the flags across all
the functions where HBA lock is being used. Also removed redundant code.
Reported-by: Jason Seba <jason.seba42@gmail.com>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Suresh Thiagarajan <Suresh.Thiagarajan@pmcs.com>
Signed-off-by: Viswas G <viswas.g@pmcs.com>
Acked-by: Jack Wang <xjtuwjp@gmail.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/pm8001/pm80xx_hwi.c')
-rw-r--r-- | drivers/scsi/pm8001/pm80xx_hwi.c | 84 |
1 files changed, 13 insertions, 71 deletions
diff --git a/drivers/scsi/pm8001/pm80xx_hwi.c b/drivers/scsi/pm8001/pm80xx_hwi.c index 9b5414249cc4..d70587f96184 100644 --- a/drivers/scsi/pm8001/pm80xx_hwi.c +++ b/drivers/scsi/pm8001/pm80xx_hwi.c @@ -2168,11 +2168,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_QUEUE_FULL; - pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); - mb();/*in order to force CPU ordering*/ - spin_unlock_irq(&pm8001_ha->lock); - t->task_done(t); - spin_lock_irq(&pm8001_ha->lock); + pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); return; } break; @@ -2188,11 +2184,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_QUEUE_FULL; - pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); - mb();/*ditto*/ - spin_unlock_irq(&pm8001_ha->lock); - t->task_done(t); - spin_lock_irq(&pm8001_ha->lock); + pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); return; } break; @@ -2214,11 +2206,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) IO_OPEN_CNX_ERROR_STP_RESOURCES_BUSY); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_QUEUE_FULL; - pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); - mb();/* ditto*/ - spin_unlock_irq(&pm8001_ha->lock); - t->task_done(t); - spin_lock_irq(&pm8001_ha->lock); + pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); return; } break; @@ -2281,11 +2269,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) IO_DS_NON_OPERATIONAL); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_QUEUE_FULL; - pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); - mb();/*ditto*/ - spin_unlock_irq(&pm8001_ha->lock); - t->task_done(t); - spin_lock_irq(&pm8001_ha->lock); + pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); return; } break; @@ -2305,11 +2289,7 @@ mpi_sata_completion(struct pm8001_hba_info *pm8001_ha, void *piomb) IO_DS_IN_ERROR); ts->resp = SAS_TASK_UNDELIVERED; ts->stat = SAS_QUEUE_FULL; - pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); - mb();/*ditto*/ - spin_unlock_irq(&pm8001_ha->lock); - t->task_done(t); - spin_lock_irq(&pm8001_ha->lock); + pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); return; } break; @@ -2338,20 +2318,9 @@ 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 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_irq(&pm8001_ha->lock); - t->task_done(t); - spin_lock_irq(&pm8001_ha->lock); - } else if (!t->uldd_task) { + } else { spin_unlock_irqrestore(&t->task_state_lock, flags); - pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); - mb();/*ditto*/ - spin_unlock_irq(&pm8001_ha->lock); - t->task_done(t); - spin_lock_irq(&pm8001_ha->lock); + pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); } } @@ -2463,11 +2432,7 @@ static void mpi_sata_event(struct pm8001_hba_info *pm8001_ha , void *piomb) IO_OPEN_CNX_ERROR_IT_NEXUS_LOSS); ts->resp = SAS_TASK_COMPLETE; ts->stat = SAS_QUEUE_FULL; - pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); - mb();/*ditto*/ - spin_unlock_irq(&pm8001_ha->lock); - t->task_done(t); - spin_lock_irq(&pm8001_ha->lock); + pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); return; } break; @@ -2589,20 +2554,9 @@ 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 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_irq(&pm8001_ha->lock); - t->task_done(t); - spin_lock_irq(&pm8001_ha->lock); - } else if (!t->uldd_task) { + } else { spin_unlock_irqrestore(&t->task_state_lock, flags); - pm8001_ccb_task_free(pm8001_ha, t, ccb, tag); - mb();/*ditto*/ - spin_unlock_irq(&pm8001_ha->lock); - t->task_done(t); - spin_lock_irq(&pm8001_ha->lock); + pm8001_ccb_task_free_done(pm8001_ha, t, ccb, tag); } } @@ -4297,23 +4251,11 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, "\n", task, ts->resp, ts->stat)); pm8001_ccb_task_free(pm8001_ha, task, ccb, tag); return 0; - } else if (task->uldd_task) { - spin_unlock_irqrestore(&task->task_state_lock, - flags); - pm8001_ccb_task_free(pm8001_ha, task, ccb, tag); - mb();/* ditto */ - spin_unlock_irq(&pm8001_ha->lock); - task->task_done(task); - spin_lock_irq(&pm8001_ha->lock); - return 0; - } else if (!task->uldd_task) { + } else { spin_unlock_irqrestore(&task->task_state_lock, flags); - pm8001_ccb_task_free(pm8001_ha, task, ccb, tag); - mb();/*ditto*/ - spin_unlock_irq(&pm8001_ha->lock); - task->task_done(task); - spin_lock_irq(&pm8001_ha->lock); + pm8001_ccb_task_free_done(pm8001_ha, task, + ccb, tag); return 0; } } |