[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: 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>
This commit is contained in:
Vikas Chaudhary 2010-04-28 11:38:11 +05:30 committed by James Bottomley
parent 2a49a78ed3
commit 065aa1b4db
4 changed files with 70 additions and 7 deletions

View 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;

View 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

View 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:

View 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)) {