-/* $OpenBSD: if_mvneta.c,v 1.22 2022/06/01 03:51:19 dlg Exp $ */
+/* $OpenBSD: if_mvneta.c,v 1.23 2022/06/01 04:31:08 dlg Exp $ */
/* $NetBSD: if_mvneta.c,v 1.41 2015/04/15 10:15:40 hsuenaga Exp $ */
/*
* Copyright (c) 2007, 2008, 2013 KIYOHARA Takashi
struct mvneta_dmamem *sc_rxring;
struct mvneta_buf *sc_rxbuf;
struct mvneta_rx_desc *sc_rxdesc;
- int sc_rx_prod; /* next rx desc to fill */
+ unsigned int sc_rx_prod; /* next rx desc to fill */
+ unsigned int sc_rx_cons; /* next rx desc recvd */
struct if_rxring sc_rx_ring;
- int sc_rx_cons; /* next rx desc recvd */
enum {
PHY_MODE_QSGMII,
struct mbuf_list ml = MBUF_LIST_INITIALIZER();
struct mbuf *m;
uint32_t rxstat;
- int i, idx, len, ready;
+ unsigned int i, done, cons;
- DPRINTFN(3, ("%s: %d\n", __func__, sc->sc_rx_cons));
-
- if (!(ifp->if_flags & IFF_RUNNING))
+ done = MVNETA_PRXS_ODC(MVNETA_READ(sc, MVNETA_PRXS(0)));
+ if (done == 0)
return;
- bus_dmamap_sync(sc->sc_dmat, MVNETA_DMA_MAP(sc->sc_rxring), 0,
- MVNETA_DMA_LEN(sc->sc_rxring),
- BUS_DMASYNC_POSTREAD | BUS_DMASYNC_POSTWRITE);
-
- ready = MVNETA_PRXS_ODC(MVNETA_READ(sc, MVNETA_PRXS(0)));
- MVNETA_WRITE(sc, MVNETA_PRXSU(0), ready);
-
- for (i = 0; i < ready; i++) {
- idx = sc->sc_rx_cons;
- KASSERT(idx < MVNETA_RX_RING_CNT);
+ bus_dmamap_sync(sc->sc_dmat, MVNETA_DMA_MAP(sc->sc_rxring),
+ 0, MVNETA_DMA_LEN(sc->sc_rxring), BUS_DMASYNC_POSTREAD);
- rxd = &sc->sc_rxdesc[idx];
+ cons = sc->sc_rx_cons;
-#ifdef DIAGNOSTIC
- if ((rxd->cmdsts &
- (MVNETA_RX_LAST_DESC | MVNETA_RX_FIRST_DESC)) !=
- (MVNETA_RX_LAST_DESC | MVNETA_RX_FIRST_DESC))
- panic("%s: buffer size is smaller than packet",
- __func__);
-#endif
+ for (i = 0; i < done; i++) {
+ rxd = &sc->sc_rxdesc[cons];
+ rxb = &sc->sc_rxbuf[cons];
- len = rxd->bytecnt;
- rxb = &sc->sc_rxbuf[idx];
- KASSERT(rxb->tb_m);
+ m = rxb->tb_m;
+ rxb->tb_m = NULL;
bus_dmamap_sync(sc->sc_dmat, rxb->tb_map, 0,
- len, BUS_DMASYNC_POSTREAD);
+ m->m_pkthdr.len, BUS_DMASYNC_POSTREAD);
bus_dmamap_unload(sc->sc_dmat, rxb->tb_map);
- m = rxb->tb_m;
- rxb->tb_m = NULL;
- m->m_pkthdr.len = m->m_len = len;
-
rxstat = rxd->cmdsts;
if (rxstat & MVNETA_ERROR_SUMMARY) {
#if 0
#else
ifp->if_ierrors++;
#endif
- panic("%s: handle input errors", __func__);
- continue;
+ m_freem(m);
+ } else {
+ m->m_pkthdr.len = m->m_len = rxd->bytecnt;
+ m_adj(m, MVNETA_HWHEADER_SIZE);
+
+ ml_enqueue(&ml, m);
}
#if notyet
}
#endif
- /* Skip on first 2byte (HW header) */
- m_adj(m, MVNETA_HWHEADER_SIZE);
+ if_rxr_put(&sc->sc_rx_ring, 1);
- ml_enqueue(&ml, m);
+ cons = MVNETA_RX_RING_NEXT(cons);
- if_rxr_put(&sc->sc_rx_ring, 1);
+ if (i == MVNETA_PRXSU_MAX) {
+ MVNETA_WRITE(sc, MVNETA_PRXSU(0),
+ MVNETA_PRXSU_NOPD(MVNETA_PRXSU_MAX));
- sc->sc_rx_cons = MVNETA_RX_RING_NEXT(idx);
+ /* tweaking the iterator inside the loop is fun */
+ done -= MVNETA_PRXSU_MAX;
+ i = 0;
+ }
+ }
+
+ sc->sc_rx_cons = cons;
+
+ bus_dmamap_sync(sc->sc_dmat, MVNETA_DMA_MAP(sc->sc_rxring),
+ 0, MVNETA_DMA_LEN(sc->sc_rxring), BUS_DMASYNC_PREREAD);
+
+ if (i > 0) {
+ MVNETA_WRITE(sc, MVNETA_PRXSU(0),
+ MVNETA_PRXSU_NOPD(i));
}
if (ifiq_input(&ifp->if_rcv, &ml))
free(mdm, M_DEVBUF, 0);
}
-struct mbuf *
+static inline struct mbuf *
mvneta_alloc_mbuf(struct mvneta_softc *sc, bus_dmamap_t map)
{
struct mbuf *m = NULL;
m = MCLGETL(NULL, M_DONTWAIT, MCLBYTES);
- if (!m)
+ if (m == NULL)
return (NULL);
m->m_len = m->m_pkthdr.len = MCLBYTES;
{
struct mvneta_rx_desc *rxd;
struct mvneta_buf *rxb;
- u_int slots;
+ unsigned int slots, used = 0;
+ unsigned int prod;
- for (slots = if_rxr_get(&sc->sc_rx_ring, MVNETA_RX_RING_CNT);
+ bus_dmamap_sync(sc->sc_dmat, MVNETA_DMA_MAP(sc->sc_rxring),
+ 0, MVNETA_DMA_LEN(sc->sc_rxring), BUS_DMASYNC_POSTWRITE);
+
+ prod = sc->sc_rx_prod;
+
+ for (slots = if_rxr_get(&sc->sc_rx_ring, MVNETA_PRXSU_MAX);
slots > 0; slots--) {
- rxb = &sc->sc_rxbuf[sc->sc_rx_prod];
+ rxb = &sc->sc_rxbuf[prod];
rxb->tb_m = mvneta_alloc_mbuf(sc, rxb->tb_map);
if (rxb->tb_m == NULL)
break;
- rxd = &sc->sc_rxdesc[sc->sc_rx_prod];
- memset(rxd, 0, sizeof(*rxd));
+ rxd = &sc->sc_rxdesc[prod];
+ rxd->cmdsts = 0;
+ rxd->bufsize = 0;
+ rxd->bytecnt = 0;
rxd->bufptr = rxb->tb_map->dm_segs[0].ds_addr;
+ rxd->nextdescptr = 0;
+ rxd->_padding[0] = 0;
+ rxd->_padding[1] = 0;
+ rxd->_padding[2] = 0;
+ rxd->_padding[3] = 0;
+
+ prod = MVNETA_RX_RING_NEXT(prod);
+ used++;
+ }
+ if_rxr_put(&sc->sc_rx_ring, slots);
- bus_dmamap_sync(sc->sc_dmat, MVNETA_DMA_MAP(sc->sc_rxring),
- sc->sc_rx_prod * sizeof(*rxd), sizeof(*rxd),
- BUS_DMASYNC_PREWRITE);
-
- sc->sc_rx_prod = MVNETA_RX_RING_NEXT(sc->sc_rx_prod);
+ sc->sc_rx_prod = prod;
- /* Tell him that there's a new free desc. */
- MVNETA_WRITE(sc, MVNETA_PRXSU(0),
- MVNETA_PRXSU_NOOFNEWDESCRIPTORS(1));
- }
+ bus_dmamap_sync(sc->sc_dmat, MVNETA_DMA_MAP(sc->sc_rxring),
+ 0, MVNETA_DMA_LEN(sc->sc_rxring), BUS_DMASYNC_PREWRITE);
- if_rxr_put(&sc->sc_rx_ring, slots);
+ if (used > 0)
+ MVNETA_WRITE(sc, MVNETA_PRXSU(0), MVNETA_PRXSU_NOND(used));
}
#if NKSTAT > 0