aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata/libata-core.c
diff options
context:
space:
mode:
authorTejun Heo <htejun@gmail.com>2007-09-23 00:14:12 -0400
committerJeff Garzik <jeff@garzik.org>2007-10-12 14:55:41 -0400
commit31cc23b34913bc173680bdc87af79e551bf8cc0d (patch)
treeec64421ead9259174f0de8b22c36449ece6d69a4 /drivers/ata/libata-core.c
parentfb7fd61454c8681cd2621051a710b78a00369203 (diff)
libata-pmp-prep: implement ops->qc_defer()
Controllers which support PMP have various restrictions on which combinations of commands are allowed to what number of devices concurrently. This patch implements ops->qc_defer() which determines whether a qc can be issued at the moment or should be deferred. If the function returns ATA_DEFER_LINK, the qc will be deferred until a qc completes on the link. If ATA_DEFER_PORT, until a qc completes on any link. The defer conditions are advisory and in general ATA_DEFER_LINK can be considered as lower priority deferring than ATA_DEFER_PORT. ops->qc_defer() replaces fixed ata_scmd_need_defer(). For standard NCQ/non-NCQ exclusion, ata_std_qc_defer() is implemented. ahci and sata_sil24 are converted to use ata_std_qc_defer(). ops->qc_defer() is heavier than the original mechanism because full qc is prepped before determining to defer it, but various information is needed to determine defer conditinos and fully translating a qc is the only way to supply such information in generic manner. IMHO, this shouldn't cause any noticeable performance issues as * for most cases deferring occurs rarely (except for NCQ-aware cmd-switching PMP) * translation itself isn't that expensive * once deferred the command won't be repeated until another command completes which usually is a very long time cpu-wise. Signed-off-by: Tejun Heo <htejun@gmail.com> Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/ata/libata-core.c')
-rw-r--r--drivers/ata/libata-core.c31
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 9467c2f6019..b666f51da7e 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4346,6 +4346,36 @@ int ata_check_atapi_dma(struct ata_queued_cmd *qc)
4346} 4346}
4347 4347
4348/** 4348/**
4349 * ata_std_qc_defer - Check whether a qc needs to be deferred
4350 * @qc: ATA command in question
4351 *
4352 * Non-NCQ commands cannot run with any other command, NCQ or
4353 * not. As upper layer only knows the queue depth, we are
4354 * responsible for maintaining exclusion. This function checks
4355 * whether a new command @qc can be issued.
4356 *
4357 * LOCKING:
4358 * spin_lock_irqsave(host lock)
4359 *
4360 * RETURNS:
4361 * ATA_DEFER_* if deferring is needed, 0 otherwise.
4362 */
4363int ata_std_qc_defer(struct ata_queued_cmd *qc)
4364{
4365 struct ata_link *link = qc->dev->link;
4366
4367 if (qc->tf.protocol == ATA_PROT_NCQ) {
4368 if (!ata_tag_valid(link->active_tag))
4369 return 0;
4370 } else {
4371 if (!ata_tag_valid(link->active_tag) && !link->sactive)
4372 return 0;
4373 }
4374
4375 return ATA_DEFER_LINK;
4376}
4377
4378/**
4349 * ata_qc_prep - Prepare taskfile for submission 4379 * ata_qc_prep - Prepare taskfile for submission
4350 * @qc: Metadata associated with taskfile to be prepared 4380 * @qc: Metadata associated with taskfile to be prepared
4351 * 4381 *
@@ -7111,6 +7141,7 @@ EXPORT_SYMBOL_GPL(ata_interrupt);
7111EXPORT_SYMBOL_GPL(ata_do_set_mode); 7141EXPORT_SYMBOL_GPL(ata_do_set_mode);
7112EXPORT_SYMBOL_GPL(ata_data_xfer); 7142EXPORT_SYMBOL_GPL(ata_data_xfer);
7113EXPORT_SYMBOL_GPL(ata_data_xfer_noirq); 7143EXPORT_SYMBOL_GPL(ata_data_xfer_noirq);
7144EXPORT_SYMBOL_GPL(ata_std_qc_defer);
7114EXPORT_SYMBOL_GPL(ata_qc_prep); 7145EXPORT_SYMBOL_GPL(ata_qc_prep);
7115EXPORT_SYMBOL_GPL(ata_dumb_qc_prep); 7146EXPORT_SYMBOL_GPL(ata_dumb_qc_prep);
7116EXPORT_SYMBOL_GPL(ata_noop_qc_prep); 7147EXPORT_SYMBOL_GPL(ata_noop_qc_prep);