aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/ata
diff options
context:
space:
mode:
authorDan Williams <dan.j.williams@intel.com>2014-04-17 14:48:21 -0400
committerTejun Heo <tj@kernel.org>2014-04-18 15:56:03 -0400
commit8a4aeec8d2d6a3edeffbdfae451cdf05cbf0fefd (patch)
tree98143931b264301d0adbb2c4addf0793a5081c97 /drivers/ata
parent2cf532f5e67c0cfe38c8c100e49280cdadacd2be (diff)
libata/ahci: accommodate tag ordered controllers
The AHCI spec allows implementations to issue commands in tag order rather than FIFO order: 5.3.2.12 P:SelectCmd HBA sets pSlotLoc = (pSlotLoc + 1) mod (CAP.NCS + 1) or HBA selects the command to issue that has had the PxCI bit set to '1' longer than any other command pending to be issued. The result is that commands posted sequentially (time-wise) may play out of sequence when issued by hardware. This behavior has likely been hidden by drives that arrange for commands to complete in issue order. However, it appears recent drives (two from different vendors that we have found so far) inflict out-of-order completions as a matter of course. So, we need to take care to maintain ordered submission, otherwise we risk triggering a drive to fall out of sequential-io automation and back to random-io processing, which incurs large latency and degrades throughput. This issue was found in simple benchmarks where QD=2 seq-write performance was 30-50% *greater* than QD=32 seq-write performance. Tagging for -stable and making the change globally since it has a low risk-to-reward ratio. Also, word is that recent versions of an unnamed OS also does it this way now. So, drives in the field are already experienced with this tag ordering scheme. Cc: <stable@vger.kernel.org> Cc: Dave Jiang <dave.jiang@intel.com> Cc: Ed Ciechanowski <ed.ciechanowski@intel.com> Reviewed-by: Matthew Wilcox <matthew.r.wilcox@intel.com> Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Tejun Heo <tj@kernel.org>
Diffstat (limited to 'drivers/ata')
-rw-r--r--drivers/ata/libata-core.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index f2a6020366e1..73c5d0410d47 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -4794,21 +4794,26 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
4794static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap) 4794static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
4795{ 4795{
4796 struct ata_queued_cmd *qc = NULL; 4796 struct ata_queued_cmd *qc = NULL;
4797 unsigned int i; 4797 unsigned int i, tag;
4798 4798
4799 /* no command while frozen */ 4799 /* no command while frozen */
4800 if (unlikely(ap->pflags & ATA_PFLAG_FROZEN)) 4800 if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
4801 return NULL; 4801 return NULL;
4802 4802
4803 /* the last tag is reserved for internal command. */ 4803 for (i = 0; i < ATA_MAX_QUEUE; i++) {
4804 for (i = 0; i < ATA_MAX_QUEUE - 1; i++) 4804 tag = (i + ap->last_tag + 1) % ATA_MAX_QUEUE;
4805 if (!test_and_set_bit(i, &ap->qc_allocated)) { 4805
4806 qc = __ata_qc_from_tag(ap, i); 4806 /* the last tag is reserved for internal command. */
4807 if (tag == ATA_TAG_INTERNAL)
4808 continue;
4809
4810 if (!test_and_set_bit(tag, &ap->qc_allocated)) {
4811 qc = __ata_qc_from_tag(ap, tag);
4812 qc->tag = tag;
4813 ap->last_tag = tag;
4807 break; 4814 break;
4808 } 4815 }
4809 4816 }
4810 if (qc)
4811 qc->tag = i;
4812 4817
4813 return qc; 4818 return qc;
4814} 4819}