Sophie

Sophie

distrib > CentOS > 5 > x86_64 > by-pkgid > ea32411352494358b8d75a78402a4713 > files > 4673

kernel-2.6.18-238.19.1.el5.centos.plus.src.rpm

From: Chad Dupuis <cdupuis@redhat.com>
Date: Tue, 30 Nov 2010 19:59:28 -0500
Subject: [scsi] qla4xxx: clear rom lock if firmware died holding
Message-id: <20101130195928.10450.15822.sendpatchset@localhost.localdomain>
Patchwork-id: 29698
O-Subject: [RHEL 5.6 PATCH 7/28] qla4xxx: Clear the rom lock if the firmware
	died while holding it.
Bugzilla: 656999

Bugzilla
--------

Bug 656999 (https://bugzilla.redhat.com/show_bug.cgi?id=656999)

Upstream Status
---------------

linux-2.6 commit id b25ee66f2d4e5f14e69d75a7363e55889e9aff92

Description
-----------

>From 72c6c8763b0497a8a4dc9b6807e2b2bf1dad711a Mon Sep 17 00:00:00 2001
From: Shyam Sundar <shyam.sundar@qlogic.com>
Date: Sat, 20 Nov 2010 14:18:34 -0800
Subject: [PATCH 08/29] qla4xxx: Clear the rom lock if the firmware died while holding it.

There is a possibility that the firmware dies while the rom
lock is held. The only way to recover from this condition is
to forcefully unlock.

Signed-off-by: Shyam Sundar <shyam.sundar@qlogic.com>
Signed-off-by: Prasanna Mumbai <prasanna.mumbai@qlogic.com>

diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c
index fcc19a6..b925c20 100644
--- a/drivers/scsi/qla4xxx/ql4_nx.c
+++ b/drivers/scsi/qla4xxx/ql4_nx.c
@@ -833,8 +833,12 @@ qla4_8xxx_rom_lock(struct scsi_qla_host *ha)
 		done = qla4_8xxx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_LOCK));
 		if (done == 1)
 			break;
-		if (timeout >= qla4_8xxx_rom_lock_timeout)
+		if (timeout >= qla4_8xxx_rom_lock_timeout) {
+			printk(KERN_WARNING "scsi%ld: "
+				"%s: Failed to acquire rom lock",
+				ha->host_no, __func__);
 			return -1;
+		}
 
 		timeout++;
 
@@ -1509,6 +1513,21 @@ qla4_8xxx_try_start_fw(struct scsi_qla_host *ha)
 	return rval;
 }
 
+static void qla4_8xxx_rom_lock_recovery(struct scsi_qla_host *ha)
+{
+	if (qla4_8xxx_rom_lock(ha)) {
+		/* Someone else is holding the lock. */
+		dev_info(&ha->pdev->dev, "Resetting rom_lock\n");
+	}
+
+	/*
+	 * Either we got the lock, or someone
+	 * else died while holding it.
+	 * In either case, unlock.
+	 */
+	qla4_8xxx_rom_unlock(ha);
+}
+
 /**
  * qla4_8xxx_device_bootstrap - Initialize device, set DEV_READY, start fw
  * @ha: pointer to adapter structure
@@ -1518,11 +1537,12 @@ qla4_8xxx_try_start_fw(struct scsi_qla_host *ha)
 static int
 qla4_8xxx_device_bootstrap(struct scsi_qla_host *ha)
 {
-	int rval, i, timeout;
+	int rval = QLA_ERROR;
+	int i, timeout;
 	uint32_t old_count, count;
+	int need_reset = 0, peg_stuck = 1;
 
-	if (qla4_8xxx_need_reset(ha))
-		goto dev_initialize;
+	need_reset = qla4_8xxx_need_reset(ha);
 
 	old_count = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER);
 
@@ -1531,12 +1551,30 @@ qla4_8xxx_device_bootstrap(struct scsi_qla_host *ha)
 		if (timeout) {
 			qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE,
 			    QLA82XX_DEV_FAILED);
-			return QLA_ERROR;  /* FIXME: CHANGE AT LATER POINT IN TIME */
+			return rval;
 		}
 
 		count = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER);
 		if (count != old_count)
+			peg_stuck = 0;
+	}
+
+	if (need_reset) {
+		/* We are trying to perform a recovery here. */
+		if (peg_stuck)
+			qla4_8xxx_rom_lock_recovery(ha);
+		goto dev_initialize;
+	} else  {
+		/* Start of day for this ha context. */
+		if (peg_stuck) {
+			/* Either we are the first or recovery in progress. */
+			qla4_8xxx_rom_lock_recovery(ha);
+			goto dev_initialize;
+		} else {
+			/* Firmware already running. */
+			rval = QLA_SUCCESS;
 			goto dev_ready;
+		}
 	}
 
 dev_initialize:
@@ -1562,7 +1600,7 @@ dev_ready:
 	DEBUG2(printk(KERN_INFO"HW State: READY\n"));
 	qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_READY);
 
-	return QLA_SUCCESS;
+	return rval;
 }
 
 /**