aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAndrew Vasquez <andrew.vasquez@qlogic.com>2006-10-02 12:00:49 -0700
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-10-03 17:29:06 -0500
commit07db51831371f2875ef234b1535a15afdb381b6c (patch)
tree49cfa4348769b6b2eccda29bb176173a45157dca /drivers
parentbb8ee4998498e15b5c8ed94cd7dd8d07e586c0ab (diff)
downloadlinux-07db51831371f2875ef234b1535a15afdb381b6c.tar.gz
[SCSI] qla2xxx: Stall mid-layer error handlers while rport is blocked.
Stall error handler if attempting recovery while an rport is blocked. This avoids device offline scenarios due to errors in the error handler. Reference implementation from lpfc/mptfc. Signed-off-by: Andrew Vasquez <andrew.vasquez@qlogic.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/scsi/qla2xxx/qla_os.c25
1 files changed, 25 insertions, 0 deletions
diff --git a/drivers/scsi/qla2xxx/qla_os.c b/drivers/scsi/qla2xxx/qla_os.c
index cdc7fca421bf2..3ba8c239f171e 100644
--- a/drivers/scsi/qla2xxx/qla_os.c
+++ b/drivers/scsi/qla2xxx/qla_os.c
@@ -589,6 +589,23 @@ qla2x00_wait_for_loop_ready(scsi_qla_host_t *ha)
return (return_status);
}
+static void
+qla2x00_block_error_handler(struct scsi_cmnd *cmnd)
+{
+ struct Scsi_Host *shost = cmnd->device->host;
+ struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
+ unsigned long flags;
+
+ spin_lock_irqsave(shost->host_lock, flags);
+ while (rport->port_state == FC_PORTSTATE_BLOCKED) {
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ msleep(1000);
+ spin_lock_irqsave(shost->host_lock, flags);
+ }
+ spin_unlock_irqrestore(shost->host_lock, flags);
+ return;
+}
+
/**************************************************************************
* qla2xxx_eh_abort
*
@@ -615,6 +632,8 @@ qla2xxx_eh_abort(struct scsi_cmnd *cmd)
unsigned long flags;
int wait = 0;
+ qla2x00_block_error_handler(cmd);
+
if (!CMD_SP(cmd))
return SUCCESS;
@@ -748,6 +767,8 @@ qla2xxx_eh_device_reset(struct scsi_cmnd *cmd)
unsigned int id, lun;
unsigned long serial;
+ qla2x00_block_error_handler(cmd);
+
ret = FAILED;
id = cmd->device->id;
@@ -877,6 +898,8 @@ qla2xxx_eh_bus_reset(struct scsi_cmnd *cmd)
unsigned int id, lun;
unsigned long serial;
+ qla2x00_block_error_handler(cmd);
+
ret = FAILED;
id = cmd->device->id;
@@ -936,6 +959,8 @@ qla2xxx_eh_host_reset(struct scsi_cmnd *cmd)
unsigned int id, lun;
unsigned long serial;
+ qla2x00_block_error_handler(cmd);
+
ret = FAILED;
id = cmd->device->id;