aboutsummaryrefslogtreecommitdiffstats
path: root/include/linux
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 /include/linux
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 'include/linux')
-rw-r--r--include/linux/libata.h6
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);
825extern void ata_data_xfer_noirq(struct ata_device *adev, unsigned char *buf, 830extern 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);
832extern int ata_std_qc_defer(struct ata_queued_cmd *qc);
827extern void ata_dumb_qc_prep(struct ata_queued_cmd *qc); 833extern void ata_dumb_qc_prep(struct ata_queued_cmd *qc);
828extern void ata_qc_prep(struct ata_queued_cmd *qc); 834extern void ata_qc_prep(struct ata_queued_cmd *qc);
829extern void ata_noop_qc_prep(struct ata_queued_cmd *qc); 835extern void ata_noop_qc_prep(struct ata_queued_cmd *qc);