]> git.karo-electronics.de Git - linux-beck.git/commitdiff
[SCSI] qla4xxx: Fix the IDC locking mechanism
authorNilesh Javali <nilesh.javali@qlogic.com>
Fri, 2 Dec 2011 06:42:11 +0000 (22:42 -0800)
committerJames Bottomley <JBottomley@Parallels.com>
Thu, 15 Dec 2011 06:57:42 +0000 (10:57 +0400)
This ensures the transition of dev_state from COLD to
INITIALIZING is within lock and atomic.

Signed-off-by: Nilesh Javali <nilesh.javali@qlogic.com>
Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Reviewed-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <JBottomley@Parallels.com>
drivers/scsi/qla4xxx/ql4_nx.c

index 7fc29c6ff57e2ded4a3ec7d296912314fb8ca80c..8d6bc1b2ff17266a45d66dfb923f5c7757cf1493 100644 (file)
@@ -1792,8 +1792,11 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha)
        int rval = QLA_SUCCESS;
        unsigned long dev_init_timeout;
 
-       if (!test_bit(AF_INIT_DONE, &ha->flags))
+       if (!test_bit(AF_INIT_DONE, &ha->flags)) {
+               qla4_8xxx_idc_lock(ha);
                qla4_8xxx_set_drv_active(ha);
+               qla4_8xxx_idc_unlock(ha);
+       }
 
        dev_state = qla4_8xxx_rd_32(ha, QLA82XX_CRB_DEV_STATE);
        ql4_printk(KERN_INFO, ha, "1:Device state is 0x%x = %s\n", dev_state,
@@ -1802,8 +1805,8 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha)
        /* wait for 30 seconds for device to go ready */
        dev_init_timeout = jiffies + (ha->nx_dev_init_timeout * HZ);
 
+       qla4_8xxx_idc_lock(ha);
        while (1) {
-               qla4_8xxx_idc_lock(ha);
 
                if (time_after_eq(jiffies, dev_init_timeout)) {
                        ql4_printk(KERN_WARNING, ha, "Device init failed!\n");
@@ -1819,15 +1822,14 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha)
                /* NOTE: Make sure idc unlocked upon exit of switch statement */
                switch (dev_state) {
                case QLA82XX_DEV_READY:
-                       qla4_8xxx_idc_unlock(ha);
                        goto exit;
                case QLA82XX_DEV_COLD:
                        rval = qla4_8xxx_device_bootstrap(ha);
-                       qla4_8xxx_idc_unlock(ha);
                        goto exit;
                case QLA82XX_DEV_INITIALIZING:
                        qla4_8xxx_idc_unlock(ha);
                        msleep(1000);
+                       qla4_8xxx_idc_lock(ha);
                        break;
                case QLA82XX_DEV_NEED_RESET:
                        if (!ql4xdontresethba) {
@@ -1841,31 +1843,32 @@ int qla4_8xxx_device_state_handler(struct scsi_qla_host *ha)
                                msleep(1000);
                                qla4_8xxx_idc_lock(ha);
                        }
-                       qla4_8xxx_idc_unlock(ha);
                        break;
                case QLA82XX_DEV_NEED_QUIESCENT:
-                       qla4_8xxx_idc_unlock(ha);
                        /* idc locked/unlocked in handler */
                        qla4_8xxx_need_qsnt_handler(ha);
-                       qla4_8xxx_idc_lock(ha);
-                       /* fall thru needs idc_locked */
+                       break;
                case QLA82XX_DEV_QUIESCENT:
                        qla4_8xxx_idc_unlock(ha);
                        msleep(1000);
+                       qla4_8xxx_idc_lock(ha);
                        break;
                case QLA82XX_DEV_FAILED:
                        qla4_8xxx_idc_unlock(ha);
                        qla4xxx_dead_adapter_cleanup(ha);
                        rval = QLA_ERROR;
+                       qla4_8xxx_idc_lock(ha);
                        goto exit;
                default:
                        qla4_8xxx_idc_unlock(ha);
                        qla4xxx_dead_adapter_cleanup(ha);
                        rval = QLA_ERROR;
+                       qla4_8xxx_idc_lock(ha);
                        goto exit;
                }
        }
 exit:
+       qla4_8xxx_idc_unlock(ha);
        return rval;
 }