diff options
Diffstat (limited to 'drivers/scsi/libfc/fc_rport.c')
-rw-r--r-- | drivers/scsi/libfc/fc_rport.c | 48 |
1 files changed, 48 insertions, 0 deletions
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index c33e25851082..03ea6748e7ee 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c | |||
@@ -1012,6 +1012,50 @@ static void fc_rport_enter_adisc(struct fc_rport_priv *rdata) | |||
1012 | } | 1012 | } |
1013 | 1013 | ||
1014 | /** | 1014 | /** |
1015 | * fc_rport_recv_adisc_req() - Handle incoming Address Discovery (ADISC) Request | ||
1016 | * @rdata: remote port private | ||
1017 | * @sp: current sequence in the ADISC exchange | ||
1018 | * @in_fp: ADISC request frame | ||
1019 | * | ||
1020 | * Locking Note: Called with the lport and rport locks held. | ||
1021 | */ | ||
1022 | static void fc_rport_recv_adisc_req(struct fc_rport_priv *rdata, | ||
1023 | struct fc_seq *sp, struct fc_frame *in_fp) | ||
1024 | { | ||
1025 | struct fc_lport *lport = rdata->local_port; | ||
1026 | struct fc_frame *fp; | ||
1027 | struct fc_exch *ep = fc_seq_exch(sp); | ||
1028 | struct fc_els_adisc *adisc; | ||
1029 | struct fc_seq_els_data rjt_data; | ||
1030 | u32 f_ctl; | ||
1031 | |||
1032 | FC_RPORT_DBG(rdata, "Received ADISC request\n"); | ||
1033 | |||
1034 | adisc = fc_frame_payload_get(in_fp, sizeof(*adisc)); | ||
1035 | if (!adisc) { | ||
1036 | rjt_data.fp = NULL; | ||
1037 | rjt_data.reason = ELS_RJT_PROT; | ||
1038 | rjt_data.explan = ELS_EXPL_INV_LEN; | ||
1039 | lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); | ||
1040 | goto drop; | ||
1041 | } | ||
1042 | |||
1043 | fp = fc_frame_alloc(lport, sizeof(*adisc)); | ||
1044 | if (!fp) | ||
1045 | goto drop; | ||
1046 | fc_adisc_fill(lport, fp); | ||
1047 | adisc = fc_frame_payload_get(fp, sizeof(*adisc)); | ||
1048 | adisc->adisc_cmd = ELS_LS_ACC; | ||
1049 | sp = lport->tt.seq_start_next(sp); | ||
1050 | f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT; | ||
1051 | fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, | ||
1052 | FC_TYPE_ELS, f_ctl, 0); | ||
1053 | lport->tt.seq_send(lport, sp, fp); | ||
1054 | drop: | ||
1055 | fc_frame_free(in_fp); | ||
1056 | } | ||
1057 | |||
1058 | /** | ||
1015 | * fc_rport_recv_els_req() - handle a validated ELS request. | 1059 | * fc_rport_recv_els_req() - handle a validated ELS request. |
1016 | * @lport: Fibre Channel local port | 1060 | * @lport: Fibre Channel local port |
1017 | * @sp: current sequence in the PLOGI exchange | 1061 | * @sp: current sequence in the PLOGI exchange |
@@ -1062,6 +1106,9 @@ static void fc_rport_recv_els_req(struct fc_lport *lport, | |||
1062 | case ELS_PRLO: | 1106 | case ELS_PRLO: |
1063 | fc_rport_recv_prlo_req(rdata, sp, fp); | 1107 | fc_rport_recv_prlo_req(rdata, sp, fp); |
1064 | break; | 1108 | break; |
1109 | case ELS_ADISC: | ||
1110 | fc_rport_recv_adisc_req(rdata, sp, fp); | ||
1111 | break; | ||
1065 | case ELS_RRQ: | 1112 | case ELS_RRQ: |
1066 | els_data.fp = fp; | 1113 | els_data.fp = fp; |
1067 | lport->tt.seq_els_rsp_send(sp, ELS_RRQ, &els_data); | 1114 | lport->tt.seq_els_rsp_send(sp, ELS_RRQ, &els_data); |
@@ -1111,6 +1158,7 @@ void fc_rport_recv_req(struct fc_seq *sp, struct fc_frame *fp, | |||
1111 | break; | 1158 | break; |
1112 | case ELS_PRLI: | 1159 | case ELS_PRLI: |
1113 | case ELS_PRLO: | 1160 | case ELS_PRLO: |
1161 | case ELS_ADISC: | ||
1114 | case ELS_RRQ: | 1162 | case ELS_RRQ: |
1115 | case ELS_REC: | 1163 | case ELS_REC: |
1116 | fc_rport_recv_els_req(lport, sp, fp); | 1164 | fc_rport_recv_els_req(lport, sp, fp); |