diff mbox

[2/2] qla2xxx: fix rwlock recursion

Message ID 1444838261-20990-3-git-send-email-himanshu.madhani@qlogic.com (mailing list archive)
State Superseded, archived
Headers show

Commit Message

Himanshu Madhani Oct. 14, 2015, 3:57 p.m. UTC
This patch fixes rwlock recursion introduced for ISP82XX by
commit 8dfa4b5a ("qla2xxx: Fix sparse annotations")

Original patch fixes other sparse warnings which did not cause
any regression. So instead of reverting complete patch, this patch
will revert only part which caused recursion.

stack track has following signature

kernel:BUG: rwlock recursion on CPU#2, insmod/39333, ffff8803e998cb28
kernel: ffffffff8181d7de ffff88040f2af8a8 ffffffff810a8047 ffff8803e998cb28
kernel: ffff8803e998cb40 ffff88040f2af8c8 ffffffff810a833a 0000000000000086
kernel: Call Trace:
kernel: [<ffffffff812bce44>] dump_stack+0x48/0x64
kernel: [<ffffffff810a8047>] rwlock_bug+0x67/0x70
kernel: [<ffffffff810a833a>] do_raw_write_lock+0x8a/0xa0
kernel: [<ffffffff815f3033>] _raw_write_lock_irqsave+0x63/0x80
kernel: [<ffffffffa08087c8>] ? qla82xx_rd_32+0xe8/0x140 [qla2xxx]
kernel: [<ffffffffa08087c8>] qla82xx_rd_32+0xe8/0x140 [qla2xxx]
kernel: [<ffffffffa0808845>] qla82xx_crb_win_lock+0x25/0x60 [qla2xxx]
kernel: [<ffffffffa0808976>] qla82xx_wr_32+0xf6/0x150 [qla2xxx]
kernel: [<ffffffffa0808aa4>] ? qla82xx_disable_intrs+0x34/0x80 [qla2xxx]
kernel: [<ffffffffa0808ac0>] qla82xx_disable_intrs+0x50/0x80 [qla2xxx]
kernel: [<ffffffffa080630a>] qla82xx_reset_chip+0x1a/0x20 [qla2xxx]
kernel: [<ffffffffa07d6ef2>] qla2x00_initialize_adapter+0x132/0x420 [qla2xxx]
kernel: [<ffffffffa08087c8>] ? qla82xx_rd_32+0xe8/0x140 [qla2xxx]
kernel: [<ffffffffa08087c8>] qla82xx_rd_32+0xe8/0x140 [qla2xxx]
kernel: [<ffffffffa0808845>] qla82xx_crb_win_lock+0x25/0x60 [qla2xxx]
kernel: [<ffffffffa0808976>] qla82xx_wr_32+0xf6/0x150 [qla2xxx]
kernel: [<ffffffffa0808aa4>] ? qla82xx_disable_intrs+0x34/0x80 [qla2xxx]
kernel: [<ffffffffa0808ac0>] qla82xx_disable_intrs+0x50/0x80 [qla2xxx]
kernel: [<ffffffffa080630a>] qla82xx_reset_chip+0x1a/0x20 [qla2xxx]
kernel: [<ffffffffa07d6ef2>] qla2x00_initialize_adapter+0x132/0x420 [qla2xxx]
kernel: [<ffffffffa07c964e>] qla2x00_probe_one+0xefe/0x2130 [qla2xxx]
kernel: [<ffffffff813ee31c>] ? __pm_runtime_resume+0x6c/0x90
kernel: [<ffffffff8130052c>] local_pci_probe+0x4c/0xa0
kernel: [<ffffffff81300603>] pci_call_probe+0x83/0xa0
kernel: [<ffffffff813008cf>] pci_device_probe+0x7f/0xb0
kernel: [<ffffffff813e2e83>] really_probe+0x133/0x390
kernel: [<ffffffff813e3139>] driver_probe_device+0x59/0xd0
kernel: [<ffffffff813e3251>] __driver_attach+0xa1/0xb0
kernel: [<ffffffff813e31b0>] ? driver_probe_device+0xd0/0xd0
kernel: [<ffffffff813e0cdd>] bus_for_each_dev+0x8d/0xb0
kernel: [<ffffffff813e28ee>] driver_attach+0x1e/0x20
kernel: [<ffffffff813e2252>] bus_add_driver+0x1d2/0x290
kernel: [<ffffffff813e3970>] driver_register+0x60/0xe0
kernel: [<ffffffff813009e4>] __pci_register_driver+0x64/0x70
kernel: [<ffffffffa04bc1cb>] qla2x00_module_init+0x1cb/0x21b [qla2xxx]
kernel: [<ffffffffa04bc000>] ? 0xffffffffa04bc000
kernel: [<ffffffff8100027d>] do_one_initcall+0xad/0x1c0
kernel: [<ffffffff810e2859>] do_init_module+0x69/0x210
kernel: [<ffffffff810e4e5c>] load_module+0x5cc/0x750
kernel: [<ffffffff810e1980>] ? mod_sysfs_teardown+0x140/0x140
kernel: [<ffffffff812c9565>] ? copy_user_enhanced_fast_string+0x5/0x10
kernel: [<ffffffff810e12f0>] ? module_sect_show+0x30/0x30
kernel: [<ffffffff810e1a8d>] ? copy_module_from_user+0x8d/0xf0
kernel: [<ffffffff810e5162>] SyS_init_module+0x92/0xc0
kernel: [<ffffffff815f37d7>] entry_SYSCALL_64_fastpath+0x12/0x6f

Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
---
 drivers/scsi/qla2xxx/qla_nx.c |   58 ++++++++++++++++++++--------------------
 1 files changed, 29 insertions(+), 29 deletions(-)

