summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorYi Zou <yi.zou@intel.com>2012-07-06 19:40:31 +0200
committerJames Bottomley <JBottomley@Parallels.com>2012-07-20 09:58:56 +0200
commita752359f2b0a291c5f229e883842e4b30c698387 (patch)
tree6ead324702ca37a69af584be38f31e6d5ecb9f83 /drivers
parent[SCSI] libfc: fix retries with FDMI lport states (diff)
downloadlinux-a752359f2b0a291c5f229e883842e4b30c698387.tar.xz
linux-a752359f2b0a291c5f229e883842e4b30c698387.zip
[SCSI] libfc: fix sending REC after FCP_RESP is received
This is exposed in the case the FCP_DATA frames somehow got lost and fc_fcp got the FCP_RSP, in fc_fcp_recv_resp(), since xfer_len is less than the expected_len it resets the the timer to wait to 2 more jiffies in case the data frames are already queued locally. However, for target does not support REC, it would just send RJT w/ ELS_RJT_UNSUP. The rec response handler thus only clears the rport flag for not doing REC later, but does not do fcp_io_complete() on the associated fsp. The fix is just check status of FCP_RSP being received already, i.e. using the FC_SRB_RCV_STATUS flag, in fc_fcp_timeout before start sending REC. We should have waited long enough if there is truely data frames queued locally. Signed-off-by: Yi Zou <yi.zou@intel.com> Tested-by: Ross Brattain <ross.b.brattain@intel.com> Signed-off-by: Robert Love <robert.w.love@intel.com> Signed-off-by: James Bottomley <JBottomley@Parallels.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/libfc/fc_fcp.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/drivers/scsi/libfc/fc_fcp.c b/drivers/scsi/libfc/fc_fcp.c
index 3c96e9300d00..14243fa5f8e8 100644
--- a/drivers/scsi/libfc/fc_fcp.c
+++ b/drivers/scsi/libfc/fc_fcp.c
@@ -1380,10 +1380,10 @@ static void fc_fcp_timeout(unsigned long data)
fsp->state |= FC_SRB_FCP_PROCESSING_TMO;
- if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED)
- fc_fcp_rec(fsp);
- else if (fsp->state & FC_SRB_RCV_STATUS)
+ if (fsp->state & FC_SRB_RCV_STATUS)
fc_fcp_complete_locked(fsp);
+ else if (rpriv->flags & FC_RP_FLAGS_REC_SUPPORTED)
+ fc_fcp_rec(fsp);
else
fc_fcp_recovery(fsp, FC_TIMED_OUT);
fsp->state &= ~FC_SRB_FCP_PROCESSING_TMO;