From owner-svn-src-head@FreeBSD.ORG Thu Jul 3 05:22:15 2014 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits)) (No client certificate requested) by hub.freebsd.org (Postfix) with ESMTPS id 0B682550; Thu, 3 Jul 2014 05:22:15 +0000 (UTC) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id EB9742C20; Thu, 3 Jul 2014 05:22:14 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.8/8.14.8) with ESMTP id s635MECv032807; Thu, 3 Jul 2014 05:22:14 GMT (envelope-from imp@svn.freebsd.org) Received: (from imp@localhost) by svn.freebsd.org (8.14.8/8.14.8/Submit) id s635MELq032806; Thu, 3 Jul 2014 05:22:14 GMT (envelope-from imp@svn.freebsd.org) Message-Id: <201407030522.s635MELq032806@svn.freebsd.org> From: Warner Losh Date: Thu, 3 Jul 2014 05:22:14 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r268205 - head/sys/cam/ata X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 03 Jul 2014 05:22:15 -0000 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,