diff options
author | Tejun Heo <htejun@gmail.com> | 2007-09-23 00:14:12 -0400 |
---|---|---|
committer | Jeff Garzik <jeff@garzik.org> | 2007-10-12 14:55:41 -0400 |
commit | 31cc23b34913bc173680bdc87af79e551bf8cc0d (patch) | |
tree | ec64421ead9259174f0de8b22c36449ece6d69a4 /drivers/ata/libata-core.c | |
parent | fb7fd61454c8681cd2621051a710b78a00369203 (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.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c index 9467c2f60192..b666f51da7ed 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 | */ | ||
4363 | int 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); | |||
7111 | EXPORT_SYMBOL_GPL(ata_do_set_mode); | 7141 | EXPORT_SYMBOL_GPL(ata_do_set_mode); |
7112 | EXPORT_SYMBOL_GPL(ata_data_xfer); | 7142 | EXPORT_SYMBOL_GPL(ata_data_xfer); |
7113 | EXPORT_SYMBOL_GPL(ata_data_xfer_noirq); | 7143 | EXPORT_SYMBOL_GPL(ata_data_xfer_noirq); |
7144 | EXPORT_SYMBOL_GPL(ata_std_qc_defer); | ||
7114 | EXPORT_SYMBOL_GPL(ata_qc_prep); | 7145 | EXPORT_SYMBOL_GPL(ata_qc_prep); |
7115 | EXPORT_SYMBOL_GPL(ata_dumb_qc_prep); | 7146 | EXPORT_SYMBOL_GPL(ata_dumb_qc_prep); |
7116 | EXPORT_SYMBOL_GPL(ata_noop_qc_prep); | 7147 | EXPORT_SYMBOL_GPL(ata_noop_qc_prep); |