mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-05-10 05:39:42 -04:00
Merge branch 'net-stmmac-yet-more-eee-updates'
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>
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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 */
|
||||
|
||||
/* 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;
|
||||
writel(value, ioaddr + LPI_CTRL_STATUS);
|
||||
}
|
||||
|
||||
static void dwmac1000_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 + 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);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dwmac1000_set_eee_pls(struct mac_device_info *hw, int link)
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
/* Set the hardware LPI entry timer */
|
||||
writel(et, ioaddr + GMAC4_LPI_ENTRY_TIMER);
|
||||
|
||||
/* Interpret a zero LPI entry timer to mean
|
||||
* immediate entry into LPI mode.
|
||||
*/
|
||||
if (et)
|
||||
value |= LPI_CTRL_STATUS_LPIATE;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
static void dwmac4_reset_eee_mode(struct mac_device_info *hw)
|
||||
{
|
||||
void __iomem *ioaddr = hw->pcsr;
|
||||
u32 value;
|
||||
|
||||
value = readl(ioaddr + GMAC4_LPI_CTRL_STATUS);
|
||||
value &= ~(GMAC4_LPI_CTRL_STATUS_LPIEN | GMAC4_LPI_CTRL_STATUS_LPITXA);
|
||||
writel(value, ioaddr + GMAC4_LPI_CTRL_STATUS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void dwmac4_set_eee_pls(struct mac_device_info *hw, int link)
|
||||
@@ -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;
|
||||
@@ -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++;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
@@ -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,
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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++;
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
@@ -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,
|
||||
|
||||
@@ -306,6 +306,12 @@ struct stmmac_pps_cfg;
|
||||
struct stmmac_rss;
|
||||
struct stmmac_est;
|
||||
|
||||
enum stmmac_lpi_mode {
|
||||
STMMAC_LPI_DISABLE,
|
||||
STMMAC_LPI_FORCED,
|
||||
STMMAC_LPI_TIMER,
|
||||
};
|
||||
|
||||
/* Helpers to program the MAC core */
|
||||
struct stmmac_ops {
|
||||
/* MAC core initialization */
|
||||
@@ -360,10 +366,9 @@ struct stmmac_ops {
|
||||
unsigned int reg_n);
|
||||
void (*get_umac_addr)(struct mac_device_info *hw, unsigned char *addr,
|
||||
unsigned int reg_n);
|
||||
void (*set_eee_mode)(struct mac_device_info *hw,
|
||||
bool en_tx_lpi_clockgating);
|
||||
void (*reset_eee_mode)(struct mac_device_info *hw);
|
||||
void (*set_eee_lpi_entry_timer)(struct mac_device_info *hw, u32 et);
|
||||
int (*set_lpi_mode)(struct mac_device_info *hw,
|
||||
enum stmmac_lpi_mode mode,
|
||||
bool en_tx_lpi_clockgating, u32 et);
|
||||
void (*set_eee_timer)(struct mac_device_info *hw, int ls, int tw);
|
||||
void (*set_eee_pls)(struct mac_device_info *hw, int link);
|
||||
void (*debug)(struct stmmac_priv *priv, void __iomem *ioaddr,
|
||||
@@ -467,12 +472,8 @@ struct stmmac_ops {
|
||||
stmmac_do_void_callback(__priv, mac, set_umac_addr, __args)
|
||||
#define stmmac_get_umac_addr(__priv, __args...) \
|
||||
stmmac_do_void_callback(__priv, mac, get_umac_addr, __args)
|
||||
#define stmmac_set_eee_mode(__priv, __args...) \
|
||||
stmmac_do_void_callback(__priv, mac, set_eee_mode, __args)
|
||||
#define stmmac_reset_eee_mode(__priv, __args...) \
|
||||
stmmac_do_void_callback(__priv, mac, reset_eee_mode, __args)
|
||||
#define stmmac_set_eee_lpi_timer(__priv, __args...) \
|
||||
stmmac_do_void_callback(__priv, mac, set_eee_lpi_entry_timer, __args)
|
||||
#define stmmac_set_lpi_mode(__priv, __args...) \
|
||||
stmmac_do_callback(__priv, mac, set_lpi_mode, __args)
|
||||
#define stmmac_set_eee_timer(__priv, __args...) \
|
||||
stmmac_do_void_callback(__priv, mac, set_eee_timer, __args)
|
||||
#define stmmac_set_eee_pls(__priv, __args...) \
|
||||
|
||||
@@ -390,16 +390,6 @@ static inline u32 stmmac_rx_dirty(struct stmmac_priv *priv, u32 queue)
|
||||
return dirty;
|
||||
}
|
||||
|
||||
static void stmmac_disable_hw_lpi_timer(struct stmmac_priv *priv)
|
||||
{
|
||||
stmmac_set_eee_lpi_timer(priv, priv->hw, 0);
|
||||
}
|
||||
|
||||
static void stmmac_enable_hw_lpi_timer(struct stmmac_priv *priv)
|
||||
{
|
||||
stmmac_set_eee_lpi_timer(priv, priv->hw, priv->tx_lpi_timer);
|
||||
}
|
||||
|
||||
static bool stmmac_eee_tx_busy(struct stmmac_priv *priv)
|
||||
{
|
||||
u32 tx_cnt = priv->plat->tx_queues_to_use;
|
||||
@@ -436,8 +426,9 @@ static void stmmac_try_to_start_sw_lpi(struct stmmac_priv *priv)
|
||||
|
||||
/* Check and enter in LPI mode */
|
||||
if (!priv->tx_path_in_lpi_mode)
|
||||
stmmac_set_eee_mode(priv, priv->hw,
|
||||
priv->plat->flags & STMMAC_FLAG_EN_TX_LPI_CLOCKGATING);
|
||||
stmmac_set_lpi_mode(priv, priv->hw, STMMAC_LPI_FORCED,
|
||||
priv->plat->flags & STMMAC_FLAG_EN_TX_LPI_CLOCKGATING,
|
||||
0);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -447,8 +438,8 @@ static void stmmac_try_to_start_sw_lpi(struct stmmac_priv *priv)
|
||||
*/
|
||||
static void stmmac_stop_sw_lpi(struct stmmac_priv *priv)
|
||||
{
|
||||
stmmac_reset_eee_mode(priv, priv->hw);
|
||||
del_timer_sync(&priv->eee_ctrl_timer);
|
||||
stmmac_set_lpi_mode(priv, priv->hw, STMMAC_LPI_DISABLE, false, 0);
|
||||
priv->tx_path_in_lpi_mode = false;
|
||||
}
|
||||
|
||||
@@ -466,74 +457,6 @@ static void stmmac_eee_ctrl_timer(struct timer_list *t)
|
||||
stmmac_try_to_start_sw_lpi(priv);
|
||||
}
|
||||
|
||||
/**
|
||||
* stmmac_eee_init - init EEE
|
||||
* @priv: driver private structure
|
||||
* @active: indicates whether EEE should be enabled.
|
||||
* Description:
|
||||
* if the GMAC supports the EEE (from the HW cap reg) and the phy device
|
||||
* can also manage EEE, this function enable the LPI state and start related
|
||||
* timer.
|
||||
*/
|
||||
static void stmmac_eee_init(struct stmmac_priv *priv, bool active)
|
||||
{
|
||||
priv->eee_active = active;
|
||||
|
||||
/* Check if MAC core supports the EEE feature. */
|
||||
if (!priv->dma_cap.eee) {
|
||||
priv->eee_enabled = false;
|
||||
return;
|
||||
}
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
|
||||
/* Check if it needs to be deactivated */
|
||||
if (!priv->eee_active) {
|
||||
if (priv->eee_enabled) {
|
||||
netdev_dbg(priv->dev, "disable EEE\n");
|
||||
priv->eee_sw_timer_en = false;
|
||||
stmmac_disable_hw_lpi_timer(priv);
|
||||
del_timer_sync(&priv->eee_ctrl_timer);
|
||||
stmmac_set_eee_timer(priv, priv->hw, 0,
|
||||
STMMAC_DEFAULT_TWT_LS);
|
||||
if (priv->hw->xpcs)
|
||||
xpcs_config_eee(priv->hw->xpcs,
|
||||
priv->plat->mult_fact_100ns,
|
||||
false);
|
||||
}
|
||||
priv->eee_enabled = false;
|
||||
mutex_unlock(&priv->lock);
|
||||
return;
|
||||
}
|
||||
|
||||
if (priv->eee_active && !priv->eee_enabled) {
|
||||
stmmac_set_eee_timer(priv, priv->hw, STMMAC_DEFAULT_LIT_LS,
|
||||
STMMAC_DEFAULT_TWT_LS);
|
||||
if (priv->hw->xpcs)
|
||||
xpcs_config_eee(priv->hw->xpcs,
|
||||
priv->plat->mult_fact_100ns,
|
||||
true);
|
||||
}
|
||||
|
||||
if (priv->plat->has_gmac4 && priv->tx_lpi_timer <= STMMAC_ET_MAX) {
|
||||
/* Use hardware LPI mode */
|
||||
del_timer_sync(&priv->eee_ctrl_timer);
|
||||
priv->tx_path_in_lpi_mode = false;
|
||||
priv->eee_sw_timer_en = false;
|
||||
stmmac_enable_hw_lpi_timer(priv);
|
||||
} else {
|
||||
/* Use software LPI mode */
|
||||
priv->eee_sw_timer_en = true;
|
||||
stmmac_disable_hw_lpi_timer(priv);
|
||||
stmmac_restart_sw_lpi_timer(priv);
|
||||
}
|
||||
|
||||
priv->eee_enabled = true;
|
||||
|
||||
mutex_unlock(&priv->lock);
|
||||
netdev_dbg(priv->dev, "Energy-Efficient Ethernet initialized\n");
|
||||
}
|
||||
|
||||
/* stmmac_get_tx_hwtstamp - get HW TX timestamps
|
||||
* @priv: driver private structure
|
||||
* @p : descriptor pointer
|
||||
@@ -1110,16 +1033,60 @@ static void stmmac_mac_disable_tx_lpi(struct phylink_config *config)
|
||||
{
|
||||
struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
|
||||
|
||||
stmmac_eee_init(priv, false);
|
||||
priv->eee_active = false;
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
|
||||
priv->eee_enabled = false;
|
||||
|
||||
netdev_dbg(priv->dev, "disable EEE\n");
|
||||
priv->eee_sw_timer_en = false;
|
||||
del_timer_sync(&priv->eee_ctrl_timer);
|
||||
stmmac_set_lpi_mode(priv, priv->hw, STMMAC_LPI_DISABLE, false, 0);
|
||||
priv->tx_path_in_lpi_mode = false;
|
||||
|
||||
stmmac_set_eee_timer(priv, priv->hw, 0, STMMAC_DEFAULT_TWT_LS);
|
||||
if (priv->hw->xpcs)
|
||||
xpcs_config_eee(priv->hw->xpcs, priv->plat->mult_fact_100ns,
|
||||
false);
|
||||
|
||||
mutex_unlock(&priv->lock);
|
||||
}
|
||||
|
||||
static int stmmac_mac_enable_tx_lpi(struct phylink_config *config, u32 timer,
|
||||
bool tx_clk_stop)
|
||||
{
|
||||
struct stmmac_priv *priv = netdev_priv(to_net_dev(config->dev));
|
||||
int ret;
|
||||
|
||||
priv->tx_lpi_timer = timer;
|
||||
stmmac_eee_init(priv, true);
|
||||
priv->eee_active = true;
|
||||
|
||||
mutex_lock(&priv->lock);
|
||||
|
||||
priv->eee_enabled = true;
|
||||
|
||||
stmmac_set_eee_timer(priv, priv->hw, STMMAC_DEFAULT_LIT_LS,
|
||||
STMMAC_DEFAULT_TWT_LS);
|
||||
if (priv->hw->xpcs)
|
||||
xpcs_config_eee(priv->hw->xpcs, priv->plat->mult_fact_100ns,
|
||||
true);
|
||||
|
||||
/* Try to cnfigure the hardware timer. */
|
||||
ret = stmmac_set_lpi_mode(priv, priv->hw, STMMAC_LPI_TIMER,
|
||||
priv->plat->flags & STMMAC_FLAG_EN_TX_LPI_CLOCKGATING,
|
||||
priv->tx_lpi_timer);
|
||||
|
||||
if (ret) {
|
||||
/* Hardware timer mode not supported, or value out of range.
|
||||
* Fall back to using software LPI mode
|
||||
*/
|
||||
priv->eee_sw_timer_en = true;
|
||||
stmmac_restart_sw_lpi_timer(priv);
|
||||
}
|
||||
|
||||
mutex_unlock(&priv->lock);
|
||||
netdev_dbg(priv->dev, "Energy-Efficient Ethernet initialized\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user