[linux,dev-4.13,v1] net: stmmac: bypass for lpi eee hang issue

Message ID 1515076573-6732-1-git-send-email-tmaimon77@gmail.com
State New
Headers show
Series
  • [linux,dev-4.13,v1] net: stmmac: bypass for lpi eee hang issue
Related show

Commit Message

Tomer Maimon Jan. 4, 2018, 2:36 p.m.
Bypass for lpi eee hang issue in the
STMicroelectronics 10/100/1000 Ethernet driver

Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac.h      |  1 +
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 27 +++++++++++++++++------
 2 files changed, 21 insertions(+), 7 deletions(-)

Comments

Joel Stanley Jan. 5, 2018, 1:54 a.m. | #1
On 5 Jan. 2018 01:36, "Tomer Maimon" <tmaimon77@gmail.com> wrote:

Bypass for lpi eee hang issue in the
STMicroelectronics 10/100/1000 Ethernet driver

Signed-off-by: Tomer Maimon <tmaimon77@gmail.com>


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(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index a916e13624eb..c19bec963e28 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -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;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 1763e48c84e2..4c8c7a463f40 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -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
<div dir="auto"><div><br><div class="gmail_extra"><br><div class="gmail_quote">On 5 Jan. 2018 01:36, &quot;Tomer Maimon&quot; &lt;<a href="mailto:tmaimon77@gmail.com">tmaimon77@gmail.com</a>&gt; wrote:<br type="attribution"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Bypass for lpi eee hang issue in the<br>
STMicroelectronics 10/100/1000 Ethernet driver<br>
<br>
Signed-off-by: Tomer Maimon &lt;<a href="mailto:tmaimon77@gmail.com">tmaimon77@gmail.com</a>&gt;<br></blockquote></div></div></div><div dir="auto"><br></div><div dir="auto">Can you please submit this one upstream?</div><div dir="auto"><br></div><div dir="auto">If you need advice on how to do this then let me know.</div><div dir="auto"><br></div><div dir="auto">Cheers,</div><div dir="auto"><br></div><div dir="auto">Joel</div><div dir="auto"><br></div><div dir="auto"><div class="gmail_extra"><div class="gmail_quote"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
---<br>
 drivers/net/ethernet/stmicro/<wbr>stmmac/stmmac.h      |  1 +<br>
 drivers/net/ethernet/stmicro/<wbr>stmmac/stmmac_main.c | 27 +++++++++++++++++------<br>
 2 files changed, 21 insertions(+), 7 deletions(-)<br>
<br>
diff --git a/drivers/net/ethernet/<wbr>stmicro/stmmac/stmmac.h b/drivers/net/ethernet/<wbr>stmicro/stmmac/stmmac.h<br>
index a916e13624eb..c19bec963e28 100644<br>
--- a/drivers/net/ethernet/<wbr>stmicro/stmmac/stmmac.h<br>
+++ b/drivers/net/ethernet/<wbr>stmicro/stmmac/stmmac.h<br>
@@ -136,6 +136,7 @@ struct stmmac_priv {<br>
        int use_riwt;<br>
        int irq_wake;<br>
        spinlock_t ptp_lock;<br>
+       spinlock_t lpi_lock;<br>
        void __iomem *mmcaddr;<br>
        void __iomem *ptpaddr;<br>
        u32 mss;<br>
diff --git a/drivers/net/ethernet/<wbr>stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/<wbr>stmicro/stmmac/stmmac_main.c<br>
index 1763e48c84e2..4c8c7a463f40 100644<br>
--- a/drivers/net/ethernet/<wbr>stmicro/stmmac/stmmac_main.c<br>
+++ b/drivers/net/ethernet/<wbr>stmicro/stmmac/stmmac_main.c<br>
@@ -333,9 +333,13 @@ static void stmmac_enable_eee_mode(struct stmmac_priv *priv)<br>
  */<br>
 void stmmac_disable_eee_mode(struct stmmac_priv *priv)<br>
 {<br>
+       unsigned long flags;<br>
+<br>
        priv-&gt;hw-&gt;mac-&gt;reset_eee_mode(<wbr>priv-&gt;hw);<br>
        del_timer_sync(&amp;priv-&gt;eee_<wbr>ctrl_timer);<br>
+       spin_lock_irqsave(&amp;priv-&gt;lpi_<wbr>lock, flags);<br>
        priv-&gt;tx_path_in_lpi_mode = false;<br>
+       spin_unlock_irqrestore(&amp;priv-&gt;<wbr>lpi_lock, flags);<br>
 }<br>
<br>
 /**<br>
@@ -1872,6 +1876,7 @@ static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue)<br>
<br>
        netdev_tx_completed_queue(<wbr>netdev_get_tx_queue(priv-&gt;dev, queue),<br>
                                  pkts_compl, bytes_compl);<br>
+       netif_tx_unlock(priv-&gt;dev);<br>
<br>
        if (unlikely(netif_tx_queue_<wbr>stopped(netdev_get_tx_queue(<wbr>priv-&gt;dev,<br>
                                                                queue))) &amp;&amp;<br>
@@ -1882,11 +1887,16 @@ static void stmmac_tx_clean(struct stmmac_priv *priv, u32 queue)<br>
                netif_tx_wake_queue(netdev_<wbr>get_tx_queue(priv-&gt;dev, queue));<br>
        }<br>
<br>
-       if ((priv-&gt;eee_enabled) &amp;&amp; (!priv-&gt;tx_path_in_lpi_mode)) {<br>
-               stmmac_enable_eee_mode(priv);<br>
-               mod_timer(&amp;priv-&gt;eee_ctrl_<wbr>timer, STMMAC_LPI_T(eee_timer));<br>
+       if (priv-&gt;eee_enabled) {<br>
+               unsigned long flags;<br>
+<br>
+               spin_lock_irqsave(&amp;priv-&gt;lpi_<wbr>lock, flags);<br>
+               if (!priv-&gt;tx_path_in_lpi_mode)<br>
+                       mod_timer(&amp;priv-&gt;eee_ctrl_<wbr>timer,<br>
+                                 STMMAC_LPI_T(eee_timer));<br>
+<br>
+               spin_unlock_irqrestore(&amp;priv-&gt;<wbr>lpi_lock, flags);<br>
        }<br>
-       netif_tx_unlock(priv-&gt;dev);<br>
 }<br>
<br>
 static inline void stmmac_enable_dma_irq(struct stmmac_priv *priv, u32 chan)<br>
@@ -2968,6 +2978,9 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)<br>
        unsigned int enh_desc;<br>
        unsigned int des;<br>
<br>
+       if (priv-&gt;tx_path_in_lpi_mode)<br>
+               stmmac_disable_eee_mode(priv);<br>
+<br>
        tx_q = &amp;priv-&gt;tx_queue[queue];<br>
<br>
        /* Manage oversized TCP frames for GMAC4 device */<br>
@@ -2988,9 +3001,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)<br>
                return NETDEV_TX_BUSY;<br>
        }<br>
