提交 5ea9c08a 编写于 作者: C Claudiu Beznea 提交者: Greg Kroah-Hartman

net: macb: restart tx after tx used bit read

[ Upstream commit 4298388574dae6168fa8940b3edc7ba965e8a7ab ]

On some platforms (currently detected only on SAMA5D4) TX might stuck
even the pachets are still present in DMA memories and TX start was
issued for them. This happens due to race condition between MACB driver
updating next TX buffer descriptor to be used and IP reading the same
descriptor. In such a case, the "TX USED BIT READ" interrupt is asserted.
GEM/MACB user guide specifies that if a "TX USED BIT READ" interrupt
is asserted TX must be restarted. Restart TX if used bit is read and
packets are present in software TX queue. Packets are removed from software
TX queue if TX was successful for them (see macb_tx_interrupt()).
Signed-off-by: NClaudiu Beznea <claudiu.beznea@microchip.com>
Acked-by: NNicolas Ferre <nicolas.ferre@microchip.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 d5f9565c
...@@ -61,7 +61,8 @@ ...@@ -61,7 +61,8 @@
#define MACB_TX_ERR_FLAGS (MACB_BIT(ISR_TUND) \ #define MACB_TX_ERR_FLAGS (MACB_BIT(ISR_TUND) \
| MACB_BIT(ISR_RLE) \ | MACB_BIT(ISR_RLE) \
| MACB_BIT(TXERR)) | MACB_BIT(TXERR))
#define MACB_TX_INT_FLAGS (MACB_TX_ERR_FLAGS | MACB_BIT(TCOMP)) #define MACB_TX_INT_FLAGS (MACB_TX_ERR_FLAGS | MACB_BIT(TCOMP) \
| MACB_BIT(TXUBR))
/* Max length of transmit frame must be a multiple of 8 bytes */ /* Max length of transmit frame must be a multiple of 8 bytes */
#define MACB_TX_LEN_ALIGN 8 #define MACB_TX_LEN_ALIGN 8
...@@ -1313,6 +1314,21 @@ static void macb_hresp_error_task(unsigned long data) ...@@ -1313,6 +1314,21 @@ static void macb_hresp_error_task(unsigned long data)
netif_tx_start_all_queues(dev); netif_tx_start_all_queues(dev);
} }
static void macb_tx_restart(struct macb_queue *queue)
{
unsigned int head = queue->tx_head;
unsigned int tail = queue->tx_tail;
struct macb *bp = queue->bp;
if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
queue_writel(queue, ISR, MACB_BIT(TXUBR));
if (head == tail)
return;
macb_writel(bp, NCR, macb_readl(bp, NCR) | MACB_BIT(TSTART));
}
static irqreturn_t macb_interrupt(int irq, void *dev_id) static irqreturn_t macb_interrupt(int irq, void *dev_id)
{ {
struct macb_queue *queue = dev_id; struct macb_queue *queue = dev_id;
...@@ -1370,6 +1386,9 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) ...@@ -1370,6 +1386,9 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
if (status & MACB_BIT(TCOMP)) if (status & MACB_BIT(TCOMP))
macb_tx_interrupt(queue); macb_tx_interrupt(queue);
if (status & MACB_BIT(TXUBR))
macb_tx_restart(queue);
/* Link change detection isn't possible with RMII, so we'll /* 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. * add that if/when we get our hands on a full-blown MII PHY.
*/ */
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册