diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 364d99d887fc137cb0147fa6c4fc218fbcb5fde3..de6acec160c7f0c22ce5139645dccd16960581b6 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -1619,35 +1619,36 @@ static void macb_hresp_error_task(unsigned long data) netif_tx_start_all_queues(dev); } -static void macb_tx_restart(struct macb_queue *queue) +static int macb_tx_restart(struct macb_queue *queue) { unsigned int head = queue->tx_head; unsigned int tail = queue->tx_tail; struct macb *bp = queue->bp; unsigned int head_idx, tbqp; - if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) - queue_writel(queue, ISR, MACB_BIT(TXUBR)); - if (head == tail) - return; + return -ENXIO; - tbqp = queue_readl(queue, TBQP) / macb_dma_desc_get_size(bp); + tbqp = queue_readl(queue, TBQP) - lower_32_bits(queue->tx_ring_dma); + tbqp = tbqp / macb_dma_desc_get_size(bp); tbqp = macb_adj_dma_desc_idx(bp, macb_tx_ring_wrap(bp, tbqp)); head_idx = macb_adj_dma_desc_idx(bp, macb_tx_ring_wrap(bp, head)); if (tbqp == head_idx) - return; + return -ENXIO; macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART)); + + return 0; } static irqreturn_t macb_interrupt(int irq, void *dev_id) { - struct macb_queue *queue = dev_id; + struct macb_queue *qq, *queue = dev_id; struct macb *bp = queue->bp; struct net_device *dev = bp->dev; u32 status, ctrl; + int q; status = queue_readl(queue, ISR); @@ -1699,8 +1700,14 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) if (status & MACB_BIT(TCOMP)) macb_tx_interrupt(queue); - if (status & MACB_BIT(TXUBR)) - macb_tx_restart(queue); + if (status & MACB_BIT(TXUBR)) { + if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) + queue_writel(queue, ISR, MACB_BIT(TXUBR)); + + for (q = 0, qq = bp->queues; q < bp->num_queues; ++q, ++qq) + if (!macb_tx_restart(qq)) + break; + } /* Link change detection isn't possible with RMII, so we'll * add that if/when we get our hands on a full-blown MII PHY.