summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2016-10-13 15:10:53 +0200
committerMartin K. Petersen <martin.petersen@oracle.com>2016-11-08 17:29:53 -0500
commitad3120cfe0c5dcd5aaa87a0f7c42d4b09a94fa12 (patch)
tree760633f790f0cbe6537ba48f10dac3f5889f76f0
parent53db8fa8a3b37d076f89bac67095e1381a2fb19a (diff)
scsi: libfc: reset timeout on queue full
When we're receiving a timeout we should be checking for queue full status; if there are still some packets pending we should be resetting the counter to ensure we're not missing out any packets which are still queued. Signed-off-by: Hannes Reinecke <hare@suse.com> Acked-by: Johannes Thumshirn <jth@kernel.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
-rw-r--r--drivers/scsi/libfc/fc_fcp.c20
-rw-r--r--include/scsi/libfc.h3
2 files changed, 19 insertions, 4 deletions
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index d43c925bace3..fb2ebc76e0eb 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -254,8 +254,10 @@ static inline void fc_fcp_unlock_pkt(struct fc_fcp_pkt *fsp)
*/
static void fc_fcp_timer_set(struct fc_fcp_pkt *fsp, unsigned long delay)
{
- if (!(fsp->state & FC_SRB_COMPL))
+ if (!(fsp->state & FC_SRB_COMPL)) {
mod_timer(&fsp->timer, jiffies + delay);
+ fsp->timer_delay = delay;
+ }
}
static void fc_fcp_abort_done(struct fc_fcp_pkt *fsp)
@@ -932,6 +934,11 @@ static void fc_fcp_resp(struct fc_fcp_pkt *fsp, struct fc_frame *fp)
* Wait a at least one jiffy to see if it is delivered.
* If this expires without data, we may do SRR.
*/
+ if (fsp->lp->qfull) {
+ FC_FCP_DBG(fsp, "tgt %6.6x queue busy retry\n",
+ fsp->rport->port_id);
+ return;
+ }
FC_FCP_DBG(fsp, "tgt %6.6x xfer len %zx data underrun "
"len %x, data len %x\n",
fsp->rport->port_id,
@@ -1434,8 +1441,15 @@ static void fc_fcp_timeout(unsigned long data)
if (fsp->cdb_cmd.fc_tm_flags)
goto unlock;
- FC_FCP_DBG(fsp, "fcp timeout, flags %x state %x\n",
- rpriv->flags, fsp->state);
+ if (fsp->lp->qfull) {
+ FC_FCP_DBG(fsp, "fcp timeout, resetting timer delay %d\n",
+ fsp->timer_delay);
+ setup_timer(&fsp->timer, fc_fcp_timeout, (unsigned long)fsp);
+ fc_fcp_timer_set(fsp, fsp->timer_delay);
+ goto unlock;
+ }
+ FC_FCP_DBG(fsp, "fcp timeout, delay %d flags %x state %x\n",
+ fsp->timer_delay, rpriv->flags, fsp->state);
fsp->state |= FC_SRB_FCP_PROCESSING_TMO;
if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED)
diff --git a/include/scsi/libfc.h b/include/scsi/libfc.h
index 8cb752f8d12b..f5aa54b40e75 100644
--- a/include/scsi/libfc.h
+++ b/include/scsi/libfc.h
@@ -355,7 +355,8 @@ struct fc_fcp_pkt {
/* Timeout/error related information */
struct timer_list timer;
- int wait_for_comp;
+ int wait_for_comp;
+ int timer_delay;
u32 recov_retry;
struct fc_seq *recov_seq;
struct completion tm_done;