aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla4xxx/ql4_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/qla4xxx/ql4_init.c')
-rw-r--r--drivers/scsi/qla4xxx/ql4_init.c239
1 files changed, 200 insertions, 39 deletions
diff --git a/drivers/scsi/qla4xxx/ql4_init.c b/drivers/scsi/qla4xxx/ql4_init.c
index 3075fbaef55..0497873a1dd 100644
--- a/drivers/scsi/qla4xxx/ql4_init.c
+++ b/drivers/scsi/qla4xxx/ql4_init.c
@@ -773,14 +773,14 @@ int qla4xxx_start_firmware(struct scsi_qla_host *ha)
773 * be freed so that when login happens from user space there are free DDB 773 * be freed so that when login happens from user space there are free DDB
774 * indices available. 774 * indices available.
775 **/ 775 **/
776static void qla4xxx_free_ddb_index(struct scsi_qla_host *ha) 776void qla4xxx_free_ddb_index(struct scsi_qla_host *ha)
777{ 777{
778 int max_ddbs; 778 int max_ddbs;
779 int ret; 779 int ret;
780 uint32_t idx = 0, next_idx = 0; 780 uint32_t idx = 0, next_idx = 0;
781 uint32_t state = 0, conn_err = 0; 781 uint32_t state = 0, conn_err = 0;
782 782
783 max_ddbs = is_qla40XX(ha) ? MAX_PRST_DEV_DB_ENTRIES : 783 max_ddbs = is_qla40XX(ha) ? MAX_DEV_DB_ENTRIES_40XX :
784 MAX_DEV_DB_ENTRIES; 784 MAX_DEV_DB_ENTRIES;
785 785
786 for (idx = 0; idx < max_ddbs; idx = next_idx) { 786 for (idx = 0; idx < max_ddbs; idx = next_idx) {
@@ -804,7 +804,6 @@ static void qla4xxx_free_ddb_index(struct scsi_qla_host *ha)
804 } 804 }
805} 805}
806 806
807
808/** 807/**
809 * qla4xxx_initialize_adapter - initiailizes hba 808 * qla4xxx_initialize_adapter - initiailizes hba
810 * @ha: Pointer to host adapter structure. 809 * @ha: Pointer to host adapter structure.
@@ -812,7 +811,7 @@ static void qla4xxx_free_ddb_index(struct scsi_qla_host *ha)
812 * This routine parforms all of the steps necessary to initialize the adapter. 811 * This routine parforms all of the steps necessary to initialize the adapter.
813 * 812 *
814 **/ 813 **/
815int qla4xxx_initialize_adapter(struct scsi_qla_host *ha) 814int qla4xxx_initialize_adapter(struct scsi_qla_host *ha, int is_reset)
816{ 815{
817 int status = QLA_ERROR; 816 int status = QLA_ERROR;
818 817
@@ -840,7 +839,8 @@ int qla4xxx_initialize_adapter(struct scsi_qla_host *ha)
840 if (status == QLA_ERROR) 839 if (status == QLA_ERROR)
841 goto exit_init_hba; 840 goto exit_init_hba;
842 841
843 qla4xxx_free_ddb_index(ha); 842 if (is_reset == RESET_ADAPTER)
843 qla4xxx_build_ddb_list(ha, is_reset);
844 844
845 set_bit(AF_ONLINE, &ha->flags); 845 set_bit(AF_ONLINE, &ha->flags);
846exit_init_hba: 846exit_init_hba:
@@ -855,38 +855,12 @@ exit_init_hba:
855 return status; 855 return status;
856} 856}
857 857
858/** 858int qla4xxx_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
859 * qla4xxx_process_ddb_changed - process ddb state change 859 struct ddb_entry *ddb_entry, uint32_t state)
860 * @ha - Pointer to host adapter structure.
861 * @fw_ddb_index - Firmware's device database index
862 * @state - Device state
863 *
864 * This routine processes a Decive Database Changed AEN Event.
865 **/
866int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
867 uint32_t state, uint32_t conn_err)
868{ 860{
869 struct ddb_entry * ddb_entry;
870 uint32_t old_fw_ddb_device_state; 861 uint32_t old_fw_ddb_device_state;
871 int status = QLA_ERROR; 862 int status = QLA_ERROR;
872 863
873 /* check for out of range index */
874 if (fw_ddb_index >= MAX_DDB_ENTRIES)
875 goto exit_ddb_event;
876
877 /* Get the corresponging ddb entry */
878 ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, fw_ddb_index);
879 /* Device does not currently exist in our database. */
880 if (ddb_entry == NULL) {
881 ql4_printk(KERN_ERR, ha, "%s: No ddb_entry at FW index [%d]\n",
882 __func__, fw_ddb_index);
883
884 if (state == DDB_DS_NO_CONNECTION_ACTIVE)
885 clear_bit(fw_ddb_index, ha->ddb_idx_map);
886
887 goto exit_ddb_event;
888 }
889
890 old_fw_ddb_device_state = ddb_entry->fw_ddb_device_state; 864 old_fw_ddb_device_state = ddb_entry->fw_ddb_device_state;
891 DEBUG2(ql4_printk(KERN_INFO, ha, 865 DEBUG2(ql4_printk(KERN_INFO, ha,
892 "%s: DDB - old state = 0x%x, new state = 0x%x for " 866 "%s: DDB - old state = 0x%x, new state = 0x%x for "
@@ -900,9 +874,7 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
900 switch (state) { 874 switch (state) {
901 case DDB_DS_SESSION_ACTIVE: 875 case DDB_DS_SESSION_ACTIVE:
902 case DDB_DS_DISCOVERY: 876 case DDB_DS_DISCOVERY:
903 iscsi_conn_start(ddb_entry->conn); 877 ddb_entry->unblock_sess(ddb_entry->sess);
904 iscsi_conn_login_event(ddb_entry->conn,
905 ISCSI_CONN_STATE_LOGGED_IN);
906 qla4xxx_update_session_conn_param(ha, ddb_entry); 878 qla4xxx_update_session_conn_param(ha, ddb_entry);
907 status = QLA_SUCCESS; 879 status = QLA_SUCCESS;
908 break; 880 break;
@@ -936,9 +908,7 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
936 switch (state) { 908 switch (state) {
937 case DDB_DS_SESSION_ACTIVE: 909 case DDB_DS_SESSION_ACTIVE:
938 case DDB_DS_DISCOVERY: 910 case DDB_DS_DISCOVERY:
939 iscsi_conn_start(ddb_entry->conn); 911 ddb_entry->unblock_sess(ddb_entry->sess);
940 iscsi_conn_login_event(ddb_entry->conn,
941 ISCSI_CONN_STATE_LOGGED_IN);
942 qla4xxx_update_session_conn_param(ha, ddb_entry); 912 qla4xxx_update_session_conn_param(ha, ddb_entry);
943 status = QLA_SUCCESS; 913 status = QLA_SUCCESS;
944 break; 914 break;
@@ -954,7 +924,198 @@ int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
954 __func__)); 924 __func__));
955 break; 925 break;
956 } 926 }
927 return status;
928}
929
930void qla4xxx_arm_relogin_timer(struct ddb_entry *ddb_entry)
931{
932 /*
933 * This triggers a relogin. After the relogin_timer
934 * expires, the relogin gets scheduled. We must wait a
935 * minimum amount of time since receiving an 0x8014 AEN
936 * with failed device_state or a logout response before
937 * we can issue another relogin.
938 *
939 * Firmware pads this timeout: (time2wait +1).
940 * Driver retry to login should be longer than F/W.
941 * Otherwise F/W will fail
942 * set_ddb() mbx cmd with 0x4005 since it still
943 * counting down its time2wait.
944 */
945 atomic_set(&ddb_entry->relogin_timer, 0);
946 atomic_set(&ddb_entry->retry_relogin_timer,
947 ddb_entry->default_time2wait + 4);
948
949}
950
951int qla4xxx_flash_ddb_change(struct scsi_qla_host *ha, uint32_t fw_ddb_index,
952 struct ddb_entry *ddb_entry, uint32_t state)
953{
954 uint32_t old_fw_ddb_device_state;
955 int status = QLA_ERROR;
956
957 old_fw_ddb_device_state = ddb_entry->fw_ddb_device_state;
958 DEBUG2(ql4_printk(KERN_INFO, ha,
959 "%s: DDB - old state = 0x%x, new state = 0x%x for "
960 "index [%d]\n", __func__,
961 ddb_entry->fw_ddb_device_state, state, fw_ddb_index));
962
963 ddb_entry->fw_ddb_device_state = state;
964
965 switch (old_fw_ddb_device_state) {
966 case DDB_DS_LOGIN_IN_PROCESS:
967 case DDB_DS_NO_CONNECTION_ACTIVE:
968 switch (state) {
969 case DDB_DS_SESSION_ACTIVE:
970 ddb_entry->unblock_sess(ddb_entry->sess);
971 qla4xxx_update_session_conn_fwddb_param(ha, ddb_entry);
972 status = QLA_SUCCESS;
973 break;
974 case DDB_DS_SESSION_FAILED:
975 iscsi_block_session(ddb_entry->sess);
976 if (!test_bit(DF_RELOGIN, &ddb_entry->flags))
977 qla4xxx_arm_relogin_timer(ddb_entry);
978 status = QLA_SUCCESS;
979 break;
980 }
981 break;
982 case DDB_DS_SESSION_ACTIVE:
983 switch (state) {
984 case DDB_DS_SESSION_FAILED:
985 iscsi_block_session(ddb_entry->sess);
986 if (!test_bit(DF_RELOGIN, &ddb_entry->flags))
987 qla4xxx_arm_relogin_timer(ddb_entry);
988 status = QLA_SUCCESS;
989 break;
990 }
991 break;
992 case DDB_DS_SESSION_FAILED:
993 switch (state) {
994 case DDB_DS_SESSION_ACTIVE:
995 ddb_entry->unblock_sess(ddb_entry->sess);
996 qla4xxx_update_session_conn_fwddb_param(ha, ddb_entry);
997 status = QLA_SUCCESS;
998 break;
999 case DDB_DS_SESSION_FAILED:
1000 if (!test_bit(DF_RELOGIN, &ddb_entry->flags))
1001 qla4xxx_arm_relogin_timer(ddb_entry);
1002 status = QLA_SUCCESS;
1003 break;
1004 }
1005 break;
1006 default:
1007 DEBUG2(ql4_printk(KERN_INFO, ha, "%s: Unknown Event\n",
1008 __func__));
1009 break;
1010 }
1011 return status;
1012}
1013
1014/**
1015 * qla4xxx_process_ddb_changed - process ddb state change
1016 * @ha - Pointer to host adapter structure.
1017 * @fw_ddb_index - Firmware's device database index
1018 * @state - Device state
1019 *
1020 * This routine processes a Decive Database Changed AEN Event.
1021 **/
1022int qla4xxx_process_ddb_changed(struct scsi_qla_host *ha,
1023 uint32_t fw_ddb_index,
1024 uint32_t state, uint32_t conn_err)
1025{
1026 struct ddb_entry *ddb_entry;
1027 int status = QLA_ERROR;
1028
1029 /* check for out of range index */
1030 if (fw_ddb_index >= MAX_DDB_ENTRIES)
1031 goto exit_ddb_event;
1032
1033 /* Get the corresponging ddb entry */
1034 ddb_entry = qla4xxx_lookup_ddb_by_fw_index(ha, fw_ddb_index);
1035 /* Device does not currently exist in our database. */
1036 if (ddb_entry == NULL) {
1037 ql4_printk(KERN_ERR, ha, "%s: No ddb_entry at FW index [%d]\n",
1038 __func__, fw_ddb_index);
1039
1040 if (state == DDB_DS_NO_CONNECTION_ACTIVE)
1041 clear_bit(fw_ddb_index, ha->ddb_idx_map);
1042
1043 goto exit_ddb_event;
1044 }
1045
1046 ddb_entry->ddb_change(ha, fw_ddb_index, ddb_entry, state);
957 1047
958exit_ddb_event: 1048exit_ddb_event:
959 return status; 1049 return status;
960} 1050}
1051
1052/**
1053 * qla4xxx_login_flash_ddb - Login to target (DDB)
1054 * @cls_session: Pointer to the session to login
1055 *
1056 * This routine logins to the target.
1057 * Issues setddb and conn open mbx
1058 **/
1059void qla4xxx_login_flash_ddb(struct iscsi_cls_session *cls_session)
1060{
1061 struct iscsi_session *sess;
1062 struct ddb_entry *ddb_entry;
1063 struct scsi_qla_host *ha;
1064 struct dev_db_entry *fw_ddb_entry = NULL;
1065 dma_addr_t fw_ddb_dma;
1066 uint32_t mbx_sts = 0;
1067 int ret;
1068
1069 sess = cls_session->dd_data;
1070 ddb_entry = sess->dd_data;
1071 ha = ddb_entry->ha;
1072
1073 if (!test_bit(AF_LINK_UP, &ha->flags))
1074 return;
1075
1076 if (ddb_entry->ddb_type != FLASH_DDB) {
1077 DEBUG2(ql4_printk(KERN_INFO, ha,
1078 "Skipping login to non FLASH DB"));
1079 goto exit_login;
1080 }
1081
1082 fw_ddb_entry = dma_pool_alloc(ha->fw_ddb_dma_pool, GFP_KERNEL,
1083 &fw_ddb_dma);
1084 if (fw_ddb_entry == NULL) {
1085 DEBUG2(ql4_printk(KERN_ERR, ha, "Out of memory\n"));
1086 goto exit_login;
1087 }
1088
1089 if (ddb_entry->fw_ddb_index == INVALID_ENTRY) {
1090 ret = qla4xxx_get_ddb_index(ha, &ddb_entry->fw_ddb_index);
1091 if (ret == QLA_ERROR)
1092 goto exit_login;
1093
1094 ha->fw_ddb_index_map[ddb_entry->fw_ddb_index] = ddb_entry;
1095 ha->tot_ddbs++;
1096 }
1097
1098 memcpy(fw_ddb_entry, &ddb_entry->fw_ddb_entry,
1099 sizeof(struct dev_db_entry));
1100 ddb_entry->sess->target_id = ddb_entry->fw_ddb_index;
1101
1102 ret = qla4xxx_set_ddb_entry(ha, ddb_entry->fw_ddb_index,
1103 fw_ddb_dma, &mbx_sts);
1104 if (ret == QLA_ERROR) {
1105 DEBUG2(ql4_printk(KERN_ERR, ha, "Set DDB failed\n"));
1106 goto exit_login;
1107 }
1108
1109 ddb_entry->fw_ddb_device_state = DDB_DS_LOGIN_IN_PROCESS;
1110 ret = qla4xxx_conn_open(ha, ddb_entry->fw_ddb_index);
1111 if (ret == QLA_ERROR) {
1112 ql4_printk(KERN_ERR, ha, "%s: Login failed: %s\n", __func__,
1113 sess->targetname);
1114 goto exit_login;
1115 }
1116
1117exit_login:
1118 if (fw_ddb_entry)
1119 dma_pool_free(ha->fw_ddb_dma_pool, fw_ddb_entry, fw_ddb_dma);
1120}
1121