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>