diff options
author | Shyam Sundar <shyam.sundar@qlogic.com> | 2010-10-07 01:50:51 -0400 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2010-10-25 15:53:29 -0400 |
commit | b25ee66f2d4e5f14e69d75a7363e55889e9aff92 (patch) | |
tree | f0a2732267387c98eb872d32911247016841426c /drivers/scsi/qla4xxx | |
parent | 2657c800dbb24761097ef341dfa43672c08a7a9e (diff) |
[SCSI] 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: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Signed-off-by: Ravi Anand <ravi.anand@qlogic.com>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/qla4xxx')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_nx.c | 49 |
1 files changed, 43 insertions, 6 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_nx.c b/drivers/scsi/qla4xxx/ql4_nx.c index b311a96acf11..74582cb46a28 100644 --- a/drivers/scsi/qla4xxx/ql4_nx.c +++ b/drivers/scsi/qla4xxx/ql4_nx.c | |||
@@ -839,8 +839,11 @@ qla4_8xxx_rom_lock(struct scsi_qla_host *ha) | |||
839 | done = qla4_8xxx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_LOCK)); | 839 | done = qla4_8xxx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_LOCK)); |
840 | if (done == 1) | 840 | if (done == 1) |
841 | break; | 841 | break; |
842 | if (timeout >= qla4_8xxx_rom_lock_timeout) | 842 | if (timeout >= qla4_8xxx_rom_lock_timeout) { |
843 | ql4_printk(KERN_WARNING, ha, | ||
844 | "%s: Failed to acquire rom lock", __func__); | ||
843 | return -1; | 845 | return -1; |
846 | } | ||
844 | 847 | ||
845 | timeout++; | 848 | timeout++; |
846 | 849 | ||
@@ -1550,6 +1553,21 @@ qla4_8xxx_try_start_fw(struct scsi_qla_host *ha) | |||
1550 | return rval; | 1553 | return rval; |
1551 | } | 1554 | } |
1552 | 1555 | ||
1556 | static void qla4_8xxx_rom_lock_recovery(struct scsi_qla_host *ha) | ||
1557 | { | ||
1558 | if (qla4_8xxx_rom_lock(ha)) { | ||
1559 | /* Someone else is holding the lock. */ | ||
1560 | dev_info(&ha->pdev->dev, "Resetting rom_lock\n"); | ||
1561 | } | ||
1562 | |||
1563 | /* | ||
1564 | * Either we got the lock, or someone | ||
1565 | * else died while holding it. | ||
1566 | * In either case, unlock. | ||
1567 | */ | ||
1568 | qla4_8xxx_rom_unlock(ha); | ||
1569 | } | ||
1570 | |||
1553 | /** | 1571 | /** |
1554 | * qla4_8xxx_device_bootstrap - Initialize device, set DEV_READY, start fw | 1572 | * qla4_8xxx_device_bootstrap - Initialize device, set DEV_READY, start fw |
1555 | * @ha: pointer to adapter structure | 1573 | * @ha: pointer to adapter structure |
@@ -1559,11 +1577,12 @@ qla4_8xxx_try_start_fw(struct scsi_qla_host *ha) | |||
1559 | static int | 1577 | static int |
1560 | qla4_8xxx_device_bootstrap(struct scsi_qla_host *ha) | 1578 | qla4_8xxx_device_bootstrap(struct scsi_qla_host *ha) |
1561 | { | 1579 | { |
1562 | int rval, i, timeout; | 1580 | int rval = QLA_ERROR; |
1581 | int i, timeout; | ||
1563 | uint32_t old_count, count; | 1582 | uint32_t old_count, count; |
1583 | int need_reset = 0, peg_stuck = 1; | ||
1564 | 1584 | ||
1565 | if (qla4_8xxx_need_reset(ha)) | 1585 | need_reset = qla4_8xxx_need_reset(ha); |
1566 | goto dev_initialize; | ||
1567 | 1586 | ||
1568 | old_count = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); | 1587 | old_count = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); |
1569 | 1588 | ||
@@ -1572,12 +1591,30 @@ qla4_8xxx_device_bootstrap(struct scsi_qla_host *ha) | |||
1572 | if (timeout) { | 1591 | if (timeout) { |
1573 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, | 1592 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, |
1574 | QLA82XX_DEV_FAILED); | 1593 | QLA82XX_DEV_FAILED); |
1575 | return QLA_ERROR; | 1594 | return rval; |
1576 | } | 1595 | } |
1577 | 1596 | ||
1578 | count = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); | 1597 | count = qla4_8xxx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER); |
1579 | if (count != old_count) | 1598 | if (count != old_count) |
1599 | peg_stuck = 0; | ||
1600 | } | ||
1601 | |||
1602 | if (need_reset) { | ||
1603 | /* We are trying to perform a recovery here. */ | ||
1604 | if (peg_stuck) | ||
1605 | qla4_8xxx_rom_lock_recovery(ha); | ||
1606 | goto dev_initialize; | ||
1607 | } else { | ||
1608 | /* Start of day for this ha context. */ | ||
1609 | if (peg_stuck) { | ||
1610 | /* Either we are the first or recovery in progress. */ | ||
1611 | qla4_8xxx_rom_lock_recovery(ha); | ||
1612 | goto dev_initialize; | ||
1613 | } else { | ||
1614 | /* Firmware already running. */ | ||
1615 | rval = QLA_SUCCESS; | ||
1580 | goto dev_ready; | 1616 | goto dev_ready; |
1617 | } | ||
1581 | } | 1618 | } |
1582 | 1619 | ||
1583 | dev_initialize: | 1620 | dev_initialize: |
@@ -1603,7 +1640,7 @@ dev_ready: | |||
1603 | ql4_printk(KERN_INFO, ha, "HW State: READY\n"); | 1640 | ql4_printk(KERN_INFO, ha, "HW State: READY\n"); |
1604 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_READY); | 1641 | qla4_8xxx_wr_32(ha, QLA82XX_CRB_DEV_STATE, QLA82XX_DEV_READY); |
1605 | 1642 | ||
1606 | return QLA_SUCCESS; | 1643 | return rval; |
1607 | } | 1644 | } |
1608 | 1645 | ||
1609 | /** | 1646 | /** |