kern/178319: [patch] [arge] arge_stop() doesn't clean the tx ring properly
Luiz Otavio O Souza
loos.br at gmail.com
Fri May 3 13:40:00 UTC 2013
>Number: 178319
>Category: kern
>Synopsis: [patch] [arge] arge_stop() doesn't clean the tx ring properly
>Confidential: no
>Severity: non-critical
>Priority: low
>Responsible: freebsd-bugs
>State: open
>Quarter:
>Keywords:
>Date-Required:
>Class: sw-bug
>Submitter-Id: current-users
>Arrival-Date: Fri May 03 13:40:00 UTC 2013
>Closed-Date:
>Last-Modified:
>Originator: Luiz Otavio O Souza
>Release: -head r250121
>Organization:
>Environment:
FreeBSD rb433 10.0-CURRENT FreeBSD 10.0-CURRENT #61 r250121M: Fri May 3 09:45:51 BRT 2013 root at devel:/data/rb/rb433/obj/mips.mips/data/rb/rb433/src/sys/RSPRO mips
>Description:
While debugging the bootp race with if_arge (kern/178318) i have observed another weird thing, i see some packets being queued on the tx ring and when the TX_PKT_SENT interrupt arrives the tx ring was reseted. After a while the driver panics with what looks like a leakage.
After some debug i found that if arge_stop() wont properly clean the tx ring.
So you may end with some leak of dma tags and mbufs on the following case (which was triggered by the bootp problem):
- arge_start() -> queue packets on tx ring;
- arge_init() ->disable interrupts -> arge_stop() -> wont reset properly the tx ring -> enable interrupts;
- TX_PKT_SENT interrupt received -> arge_tx() wont see anything to clear.
If this happens for a while the driver will panic due to the leakage of dma tags.
>How-To-Repeat:
Add some printf() debug to arge_init_locked():
Index: mips/atheros/if_arge.c
===================================================================
--- mips/atheros/if_arge.c (revision 250121)
+++ mips/atheros/if_arge.c (working copy)
@@ -1006,6 +1006,7 @@
ARGE_LOCK_ASSERT(sc);
+printf("%s: called\n", __func__);
arge_stop(sc);
/* Init circular RX list. */
Configure the RSPRO to boot from bootp/nfs:
Index: sys/mips/conf/RSPRO
===================================================================
--- sys/mips/conf/RSPRO (revision 250121)
+++ sys/mips/conf/RSPRO (working copy)
@@ -28,3 +28,12 @@
# Boot off of flash
options ROOTDEVNAME=\"ufs:redboot/rootfs.uzip\"
+options NFSCL
+options NFS_ROOT
+options BOOTP
+options BOOTP_NFSROOT
+options BOOTP_NFSV3
+options BOOTP_WIRED_TO=arge0
+options BOOTP_COMPAT
+
+
>Fix:
Make arge_stop() properly clean the tx ring.
Patch attached with submission follows:
Index: sys/mips/atheros/if_arge.c
===================================================================
--- sys/mips/atheros/if_arge.c (revision 250121)
+++ sys/mips/atheros/if_arge.c (working copy)
@@ -142,6 +142,7 @@
static int arge_rx_ring_init(struct arge_softc *);
static void arge_rx_ring_free(struct arge_softc *sc);
static int arge_tx_ring_init(struct arge_softc *);
+static void arge_tx_ring_free(struct arge_softc *);
#ifdef DEVICE_POLLING
static int arge_poll(struct ifnet *, enum poll_cmd, int);
#endif
@@ -1264,6 +1265,7 @@
/* Flush FIFO and free any existing mbufs */
arge_flush_ddr(sc);
arge_rx_ring_free(sc);
+ arge_tx_ring_free(sc);
}
@@ -1694,6 +1696,27 @@
}
/*
+ * Free the Tx ring, unload any pending dma transaction and eat the mbuf.
+ */
+static void
+arge_tx_ring_free(struct arge_softc *sc)
+{
+ struct arge_txdesc *txd;
+ int i;
+
+ /* Free the Tx buffers. */
+ for (i = 0; i < ARGE_TX_RING_COUNT; i++) {
+ txd = &sc->arge_cdata.arge_txdesc[i];
+ if (txd->tx_dmamap)
+ bus_dmamap_unload(sc->arge_cdata.arge_tx_tag,
+ txd->tx_dmamap);
+ if (txd->tx_m)
+ m_freem(txd->tx_m);
+ txd->tx_m = NULL;
+ }
+}
+
+/*
* Initialize the RX descriptors and allocate mbufs for them. Note that
* we arrange the descriptors in a closed ring, so that the last descriptor
* points back to the first.
>Release-Note:
>Audit-Trail:
>Unformatted:
More information about the freebsd-bugs
mailing list