Download raw body.
rge(4): fixup rge_encap() DMA syncs
Hi, a friend of mine has been complaining about watchdog timeouts on RK3588. I compared the driver with other ones that are stable, like dwqe(4), and found a few differences in behaviour. One thing I noticed is that the DMA syncs on rge_encap() most certainly don't work correctly, because it only syncs the *last* descriptor in the chain. I think this diff should make sure all TX descs are synced. Cheers, Patrick diff --git a/sys/dev/pci/if_rge.c b/sys/dev/pci/if_rge.c index b9d42eedfda..0b6c5e14fab 100644 --- a/sys/dev/pci/if_rge.c +++ b/sys/dev/pci/if_rge.c @@ -480,24 +480,27 @@ rge_encap(struct rge_queues *q, struct mbuf *m, int idx) if (cur == RGE_TX_LIST_CNT - 1) cmdsts |= RGE_TDCMDSTS_EOR; + if (i == (txmap->dm_nsegs - 1)) + cmdsts |= RGE_TDCMDSTS_EOF; d->rge_cmdsts = htole32(cmdsts); + bus_dmamap_sync(sc->sc_dmat, q->q_tx.rge_tx_list_map, + cur * sizeof(struct rge_tx_desc), sizeof(struct rge_tx_desc), + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + last = cur; cmdsts = RGE_TDCMDSTS_OWN; cur = RGE_NEXT_TX_DESC(cur); } - /* Set EOF on the last descriptor. */ - d->rge_cmdsts |= htole32(RGE_TDCMDSTS_EOF); - /* Transfer ownership of packet to the chip. */ d = &q->q_tx.rge_tx_list[idx]; d->rge_cmdsts |= htole32(RGE_TDCMDSTS_OWN); bus_dmamap_sync(sc->sc_dmat, q->q_tx.rge_tx_list_map, - cur * sizeof(struct rge_tx_desc), sizeof(struct rge_tx_desc), + idx * sizeof(struct rge_tx_desc), sizeof(struct rge_tx_desc), BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); /* Update info of TX queue and descriptors. */
rge(4): fixup rge_encap() DMA syncs