Restructure how the at_output dma map gets setup. Ask for a dma map that can

support up to the max ohci descriptor segments. Then attempt to fill it in
via a load. Use the number of segments filled in as the basis for figuring
out how many descriptors to supply to the ohci DMA engine.

XXX: Still needs to account for requests which because of splits may overflow
the 6 dma descriptors available today. For now this fixes cases where a
single 512 byte write was getting split into 2 dma segments from 1 incoming
iov request
This commit is contained in:
jmc 2002-12-09 09:09:54 +00:00
parent 2a3e786250
commit 4d74b607a2

View File

@ -1,4 +1,4 @@
/* $NetBSD: fwohci.c,v 1.65 2002/12/09 07:26:02 jmc Exp $ */
/* $NetBSD: fwohci.c,v 1.66 2002/12/09 09:09:54 jmc Exp $ */
/*-
* Copyright (c) 2000 The NetBSD Foundation, Inc.
@ -49,7 +49,7 @@
*/
#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: fwohci.c,v 1.65 2002/12/09 07:26:02 jmc Exp $");
__KERNEL_RCSID(0, "$NetBSD: fwohci.c,v 1.66 2002/12/09 09:09:54 jmc Exp $");
#define FWOHCI_WAIT_DEBUG 1
@ -2391,6 +2391,34 @@ fwohci_at_output(struct fwohci_softc *sc, struct fwohci_ctx *fc,
if (fc->fc_bufcnt > 50) /*XXX*/
return ENOBUFS;
fb = malloc(sizeof(*fb), M_DEVBUF, M_WAITOK);
if (ndesc > 2) {
if ((error = bus_dmamap_create(sc->sc_dmat, pkt->fp_dlen,
OHCI_DESC_MAX - 2, pkt->fp_dlen, 0, BUS_DMA_WAITOK,
&fb->fb_dmamap)) != 0) {
fwohci_desc_put(sc, fb->fb_desc, ndesc);
free(fb, M_DEVBUF);
return error;
}
if (pkt->fp_m != NULL)
error = bus_dmamap_load_mbuf(sc->sc_dmat, fb->fb_dmamap,
pkt->fp_m, BUS_DMA_WAITOK);
else
error = bus_dmamap_load_uio(sc->sc_dmat, fb->fb_dmamap,
&pkt->fp_uio, BUS_DMA_WAITOK);
if (error != 0) {
DPRINTFN(1, ("Can't load DMA map: %d\n", error));
bus_dmamap_destroy(sc->sc_dmat, fb->fb_dmamap);
fwohci_desc_put(sc, fb->fb_desc, ndesc);
free(fb, M_DEVBUF);
return error;
}
ndesc = fb->fb_dmamap->dm_nsegs + 2;
bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, 0, pkt->fp_dlen,
BUS_DMASYNC_PREWRITE);
}
fb->fb_nseg = ndesc;
fb->fb_desc = fwohci_desc_get(sc, ndesc);
if (fb->fb_desc == NULL) {
@ -2404,30 +2432,6 @@ fwohci_at_output(struct fwohci_softc *sc, struct fwohci_ctx *fc,
fb->fb_statuscb = pkt->fp_statuscb;
fb->fb_statusarg = pkt->fp_statusarg;
if (ndesc > 2) {
if ((error = bus_dmamap_create(sc->sc_dmat, pkt->fp_dlen, ndesc,
PAGE_SIZE, 0, BUS_DMA_WAITOK, &fb->fb_dmamap)) != 0) {
fwohci_desc_put(sc, fb->fb_desc, ndesc);
free(fb, M_DEVBUF);
return error;
}
if (pkt->fp_m != NULL)
error = bus_dmamap_load_mbuf(sc->sc_dmat, fb->fb_dmamap,
pkt->fp_m, BUS_DMA_WAITOK);
else
error = bus_dmamap_load_uio(sc->sc_dmat, fb->fb_dmamap,
&pkt->fp_uio, BUS_DMA_WAITOK);
if (error != 0) {
bus_dmamap_destroy(sc->sc_dmat, fb->fb_dmamap);
fwohci_desc_put(sc, fb->fb_desc, ndesc);
free(fb, M_DEVBUF);
return error;
}
bus_dmamap_sync(sc->sc_dmat, fb->fb_dmamap, 0, pkt->fp_dlen,
BUS_DMASYNC_PREWRITE);
}
fd = fb->fb_desc;
fd->fd_flags = OHCI_DESC_IMMED;
fd->fd_reqcount = pkt->fp_hlen;