aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libfc/fc_lport.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/libfc/fc_lport.c')
-rw-r--r--drivers/scsi/libfc/fc_lport.c205
1 files changed, 30 insertions, 175 deletions
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 28a35da1493b..f67ca680eb63 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -985,9 +985,9 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp)
985} 985}
986 986
987/** 987/**
988 * fc_lport_rft_id_resp() - Handle response to Register Fibre 988 * fc_lport_ns_resp() - Handle response to a name server
989 * Channel Types by ID (RFT_ID) request 989 * registration exchange
990 * @sp: current sequence in RFT_ID exchange 990 * @sp: current sequence in exchange
991 * @fp: response frame 991 * @fp: response frame
992 * @lp_arg: Fibre Channel host port instance 992 * @lp_arg: Fibre Channel host port instance
993 * 993 *
@@ -995,130 +995,23 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp)
995 * held, but it will lock, call an _enter_* function or fc_lport_error 995 * held, but it will lock, call an _enter_* function or fc_lport_error
996 * and then unlock the lport. 996 * and then unlock the lport.
997 */ 997 */
998static void fc_lport_rft_id_resp(struct fc_seq *sp, struct fc_frame *fp, 998static void fc_lport_ns_resp(struct fc_seq *sp, struct fc_frame *fp,
999 void *lp_arg) 999 void *lp_arg)
1000{ 1000{
1001 struct fc_lport *lport = lp_arg; 1001 struct fc_lport *lport = lp_arg;
1002 struct fc_frame_header *fh; 1002 struct fc_frame_header *fh;
1003 struct fc_ct_hdr *ct; 1003 struct fc_ct_hdr *ct;
1004 1004
1005 FC_LPORT_DBG(lport, "Received a RFT_ID %s\n", fc_els_resp_type(fp)); 1005 FC_LPORT_DBG(lport, "Received a ns %s\n", fc_els_resp_type(fp));
1006 1006
1007 if (fp == ERR_PTR(-FC_EX_CLOSED)) 1007 if (fp == ERR_PTR(-FC_EX_CLOSED))
1008 return; 1008 return;
1009 1009
1010 mutex_lock(&lport->lp_mutex); 1010 mutex_lock(&lport->lp_mutex);
1011 1011
1012 if (lport->state != LPORT_ST_RFT_ID) { 1012 if (lport->state < LPORT_ST_RNN_ID || lport->state > LPORT_ST_RFT_ID) {
1013 FC_LPORT_DBG(lport, "Received a RFT_ID response, but in state " 1013 FC_LPORT_DBG(lport, "Received a name server response, "
1014 "%s\n", fc_lport_state(lport)); 1014 "but in state %s\n", fc_lport_state(lport));
1015 if (IS_ERR(fp))
1016 goto err;
1017 goto out;
1018 }
1019
1020 if (IS_ERR(fp)) {
1021 fc_lport_error(lport, fp);
1022 goto err;
1023 }
1024
1025 fh = fc_frame_header_get(fp);
1026 ct = fc_frame_payload_get(fp, sizeof(*ct));
1027
1028 if (fh && ct && fh->fh_type == FC_TYPE_CT &&
1029 ct->ct_fs_type == FC_FST_DIR &&
1030 ct->ct_fs_subtype == FC_NS_SUBTYPE &&
1031 ntohs(ct->ct_cmd) == FC_FS_ACC)
1032 fc_lport_enter_scr(lport);
1033 else
1034 fc_lport_error(lport, fp);
1035out:
1036 fc_frame_free(fp);
1037err:
1038 mutex_unlock(&lport->lp_mutex);
1039}
1040
1041/**
1042 * fc_lport_rspn_id_resp() - Handle response to Register Symbolic Port Name
1043 * by ID (RSPN_ID) request
1044 * @sp: current sequence in RSPN_ID exchange
1045 * @fp: response frame
1046 * @lp_arg: Fibre Channel host port instance
1047 *
1048 * Locking Note: This function will be called without the lport lock
1049 * held, but it will lock, call an _enter_* function or fc_lport_error
1050 * and then unlock the lport.
1051 */
1052static void fc_lport_rspn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
1053 void *lp_arg)
1054{
1055 struct fc_lport *lport = lp_arg;
1056 struct fc_frame_header *fh;
1057 struct fc_ct_hdr *ct;
1058
1059 FC_LPORT_DBG(lport, "Received a RSPN_ID %s\n", fc_els_resp_type(fp));
1060
1061 if (fp == ERR_PTR(-FC_EX_CLOSED))
1062 return;
1063
1064 mutex_lock(&lport->lp_mutex);
1065
1066 if (lport->state != LPORT_ST_RSPN_ID) {
1067 FC_LPORT_DBG(lport, "Received a RSPN_ID response, but in state "
1068 "%s\n", fc_lport_state(lport));
1069 if (IS_ERR(fp))
1070 goto err;
1071 goto out;
1072 }
1073
1074 if (IS_ERR(fp)) {
1075 fc_lport_error(lport, fp);
1076 goto err;
1077 }
1078
1079 fh = fc_frame_header_get(fp);
1080 ct = fc_frame_payload_get(fp, sizeof(*ct));
1081 if (fh && ct && fh->fh_type == FC_TYPE_CT &&
1082 ct->ct_fs_type == FC_FST_DIR &&
1083 ct->ct_fs_subtype == FC_NS_SUBTYPE &&
1084 ntohs(ct->ct_cmd) == FC_FS_ACC)
1085 fc_lport_enter_rspn_id(lport);
1086 else
1087 fc_lport_error(lport, fp);
1088
1089out:
1090 fc_frame_free(fp);
1091err:
1092 mutex_unlock(&lport->lp_mutex);
1093}
1094/**
1095 * fc_lport_rsnn_nn_resp() - Handle response to Register Symbolic Node Name
1096 * by Node Name (RSNN_NN) request
1097 * @sp: current sequence in RSNN_NN exchange
1098 * @fp: response frame
1099 * @lp_arg: Fibre Channel host port instance
1100 *
1101 * Locking Note: This function will be called without the lport lock
1102 * held, but it will lock, call an _enter_* function or fc_lport_error
1103 * and then unlock the lport.
1104 */
1105static void fc_lport_rsnn_nn_resp(struct fc_seq *sp, struct fc_frame *fp,
1106 void *lp_arg)
1107{
1108 struct fc_lport *lport = lp_arg;
1109 struct fc_frame_header *fh;
1110 struct fc_ct_hdr *ct;
1111
1112 FC_LPORT_DBG(lport, "Received a RSNN_NN %s\n", fc_els_resp_type(fp));
1113
1114 if (fp == ERR_PTR(-FC_EX_CLOSED))
1115 return;
1116
1117 mutex_lock(&lport->lp_mutex);
1118
1119 if (lport->state != LPORT_ST_RSNN_NN) {
1120 FC_LPORT_DBG(lport, "Received a RSNN_NN response, but in state "
1121 "%s\n", fc_lport_state(lport));
1122 if (IS_ERR(fp)) 1015 if (IS_ERR(fp))
1123 goto err; 1016 goto err;
1124 goto out; 1017 goto out;
@@ -1131,68 +1024,30 @@ static void fc_lport_rsnn_nn_resp(struct fc_seq *sp, struct fc_frame *fp,
1131 1024
1132 fh = fc_frame_header_get(fp); 1025 fh = fc_frame_header_get(fp);
1133 ct = fc_frame_payload_get(fp, sizeof(*ct)); 1026 ct = fc_frame_payload_get(fp, sizeof(*ct));
1134 if (fh && ct && fh->fh_type == FC_TYPE_CT &&
1135 ct->ct_fs_type == FC_FST_DIR &&
1136 ct->ct_fs_subtype == FC_NS_SUBTYPE &&
1137 ntohs(ct->ct_cmd) == FC_FS_ACC)
1138 fc_lport_enter_rsnn_nn(lport);
1139 else
1140 fc_lport_error(lport, fp);
1141
1142out:
1143 fc_frame_free(fp);
1144err:
1145 mutex_unlock(&lport->lp_mutex);
1146}
1147 1027
1148/**
1149 * fc_lport_rnn_id_resp() - Handle response to Register Node
1150 * Name by ID (RNN_ID) request
1151 * @sp: current sequence in RNN_ID exchange
1152 * @fp: response frame
1153 * @lp_arg: Fibre Channel host port instance
1154 *
1155 * Locking Note: This function will be called without the lport lock
1156 * held, but it will lock, call an _enter_* function or fc_lport_error
1157 * and then unlock the lport.
1158 */
1159static void fc_lport_rnn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
1160 void *lp_arg)
1161{
1162 struct fc_lport *lport = lp_arg;
1163 struct fc_frame_header *fh;
1164 struct fc_ct_hdr *ct;
1165
1166 FC_LPORT_DBG(lport, "Received a RNN_ID %s\n", fc_els_resp_type(fp));
1167
1168 if (fp == ERR_PTR(-FC_EX_CLOSED))
1169 return;
1170
1171 mutex_lock(&lport->lp_mutex);
1172
1173 if (lport->state != LPORT_ST_RNN_ID) {
1174 FC_LPORT_DBG(lport, "Received a RNN_ID response, but in state "
1175 "%s\n", fc_lport_state(lport));
1176 if (IS_ERR(fp))
1177 goto err;
1178 goto out;
1179 }
1180
1181 if (IS_ERR(fp)) {
1182 fc_lport_error(lport, fp);
1183 goto err;
1184 }
1185
1186 fh = fc_frame_header_get(fp);
1187 ct = fc_frame_payload_get(fp, sizeof(*ct));
1188 if (fh && ct && fh->fh_type == FC_TYPE_CT && 1028 if (fh && ct && fh->fh_type == FC_TYPE_CT &&
1189 ct->ct_fs_type == FC_FST_DIR && 1029 ct->ct_fs_type == FC_FST_DIR &&
1190 ct->ct_fs_subtype == FC_NS_SUBTYPE && 1030 ct->ct_fs_subtype == FC_NS_SUBTYPE &&
1191 ntohs(ct->ct_cmd) == FC_FS_ACC) 1031 ntohs(ct->ct_cmd) == FC_FS_ACC)
1192 fc_lport_enter_rft_id(lport); 1032 switch (lport->state) {
1033 case LPORT_ST_RNN_ID:
1034 fc_lport_enter_rsnn_nn(lport);
1035 break;
1036 case LPORT_ST_RSNN_NN:
1037 fc_lport_enter_rspn_id(lport);
1038 break;
1039 case LPORT_ST_RSPN_ID:
1040 fc_lport_enter_rft_id(lport);
1041 break;
1042 case LPORT_ST_RFT_ID:
1043 fc_lport_enter_scr(lport);
1044 break;
1045 default:
1046 /* should have already been caught by state checks */
1047 break;
1048 }
1193 else 1049 else
1194 fc_lport_error(lport, fp); 1050 fc_lport_error(lport, fp);
1195
1196out: 1051out:
1197 fc_frame_free(fp); 1052 fc_frame_free(fp);
1198err: 1053err:
@@ -1311,7 +1166,7 @@ static void fc_lport_enter_rft_id(struct fc_lport *lport)
1311 } 1166 }
1312 1167
1313 if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RFT_ID, 1168 if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RFT_ID,
1314 fc_lport_rft_id_resp, 1169 fc_lport_ns_resp,
1315 lport, lport->e_d_tov)) 1170 lport, lport->e_d_tov))
1316 fc_lport_error(lport, fp); 1171 fc_lport_error(lport, fp);
1317} 1172}
@@ -1342,7 +1197,7 @@ static void fc_lport_enter_rspn_id(struct fc_lport *lport)
1342 } 1197 }
1343 1198
1344 if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RSPN_ID, 1199 if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RSPN_ID,
1345 fc_lport_rspn_id_resp, 1200 fc_lport_ns_resp,
1346 lport, lport->e_d_tov)) 1201 lport, lport->e_d_tov))
1347 fc_lport_error(lport, fp); 1202 fc_lport_error(lport, fp);
1348} 1203}
@@ -1373,7 +1228,7 @@ static void fc_lport_enter_rsnn_nn(struct fc_lport *lport)
1373 } 1228 }
1374 1229
1375 if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RSNN_NN, 1230 if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RSNN_NN,
1376 fc_lport_rsnn_nn_resp, 1231 fc_lport_ns_resp,
1377 lport, lport->e_d_tov)) 1232 lport, lport->e_d_tov))
1378 fc_lport_error(lport, fp); 1233 fc_lport_error(lport, fp);
1379} 1234}
@@ -1402,7 +1257,7 @@ static void fc_lport_enter_rnn_id(struct fc_lport *lport)
1402 } 1257 }
1403 1258
1404 if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RNN_ID, 1259 if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RNN_ID,
1405 fc_lport_rnn_id_resp, 1260 fc_lport_ns_resp,
1406 lport, lport->e_d_tov)) 1261 lport, lport->e_d_tov))
1407 fc_lport_error(lport, fp); 1262 fc_lport_error(lport, fp);
1408} 1263}