diff options
author | peter chang <dpf@google.com> | 2020-11-02 22:25:25 +0530 |
---|---|---|
committer | Martin K. Petersen <martin.petersen@oracle.com> | 2020-11-04 22:55:38 -0500 |
commit | 7640e1eb8c5de33dafa6c68fd4389214ff9ec1f9 (patch) | |
tree | bec964f1858536b3c2d49cf2e892ddbf75270fc0 /drivers/scsi/pm8001/pm8001_hwi.c | |
parent | 94a0dfcf7d33ea96bf3eb0c33e4239942a4ff087 (diff) |
scsi: pm80xx: Make mpi_build_cmd locking consistent
Driver submits all internal requests (like abort_task, event acknowledgment
etc.) through inbound queue 0. While submitting those, driver does not
acquire any lock and this may lead to a race when there is an I/O request
coming in on CPU0 and submitted through inbound queue 0. To avoid this,
lock acquisition has been moved to pm8001_mpi_build_cmd(). All command
submission will go through this path.
Link: https://lore.kernel.org/r/20201102165528.26510-2-Viswas.G@microchip.com.com
Acked-by: Jack Wang <jinpu.wang@cloud.ionos.com>
Signed-off-by: peter chang <dpf@google.com>
Signed-off-by: Viswas G <Viswas.G@microchip.com>
Signed-off-by: Ruksar Devadi <Ruksar.devadi@microchip.com>
Signed-off-by: Radha Ramachandran <radha@google.com>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/pm8001/pm8001_hwi.c')
-rw-r--r-- | drivers/scsi/pm8001/pm8001_hwi.c | 21 |
1 files changed, 15 insertions, 6 deletions
diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 2b7b2954ec31..597d7a096a97 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -1356,12 +1356,19 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, { u32 Header = 0, hpriority = 0, bc = 1, category = 0x02; void *pMessage; - - if (pm8001_mpi_msg_free_get(circularQ, pm8001_ha->iomb_size, - &pMessage) < 0) { + unsigned long flags; + int q_index = circularQ - pm8001_ha->inbnd_q_tbl; + int rv = -1; + + WARN_ON(q_index >= PM8001_MAX_INB_NUM); + spin_lock_irqsave(&circularQ->iq_lock, flags); + rv = pm8001_mpi_msg_free_get(circularQ, pm8001_ha->iomb_size, + &pMessage); + if (rv < 0) { PM8001_IO_DBG(pm8001_ha, - pm8001_printk("No free mpi buffer\n")); - return -ENOMEM; + pm8001_printk("No free mpi buffer\n")); + rv = -ENOMEM; + goto done; } if (nb > (pm8001_ha->iomb_size - sizeof(struct mpi_msg_hdr))) @@ -1384,7 +1391,9 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, pm8001_printk("INB Q %x OPCODE:%x , UPDATED PI=%d CI=%d\n", responseQueue, opCode, circularQ->producer_idx, circularQ->consumer_index)); - return 0; +done: + spin_unlock_irqrestore(&circularQ->iq_lock, flags); + return rv; } u32 pm8001_mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg, |