diff options
-rw-r--r-- | sys/cam/ata/ata_da.c | 34 |
1 files changed, 25 insertions, 9 deletions
diff --git a/sys/cam/ata/ata_da.c b/sys/cam/ata/ata_da.c index 7418e1e..f918956 100644 --- a/sys/cam/ata/ata_da.c +++ b/sys/cam/ata/ata_da.c @@ -115,10 +115,11 @@ struct disk_params { }; #define TRIM_MAX_BLOCKS 4 -#define TRIM_MAX_RANGES TRIM_MAX_BLOCKS * 64 +#define TRIM_MAX_RANGES (TRIM_MAX_BLOCKS * 64) +#define TRIM_MAX_BIOS (TRIM_MAX_RANGES * 8) struct trim_request { uint8_t data[TRIM_MAX_RANGES * 8]; - struct bio *bps[TRIM_MAX_RANGES]; + struct bio *bps[TRIM_MAX_BIOS]; }; struct ada_softc { @@ -1067,7 +1068,8 @@ adastart(struct cam_periph *periph, union ccb *start_ccb) (bp = bioq_first(&softc->trim_queue)) != 0) { struct trim_request *req = &softc->trim_req; struct bio *bp1; - int bps = 0, ranges = 0; + uint64_t lastlba = (uint64_t)-1; + int bps = 0, c, lastcount = 0, off, ranges = 0; softc->trim_running = 1; bzero(req, sizeof(*req)); @@ -1078,10 +1080,22 @@ adastart(struct cam_periph *periph, union ccb *start_ccb) softc->params.secsize; bioq_remove(&softc->trim_queue, bp1); - while (count > 0) { - int c = min(count, 0xffff); - int off = ranges * 8; + /* Try to extend the previous range. */ + if (lba == lastlba) { + c = min(count, 0xffff - lastcount); + lastcount += c; + off = (ranges - 1) * 8; + req->data[off + 6] = lastcount & 0xff; + req->data[off + 7] = + (lastcount >> 8) & 0xff; + count -= c; + lba += c; + } + + while (count > 0) { + c = min(count, 0xffff); + off = ranges * 8; req->data[off + 0] = lba & 0xff; req->data[off + 1] = (lba >> 8) & 0xff; req->data[off + 2] = (lba >> 16) & 0xff; @@ -1092,11 +1106,14 @@ adastart(struct cam_periph *periph, union ccb *start_ccb) req->data[off + 7] = (c >> 8) & 0xff; lba += c; count -= c; + lastcount = c; ranges++; } + lastlba = lba; req->bps[bps++] = bp1; bp1 = bioq_first(&softc->trim_queue); - if (bp1 == NULL || + if (bps >= TRIM_MAX_BIOS || + bp1 == NULL || bp1->bio_bcount / softc->params.secsize > (softc->trim_max_ranges - ranges) * 0xffff) break; @@ -1370,8 +1387,7 @@ adadone(struct cam_periph *periph, union ccb *done_ccb) (struct trim_request *)ataio->data_ptr; int i; - for (i = 1; i < softc->trim_max_ranges && - req->bps[i]; i++) { + for (i = 1; i < TRIM_MAX_BIOS && req->bps[i]; i++) { struct bio *bp1 = req->bps[i]; bp1->bio_resid = bp->bio_resid; |