On Mon, Jan 03, 2022 at 09:24:15PM +1000, Jonathan Matthew wrote: > This is almost identical to the changes I made to dwge(4) recently, since > these drivers are very closely related. Unfortunately the only machine I > have with dwxe(4) in it is armv7, so I can't test this properly, but it > does still work there. > > Could someone with an arm64 allwinner board try this out more extensively? >
Tested on my sopine with dwxe(4) on GENERIC.MP and it seems to work fine. > > Index: if_dwxe.c > =================================================================== > RCS file: /cvs/src/sys/dev/fdt/if_dwxe.c,v > retrieving revision 1.19 > diff -u -p -r1.19 if_dwxe.c > --- if_dwxe.c 24 Oct 2021 17:52:26 -0000 1.19 > +++ if_dwxe.c 3 Jan 2022 11:21:19 -0000 > @@ -275,6 +275,7 @@ struct dwxe_softc { > bus_space_tag_t sc_iot; > bus_space_handle_t sc_ioh; > bus_dma_tag_t sc_dmat; > + void *sc_ih; > > struct arpcom sc_ac; > #define sc_lladdr sc_ac.ac_enaddr > @@ -287,7 +288,6 @@ struct dwxe_softc { > struct dwxe_buf *sc_txbuf; > struct dwxe_desc *sc_txdesc; > int sc_tx_prod; > - int sc_tx_cnt; > int sc_tx_cons; > > struct dwxe_dmamem *sc_rxring; > @@ -322,7 +322,7 @@ uint32_t dwxe_read(struct dwxe_softc *, > void dwxe_write(struct dwxe_softc *, bus_addr_t, uint32_t); > > int dwxe_ioctl(struct ifnet *, u_long, caddr_t); > -void dwxe_start(struct ifnet *); > +void dwxe_start(struct ifqueue *); > void dwxe_watchdog(struct ifnet *); > > int dwxe_media_change(struct ifnet *); > @@ -345,7 +345,7 @@ void dwxe_rx_proc(struct dwxe_softc *); > void dwxe_up(struct dwxe_softc *); > void dwxe_down(struct dwxe_softc *); > void dwxe_iff(struct dwxe_softc *); > -int dwxe_encap(struct dwxe_softc *, struct mbuf *, int *); > +int dwxe_encap(struct dwxe_softc *, struct mbuf *, int *, int *); > > void dwxe_reset(struct dwxe_softc *); > void dwxe_stop_dma(struct dwxe_softc *); > @@ -431,8 +431,9 @@ dwxe_attach(struct device *parent, struc > ifp = &sc->sc_ac.ac_if; > ifp->if_softc = sc; > ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; > + ifp->if_xflags = IFXF_MPSAFE; > ifp->if_ioctl = dwxe_ioctl; > - ifp->if_start = dwxe_start; > + ifp->if_qstart = dwxe_start; > ifp->if_watchdog = dwxe_watchdog; > ifq_set_maxlen(&ifp->if_snd, DWXE_NTXDESC - 1); > bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ); > @@ -460,8 +461,10 @@ dwxe_attach(struct device *parent, struc > if_attach(ifp); > ether_ifattach(ifp); > > - fdt_intr_establish(faa->fa_node, IPL_NET, dwxe_intr, sc, > - sc->sc_dev.dv_xname); > + sc->sc_ih = fdt_intr_establish(faa->fa_node, IPL_NET | IPL_MPSAFE, > + dwxe_intr, sc, sc->sc_dev.dv_xname); > + if (sc->sc_ih == NULL) > + printf("%s: can't establish interrupt\n", sc->sc_dev.dv_xname); > } > > void > @@ -584,11 +587,12 @@ dwxe_lladdr_write(struct dwxe_softc *sc) > } > > void > -dwxe_start(struct ifnet *ifp) > +dwxe_start(struct ifqueue *ifq) > { > + struct ifnet *ifp = ifq->ifq_if; > struct dwxe_softc *sc = ifp->if_softc; > struct mbuf *m; > - int error, idx; > + int error, idx, left, used; > > if (!(ifp->if_flags & IFF_RUNNING)) > return; > @@ -600,27 +604,29 @@ dwxe_start(struct ifnet *ifp) > return; > > idx = sc->sc_tx_prod; > - while ((sc->sc_txdesc[idx].sd_status & DWXE_TX_DESC_CTL) == 0) { > - m = ifq_deq_begin(&ifp->if_snd); > - if (m == NULL) > + left = sc->sc_tx_cons; > + if (left <= idx) > + left += DWXE_NTXDESC; > + left -= idx; > + used = 0; > + > + for (;;) { > + if (used + DWXE_NTXSEGS + 1 > left) { > + ifq_set_oactive(ifq); > break; > + } > > - error = dwxe_encap(sc, m, &idx); > - if (error == ENOBUFS) { > - ifq_deq_rollback(&ifp->if_snd, m); > - ifq_set_oactive(&ifp->if_snd); > + m = ifq_dequeue(ifq); > + if (m == NULL) > break; > - } > + > + error = dwxe_encap(sc, m, &idx, &used); > if (error == EFBIG) { > - ifq_deq_commit(&ifp->if_snd, m); > m_freem(m); /* give up: drop it */ > ifp->if_oerrors++; > continue; > } > > - /* Now we are committed to transmit the packet. */ > - ifq_deq_commit(&ifp->if_snd, m); > - > #if NBPFILTER > 0 > if (ifp->if_bpf) > bpf_mtap(ifp->if_bpf, m, BPF_DIRECTION_OUT); > @@ -632,6 +638,9 @@ dwxe_start(struct ifnet *ifp) > > /* Set a timeout in case the chip goes out to lunch. */ > ifp->if_timer = 5; > + > + dwxe_write(sc, DWXE_TX_CTL1, dwxe_read(sc, > + DWXE_TX_CTL1) | DWXE_TX_CTL1_TX_DMA_START); > } > } > > @@ -877,7 +886,7 @@ dwxe_tx_proc(struct dwxe_softc *sc) > BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); > > txfree = 0; > - while (sc->sc_tx_cnt > 0) { > + while (sc->sc_tx_cons != sc->sc_tx_prod) { > idx = sc->sc_tx_cons; > KASSERT(idx < DWXE_NTXDESC); > > @@ -896,7 +905,6 @@ dwxe_tx_proc(struct dwxe_softc *sc) > } > > txfree++; > - sc->sc_tx_cnt--; > > if (sc->sc_tx_cons == (DWXE_NTXDESC - 1)) > sc->sc_tx_cons = 0; > @@ -906,7 +914,7 @@ dwxe_tx_proc(struct dwxe_softc *sc) > txd->sd_status = 0; > } > > - if (sc->sc_tx_cnt == 0) > + if (sc->sc_tx_cons == sc->sc_tx_prod) > ifp->if_timer = 0; > > if (txfree) { > @@ -923,7 +931,7 @@ dwxe_rx_proc(struct dwxe_softc *sc) > struct dwxe_buf *rxb; > struct mbuf_list ml = MBUF_LIST_INITIALIZER(); > struct mbuf *m; > - int idx, len; > + int idx, len, cnt, put; > > if ((ifp->if_flags & IFF_RUNNING) == 0) > return; > @@ -932,7 +940,9 @@ dwxe_rx_proc(struct dwxe_softc *sc) > DWXE_DMA_LEN(sc->sc_rxring), > BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE); > > - while (if_rxr_inuse(&sc->sc_rx_ring) > 0) { > + cnt = if_rxr_inuse(&sc->sc_rx_ring); > + put = 0; > + while (put < cnt) { > idx = sc->sc_rx_cons; > KASSERT(idx < DWXE_NRXDESC); > > @@ -959,13 +969,14 @@ dwxe_rx_proc(struct dwxe_softc *sc) > > ml_enqueue(&ml, m); > > - if_rxr_put(&sc->sc_rx_ring, 1); > + put++; > if (sc->sc_rx_cons == (DWXE_NRXDESC - 1)) > sc->sc_rx_cons = 0; > else > sc->sc_rx_cons++; > } > > + if_rxr_put(&sc->sc_rx_ring, put); > if (ifiq_input(&ifp->if_rcv, &ml)) > if_rxr_livelocked(&sc->sc_rx_ring); > > @@ -1005,7 +1016,6 @@ dwxe_up(struct dwxe_softc *sc) > 0, DWXE_DMA_LEN(sc->sc_txring), BUS_DMASYNC_PREWRITE); > > sc->sc_tx_prod = sc->sc_tx_cons = 0; > - sc->sc_tx_cnt = 0; > > dwxe_write(sc, DWXE_TX_DESC_LIST, DWXE_DMA_DVA(sc->sc_txring)); > > @@ -1103,6 +1113,9 @@ dwxe_down(struct dwxe_softc *sc) > > dwxe_write(sc, DWXE_INT_EN, 0); > > + intr_barrier(sc->sc_ih); > + ifq_barrier(&ifp->if_snd); > + > for (i = 0; i < DWXE_NTXDESC; i++) { > txb = &sc->sc_txbuf[i]; > if (txb->tb_m) { > @@ -1188,7 +1201,7 @@ dwxe_iff(struct dwxe_softc *sc) > } > > int > -dwxe_encap(struct dwxe_softc *sc, struct mbuf *m, int *idx) > +dwxe_encap(struct dwxe_softc *sc, struct mbuf *m, int *idx, int *used) > { > struct dwxe_desc *txd, *txd_start; > bus_dmamap_t map; > @@ -1204,11 +1217,6 @@ dwxe_encap(struct dwxe_softc *sc, struct > return (EFBIG); > } > > - if (map->dm_nsegs > (DWXE_NTXDESC - sc->sc_tx_cnt - 2)) { > - bus_dmamap_unload(sc->sc_dmat, map); > - return (ENOBUFS); > - } > - > /* Sync the DMA map. */ > bus_dmamap_sync(sc->sc_dmat, map, 0, map->dm_mapsize, > BUS_DMASYNC_PREWRITE); > @@ -1242,16 +1250,13 @@ dwxe_encap(struct dwxe_softc *sc, struct > bus_dmamap_sync(sc->sc_dmat, DWXE_DMA_MAP(sc->sc_txring), > *idx * sizeof(*txd), sizeof(*txd), BUS_DMASYNC_PREWRITE); > > - dwxe_write(sc, DWXE_TX_CTL1, dwxe_read(sc, > - DWXE_TX_CTL1) | DWXE_TX_CTL1_TX_DMA_START); > - > KASSERT(sc->sc_txbuf[cur].tb_m == NULL); > sc->sc_txbuf[*idx].tb_map = sc->sc_txbuf[cur].tb_map; > sc->sc_txbuf[cur].tb_map = map; > sc->sc_txbuf[cur].tb_m = m; > > - sc->sc_tx_cnt += map->dm_nsegs; > *idx = frag; > + *used += map->dm_nsegs; > > return (0); > } >