diff options
Diffstat (limited to 'drivers/scsi/libfc/fc_rport.c')
-rw-r--r-- | drivers/scsi/libfc/fc_rport.c | 27 |
1 files changed, 27 insertions, 0 deletions
diff --git a/drivers/scsi/libfc/fc_rport.c b/drivers/scsi/libfc/fc_rport.c index 6bbb9447b75d..c710d908fda6 100644 --- a/drivers/scsi/libfc/fc_rport.c +++ b/drivers/scsi/libfc/fc_rport.c @@ -926,6 +926,20 @@ err: kref_put(&rdata->kref, rdata->local_port->tt.rport_destroy); } +static bool +fc_rport_compatible_roles(struct fc_lport *lport, struct fc_rport_priv *rdata) +{ + if (rdata->ids.roles == FC_PORT_ROLE_UNKNOWN) + return true; + if ((rdata->ids.roles & FC_PORT_ROLE_FCP_TARGET) && + (lport->service_params & FCP_SPPF_INIT_FCN)) + return true; + if ((rdata->ids.roles & FC_PORT_ROLE_FCP_INITIATOR) && + (lport->service_params & FCP_SPPF_TARG_FCN)) + return true; + return false; +} + /** * fc_rport_enter_plogi() - Send Port Login (PLOGI) request * @rdata: The remote port to send a PLOGI to @@ -938,6 +952,12 @@ static void fc_rport_enter_plogi(struct fc_rport_priv *rdata) struct fc_lport *lport = rdata->local_port; struct fc_frame *fp; + if (!fc_rport_compatible_roles(lport, rdata)) { + FC_RPORT_DBG(rdata, "PLOGI suppressed for incompatible role\n"); + fc_rport_state_enter(rdata, RPORT_ST_PLOGI_WAIT); + return; + } + FC_RPORT_DBG(rdata, "Port entered PLOGI state from %s state\n", fc_rport_state(rdata)); @@ -1646,6 +1666,13 @@ static void fc_rport_recv_plogi_req(struct fc_lport *lport, rjt_data.explan = ELS_EXPL_NONE; goto reject; } + if (!fc_rport_compatible_roles(lport, rdata)) { + FC_RPORT_DBG(rdata, "Received PLOGI for incompatible role\n"); + mutex_unlock(&rdata->rp_mutex); + rjt_data.reason = ELS_RJT_LOGIC; + rjt_data.explan = ELS_EXPL_NONE; + goto reject; + } /* * Get session payload size from incoming PLOGI. |