Introduce new SATA queued commands
v4 cover Introduce new SATA queued commands
From: Marc C <[email protected]>
This patch series updates the libata driver with some additional commands which are specified in the more recent versions of the SATA and ATA specifications. These commands are:
SEND FPDMA QUEUED
RECEIVE FPDMA QUEUED.
The new queued commands augment the existing READ and WRITE FPDMA QUEUED commands. The commands are intended to transport non-media data to/from a device in a non-blocking manner.
One application of these commands include a queued-style DSM TRIM operation. The current DSM TRIM command is non-queued, and requires the initiator to empty out the queue before issuance. The new DSM TRIM allows the initiator to keep the queue full.
These patches have been validated on an Intel SATA AHCI controller, on a Micron M500 SSD, using "postmark," "fstrim," and "fsck."
Version history:
v4:
- put "auxiliary" field back into taskfile struct
- add ATA controller flag to indicate support (default on) for new field
- style cleanups
v3:
- rebased to libata/for-3.12
- put H2D FIS "auxiliary" field changes in separate patch
- added "auxiliary" field population to all FIS-based SATA drivers
v2:
- rebased to 3.11-rc4
- moved auxiliary field to ata_queued_cmd struct
- updated signoff name
v1:
- initial
Marc Carino (3):
libata: Populate host-to-device FIS "auxiliary" field
libata: Add support for SEND/RECEIVE FPDMA QUEUED
libata: Add support for queued DSM TRIM
drivers/ata/ahci.c | 8 ++++++++ drivers/ata/libata-core.c | 30 ++++++++++++++++++++++++++---- drivers/ata/libata-scsi.c | 25 +++++++++++++++++++------ include/linux/ata.h | 23 +++++++++++++++++++++++ include/linux/libata.h | 20 ++++++++++++++++++++ 5 files changed, 96 insertions(+), 10 deletions(-)
Signature · 1 line
1.8.1.2
PATCH v4 1/3 libata: Populate host-to-device FIS "auxiliary" field
From: Marc Carino <[email protected]>
SATA 3.1 added an "auxiliary" field to the host-to-device FIS. Populate the host-to-device FIS with the new field via the taskfile struct.
--- drivers/ata/ahci.c | 8 ++++++++ drivers/ata/libata-core.c | 10 ++++++---- include/linux/libata.h | 5 +++++ 3 files changed, 19 insertions(+), 4 deletions(-)
drivers/ata/ahci.c +8 -0
@@ -1288,6 +1288,14 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)*/ if (!(hpriv->flags &AHCI_HFLAG_NO_FPDMA_AA )) pi.flags |=ATA_FLAG_FPDMA_AA ; + +/* +* All AHCI controllers should be forward-compatible +* with the new auxiliary field. This code should be +* conditionalized if any buggy AHCI controllers are +* encountered. +*/ + pi.flags |=ATA_FLAG_FPDMA_AUX ; }if (hpriv->cap &HOST_CAP_PMP )
drivers/ata/libata-core.c +6 -4
@@ -546,6 +546,8 @@ int atapi_cmd_type(u8 opcode)*/ void ata_tf_to_fis (const struct ata_taskfile *tf,u8 pmp,int is_cmd,u8 *fis) { +const __le32 aux =cpu_to_le32 (tf->auxiliary); + fis[0 ] =0x27 ;/* Register - Host to Device FIS */ fis[1 ] = pmp &0xf ;/* Port multiplier number*/ if (is_cmd)
@@ -569,10 +571,10 @@ void ata_tf_to_fis(const struct ata_taskfile *tf, u8 pmp, int is_cmd, u8 *fis) fis[14 ] =0 ; fis[15 ] = tf->ctl; - fis[16 ] =0 ; - fis[17 ] =0 ; - fis[18 ] =0 ; - fis[19 ] =0 ; + fis[16 ] = aux &0xff ; + fis[17 ] = (aux >>8 ) &0xff ; + fis[18 ] = (aux >>16 ) &0xff ; + fis[19 ] = (aux >>24 ) &0xff ; }/**
include/linux/libata.h +5 -0
@@ -223,6 +223,7 @@ enum {ATA_FLAG_ACPI_SATA = (1 <<17 ),/* need native SATA ACPI layout */ ATA_FLAG_AN = (1 <<18 ),/* controller supports AN */ ATA_FLAG_PMP = (1 <<19 ),/* controller supports PMP */ +ATA_FLAG_FPDMA_AUX = (1 <<20 ),/* controller supports H2DFIS aux field */ ATA_FLAG_EM = (1 <<21 ),/* driver supports enclosure * management */ ATA_FLAG_SW_ACTIVITY = (1 << 22), /* driver supports sw activity
@@ -555,6 +556,10 @@ struct ata_taskfile {u8 device;u8 command;/* IO operation */ + +u32 auxiliary;/* auxiliary field */ +/* from SATA 3.1 and */ +/* ATA-8 ACS-3 */ };#ifdef CONFIG_ATA_SFF
Signature · 1 line
1.8.1.2
Re: [PATCH v4 1/3] libata: Populate host-to-device FIS "auxiliary" field
Quoted 29 lines · Marc C
From: Marc Carino <[email protected]>
SATA 3.1 added an "auxiliary" field to the host-to-device FIS. Populate the host-to-device FIS with the new field via the taskfile struct.
Signed-off-by Marc Carino <[email protected]>--- drivers/ata/ahci.c | 8 ++++++++ drivers/ata/libata-core.c | 10 ++++++---- include/linux/libata.h | 5 +++++ 3 files changed, 19 insertions(+), 4 deletions(-)drivers/ata/ahci.c +8
-0@@ -1288,6 +1288,14 @@ static int ahci_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)*/ if (!(hpriv->flags &AHCI_HFLAG_NO_FPDMA_AA )) pi.flags |=ATA_FLAG_FPDMA_AA ; + +/* +* All AHCI controllers should be forward-compatible +* with the new auxiliary field. This code should be +* conditionalized if any buggy AHCI controllers are +* encountered. +*/ + pi.flags |=ATA_FLAG_FPDMA_AUX ;
[...]
include/linux/libata.h enum { · line 226
Quoted 9 lines
include/linux/libata.h +1
-0@@ -223,6 +223,7 @@ enum {ATA_FLAG_ACPI_SATA = (1 <<17 ),/* need native SATA ACPI layout */ ATA_FLAG_AN = (1 <<18 ),/* controller supports AN */ ATA_FLAG_PMP = (1 <<19 ),/* controller supports PMP */ + ATA_FLAG_FPDMA_AUX = (1 << 20), /* controller supports H2DFIS aux field */
I think adding this flag is a matter of a separate patch.
WBR, Sergei
PATCH v4 2/3 libata: Add support for SEND/RECEIVE FPDMA QUEUED
In reply to Marc CFrom: Marc Carino <[email protected]>
Add support for the following ATA opcodes, which are present in SATA 3.1 and T13 ATA ACS-3:
SEND FPDMA QUEUED
RECEIVE FPDMA QUEUED
--- drivers/ata/libata-core.c | 20 ++++++++++++++++++++ include/linux/ata.h | 23 +++++++++++++++++++++++ include/linux/libata.h | 4 ++++ 3 files changed, 47 insertions(+)
drivers/ata/libata-core.c +20 -0
@@ -2141,6 +2141,26 @@ static int ata_dev_config_ncq(struct ata_device *dev,else snprintf (desc, desc_sz,"NCQ (depth %d/%d)%s" , hdepth, ddepth, aa_desc); + +if ((ap->flags &ATA_FLAG_FPDMA_AUX ) && +ata_id_has_ncq_send_and_recv (dev->id)) { + err_mask =ata_read_log_page (dev, +ATA_LOG_NCQ_SEND_RECV , +0 , + ap->sector_buf, +1 ); +if (err_mask) { +ata_dev_dbg (dev, +"failed to get NCQ Send/Recv Log " +"Emask 0x%x\n" , + err_mask); + }else { + dev->flags |=ATA_DFLAG_NCQ_SEND_RECV ; +memcpy (dev->ncq_send_recv_cmds, ap->sector_buf, +ATA_LOG_NCQ_SEND_RECV_SIZE ); + } + } +return 0 ; }
include/linux/ata.h +23 -0
@@ -239,6 +239,8 @@ enum {ATA_CMD_WRITE_QUEUED_FUA_EXT =0x3E ,ATA_CMD_FPDMA_READ =0x60 ,ATA_CMD_FPDMA_WRITE =0x61 , +ATA_CMD_FPDMA_SEND =0x64 , +ATA_CMD_FPDMA_RECV =0x65 ,ATA_CMD_PIO_READ =0x20 ,ATA_CMD_PIO_READ_EXT =0x24 , ATA_CMD_PIO_WRITE = 0x30,
@@ -293,8 +295,13 @@ enum {/* marked obsolete in the ATA/ATAPI-7 spec */ ATA_CMD_RESTORE =0x10 , +/* Subcmds for ATA_CMD_FPDMA_SEND */ +ATA_SUBCMD_FPDMA_SEND_DSM =0x00 , +ATA_SUBCMD_FPDMA_SEND_WR_LOG_DMA_EXT =0x02 , +/* READ_LOG_EXT pages */ ATA_LOG_SATA_NCQ =0x10 , +ATA_LOG_NCQ_SEND_RECV =0x13 ,ATA_LOG_SATA_ID_DEV_DATA =0x30 ,ATA_LOG_SATA_SETTINGS =0x08 , ATA_LOG_DEVSLP_OFFSET = 0x30,
@@ -305,6 +312,15 @@ enum {ATA_LOG_DEVSLP_VALID =0x07 ,ATA_LOG_DEVSLP_VALID_MASK =0x80 , +/* NCQ send and receive log */ +ATA_LOG_NCQ_SEND_RECV_SUBCMDS_OFFSET =0x00 , +ATA_LOG_NCQ_SEND_RECV_SUBCMDS_DSM = (1 <<0 ), +ATA_LOG_NCQ_SEND_RECV_DSM_OFFSET =0x04 , +ATA_LOG_NCQ_SEND_RECV_DSM_TRIM = (1 <<0 ), +ATA_LOG_NCQ_SEND_RECV_RD_LOG_OFFSET =0x08 , +ATA_LOG_NCQ_SEND_RECV_WR_LOG_OFFSET =0x0C , +ATA_LOG_NCQ_SEND_RECV_SIZE =0x10 , +/* READ/WRITE LONG (obsolete) */ ATA_CMD_READ_LONG =0x22 , ATA_CMD_READ_LONG_ONCE = 0x23,
@@ -772,6 +788,13 @@ static inline int ata_id_rotation_rate(const u16 *id)return val; } +static inline bool ata_id_has_ncq_send_and_recv (const u16 *id) +{ +if (id[ATA_ID_SATA_CAPABILITY_2 ] &BIT (6 )) +return true; +return false; +} +static inline bool ata_id_has_trim (const u16 *id) { if (ata_id_major_version(id) >= 7 &&
include/linux/libata.h +4 -0
@@ -172,6 +172,7 @@ enum {ATA_DFLAG_DUBIOUS_XFER = (1 <<16 ),/* data transfer not verified */ ATA_DFLAG_NO_UNLOAD = (1 <<17 ),/* device doesn't support unload */ ATA_DFLAG_UNLOCK_HPA = (1 <<18 ),/* unlock HPA */ +ATA_DFLAG_NCQ_SEND_RECV = (1 <<19 ),/* device supports NCQ SEND and RECV */ ATA_DFLAG_INIT_MASK = (1 <<24 ) -1 , ATA_DFLAG_DETACH = (1 << 24),
@@ -704,6 +705,9 @@ struct ata_device {/* DEVSLP Timing Variables from Identify Device Data Log */ u8 devslp_timing[ATA_LOG_DEVSLP_SIZE ]; +/* NCQ send and receive log subcommand support */ +u8 ncq_send_recv_cmds[ATA_LOG_NCQ_SEND_RECV_SIZE ]; +/* error history */ int spdn_cnt;/* ering is CLEAR_END, read comment above CLEAR_END */
Signature · 1 line
1.8.1.2
Re: [PATCH v4 2/3] libata: Add support for SEND/RECEIVE FPDMA QUEUED
Hello.
Quoted 9 lines · Marc C
From: Marc Carino <[email protected]>
Add support for the following ATA opcodes, which are present in SATA 3.1 and T13 ATA ACS-3:
SEND FPDMA QUEUED
RECEIVE FPDMA QUEUEDSigned-off-by Marc Carino <[email protected]>
[...]
drivers/ata/libata-core.c static int ata_dev_config_ncq(struct ata_device *dev, · line 2146
Quoted 11 lines
drivers/ata/libata-core.c +3
-0@@ -2141,6 +2141,26 @@ static int ata_dev_config_ncq(struct ata_device *dev,else snprintf (desc, desc_sz,"NCQ (depth %d/%d)%s" , hdepth, ddepth, aa_desc); + +if ((ap->flags &ATA_FLAG_FPDMA_AUX ) && +ata_id_has_ncq_send_and_recv (dev->id)) {
Please start this line under the second ( above. It's the style preferred
in libata as it's easier on the eyes.
Quoted 7 lines
drivers/ata/libata-core.c +7
-0+ err_mask =ata_read_log_page (dev, +ATA_LOG_NCQ_SEND_RECV , +0 , + ap->sector_buf, +1 ); +if (err_mask) { + ata_dev_dbg(dev,
drivers/ata/libata-core.c static int ata_dev_config_ncq(struct ata_device *dev, · line 2163
Quoted 10 lines
drivers/ata/libata-core.c +10
-0+"failed to get NCQ Send/Recv Log " +"Emask 0x%x\n" , + err_mask); + }else { + dev->flags |=ATA_DFLAG_NCQ_SEND_RECV ; +memcpy (dev->ncq_send_recv_cmds, ap->sector_buf, +ATA_LOG_NCQ_SEND_RECV_SIZE ); + } + } +
WBR, Sergei
Re: [PATCH v4 2/3] libata: Add support for SEND/RECEIVE FPDMA QUEUED
In reply to Marc CHello, Marc.
Quoted 21 lines · Marc C
From: Marc Carino <[email protected]>
Add support for the following ATA opcodes, which are present in SATA 3.1 and T13 ATA ACS-3:
SEND FPDMA QUEUED
RECEIVE FPDMA QUEUEDSigned-off-by Marc Carino <[email protected]>--- drivers/ata/libata-core.c | 20 ++++++++++++++++++++ include/linux/ata.h | 23 +++++++++++++++++++++++ include/linux/libata.h | 4 ++++ 3 files changed, 47 insertions(+)drivers/ata/libata-core.c +0
-0@@ -2141,6 +2141,26 @@ static int ata_dev_config_ncq(struct ata_device *dev,else
drivers/ata/libata-core.c static int ata_dev_config_ncq(struct ata_device *dev, · line 2151
Quoted 10 lines
drivers/ata/libata-core.c +8
-0snprintf (desc, desc_sz,"NCQ (depth %d/%d)%s" , hdepth, ddepth, aa_desc); + +if ((ap->flags &ATA_FLAG_FPDMA_AUX ) && +ata_id_has_ncq_send_and_recv (dev->id)) { + err_mask =ata_read_log_page (dev, +ATA_LOG_NCQ_SEND_RECV , +0 , + ap->sector_buf, +1 );
Can you please fill to 80 col instead? I know the other invocation is breaking line for each argument but let's not spread that.
drivers/ata/libata-core.c static int ata_dev_config_ncq(struct ata_device *dev, · line 2155
Quoted 4 lines
drivers/ata/libata-core.c +4
-0+if (err_mask) { + ata_dev_dbg(dev, + "failed to get NCQ Send/Recv Log " + "Emask 0x%x\n",
And no need to break line for format strings.
drivers/ata/libata-core.c static int ata_dev_config_ncq(struct ata_device *dev, · line 2161
Quoted 6 lines
drivers/ata/libata-core.c +6
-0+static inline bool ata_id_has_ncq_send_and_recv (const u16 *id) +{ +if (id[ATA_ID_SATA_CAPABILITY_2 ] &BIT (6 )) +return true; +return false; +}
return id[ATA_ID_SATA_CAPABILITY_2] & BIT(6);
thanks.
Signature · 1 line
tejun
PATCH v4 3/3 libata: Add support for queued DSM TRIM
In reply to Marc CFrom: Marc Carino <[email protected]>
Some new SSDs support the queued version of the DSM TRIM command. Let the driver use the new command if supported.
--- drivers/ata/libata-scsi.c | 25 +++++++++++++++++++------ include/linux/libata.h | 11 +++++++++++ 2 files changed, 30 insertions(+), 6 deletions(-)
drivers/ata/libata-scsi.c +19 -6
@@ -3098,12 +3098,25 @@ static unsigned int ata_scsi_write_same_xlat(struct ata_queued_cmd *qc) buf =page_address (sg_page (scsi_sglist (scmd))); size =ata_set_lba_range_entries (buf,512 , block, n_block); - tf->protocol =ATA_PROT_DMA ; - tf->hob_feature =0 ; - tf->feature =ATA_DSM_TRIM ; - tf->hob_nsect = (size /512 ) >>8 ; - tf->nsect = size /512 ; - tf->command =ATA_CMD_DSM ; +if (ata_ncq_enabled (dev) &&ata_fpdma_dsm_supported (dev)) { +/* Newer devices support queued TRIM commands */ + tf->protocol =ATA_PROT_NCQ ; + tf->command =ATA_CMD_FPDMA_SEND ; + tf->hob_nsect =ATA_SUBCMD_FPDMA_SEND_DSM &0x1f ; + tf->nsect = qc->tag <<3 ; + tf->hob_feature = (size /512 ) >>8 ; + tf->feature = size /512 ; + + tf->auxiliary =1 ; + }else { + tf->protocol =ATA_PROT_DMA ; + tf->hob_feature =0 ; + tf->feature =ATA_DSM_TRIM ; + tf->hob_nsect = (size /512 ) >>8 ; + tf->nsect = size /512 ; + tf->command =ATA_CMD_DSM ; + } + tf->flags |=ATA_TFLAG_ISADDR |ATA_TFLAG_DEVICE |ATA_TFLAG_LBA48 |ATA_TFLAG_WRITE ;
include/linux/libata.h +11 -0
@@ -1608,6 +1608,17 @@ static inline int ata_ncq_enabled(struct ata_device *dev) ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ; } +static inline int ata_fpdma_dsm_supported (struct ata_device *dev) +{ +if ((dev->flags &ATA_DFLAG_NCQ_SEND_RECV ) && + (dev->ncq_send_recv_cmds[ATA_LOG_NCQ_SEND_RECV_DSM_OFFSET ] & +ATA_LOG_NCQ_SEND_RECV_DSM_TRIM )) { +return 1 ; + }else { +return 0 ; + } +} +static inline void ata_qc_set_polling (struct ata_queued_cmd *qc) { qc->tf.ctl |=ATA_NIEN ;
Signature · 1 line
1.8.1.2
Re: [PATCH v4 3/3] libata: Add support for queued DSM TRIM
Quoted 1 line · Marc C
+static inline int
ata_fpdma_dsm_supported(struct ata_device *dev)
bool?
include/linux/libata.h static inline int ata_ncq_enabled(struct ata_device *dev) · line 1619
Quoted 8 lines
include/linux/libata.h +8
-0+{ +if ((dev->flags &ATA_DFLAG_NCQ_SEND_RECV ) && + (dev->ncq_send_recv_cmds[ATA_LOG_NCQ_SEND_RECV_DSM_OFFSET ] & +ATA_LOG_NCQ_SEND_RECV_DSM_TRIM )) { +return 1 ; + }else { +return 0 ; + }
And again, you can just use a return statement.
Signature · 1 line
tejun
Hello,
Quoted 5 lines · Marc C
From: Marc C <[email protected]>
This patch series updates the libata driver with some additional commands which are specified in the more recent versions of the SATA and ATA specifications. These commands are:
Generally looks good to me other than the cosmetic points. Can you please update the series to Sergei's and my comments?
Thanks!
Signature · 1 line
tejun