From 8df8a6ae3f2f8636b00eb50015df37abd17eab0b Mon Sep 17 00:00:00 2001 From: tsutsui Date: Sat, 30 Jun 2007 14:08:58 +0000 Subject: [PATCH] Rather than preparing DMA map for SCSI command (which is less than 16 bytes) of each SCSI command block (acb), just prepare DMA safe buffer in struct osiop_ds and copy commands into the buffer on each transfer to save resources and reduce small and unaligned cache flush ops. As a side effect, sizeof struct osiop_ds (DMA safe data buffer) is now 256 bytes (including padding) so it could be more cacheline friendly on bus_dmamap_sync(9) ops. Tested on Express5800/230 (arc) and EWS4800/360AD (ews4800mips), and no visible performance difference on bonnie. (hppa and mvme68k are untested) --- sys/dev/ic/osiop.c | 35 +++++------------------------------ sys/dev/ic/osiopvar.h | 34 ++++++++++++++++++---------------- 2 files changed, 23 insertions(+), 46 deletions(-) diff --git a/sys/dev/ic/osiop.c b/sys/dev/ic/osiop.c index 9e5ccece9679..d4087c8af6ea 100644 --- a/sys/dev/ic/osiop.c +++ b/sys/dev/ic/osiop.c @@ -1,4 +1,4 @@ -/* $NetBSD: osiop.c,v 1.27 2007/03/04 06:01:59 christos Exp $ */ +/* $NetBSD: osiop.c,v 1.28 2007/06/30 14:08:58 tsutsui Exp $ */ /* * Copyright (c) 2001 Izumi Tsutsui. All rights reserved. @@ -100,7 +100,7 @@ */ #include -__KERNEL_RCSID(0, "$NetBSD: osiop.c,v 1.27 2007/03/04 06:01:59 christos Exp $"); +__KERNEL_RCSID(0, "$NetBSD: osiop.c,v 1.28 2007/06/30 14:08:58 tsutsui Exp $"); /* #define OSIOP_DEBUG */ @@ -277,13 +277,6 @@ osiop_attach(struct osiop_softc *sc) for (i = 0; i < OSIOP_NACB; i++) { bus_addr_t dsa; - /* XXX How much size is required for each command block? */ - err = bus_dmamap_create(sc->sc_dmat, PAGE_SIZE, 1, PAGE_SIZE, - 0, BUS_DMA_NOWAIT, &acb->cmddma); - if (err) { - printf(": failed to create cmddma map, err=%d\n", err); - return; - } err = bus_dmamap_create(sc->sc_dmat, OSIOP_MAX_XFER, OSIOP_NSG, OSIOP_MAX_XFER, 0, BUS_DMA_NOWAIT, &acb->datadma); if (err) { @@ -298,6 +291,7 @@ osiop_attach(struct osiop_softc *sc) dsa = sc->sc_dsdma->dm_segs[0].ds_addr + acb->dsoffset; acb->ds->id.addr = dsa + OSIOP_DSIDOFF; + acb->ds->cmd.addr = dsa + OSIOP_DSCMDOFF; acb->ds->status.count = 1; acb->ds->status.addr = dsa + OSIOP_DSSTATOFF; acb->ds->msg.count = 1; @@ -410,19 +404,6 @@ osiop_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, acb->status = ACB_S_READY; acb->xs = xs; - /* Setup DMA map for SCSI command buffer */ - err = bus_dmamap_load(sc->sc_dmat, acb->cmddma, - xs->cmd, xs->cmdlen, NULL, BUS_DMA_NOWAIT); - if (err) { - printf("%s: unable to load cmd DMA map: %d\n", - sc->sc_dev.dv_xname, err); - xs->error = XS_DRIVER_STUFFUP; - TAILQ_INSERT_TAIL(&sc->free_list, acb, chain); - scsipi_done(xs); - splx(s); - return; - } - /* Setup DMA map for data buffer */ if (xs->xs_control & (XS_CTL_DATA_IN | XS_CTL_DATA_OUT)) { err = bus_dmamap_load(sc->sc_dmat, acb->datadma, @@ -435,7 +416,6 @@ osiop_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, sc->sc_dev.dv_xname, err); xs->error = XS_DRIVER_STUFFUP; scsipi_done(xs); - bus_dmamap_unload(sc->sc_dmat, acb->cmddma); TAILQ_INSERT_TAIL(&sc->free_list, acb, chain); splx(s); return; @@ -444,8 +424,6 @@ osiop_scsipi_request(struct scsipi_channel *chan, scsipi_adapter_req_t req, 0, xs->datalen, (xs->xs_control & XS_CTL_DATA_IN) ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); } - bus_dmamap_sync(sc->sc_dmat, acb->cmddma, 0, xs->cmdlen, - BUS_DMASYNC_PREWRITE); acb->cmdlen = xs->cmdlen; acb->datalen = xs->datalen; @@ -670,10 +648,6 @@ osiop_scsidone(struct osiop_acb *acb, int status) bus_dmamap_unload(sc->sc_dmat, acb->datadma); } - bus_dmamap_sync(sc->sc_dmat, acb->cmddma, 0, acb->cmdlen, - BUS_DMASYNC_POSTWRITE); - bus_dmamap_unload(sc->sc_dmat, acb->cmddma); - /* * Remove the ACB from whatever queue it's on. We have to do a bit of * a hack to figure out which queue it's on. Note that it is *not* @@ -953,8 +927,9 @@ osiop_start(struct osiop_softc *sc) acb->intstat = 0; + /* copy SCSI command to DMA buffer */ + memcpy(ds->scsipi_cmd, xs->cmd, acb->cmdlen); ds->cmd.count = acb->cmdlen; - ds->cmd.addr = acb->cmddma->dm_segs[0].ds_addr; ti = &sc->sc_tinfo[target]; ds->scsi_addr = ((1 << 16) << target) | (ti->sxfer << 8); diff --git a/sys/dev/ic/osiopvar.h b/sys/dev/ic/osiopvar.h index 631fea2a19a7..eefae1a6fff3 100644 --- a/sys/dev/ic/osiopvar.h +++ b/sys/dev/ic/osiopvar.h @@ -1,4 +1,4 @@ -/* $NetBSD: osiopvar.h,v 1.9 2005/12/11 12:21:28 christos Exp $ */ +/* $NetBSD: osiopvar.h,v 1.10 2007/06/30 14:08:58 tsutsui Exp $ */ /* * Copyright (c) 2001 Izumi Tsutsui. All rights reserved. @@ -96,20 +96,22 @@ typedef struct buf_table { } buf_table_t; struct osiop_ds { - uint32_t scsi_addr; /* SCSI ID & sync */ - uint32_t pad1; - buf_table_t id; /* Identify message */ - buf_table_t cmd; /* SCSI command */ - buf_table_t status; /* Status */ - buf_table_t msg; /* Message */ - buf_table_t msgin; /* Message in */ - buf_table_t extmsg; /* Extended message in */ - buf_table_t synmsg; /* Sync transfer request */ - buf_table_t data[OSIOP_NSG]; /* DMA S/G buffers */ - - uint8_t msgout[8]; - uint8_t msgbuf[8]; - uint8_t stat[8]; + uint32_t scsi_addr; /* 0: SCSI ID & sync */ + uint32_t pad1; /* 4: padding */ + buf_table_t id; /* 8: Identify message */ + buf_table_t cmd; /* 16: SCSI command */ + buf_table_t status; /* 24: Status */ + buf_table_t msg; /* 32: Message */ + buf_table_t msgin; /* 40: Message in */ + buf_table_t extmsg; /* 48: Extended message in */ + buf_table_t synmsg; /* 56: Sync transfer request */ + buf_table_t data[OSIOP_NSG]; /* 64: DMA S/G buffers */ + /* (8 * OSIOP_NSG == 136bytes) */ + uint8_t scsipi_cmd[16]; /* 200: cmd buf */ + uint8_t msgout[8]; /* 216: message out buf */ + uint8_t msgbuf[8]; /* 224: message in buf */ + uint8_t stat[8]; /* 232: stat buf */ + uint8_t pad2[16]; /* 240: padding to 256bytes */ } __attribute__((__packed__)); /* status can hold the SCSI_* status values, and 2 additional values: */ @@ -119,6 +121,7 @@ struct osiop_ds { #define MSG_INVALID 0xff /* dummy value for message buffer */ #define OSIOP_DSOFF(x) offsetof(struct osiop_ds, x) +#define OSIOP_DSCMDOFF OSIOP_DSOFF(scsipi_cmd[0]) #define OSIOP_DSIDOFF OSIOP_DSOFF(msgout[0]) #define OSIOP_DSMSGOFF OSIOP_DSOFF(msgbuf[0]) #define OSIOP_DSMSGINOFF OSIOP_DSOFF(msgbuf[1]) @@ -138,7 +141,6 @@ struct osiop_acb { struct scsipi_xfer *xs; /* SCSI xfer ctrl block from upper layer */ struct osiop_softc *sc; /* points back to our adapter */ - bus_dmamap_t cmddma; /* DMA map for SCSI command */ bus_dmamap_t datadma; /* DMA map for data transfer */ struct osiop_ds *ds; /* data structure for this acb */