Comments

Bart Van Assche Oct. 14, 2015, 4:53 p.m. UTC | #1
On 10/14/2015 08:57 AM, Himanshu Madhani wrote:
> -qla82xx_pci_set_crbwindow_2M(struct qla_hw_data *ha, ulong off_in,
> -			     void __iomem **off_out)
> +qla82xx_pci_set_crbwindow_2M(struct qla_hw_data *ha, ulong *off)
>   {

Hello Himanshu,

Do you think it would be possible to keep the input and output offset as 
separate arguments ? Something that is very unfortunate about this patch 
is that it converts the qla82xx_pci_set_crbwindow_2M() function again 
into a function that expects an unsigned long in *off and writes an I/O 
memory address into *off. It is impossible to avoid that source code 
does not trigger any sparse warning if such functions occur.

Thanks,

Bart.
--
To unsubscribe from this list: send the line "unsubscribe linux-scsi" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Hannes Reinecke Oct. 15, 2015, 7:50 a.m. UTC | #2
On 10/14/2015 05:57 PM, Himanshu Madhani wrote:
> This patch fixes rwlock recursion introduced for ISP82XX by
> commit 8dfa4b5a ("qla2xxx: Fix sparse annotations")
> 
> Original patch fixes other sparse warnings which did not cause
> any regression. So instead of reverting complete patch, this patch
> will revert only part which caused recursion.
> 
> stack track has following signature
> 
> kernel:BUG: rwlock recursion on CPU#2, insmod/39333, ffff8803e998cb28
> kernel: ffffffff8181d7de ffff88040f2af8a8 ffffffff810a8047 ffff8803e998cb28
> kernel: ffff8803e998cb40 ffff88040f2af8c8 ffffffff810a833a 0000000000000086
> kernel: Call Trace:
> kernel: [<ffffffff812bce44>] dump_stack+0x48/0x64
> kernel: [<ffffffff810a8047>] rwlock_bug+0x67/0x70
> kernel: [<ffffffff810a833a>] do_raw_write_lock+0x8a/0xa0
> kernel: [<ffffffff815f3033>] _raw_write_lock_irqsave+0x63/0x80
> kernel: [<ffffffffa08087c8>] ? qla82xx_rd_32+0xe8/0x140 [qla2xxx]
> kernel: [<ffffffffa08087c8>] qla82xx_rd_32+0xe8/0x140 [qla2xxx]
> kernel: [<ffffffffa0808845>] qla82xx_crb_win_lock+0x25/0x60 [qla2xxx]
> kernel: [<ffffffffa0808976>] qla82xx_wr_32+0xf6/0x150 [qla2xxx]
> kernel: [<ffffffffa0808aa4>] ? qla82xx_disable_intrs+0x34/0x80 [qla2xxx]
> kernel: [<ffffffffa0808ac0>] qla82xx_disable_intrs+0x50/0x80 [qla2xxx]
> kernel: [<ffffffffa080630a>] qla82xx_reset_chip+0x1a/0x20 [qla2xxx]
> kernel: [<ffffffffa07d6ef2>] qla2x00_initialize_adapter+0x132/0x420 [qla2xxx]
> kernel: [<ffffffffa08087c8>] ? qla82xx_rd_32+0xe8/0x140 [qla2xxx]
> kernel: [<ffffffffa08087c8>] qla82xx_rd_32+0xe8/0x140 [qla2xxx]
> kernel: [<ffffffffa0808845>] qla82xx_crb_win_lock+0x25/0x60 [qla2xxx]
> kernel: [<ffffffffa0808976>] qla82xx_wr_32+0xf6/0x150 [qla2xxx]
> kernel: [<ffffffffa0808aa4>] ? qla82xx_disable_intrs+0x34/0x80 [qla2xxx]
> kernel: [<ffffffffa0808ac0>] qla82xx_disable_intrs+0x50/0x80 [qla2xxx]
> kernel: [<ffffffffa080630a>] qla82xx_reset_chip+0x1a/0x20 [qla2xxx]
> kernel: [<ffffffffa07d6ef2>] qla2x00_initialize_adapter+0x132/0x420 [qla2xxx]
> kernel: [<ffffffffa07c964e>] qla2x00_probe_one+0xefe/0x2130 [qla2xxx]
> kernel: [<ffffffff813ee31c>] ? __pm_runtime_resume+0x6c/0x90
> kernel: [<ffffffff8130052c>] local_pci_probe+0x4c/0xa0
> kernel: [<ffffffff81300603>] pci_call_probe+0x83/0xa0
> kernel: [<ffffffff813008cf>] pci_device_probe+0x7f/0xb0
> kernel: [<ffffffff813e2e83>] really_probe+0x133/0x390
> kernel: [<ffffffff813e3139>] driver_probe_device+0x59/0xd0
> kernel: [<ffffffff813e3251>] __driver_attach+0xa1/0xb0
> kernel: [<ffffffff813e31b0>] ? driver_probe_device+0xd0/0xd0
> kernel: [<ffffffff813e0cdd>] bus_for_each_dev+0x8d/0xb0
> kernel: [<ffffffff813e28ee>] driver_attach+0x1e/0x20
> kernel: [<ffffffff813e2252>] bus_add_driver+0x1d2/0x290
> kernel: [<ffffffff813e3970>] driver_register+0x60/0xe0
> kernel: [<ffffffff813009e4>] __pci_register_driver+0x64/0x70
> kernel: [<ffffffffa04bc1cb>] qla2x00_module_init+0x1cb/0x21b [qla2xxx]
> kernel: [<ffffffffa04bc000>] ? 0xffffffffa04bc000
> kernel: [<ffffffff8100027d>] do_one_initcall+0xad/0x1c0
> kernel: [<ffffffff810e2859>] do_init_module+0x69/0x210
> kernel: [<ffffffff810e4e5c>] load_module+0x5cc/0x750
> kernel: [<ffffffff810e1980>] ? mod_sysfs_teardown+0x140/0x140
> kernel: [<ffffffff812c9565>] ? copy_user_enhanced_fast_string+0x5/0x10
> kernel: [<ffffffff810e12f0>] ? module_sect_show+0x30/0x30
> kernel: [<ffffffff810e1a8d>] ? copy_module_from_user+0x8d/0xf0
> kernel: [<ffffffff810e5162>] SyS_init_module+0x92/0xc0
> kernel: [<ffffffff815f37d7>] entry_SYSCALL_64_fastpath+0x12/0x6f
> 
> Signed-off-by: Himanshu Madhani <himanshu.madhani@qlogic.com>
> Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
> ---
>  drivers/scsi/qla2xxx/qla_nx.c |   58 ++++++++++++++++++++--------------------
>  1 files changed, 29 insertions(+), 29 deletions(-)
> 
> diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
> index eb0cc54..96f9b39 100644
> --- a/drivers/scsi/qla2xxx/qla_nx.c
> +++ b/drivers/scsi/qla2xxx/qla_nx.c
> @@ -347,31 +347,33 @@ char *qdev_state(uint32_t dev_state)
>  }
>  
>  /*
> - * In: 'off_in' is offset from CRB space in 128M pci map
> - * Out: 'off_out' is 2M pci map addr
> + * In: 'off' is offset from CRB space in 128M pci map
> + * Out: 'off' is 2M pci map addr
>   * side effect: lock crb window
>   */
>  static void
> -qla82xx_pci_set_crbwindow_2M(struct qla_hw_data *ha, ulong off_in,
> -			     void __iomem **off_out)
> +qla82xx_pci_set_crbwindow_2M(struct qla_hw_data *ha, ulong *off)
>  {
>  	u32 win_read;
>  	scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
>  
> -	ha->crb_win = CRB_HI(off_in);
> -	writel(ha->crb_win, CRB_WINDOW_2M + ha->nx_pcibase);
> +	ha->crb_win = CRB_HI(*off);
> +	writel(ha->crb_win,
> +	    (void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase));
>  
>  	/* Read back value to make sure write has gone through before trying
>  	 * to use it.
>  	 */
> -	win_read = RD_REG_DWORD(CRB_WINDOW_2M + ha->nx_pcibase);
> +	win_read = RD_REG_DWORD((void __iomem *)
> +	    (CRB_WINDOW_2M + ha->nx_pcibase));
>  	if (win_read != ha->crb_win) {
>  		ql_dbg(ql_dbg_p3p, vha, 0xb000,
>  		    "%s: Written crbwin (0x%x) "
>  		    "!= Read crbwin (0x%x), off=0x%lx.\n",
> -		    __func__, ha->crb_win, win_read, off_in);
> +		    __func__, ha->crb_win, win_read, *off);
>  	}
> -	*off_out = (off_in & MASK(16)) + CRB_INDIRECT_2M + ha->nx_pcibase;
> +	*off = (*off & MASK(16)) + CRB_INDIRECT_2M +
> +	    (unsigned long)ha->nx_pcibase;
>  }
>  
Weelll ... I'm not a hardware designer, but this looks dodgy as
hell. You are increasing the offset every time you call this
function. Let's better hope no-one would be stupid enough to call
this function twice ...

