Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 30 May 2009 15:27:30 GMT
From:      Alexander Motin <mav@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 163089 for review
Message-ID:  <200905301527.n4UFRUbv063243@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=163089

Change 163089 by mav@mav_mavbook on 2009/05/30 15:27:11

	Add initial experimental NCQ support.
	
	My tests of unpacking /usr/src to the empty async mount filesystem
	on Seagate ST3250620NS drive shows about 10-15% performance boost.

Affected files ...

.. //depot/projects/scottl-camlock/src/sys/cam/ata/ata_all.h#5 edit
.. //depot/projects/scottl-camlock/src/sys/cam/ata/ata_da.c#5 edit
.. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#7 edit
.. //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.h#3 edit

Differences ...

==== //depot/projects/scottl-camlock/src/sys/cam/ata/ata_all.h#5 (text+ko) ====

@@ -37,6 +37,7 @@
 	u_int8_t	command;        /* command reg */
 	u_int8_t	flags;		/* ATA command flags */
 #define		CAM_ATAIO_48BIT		0x01	/* Command has 48-bit format */
+#define		CAM_ATAIO_FPDMA		0x02	/* FPDMA command */
 	u_int16_t	feature;        /* feature reg */
 	u_int16_t	count;          /* count reg */
 	u_int64_t	lba;            /* lba reg */

==== //depot/projects/scottl-camlock/src/sys/cam/ata/ata_da.c#5 (text+ko) ====

@@ -70,6 +70,7 @@
 	DA_FLAG_PACK_INVALID	= 0x001,
 	DA_FLAG_CAN_48BIT	= 0x002,
 	DA_FLAG_CAN_FLUSHCACHE	= 0x004,
+	DA_FLAG_CAN_NCQ		= 0x008,
 	DA_FLAG_TAGGED_QUEUING	= 0x010,
 	DA_FLAG_NEED_OTAG	= 0x020,
 	DA_FLAG_WENT_IDLE	= 0x040,
@@ -598,6 +599,8 @@
 		softc->flags |= DA_FLAG_CAN_48BIT;
 	if (cgd->ident_data.support.command2 & ATA_SUPPORT_FLUSHCACHE)
 		softc->flags |= DA_FLAG_CAN_FLUSHCACHE;
+	if (cgd->ident_data.satacapabilities & ATA_SUPPORT_NCQ)
+		softc->flags |= DA_FLAG_CAN_NCQ;
 //	if ((cgd->inq_data.flags & SID_CmdQue) != 0)
 //		softc->flags |= DA_FLAG_TAGGED_QUEUING;
 
@@ -654,6 +657,9 @@
 	        dp->secsize, dp->heads,
                 dp->secs_per_track, dp->cylinders);
 	xpt_announce_periph(periph, announce_buf);
+printf("%04x %04x %04x sata: %04x, queue: %d\n",
+    cgd->ident_data.support.command1, cgd->ident_data.support.command2, cgd->ident_data.support.extension,
+    cgd->ident_data.satacapabilities, ATA_QUEUE_LEN(cgd->ident_data.queue));
 
 	softc->disk->d_sectorsize = softc->params.secsize;
 	softc->disk->d_mediasize = softc->params.secsize * (off_t)softc->params.sectors;
@@ -753,7 +759,13 @@
 				ataio->cmd.feature = 0;
 				ataio->cmd.lba = bp->bio_pblkno;
 				ataio->cmd.count = bp->bio_bcount / softc->params.secsize;
