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>
This commit is contained in:
parent
94a0dfcf7d
commit
7640e1eb8c
2 changed files with 14 additions and 13 deletions
|
@ -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;
|
||||||
|
int q_index = circularQ - pm8001_ha->inbnd_q_tbl;
|
||||||
|
int rv = -1;
|
||||||
|
|
||||||
if (pm8001_mpi_msg_free_get(circularQ, pm8001_ha->iomb_size,
|
WARN_ON(q_index >= PM8001_MAX_INB_NUM);
|
||||||
&pMessage) < 0) {
|
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,
|
||||||
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,
|
||||||
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,
|
||||||
|
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue