summaryrefslogtreecommitdiff
path: root/drivers/ata/libata-sata.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ata/libata-sata.c')
-rw-r--r--drivers/ata/libata-sata.c50
1 files changed, 31 insertions, 19 deletions
diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c
index f3e7396e3191..6c07025011ed 100644
--- a/drivers/ata/libata-sata.c
+++ b/drivers/ata/libata-sata.c
@@ -1023,7 +1023,6 @@ EXPORT_SYMBOL_GPL(dev_attr_sw_activity);
/**
* ata_change_queue_depth - Set a device maximum queue depth
* @ap: ATA port of the target device
- * @dev: target ATA device
* @sdev: SCSI device to configure queue depth for
* @queue_depth: new queue depth
*
@@ -1031,33 +1030,47 @@ EXPORT_SYMBOL_GPL(dev_attr_sw_activity);
* and libata.
*
*/
-int ata_change_queue_depth(struct ata_port *ap, struct ata_device *dev,
- struct scsi_device *sdev, int queue_depth)
+int ata_change_queue_depth(struct ata_port *ap, struct scsi_device *sdev,
+ int queue_depth)
{
+ struct ata_device *dev;
unsigned long flags;
+ int max_queue_depth;
- if (!dev || !ata_dev_enabled(dev))
- return sdev->queue_depth;
+ spin_lock_irqsave(ap->lock, flags);
- if (queue_depth < 1 || queue_depth == sdev->queue_depth)
+ dev = ata_scsi_find_dev(ap, sdev);
+ if (!dev || queue_depth < 1 || queue_depth == sdev->queue_depth) {
+ spin_unlock_irqrestore(ap->lock, flags);
return sdev->queue_depth;
+ }
- /* NCQ enabled? */
- spin_lock_irqsave(ap->lock, flags);
- dev->flags &= ~ATA_DFLAG_NCQ_OFF;
- if (queue_depth == 1 || !ata_ncq_enabled(dev)) {
+ /*
+ * Make sure that the queue depth requested does not exceed the device
+ * capabilities.
+ */
+ max_queue_depth = min(ATA_MAX_QUEUE, sdev->host->can_queue);
+ max_queue_depth = min(max_queue_depth, ata_id_queue_depth(dev->id));
+ if (queue_depth > max_queue_depth) {
+ spin_unlock_irqrestore(ap->lock, flags);
+ return -EINVAL;
+ }
+
+ /*
+ * If NCQ is not supported by the device or if the target queue depth
+ * is 1 (to disable drive side command queueing), turn off NCQ.
+ */
+ if (queue_depth == 1 || !ata_ncq_supported(dev)) {
dev->flags |= ATA_DFLAG_NCQ_OFF;
queue_depth = 1;
+ } else {
+ dev->flags &= ~ATA_DFLAG_NCQ_OFF;
}
- spin_unlock_irqrestore(ap->lock, flags);
- /* limit and apply queue depth */
- queue_depth = min(queue_depth, sdev->host->can_queue);
- queue_depth = min(queue_depth, ata_id_queue_depth(dev->id));
- queue_depth = min(queue_depth, ATA_MAX_QUEUE);
+ spin_unlock_irqrestore(ap->lock, flags);
- if (sdev->queue_depth == queue_depth)
- return -EINVAL;
+ if (queue_depth == sdev->queue_depth)
+ return sdev->queue_depth;
return scsi_change_queue_depth(sdev, queue_depth);
}
@@ -1082,8 +1095,7 @@ int ata_scsi_change_queue_depth(struct scsi_device *sdev, int queue_depth)
{
struct ata_port *ap = ata_shost_to_port(sdev->host);
- return ata_change_queue_depth(ap, ata_scsi_find_dev(ap, sdev),
- sdev, queue_depth);
+ return ata_change_queue_depth(ap, sdev, queue_depth);
}
EXPORT_SYMBOL_GPL(ata_scsi_change_queue_depth);