diff options
Diffstat (limited to 'drivers/scsi/libfc/fc_lport.c')
-rw-r--r-- | drivers/scsi/libfc/fc_lport.c | 74 |
1 files changed, 45 insertions, 29 deletions
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index b8178ef398d7..e0c247724d2b 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c | |||
@@ -618,6 +618,11 @@ int fc_fabric_logoff(struct fc_lport *lport) | |||
618 | { | 618 | { |
619 | lport->tt.disc_stop_final(lport); | 619 | lport->tt.disc_stop_final(lport); |
620 | mutex_lock(&lport->lp_mutex); | 620 | mutex_lock(&lport->lp_mutex); |
621 | if (lport->dns_rp) | ||
622 | lport->tt.rport_logoff(lport->dns_rp); | ||
623 | mutex_unlock(&lport->lp_mutex); | ||
624 | lport->tt.rport_flush_queue(); | ||
625 | mutex_lock(&lport->lp_mutex); | ||
621 | fc_lport_enter_logo(lport); | 626 | fc_lport_enter_logo(lport); |
622 | mutex_unlock(&lport->lp_mutex); | 627 | mutex_unlock(&lport->lp_mutex); |
623 | cancel_delayed_work_sync(&lport->retry_work); | 628 | cancel_delayed_work_sync(&lport->retry_work); |
@@ -639,7 +644,12 @@ EXPORT_SYMBOL(fc_fabric_logoff); | |||
639 | */ | 644 | */ |
640 | int fc_lport_destroy(struct fc_lport *lport) | 645 | int fc_lport_destroy(struct fc_lport *lport) |
641 | { | 646 | { |
647 | mutex_lock(&lport->lp_mutex); | ||
648 | lport->state = LPORT_ST_NONE; | ||
649 | lport->link_up = 0; | ||
642 | lport->tt.frame_send = fc_frame_drop; | 650 | lport->tt.frame_send = fc_frame_drop; |
651 | mutex_unlock(&lport->lp_mutex); | ||
652 | |||
643 | lport->tt.fcp_abort_io(lport); | 653 | lport->tt.fcp_abort_io(lport); |
644 | lport->tt.exch_mgr_reset(lport, 0, 0); | 654 | lport->tt.exch_mgr_reset(lport, 0, 0); |
645 | return 0; | 655 | return 0; |
@@ -1032,17 +1042,19 @@ static void fc_lport_rft_id_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
1032 | 1042 | ||
1033 | FC_DEBUG_LPORT("Received a RFT_ID response\n"); | 1043 | FC_DEBUG_LPORT("Received a RFT_ID response\n"); |
1034 | 1044 | ||
1035 | if (IS_ERR(fp)) { | ||
1036 | fc_lport_error(lport, fp); | ||
1037 | goto err; | ||
1038 | } | ||
1039 | |||
1040 | if (lport->state != LPORT_ST_RFT_ID) { | 1045 | if (lport->state != LPORT_ST_RFT_ID) { |
1041 | FC_DBG("Received a RFT_ID response, but in state %s\n", | 1046 | FC_DBG("Received a RFT_ID response, but in state %s\n", |
1042 | fc_lport_state(lport)); | 1047 | fc_lport_state(lport)); |
1048 | if (IS_ERR(fp)) | ||
1049 | goto err; | ||
1043 | goto out; | 1050 | goto out; |
1044 | } | 1051 | } |
1045 | 1052 | ||
1053 | if (IS_ERR(fp)) { | ||
1054 | fc_lport_error(lport, fp); | ||
1055 | goto err; | ||
1056 | } | ||
1057 | |||
1046 | fh = fc_frame_header_get(fp); | 1058 | fh = fc_frame_header_get(fp); |
1047 | ct = fc_frame_payload_get(fp, sizeof(*ct)); | 1059 | ct = fc_frame_payload_get(fp, sizeof(*ct)); |
1048 | 1060 | ||
@@ -1084,17 +1096,19 @@ static void fc_lport_rpn_id_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
1084 | 1096 | ||
1085 | FC_DEBUG_LPORT("Received a RPN_ID response\n"); | 1097 | FC_DEBUG_LPORT("Received a RPN_ID response\n"); |
1086 | 1098 | ||
1087 | if (IS_ERR(fp)) { | ||
1088 | fc_lport_error(lport, fp); | ||
1089 | goto err; | ||
1090 | } | ||
1091 | |||
1092 | if (lport->state != LPORT_ST_RPN_ID) { | 1099 | if (lport->state != LPORT_ST_RPN_ID) { |
1093 | FC_DBG("Received a RPN_ID response, but in state %s\n", | 1100 | FC_DBG("Received a RPN_ID response, but in state %s\n", |
1094 | fc_lport_state(lport)); | 1101 | fc_lport_state(lport)); |
1102 | if (IS_ERR(fp)) | ||
1103 | goto err; | ||
1095 | goto out; | 1104 | goto out; |
1096 | } | 1105 | } |
1097 | 1106 | ||
1107 | if (IS_ERR(fp)) { | ||
1108 | fc_lport_error(lport, fp); | ||
1109 | goto err; | ||
1110 | } | ||
1111 | |||
1098 | fh = fc_frame_header_get(fp); | 1112 | fh = fc_frame_header_get(fp); |
1099 | ct = fc_frame_payload_get(fp, sizeof(*ct)); | 1113 | ct = fc_frame_payload_get(fp, sizeof(*ct)); |
1100 | if (fh && ct && fh->fh_type == FC_TYPE_CT && | 1114 | if (fh && ct && fh->fh_type == FC_TYPE_CT && |
@@ -1134,17 +1148,19 @@ static void fc_lport_scr_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
1134 | 1148 | ||
1135 | FC_DEBUG_LPORT("Received a SCR response\n"); | 1149 | FC_DEBUG_LPORT("Received a SCR response\n"); |
1136 | 1150 | ||
1137 | if (IS_ERR(fp)) { | ||
1138 | fc_lport_error(lport, fp); | ||
1139 | goto err; | ||
1140 | } | ||
1141 | |||
1142 | if (lport->state != LPORT_ST_SCR) { | 1151 | if (lport->state != LPORT_ST_SCR) { |
1143 | FC_DBG("Received a SCR response, but in state %s\n", | 1152 | FC_DBG("Received a SCR response, but in state %s\n", |
1144 | fc_lport_state(lport)); | 1153 | fc_lport_state(lport)); |
1154 | if (IS_ERR(fp)) | ||
1155 | goto err; | ||
1145 | goto out; | 1156 | goto out; |
1146 | } | 1157 | } |
1147 | 1158 | ||
1159 | if (IS_ERR(fp)) { | ||
1160 | fc_lport_error(lport, fp); | ||
1161 | goto err; | ||
1162 | } | ||
1163 | |||
1148 | op = fc_frame_payload_op(fp); | 1164 | op = fc_frame_payload_op(fp); |
1149 | if (op == ELS_LS_ACC) | 1165 | if (op == ELS_LS_ACC) |
1150 | fc_lport_enter_ready(lport); | 1166 | fc_lport_enter_ready(lport); |
@@ -1360,17 +1376,19 @@ static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
1360 | 1376 | ||
1361 | FC_DEBUG_LPORT("Received a LOGO response\n"); | 1377 | FC_DEBUG_LPORT("Received a LOGO response\n"); |
1362 | 1378 | ||
1363 | if (IS_ERR(fp)) { | ||
1364 | fc_lport_error(lport, fp); | ||
1365 | goto err; | ||
1366 | } | ||
1367 | |||
1368 | if (lport->state != LPORT_ST_LOGO) { | 1379 | if (lport->state != LPORT_ST_LOGO) { |
1369 | FC_DBG("Received a LOGO response, but in state %s\n", | 1380 | FC_DBG("Received a LOGO response, but in state %s\n", |
1370 | fc_lport_state(lport)); | 1381 | fc_lport_state(lport)); |
1382 | if (IS_ERR(fp)) | ||
1383 | goto err; | ||
1371 | goto out; | 1384 | goto out; |
1372 | } | 1385 | } |
1373 | 1386 | ||
1387 | if (IS_ERR(fp)) { | ||
1388 | fc_lport_error(lport, fp); | ||
1389 | goto err; | ||
1390 | } | ||
1391 | |||
1374 | op = fc_frame_payload_op(fp); | 1392 | op = fc_frame_payload_op(fp); |
1375 | if (op == ELS_LS_ACC) | 1393 | if (op == ELS_LS_ACC) |
1376 | fc_lport_enter_reset(lport); | 1394 | fc_lport_enter_reset(lport); |
@@ -1400,10 +1418,6 @@ static void fc_lport_enter_logo(struct fc_lport *lport) | |||
1400 | 1418 | ||
1401 | fc_lport_state_enter(lport, LPORT_ST_LOGO); | 1419 | fc_lport_state_enter(lport, LPORT_ST_LOGO); |
1402 | 1420 | ||
1403 | /* DNS session should be closed so we can release it here */ | ||
1404 | if (lport->dns_rp) | ||
1405 | lport->tt.rport_logoff(lport->dns_rp); | ||
1406 | |||
1407 | fp = fc_frame_alloc(lport, sizeof(*logo)); | 1421 | fp = fc_frame_alloc(lport, sizeof(*logo)); |
1408 | if (!fp) { | 1422 | if (!fp) { |
1409 | fc_lport_error(lport, fp); | 1423 | fc_lport_error(lport, fp); |
@@ -1444,17 +1458,19 @@ static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
1444 | 1458 | ||
1445 | FC_DEBUG_LPORT("Received a FLOGI response\n"); | 1459 | FC_DEBUG_LPORT("Received a FLOGI response\n"); |
1446 | 1460 | ||
1447 | if (IS_ERR(fp)) { | ||
1448 | fc_lport_error(lport, fp); | ||
1449 | goto err; | ||
1450 | } | ||
1451 | |||
1452 | if (lport->state != LPORT_ST_FLOGI) { | 1461 | if (lport->state != LPORT_ST_FLOGI) { |
1453 | FC_DBG("Received a FLOGI response, but in state %s\n", | 1462 | FC_DBG("Received a FLOGI response, but in state %s\n", |
1454 | fc_lport_state(lport)); | 1463 | fc_lport_state(lport)); |
1464 | if (IS_ERR(fp)) | ||
1465 | goto err; | ||
1455 | goto out; | 1466 | goto out; |
1456 | } | 1467 | } |
1457 | 1468 | ||
1469 | if (IS_ERR(fp)) { | ||
1470 | fc_lport_error(lport, fp); | ||
1471 | goto err; | ||
1472 | } | ||
1473 | |||
1458 | fh = fc_frame_header_get(fp); | 1474 | fh = fc_frame_header_get(fp); |
1459 | did = ntoh24(fh->fh_d_id); | 1475 | did = ntoh24(fh->fh_d_id); |
1460 | if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) { | 1476 | if (fc_frame_payload_op(fp) == ELS_LS_ACC && did != 0) { |