Can't you make them idempotent, ie that multiple calls to this
function return the same 'off' number?
That would certainly decrease the likelyhood of an error ...

At the very least add some warning in the function description.

Cheers,

Hannes
diff mbox

Patch

diff --git a/drivers/scsi/qla2xxx/qla_nx.c b/drivers/scsi/qla2xxx/qla_nx.c
index eb0cc54..96f9b39 100644
--- a/drivers/scsi/qla2xxx/qla_nx.c
+++ b/drivers/scsi/qla2xxx/qla_nx.c
@@ -347,31 +347,33 @@  char *qdev_state(uint32_t dev_state)
 }
 
 /*
- * In: 'off_in' is offset from CRB space in 128M pci map
- * Out: 'off_out' is 2M pci map addr
+ * In: 'off' is offset from CRB space in 128M pci map
+ * Out: 'off' is 2M pci map addr
  * side effect: lock crb window
  */
 static void
-qla82xx_pci_set_crbwindow_2M(struct qla_hw_data *ha, ulong off_in,
-			     void __iomem **off_out)
+qla82xx_pci_set_crbwindow_2M(struct qla_hw_data *ha, ulong *off)
 {
 	u32 win_read;
 	scsi_qla_host_t *vha = pci_get_drvdata(ha->pdev);
 
-	ha->crb_win = CRB_HI(off_in);
-	writel(ha->crb_win, CRB_WINDOW_2M + ha->nx_pcibase);
+	ha->crb_win = CRB_HI(*off);
+	writel(ha->crb_win,
+	    (void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase));
 
 	/* Read back value to make sure write has gone through before trying
 	 * to use it.
 	 */
-	win_read = RD_REG_DWORD(CRB_WINDOW_2M + ha->nx_pcibase);
+	win_read = RD_REG_DWORD((void __iomem *)
+	    (CRB_WINDOW_2M + ha->nx_pcibase));
 	if (win_read != ha->crb_win) {
 		ql_dbg(ql_dbg_p3p, vha, 0xb000,
 		    "%s: Written crbwin (0x%x) "
 		    "!= Read crbwin (0x%x), off=0x%lx.\n",
-		    __func__, ha->crb_win, win_read, off_in);
+		    __func__, ha->crb_win, win_read, *off);
 	}
