diff options
Diffstat (limited to 'drivers/scsi/scsi_error.c')
-rw-r--r-- | drivers/scsi/scsi_error.c | 27 |
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. |