summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorDavid Gwynne <dlg@cvs.openbsd.org>2011-07-08 07:15:32 +0000
committerDavid Gwynne <dlg@cvs.openbsd.org>2011-07-08 07:15:32 +0000
commit8208d534a5fd66215dd01ae6601b8eca84b6a12f (patch)
tree936dcda2a6ec002b4a348d756161386227067589 /sys
parent52ef5ab1dce8f6bb318bc5bb5bdc751c22bbb181 (diff)
some trim cleanups and additions.
use less magic numbers when check the block limits for trim. fill in the block limits vpd page with some conservative numbers about how much unmap we can do at a time (~32MB over 64 descriptors).
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/ata/atascsi.c26
1 files changed, 17 insertions, 9 deletions
diff --git a/sys/dev/ata/atascsi.c b/sys/dev/ata/atascsi.c
index 8cac2939092..eedca3f6bd8 100644
--- a/sys/dev/ata/atascsi.c
+++ b/sys/dev/ata/atascsi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: atascsi.c,v 1.108 2011/07/05 03:47:55 dlg Exp $ */
+/* $OpenBSD: atascsi.c,v 1.109 2011/07/08 07:15:31 dlg Exp $ */
/*
* Copyright (c) 2007 David Gwynne <dlg@openbsd.org>
@@ -832,6 +832,16 @@ atascsi_disk_vpd_limits(struct scsi_xfer *xs)
_lto2b(1 << ata_identify_block_l2p_exp(&ap->ap_identify),
pg.optimal_xfer_granularity);
+ if (ISSET(ap->ap_features, ATA_PORT_F_TRIM)) {
+ /*
+ * ATA only supports 65535 blocks per TRIM descriptor, so
+ * avoid having to split UNMAP descriptors and overflow the page
+ * limit by using that as a max.
+ */
+ _lto4b(ATA_DSM_TRIM_MAX_LEN, pg.max_unmap_lba_count);
+ _lto4b(512 / 8, pg.max_unmap_desc_count);
+ }
+
bcopy(&pg, xs->data, MIN(sizeof(pg), xs->datalen));
atascsi_done(xs, XS_NOERROR);
@@ -879,7 +889,7 @@ atascsi_disk_write_same_16(struct scsi_xfer *xs)
ap = atascsi_lookup_port(link);
cdb = (struct scsi_write_same_16 *)xs->cmd;
- if (cdb->flags != WRITE_SAME_F_UNMAP ||
+ if (!ISSET(cdb->flags, WRITE_SAME_F_UNMAP) ||
!ISSET(ap->ap_features, ATA_PORT_F_TRIM)) {
/* generate sense data */
atascsi_done(xs, XS_DRIVER_STUFFUP);
@@ -895,7 +905,7 @@ atascsi_disk_write_same_16(struct scsi_xfer *xs)
lba = _8btol(cdb->lba);
length = _4btol(cdb->length);
- if (length > 0xffff) {
+ if (length > ATA_DSM_TRIM_MAX_LEN) {
/* XXX we dont support requests over 65535 blocks */
atascsi_done(xs, XS_DRIVER_STUFFUP);
return;
@@ -913,7 +923,7 @@ atascsi_disk_write_same_16(struct scsi_xfer *xs)
/* TRIM sends a list of blocks to discard in the databuf. */
memset(xa->data, 0, xa->datalen);
- desc = htole64(((u_int64_t)length << 48) | lba);
+ desc = htole64(ATA_DSM_TRIM_DESC(lba, length));
memcpy(xa->data, &desc, sizeof(desc));
fis = xa->fis;
@@ -934,13 +944,11 @@ atascsi_disk_write_same_16_done(struct ata_xfer *xa)
case ATA_S_COMPLETE:
xs->error = XS_NOERROR;
break;
-
case ATA_S_ERROR:
+ xs->error = XS_DRIVER_STUFFUP;
+ break;
case ATA_S_TIMEOUT:
- printf("atascsi_disk_write_same_16_done: %s\n",
- xa->state == ATA_S_TIMEOUT ? "timeout" : "error");
- xs->error = (xa->state == ATA_S_TIMEOUT ? XS_TIMEOUT :
- XS_DRIVER_STUFFUP);
+ xs->error = XS_TIMEOUT;
break;
default: