summaryrefslogtreecommitdiff
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorClaudiu Beznea <claudiu.beznea@microchip.com>2018-12-17 10:02:42 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-01-09 17:14:44 +0100
commit6e12baae0001e0dee2c349b2d5cd8f3f463e3856 (patch)
tree0794360b83a734286c840d99f74f78b75638b9ae /drivers/net/ethernet
parent95b4b711444a4414bccfc0b1fe3c5096675ab8f7 (diff)
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: Claudiu Beznea <claudiu.beznea@microchip.com> Acked-by: Nicolas Ferre <nicolas.ferre@microchip.com> Signed-off-by: David S. Miller <davem@davemloft.net> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r--drivers/net/ethernet/cadence/macb_main.c21
1 files changed, 20 insertions, 1 deletions
diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c
index d6f8d6c8b0f1..0b2f9ddfb1c4 100644
--- a/drivers/net/ethernet/cadence/macb_main.c
+++ b/drivers/net/ethernet/cadence/macb_main.c
@@ -60,7 +60,8 @@
#define MACB_TX_ERR_FLAGS (MACB_BIT(ISR_TUND) \
| MACB_BIT(ISR_RLE) \
| 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 */
#define MACB_TX_LEN_ALIGN 8
@@ -1243,6 +1244,21 @@ static int macb_poll(struct napi_struct *napi, int budget)
return work_done;
}
+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)
{
struct macb_queue *queue = dev_id;
@@ -1300,6 +1316,9 @@ 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);
+
/* 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.
*/