Skip to content

Commit

Permalink
Merge branch 'net-stmmac-yet-more-eee-updates'
Browse files Browse the repository at this point in the history
Russell King says:

====================
net: stmmac: yet more EEE updates

Continuing on with the STMMAC EEE cleanups from last cycle, this series
further cleans up the EEE code, and fixes a problem with the existing
implementation - disabling EEE doesn't immediately disable LPI
signalling until the next packet is transmitted. It likely also fixes
a potential race condition when trying to disable LPI vs the software
timer.
====================

Link: https://patch.msgid.link/Z6NqGnM2yL7Ayo-T@shell.armlinux.org.uk
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
  • Loading branch information
Jakub Kicinski committed Feb 7, 2025
2 parents be258f6 + 62b0a03 commit 02c9722
Show file tree
Hide file tree
Showing 9 changed files with 153 additions and 224 deletions.
14 changes: 14 additions & 0 deletions drivers/net/ethernet/stmicro/stmmac/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,20 @@ struct dma_features {
#define STMMAC_DEFAULT_TWT_LS 0x1E
#define STMMAC_ET_MAX 0xFFFFF

/* Common LPI register bits */
#define LPI_CTRL_STATUS_LPITCSE BIT(21) /* LPI Tx Clock Stop Enable, gmac4, xgmac2 only */
#define LPI_CTRL_STATUS_LPIATE BIT(20) /* LPI Timer Enable, gmac4 only */
#define LPI_CTRL_STATUS_LPITXA BIT(19) /* Enable LPI TX Automate */
#define LPI_CTRL_STATUS_PLSEN BIT(18) /* Enable PHY Link Status */
#define LPI_CTRL_STATUS_PLS BIT(17) /* PHY Link Status */
#define LPI_CTRL_STATUS_LPIEN BIT(16) /* LPI Enable */
#define LPI_CTRL_STATUS_RLPIST BIT(9) /* Receive LPI state, gmac1000 only? */
#define LPI_CTRL_STATUS_TLPIST BIT(8) /* Transmit LPI state, gmac1000 only? */
#define LPI_CTRL_STATUS_RLPIEX BIT(3) /* Receive LPI Exit */
#define LPI_CTRL_STATUS_RLPIEN BIT(2) /* Receive LPI Entry */
#define LPI_CTRL_STATUS_TLPIEX BIT(1) /* Transmit LPI Exit */
#define LPI_CTRL_STATUS_TLPIEN BIT(0) /* Transmit LPI Entry */

#define STMMAC_CHAIN_MODE 0x1
#define STMMAC_RING_MODE 0x2

Expand Down
13 changes: 1 addition & 12 deletions drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,22 +59,11 @@ enum power_event {
/* Energy Efficient Ethernet (EEE)
*
* LPI status, timer and control register offset
* For LPI control and status bit definitions, see common.h.
*/
#define LPI_CTRL_STATUS 0x0030
#define LPI_TIMER_CTRL 0x0034

/* LPI control and status defines */
#define LPI_CTRL_STATUS_LPITXA 0x00080000 /* Enable LPI TX Automate */
#define LPI_CTRL_STATUS_PLSEN 0x00040000 /* Enable PHY Link Status */
#define LPI_CTRL_STATUS_PLS 0x00020000 /* PHY Link Status */
#define LPI_CTRL_STATUS_LPIEN 0x00010000 /* LPI Enable */
#define LPI_CTRL_STATUS_RLPIST 0x00000200 /* Receive LPI state */
#define LPI_CTRL_STATUS_TLPIST 0x00000100 /* Transmit LPI state */
#define LPI_CTRL_STATUS_RLPIEX 0x00000008 /* Receive LPI Exit */
#define LPI_CTRL_STATUS_RLPIEN 0x00000004 /* Receive LPI Entry */
#define LPI_CTRL_STATUS_TLPIEX 0x00000002 /* Transmit LPI Exit */
#define LPI_CTRL_STATUS_TLPIEN 0x00000001 /* Transmit LPI Entry */

/* GMAC HW ADDR regs */
#define GMAC_ADDR_HIGH(reg) ((reg > 15) ? 0x00000800 + (reg - 16) * 8 : \
0x00000040 + (reg * 8))
Expand Down
30 changes: 11 additions & 19 deletions drivers/net/ethernet/stmicro/stmmac/dwmac1000_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,31 +342,24 @@ static int dwmac1000_irq_status(struct mac_device_info *hw,
return ret;
}

static void dwmac1000_set_eee_mode(struct mac_device_info *hw,
bool en_tx_lpi_clockgating)
static int dwmac1000_set_lpi_mode(struct mac_device_info *hw,
enum stmmac_lpi_mode mode,
bool en_tx_lpi_clockgating, u32 et)
{
void __iomem *ioaddr = hw->pcsr;
u32 value;

/*TODO - en_tx_lpi_clockgating treatment */
if (mode == STMMAC_LPI_TIMER)
return -EOPNOTSUPP;

/* Enable the link status receive on RGMII, SGMII ore SMII
* receive path and instruct the transmit to enter in LPI
* state.
*/
value = readl(ioaddr + LPI_CTRL_STATUS);
value |= LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA;
if (mode == STMMAC_LPI_FORCED)
value |= LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA;
else
value &= ~(LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA);
writel(value, ioaddr + LPI_CTRL_STATUS);
}

static void dwmac1000_reset_eee_mode(struct mac_device_info *hw)
{
void __iomem *ioaddr = hw->pcsr;
u32 value;

value = readl(ioaddr + LPI_CTRL_STATUS);
value &= ~(LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA);
writel(value, ioaddr + LPI_CTRL_STATUS);
return 0;
}

static void dwmac1000_set_eee_pls(struct mac_device_info *hw, int link)
Expand Down Expand Up @@ -509,8 +502,7 @@ const struct stmmac_ops dwmac1000_ops = {
.pmt = dwmac1000_pmt,
.set_umac_addr = dwmac1000_set_umac_addr,
.get_umac_addr = dwmac1000_get_umac_addr,
.set_eee_mode = dwmac1000_set_eee_mode,
.reset_eee_mode = dwmac1000_reset_eee_mode,
.set_lpi_mode = dwmac1000_set_lpi_mode,
.set_eee_timer = dwmac1000_set_eee_timer,
.set_eee_pls = dwmac1000_set_eee_pls,
.debug = dwmac1000_debug,
Expand Down
12 changes: 1 addition & 11 deletions drivers/net/ethernet/stmicro/stmmac/dwmac4.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,23 +177,13 @@ enum power_event {
/* Energy Efficient Ethernet (EEE) for GMAC4
*
* LPI status, timer and control register offset
* For LPI control and status bit definitions, see common.h.
*/
#define GMAC4_LPI_CTRL_STATUS 0xd0
#define GMAC4_LPI_TIMER_CTRL 0xd4
#define GMAC4_LPI_ENTRY_TIMER 0xd8
#define GMAC4_MAC_ONEUS_TIC_COUNTER 0xdc

/* LPI control and status defines */
#define GMAC4_LPI_CTRL_STATUS_LPITCSE BIT(21) /* LPI Tx Clock Stop Enable */
#define GMAC4_LPI_CTRL_STATUS_LPIATE BIT(20) /* LPI Timer Enable */
#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)
#define GMAC_DEBUG_TFCSTS_SHIFT 17
Expand Down
96 changes: 41 additions & 55 deletions drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,33 +376,46 @@ static void dwmac4_get_umac_addr(struct mac_device_info *hw,
GMAC_ADDR_LOW(reg_n));
}

static void dwmac4_set_eee_mode(struct mac_device_info *hw,
bool en_tx_lpi_clockgating)
static int dwmac4_set_lpi_mode(struct mac_device_info *hw,
enum stmmac_lpi_mode mode,
bool en_tx_lpi_clockgating, u32 et)
{
void __iomem *ioaddr = hw->pcsr;
u32 value;
u32 value, mask;

/* Enable the link status receive on RGMII, SGMII ore SMII
* receive path and instruct the transmit to enter in LPI
* state.
*/
value = readl(ioaddr + GMAC4_LPI_CTRL_STATUS);
value |= GMAC4_LPI_CTRL_STATUS_LPIEN | GMAC4_LPI_CTRL_STATUS_LPITXA;
if (mode == STMMAC_LPI_DISABLE) {
value = 0;
} else {
value = LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA;

if (en_tx_lpi_clockgating)
value |= GMAC4_LPI_CTRL_STATUS_LPITCSE;
if (mode == STMMAC_LPI_TIMER) {
/* Return ERANGE if the timer is larger than the
* register field.
*/
if (et > STMMAC_ET_MAX)
return -ERANGE;

writel(value, ioaddr + GMAC4_LPI_CTRL_STATUS);
}
/* Set the hardware LPI entry timer */
writel(et, ioaddr + GMAC4_LPI_ENTRY_TIMER);

static void dwmac4_reset_eee_mode(struct mac_device_info *hw)
{
void __iomem *ioaddr = hw->pcsr;
u32 value;
/* Interpret a zero LPI entry timer to mean
* immediate entry into LPI mode.
*/
if (et)
value |= LPI_CTRL_STATUS_LPIATE;
}

value = readl(ioaddr + GMAC4_LPI_CTRL_STATUS);
value &= ~(GMAC4_LPI_CTRL_STATUS_LPIEN | GMAC4_LPI_CTRL_STATUS_LPITXA);
if (en_tx_lpi_clockgating)
value |= LPI_CTRL_STATUS_LPITCSE;
}

mask = LPI_CTRL_STATUS_LPIATE | LPI_CTRL_STATUS_LPIEN |
LPI_CTRL_STATUS_LPITXA | LPI_CTRL_STATUS_LPITCSE;

value |= readl(ioaddr + GMAC4_LPI_CTRL_STATUS) & ~mask;
writel(value, ioaddr + GMAC4_LPI_CTRL_STATUS);

return 0;
}

static void dwmac4_set_eee_pls(struct mac_device_info *hw, int link)
Expand All @@ -413,34 +426,13 @@ static void dwmac4_set_eee_pls(struct mac_device_info *hw, int link)
value = readl(ioaddr + GMAC4_LPI_CTRL_STATUS);

if (link)
value |= GMAC4_LPI_CTRL_STATUS_PLS;
value |= LPI_CTRL_STATUS_PLS;
else
value &= ~GMAC4_LPI_CTRL_STATUS_PLS;
value &= ~LPI_CTRL_STATUS_PLS;

writel(value, ioaddr + GMAC4_LPI_CTRL_STATUS);
}

static void dwmac4_set_eee_lpi_entry_timer(struct mac_device_info *hw, u32 et)
{
void __iomem *ioaddr = hw->pcsr;
u32 value = et & STMMAC_ET_MAX;
int regval;

/* Program LPI entry timer value into register */
writel(value, ioaddr + GMAC4_LPI_ENTRY_TIMER);

/* Enable/disable LPI entry timer */
regval = readl(ioaddr + GMAC4_LPI_CTRL_STATUS);
regval |= GMAC4_LPI_CTRL_STATUS_LPIEN | GMAC4_LPI_CTRL_STATUS_LPITXA;

if (et)
regval |= GMAC4_LPI_CTRL_STATUS_LPIATE;
else
regval &= ~GMAC4_LPI_CTRL_STATUS_LPIATE;

writel(regval, ioaddr + GMAC4_LPI_CTRL_STATUS);
}

static void dwmac4_set_eee_timer(struct mac_device_info *hw, int ls, int tw)
{
void __iomem *ioaddr = hw->pcsr;
Expand Down Expand Up @@ -849,17 +841,17 @@ static int dwmac4_irq_status(struct mac_device_info *hw,
/* Clear LPI interrupt by reading MAC_LPI_Control_Status */
u32 status = readl(ioaddr + GMAC4_LPI_CTRL_STATUS);

if (status & GMAC4_LPI_CTRL_STATUS_TLPIEN) {
if (status & 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) {
if (status & 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)
if (status & LPI_CTRL_STATUS_RLPIEN)
x->irq_rx_path_in_lpi_mode_n++;
if (status & GMAC4_LPI_CTRL_STATUS_RLPIEX)
if (status & LPI_CTRL_STATUS_RLPIEX)
x->irq_rx_path_exit_lpi_mode_n++;
}

Expand Down Expand Up @@ -1201,9 +1193,7 @@ const struct stmmac_ops dwmac4_ops = {
.pmt = dwmac4_pmt,
.set_umac_addr = dwmac4_set_umac_addr,
.get_umac_addr = dwmac4_get_umac_addr,
.set_eee_mode = dwmac4_set_eee_mode,
.reset_eee_mode = dwmac4_reset_eee_mode,
.set_eee_lpi_entry_timer = dwmac4_set_eee_lpi_entry_timer,
.set_lpi_mode = dwmac4_set_lpi_mode,
.set_eee_timer = dwmac4_set_eee_timer,
.set_eee_pls = dwmac4_set_eee_pls,
.pcs_ctrl_ane = dwmac4_ctrl_ane,
Expand Down Expand Up @@ -1245,9 +1235,7 @@ const struct stmmac_ops dwmac410_ops = {
.pmt = dwmac4_pmt,
.set_umac_addr = dwmac4_set_umac_addr,
.get_umac_addr = dwmac4_get_umac_addr,
.set_eee_mode = dwmac4_set_eee_mode,
.reset_eee_mode = dwmac4_reset_eee_mode,
.set_eee_lpi_entry_timer = dwmac4_set_eee_lpi_entry_timer,
.set_lpi_mode = dwmac4_set_lpi_mode,
.set_eee_timer = dwmac4_set_eee_timer,
.set_eee_pls = dwmac4_set_eee_pls,
.pcs_ctrl_ane = dwmac4_ctrl_ane,
Expand Down Expand Up @@ -1291,9 +1279,7 @@ const struct stmmac_ops dwmac510_ops = {
.pmt = dwmac4_pmt,
.set_umac_addr = dwmac4_set_umac_addr,
.get_umac_addr = dwmac4_get_umac_addr,
.set_eee_mode = dwmac4_set_eee_mode,
.reset_eee_mode = dwmac4_reset_eee_mode,
.set_eee_lpi_entry_timer = dwmac4_set_eee_lpi_entry_timer,
.set_lpi_mode = dwmac4_set_lpi_mode,
.set_eee_timer = dwmac4_set_eee_timer,
.set_eee_pls = dwmac4_set_eee_pls,
.pcs_ctrl_ane = dwmac4_ctrl_ane,
Expand Down
9 changes: 1 addition & 8 deletions drivers/net/ethernet/stmicro/stmmac/dwxgmac2.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,14 +112,7 @@
#define XGMAC_MGKPKTEN BIT(1)
#define XGMAC_PWRDWN BIT(0)
#define XGMAC_LPI_CTRL 0x000000d0
#define XGMAC_TXCGE BIT(21)
#define XGMAC_LPITXA BIT(19)
#define XGMAC_PLS BIT(17)
#define XGMAC_LPITXEN BIT(16)
#define XGMAC_RLPIEX BIT(3)
#define XGMAC_RLPIEN BIT(2)
#define XGMAC_TLPIEX BIT(1)
#define XGMAC_TLPIEN BIT(0)
/* For definitions, see LPI_CTRL_STATUS_xxx in common.h */
#define XGMAC_LPI_TIMER_CTRL 0x000000d4
#define XGMAC_HW_FEATURE0 0x0000011c
#define XGMAC_HWFEAT_EDMA BIT(31)
Expand Down
49 changes: 23 additions & 26 deletions drivers/net/ethernet/stmicro/stmmac/dwxgmac2_core.c
Original file line number Diff line number Diff line change
Expand Up @@ -316,17 +316,17 @@ static int dwxgmac2_host_irq_status(struct mac_device_info *hw,
if (stat & XGMAC_LPIIS) {
u32 lpi = readl(ioaddr + XGMAC_LPI_CTRL);

if (lpi & XGMAC_TLPIEN) {
if (lpi & LPI_CTRL_STATUS_TLPIEN) {
ret |= CORE_IRQ_TX_PATH_IN_LPI_MODE;
x->irq_tx_path_in_lpi_mode_n++;
}
if (lpi & XGMAC_TLPIEX) {
if (lpi & LPI_CTRL_STATUS_TLPIEX) {
ret |= CORE_IRQ_TX_PATH_EXIT_LPI_MODE;
x->irq_tx_path_exit_lpi_mode_n++;
}
if (lpi & XGMAC_RLPIEN)
if (lpi & LPI_CTRL_STATUS_RLPIEN)
x->irq_rx_path_in_lpi_mode_n++;
if (lpi & XGMAC_RLPIEX)
if (lpi & LPI_CTRL_STATUS_RLPIEX)
x->irq_rx_path_exit_lpi_mode_n++;
}

Expand Down Expand Up @@ -425,29 +425,28 @@ static void dwxgmac2_get_umac_addr(struct mac_device_info *hw,
addr[5] = (hi_addr >> 8) & 0xff;
}

static void dwxgmac2_set_eee_mode(struct mac_device_info *hw,
bool en_tx_lpi_clockgating)
static int dwxgmac2_set_lpi_mode(struct mac_device_info *hw,
enum stmmac_lpi_mode mode,
bool en_tx_lpi_clockgating, u32 et)
{
void __iomem *ioaddr = hw->pcsr;
u32 value;

value = readl(ioaddr + XGMAC_LPI_CTRL);

value |= XGMAC_LPITXEN | XGMAC_LPITXA;
if (en_tx_lpi_clockgating)
value |= XGMAC_TXCGE;

writel(value, ioaddr + XGMAC_LPI_CTRL);
}

static void dwxgmac2_reset_eee_mode(struct mac_device_info *hw)
{
void __iomem *ioaddr = hw->pcsr;
u32 value;
if (mode == STMMAC_LPI_TIMER)
return -EOPNOTSUPP;

value = readl(ioaddr + XGMAC_LPI_CTRL);
value &= ~(XGMAC_LPITXEN | XGMAC_LPITXA | XGMAC_TXCGE);
if (mode == STMMAC_LPI_FORCED) {
value |= LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA;
if (en_tx_lpi_clockgating)
value |= LPI_CTRL_STATUS_LPITCSE;
} else {
value &= ~(LPI_CTRL_STATUS_LPIEN | LPI_CTRL_STATUS_LPITXA |
LPI_CTRL_STATUS_LPITCSE);
}
writel(value, ioaddr + XGMAC_LPI_CTRL);

return 0;
}

static void dwxgmac2_set_eee_pls(struct mac_device_info *hw, int link)
Expand All @@ -457,9 +456,9 @@ static void dwxgmac2_set_eee_pls(struct mac_device_info *hw, int link)

value = readl(ioaddr + XGMAC_LPI_CTRL);
if (link)
value |= XGMAC_PLS;
value |= LPI_CTRL_STATUS_PLS;
else
value &= ~XGMAC_PLS;
value &= ~LPI_CTRL_STATUS_PLS;
writel(value, ioaddr + XGMAC_LPI_CTRL);
}

Expand Down Expand Up @@ -1525,8 +1524,7 @@ const struct stmmac_ops dwxgmac210_ops = {
.pmt = dwxgmac2_pmt,
.set_umac_addr = dwxgmac2_set_umac_addr,
.get_umac_addr = dwxgmac2_get_umac_addr,
.set_eee_mode = dwxgmac2_set_eee_mode,
.reset_eee_mode = dwxgmac2_reset_eee_mode,
.set_lpi_mode = dwxgmac2_set_lpi_mode,
.set_eee_timer = dwxgmac2_set_eee_timer,
.set_eee_pls = dwxgmac2_set_eee_pls,
.debug = NULL,
Expand Down Expand Up @@ -1582,8 +1580,7 @@ const struct stmmac_ops dwxlgmac2_ops = {
.pmt = dwxgmac2_pmt,
.set_umac_addr = dwxgmac2_set_umac_addr,
.get_umac_addr = dwxgmac2_get_umac_addr,
.set_eee_mode = dwxgmac2_set_eee_mode,
.reset_eee_mode = dwxgmac2_reset_eee_mode,
.set_lpi_mode = dwxgmac2_set_lpi_mode,
.set_eee_timer = dwxgmac2_set_eee_timer,
.set_eee_pls = dwxgmac2_set_eee_pls,
.debug = NULL,
Expand Down
Loading

0 comments on commit 02c9722

Please sign in to comment.