Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys Use DMA from mbuf instead of copy in transmit.
details: https://anonhg.NetBSD.org/src/rev/dec6770499c1
branches: trunk
changeset: 499448:dec6770499c1
user: onoe <onoe%NetBSD.org@localhost>
date: Mon Nov 20 12:12:18 2000 +0000
description:
Use DMA from mbuf instead of copy in transmit.
Still use memcpy in receiving because we must use buffer fill mode
and many packets may share single receive buffer.
XXX: Workaround(?) for CXD3222: it fails to DMA for selfid packet according
to code placement. I'm not sure about the reason (cache? timing? bug?).
Fixed the bug: transmitter sometimes stop and OACTIVE bit of if_fw
never be cleared.
Fixed the bug: freeing free buffer.
Enable ieee1394_drain and ieee1394_watchdog for loss of fragment.
diffstat:
sys/dev/ieee1394/fwohci.c | 630 +++++++++++++++++++++++++-----------------
sys/dev/ieee1394/fwohcireg.h | 2 +
sys/dev/ieee1394/fwohcivar.h | 11 +-
sys/net/if_ieee1394.h | 24 +-
sys/net/if_ieee1394subr.c | 124 ++++++--
5 files changed, 480 insertions(+), 311 deletions(-)
diffs (truncated from 1461 to 300 lines):
diff -r b38c358718f6 -r dec6770499c1 sys/dev/ieee1394/fwohci.c
--- a/sys/dev/ieee1394/fwohci.c Mon Nov 20 11:52:37 2000 +0000
+++ b/sys/dev/ieee1394/fwohci.c Mon Nov 20 12:12:18 2000 +0000
@@ -78,9 +78,12 @@
static void fwohci_shutdown(void *);
static int fwohci_desc_alloc(struct fwohci_softc *);
+static struct fwohci_desc *fwohci_desc_get(struct fwohci_softc *, int);
+static void fwohci_desc_put(struct fwohci_softc *, struct fwohci_desc *, int);
static int fwohci_ctx_alloc(struct fwohci_softc *, struct fwohci_ctx **,
int, int);
+static void fwohci_ctx_free(struct fwohci_softc *, struct fwohci_ctx *);
static void fwohci_ctx_init(struct fwohci_softc *, struct fwohci_ctx *);
static int fwohci_buf_alloc(struct fwohci_softc *, struct fwohci_buf *);
@@ -109,7 +112,7 @@
static int fwohci_at_output(struct fwohci_softc *, struct fwohci_ctx *,
struct fwohci_pkt *);
-static void fwohci_at_done(struct fwohci_softc *, struct fwohci_ctx *);
+static void fwohci_at_done(struct fwohci_softc *, struct fwohci_ctx *, int);
static void fwohci_atrs_output(struct fwohci_softc *, int, struct fwohci_pkt *,
struct fwohci_pkt *);
@@ -253,15 +256,16 @@
OHCI_CTX_ASYNC_RX_REQUEST);
fwohci_ctx_alloc(sc, &sc->sc_ctx_arrs, OHCI_BUF_ARRS_CNT,
OHCI_CTX_ASYNC_RX_RESPONSE);
- fwohci_ctx_alloc(sc, &sc->sc_ctx_atrq, OHCI_BUF_ATRQ_CNT,
- OHCI_CTX_ASYNC_TX_REQUEST);
- fwohci_ctx_alloc(sc, &sc->sc_ctx_atrs, OHCI_BUF_ATRS_CNT,
- OHCI_CTX_ASYNC_TX_RESPONSE);
+ fwohci_ctx_alloc(sc, &sc->sc_ctx_atrq, 0, OHCI_CTX_ASYNC_TX_REQUEST);
+ fwohci_ctx_alloc(sc, &sc->sc_ctx_atrs, 0, OHCI_CTX_ASYNC_TX_RESPONSE);
sc->sc_ctx_ir = malloc(sizeof(sc->sc_ctx_ir[0]) * sc->sc_isoctx,
M_DEVBUF, M_WAITOK);
for (i = 0; i < sc->sc_isoctx; i++) {
+ sc->sc_ctx_ir[i] = NULL;
+#if 0
fwohci_ctx_alloc(sc, &sc->sc_ctx_ir[i], OHCI_BUF_IR_CNT, i);
- sc->sc_ctx_ir[i]->fc_ppbmode = 1;
+ sc->sc_ctx_ir[i]->fc_isoch = 1;
+#endif
}
/*
@@ -381,7 +385,9 @@
*/
OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskClear,
OHCI_Int_BusReset);
+ intmask &= OHCI_Int_SelfIDComplete;
fwohci_buf_stop(sc);
+ fwohci_buf_init(sc);
if (sc->sc_uidtbl != NULL) {
free(sc->sc_uidtbl, M_DEVBUF);
sc->sc_uidtbl = NULL;
@@ -389,14 +395,27 @@
callout_reset(&sc->sc_selfid_callout,
OHCI_SELFID_TIMEOUT,
(void (*)(void *))fwohci_phy_busreset, sc);
+ sc->sc_nodeid = 0xffff; /* indicate invalid */
sc->sc_rootid = 0;
sc->sc_irmid = IEEE1394_BCAST_PHY_ID;
}
+ if (intmask & OHCI_Int_SelfIDComplete) {
+ OHCI_CSR_WRITE(sc, OHCI_REG_IntEventClear,
+ OHCI_Int_BusReset);
+ OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet,
+ OHCI_Int_BusReset);
+ callout_stop(&sc->sc_selfid_callout);
+ if (fwohci_selfid_input(sc) == 0) {
+ fwohci_buf_start(sc);
+ fwohci_uid_collect(sc);
+ }
+ }
+
if (intmask & OHCI_Int_ReqTxComplete)
- fwohci_at_done(sc, sc->sc_ctx_atrq);
+ fwohci_at_done(sc, sc->sc_ctx_atrq, 0);
if (intmask & OHCI_Int_RespTxComplete)
- fwohci_at_done(sc, sc->sc_ctx_atrs);
+ fwohci_at_done(sc, sc->sc_ctx_atrs, 0);
if (intmask & OHCI_Int_RQPkt)
fwohci_arrq_input(sc, sc->sc_ctx_arrq);
if (intmask & OHCI_Int_RSPkt)
@@ -410,24 +429,11 @@
iso = OHCI_CSR_READ(sc, OHCI_REG_IsoRecvIntEventClear);
OHCI_CSR_WRITE(sc, OHCI_REG_IsoRecvIntEventClear, iso);
for (i = 0; i < sc->sc_isoctx; i++) {
- if (iso & (1 << i))
+ if ((iso & (1<<i)) && sc->sc_ctx_ir[i] != NULL)
fwohci_ir_input(sc, sc->sc_ctx_ir[i]);
}
}
- if (intmask & OHCI_Int_SelfIDComplete) {
- if (fwohci_selfid_input(sc) == 0) {
- callout_stop(&sc->sc_selfid_callout);
- OHCI_CSR_WRITE(sc, OHCI_REG_IntEventClear,
- OHCI_Int_BusReset);
- OHCI_CSR_WRITE(sc, OHCI_REG_IntMaskSet,
- OHCI_Int_BusReset);
- fwohci_buf_init(sc);
- fwohci_buf_start(sc);
- fwohci_uid_collect(sc);
- }
- }
-
if (!progress) {
sc->sc_intrcnt.ev_count++;
progress = 1;
@@ -744,61 +750,95 @@
static int
fwohci_desc_alloc(struct fwohci_softc *sc)
{
- int error;
+ int error, mapsize, dsize;
/*
* allocate descriptor buffer
*/
- sc->sc_descsize = sizeof(struct fwohci_desc) *
- (OHCI_BUF_ARRQ_CNT + OHCI_BUF_ARRS_CNT +
+ sc->sc_descsize = OHCI_BUF_ARRQ_CNT + OHCI_BUF_ARRS_CNT +
OHCI_BUF_ATRQ_CNT + OHCI_BUF_ATRS_CNT +
- OHCI_BUF_IR_CNT * sc->sc_isoctx + 2);
+ OHCI_BUF_IR_CNT * sc->sc_isoctx + 2;
+ dsize = sizeof(struct fwohci_desc) * sc->sc_descsize;
+ mapsize = howmany(sc->sc_descsize, NBBY);
+ sc->sc_descmap = malloc(mapsize, M_DEVBUF, M_WAITOK);
+ memset(sc->sc_descmap, 0, mapsize);
- if ((error = bus_dmamem_alloc(sc->sc_dmat, sc->sc_descsize,
- PAGE_SIZE, 0, &sc->sc_dseg, 1, &sc->sc_dnseg, 0)) != 0) {
+ if ((error = bus_dmamem_alloc(sc->sc_dmat, dsize, PAGE_SIZE, 0,
+ &sc->sc_dseg, 1, &sc->sc_dnseg, 0)) != 0) {
printf("%s: unable to allocate descriptor buffer, error = %d\n",
sc->sc_sc1394.sc1394_dev.dv_xname, error);
goto fail_0;
}
if ((error = bus_dmamem_map(sc->sc_dmat, &sc->sc_dseg, sc->sc_dnseg,
- sc->sc_descsize, (caddr_t *)&sc->sc_desc,
- BUS_DMA_COHERENT|BUS_DMA_WAITOK)) != 0) {
+ dsize, (caddr_t *)&sc->sc_desc, BUS_DMA_COHERENT | BUS_DMA_WAITOK))
+ != 0) {
printf("%s: unable to map descriptor buffer, error = %d\n",
sc->sc_sc1394.sc1394_dev.dv_xname, error);
goto fail_1;
}
- if ((error = bus_dmamap_create(sc->sc_dmat, sc->sc_descsize,
- sc->sc_dnseg, sc->sc_descsize, 0, BUS_DMA_WAITOK, &sc->sc_ddmamap))
- != 0) {
+ if ((error = bus_dmamap_create(sc->sc_dmat, dsize, sc->sc_dnseg,
+ sc->sc_descsize, 0, BUS_DMA_WAITOK, &sc->sc_ddmamap)) != 0) {
printf("%s: unable to create descriptor buffer DMA map, "
"error = %d\n", sc->sc_sc1394.sc1394_dev.dv_xname, error);
goto fail_2;
}
if ((error = bus_dmamap_load(sc->sc_dmat, sc->sc_ddmamap, sc->sc_desc,
- sc->sc_descsize, NULL, BUS_DMA_WAITOK)) != 0) {
+ dsize, NULL, BUS_DMA_WAITOK)) != 0) {
printf("%s: unable to load descriptor buffer DMA map, "
"error = %d\n", sc->sc_sc1394.sc1394_dev.dv_xname, error);
goto fail_3;
}
- sc->sc_descfree = sc->sc_desc;
-
return 0;
fail_3:
bus_dmamap_destroy(sc->sc_dmat, sc->sc_ddmamap);
fail_2:
- bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_desc, sc->sc_descsize);
+ bus_dmamem_unmap(sc->sc_dmat, (caddr_t)sc->sc_desc, dsize);
fail_1:
bus_dmamem_free(sc->sc_dmat, &sc->sc_dseg, sc->sc_dnseg);
fail_0:
return error;
}
+static struct fwohci_desc *
+fwohci_desc_get(struct fwohci_softc *sc, int ndesc)
+{
+ int i, n;
+
+ for (n = 0; n <= sc->sc_descsize - ndesc; n++) {
+ for (i = 0; ; i++) {
+ if (i == ndesc) {
+ for (i = 0; i < ndesc; i++)
+ setbit(sc->sc_descmap, n + i);
+ return sc->sc_desc + n;
+ }
+ if (isset(sc->sc_descmap, n + i))
+ break;
+ }
+ }
+ return NULL;
+}
+
+static void
+fwohci_desc_put(struct fwohci_softc *sc, struct fwohci_desc *fd, int ndesc)
+{
+ int i, n;
+
+ n = fd - sc->sc_desc;
+ for (i = 0; i < ndesc; i++, n++) {
+#ifdef DIAGNOSTICS
+ if (isclr(sc->sc_descmap, n))
+ panic("fwohci_desc_put: duplicated free");
+#endif
+ clrbit(sc->sc_descmap, n);
+ }
+}
+
/*
* Asyncronous/Isochronous Transmit/Receive Context
*/
@@ -815,20 +855,16 @@
memset(fc, 0, sizeof(*fc) + sizeof(*fb) * bufcnt);
LIST_INIT(&fc->fc_handler);
TAILQ_INIT(&fc->fc_buf);
- TAILQ_INIT(&fc->fc_busy);
fc->fc_ctx = ctx;
fc->fc_bufcnt = bufcnt;
fb = (struct fwohci_buf *)&fc[1];
for (i = 0; i < bufcnt; i++, fb++) {
if ((error = fwohci_buf_alloc(sc, fb)) != 0)
goto fail;
-#ifdef DIAGNOSTICS
- if ((caddr_t)sc->sc_descfree >=
- (caddr_t)sc->sc_desc + sc->sc_descsize)
- panic("fwohci_ctx_alloc: descriptor exhausted: %d\n",
- sc->sc_descfree - sc->sc_desc);
-#endif
- fd = sc->sc_descfree++;
+ if ((fd = fwohci_desc_get(sc, 1)) == NULL) {
+ error = ENOBUFS;
+ goto fail;
+ }
fb->fb_desc = fd;
fb->fb_daddr = sc->sc_ddmamap->dm_segs[0].ds_addr +
((caddr_t)fd - (caddr_t)sc->sc_desc);
@@ -849,10 +885,27 @@
}
static void
+fwohci_ctx_free(struct fwohci_softc *sc, struct fwohci_ctx *fc)
+{
+ struct fwohci_buf *fb;
+ struct fwohci_handler *fh;
+
+ while ((fh = LIST_FIRST(&fc->fc_handler)) != NULL)
+ fwohci_handler_set(sc, fh->fh_tcode, fh->fh_key1, fh->fh_key2,
+ NULL, NULL);
+ while ((fb = TAILQ_FIRST(&fc->fc_buf)) != NULL) {
+ TAILQ_REMOVE(&fc->fc_buf, fb, fb_list);
+ fwohci_buf_free(sc, fb);
+ }
+ free(fc, M_DEVBUF);
+}
+
+static void
fwohci_ctx_init(struct fwohci_softc *sc, struct fwohci_ctx *fc)
{
struct fwohci_buf *fb, *nfb;
struct fwohci_desc *fd;
+ int n;
for (fb = TAILQ_FIRST(&fc->fc_buf); fb != NULL; fb = nfb) {
nfb = TAILQ_NEXT(fb, fb_list);
@@ -861,6 +914,23 @@
fd->fd_branch = (nfb != NULL) ? (nfb->fb_daddr | 1) : 0;
fd->fd_rescount = fd->fd_reqcount;
}
+
+ n = fc->fc_ctx;
+ fb = TAILQ_FIRST(&fc->fc_buf);
+ if (fc->fc_isoch) {
+ OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_CommandPtr,
+ fb->fb_daddr | 1);
+ OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextControlClear,
+ OHCI_CTXCTL_RX_BUFFER_FILL |
+ OHCI_CTXCTL_RX_CYCLE_MATCH_ENABLE |
+ OHCI_CTXCTL_RX_MULTI_CHAN_MODE |
+ OHCI_CTXCTL_RX_DUAL_BUFFER_MODE);
+ OHCI_SYNC_RX_DMA_WRITE(sc, n, OHCI_SUBREG_ContextControlSet,
+ OHCI_CTXCTL_RX_ISOCH_HEADER);
+ } else {
+ OHCI_ASYNC_DMA_WRITE(sc, n, OHCI_SUBREG_CommandPtr,
+ fb->fb_daddr | 1);
+ }
}
Home |
Main Index |
Thread Index |
Old Index