diff mbox

qla4xxx: Fix a sleep-in-atomic bug

Message ID 1496193571-31682-1-git-send-email-baijiaju1990@163.com (mailing list archive)
State Rejected, archived
Headers show

Commit Message

Jia-Ju Bai May 31, 2017, 1:19 a.m. UTC
The driver may sleep under a write spin lock, the function call path is:
qla4_82xx_wr_32 (acquire the lock)
  qla4_82xx_crb_win_lock
      schedule or cpu_relax

To fixed it, the lock is released before "schedule" and "cpu_relax", 
and the lock is acquired again after "schedule" and "cpu_relax".

Signed-off-by: Jia-Ju Bai <baijiaju1990@163.com>
---
 drivers/scsi/qla4xxx/ql4_nx.c |    8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

Comments

kernel test robot May 31, 2017, 3:15 a.m. UTC | #1
Hi Jia-Ju,

[auto build test ERROR on scsi/for-next]
[also build test ERROR on v4.12-rc3 next-20170530]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Jia-Ju-Bai/qla4xxx-Fix-a-sleep-in-atomic-bug/20170531-104628
base:   https://git.kernel.org/pub/scm/linux/kernel/git/jejb/scsi.git for-next
config: x86_64-randconfig-x006-201722 (attached as .config)
compiler: gcc-6 (Debian 6.2.0-3) 6.2.0 20160901
reproduce:
        # save the attached .config to linux build tree
        make ARCH=x86_64 

All errors (new ones prefixed by >>):

   drivers/scsi/qla4xxx/ql4_nx.c: In function 'qla4_82xx_wr_32':
>> drivers/scsi/qla4xxx/ql4_nx.c:389:3: error: too many arguments to function 'qla4_82xx_crb_win_lock'
      qla4_82xx_crb_win_lock(ha, flags);
      ^~~~~~~~~~~~~~~~~~~~~~
   In file included from drivers/scsi/qla4xxx/ql4_nx.c:12:0:
   drivers/scsi/qla4xxx/ql4_glbl.h:118:5: note: declared here
    int qla4_82xx_crb_win_lock(struct scsi_qla_host *);
        ^~~~~~~~~~~~~~~~~~~~~~
   drivers/scsi/qla4xxx/ql4_nx.c: In function 'qla4_82xx_rd_32':
   drivers/scsi/qla4xxx/ql4_nx.c:413:3: error: too many arguments to function 'qla4_82xx_crb_win_lock'
      qla4_82xx_crb_win_lock(ha, flags);
      ^~~~~~~~~~~~~~~~~~~~~~
   In file included from drivers/scsi/qla4xxx/ql4_nx.c:12:0:
   drivers/scsi/qla4xxx/ql4_glbl.h:118:5: note: declared here
    int qla4_82xx_crb_win_lock(struct scsi_qla_host *);
        ^~~~~~~~~~~~~~~~~~~~~~
   drivers/scsi/qla4xxx/ql4_nx.c: At top level:
>> drivers/scsi/qla4xxx/ql4_nx.c:479:5: error: conflicting types for 'qla4_82xx_crb_win_lock'
    int qla4_82xx_crb_win_lock(struct scsi_qla_host *ha, unsigned long flags)
        ^~~~~~~~~~~~~~~~~~~~~~
   In file included from drivers/scsi/qla4xxx/ql4_nx.c:12:0:
   drivers/scsi/qla4xxx/ql4_glbl.h:118:5: note: previous declaration of 'qla4_82xx_crb_win_lock' was here
    int qla4_82xx_crb_win_lock(struct scsi_qla_host *);
        ^~~~~~~~~~~~~~~~~~~~~~

