Date: Thu, 17 Jul 2014 22:58:06 +0000 (UTC) From: Warner Losh <imp@FreeBSD.org> To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-10@freebsd.org Subject: svn commit: r268815 - stable/10/sys/cam/ata Message-ID: <201407172258.s6HMw6QF050671@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: imp Date: Thu Jul 17 22:58:05 2014 New Revision: 268815 URL: http://svnweb.freebsd.org/changeset/base/268815 Log: MFC: >r268205 | imp | 2014-07-02 23:22:13 -0600 (Wed, 02 Jul 2014) | 9 lines >Rework the BIO_DELETE code slightly. Always queue the BIO_DELETE >requests on the trim_queue, even for the CFA ERASE. This allows us, in >the future, to collapse adjacent requests. Since CFA ERASE is only for >CF cards, and it is so restrictive in what it can do, the collapse >code is not presently here. This also brings the ada driver more in >line with the da driver's treatment of BIO_DELETEs. Modified: stable/10/sys/cam/ata/ata_da.c Directory Properties: stable/10/ (props changed) Modified: stable/10/sys/cam/ata/ata_da.c ============================================================================== --- stable/10/sys/cam/ata/ata_da.c Thu Jul 17 22:42:18 2014 (r268814) +++ stable/10/sys/cam/ata/ata_da.c Thu Jul 17 22:58:05 2014 (r268815) @@ -727,8 +727,11 @@ adastrategy(struct bio *bp) /* * Place it in the queue of disk activities for this disk */ - if (bp->bio_cmd == BIO_DELETE && - (softc->flags & ADA_FLAG_CAN_TRIM)) { + if (bp->bio_cmd == BIO_DELETE) { + KASSERT((softc->flags & ADA_FLAG_CAN_TRIM) || + ((softc->flags & ADA_FLAG_CAN_CFA) && + !(softc->flags & ADA_FLAG_CAN_48BIT)), + ("BIO_DELETE but no supported TRIM method.")); if (ADA_SIO) bioq_disksort(&softc->trim_queue, bp); else @@ -1386,6 +1389,96 @@ adaregister(struct cam_periph *periph, v } static void +ada_dsmtrim(struct ada_softc *softc, struct bio *bp, struct ccb_ataio *ataio) +{ + struct trim_request *req = &softc->trim_req; + uint64_t lastlba = (uint64_t)-1; + int c, lastcount = 0, off, ranges = 0; + + bzero(req, sizeof(*req)); + TAILQ_INIT(&req->bps); + do { + uint64_t lba = bp->bio_pblkno; + int count = bp->bio_bcount / softc->params.secsize; + + bioq_remove(&softc->trim_queue, bp); + + /* Try to extend the previous range. */ + if (lba == lastlba) { + c = min(count, ATA_DSM_RANGE_MAX - lastcount); + lastcount += c; + off = (ranges - 1) * ATA_DSM_RANGE_SIZE; + req->data[off + 6] = lastcount & 0xff; + req->data[off + 7] = + (lastcount >> 8) & 0xff; + count -= c; + lba += c; + } + + while (count > 0) { + c = min(count, ATA_DSM_RANGE_MAX); + off = ranges * ATA_DSM_RANGE_SIZE; + req->data[off + 0] = lba & 0xff; + req->data[off + 1] = (lba >> 8) & 0xff; + req->data[off + 2] = (lba >> 16) & 0xff; + req->data[off + 3] = (lba >> 24) & 0xff; + req->data[off + 4] = (lba >> 32) & 0xff; + req->data[off + 5] = (lba >> 40) & 0xff; + req->data[off + 6] = c & 0xff; + req->data[off + 7] = (c >> 8) & 0xff; + lba += c; + count -= c; + lastcount = c; + ranges++; + /* + * Its the caller's responsibility to ensure the + * request will fit so we don't need to check for + * overrun here + */ + } + lastlba = lba; + TAILQ_INSERT_TAIL(&req->bps, bp, bio_queue); + bp = bioq_first(&softc->trim_queue); + if (bp == NULL || + bp->bio_bcount / softc->params.secsize > + (softc->trim_max_ranges - ranges) * ATA_DSM_RANGE_MAX) + break; + } while (1); + cam_fill_ataio(ataio, + ada_retry_count, + adadone, + CAM_DIR_OUT, + 0, + req->data, + ((ranges + ATA_DSM_BLK_RANGES - 1) / + ATA_DSM_BLK_RANGES) * ATA_DSM_BLK_SIZE, + ada_default_timeout * 1000); + ata_48bit_cmd(ataio, ATA_DATA_SET_MANAGEMENT, + ATA_DSM_TRIM, 0, (ranges + ATA_DSM_BLK_RANGES - + 1) / ATA_DSM_BLK_RANGES); +} + +static void +ada_cfaerase(struct ada_softc *softc, struct bio *bp, struct ccb_ataio *ataio) +{ + uint64_t lba = bp->bio_pblkno; + uint16_t count = bp->bio_bcount / softc->params.secsize; + + cam_fill_ataio(ataio, + ada_retry_count, + adadone, + CAM_DIR_NONE, + 0, + NULL, + 0, + ada_default_timeout*1000); + + if (count >= 256) + count = 0; + ata_28bit_cmd(ataio, ATA_CFA_ERASE, 0, lba, count); +} + +static void adastart(struct cam_periph *periph, union ccb *start_ccb) { struct ada_softc *softc = (struct ada_softc *)periph->softc; @@ -1402,76 +1495,15 @@ adastart(struct cam_periph *periph, unio /* Run TRIM if not running yet. */ if (!softc->trim_running && (bp = bioq_first(&softc->trim_queue)) != 0) { - struct trim_request *req = &softc->trim_req; - struct bio *bp1; - uint64_t lastlba = (uint64_t)-1; - int c, lastcount = 0, off, ranges = 0; - + if (softc->flags & ADA_FLAG_CAN_TRIM) { + ada_dsmtrim(softc, bp, ataio); + } else if ((softc->flags & ADA_FLAG_CAN_CFA) && + !(softc->flags & ADA_FLAG_CAN_48BIT)) { + ada_cfaerase(softc, bp, ataio); + } else { + panic("adastart: BIO_DELETE without method, not possible."); + } softc->trim_running = 1; - bzero(req, sizeof(*req)); - TAILQ_INIT(&req->bps); - bp1 = bp; - do { - uint64_t lba = bp1->bio_pblkno; - int count = bp1->bio_bcount / - softc->params.secsize; - - bioq_remove(&softc->trim_queue, bp1); - - /* Try to extend the previous range. */ - if (lba == lastlba) { - c = min(count, ATA_DSM_RANGE_MAX - lastcount); - lastcount += c; - off = (ranges - 1) * ATA_DSM_RANGE_SIZE; - req->data[off + 6] = lastcount & 0xff; - req->data[off + 7] = - (lastcount >> 8) & 0xff; - count -= c; - lba += c; - } - - while (count > 0) { - c = min(count, ATA_DSM_RANGE_MAX); - off = ranges * ATA_DSM_RANGE_SIZE; - req->data[off + 0] = lba & 0xff; - req->data[off + 1] = (lba >> 8) & 0xff; - req->data[off + 2] = (lba >> 16) & 0xff; - req->data[off + 3] = (lba >> 24) & 0xff; - req->data[off + 4] = (lba >> 32) & 0xff; - req->data[off + 5] = (lba >> 40) & 0xff; - req->data[off + 6] = c & 0xff; - req->data[off + 7] = (c >> 8) & 0xff; - lba += c; - count -= c; - lastcount = c; - ranges++; - /* - * Its the caller's responsibility to ensure the - * request will fit so we don't need to check for - * overrun here - */ - } - lastlba = lba; - TAILQ_INSERT_TAIL(&req->bps, bp1, bio_queue); - bp1 = bioq_first(&softc->trim_queue); - if (bp1 == NULL || - bp1->bio_bcount / softc->params.secsize > - (softc->trim_max_ranges - ranges) * - ATA_DSM_RANGE_MAX) - break; - } while (1); - cam_fill_ataio(ataio, - ada_retry_count, - adadone, - CAM_DIR_OUT, - 0, - req->data, - ((ranges + ATA_DSM_BLK_RANGES - 1) / - ATA_DSM_BLK_RANGES) * ATA_DSM_BLK_SIZE, - ada_default_timeout * 1000); - ata_48bit_cmd(ataio, ATA_DATA_SET_MANAGEMENT, - ATA_DSM_TRIM, 0, (ranges + ATA_DSM_BLK_RANGES - - 1) / ATA_DSM_BLK_RANGES); start_ccb->ccb_h.ccb_state = ADA_CCB_TRIM; start_ccb->ccb_h.flags |= CAM_UNLOCKED; goto out; @@ -1606,25 +1638,6 @@ adastart(struct cam_periph *periph, unio } break; } - case BIO_DELETE: - { - uint64_t lba = bp->bio_pblkno; - uint16_t count = bp->bio_bcount / softc->params.secsize; - - cam_fill_ataio(ataio, - ada_retry_count, - adadone, - CAM_DIR_NONE, - 0, - NULL, - 0, - ada_default_timeout*1000); - - if (count >= 256) - count = 0; - ata_28bit_cmd(ataio, ATA_CFA_ERASE, 0, lba, count); - break; - } case BIO_FLUSH: cam_fill_ataio(ataio, 1,
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201407172258.s6HMw6QF050671>