aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorJames Smart <James.Smart@Emulex.Com>2006-08-17 11:58:04 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-08-19 16:46:30 -0400
commita90f56847e8df9034c1c05d1157e1b0cd96987fb (patch)
treed0ec40b563855c7100675e800c2a95c711cd376d /drivers
parent33ccf8d1080bdccb4751a92f6da361a6e01b7cc0 (diff)
[SCSI] lpfc 8.1.9 : Stall eh handlers if resetting while rport blocked
Stall error handler if attempting resets/aborts while an rport is blocked. This avoids device offline scenarios due to errors in the error handler. Background: Although the transport is using the scsi_timed_out functionality to restart the timeout if the rport is blocked, if the timeout has already fired before the block occurs, the eh handler still runs and can take the device offline. Ultimately, this window cannot be resolved without significant work in the error handler thread. Christoph noted the first level of these issues when he noted the poor error response handling by the error thread. We found, under heavy load and error testing, that time window from when the scsi_times_out() adds the io to the queue to when the scsi_error_handler gets around to servicing it, can be in the several seconds range. In most cases, these test conditions are highly unusual, but possible. As a result, we're stalling the error handler in this race window so that we can avoid the device_offline transitions. Signed-off-by: James Smart <James.Smart@emulex.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/lpfc/lpfc_scsi.c19
1 files changed, 19 insertions, 0 deletions
diff --git a/drivers/scsi/lpfc/lpfc_scsi.c b/drivers/scsi/lpfc/lpfc_scsi.c
index 0811c824e0e0..a8816a8738f8 100644
--- a/drivers/scsi/lpfc/lpfc_scsi.c
+++ b/drivers/scsi/lpfc/lpfc_scsi.c
@@ -21,6 +21,7 @@
21 21
22#include <linux/pci.h> 22#include <linux/pci.h>
23#include <linux/interrupt.h> 23#include <linux/interrupt.h>
24#include <linux/delay.h>
24 25
25#include <scsi/scsi.h> 26#include <scsi/scsi.h>
26#include <scsi/scsi_device.h> 27#include <scsi/scsi_device.h>
@@ -841,6 +842,21 @@ lpfc_queuecommand(struct scsi_cmnd *cmnd, void (*done) (struct scsi_cmnd *))
841 return 0; 842 return 0;
842} 843}
843 844
845static void
846lpfc_block_error_handler(struct scsi_cmnd *cmnd)
847{
848 struct Scsi_Host *shost = cmnd->device->host;
849 struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
850
851 spin_lock_irq(shost->host_lock);
852 while (rport->port_state == FC_PORTSTATE_BLOCKED) {
853 spin_unlock_irq(shost->host_lock);
854 msleep(1000);
855 spin_lock_irq(shost->host_lock);
856 }
857 spin_unlock_irq(shost->host_lock);
858 return;
859}
844 860
845static int 861static int
846lpfc_abort_handler(struct scsi_cmnd *cmnd) 862lpfc_abort_handler(struct scsi_cmnd *cmnd)
@@ -855,6 +871,7 @@ lpfc_abort_handler(struct scsi_cmnd *cmnd)
855 unsigned int loop_count = 0; 871 unsigned int loop_count = 0;
856 int ret = SUCCESS; 872 int ret = SUCCESS;
857 873
874 lpfc_block_error_handler(cmnd);
858 spin_lock_irq(shost->host_lock); 875 spin_lock_irq(shost->host_lock);
859 876
860 lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble; 877 lpfc_cmd = (struct lpfc_scsi_buf *)cmnd->host_scribble;
@@ -957,6 +974,7 @@ lpfc_reset_lun_handler(struct scsi_cmnd *cmnd)
957 int ret = FAILED; 974 int ret = FAILED;
958 int cnt, loopcnt; 975 int cnt, loopcnt;
959 976
977 lpfc_block_error_handler(cmnd);
960 spin_lock_irq(shost->host_lock); 978 spin_lock_irq(shost->host_lock);
961 /* 979 /*
962 * If target is not in a MAPPED state, delay the reset until 980 * If target is not in a MAPPED state, delay the reset until
@@ -1073,6 +1091,7 @@ lpfc_reset_bus_handler(struct scsi_cmnd *cmnd)
1073 int cnt, loopcnt; 1091 int cnt, loopcnt;
1074 struct lpfc_scsi_buf * lpfc_cmd; 1092 struct lpfc_scsi_buf * lpfc_cmd;
1075 1093
1094 lpfc_block_error_handler(cmnd);
1076 spin_lock_irq(shost->host_lock); 1095 spin_lock_irq(shost->host_lock);
1077 1096
1078 lpfc_cmd = lpfc_get_scsi_buf(phba); 1097 lpfc_cmd = lpfc_get_scsi_buf(phba);