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);
                 * 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
 
                        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:
 
             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"
        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)) {