diff mbox series

[net-next,v2] net: stmmac: fix LPI transitioning for dwmac4

Message ID 20171114101555.18902-1-niklas.cassel@axis.com
State Accepted, archived
Delegated to: David Miller
Headers show
Series [net-next,v2] net: stmmac: fix LPI transitioning for dwmac4 | expand

Commit Message

Niklas Cassel Nov. 14, 2017, 10:15 a.m. UTC
The LPI transitioning logic in stmmac_main uses
priv->tx_path_in_lpi_mode to enter/exit LPI.

However, priv->tx_path_in_lpi_mode is assigned
using the return value from host_irq_status().

So for dwmac4, priv->tx_path_in_lpi_mode was always false,
so stmmac_tx_clean() would always try to put us in eee mode,
and stmmac_xmit() would never take us out of eee mode.

To fix this, make host_irq_status() read and return the LPI
irq status also for dwmac4.

This also increments the existing LPI counters, so that
ethtool --statistics shows LPI transitions also for dwmac4.

For dwmac1000, irqs are enabled/disabled using the register
named "Interrupt Mask Register", and thus setting a bit disables
that specific irq.

For dwmac4 the matching register is named "MAC_Interrupt_Enable",
and thus setting a bit enables that specific irq.

Looking at dwmac1000_core.c, the irqs that are always enabled are:
LPI and PMT.

Looking at dwmac4_core.c, the irqs that are always enabled are:
PMT.

To be able to read the LPI irq status, we need to enable the LPI
irq also for dwmac4.

Signed-off-by: Niklas Cassel <niklas.cassel@axis.com>
---
Changes since v1:
Fixed two typos in the commit message.

 drivers/net/ethernet/stmicro/stmmac/dwmac4.h      |  7 ++++++-
 drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 19 +++++++++++++++++++
 2 files changed, 25 insertions(+), 1 deletion(-)

Comments

David Miller Nov. 14, 2017, 1:05 p.m. UTC | #1
From: Niklas Cassel <niklas.cassel@axis.com>
Date: Tue, 14 Nov 2017 11:15:54 +0100

> The LPI transitioning logic in stmmac_main uses
> priv->tx_path_in_lpi_mode to enter/exit LPI.
> 
> However, priv->tx_path_in_lpi_mode is assigned
> using the return value from host_irq_status().
> 
> So for dwmac4, priv->tx_path_in_lpi_mode was always false,
> so stmmac_tx_clean() would always try to put us in eee mode,
> and stmmac_xmit() would never take us out of eee mode.
> 
> To fix this, make host_irq_status() read and return the LPI
> irq status also for dwmac4.
> 
> This also increments the existing LPI counters, so that
> ethtool --statistics shows LPI transitions also for dwmac4.
> 
> For dwmac1000, irqs are enabled/disabled using the register
> named "Interrupt Mask Register", and thus setting a bit disables
> that specific irq.
> 
> For dwmac4 the matching register is named "MAC_Interrupt_Enable",
> and thus setting a bit enables that specific irq.
> 
> Looking at dwmac1000_core.c, the irqs that are always enabled are:
> LPI and PMT.
> 
> Looking at dwmac4_core.c, the irqs that are always enabled are:
> PMT.
> 
> To be able to read the LPI irq status, we need to enable the LPI
> irq also for dwmac4.
> 
> Signed-off-by: Niklas Cassel <niklas.cassel@axis.com>

Applied.
diff mbox series

Patch

diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
index aeda3ab2d761..789dad8a07b5 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4.h
@@ -98,7 +98,7 @@ 
 #define	GMAC_PCS_IRQ_DEFAULT	(GMAC_INT_RGSMIIS | GMAC_INT_PCS_LINK |	\
 				 GMAC_INT_PCS_ANE)
 
-#define	GMAC_INT_DEFAULT_MASK	GMAC_INT_PMT_EN
+#define	GMAC_INT_DEFAULT_MASK	(GMAC_INT_PMT_EN | GMAC_INT_LPI_EN)
 
 enum dwmac4_irq_status {
 	time_stamp_irq = 0x00001000,
@@ -106,6 +106,7 @@  enum dwmac4_irq_status {
 	mmc_tx_irq = 0x00000400,
 	mmc_rx_irq = 0x00000200,
 	mmc_irq = 0x00000100,
+	lpi_irq = 0x00000020,
 	pmt_irq = 0x00000010,
 };
 
@@ -132,6 +133,10 @@  enum power_event {
 #define GMAC4_LPI_CTRL_STATUS_LPITXA	BIT(19)	/* Enable LPI TX Automate */
 #define GMAC4_LPI_CTRL_STATUS_PLS	BIT(17) /* PHY Link Status */
 #define GMAC4_LPI_CTRL_STATUS_LPIEN	BIT(16)	/* LPI Enable */
+#define GMAC4_LPI_CTRL_STATUS_RLPIEX	BIT(3) /* Receive LPI Exit */
+#define GMAC4_LPI_CTRL_STATUS_RLPIEN	BIT(2) /* Receive LPI Entry */
+#define GMAC4_LPI_CTRL_STATUS_TLPIEX	BIT(1) /* Transmit LPI Exit */
+#define GMAC4_LPI_CTRL_STATUS_TLPIEN	BIT(0) /* Transmit LPI Entry */
 
 /* MAC Debug bitmap */
 #define GMAC_DEBUG_TFCSTS_MASK		GENMASK(18, 17)
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
index 2f7d7ec59962..f3ed8f7853eb 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
@@ -580,6 +580,25 @@  static int dwmac4_irq_status(struct mac_device_info *hw,
 		x->irq_receive_pmt_irq_n++;
 	}
 
+	/* MAC tx/rx EEE LPI entry/exit interrupts */
+	if (intr_status & lpi_irq) {
+		/* Clear LPI interrupt by reading MAC_LPI_Control_Status */
+		u32 status = readl(ioaddr + GMAC4_LPI_CTRL_STATUS);
+
+		if (status & GMAC4_LPI_CTRL_STATUS_TLPIEN) {
+			ret |= CORE_IRQ_TX_PATH_IN_LPI_MODE;
+			x->irq_tx_path_in_lpi_mode_n++;
+		}
+		if (status & GMAC4_LPI_CTRL_STATUS_TLPIEX) {
+			ret |= CORE_IRQ_TX_PATH_EXIT_LPI_MODE;
+			x->irq_tx_path_exit_lpi_mode_n++;
+		}
+		if (status & GMAC4_LPI_CTRL_STATUS_RLPIEN)
+			x->irq_rx_path_in_lpi_mode_n++;
+		if (status & GMAC4_LPI_CTRL_STATUS_RLPIEX)
+			x->irq_rx_path_exit_lpi_mode_n++;
+	}
+
 	dwmac_pcs_isr(ioaddr, GMAC_PCS_BASE, intr_status, x);
 	if (intr_status & PCS_RGSMIIIS_IRQ)
 		dwmac4_phystatus(ioaddr, x);