Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

ata: Enabling ATA Command Priorities

This patch checks to see if an ATA device supports NCQ command priorities.
If so and the user has specified an iocontext that indicates
IO_PRIO_CLASS_RT then we build a tf with a high priority command.

This is done to improve the tail latency of commands that are high
priority by passing priority to the device.

tj: Removed trivial ata_ncq_prio_enabled() and open-coded the test.

Signed-off-by: Adam Manzanares <adam.manzanares@hgst.com>
Signed-off-by: Tejun Heo <tj@kernel.org>

authored by

Adam Manzanares and committed by
Tejun Heo
8e061784 5dc8b362

+49 -3
+34 -1
drivers/ata/libata-core.c
··· 739 739 * @n_block: Number of blocks 740 740 * @tf_flags: RW/FUA etc... 741 741 * @tag: tag 742 + * @class: IO priority class 742 743 * 743 744 * LOCKING: 744 745 * None. ··· 754 753 */ 755 754 int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, 756 755 u64 block, u32 n_block, unsigned int tf_flags, 757 - unsigned int tag) 756 + unsigned int tag, int class) 758 757 { 759 758 tf->flags |= ATA_TFLAG_ISADDR | ATA_TFLAG_DEVICE; 760 759 tf->flags |= tf_flags; ··· 786 785 tf->device = ATA_LBA; 787 786 if (tf->flags & ATA_TFLAG_FUA) 788 787 tf->device |= 1 << 7; 788 + 789 + if (dev->flags & ATA_DFLAG_NCQ_PRIO) { 790 + if (class == IOPRIO_CLASS_RT) 791 + tf->hob_nsect |= ATA_PRIO_HIGH << 792 + ATA_SHIFT_PRIO; 793 + } 789 794 } else if (dev->flags & ATA_DFLAG_LBA) { 790 795 tf->flags |= ATA_TFLAG_LBA; 791 796 ··· 2163 2156 } 2164 2157 } 2165 2158 2159 + static void ata_dev_config_ncq_prio(struct ata_device *dev) 2160 + { 2161 + struct ata_port *ap = dev->link->ap; 2162 + unsigned int err_mask; 2163 + 2164 + err_mask = ata_read_log_page(dev, 2165 + ATA_LOG_SATA_ID_DEV_DATA, 2166 + ATA_LOG_SATA_SETTINGS, 2167 + ap->sector_buf, 2168 + 1); 2169 + if (err_mask) { 2170 + ata_dev_dbg(dev, 2171 + "failed to get Identify Device data, Emask 0x%x\n", 2172 + err_mask); 2173 + return; 2174 + } 2175 + 2176 + if (ap->sector_buf[ATA_LOG_NCQ_PRIO_OFFSET] & BIT(3)) 2177 + dev->flags |= ATA_DFLAG_NCQ_PRIO; 2178 + else 2179 + ata_dev_dbg(dev, "SATA page does not support priority\n"); 2180 + 2181 + } 2182 + 2166 2183 static int ata_dev_config_ncq(struct ata_device *dev, 2167 2184 char *desc, size_t desc_sz) 2168 2185 { ··· 2236 2205 ata_dev_config_ncq_send_recv(dev); 2237 2206 if (ata_id_has_ncq_non_data(dev->id)) 2238 2207 ata_dev_config_ncq_non_data(dev); 2208 + if (ata_id_has_ncq_prio(dev->id)) 2209 + ata_dev_config_ncq_prio(dev); 2239 2210 } 2240 2211 2241 2212 return 0;
+5 -1
drivers/ata/libata-scsi.c
··· 50 50 #include <linux/uaccess.h> 51 51 #include <linux/suspend.h> 52 52 #include <asm/unaligned.h> 53 + #include <linux/ioprio.h> 53 54 54 55 #include "libata.h" 55 56 #include "libata-transport.h" ··· 1756 1755 { 1757 1756 struct scsi_cmnd *scmd = qc->scsicmd; 1758 1757 const u8 *cdb = scmd->cmnd; 1758 + struct request *rq = scmd->request; 1759 + int class = IOPRIO_PRIO_CLASS(req_get_ioprio(rq)); 1759 1760 unsigned int tf_flags = 0; 1760 1761 u64 block; 1761 1762 u32 n_block; ··· 1824 1821 qc->nbytes = n_block * scmd->device->sector_size; 1825 1822 1826 1823 rc = ata_build_rw_tf(&qc->tf, qc->dev, block, n_block, tf_flags, 1827 - qc->tag); 1824 + qc->tag, class); 1825 + 1828 1826 if (likely(rc == 0)) 1829 1827 return 0; 1830 1828
+1 -1
drivers/ata/libata.h
··· 66 66 extern struct ata_queued_cmd *ata_qc_new_init(struct ata_device *dev, int tag); 67 67 extern int ata_build_rw_tf(struct ata_taskfile *tf, struct ata_device *dev, 68 68 u64 block, u32 n_block, unsigned int tf_flags, 69 - unsigned int tag); 69 + unsigned int tag, int class); 70 70 extern u64 ata_tf_read_block(const struct ata_taskfile *tf, 71 71 struct ata_device *dev); 72 72 extern unsigned ata_exec_internal(struct ata_device *dev,
+6
include/linux/ata.h
··· 348 348 ATA_LOG_DEVSLP_DETO = 0x01, 349 349 ATA_LOG_DEVSLP_VALID = 0x07, 350 350 ATA_LOG_DEVSLP_VALID_MASK = 0x80, 351 + ATA_LOG_NCQ_PRIO_OFFSET = 0x09, 351 352 352 353 /* NCQ send and receive log */ 353 354 ATA_LOG_NCQ_SEND_RECV_SUBCMDS_OFFSET = 0x00, ··· 939 938 static inline bool ata_id_has_ncq_non_data(const u16 *id) 940 939 { 941 940 return id[ATA_ID_SATA_CAPABILITY_2] & BIT(5); 941 + } 942 + 943 + static inline bool ata_id_has_ncq_prio(const u16 *id) 944 + { 945 + return id[ATA_ID_SATA_CAPABILITY] & BIT(12); 942 946 } 943 947 944 948 static inline bool ata_id_has_trim(const u16 *id)
+3
include/linux/libata.h
··· 166 166 ATA_DFLAG_NO_UNLOAD = (1 << 17), /* device doesn't support unload */ 167 167 ATA_DFLAG_UNLOCK_HPA = (1 << 18), /* unlock HPA */ 168 168 ATA_DFLAG_NCQ_SEND_RECV = (1 << 19), /* device supports NCQ SEND and RECV */ 169 + ATA_DFLAG_NCQ_PRIO = (1 << 20), /* device supports NCQ priority */ 169 170 ATA_DFLAG_INIT_MASK = (1 << 24) - 1, 170 171 171 172 ATA_DFLAG_DETACH = (1 << 24), ··· 343 342 ATA_SHIFT_PIO = 0, 344 343 ATA_SHIFT_MWDMA = ATA_SHIFT_PIO + ATA_NR_PIO_MODES, 345 344 ATA_SHIFT_UDMA = ATA_SHIFT_MWDMA + ATA_NR_MWDMA_MODES, 345 + ATA_SHIFT_PRIO = 6, 346 346 347 + ATA_PRIO_HIGH = 2, 347 348 /* size of buffer to pad xfers ending on unaligned boundaries */ 348 349 ATA_DMA_PAD_SZ = 4, 349 350