PERFORCE change 163089 for review
Alexander Motin
mav at FreeBSD.org
Sat May 30 15:27:32 UTC 2009
http://perforce.freebsd.org/chv.cgi?CH=163089
Change 163089 by mav at 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 */
};
More information about the p4-projects
mailing list