aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVikas Chaudhary <vikas.chaudhary@qlogic.com>2010-04-28 02:08:11 -0400
committerJames Bottomley <James.Bottomley@suse.de>2010-05-02 15:39:20 -0400
commit065aa1b4db63c7fa68a3e889510c4e63404a1ac7 (patch)
tree11a19a7faf1ef71d0a8f45f385b87c8235155f64
parent2a49a78ed3c8d7c8319595270110c69f99c61a74 (diff)
[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>
-rw-r--r--drivers/scsi/qla4xxx/ql4_def.h1
-rw-r--r--drivers/scsi/qla4xxx/ql4_init.c12
-rw-r--r--drivers/scsi/qla4xxx/ql4_isr.c15
-rw-r--r--drivers/scsi/qla4xxx/ql4_os.c49
4 files changed, 70 insertions, 7 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_def.h b/drivers/scsi/qla4xxx/ql4_def.h
index 3175709d4861..347a7c8b53e7 100644
--- a/drivers/scsi/qla4xxx/ql4_def.h
+++ b/drivers/scsi/qla4xxx/ql4_def.h
@@ -310,6 +310,7 @@ struct scsi_qla_host {
310#define DPC_ISNS_RESTART 7 /* 0x00000080 */ 310#define DPC_ISNS_RESTART 7 /* 0x00000080 */
311#define DPC_AEN 9 /* 0x00000200 */ 311#define DPC_AEN 9 /* 0x00000200 */
312#define DPC_GET_DHCP_IP_ADDR 15 /* 0x00008000 */ 312#define DPC_GET_DHCP_IP_ADDR 15 /* 0x00008000 */
313#define DPC_LINK_CHANGED 18 /* 0x00040000 */
313 314
314 struct Scsi_Host *host; /* pointer to host data */ 315 struct Scsi_Host *host; /* pointer to host data */
315 uint32_t tot_ddbs; 316 uint32_t tot_ddbs;
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index 36ec02c49a1b..7f6cc2ebf46c 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -1279,6 +1279,7 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha,
1279 int status = QLA_ERROR; 1279 int status = QLA_ERROR;
1280 int8_t ip_address[IP_ADDR_LEN] = {0} ; 1280 int8_t ip_address[IP_ADDR_LEN] = {0} ;
1281 1281
1282 clear_bit(AF_ONLINE, &ha->flags);
1282 ha->eeprom_cmd_data = 0; 1283 ha->eeprom_cmd_data = 0;
1283 1284
1284 qla4x00_pci_config(ha); 1285 qla4x00_pci_config(ha);
@@ -1456,10 +1457,15 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha,
1456 * the device came back. 1457 * the device came back.
1457 */ 1458 */
1458 } else { 1459 } else {
1459 /* Device went away, try to relogin. */ 1460 /* Device went away, mark device missing */
1460 /* Mark device missing */ 1461 if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE) {
1461 if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE) 1462 DEBUG2(dev_info(&ha->pdev->dev, "%s mark missing "
1463 "ddb_entry 0x%p sess 0x%p conn 0x%p\n",
1464 __func__, ddb_entry,
1465 ddb_entry->sess, ddb_entry->conn));
1462 qla4xxx_mark_device_missing(ha, ddb_entry); 1466 qla4xxx_mark_device_missing(ha, ddb_entry);
1467 }
1468
1463 /* 1469 /*
1464 * Relogin if device state changed to a not active state. 1470 * Relogin if device state changed to a not active state.
1465 * However, do not relogin if this aen is a result of an IOCTL 1471 * However, do not relogin if this aen is a result of an IOCTL
diff --git a/drivers/scsi/qla4xxx/ql4_isr.c b/drivers/scsi/qla4xxx/ql4_isr.c
index c196d55eae39..9db286df7ca0 100644
--- a/drivers/scsi/qla4xxx/ql4_isr.c
+++ b/drivers/scsi/qla4xxx/ql4_isr.c
@@ -498,15 +498,22 @@ static void qla4xxx_isr_decode_mailbox(struct scsi_qla_host * ha,
498 break; 498 break;
499 499
500 case MBOX_ASTS_LINK_UP: 500 case MBOX_ASTS_LINK_UP:
501 DEBUG2(printk("scsi%ld: AEN %04x Adapter LINK UP\n",
502 ha->host_no, mbox_status));
503 set_bit(AF_LINK_UP, &ha->flags); 501 set_bit(AF_LINK_UP, &ha->flags);
502 if (test_bit(AF_INIT_DONE, &ha->flags))
503 set_bit(DPC_LINK_CHANGED, &ha->dpc_flags);
504
505 DEBUG2(printk(KERN_INFO "scsi%ld: AEN %04x Adapter"
506 " LINK UP\n", ha->host_no,
507 mbox_status));
504 break; 508 break;
505 509
506 case MBOX_ASTS_LINK_DOWN: 510 case MBOX_ASTS_LINK_DOWN:
507 DEBUG2(printk("scsi%ld: AEN %04x Adapter LINK DOWN\n",
508 ha->host_no, mbox_status));
509 clear_bit(AF_LINK_UP, &ha->flags); 511 clear_bit(AF_LINK_UP, &ha->flags);
512 set_bit(DPC_LINK_CHANGED, &ha->dpc_flags);
513
514 DEBUG2(printk(KERN_INFO "scsi%ld: AEN %04x Adapter"
515 " LINK DOWN\n", ha->host_no,
516 mbox_status));
510 break; 517 break;
511 518
512 case MBOX_ASTS_HEARTBEAT: 519 case MBOX_ASTS_HEARTBEAT:
diff --git a/drivers/scsi/qla4xxx/ql4_os.c b/drivers/scsi/qla4xxx/ql4_os.c
index 2ccad36bee9f..d6c8b429a675 100644
--- a/drivers/scsi/qla4xxx/ql4_os.c
+++ b/drivers/scsi/qla4xxx/ql4_os.c
@@ -685,6 +685,7 @@ static void qla4xxx_timer(struct scsi_qla_host *ha)
685 test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) || 685 test_bit(DPC_RESET_HA_DESTROY_DDB_LIST, &ha->dpc_flags) ||
686 test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) || 686 test_bit(DPC_RESET_HA_INTR, &ha->dpc_flags) ||
687 test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) || 687 test_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags) ||
688 test_bit(DPC_LINK_CHANGED, &ha->dpc_flags) ||
688 test_bit(DPC_AEN, &ha->dpc_flags)) && 689 test_bit(DPC_AEN, &ha->dpc_flags)) &&
689 ha->dpc_thread) { 690 ha->dpc_thread) {
690 DEBUG2(printk("scsi%ld: %s: scheduling dpc routine" 691 DEBUG2(printk("scsi%ld: %s: scheduling dpc routine"
@@ -1069,6 +1070,54 @@ static void qla4xxx_do_dpc(struct work_struct *work)
1069 if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags)) 1070 if (test_and_clear_bit(DPC_GET_DHCP_IP_ADDR, &ha->dpc_flags))
1070 qla4xxx_get_dhcp_ip_address(ha); 1071 qla4xxx_get_dhcp_ip_address(ha);
1071 1072
1073 /* ---- link change? --- */
1074 if (test_and_clear_bit(DPC_LINK_CHANGED, &ha->dpc_flags)) {
1075 if (!test_bit(AF_LINK_UP, &ha->flags)) {
1076 /* ---- link down? --- */
1077 list_for_each_entry_safe(ddb_entry, dtemp,
1078 &ha->ddb_list, list) {
1079 if (atomic_read(&ddb_entry->state) ==
1080 DDB_STATE_ONLINE)
1081 qla4xxx_mark_device_missing(ha,
1082 ddb_entry);
1083 }
1084 } else {
1085 /* ---- link up? --- *
1086 * F/W will auto login to all devices ONLY ONCE after
1087 * link up during driver initialization and runtime
1088 * fatal error recovery. Therefore, the driver must
1089 * manually relogin to devices when recovering from
1090 * connection failures, logouts, expired KATO, etc. */
1091
1092 list_for_each_entry_safe(ddb_entry, dtemp,
1093 &ha->ddb_list, list) {
1094 if ((atomic_read(&ddb_entry->state) ==
1095 DDB_STATE_MISSING) ||
1096 (atomic_read(&ddb_entry->state) ==
1097 DDB_STATE_DEAD)) {
1098 if (ddb_entry->fw_ddb_device_state ==
1099 DDB_DS_SESSION_ACTIVE) {
1100 atomic_set(&ddb_entry->state,
1101 DDB_STATE_ONLINE);
1102 dev_info(&ha->pdev->dev,
1103 "scsi%ld: %s: ddb[%d]"
1104 " os[%d] marked"
1105 " ONLINE\n",
1106 ha->host_no, __func__,
1107 ddb_entry->fw_ddb_index,
1108 ddb_entry->os_target_id);
1109
1110 iscsi_unblock_session(
1111 ddb_entry->sess);
1112 } else
1113 qla4xxx_relogin_device(
1114 ha, ddb_entry);
1115 }
1116
1117 }
1118 }
1119 }
1120
1072 /* ---- relogin device? --- */ 1121 /* ---- relogin device? --- */
1073 if (adapter_up(ha) && 1122 if (adapter_up(ha) &&
1074 test_and_clear_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags)) { 1123 test_and_clear_bit(DPC_RELOGIN_DEVICE, &ha->dpc_flags)) {