* [PATCH 0/2] Introduce new SATA queued commands
@ 2013-08-03 3:34 Marc C
2013-08-03 3:34 ` [PATCH 1/2] libata: Add support for SEND/RECEIVE FPDMA QUEUED Marc C
2013-08-03 3:34 ` [PATCH 2/2] libata: Add support for queued DSM TRIM Marc C
0 siblings, 2 replies; 5+ messages in thread
From: Marc C @ 2013-08-03 3:34 UTC (permalink / raw)
To: tj, linux-ide; +Cc: Marc C
From: Marc C <marc.ceeeee@gmail.com>
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 host 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."
Marc C (2):
libata: Add support for SEND/RECEIVE FPDMA QUEUED
libata: Add support for queued DSM TRIM
drivers/ata/libata-core.c | 25 +++++++++++++++++++++----
drivers/ata/libata-scsi.c | 26 ++++++++++++++++++++------
include/linux/ata.h | 25 +++++++++++++++++++++++++
include/linux/libata.h | 4 ++++
4 files changed, 70 insertions(+), 10 deletions(-)
--
1.8.1.2
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH 1/2] libata: Add support for SEND/RECEIVE FPDMA QUEUED
2013-08-03 3:34 [PATCH 0/2] Introduce new SATA queued commands Marc C
@ 2013-08-03 3:34 ` Marc C
2013-08-03 14:52 ` Sergei Shtylyov
2013-08-03 3:34 ` [PATCH 2/2] libata: Add support for queued DSM TRIM Marc C
1 sibling, 1 reply; 5+ messages in thread
From: Marc C @ 2013-08-03 3:34 UTC (permalink / raw)
To: tj, linux-ide; +Cc: Marc C
From: Marc C <marc.ceeeee@gmail.com>
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
Signed-off-by: Marc C <marc.ceeeee@gmail.com>
---
drivers/ata/libata-core.c | 25 +++++++++++++++++++++----
include/linux/ata.h | 25 +++++++++++++++++++++++++
include/linux/libata.h | 4 ++++
3 files changed, 50 insertions(+), 4 deletions(-)
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index c24354d..f89b2ef 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -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;
}
/**
@@ -2103,6 +2105,7 @@ static int ata_dev_config_ncq(struct ata_device *dev,
int hdepth = 0, ddepth = ata_id_queue_depth(dev->id);
unsigned int err_mask;
char *aa_desc = "";
+ u8 sata_setting[ATA_SECT_SIZE];
if (!ata_id_has_ncq(dev->id)) {
desc[0] = '\0';
@@ -2139,6 +2142,20 @@ 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 (ata_id_has_ncq_send_and_recv(dev->id)) {
+ err_mask = ata_read_log_page(dev,
+ ATA_LOG_NCQ_SEND_RECV,
+ 0,
+ sata_setting,
+ 1);
+ if (!err_mask) {
+ dev->flags |= ATA_DFLAG_NCQ_SEND_RECV;
+ memcpy(dev->ncq_send_recv_cmds, sata_setting,
+ ATA_LOG_NCQ_SEND_RECV_SIZE);
+ }
+ }
+
return 0;
}
diff --git a/include/linux/ata.h b/include/linux/ata.h
index ee0bd95..dd26211 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -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,
@@ -509,6 +525,8 @@ struct ata_taskfile {
u8 device;
u8 command; /* IO operation */
+
+ u32 auxiliary;
};
/*
@@ -865,6 +883,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 &&
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 4ea55bb..5e1b7f4 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -164,6 +164,7 @@ enum {
ATA_DFLAG_DA = (1 << 26), /* device supports Device Attention */
ATA_DFLAG_DEVSLP = (1 << 27), /* device supports Device Sleep */
ATA_DFLAG_ACPI_DISABLED = (1 << 28), /* ACPI for the device is disabled */
+ ATA_DFLAG_NCQ_SEND_RECV = (1 << 29), /* device supports NCQ SEND and RECV */
ATA_DEV_UNKNOWN = 0, /* unknown device */
ATA_DEV_ATA = 1, /* ATA device */
@@ -660,6 +661,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 */
--
1.8.1.2
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH 2/2] libata: Add support for queued DSM TRIM
2013-08-03 3:34 [PATCH 0/2] Introduce new SATA queued commands Marc C
2013-08-03 3:34 ` [PATCH 1/2] libata: Add support for SEND/RECEIVE FPDMA QUEUED Marc C
@ 2013-08-03 3:34 ` Marc C
1 sibling, 0 replies; 5+ messages in thread
From: Marc C @ 2013-08-03 3:34 UTC (permalink / raw)
To: tj, linux-ide; +Cc: Marc C
From: Marc C <marc.ceeeee@gmail.com>
Some new SSDs support the queued version of the DSM TRIM command.
Let the driver use the new command if supported.
Signed-off-by: Marc C <marc.ceeeee@gmail.com>
---
drivers/ata/libata-scsi.c | 26 ++++++++++++++++++++------
1 file changed, 20 insertions(+), 6 deletions(-)
diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
index b1e880a..8781e1b 100644
--- a/drivers/ata/libata-scsi.c
+++ b/drivers/ata/libata-scsi.c
@@ -3100,12 +3100,26 @@ 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) &&
+ (dev->ncq_send_recv_cmds[ATA_LOG_NCQ_SEND_RECV_DSM_OFFSET] &
+ ATA_LOG_NCQ_SEND_RECV_DSM_TRIM)) {
+ /* Newer devices support queued TRIM commands */
+ tf->protocol = ATA_PROT_NCQ;
+ tf->auxiliary = 1;
+ 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;
+ } 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;
--
1.8.1.2
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] libata: Add support for SEND/RECEIVE FPDMA QUEUED
2013-08-03 3:34 ` [PATCH 1/2] libata: Add support for SEND/RECEIVE FPDMA QUEUED Marc C
@ 2013-08-03 14:52 ` Sergei Shtylyov
2013-08-03 16:30 ` Marc C
0 siblings, 1 reply; 5+ messages in thread
From: Sergei Shtylyov @ 2013-08-03 14:52 UTC (permalink / raw)
To: Marc C; +Cc: tj, linux-ide
Hello.
On 03-08-2013 7:34, Marc C wrote:
> From: Marc C <marc.ceeeee@gmail.com>
Real name is required in signoff.
> 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
> Signed-off-by: Marc C <marc.ceeeee@gmail.com>
[...]
> diff --git a/include/linux/ata.h b/include/linux/ata.h
> index ee0bd95..dd26211 100644
> --- a/include/linux/ata.h
> +++ b/include/linux/ata.h
[...]
> @@ -509,6 +525,8 @@ struct ata_taskfile {
> u8 device;
>
> u8 command; /* IO operation */
> +
> + u32 auxiliary;
The 'struct ata_taskfile' has been moved to libata.h for 3.12, so you are
basing your work off of the wrong branch. And what does this new field have to
do with the classical ATA taskfile registers? Can't we place it into 'struct
ata_queued_cmd'?
WBR, Sergei
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH 1/2] libata: Add support for SEND/RECEIVE FPDMA QUEUED
2013-08-03 14:52 ` Sergei Shtylyov
@ 2013-08-03 16:30 ` Marc C
0 siblings, 0 replies; 5+ messages in thread
From: Marc C @ 2013-08-03 16:30 UTC (permalink / raw)
To: Sergei Shtylyov; +Cc: tj, linux-ide
Hello,
> Real name is required in signoff.
Got it. I will update it in the resubmission.
>> diff --git a/include/linux/ata.h b/include/linux/ata.h
>> index ee0bd95..dd26211 100644
>> --- a/include/linux/ata.h
>> +++ b/include/linux/ata.h
> [...]
>> @@ -509,6 +525,8 @@ struct ata_taskfile {
>> u8 device;
>>
>> u8 command; /* IO operation */
>> +
>> + u32 auxiliary;
>
> The 'struct ata_taskfile' has been moved to libata.h for 3.12, so
> you are basing your work off of the wrong branch.
My bad! I'll rebase my tree to 3.12.
> And what does this new field have to do with the classical ATA
> taskfile registers? Can't we place it into 'struct ata_queued_cmd'?
Actually, nothing, since it's impossible to transport the new field via
a legacy TF. 'struct ata_queued_cmd' is a more appropriate place to put
it. Thank you for pointing that out.
Regards,
Marc
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2013-08-03 16:30 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-08-03 3:34 [PATCH 0/2] Introduce new SATA queued commands Marc C
2013-08-03 3:34 ` [PATCH 1/2] libata: Add support for SEND/RECEIVE FPDMA QUEUED Marc C
2013-08-03 14:52 ` Sergei Shtylyov
2013-08-03 16:30 ` Marc C
2013-08-03 3:34 ` [PATCH 2/2] libata: Add support for queued DSM TRIM Marc C
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).