[SCSI] libfc: use rport timeout values for fcp recovery
Use the rport value for rec_tov for timeout values when sending fcp commands. Currently, defaults are being used which may or may not match the advertised values. The default may cause i/o to timeout on networks that set this value larger then the default value. To make the timeout more configurable in the non-REC mode we remove the FC_SCSI_ER_TIMEOUT completely allowing the scsi-ml to do the timeout. This removes an unneeded timer and allows the i/o timeout to be configured using the scsi-ml knobs. Signed-off-by: John Fastabend <john.r.fastabend@intel.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
This commit is contained in:
parent
ac17ea8d7d
commit
e0883a3c3e
@ -57,6 +57,9 @@ struct kmem_cache *scsi_pkt_cachep;
|
|||||||
#define FC_SRB_READ (1 << 1)
|
#define FC_SRB_READ (1 << 1)
|
||||||
#define FC_SRB_WRITE (1 << 0)
|
#define FC_SRB_WRITE (1 << 0)
|
||||||
|
|
||||||
|
/* constant added to e_d_tov timeout to get rec_tov value */
|
||||||
|
#define REC_TOV_CONST 1
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The SCp.ptr should be tested and set under the scsi_pkt_queue lock
|
* The SCp.ptr should be tested and set under the scsi_pkt_queue lock
|
||||||
*/
|
*/
|
||||||
@ -126,9 +129,7 @@ static void fc_fcp_srr_error(struct fc_fcp_pkt *, struct fc_frame *);
|
|||||||
/*
|
/*
|
||||||
* Error recovery timeout values.
|
* Error recovery timeout values.
|
||||||
*/
|
*/
|
||||||
#define FC_SCSI_ER_TIMEOUT (10 * HZ)
|
|
||||||
#define FC_SCSI_TM_TOV (10 * HZ)
|
#define FC_SCSI_TM_TOV (10 * HZ)
|
||||||
#define FC_SCSI_REC_TOV (2 * HZ)
|
|
||||||
#define FC_HOST_RESET_TIMEOUT (30 * HZ)
|
#define FC_HOST_RESET_TIMEOUT (30 * HZ)
|
||||||
#define FC_CAN_QUEUE_PERIOD (60 * HZ)
|
#define FC_CAN_QUEUE_PERIOD (60 * HZ)
|
||||||
|
|
||||||
@ -1082,6 +1083,21 @@ static int fc_fcp_pkt_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp)
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* get_fsp_rec_tov() - Helper function to get REC_TOV
|
||||||
|
* @fsp: the FCP packet
|
||||||
|
*/
|
||||||
|
static inline unsigned int get_fsp_rec_tov(struct fc_fcp_pkt *fsp)
|
||||||
|
{
|
||||||
|
struct fc_rport *rport;
|
||||||
|
struct fc_rport_libfc_priv *rpriv;
|
||||||
|
|
||||||
|
rport = fsp->rport;
|
||||||
|
rpriv = rport->dd_data;
|
||||||
|
|
||||||
|
return rpriv->e_d_tov + REC_TOV_CONST;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* fc_fcp_cmd_send() - Send a FCP command
|
* fc_fcp_cmd_send() - Send a FCP command
|
||||||
* @lport: The local port to send the command on
|
* @lport: The local port to send the command on
|
||||||
@ -1099,6 +1115,7 @@ static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp,
|
|||||||
struct fc_rport_libfc_priv *rpriv;
|
struct fc_rport_libfc_priv *rpriv;
|
||||||
const size_t len = sizeof(fsp->cdb_cmd);
|
const size_t len = sizeof(fsp->cdb_cmd);
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
unsigned int rec_tov;
|
||||||
|
|
||||||
if (fc_fcp_lock_pkt(fsp))
|
if (fc_fcp_lock_pkt(fsp))
|
||||||
return 0;
|
return 0;
|
||||||
@ -1129,10 +1146,12 @@ static int fc_fcp_cmd_send(struct fc_lport *lport, struct fc_fcp_pkt *fsp,
|
|||||||
fsp->seq_ptr = seq;
|
fsp->seq_ptr = seq;
|
||||||
fc_fcp_pkt_hold(fsp); /* hold for fc_fcp_pkt_destroy */
|
fc_fcp_pkt_hold(fsp); /* hold for fc_fcp_pkt_destroy */
|
||||||
|
|
||||||
|
rec_tov = get_fsp_rec_tov(fsp);
|
||||||
|
|
||||||
setup_timer(&fsp->timer, fc_fcp_timeout, (unsigned long)fsp);
|
setup_timer(&fsp->timer, fc_fcp_timeout, (unsigned long)fsp);
|
||||||
fc_fcp_timer_set(fsp,
|
|
||||||
(fsp->tgt_flags & FC_RP_FLAGS_REC_SUPPORTED) ?
|
if (fsp->tgt_flags & FC_RP_FLAGS_REC_SUPPORTED)
|
||||||
FC_SCSI_REC_TOV : FC_SCSI_ER_TIMEOUT);
|
fc_fcp_timer_set(fsp, rec_tov);
|
||||||
unlock:
|
unlock:
|
||||||
fc_fcp_unlock_pkt(fsp);
|
fc_fcp_unlock_pkt(fsp);
|
||||||
return rc;
|
return rc;
|
||||||
@ -1207,13 +1226,16 @@ static void fc_lun_reset_send(unsigned long data)
|
|||||||
{
|
{
|
||||||
struct fc_fcp_pkt *fsp = (struct fc_fcp_pkt *)data;
|
struct fc_fcp_pkt *fsp = (struct fc_fcp_pkt *)data;
|
||||||
struct fc_lport *lport = fsp->lp;
|
struct fc_lport *lport = fsp->lp;
|
||||||
|
unsigned int rec_tov;
|
||||||
|
|
||||||
if (lport->tt.fcp_cmd_send(lport, fsp, fc_tm_done)) {
|
if (lport->tt.fcp_cmd_send(lport, fsp, fc_tm_done)) {
|
||||||
if (fsp->recov_retry++ >= FC_MAX_RECOV_RETRY)
|
if (fsp->recov_retry++ >= FC_MAX_RECOV_RETRY)
|
||||||
return;
|
return;
|
||||||
if (fc_fcp_lock_pkt(fsp))
|
if (fc_fcp_lock_pkt(fsp))
|
||||||
return;
|
return;
|
||||||
|
rec_tov = get_fsp_rec_tov(fsp);
|
||||||
setup_timer(&fsp->timer, fc_lun_reset_send, (unsigned long)fsp);
|
setup_timer(&fsp->timer, fc_lun_reset_send, (unsigned long)fsp);
|
||||||
fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV);
|
fc_fcp_timer_set(fsp, rec_tov);
|
||||||
fc_fcp_unlock_pkt(fsp);
|
fc_fcp_unlock_pkt(fsp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1351,9 +1373,6 @@ static void fc_fcp_timeout(unsigned long data)
|
|||||||
|
|
||||||
if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED)
|
if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED)
|
||||||
fc_fcp_rec(fsp);
|
fc_fcp_rec(fsp);
|
||||||
else if (time_after_eq(fsp->last_pkt_time + (FC_SCSI_ER_TIMEOUT / 2),
|
|
||||||
jiffies))
|
|
||||||
fc_fcp_timer_set(fsp, FC_SCSI_ER_TIMEOUT);
|
|
||||||
else if (fsp->state & FC_SRB_RCV_STATUS)
|
else if (fsp->state & FC_SRB_RCV_STATUS)
|
||||||
fc_fcp_complete_locked(fsp);
|
fc_fcp_complete_locked(fsp);
|
||||||
else
|
else
|
||||||
@ -1373,6 +1392,7 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp)
|
|||||||
struct fc_frame *fp;
|
struct fc_frame *fp;
|
||||||
struct fc_rport *rport;
|
struct fc_rport *rport;
|
||||||
struct fc_rport_libfc_priv *rpriv;
|
struct fc_rport_libfc_priv *rpriv;
|
||||||
|
unsigned int rec_tov;
|
||||||
|
|
||||||
lport = fsp->lp;
|
lport = fsp->lp;
|
||||||
rport = fsp->rport;
|
rport = fsp->rport;
|
||||||
@ -1383,6 +1403,9 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp)
|
|||||||
fc_fcp_complete_locked(fsp);
|
fc_fcp_complete_locked(fsp);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rec_tov = get_fsp_rec_tov(fsp);
|
||||||
|
|
||||||
fp = fc_fcp_frame_alloc(lport, sizeof(struct fc_els_rec));
|
fp = fc_fcp_frame_alloc(lport, sizeof(struct fc_els_rec));
|
||||||
if (!fp)
|
if (!fp)
|
||||||
goto retry;
|
goto retry;
|
||||||
@ -1393,13 +1416,13 @@ static void fc_fcp_rec(struct fc_fcp_pkt *fsp)
|
|||||||
FC_FCTL_REQ, 0);
|
FC_FCTL_REQ, 0);
|
||||||
if (lport->tt.elsct_send(lport, rport->port_id, fp, ELS_REC,
|
if (lport->tt.elsct_send(lport, rport->port_id, fp, ELS_REC,
|
||||||
fc_fcp_rec_resp, fsp,
|
fc_fcp_rec_resp, fsp,
|
||||||
jiffies_to_msecs(FC_SCSI_REC_TOV))) {
|
jiffies_to_msecs(rec_tov))) {
|
||||||
fc_fcp_pkt_hold(fsp); /* hold while REC outstanding */
|
fc_fcp_pkt_hold(fsp); /* hold while REC outstanding */
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
retry:
|
retry:
|
||||||
if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
|
if (fsp->recov_retry++ < FC_MAX_RECOV_RETRY)
|
||||||
fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV);
|
fc_fcp_timer_set(fsp, rec_tov);
|
||||||
else
|
else
|
||||||
fc_fcp_recovery(fsp, FC_TIMED_OUT);
|
fc_fcp_recovery(fsp, FC_TIMED_OUT);
|
||||||
}
|
}
|
||||||
@ -1455,7 +1478,6 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
|
|||||||
* making progress.
|
* making progress.
|
||||||
*/
|
*/
|
||||||
rpriv->flags &= ~FC_RP_FLAGS_REC_SUPPORTED;
|
rpriv->flags &= ~FC_RP_FLAGS_REC_SUPPORTED;
|
||||||
fc_fcp_timer_set(fsp, FC_SCSI_ER_TIMEOUT);
|
|
||||||
break;
|
break;
|
||||||
case ELS_RJT_LOGIC:
|
case ELS_RJT_LOGIC:
|
||||||
case ELS_RJT_UNAB:
|
case ELS_RJT_UNAB:
|
||||||
@ -1508,12 +1530,12 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
|
|||||||
}
|
}
|
||||||
fc_fcp_srr(fsp, r_ctl, offset);
|
fc_fcp_srr(fsp, r_ctl, offset);
|
||||||
} else if (e_stat & ESB_ST_SEQ_INIT) {
|
} else if (e_stat & ESB_ST_SEQ_INIT) {
|
||||||
|
unsigned int rec_tov = get_fsp_rec_tov(fsp);
|
||||||
/*
|
/*
|
||||||
* The remote port has the initiative, so just
|
* The remote port has the initiative, so just
|
||||||
* keep waiting for it to complete.
|
* keep waiting for it to complete.
|
||||||
*/
|
*/
|
||||||
fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV);
|
fc_fcp_timer_set(fsp, rec_tov);
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1626,6 +1648,7 @@ static void fc_fcp_srr(struct fc_fcp_pkt *fsp, enum fc_rctl r_ctl, u32 offset)
|
|||||||
struct fcp_srr *srr;
|
struct fcp_srr *srr;
|
||||||
struct fc_frame *fp;
|
struct fc_frame *fp;
|
||||||
u8 cdb_op;
|
u8 cdb_op;
|
||||||
|
unsigned int rec_tov;
|
||||||
|
|
||||||
rport = fsp->rport;
|
rport = fsp->rport;
|
||||||
rpriv = rport->dd_data;
|
rpriv = rport->dd_data;
|
||||||
@ -1650,8 +1673,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, NULL,
|
seq = lport->tt.exch_seq_send(lport, fp, fc_fcp_srr_resp, NULL,
|
||||||
fsp, jiffies_to_msecs(FC_SCSI_REC_TOV));
|
fsp, jiffies_to_msecs(rec_tov));
|
||||||
if (!seq)
|
if (!seq)
|
||||||
goto retry;
|
goto retry;
|
||||||
|
|
||||||
@ -1675,6 +1699,7 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
|
|||||||
{
|
{
|
||||||
struct fc_fcp_pkt *fsp = arg;
|
struct fc_fcp_pkt *fsp = arg;
|
||||||
struct fc_frame_header *fh;
|
struct fc_frame_header *fh;
|
||||||
|
unsigned int rec_tov;
|
||||||
|
|
||||||
if (IS_ERR(fp)) {
|
if (IS_ERR(fp)) {
|
||||||
fc_fcp_srr_error(fsp, fp);
|
fc_fcp_srr_error(fsp, fp);
|
||||||
@ -1701,7 +1726,8 @@ static void fc_fcp_srr_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
|
|||||||
switch (fc_frame_payload_op(fp)) {
|
switch (fc_frame_payload_op(fp)) {
|
||||||
case ELS_LS_ACC:
|
case ELS_LS_ACC:
|
||||||
fsp->recov_retry = 0;
|
fsp->recov_retry = 0;
|
||||||
fc_fcp_timer_set(fsp, FC_SCSI_REC_TOV);
|
rec_tov = get_fsp_rec_tov(fsp);
|
||||||
|
fc_fcp_timer_set(fsp, rec_tov);
|
||||||
break;
|
break;
|
||||||
case ELS_LS_RJT:
|
case ELS_LS_RJT:
|
||||||
default:
|
default:
|
||||||
|
Loading…
Reference in New Issue
Block a user