diff options
Diffstat (limited to 'drivers/ata/libata-sata.c')
-rw-r--r-- | drivers/ata/libata-sata.c | 50 |
1 files changed, 31 insertions, 19 deletions
diff --git a/drivers/ata/libata-sata.c b/drivers/ata/libata-sata.c index 7de4d8901fac..85e279a12f62 100644 --- a/drivers/ata/libata-sata.c +++ b/drivers/ata/libata-sata.c @@ -1032,7 +1032,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 * @@ -1040,33 +1039,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); } @@ -1091,8 +1104,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); |