aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-scsi.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-02-20 09:31:22 -0500
committerJeff Garzik <jeff@garzik.org>2007-02-21 04:58:19 -0500
commitc3c70c443c2ef1fce31f201a93780c884b903993 (patch)
treecfb23ec2831ad4f10c87f6362573db9eb6a33cbd /drivers/ata/libata-scsi.c
parentfcf1bf1584647f9fd864c193fee81840c4c5ce41 (diff)
libata: fix ata_scsi_change_queue_depth()
Fix ata_scsi_change_queue_depth() such that... * NCQ on/off is exactly determined using the same logic as the issue path. * queue depth is adjusted to 1 if NCQ is not enabled. * -EINVAL is returned if requested action is ignored due to limitations. This fixes the bug which allows queue depth to be increased on blacklisted NCQ hosts/devices. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/libata-scsi.c')
-rw-r--r--drivers/ata/libata-scsi.c27
1 files changed, 15 insertions, 12 deletions
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index aa6cb6dcec41..48e388800f5a 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -987,29 +987,32 @@ int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
987 struct ata_port *ap = ata_shost_to_port(sdev->host); 987 struct ata_port *ap = ata_shost_to_port(sdev->host);
988 struct ata_device *dev; 988 struct ata_device *dev;
989 unsigned long flags; 989 unsigned long flags;
990 int max_depth;
991 990
992 if (queue_depth < 1) 991 if (queue_depth < 1 || queue_depth == sdev->queue_depth)
993 return sdev->queue_depth; 992 return sdev->queue_depth;
994 993
995 dev = ata_scsi_find_dev(ap, sdev); 994 dev = ata_scsi_find_dev(ap, sdev);
996 if (!dev || !ata_dev_enabled(dev)) 995 if (!dev || !ata_dev_enabled(dev))
997 return sdev->queue_depth; 996 return sdev->queue_depth;
998 997
999 max_depth = min(sdev->host->can_queue, ata_id_queue_depth(dev->id)); 998 /* NCQ enabled? */
1000 max_depth = min(ATA_MAX_QUEUE - 1, max_depth);
1001 if (queue_depth > max_depth)
1002 queue_depth = max_depth;
1003
1004 scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, queue_depth);
1005
1006 spin_lock_irqsave(ap->lock, flags); 999 spin_lock_irqsave(ap->lock, flags);
1007 if (queue_depth > 1) 1000 dev->flags &= ~ATA_DFLAG_NCQ_OFF;
1008 dev->flags &= ~ATA_DFLAG_NCQ_OFF; 1001 if (queue_depth == 1 || !ata_ncq_enabled(dev)) {
1009 else
1010 dev->flags |= ATA_DFLAG_NCQ_OFF; 1002 dev->flags |= ATA_DFLAG_NCQ_OFF;
1003 queue_depth = 1;
1004 }
1011 spin_unlock_irqrestore(ap->lock, flags); 1005 spin_unlock_irqrestore(ap->lock, flags);
1012 1006
1007 /* limit and apply queue depth */
1008 queue_depth = min(queue_depth, sdev->host->can_queue);
1009 queue_depth = min(queue_depth, ata_id_queue_depth(dev->id));
1010 queue_depth = min(queue_depth, ATA_MAX_QUEUE - 1);
1011
1012 if (sdev->queue_depth == queue_depth)
1013 return -EINVAL;
1014
1015 scsi_adjust_queue_depth(sdev, MSG_SIMPLE_TAG, queue_depth);
1013 return queue_depth; 1016 return queue_depth;
1014} 1017}
1015 1018