-				if ((softc->flags & DA_FLAG_CAN_48BIT) &&
+				if (softc->flags & DA_FLAG_CAN_NCQ) {
+					if (bp->bio_cmd == BIO_READ)
+						ataio->cmd.command = ATA_READ_FPDMA_QUEUED;
+					else
+						ataio->cmd.command = ATA_WRITE_FPDMA_QUEUED;
+					ataio->cmd.flags = CAM_ATAIO_48BIT | CAM_ATAIO_FPDMA;
+				} else if ((softc->flags & DA_FLAG_CAN_48BIT) &&
 				    (ataio->cmd.lba + ataio->cmd.count >= ATA_MAX_28BIT_LBA ||
 				    ataio->cmd.count >= 256)) {
 					if (bp->bio_cmd == BIO_READ)

==== //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.c#7 (text+ko) ====

@@ -72,7 +72,7 @@
 //static int ahci_pm_write(device_t dev, int port, int reg, u_int32_t result);
 static int ahci_hardreset(device_t dev, int port, uint32_t *signature);
 static u_int32_t ahci_softreset(device_t dev, int port);
-static int ahci_setup_fis(struct ahci_cmd_tab *ctp, union ccb *ccb);
+static int ahci_setup_fis(struct ahci_cmd_tab *ctp, union ccb *ccb, int tag);
 static void ahci_dmainit(device_t dev);
 static void ahci_dmasetupc_cb(void *xsc, bus_dma_segment_t *segs, int nsegs, int error);
 static void ahci_dmafini(device_t dev);
@@ -621,7 +621,7 @@
 {
 	device_t dev = (device_t)data;
 	struct ahci_channel *ch = device_get_softc(dev);
-	uint32_t istatus, cstatus, res, err;
+	uint32_t istatus, cstatus, sstatus, res, err;
 	enum ahci_err_type et;
 	int i, ccs;
 
@@ -629,7 +629,8 @@
 	/* Read interrupt and command statuses. */
 	istatus = ATA_INL(ch->r_mem, AHCI_P_IS);
 	cstatus = ATA_INL(ch->r_mem, AHCI_P_CI);
-//device_printf(dev, "%s is %08x cs %08x rslots %08x\n", __func__, istatus, cstatus, ch->rslots);
+	sstatus = ATA_IDX_INL(ch, ATA_SACTIVE);
+//device_printf(dev, "%s is %08x cs %08x ss %08x rslots %08x\n", __func__, istatus, cstatus, sstatus, ch->rslots);
 
 	/* Clear interrupt(s) */
 	ATA_OUTL(ch->r_mem, AHCI_P_IS, istatus);
@@ -641,18 +642,18 @@
 #define AHCI_STATBITS \
 	(AHCI_P_IX_IF|AHCI_P_IX_HBD|AHCI_P_IX_HBF|AHCI_P_IX_TFE)
 
-	if ((istatus & AHCI_STATBITS) && (cstatus & ch->rslots)) {
-device_printf(dev, "%s ERROR is %08x cs %08x rs %08x\n", __func__, istatus, cstatus, ch->rslots);
+	if ((istatus & AHCI_STATBITS) && ((cstatus | sstatus) & ch->rslots)) {
+device_printf(dev, "%s ERROR is %08x cs %08x ss %08x rs %08x\n", __func__, istatus, cstatus, sstatus, ch->rslots);
 		ccs = (ATA_INL(ch->r_mem, AHCI_P_CMD) & AHCI_P_CMD_CCS_MASK)
 		    >> AHCI_P_CMD_CCS_SHIFT;
 		/* kick controller into sane state */
 		ahci_stop(dev);
 		ahci_start(dev);
 		res = ch->rslots;
-		err = ch->rslots & cstatus;
+		err = ch->rslots & (cstatus | sstatus);
 	} else {
 		ccs = 0;
-		res = ch->rslots & ~cstatus;
+		res = ch->rslots & ~(cstatus | sstatus);
 		err = 0;
 	}
 	/* Check all slots. */
@@ -779,7 +780,7 @@
 		(ch->dma.work + AHCI_CT_OFFSET + (AHCI_CT_SIZE * slot->slot));
 
 	/* setup the FIS for this request */
-	if (!(fis_size = ahci_setup_fis(ctp, slot->ccb))) {
+	if (!(fis_size = ahci_setup_fis(ctp, slot->ccb, slot->slot))) {
 		device_printf(ch->dev, "setting up SATA FIS failed\n");
 		slot->ccb->ccb_h.status = CAM_REQ_INVALID;
 		xpt_done(slot->ccb);
@@ -800,10 +801,6 @@
 	clp->cmd_table_phys = htole64(ch->dma.work_bus + AHCI_CT_OFFSET +
 				  (AHCI_CT_SIZE * slot->slot));
 
-	/* clear eventual ACTIVE bit */
-//	ATA_IDX_OUTL(ch, ATA_SACTIVE,
-//		 ATA_IDX_INL(ch, ATA_SACTIVE) & (1 << slot->slot));
-
 	/* set command type bit */
 	if (slot->ccb->ccb_h.func_code == XPT_SCSI_IO) {
 		ATA_OUTL(ch->r_mem, AHCI_P_CMD,
@@ -815,6 +812,12 @@
 
 	slot->state = AHCI_SLOT_RUNNING;
 	ch->rslots |= (1 << slot->slot);
+	if ((slot->ccb->ccb_h.func_code == XPT_ATA_IO) &&
+	    (slot->ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA)) {
+		/* Set ACTIVE bit */
+		ch->aslots |= (1 << slot->slot);
+		ATA_IDX_OUTL(ch, ATA_SACTIVE, 1 << slot->slot);
+	}
 
 	/* issue command to controller */
 	ATA_OUTL(ch->r_mem, AHCI_P_CI, (1 << slot->slot));
@@ -1492,7 +1495,7 @@
 }
 
 static int
-ahci_setup_fis(struct ahci_cmd_tab *ctp, union ccb *ccb)
+ahci_setup_fis(struct ahci_cmd_tab *ctp, union ccb *ccb, int tag)
 {
 	u_int8_t *fis = &ctp->cfis[0];
 
@@ -1514,7 +1517,23 @@
 		}
 		fis[7] = ATA_D_LBA;
 		fis[15] = ATA_A_4BIT;
-		return 20;
+	} else if (ccb->ataio.cmd.flags & CAM_ATAIO_FPDMA) {
+		fis[0] = 0x27;			/* host to device */
+//		fis[1] = 0x80 | (atadev->unit & 0x0f);
+		fis[1] = 0x80 | (0 & 0x0f);
+		fis[2] = ccb->ataio.cmd.command;
+		fis[3] = ccb->ataio.cmd.count;
+		fis[4] = ccb->ataio.cmd.lba;
+		fis[5] = ccb->ataio.cmd.lba >> 8;
+		fis[6] = ccb->ataio.cmd.lba >> 16;
+		fis[7] = ATA_D_LBA;
+		fis[8] = ccb->ataio.cmd.lba >> 24;
+		fis[9] = ccb->ataio.cmd.lba >> 32; 
+		fis[10] = ccb->ataio.cmd.lba >> 40; 
+		fis[11] = ccb->ataio.cmd.count >> 8;
+		fis[12] = tag << 3;
+		fis[13] = 0;
+		fis[15] = ATA_A_4BIT;
 	} else {
 		fis[0] = 0x27;			/* host to device */
 //		fis[1] = 0x80 | (atadev->unit & 0x0f);
@@ -1534,8 +1553,8 @@
 		fis[12] = ccb->ataio.cmd.count;
 		fis[13] = ccb->ataio.cmd.count >> 8;
 		fis[15] = ATA_A_4BIT;
-		return 20;
 	}
+	return (20);
 }
 
 static int

==== //depot/projects/scottl-camlock/src/sys/dev/ahci/ahci.h#3 (text+ko) ====

@@ -431,6 +431,7 @@
 	
 	struct ahci_slot	slot[AHCI_MAX_SLOTS];
 	uint32_t		rslots;		/* Running slots */
+	uint32_t		aslots;		/* SACTIVE slots */
 	int			lastslot;	/* Last used slot */
 };
 



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