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; } /**