diff options
Diffstat (limited to 'drivers/scsi/libfc')
| -rw-r--r-- | drivers/scsi/libfc/fc_exch.c | 4 | ||||
| -rw-r--r-- | drivers/scsi/libfc/fc_fcp.c | 2 | ||||
| -rw-r--r-- | drivers/scsi/libfc/fc_rport.c | 27 | 
3 files changed, 30 insertions, 3 deletions
| diff --git a/drivers/scsi/libfc/fc_exch.c b/drivers/scsi/libfc/fc_exch.c index 8b928c67e4b9..587992952b3c 100644 --- a/drivers/scsi/libfc/fc_exch.c +++ b/drivers/scsi/libfc/fc_exch.c @@ -337,7 +337,7 @@ static void fc_exch_release(struct fc_exch *ep)   * fc_exch_timer_cancel() - cancel exch timer   * @ep:		The exchange whose timer to be canceled   */ -static inline  void fc_exch_timer_cancel(struct fc_exch *ep) +static inline void fc_exch_timer_cancel(struct fc_exch *ep)  {  	if (cancel_delayed_work(&ep->timeout_work)) {  		FC_EXCH_DBG(ep, "Exchange timer canceled\n"); @@ -1567,7 +1567,7 @@ static void fc_exch_abts_resp(struct fc_exch *ep, struct fc_frame *fp)  		    fc_exch_rctl_name(fh->fh_r_ctl));  	if (cancel_delayed_work_sync(&ep->timeout_work)) { -		FC_EXCH_DBG(ep, "Exchange timer canceled\n"); +		FC_EXCH_DBG(ep, "Exchange timer canceled due to ABTS response\n");  		fc_exch_release(ep);	/* release from pending timer hold */  	} diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c index 09c81b2f2169..5fd0f1fbe586 100644 --- a/drivers/scsi/libfc/fc_fcp.c +++ b/drivers/scsi/libfc/fc_fcp.c @@ -2043,7 +2043,7 @@ int fc_eh_abort(struct scsi_cmnd *sc_cmd)  		spin_unlock_irqrestore(&si->scsi_queue_lock, flags);  		return SUCCESS;  	} -	/* grab a ref so the fsp and sc_cmd cannot be relased from under us */ +	/* grab a ref so the fsp and sc_cmd cannot be released from under us */  	fc_fcp_pkt_hold(fsp);  	spin_unlock_irqrestore(&si->scsi_queue_lock, flags); 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. |