[SCSI] qla4xxx: set device state as per Link UP and LINK DOWN
authorVikas Chaudhary <vikas.chaudhary@qlogic.com>
Wed, 28 Apr 2010 06:08:11 +0000 (11:38 +0530)
committerJames Bottomley <James.Bottomley@suse.de>
Sun, 2 May 2010 19:39:20 +0000 (15:39 -0400)
Link Down -> Mark all devices missing
 Previously, the driver took no action on a Link Down,
 and waited for the I/O on a dead connection to timeout
 in the firmware before marking the DDB missing.

Link Up -> Mark all devices online
 F/W will do auto login to all the devices only once.
 After that its the responsibility of the driver to
 relogin to devices whenever there is :
        * Any sort of connection failure or
        * KATO expires indicating target has logged out or
        * I/O times out etc.

Signed-off-by: Vikas Chaudhary <vikas.chaudhary@qlogic.com>
Signed-off-by: Karen Higgins <karen.higgins@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>
drivers/scsi/qla4xxx/ql4_def.h
drivers/scsi/qla4xxx/ql4_init.c
drivers/scsi/qla4xxx/ql4_isr.c
drivers/scsi/qla4xxx/ql4_os.c

index 3175709d4861c1d15155b8d6ee75d59a92fa2db9..347a7c8b53e7e82c4f1224771d74bcc1c5fea2bd 100644 (file)
@@ -310,6 +310,7 @@ struct scsi_qla_host {
 #define DPC_ISNS_RESTART               7 /* 0x00000080 */
 #define DPC_AEN                                9 /* 0x00000200 */
 #define DPC_GET_DHCP_IP_ADDR           15 /* 0x00008000 */
+#define DPC_LINK_CHANGED               18 /* 0x00040000 */
 
        struct Scsi_Host *host; /* pointer to host data */
        uint32_t tot_ddbs;
index 36ec02c49a1b409c36ec212127c49e04757ca437..7f6cc2ebf46cacf2a77d8f10c552dfd842f8e707 100644 (file)
@@ -1279,6 +1279,7 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha,
        int status = QLA_ERROR;
        int8_t ip_address[IP_ADDR_LEN] = {0} ;
 
+       clear_bit(AF_ONLINE, &ha->flags);
        ha->eeprom_cmd_data = 0;
 
        qla4x00_pci_config(ha);
@@ -1456,10 +1457,15 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha,
                 * the device came back.
                 */
        } else {
-               /* Device went away, try to relogin. */
-               /* Mark device missing */
-               if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE)
+               /* Device went away, mark device missing */
+               if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE) {
+                       DEBUG2(dev_info(&ha->pdev->dev, "%s mark missing "
+                                       "ddb_entry 0x%p sess 0x%p conn 0x%p\n",
+                                       __func__, ddb_entry,
+                                       ddb_entry->sess, ddb_entry->conn));
                        qla4xxx_mark_device_missing(ha, ddb_entry);
+               }
+
                /*
                 * Relogin if device state changed to a not active state.
                 * However, do not relogin if this aen is a result of an IOCTL
index c196d55eae3939c71b8cae29afaa335665dc1aea..9db286df7ca081ae1f6cf2025791ea4d98f1f7db 100644 (file)
@@ -498,15 +498,22 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
                        break;
 
                case MBOX_ASTS_LINK_UP:
-                       DEBUG2(printk("scsi%ld: AEN %04x Adapter LINK UP\n",
-                                     ha->host_no, mbox_status));
                        set_bit(AF_LINK_UP, &ha->flags);
+                       if (test_bit(AF_INIT_DONE, &ha->flags))
+                               set_bit(DPC_LINK_CHANGED, &ha->dpc_flags);
+
+                       DEBUG2(printk(KERN_INFO "scsi%ld: AEN %04x Adapter"
+                                       " LINK UP\n", ha->host_no,
+                                       mbox_status));
                        break;
 
                case MBOX_ASTS_LINK_DOWN:
-                       DEBUG2(printk("scsi%ld: AEN %04x Adapter LINK DOWN\n",
-                                     ha->host_no, mbox_status));
                        clear_bit(AF_LINK_UP, &ha->flags);
+                       set_bit(DPC_LINK_CHANGED, &ha->dpc_flags);
+
+                       DEBUG2(printk(KERN_INFO "scsi%ld: AEN %04x Adapter"
+                                       " LINK DOWN\n", ha->host_no,
+                                       mbox_status));
                        break;
 
                case MBOX_ASTS_HEARTBEAT:
index 2ccad36bee9f0843a6807ede4cd44b5fd62dc48f..d6c8b429a67518edf41eab8a60f28af3c444ffda 100644 (file)
@@ -685,6 +685,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha)
             test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) ||
             test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||
             test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) ||
+            test_bit(DPC_LINK_CHANGED, &ha->dpc_flags) ||
             test_bit(DPC_AEN, &ha->dpc_flags)) &&
             ha->dpc_thread) {
                DEBUG2(printk("scsi%ld: %s: scheduling dpc routine"
@@ -1069,6 +1070,54 @@ static void qla4xxx_do_dpc(struct work_struct *work)
        if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags))
                qla4xxx_get_dhcp_ip_address(ha);
 
+       /* ---- link change? --- */
+       if (test_and_clear_bit(DPC_LINK_CHANGED, &ha->dpc_flags)) {
+               if (!test_bit(AF_LINK_UP, &ha->flags)) {
+                       /* ---- link down? --- */
+                       list_for_each_entry_safe(ddb_entry, dtemp,
+                                                &ha->ddb_list, list) {
+                               if (atomic_read(&ddb_entry->state) ==
+                                               DDB_STATE_ONLINE)
+                                       qla4xxx_mark_device_missing(ha,
+                                                       ddb_entry);
+                       }
+               } else {
+                       /* ---- link up? --- *
+                        * F/W will auto login to all devices ONLY ONCE after
+                        * link up during driver initialization and runtime
+                        * fatal error recovery.  Therefore, the driver must
+                        * manually relogin to devices when recovering from
+                        * connection failures, logouts, expired KATO, etc. */
+
+                       list_for_each_entry_safe(ddb_entry, dtemp,
+                                                       &ha->ddb_list, list) {
+                               if ((atomic_read(&ddb_entry->state) ==
+                                                DDB_STATE_MISSING) ||
+                                   (atomic_read(&ddb_entry->state) ==
+                                                DDB_STATE_DEAD)) {
+                                       if (ddb_entry->fw_ddb_device_state ==
+                                           DDB_DS_SESSION_ACTIVE) {
+                                               atomic_set(&ddb_entry->state,
+                                                          DDB_STATE_ONLINE);
+                                               dev_info(&ha->pdev->dev,
+                                                   "scsi%ld: %s: ddb[%d]"
+                                                   " os[%d] marked"
+                                                   " ONLINE\n",
+                                                   ha->host_no, __func__,
+                                                   ddb_entry->fw_ddb_index,
+                                                   ddb_entry->os_target_id);
+
+                                               iscsi_unblock_session(
+                                                   ddb_entry->sess);
+                                       } else
+                                               qla4xxx_relogin_device(
+                                                   ha, ddb_entry);
+                               }
+
+                       }
+               }
+       }
+
        /* ---- relogin device? --- */
        if (adapter_up(ha) &&
            test_and_clear_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags)) {