net: stmmac: bypass for lpi eee hang issue
Subsystems (3)
PATCH 1/1 net: stmmac: bypass for lpi eee hang issue
Bypass for lpi eee hang issue in the
STMicroelectronics 10/100/1000 Ethernet driver
--- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 27 +++++++++++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-)
drivers/net/ethernet/stmicro/stmmac/stmmac.h +1 -0
@@ -136,6 +136,7 @@ struct stmmac_priv {int use_riwt;int irq_wake;spinlock_t ptp_lock; +spinlock_t lpi_lock;void __iomem *mmcaddr;void __iomem *ptpaddr;u32 mss;
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +20 -7
@@ -333,9 +333,13 @@ static void stmmac_enable_eee_mode(struct stmmac_priv *priv)*/ void stmmac_disable_eee_mode (struct stmmac_priv *priv) { +unsigned long flags; + priv->hw->mac->reset_eee_mode (priv->hw);del_timer_sync (&priv->eee_ctrl_timer); +spin_lock_irqsave (&priv->lpi_lock, flags); priv->tx_path_in_lpi_mode = false; +spin_unlock_irqrestore (&priv->lpi_lock, flags); }/**
@@ -1872,6 +1876,7 @@ static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue)netdev_tx_completed_queue (netdev_get_tx_queue (priv->dev, queue), pkts_compl, bytes_compl); +netif_tx_unlock (priv->dev); if (unlikely(netif_tx_queue_stopped(netdev_get_tx_queue(priv->dev, queue))) &&
@@ -1882,11 +1887,16 @@ static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue)netif_tx_wake_queue (netdev_get_tx_queue (priv->dev, queue)); } -if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) { -stmmac_enable_eee_mode (priv); -mod_timer (&priv->eee_ctrl_timer,STMMAC_LPI_T (eee_timer)); +if (priv->eee_enabled) { +unsigned long flags; + +spin_lock_irqsave (&priv->lpi_lock, flags); +if (!priv->tx_path_in_lpi_mode) +mod_timer (&priv->eee_ctrl_timer, +STMMAC_LPI_T (eee_timer)); + +spin_unlock_irqrestore (&priv->lpi_lock, flags); } -netif_tx_unlock (priv->dev); }static inline void stmmac_enable_dma_irq (struct stmmac_priv *priv,u32 chan)
@@ -2968,6 +2978,9 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)unsigned int enh_desc;unsigned int des; +if (priv->tx_path_in_lpi_mode) +stmmac_disable_eee_mode (priv); + tx_q = &priv->tx_queue[queue];/* Manage oversized TCP frames for GMAC4 device */
@@ -2988,9 +3001,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)return NETDEV_TX_BUSY ; } -if (priv->tx_path_in_lpi_mode) -stmmac_disable_eee_mode (priv); - entry = tx_q->cur_tx; first_entry = entry;
@@ -3638,11 +3648,13 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id) &priv->xstats);if (unlikely (status)) { +spin_lock (&priv->lpi_lock);/* For LPI we need to save the tx status */ if (status &CORE_IRQ_TX_PATH_IN_LPI_MODE ) priv->tx_path_in_lpi_mode = true;if (status &CORE_IRQ_TX_PATH_EXIT_LPI_MODE ) priv->tx_path_in_lpi_mode = false; +spin_unlock (&priv->lpi_lock); }if (priv->synopsys_id >=DWMAC_CORE_4_00 ) {
@@ -4196,6 +4208,7 @@ int stmmac_dvr_probe(struct device *device, }spin_lock_init (&priv->lock); +spin_lock_init (&priv->lpi_lock);/* If a specific clk_csr value is passed from the platform * this means that the CSR Clock Range selection cannot be
Signature · 1 line
2.14.1
On 5 Jan. 2018 01:36, "Tomer Maimon" <[email protected]> wrote:
Bypass for lpi eee hang issue in the
STMicroelectronics 10/100/1000 Ethernet driver
Can you please submit this one upstream?
If you need advice on how to do this then let me know.
Cheers,
Joel
--- drivers/net/ethernet/stmicro/stmmac/stmmac.h | 1 + drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 27 +++++++++++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-)
(quoted diff) +0 -0
b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index a916e13624eb..c19bec963e28 100644
drivers/net/ethernet/stmicro/stmmac/stmmac.h +1 -0
@@ -136,6 +136,7 @@ struct stmmac_priv {int use_riwt;int irq_wake;spinlock_t ptp_lock; +spinlock_t lpi_lock;void __iomem *mmcaddr;void __iomem *ptpaddr;u32 mss;
(quoted diff) +0 -0
b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 1763e48c84e2..4c8c7a463f40 100644
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +0 -0
@@ -333,9 +333,13 @@ static void stmmac_enable_eee_mode(struct stmmac_priv
*priv)
*/
void stmmac_disable_eee_mode(struct stmmac_priv *priv) {
+ unsigned long flags;
+
priv->hw->mac->reset_eee_mode(priv->hw);
del_timer_sync(&priv->eee_ctrl_timer);
+ spin_lock_irqsave(&priv->lpi_lock, flags);
priv->tx_path_in_lpi_mode = false;+ spin_unlock_irqrestore(&priv->lpi_lock, flags);
}
/**
@@ -1872,6 +1876,7 @@ static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue)
netdev_tx_completed_queue(netdev_get_tx_queue(priv->dev, queue),
pkts_compl, bytes_compl);+ netif_tx_unlock(priv->dev);
if (unlikely(netif_tx_queue_stopped(netdev_get_tx_queue(priv->dev,
queue))) &&
@@ -1882,11 +1887,16 @@ static void stmmac_tx_clean(struct stmmac_priv
*priv, u32 queue)
netif_tx_wake_queue(netdev_get_tx_queue(priv->dev, queue));
}- if ((priv->eee_enabled) && (!priv->tx_path_in_lpi_mode)) {
- stmmac_enable_eee_mode(priv);
- mod_timer(&priv->eee_ctrl_timer, STMMAC_LPI_T(eee_timer));
+ if (priv->eee_enabled) {
+ unsigned long flags;
+
+ spin_lock_irqsave(&priv->lpi_lock, flags);
+ if (!priv->tx_path_in_lpi_mode)
+ mod_timer(&priv->eee_ctrl_timer,
+ STMMAC_LPI_T(eee_timer));
+
+ spin_unlock_irqrestore(&priv->lpi_lock, flags);
}- netif_tx_unlock(priv->dev);
}
static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv, u32
chan)
@@ -2968,6 +2978,9 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
unsigned int enh_desc;
unsigned int des;+ if (priv->tx_path_in_lpi_mode)
+ stmmac_disable_eee_mode(priv);
+
tx_q = &priv->tx_queue[queue];
/* Manage oversized TCP frames for GMAC4 device */
@@ -2988,9 +3001,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb,
struct net_device *dev)
return NETDEV_TX_BUSY;
}- if (priv->tx_path_in_lpi_mode)
- stmmac_disable_eee_mode(priv);
-
entry = tx_q->cur_tx;
first_entry = entry;@@ -3638,11 +3648,13 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)
&priv->xstats);
if (unlikely(status)) {
+ spin_lock(&priv->lpi_lock);
/* For LPI we need to save the tx status */
if (status & CORE_IRQ_TX_PATH_IN_LPI_MODE)
priv->tx_path_in_lpi_mode = true;
if (status & CORE_IRQ_TX_PATH_EXIT_LPI_MODE)
priv->tx_path_in_lpi_mode = false;
+ spin_unlock(&priv->lpi_lock);
}
if (priv->synopsys_id >= DWMAC_CORE_4_00) {
@@ -4196,6 +4208,7 @@ int stmmac_dvr_probe(struct device *device,
}
spin_lock_init(&priv->lock);+ spin_lock_init(&priv->lpi_lock);
/* If a specific clk_csr value is passed from the platform
* this means that the CSR Clock Range selection cannot be
--
2.14.1