Commit 76e72ad1 authored by Hannes Reinecke's avatar Hannes Reinecke Committed by Martin K. Petersen

scsi: libfc: sanitize E_D_TOV and R_A_TOV setting

When setting the FCP timeout we need to ensure a lower boundary
for E_D_TOV and R_A_TOV, otherwise we'd be getting spurious I/O
issues due to the fcp timer firing too early.
Signed-off-by: default avatarHannes Reinecke <hare@suse.com>
Acked-by: default avatarJohannes Thumshirn <jth@kernel.org>
Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
parent a50cc9ec
...@@ -1137,8 +1137,11 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp) ...@@ -1137,8 +1137,11 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp)
static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp) static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp)
{ {
struct fc_rport_libfc_priv *rpriv = fsp->rport->dd_data; struct fc_rport_libfc_priv *rpriv = fsp->rport->dd_data;
unsigned int e_d_tov = FC_DEF_E_D_TOV;
return msecs_to_jiffies(rpriv->e_d_tov) + HZ; if (rpriv && rpriv->e_d_tov > e_d_tov)
e_d_tov = rpriv->e_d_tov;
return msecs_to_jiffies(e_d_tov) + HZ;
} }
/** /**
...@@ -1693,7 +1696,6 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) ...@@ -1693,7 +1696,6 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset)
struct fc_seq *seq; struct fc_seq *seq;
struct fcp_srr *srr; struct fcp_srr *srr;
struct fc_frame *fp; struct fc_frame *fp;
unsigned int rec_tov;
rport = fsp->rport; rport = fsp->rport;
rpriv = rport->dd_data; rpriv = rport->dd_data;
...@@ -1717,10 +1719,9 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset) ...@@ -1717,10 +1719,9 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset)
rpriv->local_port->port_id, FC_TYPE_FCP, rpriv->local_port->port_id, FC_TYPE_FCP,
FC_FCTL_REQ, 0); FC_FCTL_REQ, 0);
rec_tov = get_fsp_rec_tov(fsp);
seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp,
fc_fcp_pkt_destroy, fc_fcp_pkt_destroy,
fsp, jiffies_to_msecs(rec_tov)); fsp, get_fsp_rec_tov(fsp));
if (!seq) if (!seq)
goto retry; goto retry;
......
...@@ -1777,7 +1777,7 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, ...@@ -1777,7 +1777,7 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
if ((csp_flags & FC_SP_FT_FPORT) == 0) { if ((csp_flags & FC_SP_FT_FPORT) == 0) {
if (e_d_tov > lport->e_d_tov) if (e_d_tov > lport->e_d_tov)
lport->e_d_tov = e_d_tov; lport->e_d_tov = e_d_tov;
lport->r_a_tov = 2 * e_d_tov; lport->r_a_tov = 2 * lport->e_d_tov;
fc_lport_set_port_id(lport, did, fp); fc_lport_set_port_id(lport, did, fp);
printk(KERN_INFO "host%d: libfc: " printk(KERN_INFO "host%d: libfc: "
"Port (%6.6x) entered " "Port (%6.6x) entered "
...@@ -1789,8 +1789,10 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp, ...@@ -1789,8 +1789,10 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
get_unaligned_be64( get_unaligned_be64(
&flp->fl_wwnn)); &flp->fl_wwnn));
} else { } else {
lport->e_d_tov = e_d_tov; if (e_d_tov > lport->e_d_tov)
lport->r_a_tov = r_a_tov; lport->e_d_tov = e_d_tov;
if (r_a_tov > lport->r_a_tov)
lport->r_a_tov = r_a_tov;
fc_host_fabric_name(lport->host) = fc_host_fabric_name(lport->host) =
get_unaligned_be64(&flp->fl_wwnn); get_unaligned_be64(&flp->fl_wwnn);
fc_lport_set_port_id(lport, did, fp); fc_lport_set_port_id(lport, did, fp);
......
...@@ -1296,13 +1296,15 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp, ...@@ -1296,13 +1296,15 @@ static void fc_rport_rtv_resp(struct fc_seq *sp, struct fc_frame *fp,
tov = ntohl(rtv->rtv_r_a_tov); tov = ntohl(rtv->rtv_r_a_tov);
if (tov == 0) if (tov == 0)
tov = 1; tov = 1;
rdata->r_a_tov = tov; if (tov > rdata->r_a_tov)
rdata->r_a_tov = tov;
tov = ntohl(rtv->rtv_e_d_tov); tov = ntohl(rtv->rtv_e_d_tov);
if (toq & FC_ELS_RTV_EDRES) if (toq & FC_ELS_RTV_EDRES)
tov /= 1000000; tov /= 1000000;
if (tov == 0) if (tov == 0)
tov = 1; tov = 1;
rdata->e_d_tov = tov; if (tov > rdata->e_d_tov)
rdata->e_d_tov = tov;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment