From: Mike Christie Date: Fri, 16 Oct 2009 00:46:44 +0000 (-0700) Subject: [SCSI] scsi error: have scsi-ml call change_queue_depth to handle QUEUE_FULL X-Git-Url: https://git.karo-electronics.de/?a=commitdiff_plain;h=42a6a91833f1e0f5ee5b5ef98e9f00167b615f46;p=linux-beck.git [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 -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 Signed-off-by: James Bottomley --- diff --git a/drivers/scsi/scsi_error.c b/drivers/scsi/scsi_error.c index 1b0060b791e8..7b1e20fee906 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.