diff options
author | Niklas Cassel <niklas.cassel@axis.com> | 2017-11-14 11:15:54 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-11-14 22:04:56 +0900 |
commit | 4497478c60c04d2bf37082e27fc98f4f835db96b (patch) | |
tree | 1cbc7d11dc9d0c70b6e1892e3fb84e82dad0de5c /drivers/net | |
parent | bde533f2ea607cbbbe76ef8738b36243939a7bc2 (diff) | |
download | linux-4497478c60c04d2bf37082e27fc98f4f835db96b.tar.bz2 |
net: stmmac: fix LPI transitioning for dwmac4
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>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac4.h | 7 | ||||
-rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c | 19 |
2 files changed, 25 insertions, 1 deletions
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); |