diff options
author | Joe Eykholt <jeykholt@cisco.com> | 2011-01-28 19:04:23 -0500 |
---|---|---|
committer | James Bottomley <James.Bottomley@suse.de> | 2011-02-12 12:02:22 -0500 |
commit | 925cedae2b223d44d59a02df1b35902fc8bdd6d2 (patch) | |
tree | 4fe2398d8761fd967a3ade45265ac6ce46319e9e /drivers/scsi/libfc | |
parent | 70d53b046a6221e3ceb3bd8eaa807ef6a1c53762 (diff) |
[SCSI] libfc: use PRLI hook to get parameters when sending outgoing PRLI
When sending an outgoing PRLI as an initiator, get the parameters
from registered providers so that they all get a chance to decide
on roles.
The passive provider is called last, and could override the
initiator role.
Signed-off-by: Joe Eykholt <jeykholt@cisco.com>
Signed-off-by: Robert Love <robert.w.love@intel.com>
Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi/libfc')
-rw-r--r-- | drivers/scsi/libfc/fc_rport.c | 27 |
1 files changed, 24 insertions, 3 deletions
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index a92954c1f42..9ded6123ff6 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c | |||
@@ -961,6 +961,8 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
961 | struct fc_els_prli prli; | 961 | struct fc_els_prli prli; |
962 | struct fc_els_spp spp; | 962 | struct fc_els_spp spp; |
963 | } *pp; | 963 | } *pp; |
964 | struct fc_els_spp temp_spp; | ||
965 | struct fc4_prov *prov; | ||
964 | u32 roles = FC_RPORT_ROLE_UNKNOWN; | 966 | u32 roles = FC_RPORT_ROLE_UNKNOWN; |
965 | u32 fcp_parm = 0; | 967 | u32 fcp_parm = 0; |
966 | u8 op; | 968 | u8 op; |
@@ -1009,6 +1011,13 @@ static void fc_rport_prli_resp(struct fc_seq *sp, struct fc_frame *fp, | |||
1009 | if (fcp_parm & FCP_SPPF_RETRY) | 1011 | if (fcp_parm & FCP_SPPF_RETRY) |
1010 | rdata->flags |= FC_RP_FLAGS_RETRY; | 1012 | rdata->flags |= FC_RP_FLAGS_RETRY; |
1011 | 1013 | ||
1014 | prov = fc_passive_prov[FC_TYPE_FCP]; | ||
1015 | if (prov) { | ||
1016 | memset(&temp_spp, 0, sizeof(temp_spp)); | ||
1017 | prov->prli(rdata, pp->prli.prli_spp_len, | ||
1018 | &pp->spp, &temp_spp); | ||
1019 | } | ||
1020 | |||
1012 | rdata->supported_classes = FC_COS_CLASS3; | 1021 | rdata->supported_classes = FC_COS_CLASS3; |
1013 | if (fcp_parm & FCP_SPPF_INIT_FCN) | 1022 | if (fcp_parm & FCP_SPPF_INIT_FCN) |
1014 | roles |= FC_RPORT_ROLE_FCP_INITIATOR; | 1023 | roles |= FC_RPORT_ROLE_FCP_INITIATOR; |
@@ -1045,6 +1054,7 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata) | |||
1045 | struct fc_els_spp spp; | 1054 | struct fc_els_spp spp; |
1046 | } *pp; | 1055 | } *pp; |
1047 | struct fc_frame *fp; | 1056 | struct fc_frame *fp; |
1057 | struct fc4_prov *prov; | ||
1048 | 1058 | ||
1049 | /* | 1059 | /* |
1050 | * If the rport is one of the well known addresses | 1060 | * If the rport is one of the well known addresses |
@@ -1066,9 +1076,20 @@ static void fc_rport_enter_prli(struct fc_rport_priv *rdata) | |||
1066 | return; | 1076 | return; |
1067 | } | 1077 | } |
1068 | 1078 | ||
1069 | if (!lport->tt.elsct_send(lport, rdata->ids.port_id, fp, ELS_PRLI, | 1079 | fc_prli_fill(lport, fp); |
1070 | fc_rport_prli_resp, rdata, | 1080 | |
1071 | 2 * lport->r_a_tov)) | 1081 | prov = fc_passive_prov[FC_TYPE_FCP]; |
1082 | if (prov) { | ||
1083 | pp = fc_frame_payload_get(fp, sizeof(*pp)); | ||
1084 | prov->prli(rdata, sizeof(pp->spp), NULL, &pp->spp); | ||
1085 | } | ||
1086 | |||
1087 | fc_fill_fc_hdr(fp, FC_RCTL_ELS_REQ, rdata->ids.port_id, | ||
1088 | fc_host_port_id(lport->host), FC_TYPE_ELS, | ||
1089 | FC_FC_FIRST_SEQ | FC_FC_END_SEQ | FC_FC_SEQ_INIT, 0); | ||
1090 | |||
1091 | if (!lport->tt.exch_seq_send(lport, fp, fc_rport_prli_resp, | ||
1092 | NULL, rdata, 2 * lport->r_a_tov)) | ||
1072 | fc_rport_error_retry(rdata, NULL); | 1093 | fc_rport_error_retry(rdata, NULL); |
1073 | else | 1094 | else |
1074 | kref_get(&rdata->kref); | 1095 | kref_get(&rdata->kref); |