Sorry for the delay in responding.

On 2019-Dec-27 21:59:49 -0800, Mark Millard via freebsd-arm 
<freebsd-...@freebsd.org> wrote:
>The following sort of sequence leads to the Rock64 not
>responding on the console or over ethernet, after notifying
>of nmbclusters having been reached. (This limits what
>information I have of what things were like at the end.)

There's a bug in the dwc(4) driver such that it can leak mbuf clusters.
I've been running with the following patch but need to clean it up
samewhat before I can commit it:

Index: sys/dev/dwc/if_dwc.c
===================================================================
--- sys/dev/dwc/if_dwc.c        (revision 356350)
+++ sys/dev/dwc/if_dwc.c        (working copy)
@@ -755,7 +755,6 @@
 dwc_rxfinish_locked(struct dwc_softc *sc)
 {
        struct ifnet *ifp;
-       struct mbuf *m0;
        struct mbuf *m;
        int error, idx, len;
        uint32_t rdes0;
@@ -762,9 +761,8 @@
 
        ifp = sc->ifp;
 
-       for (;;) {
+       for (; ; sc->rx_idx = next_rxidx(sc, sc->rx_idx)) {
                idx = sc->rx_idx;
-
                rdes0 = sc->rxdesc_ring[idx].tdes0;
                if ((rdes0 & DDESC_RDES0_OWN) != 0)
                        break;
@@ -773,9 +771,9 @@
                    BUS_DMASYNC_POSTREAD);
                bus_dmamap_unload(sc->rxbuf_tag, sc->rxbuf_map[idx].map);
 
+               m = sc->rxbuf_map[idx].mbuf;
                len = (rdes0 >> DDESC_RDES0_FL_SHIFT) & DDESC_RDES0_FL_MASK;
                if (len != 0) {
-                       m = sc->rxbuf_map[idx].mbuf;
                        m->m_pkthdr.rcvif = ifp;
                        m->m_pkthdr.len = len;
                        m->m_len = len;
@@ -784,24 +782,33 @@
                        /* Remove trailing FCS */
                        m_adj(m, -ETHER_CRC_LEN);
 
+                       /* Consume the mbuf and mark it as consumed */
+                       sc->rxbuf_map[idx].mbuf = NULL;
                        DWC_UNLOCK(sc);
                        (*ifp->if_input)(ifp, m);
                        DWC_LOCK(sc);
+                       m = NULL;
                } else {
                        /* XXX Zero-length packet ? */
                }
 
-               if ((m0 = dwc_alloc_mbufcl(sc)) != NULL) {
-                       if ((error = dwc_setup_rxbuf(sc, idx, m0)) != 0) {
-                               /*
-                                * XXX Now what?
-                                * We've got a hole in the rx ring.
-                                */
+               if (m == NULL) {
+                       if ((m = dwc_alloc_mbufcl(sc)) == NULL) {
+                               if_inc_counter(sc->ifp, IFCOUNTER_IQDROPS, 1);
+                               continue;
                        }
-               } else
+               }
+
+               if ((error = dwc_setup_rxbuf(sc, idx, m)) != 0) {
+                       m_free(m);
+                       device_printf(sc->dev,
+                           "dwc_setup_rxbuf returned %d\n", error);
                        if_inc_counter(sc->ifp, IFCOUNTER_IQDROPS, 1);
-
-               sc->rx_idx = next_rxidx(sc, sc->rx_idx);
+                       /*
+                        * XXX Now what?
+                        * We've got a hole in the rx ring.
+                        */
+               }
        }
 }

-- 
Peter Jeremy

Attachment: signature.asc
Description: PGP signature

Reply via email to