Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/sys/dev/pci msk(4): add 64-bit DMA support



details:   https://anonhg.NetBSD.org/src/rev/3220a70a1cf7
branches:  trunk
changeset: 433435:3220a70a1cf7
user:      jakllsch <jakllsch%NetBSD.org@localhost>
date:      Fri Sep 14 18:46:47 2018 +0000

description:
msk(4): add 64-bit DMA support

portions of this change set provided by mrg@

diffstat:

 sys/dev/pci/if_msk.c    |  219 +++++++++++++++++++++++++++++++++++------------
 sys/dev/pci/if_mskvar.h |   16 +-
 sys/dev/pci/if_skreg.h  |    4 +-
 3 files changed, 175 insertions(+), 64 deletions(-)

diffs (truncated from 447 to 300 lines):

diff -r 960a439aa0ed -r 3220a70a1cf7 sys/dev/pci/if_msk.c
--- a/sys/dev/pci/if_msk.c      Fri Sep 14 13:47:14 2018 +0000
+++ b/sys/dev/pci/if_msk.c      Fri Sep 14 18:46:47 2018 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_msk.c,v 1.77 2018/09/12 13:52:36 jakllsch Exp $ */
+/* $NetBSD: if_msk.c,v 1.78 2018/09/14 18:46:47 jakllsch Exp $ */
 /*     $OpenBSD: if_msk.c,v 1.79 2009/10/15 17:54:56 deraadt Exp $     */
 
 /*
@@ -52,7 +52,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_msk.c,v 1.77 2018/09/12 13:52:36 jakllsch Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_msk.c,v 1.78 2018/09/14 18:46:47 jakllsch Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
@@ -150,6 +150,9 @@
 static int msk_sysctl_handler(SYSCTLFN_PROTO);
 static int msk_root_num;
 
+#define MSK_ADDR_LO(x)  ((uint64_t) (x) & 0xffffffffUL)
+#define MSK_ADDR_HI(x)  ((uint64_t) (x) >> 32)
+
 /* supported device vendors */
 static const struct msk_product {
        pci_vendor_id_t         msk_vendor;
@@ -409,6 +412,7 @@
 {
        struct msk_chain_data   *cd = &sc_if->sk_cdata;
        struct msk_ring_data    *rd = sc_if->sk_rdata;
+       struct msk_rx_desc      *r;
        int                     i, nexti;
 
        memset(rd->sk_rx_ring, 0, sizeof(struct msk_rx_desc) * MSK_RX_RING_CNT);
@@ -426,6 +430,18 @@
        sc_if->sk_cdata.sk_rx_cons = 0;
        sc_if->sk_cdata.sk_rx_cnt = 0;
 
+       /* Mark the first ring element to initialize the high address. */
+       sc_if->sk_cdata.sk_rx_hiaddr = 0;
+       r = &rd->sk_rx_ring[cd->sk_rx_prod];
+       r->sk_addr = htole32(cd->sk_rx_hiaddr);
+       r->sk_len = 0;
+       r->sk_ctl = 0;
+       r->sk_opcode = SK_Y2_BMUOPC_ADDR64 | SK_Y2_RXOPC_OWN;
+       MSK_CDRXSYNC(sc_if, cd->sk_rx_prod,
+           BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
+       SK_INC(sc_if->sk_cdata.sk_rx_prod, MSK_RX_RING_CNT);
+       sc_if->sk_cdata.sk_rx_cnt++;
+
        msk_fill_rx_ring(sc_if);
        return (0);
 }
@@ -436,6 +452,7 @@
        struct sk_softc         *sc = sc_if->sk_softc;
        struct msk_chain_data   *cd = &sc_if->sk_cdata;
        struct msk_ring_data    *rd = sc_if->sk_rdata;
+       struct msk_tx_desc      *t;
        bus_dmamap_t            dmamap;
        struct sk_txmap_entry   *entry;
        int                     i, nexti;
@@ -468,8 +485,17 @@
        sc_if->sk_cdata.sk_tx_cons = 0;
        sc_if->sk_cdata.sk_tx_cnt = 0;
 
+       /* Mark the first ring element to initialize the high address. */
+       sc_if->sk_cdata.sk_tx_hiaddr = 0;
+       t = &rd->sk_tx_ring[cd->sk_tx_prod];
+       t->sk_addr = htole32(cd->sk_tx_hiaddr);
+       t->sk_len = 0;
+       t->sk_ctl = 0;
+       t->sk_opcode = SK_Y2_BMUOPC_ADDR64 | SK_Y2_TXOPC_OWN;
        MSK_CDTXSYNC(sc_if, 0, MSK_TX_RING_CNT,
            BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
+       SK_INC(sc_if->sk_cdata.sk_tx_prod, MSK_TX_RING_CNT);
+       sc_if->sk_cdata.sk_tx_cnt++;
 
        return (0);
 }
@@ -480,7 +506,8 @@
        struct mbuf             *m_new = NULL;
        struct sk_chain         *c;
        struct msk_rx_desc      *r;
-       void *buf = NULL;
+       void                    *buf = NULL;
+       bus_addr_t              addr;
 
        MGETHDR(m_new, M_DONTWAIT, MT_DATA);
        if (m_new == NULL)
@@ -501,12 +528,34 @@
 
        m_adj(m_new, ETHER_ALIGN);
 
+       addr = dmamap->dm_segs[0].ds_addr +
+                 ((vaddr_t)m_new->m_data -
+                  (vaddr_t)sc_if->sk_cdata.sk_jumbo_buf);
+
+       if (sc_if->sk_cdata.sk_rx_hiaddr != MSK_ADDR_HI(addr)) {
+               c = &sc_if->sk_cdata.sk_rx_chain[sc_if->sk_cdata.sk_rx_prod];
+               r = c->sk_le;
+               c->sk_mbuf = NULL;
+               r->sk_addr = htole32(MSK_ADDR_HI(addr));
+               r->sk_len = 0;
+               r->sk_ctl = 0;
+               r->sk_opcode = SK_Y2_BMUOPC_ADDR64 | SK_Y2_RXOPC_OWN;
+               sc_if->sk_cdata.sk_rx_hiaddr = MSK_ADDR_HI(addr);
+
+               MSK_CDRXSYNC(sc_if, sc_if->sk_cdata.sk_rx_prod,
+                   BUS_DMASYNC_PREWRITE|BUS_DMASYNC_PREREAD);
+
+               SK_INC(sc_if->sk_cdata.sk_rx_prod, MSK_RX_RING_CNT);
+               sc_if->sk_cdata.sk_rx_cnt++;
+
+               DPRINTFN(10, ("%s: rx ADDR64: %#x\n",
+                   sc_if->sk_ethercom.ec_if.if_xname, (unsigned)MSK_ADDR_HI(addr)));
+       }
+
        c = &sc_if->sk_cdata.sk_rx_chain[sc_if->sk_cdata.sk_rx_prod];
        r = c->sk_le;
        c->sk_mbuf = m_new;
-       r->sk_addr = htole32(dmamap->dm_segs[0].ds_addr +
-           (((vaddr_t)m_new->m_data
-           - (vaddr_t)sc_if->sk_cdata.sk_jumbo_buf)));
+       r->sk_addr = htole32(MSK_ADDR_LO(addr));
        r->sk_len = htole16(SK_JLEN);
        r->sk_ctl = 0;
        r->sk_opcode = SK_Y2_RXOPC_PACKET | SK_Y2_RXOPC_OWN;
@@ -702,7 +751,7 @@
 
        s = splnet();
 
-       DPRINTFN(2, ("msk_ioctl ETHER\n"));
+       DPRINTFN(2, ("msk_ioctl ETHER cmd %lx\n", cmd));
        switch (cmd) {
        case SIOCSIFFLAGS:
                if ((error = ifioctl_common(ifp, cmd, data)) != 0)
@@ -1101,17 +1150,19 @@
         * give the receiver 2/3 of the memory (rounded down), and the
         * transmitter whatever remains.
         */
-       chunk = (2 * (sc->sk_ramsize / sizeof(u_int64_t)) / 3) & ~0xff;
-       sc_if->sk_rx_ramstart = 0;
-       sc_if->sk_rx_ramend = sc_if->sk_rx_ramstart + chunk - 1;
-       chunk = (sc->sk_ramsize / sizeof(u_int64_t)) - chunk;
-       sc_if->sk_tx_ramstart = sc_if->sk_rx_ramend + 1;
-       sc_if->sk_tx_ramend = sc_if->sk_tx_ramstart + chunk - 1;
-
-       DPRINTFN(2, ("msk_attach: rx_ramstart=%#x rx_ramend=%#x\n"
-                    "           tx_ramstart=%#x tx_ramend=%#x\n",
-                    sc_if->sk_rx_ramstart, sc_if->sk_rx_ramend,
-                    sc_if->sk_tx_ramstart, sc_if->sk_tx_ramend));
+       if (sc->sk_ramsize) {
+               chunk = (2 * (sc->sk_ramsize / sizeof(u_int64_t)) / 3) & ~0xff;
+               sc_if->sk_rx_ramstart = 0;
+               sc_if->sk_rx_ramend = sc_if->sk_rx_ramstart + chunk - 1;
+               chunk = (sc->sk_ramsize / sizeof(u_int64_t)) - chunk;
+               sc_if->sk_tx_ramstart = sc_if->sk_rx_ramend + 1;
+               sc_if->sk_tx_ramend = sc_if->sk_tx_ramstart + chunk - 1;
+
+               DPRINTFN(2, ("msk_attach: rx_ramstart=%#x rx_ramend=%#x\n"
+                            "           tx_ramstart=%#x tx_ramend=%#x\n",
+                            sc_if->sk_rx_ramstart, sc_if->sk_rx_ramend,
+                            sc_if->sk_tx_ramstart, sc_if->sk_tx_ramend));
+       }
 
        /* Allocate the descriptor queues. */
        if (bus_dmamem_alloc(sc->sc_dmatag, sizeof(struct msk_ring_data),
@@ -1360,7 +1411,10 @@
                return;
        }
 
-       sc->sc_dmatag = pa->pa_dmat;
+       if (pci_dma64_available(pa))
+               sc->sc_dmatag = pa->pa_dmat64;
+       else
+               sc->sc_dmatag = pa->pa_dmat;
 
        command = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
        command |= PCI_COMMAND_MASTER_ENABLE;
@@ -1714,10 +1768,12 @@
 {
        struct sk_softc         *sc = sc_if->sk_softc;
        struct msk_tx_desc              *f = NULL;
-       u_int32_t               frag, cur;
-       int                     i;
+       u_int32_t               frag, cur, hiaddr, old_hiaddr, total;
+       u_int32_t               entries = 0;
+       size_t                  i;
        struct sk_txmap_entry   *entry;
        bus_dmamap_t            txmap;
+       bus_addr_t              addr;
 
        DPRINTFN(2, ("msk_encap\n"));
 
@@ -1746,30 +1802,68 @@
                return (ENOBUFS);
        }
 
-       if (txmap->dm_nsegs > (MSK_TX_RING_CNT - sc_if->sk_cdata.sk_tx_cnt - 2)) {
+       /* Count how many tx descriptors needed. */
+       hiaddr = sc_if->sk_cdata.sk_tx_hiaddr;
+       for (total = i = 0; i < txmap->dm_nsegs; i++) {
+               if (hiaddr != MSK_ADDR_HI(txmap->dm_segs[i].ds_addr)) {
+                       hiaddr = MSK_ADDR_HI(txmap->dm_segs[i].ds_addr);
+                       total++;
+               }
+               total++;
+       }
+
+       if (total > MSK_TX_RING_CNT - sc_if->sk_cdata.sk_tx_cnt - 2) {
                DPRINTFN(2, ("msk_encap: too few descriptors free\n"));
                bus_dmamap_unload(sc->sc_dmatag, txmap);
                return (ENOBUFS);
        }
 
-       DPRINTFN(2, ("msk_encap: dm_nsegs=%d\n", txmap->dm_nsegs));
+       DPRINTFN(2, ("msk_encap: dm_nsegs=%d total desc=%u\n",
+           txmap->dm_nsegs, total));
 
        /* Sync the DMA map. */
        bus_dmamap_sync(sc->sc_dmatag, txmap, 0, txmap->dm_mapsize,
            BUS_DMASYNC_PREWRITE);
 
+       old_hiaddr = sc_if->sk_cdata.sk_tx_hiaddr;
        for (i = 0; i < txmap->dm_nsegs; i++) {
+               addr = txmap->dm_segs[i].ds_addr;
+               DPRINTFN(2, ("msk_encap: addr %llx\n",
+                   (unsigned long long)addr));
+               hiaddr = MSK_ADDR_HI(addr);
+
+               if (sc_if->sk_cdata.sk_tx_hiaddr != hiaddr) {
+                       f = &sc_if->sk_rdata->sk_tx_ring[frag];
+                       f->sk_addr = htole32(hiaddr);
+                       f->sk_len = 0;
+                       f->sk_ctl = 0;
+                       if (i == 0)
+                               f->sk_opcode = SK_Y2_BMUOPC_ADDR64;
+                       else
+                               f->sk_opcode = SK_Y2_BMUOPC_ADDR64 | SK_Y2_TXOPC_OWN;
+                       sc_if->sk_cdata.sk_tx_hiaddr = hiaddr;
+                       SK_INC(frag, MSK_TX_RING_CNT);
+                       entries++;
+                       DPRINTFN(10, ("%s: tx ADDR64: %#x\n",
+                           sc_if->sk_ethercom.ec_if.if_xname, hiaddr));
+               }
+
                f = &sc_if->sk_rdata->sk_tx_ring[frag];
-               f->sk_addr = htole32(txmap->dm_segs[i].ds_addr);
+               f->sk_addr = htole32(MSK_ADDR_LO(addr));
                f->sk_len = htole16(txmap->dm_segs[i].ds_len);
                f->sk_ctl = 0;
-               if (i == 0)
-                       f->sk_opcode = SK_Y2_TXOPC_PACKET;
-               else
+               if (i == 0) {
+                       if (hiaddr != old_hiaddr)
+                               f->sk_opcode = SK_Y2_TXOPC_PACKET | SK_Y2_TXOPC_OWN;
+                       else
+                               f->sk_opcode = SK_Y2_TXOPC_PACKET;
+               } else
                        f->sk_opcode = SK_Y2_TXOPC_BUFFER | SK_Y2_TXOPC_OWN;
                cur = frag;
                SK_INC(frag, MSK_TX_RING_CNT);
+               entries++;
        }
+       KASSERTMSG(entries == total, "entries %u total %u", entries, total);
 
        sc_if->sk_cdata.sk_tx_chain[cur].sk_mbuf = m_head;
        SIMPLEQ_REMOVE_HEAD(&sc_if->sk_txmap_head, link);
@@ -1778,7 +1872,7 @@
        sc_if->sk_rdata->sk_tx_ring[cur].sk_ctl |= SK_Y2_TXCTL_LASTFRAG;
 
        /* Sync descriptors before handing to chip */
-       MSK_CDTXSYNC(sc_if, *txidx, txmap->dm_nsegs,
+       MSK_CDTXSYNC(sc_if, *txidx, entries,
            BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
 
        sc_if->sk_rdata->sk_tx_ring[*txidx].sk_opcode |= SK_Y2_TXOPC_OWN;
@@ -1787,7 +1881,7 @@
        MSK_CDTXSYNC(sc_if, *txidx, 1,
            BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
 
-       sc_if->sk_cdata.sk_tx_cnt += txmap->dm_nsegs;
+       sc_if->sk_cdata.sk_tx_cnt += entries;
 
 #ifdef MSK_DEBUG
        if (mskdebug >= 2) {
@@ -1922,31 +2016,38 @@
        struct sk_softc         *sc = sc_if->sk_softc;
        struct ifnet            *ifp = &sc_if->sk_ethercom.ec_if;
        struct mbuf             *m;
-       struct sk_chain         *cur_rx;
-       int                     cur, total_len = len;
+       unsigned                cur, prod, tail, total_len = len;
        bus_dmamap_t            dmamap;
 
-       DPRINTFN(2, ("msk_rxeof\n"));
-



Home | Main Index | Thread Index | Old Index