diff options
Diffstat (limited to 'drivers/scsi/qla4xxx/ql4_init.c')
-rw-r--r-- | drivers/scsi/qla4xxx/ql4_init.c | 207 |
1 files changed, 34 insertions, 173 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c index 1629c48c35e..bbb2e903d38 100644 --- a/drivers/scsi/qla4xxx/ql4_init.c +++ b/drivers/scsi/qla4xxx/ql4_init.c | |||
@@ -723,13 +723,38 @@ int qla4_is_relogin_allowed(struct scsi_qla_host *ha, uint32_t conn_err) | |||
723 | return relogin; | 723 | return relogin; |
724 | } | 724 | } |
725 | 725 | ||
726 | static void qla4xxx_flush_AENS(struct scsi_qla_host *ha) | ||
727 | { | ||
728 | unsigned long wtime; | ||
729 | |||
730 | /* Flush the 0x8014 AEN from the firmware as a result of | ||
731 | * Auto connect. We are basically doing get_firmware_ddb() | ||
732 | * to determine whether we need to log back in or not. | ||
733 | * Trying to do a set ddb before we have processed 0x8014 | ||
734 | * will result in another set_ddb() for the same ddb. In other | ||
735 | * words there will be stale entries in the aen_q. | ||
736 | */ | ||
737 | wtime = jiffies + (2 * HZ); | ||
738 | do { | ||
739 | if (qla4xxx_get_firmware_state(ha) == QLA_SUCCESS) | ||
740 | if (ha->firmware_state & (BIT_2 | BIT_0)) | ||
741 | return; | ||
742 | |||
743 | if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags)) | ||
744 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); | ||
745 | |||
746 | msleep(1000); | ||
747 | } while (!time_after_eq(jiffies, wtime)); | ||
748 | } | ||
749 | |||
726 | /** | 750 | /** |
727 | * qla4xxx_configure_ddbs - builds driver ddb list | 751 | * qla4xxx_build_ddb_list - builds driver ddb list |
728 | * @ha: Pointer to host adapter structure. | 752 | * @ha: Pointer to host adapter structure. |
729 | * | 753 | * |
730 | * This routine searches for all valid firmware ddb entries and builds | 754 | * This routine searches for all valid firmware ddb entries and builds |
731 | * an internal ddb list. Ddbs that are considered valid are those with | 755 | * an internal ddb list. Ddbs that are considered valid are those with |
732 | * a device state of SESSION_ACTIVE. | 756 | * a device state of SESSION_ACTIVE. |
757 | * A relogin (set_ddb) is issued for DDBs that are not online. | ||
733 | **/ | 758 | **/ |
734 | static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) | 759 | static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) |
735 | { | 760 | { |
@@ -744,6 +769,8 @@ static int qla4xxx_build_ddb_list(struct scsi_qla_host *ha) | |||
744 | uint32_t ipv6_device; | 769 | uint32_t ipv6_device; |
745 | uint32_t new_tgt; | 770 | uint32_t new_tgt; |
746 | 771 | ||
772 | qla4xxx_flush_AENS(ha); | ||
773 | |||
747 | fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), | 774 | fw_ddb_entry = dma_alloc_coherent(&ha->pdev->dev, sizeof(*fw_ddb_entry), |
748 | &fw_ddb_entry_dma, GFP_KERNEL); | 775 | &fw_ddb_entry_dma, GFP_KERNEL); |
749 | if (fw_ddb_entry == NULL) { | 776 | if (fw_ddb_entry == NULL) { |
@@ -847,144 +874,6 @@ exit_build_ddb_list_no_free: | |||
847 | return status; | 874 | return status; |
848 | } | 875 | } |
849 | 876 | ||
850 | struct qla4_relog_scan { | ||
851 | int halt_wait; | ||
852 | uint32_t conn_err; | ||
853 | uint32_t fw_ddb_index; | ||
854 | uint32_t next_fw_ddb_index; | ||
855 | uint32_t fw_ddb_device_state; | ||
856 | }; | ||
857 | |||
858 | static int qla4_test_rdy(struct scsi_qla_host *ha, struct qla4_relog_scan *rs) | ||
859 | { | ||
860 | struct ddb_entry *ddb_entry; | ||
861 | |||
862 | if (qla4_is_relogin_allowed(ha, rs->conn_err)) { | ||
863 | /* We either have a device that is in | ||
864 | * the process of relogging in or a | ||
865 | * device that is waiting to be | ||
866 | * relogged in */ | ||
867 | rs->halt_wait = 0; | ||
868 | |||
869 | ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, | ||
870 | rs->fw_ddb_index); | ||
871 | if (ddb_entry == NULL) | ||
872 | return QLA_ERROR; | ||
873 | |||
874 | if (ddb_entry->dev_scan_wait_to_start_relogin != 0 | ||
875 | && time_after_eq(jiffies, | ||
876 | ddb_entry-> | ||
877 | dev_scan_wait_to_start_relogin)) | ||
878 | { | ||
879 | ddb_entry->dev_scan_wait_to_start_relogin = 0; | ||
880 | qla4xxx_set_ddb_entry(ha, rs->fw_ddb_index, 0); | ||
881 | } | ||
882 | } | ||
883 | return QLA_SUCCESS; | ||
884 | } | ||
885 | |||
886 | static int qla4_scan_for_relogin(struct scsi_qla_host *ha, | ||
887 | struct qla4_relog_scan *rs) | ||
888 | { | ||
889 | int error; | ||
890 | |||
891 | /* scan for relogins | ||
892 | * ----------------- */ | ||
893 | for (rs->fw_ddb_index = 0; rs->fw_ddb_index < MAX_DDB_ENTRIES; | ||
894 | rs->fw_ddb_index = rs->next_fw_ddb_index) { | ||
895 | if (qla4xxx_get_fwddb_entry(ha, rs->fw_ddb_index, NULL, 0, | ||
896 | NULL, &rs->next_fw_ddb_index, | ||
897 | &rs->fw_ddb_device_state, | ||
898 | &rs->conn_err, NULL, NULL) | ||
899 | == QLA_ERROR) | ||
900 | return QLA_ERROR; | ||
901 | |||
902 | if (rs->fw_ddb_device_state == DDB_DS_LOGIN_IN_PROCESS) | ||
903 | rs->halt_wait = 0; | ||
904 | |||
905 | if (rs->fw_ddb_device_state == DDB_DS_SESSION_FAILED || | ||
906 | rs->fw_ddb_device_state == DDB_DS_NO_CONNECTION_ACTIVE) { | ||
907 | error = qla4_test_rdy(ha, rs); | ||
908 | if (error) | ||
909 | return error; | ||
910 | } | ||
911 | |||
912 | /* We know we've reached the last device when | ||
913 | * next_fw_ddb_index is 0 */ | ||
914 | if (rs->next_fw_ddb_index == 0) | ||
915 | break; | ||
916 | } | ||
917 | return QLA_SUCCESS; | ||
918 | } | ||
919 | |||
920 | /** | ||
921 | * qla4xxx_devices_ready - wait for target devices to be logged in | ||
922 | * @ha: pointer to adapter structure | ||
923 | * | ||
924 | * This routine waits up to ql4xdiscoverywait seconds | ||
925 | * F/W database during driver load time. | ||
926 | **/ | ||
927 | static int qla4xxx_devices_ready(struct scsi_qla_host *ha) | ||
928 | { | ||
929 | int error; | ||
930 | unsigned long discovery_wtime; | ||
931 | struct qla4_relog_scan rs; | ||
932 | |||
933 | discovery_wtime = jiffies + (ql4xdiscoverywait * HZ); | ||
934 | |||
935 | DEBUG(printk("Waiting (%d) for devices ...\n", ql4xdiscoverywait)); | ||
936 | do { | ||
937 | /* poll for AEN. */ | ||
938 | qla4xxx_get_firmware_state(ha); | ||
939 | if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags)) { | ||
940 | /* Set time-between-relogin timer */ | ||
941 | qla4xxx_process_aen(ha, RELOGIN_DDB_CHANGED_AENS); | ||
942 | } | ||
943 | |||
944 | /* if no relogins active or needed, halt discvery wait */ | ||
945 | rs.halt_wait = 1; | ||
946 | |||
947 | error = qla4_scan_for_relogin(ha, &rs); | ||
948 | |||
949 | if (rs.halt_wait) { | ||
950 | DEBUG2(printk("scsi%ld: %s: Delay halted. Devices " | ||
951 | "Ready.\n", ha->host_no, __func__)); | ||
952 | return QLA_SUCCESS; | ||
953 | } | ||
954 | |||
955 | msleep(2000); | ||
956 | } while (!time_after_eq(jiffies, discovery_wtime)); | ||
957 | |||
958 | DEBUG3(qla4xxx_get_conn_event_log(ha)); | ||
959 | |||
960 | return QLA_SUCCESS; | ||
961 | } | ||
962 | |||
963 | static void qla4xxx_flush_AENS(struct scsi_qla_host *ha) | ||
964 | { | ||
965 | unsigned long wtime; | ||
966 | |||
967 | /* Flush the 0x8014 AEN from the firmware as a result of | ||
968 | * Auto connect. We are basically doing get_firmware_ddb() | ||
969 | * to determine whether we need to log back in or not. | ||
970 | * Trying to do a set ddb before we have processed 0x8014 | ||
971 | * will result in another set_ddb() for the same ddb. In other | ||
972 | * words there will be stale entries in the aen_q. | ||
973 | */ | ||
974 | wtime = jiffies + (2 * HZ); | ||
975 | do { | ||
976 | if (qla4xxx_get_firmware_state(ha) == QLA_SUCCESS) | ||
977 | if (ha->firmware_state & (BIT_2 | BIT_0)) | ||
978 | return; | ||
979 | |||
980 | if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags)) | ||
981 | qla4xxx_process_aen(ha, FLUSH_DDB_CHANGED_AENS); | ||
982 | |||
983 | msleep(1000); | ||
984 | } while (!time_after_eq(jiffies, wtime)); | ||
985 | |||
986 | } | ||
987 | |||
988 | static int qla4xxx_initialize_ddb_list(struct scsi_qla_host *ha) | 877 | static int qla4xxx_initialize_ddb_list(struct scsi_qla_host *ha) |
989 | { | 878 | { |
990 | uint16_t fw_ddb_index; | 879 | uint16_t fw_ddb_index; |
@@ -996,29 +885,12 @@ static int qla4xxx_initialize_ddb_list(struct scsi_qla_host *ha) | |||
996 | 885 | ||
997 | for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES; fw_ddb_index++) | 886 | for (fw_ddb_index = 0; fw_ddb_index < MAX_DDB_ENTRIES; fw_ddb_index++) |
998 | ha->fw_ddb_index_map[fw_ddb_index] = | 887 | ha->fw_ddb_index_map[fw_ddb_index] = |
999 | (struct ddb_entry *)INVALID_ENTRY; | 888 | (struct ddb_entry *)INVALID_ENTRY; |
1000 | 889 | ||
1001 | ha->tot_ddbs = 0; | 890 | ha->tot_ddbs = 0; |
1002 | 891 | ||
1003 | qla4xxx_flush_AENS(ha); | 892 | /* Perform device discovery and build ddb list. */ |
1004 | 893 | status = qla4xxx_build_ddb_list(ha); | |
1005 | /* Wait for an AEN */ | ||
1006 | qla4xxx_devices_ready(ha); | ||
1007 | |||
1008 | /* | ||
1009 | * First perform device discovery for active | ||
1010 | * fw ddb indexes and build | ||
1011 | * ddb list. | ||
1012 | */ | ||
1013 | if ((status = qla4xxx_build_ddb_list(ha)) == QLA_ERROR) | ||
1014 | return status; | ||
1015 | |||
1016 | /* | ||
1017 | * Targets can come online after the inital discovery, so processing | ||
1018 | * the aens here will catch them. | ||
1019 | */ | ||
1020 | if (test_and_clear_bit(DPC_AEN, &ha->dpc_flags)) | ||
1021 | qla4xxx_process_aen(ha, PROCESS_ALL_AENS); | ||
1022 | 894 | ||
1023 | return status; | 895 | return status; |
1024 | } | 896 | } |
@@ -1537,7 +1409,6 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, | |||
1537 | uint32_t state, uint32_t conn_err) | 1409 | uint32_t state, uint32_t conn_err) |
1538 | { | 1410 | { |
1539 | struct ddb_entry * ddb_entry; | 1411 | struct ddb_entry * ddb_entry; |
1540 | uint32_t old_fw_ddb_device_state; | ||
1541 | 1412 | ||
1542 | /* check for out of range index */ | 1413 | /* check for out of range index */ |
1543 | if (fw_ddb_index >= MAX_DDB_ENTRIES) | 1414 | if (fw_ddb_index >= MAX_DDB_ENTRIES) |
@@ -1553,27 +1424,18 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, | |||
1553 | } | 1424 | } |
1554 | 1425 | ||
1555 | /* Device already exists in our database. */ | 1426 | /* Device already exists in our database. */ |
1556 | old_fw_ddb_device_state = ddb_entry->fw_ddb_device_state; | ||
1557 | DEBUG2(printk("scsi%ld: %s DDB - old state= 0x%x, new state=0x%x for " | 1427 | DEBUG2(printk("scsi%ld: %s DDB - old state= 0x%x, new state=0x%x for " |
1558 | "index [%d]\n", ha->host_no, __func__, | 1428 | "index [%d]\n", ha->host_no, __func__, |
1559 | ddb_entry->fw_ddb_device_state, state, fw_ddb_index)); | 1429 | ddb_entry->fw_ddb_device_state, state, fw_ddb_index)); |
1560 | if (old_fw_ddb_device_state == state && | ||
1561 | state == DDB_DS_SESSION_ACTIVE) { | ||
1562 | if (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE) { | ||
1563 | atomic_set(&ddb_entry->state, DDB_STATE_ONLINE); | ||
1564 | iscsi_unblock_session(ddb_entry->sess); | ||
1565 | } | ||
1566 | return QLA_SUCCESS; | ||
1567 | } | ||
1568 | 1430 | ||
1569 | ddb_entry->fw_ddb_device_state = state; | 1431 | ddb_entry->fw_ddb_device_state = state; |
1570 | /* Device is back online. */ | 1432 | /* Device is back online. */ |
1571 | if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) { | 1433 | if ((ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_ACTIVE) && |
1434 | (atomic_read(&ddb_entry->state) != DDB_STATE_ONLINE)) { | ||
1572 | atomic_set(&ddb_entry->state, DDB_STATE_ONLINE); | 1435 | atomic_set(&ddb_entry->state, DDB_STATE_ONLINE); |
1573 | atomic_set(&ddb_entry->relogin_retry_count, 0); | 1436 | atomic_set(&ddb_entry->relogin_retry_count, 0); |
1574 | atomic_set(&ddb_entry->relogin_timer, 0); | 1437 | atomic_set(&ddb_entry->relogin_timer, 0); |
1575 | clear_bit(DF_RELOGIN, &ddb_entry->flags); | 1438 | clear_bit(DF_RELOGIN, &ddb_entry->flags); |
1576 | clear_bit(DF_NO_RELOGIN, &ddb_entry->flags); | ||
1577 | iscsi_unblock_session(ddb_entry->sess); | 1439 | iscsi_unblock_session(ddb_entry->sess); |
1578 | iscsi_session_event(ddb_entry->sess, | 1440 | iscsi_session_event(ddb_entry->sess, |
1579 | ISCSI_KEVENT_CREATE_SESSION); | 1441 | ISCSI_KEVENT_CREATE_SESSION); |
@@ -1581,7 +1443,7 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, | |||
1581 | * Change the lun state to READY in case the lun TIMEOUT before | 1443 | * Change the lun state to READY in case the lun TIMEOUT before |
1582 | * the device came back. | 1444 | * the device came back. |
1583 | */ | 1445 | */ |
1584 | } else { | 1446 | } else if (ddb_entry->fw_ddb_device_state != DDB_DS_SESSION_ACTIVE) { |
1585 | /* Device went away, mark device missing */ | 1447 | /* Device went away, mark device missing */ |
1586 | if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE) { | 1448 | if (atomic_read(&ddb_entry->state) == DDB_STATE_ONLINE) { |
1587 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s mark missing " | 1449 | DEBUG2(ql4_printk(KERN_INFO, ha, "%s mark missing " |
@@ -1598,7 +1460,6 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index, | |||
1598 | */ | 1460 | */ |
1599 | if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_FAILED && | 1461 | if (ddb_entry->fw_ddb_device_state == DDB_DS_SESSION_FAILED && |
1600 | !test_bit(DF_RELOGIN, &ddb_entry->flags) && | 1462 | !test_bit(DF_RELOGIN, &ddb_entry->flags) && |
1601 | !test_bit(DF_NO_RELOGIN, &ddb_entry->flags) && | ||
1602 | qla4_is_relogin_allowed(ha, conn_err)) { | 1463 | qla4_is_relogin_allowed(ha, conn_err)) { |
1603 | /* | 1464 | /* |
1604 | * This triggers a relogin. After the relogin_timer | 1465 | * This triggers a relogin. After the relogin_timer |