-	*off_out = (off_in & MASK(16)) + CRB_INDIRECT_2M + ha->nx_pcibase;
+	*off = (*off & MASK(16)) + CRB_INDIRECT_2M +
+	    (unsigned long)ha->nx_pcibase;
 }
 
 static inline unsigned long
@@ -416,30 +418,30 @@  qla82xx_pci_set_crbwindow(struct qla_hw_data *ha, u64 off)
 }
 
 static int
-qla82xx_pci_get_crb_addr_2M(struct qla_hw_data *ha, ulong off_in,
-			    void __iomem **off_out)
+qla82xx_pci_get_crb_addr_2M(struct qla_hw_data *ha, ulong *off)
 {
 	struct crb_128M_2M_sub_block_map *m;
 
-	if (off_in >= QLA82XX_CRB_MAX)
+	if (*off >= QLA82XX_CRB_MAX)
 		return -1;
 
-	if (off_in >= QLA82XX_PCI_CAMQM && off_in < QLA82XX_PCI_CAMQM_2M_END) {
-		*off_out = (off_in - QLA82XX_PCI_CAMQM) +
-		    QLA82XX_PCI_CAMQM_2M_BASE + ha->nx_pcibase;
+	if (*off >= QLA82XX_PCI_CAMQM && (*off < QLA82XX_PCI_CAMQM_2M_END)) {
+		*off = (*off - QLA82XX_PCI_CAMQM) +
+		    QLA82XX_PCI_CAMQM_2M_BASE + (unsigned long)ha->nx_pcibase;
 		return 0;
 	}
 
-	if (off_in < QLA82XX_PCI_CRBSPACE)
+	if (*off < QLA82XX_PCI_CRBSPACE)
 		return -1;
 
-	*off_out = (void __iomem *)(off_in - QLA82XX_PCI_CRBSPACE);
+	*off -= QLA82XX_PCI_CRBSPACE;
 
 	/* Try direct map */
-	m = &crb_128M_2M_map[CRB_BLK(off_in)].sub_block[CRB_SUBBLK(off_in)];
+	m = &crb_128M_2M_map[CRB_BLK(*off)].sub_block[CRB_SUBBLK(*off)];
 
-	if (m->valid && (m->start_128M <= off_in) && (m->end_128M > off_in)) {
-		*off_out = off_in + m->start_2M - m->start_128M + ha->nx_pcibase;
+	if (m->valid && (m->start_128M <= *off) && (m->end_128M > *off)) {
+		*off = *off + m->start_2M - m->start_128M +
+		    (unsigned long) ha->nx_pcibase;
 		return 0;
 	}
 	/* Not in direct map, use crb window */
@@ -465,13 +467,12 @@  static int qla82xx_crb_win_lock(struct qla_hw_data *ha)
 }
 
 int
-qla82xx_wr_32(struct qla_hw_data *ha, ulong off_in, u32 data)
+qla82xx_wr_32(struct qla_hw_data *ha, ulong off, u32 data)
 {
-	void __iomem *off;
 	unsigned long flags = 0;
 	int rv;
 
-	rv = qla82xx_pci_get_crb_addr_2M(ha, off_in, &off);
+	rv = qla82xx_pci_get_crb_addr_2M(ha, &off);
 
 	BUG_ON(rv == -1);
 
@@ -480,7 +481,7 @@  qla82xx_wr_32(struct qla_hw_data *ha, ulong off_in, u32 data)
 		write_lock_irqsave(&ha->hw_lock, flags);
 #endif
 		qla82xx_crb_win_lock(ha);
-		qla82xx_pci_set_crbwindow_2M(ha, off_in, &off);
+		qla82xx_pci_set_crbwindow_2M(ha, &off);
 	}
 
 	writel(data, (void __iomem *)off);
@@ -495,14 +496,13 @@  qla82xx_wr_32(struct qla_hw_data *ha, ulong off_in, u32 data)
 }
 
 int
-qla82xx_rd_32(struct qla_hw_data *ha, ulong off_in)
+qla82xx_rd_32(struct qla_hw_data *ha, ulong off)
 {
-	void __iomem *off;
 	unsigned long flags = 0;
 	int rv;
 	u32 data;
 
-	rv = qla82xx_pci_get_crb_addr_2M(ha, off_in, &off);
+	rv = qla82xx_pci_get_crb_addr_2M(ha, &off);
 
 	BUG_ON(rv == -1);
 
@@ -511,9 +511,9 @@  qla82xx_rd_32(struct qla_hw_data *ha, ulong off_in)
 		write_lock_irqsave(&ha->hw_lock, flags);
 #endif
 		qla82xx_crb_win_lock(ha);
-		qla82xx_pci_set_crbwindow_2M(ha, off_in, &off);
+		qla82xx_pci_set_crbwindow_2M(ha, &off);
 	}
-	data = RD_REG_DWORD(off);
+	data = RD_REG_DWORD((void __iomem *)off);
 
 	if (rv == 1) {
 		qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM7_UNLOCK));