summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
Diffstat (limited to 'sys')
-rw-r--r--sys/dev/fdt/if_dwge.c78
1 files changed, 42 insertions, 36 deletions
diff --git a/sys/dev/fdt/if_dwge.c b/sys/dev/fdt/if_dwge.c
index 3f2d24a0e6d..400807576b0 100644
--- a/sys/dev/fdt/if_dwge.c
+++ b/sys/dev/fdt/if_dwge.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: if_dwge.c,v 1.12 2021/10/24 17:52:26 mpi Exp $ */
+/* $OpenBSD: if_dwge.c,v 1.13 2021/12/20 04:21:32 jmatthew Exp $ */
/*
* Copyright (c) 2008, 2019 Mark Kettenis <kettenis@openbsd.org>
* Copyright (c) 2017 Patrick Wildt <patrick@blueri.se>
@@ -234,6 +234,7 @@ struct dwge_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
@@ -247,7 +248,6 @@ struct dwge_softc {
struct dwge_buf *sc_txbuf;
struct dwge_desc *sc_txdesc;
int sc_tx_prod;
- int sc_tx_cnt;
int sc_tx_cons;
struct dwge_dmamem *sc_rxring;
@@ -289,7 +289,7 @@ uint32_t dwge_read(struct dwge_softc *, bus_addr_t);
void dwge_write(struct dwge_softc *, bus_addr_t, uint32_t);
int dwge_ioctl(struct ifnet *, u_long, caddr_t);
-void dwge_start(struct ifnet *);
+void dwge_start(struct ifqueue *);
void dwge_watchdog(struct ifnet *);
int dwge_media_change(struct ifnet *);
@@ -312,7 +312,7 @@ void dwge_rx_proc(struct dwge_softc *);
void dwge_up(struct dwge_softc *);
void dwge_down(struct dwge_softc *);
void dwge_iff(struct dwge_softc *);
-int dwge_encap(struct dwge_softc *, struct mbuf *, int *);
+int dwge_encap(struct dwge_softc *, struct mbuf *, int *, int *);
void dwge_reset(struct dwge_softc *);
void dwge_stop_dma(struct dwge_softc *);
@@ -422,8 +422,9 @@ dwge_attach(struct device *parent, struct device *self, void *aux)
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 = dwge_ioctl;
- ifp->if_start = dwge_start;
+ ifp->if_qstart = dwge_start;
ifp->if_watchdog = dwge_watchdog;
ifq_set_maxlen(&ifp->if_snd, DWGE_NTXDESC - 1);
bcopy(sc->sc_dev.dv_xname, ifp->if_xname, IFNAMSIZ);
@@ -535,8 +536,10 @@ dwge_attach(struct device *parent, struct device *self, void *aux)
dwge_write(sc, GMAC_MMC_TX_INT_MSK, 0xffffffff);
dwge_write(sc, GMAC_MMC_IPC_INT_MSK, 0xffffffff);
- fdt_intr_establish(faa->fa_node, IPL_NET, dwge_intr, sc,
- sc->sc_dev.dv_xname);
+ sc->sc_ih = fdt_intr_establish(faa->fa_node, IPL_NET | IPL_MPSAFE,
+ dwge_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
@@ -612,11 +615,12 @@ dwge_lladdr_write(struct dwge_softc *sc)
}
void
-dwge_start(struct ifnet *ifp)
+dwge_start(struct ifqueue *ifq)
{
+ struct ifnet *ifp = ifq->ifq_if;
struct dwge_softc *sc = ifp->if_softc;
struct mbuf *m;
- int error, idx;
+ int error, idx, left, used;
if (!(ifp->if_flags & IFF_RUNNING))
return;
@@ -628,27 +632,29 @@ dwge_start(struct ifnet *ifp)
return;
idx = sc->sc_tx_prod;
- while ((sc->sc_txdesc[idx].sd_status & TDES0_OWN) == 0) {
- m = ifq_deq_begin(&ifp->if_snd);
- if (m == NULL)
+ left = sc->sc_tx_cons;
+ if (left <= idx)
+ left += DWGE_NTXDESC;
+ left -= idx;
+ used = 0;
+
+ for (;;) {
+ if (used + DWGE_NTXSEGS + 1 > left) {
+ ifq_set_oactive(ifq);
break;
+ }
- error = dwge_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 = dwge_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);
@@ -660,6 +666,8 @@ dwge_start(struct ifnet *ifp)
/* Set a timeout in case the chip goes out to lunch. */
ifp->if_timer = 5;
+
+ dwge_write(sc, GMAC_TX_POLL_DEMAND, 0xffffffff);
}
}
@@ -901,7 +909,7 @@ dwge_tx_proc(struct dwge_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 < DWGE_NTXDESC);
@@ -920,7 +928,6 @@ dwge_tx_proc(struct dwge_softc *sc)
}
txfree++;
- sc->sc_tx_cnt--;
if (sc->sc_tx_cons == (DWGE_NTXDESC - 1))
sc->sc_tx_cons = 0;
@@ -930,7 +937,7 @@ dwge_tx_proc(struct dwge_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) {
@@ -947,7 +954,7 @@ dwge_rx_proc(struct dwge_softc *sc)
struct dwge_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;
@@ -956,7 +963,9 @@ dwge_rx_proc(struct dwge_softc *sc)
DWGE_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 < DWGE_NRXDESC);
@@ -982,13 +991,14 @@ dwge_rx_proc(struct dwge_softc *sc)
ml_enqueue(&ml, m);
- if_rxr_put(&sc->sc_rx_ring, 1);
+ put++;
if (sc->sc_rx_cons == (DWGE_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);
@@ -1030,7 +1040,6 @@ dwge_up(struct dwge_softc *sc)
0, DWGE_DMA_LEN(sc->sc_txring), BUS_DMASYNC_PREWRITE);
sc->sc_tx_prod = sc->sc_tx_cons = 0;
- sc->sc_tx_cnt = 0;
dwge_write(sc, GMAC_TX_DESC_LIST_ADDR, DWGE_DMA_DVA(sc->sc_txring));
@@ -1123,6 +1132,9 @@ dwge_down(struct dwge_softc *sc)
dwge_write(sc, GMAC_INT_ENA, 0);
+ intr_barrier(sc->sc_ih);
+ ifq_barrier(&ifp->if_snd);
+
for (i = 0; i < DWGE_NTXDESC; i++) {
txb = &sc->sc_txbuf[i];
if (txb->tb_m) {
@@ -1208,7 +1220,7 @@ dwge_iff(struct dwge_softc *sc)
}
int
-dwge_encap(struct dwge_softc *sc, struct mbuf *m, int *idx)
+dwge_encap(struct dwge_softc *sc, struct mbuf *m, int *idx, int *used)
{
struct dwge_desc *txd, *txd_start;
bus_dmamap_t map;
@@ -1224,11 +1236,6 @@ dwge_encap(struct dwge_softc *sc, struct mbuf *m, int *idx)
return (EFBIG);
}
- if (map->dm_nsegs > (DWGE_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);
@@ -1262,15 +1269,14 @@ dwge_encap(struct dwge_softc *sc, struct mbuf *m, int *idx)
bus_dmamap_sync(sc->sc_dmat, DWGE_DMA_MAP(sc->sc_txring),
*idx * sizeof(*txd), sizeof(*txd), BUS_DMASYNC_PREWRITE);
- dwge_write(sc, GMAC_TX_POLL_DEMAND, 0xffffffff);
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);
}