Skip to content

Commit

Permalink
[SCSI] qla4xxx: set device state as per Link UP and LINK DOWN
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Vikas Chaudhary authored and James Bottomley committed May 2, 2010
1 parent 2a49a78 commit 065aa1b
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 7 deletions.
1 change: 1 addition & 0 deletions drivers/scsi/qla4xxx/ql4_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
12 changes: 9 additions & 3 deletions drivers/scsi/qla4xxx/ql4_init.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down
15 changes: 11 additions & 4 deletions drivers/scsi/qla4xxx/ql4_isr.c
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
49 changes: 49 additions & 0 deletions drivers/scsi/qla4xxx/ql4_os.c
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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)) {
Expand Down

0 comments on commit 065aa1b

Please sign in to comment.