diff options
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/libfc/fc_lport.c | 53 | ||||
-rw-r--r-- | drivers/scsi/libfc/fc_rport.c | 48 |
2 files changed, 48 insertions, 53 deletions
diff --git a/drivers/scsi/libfc/fc_lport.c b/drivers/scsi/libfc/fc_lport.c index 3f2f72390145..bd2f77197447 100644 --- a/drivers/scsi/libfc/fc_lport.c +++ b/drivers/scsi/libfc/fc_lport.c | |||
@@ -452,56 +452,6 @@ static void fc_lport_recv_rnid_req(struct fc_seq *sp, struct fc_frame *in_fp, | |||
452 | } | 452 | } |
453 | 453 | ||
454 | /** | 454 | /** |
455 | * fc_lport_recv_adisc_req() - Handle received Address Discovery Request | ||
456 | * @lport: Fibre Channel local port recieving the ADISC | ||
457 | * @sp: current sequence in the ADISC exchange | ||
458 | * @fp: ADISC request frame | ||
459 | * | ||
460 | * Locking Note: The lport lock is expected to be held before calling | ||
461 | * this function. | ||
462 | */ | ||
463 | static void fc_lport_recv_adisc_req(struct fc_seq *sp, struct fc_frame *in_fp, | ||
464 | struct fc_lport *lport) | ||
465 | { | ||
466 | struct fc_frame *fp; | ||
467 | struct fc_exch *ep = fc_seq_exch(sp); | ||
468 | struct fc_els_adisc *req, *rp; | ||
469 | struct fc_seq_els_data rjt_data; | ||
470 | size_t len; | ||
471 | u32 f_ctl; | ||
472 | |||
473 | FC_LPORT_DBG(lport, "Received ADISC request while in state %s\n", | ||
474 | fc_lport_state(lport)); | ||
475 | |||
476 | req = fc_frame_payload_get(in_fp, sizeof(*req)); | ||
477 | if (!req) { | ||
478 | rjt_data.fp = NULL; | ||
479 | rjt_data.reason = ELS_RJT_LOGIC; | ||
480 | rjt_data.explan = ELS_EXPL_NONE; | ||
481 | lport->tt.seq_els_rsp_send(sp, ELS_LS_RJT, &rjt_data); | ||
482 | } else { | ||
483 | len = sizeof(*rp); | ||
484 | fp = fc_frame_alloc(lport, len); | ||
485 | if (fp) { | ||
486 | rp = fc_frame_payload_get(fp, len); | ||
487 | memset(rp, 0, len); | ||
488 | rp->adisc_cmd = ELS_LS_ACC; | ||
489 | rp->adisc_wwpn = htonll(lport->wwpn); | ||
490 | rp->adisc_wwnn = htonll(lport->wwnn); | ||
491 | hton24(rp->adisc_port_id, | ||
492 | fc_host_port_id(lport->host)); | ||
493 | sp = lport->tt.seq_start_next(sp); | ||
494 | f_ctl = FC_FC_EX_CTX | FC_FC_LAST_SEQ; | ||
495 | f_ctl |= FC_FC_END_SEQ | FC_FC_SEQ_INIT; | ||
496 | fc_fill_fc_hdr(fp, FC_RCTL_ELS_REP, ep->did, ep->sid, | ||
497 | FC_TYPE_ELS, f_ctl, 0); | ||
498 | lport->tt.seq_send(lport, sp, fp); | ||
499 | } | ||
500 | } | ||
501 | fc_frame_free(in_fp); | ||
502 | } | ||
503 | |||
504 | /** | ||
505 | * fc_lport_recv_logo_req() - Handle received fabric LOGO request | 455 | * fc_lport_recv_logo_req() - Handle received fabric LOGO request |
506 | * @lport: Fibre Channel local port recieving the LOGO | 456 | * @lport: Fibre Channel local port recieving the LOGO |
507 | * @sp: current sequence in the LOGO exchange | 457 | * @sp: current sequence in the LOGO exchange |
@@ -849,9 +799,6 @@ static void fc_lport_recv_req(struct fc_lport *lport, struct fc_seq *sp, | |||
849 | case ELS_RNID: | 799 | case ELS_RNID: |
850 | recv = fc_lport_recv_rnid_req; | 800 | recv = fc_lport_recv_rnid_req; |
851 | break; | 801 | break; |
852 | case ELS_ADISC: | ||
853 | recv = fc_lport_recv_adisc_req; | ||
854 | break; | ||
855 | } | 802 | } |
856 | 803 | ||
857 | recv(sp, fp, lport); | 804 | recv(sp, fp, lport); |
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); |