Skip to content

Commit

Permalink
libata: Add support for queued DSM TRIM
Browse files Browse the repository at this point in the history
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 Carino <marc.ceeeee@gmail.com>
Signed-off-by: Tejun Heo <tj@kernel.org>
  • Loading branch information
Marc Carino authored and Tejun Heo committed Aug 25, 2013
1 parent ed36911 commit 87fb6c3
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 6 deletions.
25 changes: 19 additions & 6 deletions drivers/ata/libata-scsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -3097,12 +3097,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;

Expand Down
7 changes: 7 additions & 0 deletions include/linux/libata.h
Original file line number Diff line number Diff line change
Expand Up @@ -1606,6 +1606,13 @@ static inline int ata_ncq_enabled(struct ata_device *dev)
ATA_DFLAG_NCQ)) == ATA_DFLAG_NCQ;
}

static inline bool ata_fpdma_dsm_supported(struct ata_device *dev)
{
return (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);
}

static inline void ata_qc_set_polling(struct ata_queued_cmd *qc)
{
qc->tf.ctl |= ATA_NIEN;
Expand Down

0 comments on commit 87fb6c3

Please sign in to comment.