Author: imp Date: Thu Jul 3 05:22:13 2014 New Revision: 268205 URL: http://svnweb.freebsd.org/changeset/base/268205
Log: 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. Reviewed by: mav@ Modified: head/sys/cam/ata/ata_da.c Modified: head/sys/cam/ata/ata_da.c ============================================================================== --- head/sys/cam/ata/ata_da.c Thu Jul 3 04:26:53 2014 (r268204) +++ head/sys/cam/ata/ata_da.c Thu Jul 3 05:22:13 2014 (r268205) @@ -719,8 +719,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.")); bioq_disksort(&softc->trim_queue, bp); } else { if (ADA_SIO) @@ -1376,6 +1379,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; @@ -1392,76 +1485,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; @@ -1596,25 +1628,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, _______________________________________________ svn-src-head@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-head To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"