summaryrefslogtreecommitdiff
path: root/drivers/scsi
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2009-10-15 17:46:44 -0700
committerJames Bottomley <James.Bottomley@suse.de>2009-12-04 12:00:42 -0600
commit42a6a91833f1e0f5ee5b5ef98e9f00167b615f46 (patch)
tree6173edb1fd2e4579d3223c7e3be1d0cc8430457c /drivers/scsi
parente881a172dac4d9ea3b2a1540041d872963c269bd (diff)
downloadlinux-3.10-42a6a91833f1e0f5ee5b5ef98e9f00167b615f46.tar.gz
linux-3.10-42a6a91833f1e0f5ee5b5ef98e9f00167b615f46.tar.bz2
linux-3.10-42a6a91833f1e0f5ee5b5ef98e9f00167b615f46.zip
[SCSI] scsi error: have scsi-ml call change_queue_depth to handle QUEUE_FULL
This has scsi-ml call the change_queue_depth functions when we get a QUEUE_FULL. It will only change the queue depth if change_queue_depth is set because the LLD may have to modify some internal resources, so I thought this would be the safest route. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> -v2 Limits change_queue_depth to only all luns of target by adding channel check while iterating for all luns of Scsi_Host. This is same as currently qla2xxx FC HBA does on QUEUE_FULL event. Signed-off-by: Vasu Dev <vasu.dev@intel.com> Signed-off-by: James Bottomley <James.Bottomley@suse.de>
Diffstat (limited to 'drivers/scsi')
-rw-r--r--drivers/scsi/scsi_error.c27
1 files changed, 26 insertions, 1 deletions
diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c
index 1b0060b791e..7b1e20fee90 100644
--- a/drivers/scsi/scsi_error.c
+++ b/drivers/scsi/scsi_error.c
@@ -331,6 +331,28 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
}
}
+static void scsi_handle_queue_full(struct scsi_device *sdev)
+{
+ struct scsi_host_template *sht = sdev->host->hostt;
+ struct scsi_device *tmp_sdev;
+
+ if (!sht->change_queue_depth)
+ return;
+
+ shost_for_each_device(tmp_sdev, sdev->host) {
+ if (tmp_sdev->channel != sdev->channel ||
+ tmp_sdev->id != sdev->id)
+ continue;
+ /*
+ * We do not know the number of commands that were at
+ * the device when we got the queue full so we start
+ * from the highest possible value and work our way down.
+ */
+ sht->change_queue_depth(tmp_sdev, tmp_sdev->queue_depth - 1,
+ SCSI_QDEPTH_QFULL);
+ }
+}
+
/**
* scsi_eh_completed_normally - Disposition a eh cmd on return from LLD.
* @scmd: SCSI cmd to examine.
@@ -387,8 +409,10 @@ static int scsi_eh_completed_normally(struct scsi_cmnd *scmd)
* let issuer deal with this, it could be just fine
*/
return SUCCESS;
- case BUSY:
case QUEUE_FULL:
+ scsi_handle_queue_full(scmd->device);
+ /* fall through */
+ case BUSY:
default:
return FAILED;
}
@@ -1387,6 +1411,7 @@ int scsi_decide_disposition(struct scsi_cmnd *scmd)
*/
switch (status_byte(scmd->result)) {
case QUEUE_FULL:
+ scsi_handle_queue_full(scmd->device);
/*
* the case of trying to send too many commands to a
* tagged queueing device.