DF-4304 / fix.diff
--- a/sys/dev/netif/bfe/if_bfe.c +++ b/sys/dev/netif/bfe/if_bfe.c @@ -1064,6 +1064,16 @@ chipidx = CSR_READ_4(sc, BFE_DMATX_STAT) & BFE_STAT_CDMASK; chipidx /= sizeof(struct bfe_desc); + /* The 12-bit field encodes offsets 0..4095 -> indices 0..511, + * but the ring holds BFE_TX_LIST_CNT (511) descriptors. An + * out-of-range index (e.g. from a wedged/errant DMA engine) + * would make the cleanup walk below non-terminating while + * holding the serializer in interrupt context. */ + if (chipidx >= BFE_TX_LIST_CNT) { + if_printf(ifp, "tx dma status bogus (cd=%u)\n", chipidx); + return; + } + i = sc->bfe_tx_cons; /* Go through the mbufs and free those that have been transmitted */ @@ -1106,6 +1116,13 @@ status = CSR_READ_4(sc, BFE_DMARX_STAT); current = (status & BFE_STAT_CDMASK) / sizeof(struct bfe_desc); + /* See bfe_txeof(): index 511 is encodable but not a valid ring + * index; walking toward it never terminates. */ + if (current >= BFE_RX_LIST_CNT) { + if_printf(ifp, "rx dma status bogus (cd=%u)\n", current); + return; + } + while (current != cons) { r = &sc->bfe_rx_ring[cons]; bus_dmamap_sync(sc->bfe_rxbuf_tag, r->bfe_map, |