Skip to content

Commit 8a4aeec

Browse files
djbwhtejun
authored andcommitted
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>
1 parent 2cf532f commit 8a4aeec

File tree

2 files changed

+14
-8
lines changed

2 files changed

+14
-8
lines changed

drivers/ata/libata-core.c

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4794,21 +4794,26 @@ void swap_buf_le16(u16 *buf, unsigned int buf_words)
47944794
static struct ata_queued_cmd *ata_qc_new(struct ata_port *ap)
47954795
{
47964796
struct ata_queued_cmd *qc = NULL;
4797-
unsigned int i;
4797+
unsigned int i, tag;
47984798

47994799
/* no command while frozen */
48004800
if (unlikely(ap->pflags & ATA_PFLAG_FROZEN))
48014801
return NULL;
48024802

4803-
/* the last tag is reserved for internal command. */
4804-
for (i = 0; i < ATA_MAX_QUEUE - 1; i++)
4805-
if (!test_and_set_bit(i, &ap->qc_allocated)) {
4806-
qc = __ata_qc_from_tag(ap, i);
4803+
for (i = 0; i < ATA_MAX_QUEUE; i++) {
4804+
tag = (i + ap->last_tag + 1) % ATA_MAX_QUEUE;
4805+
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;
48074814
break;
48084815
}
4809-
4810-
if (qc)
4811-
qc->tag = i;
4816+
}
48124817

48134818
return qc;
48144819
}

include/linux/libata.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,7 @@ struct ata_port {
822822
unsigned long qc_allocated;
823823
unsigned int qc_active;
824824
int nr_active_links; /* #links with active qcs */
825+
unsigned int last_tag; /* track next tag hw expects */
825826

826827
struct ata_link link; /* host default link */
827828
struct ata_link *slave_link; /* see ata_slave_link_init() */

0 commit comments

Comments
 (0)