From f1f4825c627b405121063fcf5fabe86346ababef Mon Sep 17 00:00:00 2001 From: Jaeden Amero Date: Thu, 12 Mar 2015 18:07:54 -0500 Subject: [PATCH 1/7] net/macb: Only adjust tx_clk on link change The PHY state machine (in drivers/net/phy/phy.c) will unconditionally call phydev->adjust_link (macb_handle_link_change) when polling in the PHY_CHANGELINK state. As currently written, macb always ends up requesting a new tx_clk frequency in macb_handle_link_change. It is a waste of time to request a new tx_clk frequency if the link state hasn't changed, as the tx_clk will already be configured properly. Let's only request a new tx_clk clock frequency when necessary. Signed-off-by: Jaeden Amero Cc: Josh Cartwright Cc: Soren Brinkmann Signed-off-by: David S. Miller Conflicts: drivers/net/ethernet/cadence/macb.c --- drivers/net/ethernet/cadence/macb.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 414f7966baa038..967c3466490cc3 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -292,11 +292,14 @@ static void macb_handle_link_change(struct net_device *dev) spin_unlock_irqrestore(&bp->lock, flags); - if (!IS_ERR(bp->tx_clk)) - macb_set_tx_clk(bp->tx_clk, phydev->speed, dev); - if (status_change) { if (phydev->link) { + /* Update the TX clock rate if and only if the link is + * up and there has been a link change. + */ + if (!IS_ERR(bp->tx_clk)) + macb_set_tx_clk(bp->tx_clk, phydev->speed, dev); + netif_carrier_on(dev); netdev_info(dev, "link up (%d/%s)\n", phydev->speed, From e7483565114dd41e74ae08610ac13a93907953b4 Mon Sep 17 00:00:00 2001 From: Nicolas Ferre Date: Tue, 31 Mar 2015 15:02:04 +0200 Subject: [PATCH 2/7] net/macb: add the user i/o to ethtool register dump User i/o register EMAC_USRIO or GMAC_UR can be found on both macb and gem flavors of the peripheral. By using the proper accessor, we can add it to the register dump feature of ethtool. Increment the version of this API so it can be noticed from user space. Signed-off-by: Nicolas Ferre Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 2 +- drivers/net/ethernet/cadence/macb.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 967c3466490cc3..d173fbf26d0cef 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -1978,8 +1978,8 @@ static void macb_get_regs(struct net_device *dev, struct ethtool_regs *regs, regs_buff[10] = macb_tx_dma(&bp->queues[0], tail); regs_buff[11] = macb_tx_dma(&bp->queues[0], head); + regs_buff[12] = macb_or_gem_readl(bp, USRIO); if (macb_is_gem(bp)) { - regs_buff[12] = gem_readl(bp, USRIO); regs_buff[13] = gem_readl(bp, DMACFG); } } diff --git a/drivers/net/ethernet/cadence/macb.h b/drivers/net/ethernet/cadence/macb.h index 084191b6fad206..41b87e49dd6fa7 100644 --- a/drivers/net/ethernet/cadence/macb.h +++ b/drivers/net/ethernet/cadence/macb.h @@ -11,7 +11,7 @@ #define _MACB_H #define MACB_GREGS_NBR 16 -#define MACB_GREGS_VERSION 1 +#define MACB_GREGS_VERSION 2 #define MACB_MAX_QUEUES 8 /* MACB register offsets */ From 62499528b4489866bb4dcedf16ddc25ae8894bdf Mon Sep 17 00:00:00 2001 From: Wolfgang Steinwender Date: Fri, 10 Apr 2015 11:42:56 +0200 Subject: [PATCH 3/7] net/macb: sqe_test_errors are TX errors, not RX errors The statistics are grouped by TX and RX errors. The SQE Test Errors Register indicates problems with TX. Signed-off-by: Wolfgang Steinwender Acked-by: Nicolas Ferre Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index d173fbf26d0cef..df48f563735bc8 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -1896,12 +1896,12 @@ struct net_device_stats *macb_get_stats(struct net_device *dev) hwstat->rx_oversize_pkts + hwstat->rx_jabbers + hwstat->rx_undersize_pkts + - hwstat->sqe_test_errors + hwstat->rx_length_mismatch); nstat->tx_errors = (hwstat->tx_late_cols + hwstat->tx_excessive_cols + hwstat->tx_underruns + - hwstat->tx_carrier_errors); + hwstat->tx_carrier_errors + + hwstat->sqe_test_errors); nstat->collisions = (hwstat->tx_single_cols + hwstat->tx_multiple_cols + hwstat->tx_excessive_cols); From 53349c4797329ab24d67f805f92c40302df98a28 Mon Sep 17 00:00:00 2001 From: Ben Shelton Date: Wed, 22 Apr 2015 17:28:54 -0500 Subject: [PATCH 4/7] net/macb: Factor out one-time assignment from loop In 02c958dd3 (net/macb: add TX multiqueue support for gem), the initialization of tx_head and tx_tail in macb_init_rings() was moved inside the loop that iterates over each element in the ring. Since tx_head and tx_tail only need to be assigned once, move them back out of the loop. Signed-off-by: Ben Shelton Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index df48f563735bc8..2d975ad89980fc 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -1474,9 +1474,9 @@ static void macb_init_rings(struct macb *bp) for (i = 0; i < TX_RING_SIZE; i++) { bp->queues[0].tx_ring[i].addr = 0; bp->queues[0].tx_ring[i].ctrl = MACB_BIT(TX_USED); - bp->queues[0].tx_head = 0; - bp->queues[0].tx_tail = 0; } + bp->queues[0].tx_head = 0; + bp->queues[0].tx_tail = 0; bp->queues[0].tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP); bp->rx_tail = 0; From 5d28d75b5ea38006588fc7178cef672249c75dd5 Mon Sep 17 00:00:00 2001 From: Punnaiah Choudary Kalluri Date: Wed, 29 Apr 2015 08:34:46 +0530 Subject: [PATCH 5/7] net: macb: Fix race condition in driver when Rx frame is dropped Under heavy Rx load, observed that the Hw is updating the USED bit and it is not updating the received frame status to the BD control field. This could be lack of resources for processing the BDs at high data rates. Driver drops the frame associated with this BD but not clearing the USED bit. So, this is causing hang condition as Hw expects USED bit to be cleared for this BD. Signed-off-by: Punnaiah Choudary Kalluri Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 2d975ad89980fc..1da29958cf7bbb 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -708,6 +708,9 @@ static void gem_rx_refill(struct macb *bp) /* properly align Ethernet header */ skb_reserve(skb, NET_IP_ALIGN); + } else { + bp->rx_ring[entry].addr &= ~MACB_BIT(RX_USED); + bp->rx_ring[entry].ctrl = 0; } } From 5aab9edc53a794604d142181c0baf86529abf9ee Mon Sep 17 00:00:00 2001 From: Nathan Sullivan Date: Tue, 5 May 2015 15:00:25 -0500 Subject: [PATCH 6/7] net: macb: Handle the RXUBR interrupt on all devices The same hardware issue the at91 must work around applies to at least the Zynq ethernet, and possibly more devices. The driver also needs to handle the RXUBR interrupt since it turns it on with MACB_RX_INT_FLAGS anyway. Signed-off-by: Nathan Sullivan Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index 1da29958cf7bbb..cec7d6805aaa7b 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -982,7 +982,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) struct macb_queue *queue = dev_id; struct macb *bp = queue->bp; struct net_device *dev = bp->dev; - u32 status; + u32 status, ctrl; status = queue_readl(queue, ISR); @@ -1038,6 +1038,15 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) * add that if/when we get our hands on a full-blown MII PHY. */ + if (status & MACB_BIT(RXUBR)) { + ctrl = macb_readl(bp, NCR); + macb_writel(bp, NCR, ctrl & ~MACB_BIT(RE)); + macb_writel(bp, NCR, ctrl | MACB_BIT(RE)); + + if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE) + macb_writel(bp, ISR, MACB_BIT(RXUBR)); + } + if (status & MACB_BIT(ISR_ROVR)) { /* We missed at least one packet */ if (macb_is_gem(bp)) From 3eb426328c050b41f4f896ab1b458b0a602a1a5a Mon Sep 17 00:00:00 2001 From: Nathan Sullivan Date: Wed, 13 May 2015 17:01:36 -0500 Subject: [PATCH 7/7] net: macb: Add better comment for RXUBR handling Describe the handler for RXUBR better with a new comment. Signed-off-by: Nathan Sullivan Reviewied-by: Josh Cartwright Reviewied-by: Ben Shelton Acked-by: Nicolas Ferre Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/ethernet/cadence/macb.c b/drivers/net/ethernet/cadence/macb.c index cec7d6805aaa7b..5db1e77c54a9e3 100644 --- a/drivers/net/ethernet/cadence/macb.c +++ b/drivers/net/ethernet/cadence/macb.c @@ -1038,6 +1038,12 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id) * add that if/when we get our hands on a full-blown MII PHY. */ + /* There is a hardware issue under heavy load where DMA can + * stop, this causes endless "used buffer descriptor read" + * interrupts but it can be cleared by re-enabling RX. See + * the at91 manual, section 41.3.1 or the Zynq manual + * section 16.7.4 for details. + */ if (status & MACB_BIT(RXUBR)) { ctrl = macb_readl(bp, NCR); macb_writel(bp, NCR, ctrl & ~MACB_BIT(RE));