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)
This commit is contained in:
parent
e99b2da36f
commit
8df8a6ae3f
|
@ -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 <sys/cdefs.h>
|
||||
__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);
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue