aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/qla4xxx/ql4_init.c
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2011-12-01 22:38:41 -0500
committerJames Bottomley <JBottomley@Parallels.com>2011-12-14 06:40:43 -0500
commit13483730a13bef372894aefcf73760f5c6c297be (patch)
treeb65e573e43e791b91e32a16cb67653354f0d33d0 /drivers/scsi/qla4xxx/ql4_init.c
parent44f747fff6e9f027a4866c1a6864e26ae7c510c8 (diff)
[SCSI] qla4xxx: fix flash/ddb support
With open-iscsi support, target entries persisted in the FLASH were not login. Added support in the qla4xxx driver to do the login on probe time to the target entries saved in the FLASH by user. With this changes upgrade to the new kernel with open-iscsi support in qla4xxx will ensure users original target entries login on driver load Signed-off-by: Manish Rangankar <manish.rangankar@qlogic.com> Signed-off-by: Ravi Anand <ravi.anand@qlogic.com> Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
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 3075fbaef553..0497873a1dd2 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