diff options
Diffstat (limited to 'drivers/scsi/libfc/fc_lport.c')
-rw-r--r-- | drivers/scsi/libfc/fc_lport.c | 283 |
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 *); | |||
113 | static void fc_lport_enter_logo(struct fc_lport *); | 113 | static void fc_lport_enter_logo(struct fc_lport *); |
114 | 114 | ||
115 | static const char *fc_lport_state_names[] = { | 115 | static 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 | */ |
142 | static void fc_lport_rport_callback(struct fc_lport *lport, | 142 | static 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 | */ | ||
483 | static 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); | |||
637 | int fc_lport_destroy(struct fc_lport *lport) | 567 | int 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 | |||
813 | out: | 743 | out: |
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) | |||
930 | EXPORT_SYMBOL(fc_lport_reset); | 834 | EXPORT_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 | */ |
939 | static void fc_lport_enter_reset(struct fc_lport *lport) | 843 | static 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 | */ | ||
864 | static 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 | */ | ||
882 | static 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 | */ |
1276 | static void fc_lport_enter_dns(struct fc_lport *lport) | 1203 | static 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 | ||
1302 | err: | 1222 | err: |
@@ -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 | } |
1593 | EXPORT_SYMBOL(fc_lport_init); | 1506 | EXPORT_SYMBOL(fc_lport_init); |