scsi: qla4xxx: Remove in_interrupt()
qla4_82xx_crb_win_lock() spins on a certain hardware state until it's
updated. At the end of each spin, if in_interrupt() is true, it does 20
loops of cpu_relax(). Otherwise, it yields the CPU.
The in_interrupt() macro is ill-defined as it does not provide what the
name suggests, and it does not catch the intended use-case here.
qla4_82xx_crb_win_lock() is always invoked with scsi_qla_host::hw_lock
acquired, with disabled interrupts. If the caller is in process context, as
in qla4_82xx_need_reset_handler(), then in_interrupt() will return false
even though it is not allowed to call schedule().
Remove the in_interrupt() check.
Change qla4_82xx_crb_win_lock() specification to a purely atomic
function. Mark it as static, remove its forward declaration, and move it
above its callers. To avoid hammering the PCI bus while spinning, use a 10
micro-second delay instead of cpu_relax().
Link: https://lore.kernel.org/r/20201126132952.2287996-4-bigeasy@linutronix.de
Fixes: f4f5df23bf
("[SCSI] qla4xxx: Added support for ISP82XX")
Cc: Nilesh Javali <njavali@marvell.com>
Cc: Manish Rangankar <mrangankar@marvell.com>
Cc: <GR-QLogic-Storage-Upstream@marvell.com>
Reviewed-by: Daniel Wagner <dwagner@suse.de>
Signed-off-by: Ahmed S. Darwish <a.darwish@linutronix.de>
Signed-off-by: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
This commit is contained in:
Родитель
18577cdcae
Коммит
a93c383531
|
@ -114,7 +114,6 @@ irqreturn_t qla4_82xx_intr_handler(int irq, void *dev_id);
|
||||||
void qla4_82xx_queue_iocb(struct scsi_qla_host *ha);
|
void qla4_82xx_queue_iocb(struct scsi_qla_host *ha);
|
||||||
void qla4_82xx_complete_iocb(struct scsi_qla_host *ha);
|
void qla4_82xx_complete_iocb(struct scsi_qla_host *ha);
|
||||||
|
|
||||||
int qla4_82xx_crb_win_lock(struct scsi_qla_host *);
|
|
||||||
void qla4_82xx_crb_win_unlock(struct scsi_qla_host *);
|
void qla4_82xx_crb_win_unlock(struct scsi_qla_host *);
|
||||||
int qla4_82xx_pci_get_crb_addr_2M(struct scsi_qla_host *, ulong *);
|
int qla4_82xx_pci_get_crb_addr_2M(struct scsi_qla_host *, ulong *);
|
||||||
void qla4_82xx_wr_32(struct scsi_qla_host *, ulong, u32);
|
void qla4_82xx_wr_32(struct scsi_qla_host *, ulong, u32);
|
||||||
|
|
|
@ -375,6 +375,35 @@ qla4_82xx_pci_set_crbwindow_2M(struct scsi_qla_host *ha, ulong *off)
|
||||||
*off = (*off & MASK(16)) + CRB_INDIRECT_2M + ha->nx_pcibase;
|
*off = (*off & MASK(16)) + CRB_INDIRECT_2M + ha->nx_pcibase;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define CRB_WIN_LOCK_TIMEOUT 100000000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Context: atomic
|
||||||
|
*/
|
||||||
|
static int qla4_82xx_crb_win_lock(struct scsi_qla_host *ha)
|
||||||
|
{
|
||||||
|
int done = 0, timeout = 0;
|
||||||
|
|
||||||
|
while (!done) {
|
||||||
|
/* acquire semaphore3 from PCI HW block */
|
||||||
|
done = qla4_82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_LOCK));
|
||||||
|
if (done == 1)
|
||||||
|
break;
|
||||||
|
if (timeout >= CRB_WIN_LOCK_TIMEOUT)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
timeout++;
|
||||||
|
udelay(10);
|
||||||
|
}
|
||||||
|
qla4_82xx_wr_32(ha, QLA82XX_CRB_WIN_LOCK_ID, ha->func_num);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void qla4_82xx_crb_win_unlock(struct scsi_qla_host *ha)
|
||||||
|
{
|
||||||
|
qla4_82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_UNLOCK));
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
qla4_82xx_wr_32(struct scsi_qla_host *ha, ulong off, u32 data)
|
qla4_82xx_wr_32(struct scsi_qla_host *ha, ulong off, u32 data)
|
||||||
{
|
{
|
||||||
|
@ -475,40 +504,6 @@ int qla4_82xx_md_wr_32(struct scsi_qla_host *ha, uint32_t off, uint32_t data)
|
||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define CRB_WIN_LOCK_TIMEOUT 100000000
|
|
||||||
|
|
||||||
int qla4_82xx_crb_win_lock(struct scsi_qla_host *ha)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
int done = 0, timeout = 0;
|
|
||||||
|
|
||||||
while (!done) {
|
|
||||||
/* acquire semaphore3 from PCI HW block */
|
|
||||||
done = qla4_82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_LOCK));
|
|
||||||
if (done == 1)
|
|
||||||
break;
|
|
||||||
if (timeout >= CRB_WIN_LOCK_TIMEOUT)
|
|
||||||
return -1;
|
|
||||||
|
|
||||||
timeout++;
|
|
||||||
|
|
||||||
/* Yield CPU */
|
|
||||||
if (!in_interrupt())
|
|
||||||
schedule();
|
|
||||||
else {
|
|
||||||
for (i = 0; i < 20; i++)
|
|
||||||
cpu_relax(); /*This a nop instr on i386*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
qla4_82xx_wr_32(ha, QLA82XX_CRB_WIN_LOCK_ID, ha->func_num);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void qla4_82xx_crb_win_unlock(struct scsi_qla_host *ha)
|
|
||||||
{
|
|
||||||
qla4_82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_UNLOCK));
|
|
||||||
}
|
|
||||||
|
|
||||||
#define IDC_LOCK_TIMEOUT 100000000
|
#define IDC_LOCK_TIMEOUT 100000000
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Загрузка…
Ссылка в новой задаче