Commit 7640e1eb authored by peter chang's avatar peter chang Committed by Martin K. Petersen

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.comAcked-by: default avatarJack Wang <jinpu.wang@cloud.ionos.com>
Signed-off-by: default avatarpeter chang <dpf@google.com>
Signed-off-by: default avatarViswas G <Viswas.G@microchip.com>
Signed-off-by: default avatarRuksar Devadi <Ruksar.devadi@microchip.com>
Signed-off-by: default avatarRadha Ramachandran <radha@google.com>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent 94a0dfcf
...@@ -1356,12 +1356,19 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha, ...@@ -1356,12 +1356,19 @@ int pm8001_mpi_build_cmd(struct pm8001_hba_info *pm8001_ha,
{ {
u32 Header = 0, hpriority = 0, bc = 1, category = 0x02; u32 Header = 0, hpriority = 0, bc = 1, category = 0x02;
void *pMessage; void *pMessage;
unsigned long flags;
if (pm8001_mpi_msg_free_get(circularQ, pm8001_ha->iomb_size, int q_index = circularQ - pm8001_ha->inbnd_q_tbl;
&pMessage) < 0) { 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_IO_DBG(pm8001_ha,
pm8001_printk("No free mpi buffer\n")); pm8001_printk("No free mpi buffer\n"));
return -ENOMEM; rv = -ENOMEM;
goto done;
} }
if (nb > (pm8001_ha->iomb_size - sizeof(struct mpi_msg_hdr))) 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, ...@@ -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", pm8001_printk("INB Q %x OPCODE:%x , UPDATED PI=%d CI=%d\n",
responseQueue, opCode, circularQ->producer_idx, responseQueue, opCode, circularQ->producer_idx,
circularQ->consumer_index)); 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, u32 pm8001_mpi_msg_free_set(struct pm8001_hba_info *pm8001_ha, void *pMsg,
......
...@@ -4281,7 +4281,6 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, ...@@ -4281,7 +4281,6 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha,
char *preq_dma_addr = NULL; char *preq_dma_addr = NULL;
__le64 tmp_addr; __le64 tmp_addr;
u32 i, length; u32 i, length;
unsigned long flags;
memset(&smp_cmd, 0, sizeof(smp_cmd)); memset(&smp_cmd, 0, sizeof(smp_cmd));
/* /*
...@@ -4377,10 +4376,8 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha, ...@@ -4377,10 +4376,8 @@ static int pm80xx_chip_smp_req(struct pm8001_hba_info *pm8001_ha,
build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag, build_smp_cmd(pm8001_dev->device_id, smp_cmd.tag,
&smp_cmd, pm8001_ha->smp_exp_mode, length); &smp_cmd, pm8001_ha->smp_exp_mode, length);
spin_lock_irqsave(&circularQ->iq_lock, flags);
rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &smp_cmd, rc = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, &smp_cmd,
sizeof(smp_cmd), 0); sizeof(smp_cmd), 0);
spin_unlock_irqrestore(&circularQ->iq_lock, flags);
if (rc) if (rc)
goto err_out_2; goto err_out_2;
return 0; return 0;
...@@ -4444,7 +4441,6 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, ...@@ -4444,7 +4441,6 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
u64 phys_addr, start_addr, end_addr; u64 phys_addr, start_addr, end_addr;
u32 end_addr_high, end_addr_low; u32 end_addr_high, end_addr_low;
struct inbound_queue_table *circularQ; struct inbound_queue_table *circularQ;
unsigned long flags;
u32 q_index, cpu_id; u32 q_index, cpu_id;
u32 opc = OPC_INB_SSPINIIOSTART; u32 opc = OPC_INB_SSPINIIOSTART;
memset(&ssp_cmd, 0, sizeof(ssp_cmd)); memset(&ssp_cmd, 0, sizeof(ssp_cmd));
...@@ -4582,10 +4578,8 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha, ...@@ -4582,10 +4578,8 @@ static int pm80xx_chip_ssp_io_req(struct pm8001_hba_info *pm8001_ha,
ssp_cmd.esgl = 0; ssp_cmd.esgl = 0;
} }
} }
spin_lock_irqsave(&circularQ->iq_lock, flags);
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
&ssp_cmd, sizeof(ssp_cmd), q_index); &ssp_cmd, sizeof(ssp_cmd), q_index);
spin_unlock_irqrestore(&circularQ->iq_lock, flags);
return ret; return ret;
} }
...@@ -4819,10 +4813,8 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha, ...@@ -4819,10 +4813,8 @@ static int pm80xx_chip_sata_req(struct pm8001_hba_info *pm8001_ha,
} }
} }
} }
spin_lock_irqsave(&circularQ->iq_lock, flags);
ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc, ret = pm8001_mpi_build_cmd(pm8001_ha, circularQ, opc,
&sata_cmd, sizeof(sata_cmd), q_index); &sata_cmd, sizeof(sata_cmd), q_index);
spin_unlock_irqrestore(&circularQ->iq_lock, flags);
return ret; return ret;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment