Commit 065aa1b4 authored by Vikas Chaudhary's avatar Vikas Chaudhary Committed by James Bottomley

[SCSI] qla4xxx: set device state as per Link UP and LINK DOWN

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: default avatarVikas Chaudhary <vikas.chaudhary@qlogic.com>
Signed-off-by: default avatarKaren Higgins <karen.higgins@qlogic.com>
Signed-off-by: default avatarRavi Anand <ravi.anand@qlogic.com>
Reviewed-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 2a49a78e
...@@ -310,6 +310,7 @@ struct scsi_qla_host { ...@@ -310,6 +310,7 @@ struct scsi_qla_host {
#define DPC_ISNS_RESTART 7 /* 0x00000080 */ #define DPC_ISNS_RESTART 7 /* 0x00000080 */
#define DPC_AEN 9 /* 0x00000200 */ #define DPC_AEN 9 /* 0x00000200 */
#define DPC_GET_DHCP_IP_ADDR 15 /* 0x00008000 */ #define DPC_GET_DHCP_IP_ADDR 15 /* 0x00008000 */
#define DPC_LINK_CHANGED 18 /* 0x00040000 */
struct Scsi_Host *host; /* pointer to host data */ struct Scsi_Host *host; /* pointer to host data */
uint32_t tot_ddbs; uint32_t tot_ddbs;
......
...@@ -1279,6 +1279,7 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, ...@@ -1279,6 +1279,7 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha,
int status = QLA_ERROR; int status = QLA_ERROR;
int8_t ip_address[IP_ADDR_LEN] = {0} ; int8_t ip_address[IP_ADDR_LEN] = {0} ;
clear_bit(AF_ONLINE, &ha->flags);
ha->eeprom_cmd_data = 0; ha->eeprom_cmd_data = 0;
qla4x00_pci_config(ha); qla4x00_pci_config(ha);
...@@ -1456,10 +1457,15 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, ...@@ -1456,10 +1457,15 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha,
* the device came back. * the device came back.
*/ */
} else { } else {
/* Device went away, try to relogin. */ /* Device went away, mark device missing */
/* Mark device missing */ if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE) {
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); qla4xxx_mark_device_missing(ha, ddb_entry);
}
/* /*
* Relogin if device state changed to a not active state. * Relogin if device state changed to a not active state.
* However, do not relogin if this aen is a result of an IOCTL * However, do not relogin if this aen is a result of an IOCTL
......
...@@ -498,15 +498,22 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha, ...@@ -498,15 +498,22 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
break; break;
case MBOX_ASTS_LINK_UP: 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); 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; break;
case MBOX_ASTS_LINK_DOWN: 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); 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; break;
case MBOX_ASTS_HEARTBEAT: case MBOX_ASTS_HEARTBEAT:
......
...@@ -685,6 +685,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha) ...@@ -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_DESTROY_DDB_LIST, &ha->dpc_flags) ||
test_bit(DPC_RESET_HA_INTR, &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_GET_DHCP_IP_ADDR, &ha->dpc_flags) ||
test_bit(DPC_LINK_CHANGED, &ha->dpc_flags) ||
test_bit(DPC_AEN, &ha->dpc_flags)) && test_bit(DPC_AEN, &ha->dpc_flags)) &&
ha->dpc_thread) { ha->dpc_thread) {
DEBUG2(printk("scsi%ld: %s: scheduling dpc routine" DEBUG2(printk("scsi%ld: %s: scheduling dpc routine"
...@@ -1069,6 +1070,54 @@ static void qla4xxx_do_dpc(struct work_struct *work) ...@@ -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)) if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags))
qla4xxx_get_dhcp_ip_address(ha); 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? --- */ /* ---- relogin device? --- */
if (adapter_up(ha) && if (adapter_up(ha) &&
test_and_clear_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags)) { test_and_clear_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags)) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment