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.c283
1 files changed, 98 insertions, 185 deletions
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c
index 745fa5555d6a..bd2f77197447 100644
--- a/drivers/scsi/libfc/fc_lport.c
+++ b/drivers/scsi/libfc/fc_lport.c
@@ -113,7 +113,7 @@ static void fc_lport_enter_ready(struct fc_lport *);
113static void fc_lport_enter_logo(struct fc_lport *); 113static void fc_lport_enter_logo(struct fc_lport *);
114 114
115static const char *fc_lport_state_names[] = { 115static const char *fc_lport_state_names[] = {
116 [LPORT_ST_NONE] = "none", 116 [LPORT_ST_DISABLED] = "disabled",
117 [LPORT_ST_FLOGI] = "FLOGI", 117 [LPORT_ST_FLOGI] = "FLOGI",
118 [LPORT_ST_DNS] = "dNS", 118 [LPORT_ST_DNS] = "dNS",
119 [LPORT_ST_RPN_ID] = "RPN_ID", 119 [LPORT_ST_RPN_ID] = "RPN_ID",
@@ -133,57 +133,44 @@ static int fc_frame_drop(struct fc_lport *lport, struct fc_frame *fp)
133/** 133/**
134 * fc_lport_rport_callback() - Event handler for rport events 134 * fc_lport_rport_callback() - Event handler for rport events
135 * @lport: The lport which is receiving the event 135 * @lport: The lport which is receiving the event
136 * @rport: The rport which the event has occured on 136 * @rdata: private remote port data
137 * @event: The event that occured 137 * @event: The event that occured
138 * 138 *
139 * Locking Note: The rport lock should not be held when calling 139 * Locking Note: The rport lock should not be held when calling
140 * this function. 140 * this function.
141 */ 141 */
142static void fc_lport_rport_callback(struct fc_lport *lport, 142static void fc_lport_rport_callback(struct fc_lport *lport,
143 struct fc_rport *rport, 143 struct fc_rport_priv *rdata,
144 enum fc_rport_event event) 144 enum fc_rport_event event)
145{ 145{
146 FC_LPORT_DBG(lport, "Received a %d event for port (%6x)\n", event, 146 FC_LPORT_DBG(lport, "Received a %d event for port (%6x)\n", event,
147 rport->port_id); 147 rdata->ids.port_id);
148 148
149 mutex_lock(&lport->lp_mutex);
149 switch (event) { 150 switch (event) {
150 case RPORT_EV_CREATED: 151 case RPORT_EV_READY:
151 if (rport->port_id == FC_FID_DIR_SERV) { 152 if (lport->state == LPORT_ST_DNS) {
152 mutex_lock(&lport->lp_mutex); 153 lport->dns_rp = rdata;
153 if (lport->state == LPORT_ST_DNS) { 154 fc_lport_enter_rpn_id(lport);
154 lport->dns_rp = rport; 155 } else {
155 fc_lport_enter_rpn_id(lport); 156 FC_LPORT_DBG(lport, "Received an READY event "
156 } else { 157 "on port (%6x) for the directory "
157 FC_LPORT_DBG(lport, "Received an CREATED event " 158 "server, but the lport is not "
158 "on port (%6x) for the directory " 159 "in the DNS state, it's in the "
159 "server, but the lport is not " 160 "%d state", rdata->ids.port_id,
160 "in the DNS state, it's in the " 161 lport->state);
161 "%d state", rport->port_id, 162 lport->tt.rport_logoff(rdata);
162 lport->state); 163 }
163 lport->tt.rport_logoff(rport);
164 }
165 mutex_unlock(&lport->lp_mutex);
166 } else
167 FC_LPORT_DBG(lport, "Received an event for port (%6x) "
168 "which is not the directory server\n",
169 rport->port_id);
170 break; 164 break;
171 case RPORT_EV_LOGO: 165 case RPORT_EV_LOGO:
172 case RPORT_EV_FAILED: 166 case RPORT_EV_FAILED:
173 case RPORT_EV_STOP: 167 case RPORT_EV_STOP:
174 if (rport->port_id == FC_FID_DIR_SERV) { 168 lport->dns_rp = NULL;
175 mutex_lock(&lport->lp_mutex);
176 lport->dns_rp = NULL;
177 mutex_unlock(&lport->lp_mutex);
178
179 } else
180 FC_LPORT_DBG(lport, "Received an event for port (%6x) "
181 "which is not the directory server\n",
182 rport->port_id);
183 break; 169 break;
184 case RPORT_EV_NONE: 170 case RPORT_EV_NONE:
185 break; 171 break;
186 } 172 }
173 mutex_unlock(&lport->lp_mutex);
187} 174}
188 175
189/** 176/**
@@ -211,20 +198,13 @@ static void fc_lport_ptp_setup(struct fc_lport *lport,
211 u32 remote_fid, u64 remote_wwpn, 198 u32 remote_fid, u64 remote_wwpn,
212 u64 remote_wwnn) 199 u64 remote_wwnn)
213{ 200{
214 struct fc_disc_port dp; 201 mutex_lock(&lport->disc.disc_mutex);
215 202 if (lport->ptp_rp)
216 dp.lp = lport;
217 dp.ids.port_id = remote_fid;
218 dp.ids.port_name = remote_wwpn;
219 dp.ids.node_name = remote_wwnn;
220 dp.ids.roles = FC_RPORT_ROLE_UNKNOWN;
221
222 if (lport->ptp_rp) {
223 lport->tt.rport_logoff(lport->ptp_rp); 203 lport->tt.rport_logoff(lport->ptp_rp);
224 lport->ptp_rp = NULL; 204 lport->ptp_rp = lport->tt.rport_create(lport, remote_fid);
225 } 205 lport->ptp_rp->ids.port_name = remote_wwpn;
226 206 lport->ptp_rp->ids.node_name = remote_wwnn;
227 lport->ptp_rp = lport->tt.rport_create(&dp); 207 mutex_unlock(&lport->disc.disc_mutex);
228 208
229 lport->tt.rport_login(lport->ptp_rp); 209 lport->tt.rport_login(lport->ptp_rp);
230 210
@@ -472,56 +452,6 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp,
472} 452}
473 453
474/** 454/**
475 * fc_lport_recv_adisc_req() - Handle received Address Discovery Request
476 * @lport: Fibre Channel local port recieving the ADISC
477 * @sp: current sequence in the ADISC exchange
478 * @fp: ADISC request frame
479 *
480 * Locking Note: The lport lock is expected to be held before calling
481 * this function.
482 */
483static void fc_lport_recv_adisc_req(struct fc_seq *sp, struct fc_frame *in_fp,
484 struct fc_lport *lport)
485{
486 struct fc_frame *fp;
487 struct fc_exch *ep = fc_seq_exch(sp);
488 struct fc_els_adisc *req, *rp;
489 struct fc_seq_els_data rjt_data;
490 size_t len;
491 u32 f_ctl;
492
493 FC_LPORT_DBG(lport, "Received ADISC request while in state %s\n",
494 fc_lport_state(lport));
495
496 req = fc_frame_payload_get(in_fp, sizeof(*req));
497 if (!req) {
498 rjt_data.fp = NULL;
499 rjt_data.reason = ELS_RJT_LOGIC;
500 rjt_data.explan = ELS_EXPL_NONE;
501 lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data);
502 } else {
503 len = sizeof(*rp);
504 fp = fc_frame_alloc(lport, len);
505 if (fp) {
506 rp = fc_frame_payload_get(fp, len);
507 memset(rp, 0, len);
508 rp->adisc_cmd = ELS_LS_ACC;
509 rp->adisc_wwpn = htonll(lport->wwpn);
510 rp->adisc_wwnn = htonll(lport->wwnn);
511 hton24(rp->adisc_port_id,
512 fc_host_port_id(lport->host));
513 sp = lport->tt.seq_start_next(sp);
514 f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ;
515 f_ctl |= FC_FC_END_SEQ | FC_FC_SEQ_INIT;
516 fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid,
517 FC_TYPE_ELS, f_ctl, 0);
518 lport->tt.seq_send(lport, sp, fp);
519 }
520 }
521 fc_frame_free(in_fp);
522}
523
524/**
525 * fc_lport_recv_logo_req() - Handle received fabric LOGO request 455 * fc_lport_recv_logo_req() - Handle received fabric LOGO request
526 * @lport: Fibre Channel local port recieving the LOGO 456 * @lport: Fibre Channel local port recieving the LOGO
527 * @sp: current sequence in the LOGO exchange 457 * @sp: current sequence in the LOGO exchange
@@ -550,7 +480,7 @@ int fc_fabric_login(struct fc_lport *lport)
550 int rc = -1; 480 int rc = -1;
551 481
552 mutex_lock(&lport->lp_mutex); 482 mutex_lock(&lport->lp_mutex);
553 if (lport->state == LPORT_ST_NONE) { 483 if (lport->state == LPORT_ST_DISABLED) {
554 fc_lport_enter_reset(lport); 484 fc_lport_enter_reset(lport);
555 rc = 0; 485 rc = 0;
556 } 486 }
@@ -637,12 +567,13 @@ EXPORT_SYMBOL(fc_fabric_logoff);
637int fc_lport_destroy(struct fc_lport *lport) 567int fc_lport_destroy(struct fc_lport *lport)
638{ 568{
639 mutex_lock(&lport->lp_mutex); 569 mutex_lock(&lport->lp_mutex);
640 lport->state = LPORT_ST_NONE; 570 lport->state = LPORT_ST_DISABLED;
641 lport->link_up = 0; 571 lport->link_up = 0;
642 lport->tt.frame_send = fc_frame_drop; 572 lport->tt.frame_send = fc_frame_drop;
643 mutex_unlock(&lport->lp_mutex); 573 mutex_unlock(&lport->lp_mutex);
644 574
645 lport->tt.fcp_abort_io(lport); 575 lport->tt.fcp_abort_io(lport);
576 lport->tt.disc_stop_final(lport);
646 lport->tt.exch_mgr_reset(lport, 0, 0); 577 lport->tt.exch_mgr_reset(lport, 0, 0);
647 return 0; 578 return 0;
648} 579}
@@ -722,7 +653,8 @@ static void fc_lport_enter_ready(struct fc_lport *lport)
722 653
723 fc_lport_state_enter(lport, LPORT_ST_READY); 654 fc_lport_state_enter(lport, LPORT_ST_READY);
724 655
725 lport->tt.disc_start(fc_lport_disc_callback, lport); 656 if (!lport->ptp_rp)
657 lport->tt.disc_start(fc_lport_disc_callback, lport);
726} 658}
727 659
728/** 660/**
@@ -808,8 +740,6 @@ static void fc_lport_recv_flogi_req(struct fc_seq *sp_in,
808 fc_lport_ptp_setup(lport, remote_fid, remote_wwpn, 740 fc_lport_ptp_setup(lport, remote_fid, remote_wwpn,
809 get_unaligned_be64(&flp->fl_wwnn)); 741 get_unaligned_be64(&flp->fl_wwnn));
810 742
811 lport->tt.disc_start(fc_lport_disc_callback, lport);
812
813out: 743out:
814 sp = fr_seq(rx_fp); 744 sp = fr_seq(rx_fp);
815 fc_frame_free(rx_fp); 745 fc_frame_free(rx_fp);
@@ -832,10 +762,6 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
832{ 762{
833 struct fc_frame_header *fh = fc_frame_header_get(fp); 763 struct fc_frame_header *fh = fc_frame_header_get(fp);
834 void (*recv) (struct fc_seq *, struct fc_frame *, struct fc_lport *); 764 void (*recv) (struct fc_seq *, struct fc_frame *, struct fc_lport *);
835 struct fc_rport *rport;
836 u32 s_id;
837 u32 d_id;
838 struct fc_seq_els_data rjt_data;
839 765
840 mutex_lock(&lport->lp_mutex); 766 mutex_lock(&lport->lp_mutex);
841 767
@@ -844,11 +770,14 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
844 * RSCN here. These don't require a session. 770 * RSCN here. These don't require a session.
845 * Even if we had a session, it might not be ready. 771 * Even if we had a session, it might not be ready.
846 */ 772 */
847 if (fh->fh_type == FC_TYPE_ELS && fh->fh_r_ctl == FC_RCTL_ELS_REQ) { 773 if (!lport->link_up)
774 fc_frame_free(fp);
775 else if (fh->fh_type == FC_TYPE_ELS &&
776 fh->fh_r_ctl == FC_RCTL_ELS_REQ) {
848 /* 777 /*
849 * Check opcode. 778 * Check opcode.
850 */ 779 */
851 recv = NULL; 780 recv = lport->tt.rport_recv_req;
852 switch (fc_frame_payload_op(fp)) { 781 switch (fc_frame_payload_op(fp)) {
853 case ELS_FLOGI: 782 case ELS_FLOGI:
854 recv = fc_lport_recv_flogi_req; 783 recv = fc_lport_recv_flogi_req;
@@ -870,34 +799,9 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp,
870 case ELS_RNID: 799 case ELS_RNID:
871 recv = fc_lport_recv_rnid_req; 800 recv = fc_lport_recv_rnid_req;
872 break; 801 break;
873 case ELS_ADISC:
874 recv = fc_lport_recv_adisc_req;
875 break;
876 } 802 }
877 803
878 if (recv) 804 recv(sp, fp, lport);
879 recv(sp, fp, lport);
880 else {
881 /*
882 * Find session.
883 * If this is a new incoming PLOGI, we won't find it.
884 */
885 s_id = ntoh24(fh->fh_s_id);
886 d_id = ntoh24(fh->fh_d_id);
887
888 rport = lport->tt.rport_lookup(lport, s_id);
889 if (rport)
890 lport->tt.rport_recv_req(sp, fp, rport);
891 else {
892 rjt_data.fp = NULL;
893 rjt_data.reason = ELS_RJT_UNAB;
894 rjt_data.explan = ELS_EXPL_NONE;
895 lport->tt.seq_els_rsp_send(sp,
896 ELS_LS_RJT,
897 &rjt_data);
898 fc_frame_free(fp);
899 }
900 }
901 } else { 805 } else {
902 FC_LPORT_DBG(lport, "dropping invalid frame (eof %x)\n", 806 FC_LPORT_DBG(lport, "dropping invalid frame (eof %x)\n",
903 fr_eof(fp)); 807 fr_eof(fp));
@@ -930,38 +834,61 @@ int fc_lport_reset(struct fc_lport *lport)
930EXPORT_SYMBOL(fc_lport_reset); 834EXPORT_SYMBOL(fc_lport_reset);
931 835
932/** 836/**
933 * fc_rport_enter_reset() - Reset the local port 837 * fc_lport_reset_locked() - Reset the local port
934 * @lport: Fibre Channel local port to be reset 838 * @lport: Fibre Channel local port to be reset
935 * 839 *
936 * Locking Note: The lport lock is expected to be held before calling 840 * Locking Note: The lport lock is expected to be held before calling
937 * this routine. 841 * this routine.
938 */ 842 */
939static void fc_lport_enter_reset(struct fc_lport *lport) 843static void fc_lport_reset_locked(struct fc_lport *lport)
940{ 844{
941 FC_LPORT_DBG(lport, "Entered RESET state from %s state\n",
942 fc_lport_state(lport));
943
944 fc_lport_state_enter(lport, LPORT_ST_RESET);
945
946 if (lport->dns_rp) 845 if (lport->dns_rp)
947 lport->tt.rport_logoff(lport->dns_rp); 846 lport->tt.rport_logoff(lport->dns_rp);
948 847
949 if (lport->ptp_rp) { 848 lport->ptp_rp = NULL;
950 lport->tt.rport_logoff(lport->ptp_rp);
951 lport->ptp_rp = NULL;
952 }
953 849
954 lport->tt.disc_stop(lport); 850 lport->tt.disc_stop(lport);
955 851
956 lport->tt.exch_mgr_reset(lport, 0, 0); 852 lport->tt.exch_mgr_reset(lport, 0, 0);
957 fc_host_fabric_name(lport->host) = 0; 853 fc_host_fabric_name(lport->host) = 0;
958 fc_host_port_id(lport->host) = 0; 854 fc_host_port_id(lport->host) = 0;
855}
959 856
857/**
858 * fc_lport_enter_reset() - Reset the local port
859 * @lport: Fibre Channel local port to be reset
860 *
861 * Locking Note: The lport lock is expected to be held before calling
862 * this routine.
863 */
864static void fc_lport_enter_reset(struct fc_lport *lport)
865{
866 FC_LPORT_DBG(lport, "Entered RESET state from %s state\n",
867 fc_lport_state(lport));
868
869 fc_lport_state_enter(lport, LPORT_ST_RESET);
870 fc_lport_reset_locked(lport);
960 if (lport->link_up) 871 if (lport->link_up)
961 fc_lport_enter_flogi(lport); 872 fc_lport_enter_flogi(lport);
962} 873}
963 874
964/** 875/**
876 * fc_lport_enter_disabled() - disable the local port
877 * @lport: Fibre Channel local port to be reset
878 *
879 * Locking Note: The lport lock is expected to be held before calling
880 * this routine.
881 */
882static void fc_lport_enter_disabled(struct fc_lport *lport)
883{
884 FC_LPORT_DBG(lport, "Entered disabled state from %s state\n",
885 fc_lport_state(lport));
886
887 fc_lport_state_enter(lport, LPORT_ST_DISABLED);
888 fc_lport_reset_locked(lport);
889}
890
891/**
965 * fc_lport_error() - Handler for any errors 892 * fc_lport_error() - Handler for any errors
966 * @lport: The fc_lport object 893 * @lport: The fc_lport object
967 * @fp: The frame pointer 894 * @fp: The frame pointer
@@ -992,7 +919,7 @@ static void fc_lport_error(struct fc_lport *lport, struct fc_frame *fp)
992 schedule_delayed_work(&lport->retry_work, delay); 919 schedule_delayed_work(&lport->retry_work, delay);
993 } else { 920 } else {
994 switch (lport->state) { 921 switch (lport->state) {
995 case LPORT_ST_NONE: 922 case LPORT_ST_DISABLED:
996 case LPORT_ST_READY: 923 case LPORT_ST_READY:
997 case LPORT_ST_RESET: 924 case LPORT_ST_RESET:
998 case LPORT_ST_RPN_ID: 925 case LPORT_ST_RPN_ID:
@@ -1026,13 +953,13 @@ static void fc_lport_rft_id_resp(struct fc_seq *sp, struct fc_frame *fp,
1026 struct fc_frame_header *fh; 953 struct fc_frame_header *fh;
1027 struct fc_ct_hdr *ct; 954 struct fc_ct_hdr *ct;
1028 955
956 FC_LPORT_DBG(lport, "Received a RFT_ID %s\n", fc_els_resp_type(fp));
957
1029 if (fp == ERR_PTR(-FC_EX_CLOSED)) 958 if (fp == ERR_PTR(-FC_EX_CLOSED))
1030 return; 959 return;
1031 960
1032 mutex_lock(&lport->lp_mutex); 961 mutex_lock(&lport->lp_mutex);
1033 962
1034 FC_LPORT_DBG(lport, "Received a RFT_ID response\n");
1035
1036 if (lport->state != LPORT_ST_RFT_ID) { 963 if (lport->state != LPORT_ST_RFT_ID) {
1037 FC_LPORT_DBG(lport, "Received a RFT_ID response, but in state " 964 FC_LPORT_DBG(lport, "Received a RFT_ID response, but in state "
1038 "%s\n", fc_lport_state(lport)); 965 "%s\n", fc_lport_state(lport));
@@ -1080,13 +1007,13 @@ static void fc_lport_rpn_id_resp(struct fc_seq *sp, struct fc_frame *fp,
1080 struct fc_frame_header *fh; 1007 struct fc_frame_header *fh;
1081 struct fc_ct_hdr *ct; 1008 struct fc_ct_hdr *ct;
1082 1009
1010 FC_LPORT_DBG(lport, "Received a RPN_ID %s\n", fc_els_resp_type(fp));
1011
1083 if (fp == ERR_PTR(-FC_EX_CLOSED)) 1012 if (fp == ERR_PTR(-FC_EX_CLOSED))
1084 return; 1013 return;
1085 1014
1086 mutex_lock(&lport->lp_mutex); 1015 mutex_lock(&lport->lp_mutex);
1087 1016
1088 FC_LPORT_DBG(lport, "Received a RPN_ID response\n");
1089
1090 if (lport->state != LPORT_ST_RPN_ID) { 1017 if (lport->state != LPORT_ST_RPN_ID) {
1091 FC_LPORT_DBG(lport, "Received a RPN_ID response, but in state " 1018 FC_LPORT_DBG(lport, "Received a RPN_ID response, but in state "
1092 "%s\n", fc_lport_state(lport)); 1019 "%s\n", fc_lport_state(lport));
@@ -1132,13 +1059,13 @@ static void fc_lport_scr_resp(struct fc_seq *sp, struct fc_frame *fp,
1132 struct fc_lport *lport = lp_arg; 1059 struct fc_lport *lport = lp_arg;
1133 u8 op; 1060 u8 op;
1134 1061
1062 FC_LPORT_DBG(lport, "Received a SCR %s\n", fc_els_resp_type(fp));
1063
1135 if (fp == ERR_PTR(-FC_EX_CLOSED)) 1064 if (fp == ERR_PTR(-FC_EX_CLOSED))
1136 return; 1065 return;
1137 1066
1138 mutex_lock(&lport->lp_mutex); 1067 mutex_lock(&lport->lp_mutex);
1139 1068
1140 FC_LPORT_DBG(lport, "Received a SCR response\n");
1141
1142 if (lport->state != LPORT_ST_SCR) { 1069 if (lport->state != LPORT_ST_SCR) {
1143 FC_LPORT_DBG(lport, "Received a SCR response, but in state " 1070 FC_LPORT_DBG(lport, "Received a SCR response, but in state "
1144 "%s\n", fc_lport_state(lport)); 1071 "%s\n", fc_lport_state(lport));
@@ -1186,7 +1113,7 @@ static void fc_lport_enter_scr(struct fc_lport *lport)
1186 return; 1113 return;
1187 } 1114 }
1188 1115
1189 if (!lport->tt.elsct_send(lport, NULL, fp, ELS_SCR, 1116 if (!lport->tt.elsct_send(lport, FC_FID_FCTRL, fp, ELS_SCR,
1190 fc_lport_scr_resp, lport, lport->e_d_tov)) 1117 fc_lport_scr_resp, lport, lport->e_d_tov))
1191 fc_lport_error(lport, fp); 1118 fc_lport_error(lport, fp);
1192} 1119}
@@ -1227,7 +1154,7 @@ static void fc_lport_enter_rft_id(struct fc_lport *lport)
1227 return; 1154 return;
1228 } 1155 }
1229 1156
1230 if (!lport->tt.elsct_send(lport, NULL, fp, FC_NS_RFT_ID, 1157 if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RFT_ID,
1231 fc_lport_rft_id_resp, 1158 fc_lport_rft_id_resp,
1232 lport, lport->e_d_tov)) 1159 lport, lport->e_d_tov))
1233 fc_lport_error(lport, fp); 1160 fc_lport_error(lport, fp);
@@ -1256,7 +1183,7 @@ static void fc_lport_enter_rpn_id(struct fc_lport *lport)
1256 return; 1183 return;
1257 } 1184 }
1258 1185
1259 if (!lport->tt.elsct_send(lport, NULL, fp, FC_NS_RPN_ID, 1186 if (!lport->tt.elsct_send(lport, FC_FID_DIR_SERV, fp, FC_NS_RPN_ID,
1260 fc_lport_rpn_id_resp, 1187 fc_lport_rpn_id_resp,
1261 lport, lport->e_d_tov)) 1188 lport, lport->e_d_tov))
1262 fc_lport_error(lport, fp); 1189 fc_lport_error(lport, fp);
@@ -1275,28 +1202,21 @@ static struct fc_rport_operations fc_lport_rport_ops = {
1275 */ 1202 */
1276static void fc_lport_enter_dns(struct fc_lport *lport) 1203static void fc_lport_enter_dns(struct fc_lport *lport)
1277{ 1204{
1278 struct fc_rport *rport; 1205 struct fc_rport_priv *rdata;
1279 struct fc_rport_libfc_priv *rdata;
1280 struct fc_disc_port dp;
1281
1282 dp.ids.port_id = FC_FID_DIR_SERV;
1283 dp.ids.port_name = -1;
1284 dp.ids.node_name = -1;
1285 dp.ids.roles = FC_RPORT_ROLE_UNKNOWN;
1286 dp.lp = lport;
1287 1206
1288 FC_LPORT_DBG(lport, "Entered DNS state from %s state\n", 1207 FC_LPORT_DBG(lport, "Entered DNS state from %s state\n",
1289 fc_lport_state(lport)); 1208 fc_lport_state(lport));
1290 1209
1291 fc_lport_state_enter(lport, LPORT_ST_DNS); 1210 fc_lport_state_enter(lport, LPORT_ST_DNS);
1292 1211
1293 rport = lport->tt.rport_create(&dp); 1212 mutex_lock(&lport->disc.disc_mutex);
1294 if (!rport) 1213 rdata = lport->tt.rport_create(lport, FC_FID_DIR_SERV);
1214 mutex_unlock(&lport->disc.disc_mutex);
1215 if (!rdata)
1295 goto err; 1216 goto err;
1296 1217
1297 rdata = rport->dd_data;
1298 rdata->ops = &fc_lport_rport_ops; 1218 rdata->ops = &fc_lport_rport_ops;
1299 lport->tt.rport_login(rport); 1219 lport->tt.rport_login(rdata);
1300 return; 1220 return;
1301 1221
1302err: 1222err:
@@ -1316,7 +1236,7 @@ static void fc_lport_timeout(struct work_struct *work)
1316 mutex_lock(&lport->lp_mutex); 1236 mutex_lock(&lport->lp_mutex);
1317 1237
1318 switch (lport->state) { 1238 switch (lport->state) {
1319 case LPORT_ST_NONE: 1239 case LPORT_ST_DISABLED:
1320 case LPORT_ST_READY: 1240 case LPORT_ST_READY:
1321 case LPORT_ST_RESET: 1241 case LPORT_ST_RESET:
1322 WARN_ON(1); 1242 WARN_ON(1);
@@ -1360,13 +1280,13 @@ static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
1360 struct fc_lport *lport = lp_arg; 1280 struct fc_lport *lport = lp_arg;
1361 u8 op; 1281 u8 op;
1362 1282
1283 FC_LPORT_DBG(lport, "Received a LOGO %s\n", fc_els_resp_type(fp));
1284
1363 if (fp == ERR_PTR(-FC_EX_CLOSED)) 1285 if (fp == ERR_PTR(-FC_EX_CLOSED))
1364 return; 1286 return;
1365 1287
1366 mutex_lock(&lport->lp_mutex); 1288 mutex_lock(&lport->lp_mutex);
1367 1289
1368 FC_LPORT_DBG(lport, "Received a LOGO response\n");
1369
1370 if (lport->state != LPORT_ST_LOGO) { 1290 if (lport->state != LPORT_ST_LOGO) {
1371 FC_LPORT_DBG(lport, "Received a LOGO response, but in state " 1291 FC_LPORT_DBG(lport, "Received a LOGO response, but in state "
1372 "%s\n", fc_lport_state(lport)); 1292 "%s\n", fc_lport_state(lport));
@@ -1382,7 +1302,7 @@ static void fc_lport_logo_resp(struct fc_seq *sp, struct fc_frame *fp,
1382 1302
1383 op = fc_frame_payload_op(fp); 1303 op = fc_frame_payload_op(fp);
1384 if (op == ELS_LS_ACC) 1304 if (op == ELS_LS_ACC)
1385 fc_lport_enter_reset(lport); 1305 fc_lport_enter_disabled(lport);
1386 else 1306 else
1387 fc_lport_error(lport, fp); 1307 fc_lport_error(lport, fp);
1388 1308
@@ -1415,8 +1335,8 @@ static void fc_lport_enter_logo(struct fc_lport *lport)
1415 return; 1335 return;
1416 } 1336 }
1417 1337
1418 if (!lport->tt.elsct_send(lport, NULL, fp, ELS_LOGO, fc_lport_logo_resp, 1338 if (!lport->tt.elsct_send(lport, FC_FID_FLOGI, fp, ELS_LOGO,
1419 lport, lport->e_d_tov)) 1339 fc_lport_logo_resp, lport, lport->e_d_tov))
1420 fc_lport_error(lport, fp); 1340 fc_lport_error(lport, fp);
1421} 1341}
1422 1342
@@ -1442,13 +1362,13 @@ static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
1442 unsigned int e_d_tov; 1362 unsigned int e_d_tov;
1443 u16 mfs; 1363 u16 mfs;
1444 1364
1365 FC_LPORT_DBG(lport, "Received a FLOGI %s\n", fc_els_resp_type(fp));
1366
1445 if (fp == ERR_PTR(-FC_EX_CLOSED)) 1367 if (fp == ERR_PTR(-FC_EX_CLOSED))
1446 return; 1368 return;
1447 1369
1448 mutex_lock(&lport->lp_mutex); 1370 mutex_lock(&lport->lp_mutex);
1449 1371
1450 FC_LPORT_DBG(lport, "Received a FLOGI response\n");
1451
1452 if (lport->state != LPORT_ST_FLOGI) { 1372 if (lport->state != LPORT_ST_FLOGI) {
1453 FC_LPORT_DBG(lport, "Received a FLOGI response, but in state " 1373 FC_LPORT_DBG(lport, "Received a FLOGI response, but in state "
1454 "%s\n", fc_lport_state(lport)); 1374 "%s\n", fc_lport_state(lport));
@@ -1501,14 +1421,6 @@ static void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
1501 fc_lport_enter_dns(lport); 1421 fc_lport_enter_dns(lport);
1502 } 1422 }
1503 } 1423 }
1504
1505 if (flp) {
1506 csp_flags = ntohs(flp->fl_csp.sp_features);
1507 if ((csp_flags & FC_SP_FT_FPORT) == 0) {
1508 lport->tt.disc_start(fc_lport_disc_callback,
1509 lport);
1510 }
1511 }
1512 } else { 1424 } else {
1513 FC_LPORT_DBG(lport, "Bad FLOGI response\n"); 1425 FC_LPORT_DBG(lport, "Bad FLOGI response\n");
1514 } 1426 }
@@ -1539,7 +1451,7 @@ void fc_lport_enter_flogi(struct fc_lport *lport)
1539 if (!fp) 1451 if (!fp)
1540 return fc_lport_error(lport, fp); 1452 return fc_lport_error(lport, fp);
1541 1453
1542 if (!lport->tt.elsct_send(lport, NULL, fp, ELS_FLOGI, 1454 if (!lport->tt.elsct_send(lport, FC_FID_FLOGI, fp, ELS_FLOGI,
1543 fc_lport_flogi_resp, lport, lport->e_d_tov)) 1455 fc_lport_flogi_resp, lport, lport->e_d_tov))
1544 fc_lport_error(lport, fp); 1456 fc_lport_error(lport, fp);
1545} 1457}
@@ -1550,7 +1462,7 @@ int fc_lport_config(struct fc_lport *lport)
1550 INIT_DELAYED_WORK(&lport->retry_work, fc_lport_timeout); 1462 INIT_DELAYED_WORK(&lport->retry_work, fc_lport_timeout);
1551 mutex_init(&lport->lp_mutex); 1463 mutex_init(&lport->lp_mutex);
1552 1464
1553 fc_lport_state_enter(lport, LPORT_ST_NONE); 1465 fc_lport_state_enter(lport, LPORT_ST_DISABLED);
1554 1466
1555 fc_lport_add_fc4_type(lport, FC_TYPE_FCP); 1467 fc_lport_add_fc4_type(lport, FC_TYPE_FCP);
1556 fc_lport_add_fc4_type(lport, FC_TYPE_CT); 1468 fc_lport_add_fc4_type(lport, FC_TYPE_CT);
@@ -1588,6 +1500,7 @@ int fc_lport_init(struct fc_lport *lport)
1588 if (lport->link_supported_speeds & FC_PORTSPEED_10GBIT) 1500 if (lport->link_supported_speeds & FC_PORTSPEED_10GBIT)
1589 fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_10GBIT; 1501 fc_host_supported_speeds(lport->host) |= FC_PORTSPEED_10GBIT;
1590 1502
1503 INIT_LIST_HEAD(&lport->ema_list);
1591 return 0; 1504 return 0;
1592} 1505}
1593EXPORT_SYMBOL(fc_lport_init); 1506EXPORT_SYMBOL(fc_lport_init);