summaryrefslogtreecommitdiffstats
path: root/drivers/scsi/libfc/fc_fcp.c
diff options
context:
space:
mode:
authorHannes Reinecke <hare@suse.de>2016-10-13 15:10:50 +0200
committerMartin K. Petersen <martin.petersen@oracle.com>2016-11-08 17:29:52 -0500
commit9ca1e182b9d1ef3f97718c4072a18a23dc47d4f9 (patch)
tree8931ec7605a437d59eb6e7edaff18d4cf031b01b /drivers/scsi/libfc/fc_fcp.c
parentb73aa56ee91cd88a4977033cfd2a18d6b25dddde (diff)
downloadlinux-9ca1e182b9d1ef3f97718c4072a18a23dc47d4f9.tar.gz
linux-9ca1e182b9d1ef3f97718c4072a18a23dc47d4f9.tar.bz2
linux-9ca1e182b9d1ef3f97718c4072a18a23dc47d4f9.zip
scsi: libfc: quarantine timed out xids
When a sequence times out we have no idea what happened to the frame. And we do not know if we will ever receive the frame. Hence we cannot re-use the xid as we would risk data corruption if the xid had been re-used and the timed out frame would be received after that. So we need to quarantine the xid until the lport is reset. Yes, I know this will (eventually) deplete the xid pool. But for now it's the safest method. Signed-off-by: Hannes Reinecke <hare@suse.com> Reviewed-by: Bart Van Assche <bart.vanassche@sandisk.com> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
Diffstat (limited to 'drivers/scsi/libfc/fc_fcp.c')
-rw-r--r--drivers/scsi/libfc/fc_fcp.c13
1 files changed, 7 insertions, 6 deletions
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index f7700cccf793..780d9f09a267 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -1529,13 +1529,14 @@ static void fc_fcp_rec_resp(struct fc_seq *seq, struct fc_frame *fp, void *arg)
fsp->rport->port_id, rjt->er_reason,
rjt->er_explan);
/*
- * If no data transfer, the command frame got dropped
- * so we just retry. If data was transferred, we
- * lost the response but the target has no record,
- * so we abort and retry.
+ * If response got lost or is stuck in the
+ * queue somewhere we have no idea if and when
+ * the response will be received. So quarantine
+ * the xid and retry the command.
*/
- if (rjt->er_explan == ELS_EXPL_OXID_RXID &&
- fsp->xfer_len == 0) {
+ if (rjt->er_explan == ELS_EXPL_OXID_RXID) {
+ struct fc_exch *ep = fc_seq_exch(fsp->seq_ptr);
+ ep->state |= FC_EX_QUARANTINE;
fsp->state |= FC_SRB_ABORTED;
fc_fcp_retry_cmd(fsp, FC_TRANS_RESET);
break;