If eqos_free_pkt() is called after eqos_stop(), eqos_stop_resets() will have been called already. This may prevent accessing the MMIO space to update the RX descriptor tail pointer, so we must skip the descriptor maintenance logic. This is okay because the descriptors and tail pointer will all be rewritten anyway during the next call to eqos_start().
This hang was observed after a failed TFTP transaction: eqos_recv(dev=000000047fb57330, flags=1): eqos_recv: *packetp=000000c3ffb5c080, length=151 TFTP error: 'file <FILE> not found for <IP>' (1) Not retrying... eqos_stop(dev=000000047fb57330): eqos_stop: OK eqos_free_pkt(packet=000000c3ffb5c080, length=151) <HANG> Fixes: ba4dfef1469f ("net: add driver for Synopsys Ethernet QoS device") Signed-off-by: Samuel Holland <samuel.holl...@sifive.com> --- drivers/net/dwc_eth_qos.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c index b4ec3614696..b9a2846b2d7 100644 --- a/drivers/net/dwc_eth_qos.c +++ b/drivers/net/dwc_eth_qos.c @@ -1173,7 +1173,7 @@ static int eqos_free_pkt(struct udevice *dev, uchar *packet, int length) eqos->config->ops->eqos_inval_buffer(packet, length); - if ((eqos->rx_desc_idx & idx_mask) == idx_mask) { + if (eqos->started && (eqos->rx_desc_idx & idx_mask) == idx_mask) { for (idx = eqos->rx_desc_idx - idx_mask; idx <= eqos->rx_desc_idx; idx++) { -- 2.47.2 base-commit: 739ad58dbee874a3ad3bddd116e995212a254e07 branch: up/dwmac-hang-fix