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