Hi David,

I don't have your original message to reply to so I apologize if this doesn't 
appear as a reply to it.

I tried your patch (it worked), but I noticed a curious thing:
Linux uses both FIFOs but they only use the first data register [1].

So I slightly changed your patch to replicate the behavior 
(bus_space_write_multi_4(.., SXIE_TXIO0 , ...)) and set the max queue length to 
IFQ_MAXLENGTH.

I'm now getting the full 10MB/s transfer speed :-)  Also referencing the 
on-going conversation on arm@ [2] as there I had 1MB/s with only one FIFO.  
(CC-ing Artturi as maybe this is why it was fully working "at some point"?)

Many Thanks and hope this helps!
Eduard


[1] 
https://elixir.free-electrons.com/linux/v4.14/source/drivers/net/ethernet/allwinner/sun4i-emac.c#L452

[2] https://marc.info/?l=openbsd-arm&m=151116582730643&w=2

Index: sys/arch/armv7/sunxi/sxie.c
===================================================================
RCS file: /cvs/src/sys/arch/armv7/sunxi/sxie.c,v
retrieving revision 1.25
diff -u -p -r1.25 sxie.c
--- sys/arch/armv7/sunxi/sxie.c 22 Jan 2017 10:17:37 -0000      1.25
+++ sys/arch/armv7/sunxi/sxie.c 20 Nov 2017 11:30:09 -0000
@@ -250,7 +250,7 @@ sxie_attach(struct device *parent, struc
        ifp->if_watchdog = sxie_watchdog;
        ifp->if_capabilities = IFCAP_VLAN_MTU; /* XXX status check in recv? */
 
-       IFQ_SET_MAXLEN(&ifp->if_snd, 1);
+       IFQ_SET_MAXLEN(&ifp->if_snd, IFQ_MAXLEN);
 
        /* Initialize MII/media info. */
        mii = &sc->sc_mii;
@@ -439,16 +439,15 @@ sxie_intr(void *arg)
        }
 
        if (pending & (SXIE_TX_FIFO0 | SXIE_TX_FIFO1)) {
-               ifq_clr_oactive(&ifp->if_snd);
                sc->txf_inuse &= ~pending;
                if (sc->txf_inuse == 0)
                        ifp->if_timer = 0;
                else
                        ifp->if_timer = 5;
-       }
 
-       if (ifp->if_flags & IFF_RUNNING && !IFQ_IS_EMPTY(&ifp->if_snd))
-               sxie_start(ifp);
+               if (ifq_is_oactive(&ifp->if_snd))
+                       ifq_restart(&ifp->if_snd);
+       }
 
        SXISET4(sc, SXIE_INTCR, SXIE_INTR_ENABLE);
 
@@ -468,65 +467,59 @@ sxie_start(struct ifnet *ifp)
        uint32_t fifo;
        uint32_t txbuf[SXIE_MAX_PKT_SIZE / sizeof(uint32_t)]; /* XXX !!! */
 
-       if (sc->txf_inuse == (SXIE_TX_FIFO0 | SXIE_TX_FIFO1))
-               ifq_set_oactive(&ifp->if_snd);
-
        if (!(ifp->if_flags & IFF_RUNNING) || ifq_is_oactive(&ifp->if_snd))
                return;
 
+
        td = (uint8_t *)&txbuf[0];
        m = NULL;
        head = NULL;
-trynext:
-       m = ifq_deq_begin(&ifp->if_snd);
-       if (m == NULL)
-               return;
-
-       if (m->m_pkthdr.len > SXIE_MAX_PKT_SIZE) {
-               ifq_deq_commit(&ifp->if_snd, m);
-               printf("sxie_start: packet too big\n");
-               m_freem(m);
-               return;
-       }
 
-       if (sc->txf_inuse == (SXIE_TX_FIFO0 | SXIE_TX_FIFO1)) {
-               ifq_deq_rollback(&ifp->if_snd, m);
-               printf("sxie_start: tx fifos in use.\n");
-               ifq_set_oactive(&ifp->if_snd);
-               return;
-       }
-
-       /* select fifo */
-       if (sc->txf_inuse & SXIE_TX_FIFO0) {
-               sc->txf_inuse |= SXIE_TX_FIFO1;
-               fifo = 1;
-       } else {
-               sc->txf_inuse |= SXIE_TX_FIFO0;
-               fifo = 0;
-       }
-       SXIWRITE4(sc, SXIE_TXINS, fifo);
-
-       /* set packet length */
-       SXIWRITE4(sc, SXIE_TXPKTLEN0 + (fifo * 4), m->m_pkthdr.len);
-
-       /* copy the actual packet to fifo XXX through 'align buffer'.. */
-       m_copydata(m, 0, m->m_pkthdr.len, (caddr_t)td);
-       bus_space_write_multi_4(sc->sc_iot, sc->sc_ioh,
-           SXIE_TXIO0 + (fifo * 4),
-           (uint32_t *)td, SXIE_ROUNDUP(m->m_pkthdr.len, 4) >> 2);
-
-       /* transmit to PHY from fifo */
-       SXISET4(sc, SXIE_TXCR0 + (fifo * 4), 1);
-       ifp->if_timer = 5;
-       ifq_deq_commit(&ifp->if_snd, m);
+       for (;;) {
+               if (sc->txf_inuse == (SXIE_TX_FIFO0 | SXIE_TX_FIFO1)) {
+                       ifq_set_oactive(&ifp->if_snd);
+                       break;
+               }
+
+               m = ifq_dequeue(&ifp->if_snd);
+               if (m == NULL)
+                       break;
+
+               if (m->m_pkthdr.len > SXIE_MAX_PKT_SIZE) {
+                       m_freem(m);
+                       continue;
+               }
 
 #if NBPFILTER > 0
-       if (ifp->if_bpf)
-               bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
+               if (ifp->if_bpf)
+                       bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT);
 #endif
-       m_freem(m);
 
-       goto trynext;
+               /* select fifo */
+               if (sc->txf_inuse & SXIE_TX_FIFO0) {
+                       sc->txf_inuse |= SXIE_TX_FIFO1;
+                       fifo = 1;
+               } else {
+                       sc->txf_inuse |= SXIE_TX_FIFO0;
+                       fifo = 0;
+               }
+               SXIWRITE4(sc, SXIE_TXINS, fifo);
+
+               /* set packet length */
+               SXIWRITE4(sc, SXIE_TXPKTLEN0 + (fifo * 4), m->m_pkthdr.len);
+
+               /* copy the actual packet to fifo XXX through 'align buffer' */
+               m_copydata(m, 0, m->m_pkthdr.len, (caddr_t)td);
+               bus_space_write_multi_4(sc->sc_iot, sc->sc_ioh,
+                   SXIE_TXIO0,
+                   (uint32_t *)td, SXIE_ROUNDUP(m->m_pkthdr.len, 4) >> 2);
+
+               /* transmit to PHY from fifo */
+               SXISET4(sc, SXIE_TXCR0 + (fifo * 4), 1);
+               ifp->if_timer = 5;
+
+               m_freem(m);
+       }
 }
 
 void

Reply via email to