Correctly (I hope) deallocate the if_arge RX buffer ring on arge_stop().
I had some interesting hangs until I realised I should try flushing the DDR FIFO register and lo and behold, hangs stopped occuring. I've put in a few DDR flushes here and there in case people decide to reuse some of these functions. It's very very likely they're almost all superflous. To test: * Connect to a network with a _lot_ of broadcast traffic * Do this: # while true; do ifconfig arge0 down; ifconfig arge0 up; done This fixes the mbuf exhaustion that has been reported when the interface state flaps up/down.
This commit is contained in:
parent
505a01e936
commit
eeaef4bae5
@ -118,6 +118,7 @@ static int arge_probe(device_t);
|
||||
static void arge_reset_dma(struct arge_softc *);
|
||||
static int arge_resume(device_t);
|
||||
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 *);
|
||||
#ifdef DEVICE_POLLING
|
||||
static int arge_poll(struct ifnet *, enum poll_cmd, int);
|
||||
@ -807,6 +808,12 @@ arge_reset_dma(struct arge_softc *sc)
|
||||
DMA_RX_STATUS_BUS_ERROR | DMA_RX_STATUS_OVERFLOW);
|
||||
ARGE_WRITE(sc, AR71XX_DMA_TX_STATUS,
|
||||
DMA_TX_STATUS_BUS_ERROR | DMA_TX_STATUS_UNDERRUN);
|
||||
|
||||
/*
|
||||
* Force a DDR flush so any pending data is properly
|
||||
* flushed to RAM before underlying buffers are freed.
|
||||
*/
|
||||
arge_flush_ddr(sc);
|
||||
}
|
||||
|
||||
|
||||
@ -1083,6 +1090,10 @@ arge_stop(struct arge_softc *sc)
|
||||
ARGE_WRITE(sc, AR71XX_DMA_INTR, 0);
|
||||
|
||||
arge_reset_dma(sc);
|
||||
|
||||
/* Flush FIFO and free any existing mbufs */
|
||||
arge_flush_ddr(sc);
|
||||
arge_rx_ring_free(sc);
|
||||
}
|
||||
|
||||
|
||||
@ -1531,6 +1542,12 @@ arge_rx_ring_init(struct arge_softc *sc)
|
||||
bzero(rd->arge_rx_ring, sizeof(rd->arge_rx_ring));
|
||||
for (i = 0; i < ARGE_RX_RING_COUNT; i++) {
|
||||
rxd = &sc->arge_cdata.arge_rxdesc[i];
|
||||
if (rxd->rx_m != NULL) {
|
||||
device_printf(sc->arge_dev,
|
||||
"%s: ring[%d] rx_m wasn't free?\n",
|
||||
__func__,
|
||||
i);
|
||||
}
|
||||
rxd->rx_m = NULL;
|
||||
rxd->desc = &rd->arge_rx_ring[i];
|
||||
if (i == ARGE_RX_RING_COUNT - 1)
|
||||
@ -1550,6 +1567,32 @@ arge_rx_ring_init(struct arge_softc *sc)
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Free all the buffers in the RX ring.
|
||||
*
|
||||
* TODO: ensure that DMA is disabled and no pending DMA
|
||||
* is lurking in the FIFO.
|
||||
*/
|
||||
static void
|
||||
arge_rx_ring_free(struct arge_softc *sc)
|
||||
{
|
||||
int i;
|
||||
struct arge_rxdesc *rxd;
|
||||
|
||||
ARGE_LOCK_ASSERT(sc);
|
||||
|
||||
for (i = 0; i < ARGE_RX_RING_COUNT; i++) {
|
||||
rxd = &sc->arge_cdata.arge_rxdesc[i];
|
||||
/* Unmap the mbuf */
|
||||
if (rxd->rx_m != NULL) {
|
||||
bus_dmamap_unload(sc->arge_cdata.arge_rx_tag,
|
||||
rxd->rx_dmamap);
|
||||
m_free(rxd->rx_m);
|
||||
rxd->rx_m = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize an RX descriptor and attach an MBUF cluster.
|
||||
*/
|
||||
|
Loading…
x
Reference in New Issue
Block a user