vim +/qla4_82xx_crb_win_lock +389 drivers/scsi/qla4xxx/ql4_nx.c

   383		rv = qla4_82xx_pci_get_crb_addr_2M(ha, &off);
   384	
   385		BUG_ON(rv == -1);
   386	
   387		if (rv == 1) {
   388			write_lock_irqsave(&ha->hw_lock, flags);
 > 389			qla4_82xx_crb_win_lock(ha, flags);
   390			qla4_82xx_pci_set_crbwindow_2M(ha, &off);
   391		}
   392	
   393		writel(data, (void __iomem *)off);
   394	
   395		if (rv == 1) {
   396			qla4_82xx_crb_win_unlock(ha);
   397			write_unlock_irqrestore(&ha->hw_lock, flags);
   398		}
   399	}
   400	
   401	uint32_t qla4_82xx_rd_32(struct scsi_qla_host *ha, ulong off)
   402	{
   403		unsigned long flags = 0;
   404		int rv;
   405		u32 data;
   406	
   407		rv = qla4_82xx_pci_get_crb_addr_2M(ha, &off);
   408	
   409		BUG_ON(rv == -1);
   410	
   411		if (rv == 1) {
   412			write_lock_irqsave(&ha->hw_lock, flags);
 > 413			qla4_82xx_crb_win_lock(ha, flags);
   414			qla4_82xx_pci_set_crbwindow_2M(ha, &off);
   415		}
   416		data = readl((void __iomem *)off);
   417	
   418		if (rv == 1) {
   419			qla4_82xx_crb_win_unlock(ha);
   420			write_unlock_irqrestore(&ha->hw_lock, flags);
   421		}
   422		return data;
   423	}
   424	
   425	/* Minidump related functions */
   426	int qla4_82xx_md_rd_32(struct scsi_qla_host *ha, uint32_t off, uint32_t *data)
   427	{
   428		uint32_t win_read, off_value;
   429		int rval = QLA_SUCCESS;
   430	
   431		off_value  = off & 0xFFFF0000;
   432		writel(off_value, (void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase));
   433	
   434		/*
   435		 * Read back value to make sure write has gone through before trying
   436		 * to use it.
   437		 */
   438		win_read = readl((void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase));
   439		if (win_read != off_value) {
   440			DEBUG2(ql4_printk(KERN_INFO, ha,
   441					  "%s: Written (0x%x) != Read (0x%x), off=0x%x\n",
   442					  __func__, off_value, win_read, off));
   443			rval = QLA_ERROR;
   444		} else {
   445			off_value  = off & 0x0000FFFF;
   446			*data = readl((void __iomem *)(off_value + CRB_INDIRECT_2M +
   447						       ha->nx_pcibase));
   448		}
   449		return rval;
   450	}
   451	
   452	int qla4_82xx_md_wr_32(struct scsi_qla_host *ha, uint32_t off, uint32_t data)
   453	{
   454		uint32_t win_read, off_value;
   455		int rval = QLA_SUCCESS;
   456	
   457		off_value  = off & 0xFFFF0000;
   458		writel(off_value, (void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase));
   459	
   460		/* Read back value to make sure write has gone through before trying
   461		 * to use it.
   462		 */
   463		win_read = readl((void __iomem *)(CRB_WINDOW_2M + ha->nx_pcibase));
   464		if (win_read != off_value) {
   465			DEBUG2(ql4_printk(KERN_INFO, ha,
   466					  "%s: Written (0x%x) != Read (0x%x), off=0x%x\n",
   467					  __func__, off_value, win_read, off));
   468			rval = QLA_ERROR;
   469		} else {
   470			off_value  = off & 0x0000FFFF;
   471			writel(data, (void __iomem *)(off_value + CRB_INDIRECT_2M +
   472						      ha->nx_pcibase));
   473		}
   474		return rval;
   475	}
   476	
   477	#define CRB_WIN_LOCK_TIMEOUT 100000000
   478	
 > 479	int qla4_82xx_crb_win_lock(struct scsi_qla_host *ha, unsigned long flags)
   480	{
   481		int i;
   482		int done = 0, timeout = 0;

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
diff mbox

Patch

diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c
index e91abb3..1cf5f4a 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.c
+++ b/drivers/scsi/qla4xxx/ql4_nx.c
@@ -386,7 +386,7 @@ 
 
 	if (rv == 1) {
 		write_lock_irqsave(&ha->hw_lock, flags);
-		qla4_82xx_crb_win_lock(ha);
+		qla4_82xx_crb_win_lock(ha, flags);
 		qla4_82xx_pci_set_crbwindow_2M(ha, &off);
 	}
 
@@ -410,7 +410,7 @@  uint32_t qla4_82xx_rd_32(struct scsi_qla_host *ha, ulong off)
 
 	if (rv == 1) {
 		write_lock_irqsave(&ha->hw_lock, flags);
-		qla4_82xx_crb_win_lock(ha);
+		qla4_82xx_crb_win_lock(ha, flags);
 		qla4_82xx_pci_set_crbwindow_2M(ha, &off);
 	}
 	data = readl((void __iomem *)off);
@@ -476,7 +476,7 @@  int qla4_82xx_md_wr_32(struct scsi_qla_host *ha, uint32_t off, uint32_t data)
 
 #define CRB_WIN_LOCK_TIMEOUT 100000000
 
-int qla4_82xx_crb_win_lock(struct scsi_qla_host *ha)
+int qla4_82xx_crb_win_lock(struct scsi_qla_host *ha, unsigned long flags)
 {
 	int i;
 	int done = 0, timeout = 0;
@@ -491,6 +491,7 @@  int qla4_82xx_crb_win_lock(struct scsi_qla_host *ha)
 
 		timeout++;
 
+		write_unlock_irqrestore(&ha->hw_lock, flags);
 		/* Yield CPU */
 		if (!in_interrupt())
 			schedule();
@@ -498,6 +499,7 @@  int qla4_82xx_crb_win_lock(struct scsi_qla_host *ha)
 			for (i = 0; i < 20; i++)
 				cpu_relax();    /*This a nop instr on i386*/
 		}
+		write_lock_irqsave(&ha->hw_lock, flags);
 	}
 	qla4_82xx_wr_32(ha, QLA82XX_CRB_WIN_LOCK_ID, ha->func_num);
 	return 0;