[SCSI] qla2xxx: ROM lock recovery if fw hangs while holding the lock.
authorShyam Sundar <shyam.sundar@qlogic.com>
Wed, 8 Sep 2010 03:55:32 +0000 (20:55 -0700)
committerJames Bottomley <James.Bottomley@suse.de>
Fri, 17 Sep 2010 02:54:10 +0000 (22:54 -0400)
Signed-off-by: Giridhar Malavali <giridhar.malavali@qlogic.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
drivers/scsi/qla2xxx/qla_nx.c

index 614d745d7e110be904bce26653d65c3322ed7f00..8d8e40b829e4df89db23047c8508a938d1cd8274 100644 (file)
@@ -3152,6 +3152,20 @@ qla82xx_start_iocbs(srb_t *sp)
        }
 }
 
+void qla82xx_rom_lock_recovery(struct qla_hw_data *ha)
+{
+       if (qla82xx_rom_lock(ha))
+               /* Someone else is holding the lock. */
+               qla_printk(KERN_INFO, ha, "Resetting rom_lock\n");
+
+       /*
+        * Either we got the lock, or someone
+        * else died while holding it.
+        * In either case, unlock.
+        */
+       qla82xx_rd_32(ha, QLA82XX_PCIE_REG(PCIE_SEM2_UNLOCK));
+}
+
 /*
  * qla82xx_device_bootstrap
  *    Initialize device, set DEV_READY, start fw
@@ -3166,12 +3180,13 @@ qla82xx_start_iocbs(srb_t *sp)
 static int
 qla82xx_device_bootstrap(scsi_qla_host_t *vha)
 {
-       int rval, i, timeout;
+       int rval = QLA_SUCCESS;
+       int i, timeout;
        uint32_t old_count, count;
        struct qla_hw_data *ha = vha->hw;
+       int need_reset = 0, peg_stuck = 1;
 
-       if (qla82xx_need_reset(ha))
-               goto dev_initialize;
+       need_reset = qla82xx_need_reset(ha);
 
        old_count = qla82xx_rd_32(ha, QLA82XX_PEG_ALIVE_COUNTER);
 
@@ -3185,9 +3200,27 @@ qla82xx_device_bootstrap(scsi_qla_host_t *vha)
 
                count = qla82xx_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)
+                       qla82xx_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. */
+                       qla82xx_rom_lock_recovery(ha);
+                       goto dev_initialize;
+               } else
+                       /* Firmware already running. */
                        goto dev_ready;
        }
 
+       return rval;
+
 dev_initialize:
        /* set to DEV_INITIALIZING */
        qla_printk(KERN_INFO, ha, "HW State: INITIALIZING\n");