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);
>  }
>

Reply via email to