aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAhmed S. Darwish <a.darwish@linutronix.de>2020-11-26 14:29:41 +0100
committerMartin K. Petersen <martin.petersen@oracle.com>2020-12-01 00:03:52 -0500
commita93c3835319849f0226b9a7101284aeb60a5ed8e (patch)
treef62d0e9cce74600bece44e4f6cfca53d9763407c
parentscsi: hisi_sas: Remove preemptible() (diff)
downloadlinux-dev-a93c3835319849f0226b9a7101284aeb60a5ed8e.tar.xz
linux-dev-a93c3835319849f0226b9a7101284aeb60a5ed8e.zip
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: f4f5df23bf72 ("[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>
-rw-r--r--drivers/scsi/qla4xxx/ql4_glbl.h1
-rw-r--r--drivers/scsi/qla4xxx/ql4_nx.c63
2 files changed, 29 insertions, 35 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_glbl.h b/drivers/scsi/qla4xxx/ql4_glbl.h
index b8f02210aeb0..ea60057b2e20 100644
--- a/drivers/scsi/qla4xxx/ql4_glbl.h
+++ b/drivers/scsi/qla4xxx/ql4_glbl.h
@@ -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_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 *);
int qla4_82xx_pci_get_crb_addr_2M(struct scsi_qla_host *, ulong *);
void qla4_82xx_wr_32(struct scsi_qla_host *, ulong, u32);
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c
index f1767b21076f..da903a545b2c 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.c
+++ b/drivers/scsi/qla4xxx/ql4_nx.c
@@ -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;
}
+#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
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;
}
-#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
/**