Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 3 Jul 2014 05:22:14 +0000 (UTC)
From:      Warner Losh <imp@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r268205 - head/sys/cam/ata
Message-ID:  <201407030522.s635MELq032806@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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,



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201407030522.s635MELq032806>