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 /include/linux/libata.h | |
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 'include/linux/libata.h')
-rw-r--r-- | include/linux/libata.h | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/include/linux/libata.h b/include/linux/libata.h index c3820f105ffa..b0d4ca0d27b4 100644 --- a/include/linux/libata.h +++ b/include/linux/libata.h | |||
@@ -272,6 +272,10 @@ enum { | |||
272 | /* ering size */ | 272 | /* ering size */ |
273 | ATA_ERING_SIZE = 32, | 273 | ATA_ERING_SIZE = 32, |
274 | 274 | ||
275 | /* return values for ->qc_defer */ | ||
276 | ATA_DEFER_LINK = 1, | ||
277 | ATA_DEFER_PORT = 2, | ||
278 | |||
275 | /* desc_len for ata_eh_info and context */ | 279 | /* desc_len for ata_eh_info and context */ |
276 | ATA_EH_DESC_LEN = 80, | 280 | ATA_EH_DESC_LEN = 80, |
277 | 281 | ||
@@ -639,6 +643,7 @@ struct ata_port_operations { | |||
639 | 643 | ||
640 | void (*data_xfer) (struct ata_device *, unsigned char *, unsigned int, int); | 644 | void (*data_xfer) (struct ata_device *, unsigned char *, unsigned int, int); |
641 | 645 | ||
646 | int (*qc_defer) (struct ata_queued_cmd *qc); | ||
642 | void (*qc_prep) (struct ata_queued_cmd *qc); | 647 | void (*qc_prep) (struct ata_queued_cmd *qc); |
643 | unsigned int (*qc_issue) (struct ata_queued_cmd *qc); | 648 | unsigned int (*qc_issue) (struct ata_queued_cmd *qc); |
644 | 649 | ||
@@ -824,6 +829,7 @@ extern void ata_data_xfer(struct ata_device *adev, unsigned char *buf, | |||
824 | unsigned int buflen, int write_data); | 829 | unsigned int buflen, int write_data); |
825 | extern void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf, | 830 | extern void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf, |
826 | unsigned int buflen, int write_data); | 831 | unsigned int buflen, int write_data); |
832 | extern int ata_std_qc_defer(struct ata_queued_cmd *qc); | ||
827 | extern void ata_dumb_qc_prep(struct ata_queued_cmd *qc); | 833 | extern void ata_dumb_qc_prep(struct ata_queued_cmd *qc); |
828 | extern void ata_qc_prep(struct ata_queued_cmd *qc); | 834 | extern void ata_qc_prep(struct ata_queued_cmd *qc); |
829 | extern void ata_noop_qc_prep(struct ata_queued_cmd *qc); | 835 | extern void ata_noop_qc_prep(struct ata_queued_cmd *qc); |