Browse Source

[SCSI] be2iscsi: Fix soft lock up issue during UE or if FW taking time to respond

The timeout set in MBX_CMD is 100sec and the ready bit checking in BMBX
mode is done for 4sec. After 4sec the task is scheduled out for 5 secs
to avoid kernel soft lockup stack trace. The loop of 4sec ready bit check
and then schedule out is done until the following conditon occur
- The Ready Bit is Set
- The timeout set in MBX_CMD expires

Signed-off-by: John Soni Jose <sony.john-n@emulex.com>
Signed-off-by: Jayamohan Kallickal <jayamohan.kallickal@emulex.com>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Jayamohan Kallickal 11 years ago
parent
commit
92665a6628
3 changed files with 34 additions and 21 deletions
  1. 1 1
      drivers/scsi/be2iscsi/be.h
  2. 31 17
      drivers/scsi/be2iscsi/be_cmds.c
  3. 2 3
      drivers/scsi/be2iscsi/be_main.c

+ 1 - 1
drivers/scsi/be2iscsi/be.h

@@ -128,7 +128,7 @@ struct be_ctrl_info {
 
 #define PAGE_SHIFT_4K 12
 #define PAGE_SIZE_4K (1 << PAGE_SHIFT_4K)
-#define mcc_timeout		120000 /* 5s timeout */
+#define mcc_timeout		120000 /* 12s timeout */
 
 /* Returns number of pages spanned by the data starting at the given addr */
 #define PAGES_4K_SPANNED(_address, size)				\

+ 31 - 17
drivers/scsi/be2iscsi/be_cmds.c

@@ -490,33 +490,47 @@ int be_mcc_notify_wait(struct beiscsi_hba *phba)
  **/
 static int be_mbox_db_ready_wait(struct be_ctrl_info *ctrl)
 {
+#define BEISCSI_MBX_RDY_BIT_TIMEOUT	4000	/* 4sec */
 	void __iomem *db = ctrl->db + MPU_MAILBOX_DB_OFFSET;
 	struct beiscsi_hba *phba = pci_get_drvdata(ctrl->pdev);
-	uint32_t wait = 0;
+	unsigned long timeout;
+	bool read_flag = false;
+	int ret = 0, i;
 	u32 ready;
+	DECLARE_WAIT_QUEUE_HEAD_ONSTACK(rdybit_check_q);
 
-	do {
+	if (beiscsi_error(phba))
+		return -EIO;
 
-		if (beiscsi_error(phba))
-			return -EIO;
+	timeout = jiffies + (HZ * 110);
 
-		ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK;
-		if (ready)
-			break;
+	do {
+		for (i = 0; i < BEISCSI_MBX_RDY_BIT_TIMEOUT; i++) {
+			ready = ioread32(db) & MPU_MAILBOX_DB_RDY_MASK;
+			if (ready) {
+				read_flag = true;
+				break;
+			}
+			mdelay(1);
+		}
 
-		if (wait > BEISCSI_HOST_MBX_TIMEOUT) {
-			beiscsi_log(phba, KERN_ERR,
-				    BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
-				    "BC_%d : FW Timed Out\n");
+		if (!read_flag) {
+			wait_event_timeout(rdybit_check_q,
+					  (read_flag != true),
+					   HZ * 5);
+		}
+	} while ((time_before(jiffies, timeout)) && !read_flag);
+
+	if (!read_flag) {
+		beiscsi_log(phba, KERN_ERR,
+			    BEISCSI_LOG_CONFIG | BEISCSI_LOG_MBOX,
+			    "BC_%d : FW Timed Out\n");
 			phba->fw_timeout = true;
 			beiscsi_ue_detect(phba);
-			return -EBUSY;
-		}
+			ret = -EBUSY;
+	}
 
-		mdelay(1);
-		wait++;
-	} while (true);
-	return 0;
+	return ret;
 }
 
 /*

+ 2 - 3
drivers/scsi/be2iscsi/be_main.c

@@ -5002,14 +5002,13 @@ static int beiscsi_dev_probe(struct pci_dev *pcidev,
 	ret = beiscsi_cmd_reset_function(phba);
 	if (ret) {
 		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
-			    "BM_%d : Reset Failed. Aborting Crashdump\n");
+			    "BM_%d : Reset Failed\n");
 		goto hba_free;
 	}
 	ret = be_chk_reset_complete(phba);
 	if (ret) {
 		beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_INIT,
-			    "BM_%d : Failed to get out of reset."
-			    "Aborting Crashdump\n");
+			    "BM_%d : Failed to get out of reset.\n");
 		goto hba_free;
 	}