<br>
-       if (priv-&gt;tx_path_in_lpi_mode)<br>
-               stmmac_disable_eee_mode(priv);<br>
-<br>
        entry = tx_q-&gt;cur_tx;<br>
        first_entry = entry;<br>
<br>
@@ -3638,11 +3648,13 @@ static irqreturn_t stmmac_interrupt(int irq, void *dev_id)<br>
                                                            &amp;priv-&gt;xstats);<br>
<br>
                if (unlikely(status)) {<br>
+                       spin_lock(&amp;priv-&gt;lpi_lock);<br>
                        /* For LPI we need to save the tx status */<br>
                        if (status &amp; CORE_IRQ_TX_PATH_IN_LPI_MODE)<br>
                                priv-&gt;tx_path_in_lpi_mode = true;<br>
                        if (status &amp; CORE_IRQ_TX_PATH_EXIT_LPI_<wbr>MODE)<br>
                                priv-&gt;tx_path_in_lpi_mode = false;<br>
+                       spin_unlock(&amp;priv-&gt;lpi_lock);<br>
                }<br>
<br>
                if (priv-&gt;synopsys_id &gt;= DWMAC_CORE_4_00) {<br>
@@ -4196,6 +4208,7 @@ int stmmac_dvr_probe(struct device *device,<br>
        }<br>
<br>
        spin_lock_init(&amp;priv-&gt;lock);<br>
+       spin_lock_init(&amp;priv-&gt;lpi_<wbr>lock);<br>
<br>
        /* If a specific clk_csr value is passed from the platform<br>
         * this means that the CSR Clock Range selection cannot be<br>
<font color="#888888">--<br>
2.14.1<br>
<br>
</font></blockquote></div><br></div></div></div>

Patch

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac.h b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
index a916e13624eb..c19bec963e28 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac.h
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac.h
@@ -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;
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 1763e48c84e2..4c8c7a463f40 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -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