diff options
author | Santosh Nayak <santoshprasadnayak@gmail.com> | 2012-02-26 08:35:03 -0500 |
---|---|---|
committer | James Bottomley <JBottomley@Parallels.com> | 2012-02-29 17:52:59 -0500 |
commit | 50ec5babd3b9da274ac3e0d5ca0c4772e3c7bc8d (patch) | |
tree | 8f975cfed3e6bd9b1e15dd862bf8f7ad9dd9387d /drivers/scsi/pm8001/pm8001_hwi.c | |
parent | bdaefbf580cd200ae3230b6aacd1f4f2dadb18e3 (diff) |
[SCSI] pm8001: Fix possible racing condition.
There is a possble racing scenario.
'process_oq' is called by two routines, as shown below.
pm8001_8001_dispatch = {
.......
.isr = pm8001_chip_isr --> process_oq,// A
.isr_process_oq = process_oq, // B
.....
}
process_oq() --> process_one_iomb() --> mpi_sata_completion()
In 'mpi_sata_completion', "pm8001_ha->lock" is first released.
It means lock is taken before, which is true for
the context A, as 'pm8001_ha->lock' is taken in 'pm8001_chip_isr()'
But for context B there is no lock taken before and pm8001_ha->lock
is unlocked in 'mpi_sata_completion()'. This may unlock the lock
taken in context A. Possible racing ??
If 'pm8001_ha->lock' is taken in 'process_oq()' instead of
'pm8001_chip_isr' then the above issue can be avoided.
Signed-off-by: Santosh Nayak <santoshprasadnayak@gmail.com>
Acked-by: Jack Wang <jack_wang@usish.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers/scsi/pm8001/pm8001_hwi.c')
-rw-r--r-- | drivers/scsi/pm8001/pm8001_hwi.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 871d1c3fa01b..dc28ae186450 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c | |||
@@ -3869,7 +3869,9 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha) | |||
3869 | void *pMsg1 = NULL; | 3869 | void *pMsg1 = NULL; |
3870 | u8 bc = 0; | 3870 | u8 bc = 0; |
3871 | u32 ret = MPI_IO_STATUS_FAIL; | 3871 | u32 ret = MPI_IO_STATUS_FAIL; |
3872 | unsigned long flags; | ||
3872 | 3873 | ||
3874 | spin_lock_irqsave(&pm8001_ha->lock, flags); | ||
3873 | circularQ = &pm8001_ha->outbnd_q_tbl[0]; | 3875 | circularQ = &pm8001_ha->outbnd_q_tbl[0]; |
3874 | do { | 3876 | do { |
3875 | ret = mpi_msg_consume(pm8001_ha, circularQ, &pMsg1, &bc); | 3877 | ret = mpi_msg_consume(pm8001_ha, circularQ, &pMsg1, &bc); |
@@ -3890,6 +3892,7 @@ static int process_oq(struct pm8001_hba_info *pm8001_ha) | |||
3890 | break; | 3892 | break; |
3891 | } | 3893 | } |
3892 | } while (1); | 3894 | } while (1); |
3895 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
3893 | return ret; | 3896 | return ret; |
3894 | } | 3897 | } |
3895 | 3898 | ||
@@ -4295,12 +4298,9 @@ static u32 pm8001_chip_is_our_interupt(struct pm8001_hba_info *pm8001_ha) | |||
4295 | static irqreturn_t | 4298 | static irqreturn_t |
4296 | pm8001_chip_isr(struct pm8001_hba_info *pm8001_ha) | 4299 | pm8001_chip_isr(struct pm8001_hba_info *pm8001_ha) |
4297 | { | 4300 | { |
4298 | unsigned long flags; | ||
4299 | spin_lock_irqsave(&pm8001_ha->lock, flags); | ||
4300 | pm8001_chip_interrupt_disable(pm8001_ha); | 4301 | pm8001_chip_interrupt_disable(pm8001_ha); |
4301 | process_oq(pm8001_ha); | 4302 | process_oq(pm8001_ha); |
4302 | pm8001_chip_interrupt_enable(pm8001_ha); | 4303 | pm8001_chip_interrupt_enable(pm8001_ha); |
4303 | spin_unlock_irqrestore(&pm8001_ha->lock, flags); | ||
4304 | return IRQ_HANDLED; | 4304 | return IRQ_HANDLED; |
4305 | } | 4305 | } |
4306 | 4306 | ||