aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/scsi/libfc/fc_lport.c53
-rw-r--r--drivers/scsi/libfc/fc_rport.c48
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 */
463static 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 */
1022static 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);
1054drop:
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);