[PATCH] stmmac: Don't access tx_q->dirty_tx before netif_tx_lock

2017-10-21 Thread Bernd Edlinger
This is the possible reason for different hard to reproduce
problems on my ARMv7-SMP test system.

The symptoms are in recent kernels imprecise external aborts,
and in older kernels various kinds of network stalls and
unexpected page allocation failures.

My testing indicates that the trouble started between v4.5 and v4.6
and prevails up to v4.14.

Using the dirty_tx before acquiring the spin lock is clearly
wrong and was first introduced with v4.6.

Fixes: e3ad57c96715 ("stmmac: review RX/TX ring management")

Signed-off-by: Bernd Edlinger <bernd.edlin...@hotmail.de>
---
 drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c 
b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
index 1763e48..c8e280fa 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
@@ -1800,12 +1800,13 @@ static void stmmac_tx_clean(struct stmmac_priv *priv, 
u32 queue)
 {
struct stmmac_tx_queue *tx_q = >tx_queue[queue];
unsigned int bytes_compl = 0, pkts_compl = 0;
-   unsigned int entry = tx_q->dirty_tx;
+   unsigned int entry;
 
netif_tx_lock(priv->dev);
 
priv->xstats.tx_clean++;
 
+   entry = tx_q->dirty_tx;
while (entry != tx_q->cur_tx) {
struct sk_buff *skb = tx_q->tx_skbuff[entry];
struct dma_desc *p;
-- 
1.9.1


[PATCHv2] Add a driver for Renesas uPD60620 and uPD60620A PHYs

2017-10-08 Thread Bernd Edlinger
Signed-off-by: Bernd Edlinger <bernd.edlin...@hotmail.de>
---
 drivers/net/phy/Kconfig|   5 +++
 drivers/net/phy/Makefile   |   1 +
 drivers/net/phy/uPD60620.c | 109 +
 3 files changed, 115 insertions(+)
 create mode 100644 drivers/net/phy/uPD60620.c

diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index cd931cf..e2cf8ff 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -366,6 +366,11 @@ config REALTEK_PHY
---help---
  Supports the Realtek 821x PHY.
 
+config RENESAS_PHY
+   tristate "Driver for Renesas PHYs"
+   ---help---
+ Supports the Renesas PHYs uPD60620 and uPD60620A.
+
 config ROCKCHIP_PHY
 tristate "Driver for Rockchip Ethernet PHYs"
 ---help---
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 416df92..1404ad3 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -72,6 +72,7 @@ obj-$(CONFIG_MICROSEMI_PHY)   += mscc.o
 obj-$(CONFIG_NATIONAL_PHY) += national.o
 obj-$(CONFIG_QSEMI_PHY)+= qsemi.o
 obj-$(CONFIG_REALTEK_PHY)  += realtek.o
+obj-$(CONFIG_RENESAS_PHY)  += uPD60620.o
 obj-$(CONFIG_ROCKCHIP_PHY) += rockchip.o
 obj-$(CONFIG_SMSC_PHY) += smsc.o
 obj-$(CONFIG_STE10XP)  += ste10Xp.o
diff --git a/drivers/net/phy/uPD60620.c b/drivers/net/phy/uPD60620.c
new file mode 100644
index 000..96b3347
--- /dev/null
+++ b/drivers/net/phy/uPD60620.c
@@ -0,0 +1,109 @@
+/*
+ * Driver for the Renesas PHY uPD60620.
+ *
+ * Copyright (C) 2015 Softing Industrial Automation GmbH
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#define UPD60620_PHY_ID0xb8242824
+
+/* Extended Registers and values */
+/* PHY Special Control/Status*/
+#define PHY_PHYSCR 0x1F  /* PHY.31 */
+#define PHY_PHYSCR_10MB0x0004/* PHY speed = 10mb */
+#define PHY_PHYSCR_100MB   0x0008/* PHY speed = 100mb */
+#define PHY_PHYSCR_DUPLEX  0x0010/* PHY Duplex */
+
+/* PHY Special Modes */
+#define PHY_SPM0x12  /* PHY.18 */
+
+/* Init PHY */
+
+static int upd60620_config_init(struct phy_device *phydev)
+{
+   /* Enable support for passive HUBs (could be a strap option) */
+   /* PHYMODE: All speeds, HD in parallel detect */
+   return phy_write(phydev, PHY_SPM, 0x0180 | phydev->mdio.addr);
+}
+
+/* Get PHY status from common registers */
+
+static int upd60620_read_status(struct phy_device *phydev)
+{
+   int phy_state;
+
+   /* Read negotiated state */
+   phy_state = phy_read(phydev, MII_BMSR);
+   if (phy_state < 0)
+   return phy_state;
+
+   phydev->link = 0;
+   phydev->lp_advertising = 0;
+   phydev->pause = 0;
+   phydev->asym_pause = 0;
+
+   if (phy_state & (BMSR_ANEGCOMPLETE | BMSR_LSTATUS)) {
+   phy_state = phy_read(phydev, PHY_PHYSCR);
+   if (phy_state < 0)
+   return phy_state;
+
+   if (phy_state & (PHY_PHYSCR_10MB | PHY_PHYSCR_100MB)) {
+   phydev->link = 1;
+   phydev->speed = SPEED_10;
+   phydev->duplex = DUPLEX_HALF;
+
+   if (phy_state & PHY_PHYSCR_100MB)
+   phydev->speed = SPEED_100;
+   if (phy_state & PHY_PHYSCR_DUPLEX)
+   phydev->duplex = DUPLEX_FULL;
+
+   phy_state = phy_read(phydev, MII_LPA);
+   if (phy_state < 0)
+   return phy_state;
+
+   phydev->lp_advertising
+   = mii_lpa_to_ethtool_lpa_t(phy_state);
+
+   if (phydev->duplex == DUPLEX_FULL) {
+   if (phy_state & LPA_PAUSE_CAP)
+   phydev->pause = 1;
+   if (phy_state & LPA_PAUSE_ASYM)
+   phydev->asym_pause = 1;
+   }
+   }
+   }
+   return 0;
+}
+
+MODULE_DESCRIPTION("Renesas uPD60620 PHY driver");
+MODULE_AUTHOR("Bernd Edlinger <bernd.edlin...@hotmail.de>");
+MODULE_LICENSE("GPL");
+
+static struct phy_driver upd60620_driver[1] = { {
+   .phy_id = UPD60620_PHY_ID,
+   .phy_id_mask= 0xfffe,
+   .name   = "Renesas uPD60620",
+   .features   = PHY_BASIC_FEATURES,
+   .flags  = 0,
+   .config_init= upd60620_config_init,
+   .config_aneg= genphy_confi

Re: [PATCH] Add a driver for Renesas uPD60620 and uPD60620A PHYs

2017-10-08 Thread Bernd Edlinger
Hi Andrew,

sorry for delayed reply.
Looks like I did not receive a copy of your e-mail.

 >> Do you suggest that there are cases where auto negotiation does not
 >> reach completion, and still provides a usable link status?
 >
 > My experience is that it often return 10/half, since everything should
 > support that. And depending on what the MAC is doing, packets can
 > sometime get across the link.
 >>
 >> I have tried to connect to link partners with fixed configuration
 >> but even then the auto negotiation always competes normally.
 >
 > Which is a bit odd.
 >
 > There are a few different possibilities here.  The peer PHY driver is
 > broken. Rather than doing fixed, it actually set the possible
 > negotiation options to just the one setting you tried to fix it
 > to. And hence the uPD60620 device negotiated fine. Or the uPD60620 is
 > broken is said it negotiated, but in fact it failed.
 >
 > What was the result? 10/Half, or the fixed values you set the peer to?

This is a dual-channel PHY, so I did just connect both ports and
played with the mii-tool -F / -A in different combinations on each
port and observed what happens when the cable is plugged in.

What happens is that the port with autonegotiation enabled detects
the correct speed and always half duplex, so the ASIC _pretends_ that
autonegotiatiation completes, when in fact only parallel detection
succeeded.  Of course the other phy may be in full-duplex mode, but
that can not be detected by parallel detection.

The duplex mode would be full duplex by default, but my initialization
overrides a possible strap option and changes that to half duplex:

+   /* Enable support for passive HUBs (could be a strap option) */
+   /* PHYMODE: All speeds, HD in parallel detect */
+   return phy_write(phydev, PHY_SPM, 0x0180 | phydev->mdio.addr);

 >>
 >> Signed-off-by: Bernd Edlinger <bernd.edlin...@hotmail.de>
 >
 > Please send this is a new patch. If we were to take this is is, all
 > the comments above would end up in the commit message.
 >
 > ---
 >
 > Under the --- you can however add comments which don't go into the
 > commit log. Good practice is to list the things you changed since the
 > previous version.

Thanks, I did not know that.
I will re-send the patch in a new thread.

Bernd.


Re: [PATCH] Add a driver for Renesas uPD60620 and uPD60620A PHYs

2017-09-28 Thread Bernd Edlinger
On 09/22/17 19:59, Andrew Lunn wrote:
> On Fri, Sep 22, 2017 at 05:08:45PM +0000, Bernd Edlinger wrote:
>>
>> +config RENESAS_PHY
>> +tristate "Driver for Renesas PHYs"
>> +---help---
>> +  Supports the uPD60620 and uPD60620A PHYs.
>> +
> 
> Hi Bernd
> 
> Please call this "Reneseas PHYs" and place in it alphabetical order.
> 

Done.

>> +
>> +/* Extended Registers and values */
>> +/* PHY Special Control/Status*/
>> +#define PHY_PHYSCR 0x1F  /* PHY.31 */
>> +#define PHY_PHYSCR_10MB0x0004/* PHY speed = 10mb */
>> +#define PHY_PHYSCR_100MB   0x0008/* PHY speed = 100mb */
>> +#define PHY_PHYSCR_DUPLEX  0x0010/* PHY Duplex */
>> +#define PHY_PHYSCR_RSVD5   0x0020/* Reserved Bit 5 */
>> +#define PHY_PHYSCR_MIIMOD  0x0040/* Enable 4B5B MII mode */
> 
> Are any of these comments actually useful. It seems like the defines
> are pretty obvious.
> 
>> +#define PHY_PHYSCR_RSVD7   0x0080/* Reserved Bit 7 */
>> +#define PHY_PHYSCR_RSVD8   0x0100/* Reserved Bit 8 */
>> +#define PHY_PHYSCR_RSVD9   0x0200/* Reserved Bit 9 */
>> +#define PHY_PHYSCR_RSVD10  0x0400/* Reserved Bit 10 */
>> +#define PHY_PHYSCR_RSVD11  0x0800/* Reserved Bit 11 */
>> +#define PHY_PHYSCR_ANDONE  0x1000/* Auto negotiation done */
>> +#define PHY_PHYSCR_RSVD13  0x2000/* Reserved Bit 13 */
>> +#define PHY_PHYSCR_RSVD14  0x4000/* Reserved Bit 14 */
>> +#define PHY_PHYSCR_RSVD15  0x8000/* Reserved Bit 15 */
> 
> It looks like the only register you use is SCR and SPM. Maybe delete
> all the rest? Or do you plan to add more features making use of these
> registers?
> 

No, I removed all unused defines for now.

>> +phydev->link = 0;
>> +phydev->lp_advertising = 0;
>> +phydev->pause = 0;
>> +phydev->asym_pause = 0;
>> +
>> +if (phy_state & BMSR_ANEGCOMPLETE) {
> 
> It is worth comparing this against genphy_read_status() which is the
> reference implementation. You would normally check if auto negotiation
> is enabled, not if it has completed. If it is enabled you read the
> current negotiated state, even if it is not completed.
> 

Do you suggest that there are cases where auto negotiation does not
reach completion, and still provides a usable link status?

I have tried to connect to link partners with fixed configuration
but even then the auto negotiation always competes normally.
 

>> +phy_state = phy_read(phydev, PHY_PHYSCR);
>> +if (phy_state < 0)
>> +return phy_state;
>> +
>> +if (phy_state & (PHY_PHYSCR_10MB | PHY_PHYSCR_100MB)) {
>> +phydev->link = 1;
>> +phydev->speed = SPEED_10;
>> +phydev->duplex = DUPLEX_HALF;
>> +
>> +if (phy_state & PHY_PHYSCR_100MB)
>> +phydev->speed = SPEED_100;
>> +if (phy_state & PHY_PHYSCR_DUPLEX)
>> +phydev->duplex = DUPLEX_FULL;
>> +
>> +phy_state = phy_read(phydev, MII_LPA);
>> +if (phy_state < 0)
>> +return phy_state;
>> +
>> +phydev->lp_advertising
>> += mii_lpa_to_ethtool_lpa_t(phy_state);
>> +
>> +if (phydev->duplex == DUPLEX_FULL) {
>> +if (phy_state & LPA_PAUSE_CAP)
>> +phydev->pause = 1;
>> +if (phy_state & LPA_PAUSE_ASYM)
>> +phydev->asym_pause = 1;
>> +}
>> +}
>> +} else if (phy_state & BMSR_LSTATUS) {
> 
> The else clause is then for a fixed configuration. Since all you are
> looking at is BMCR, you can probably just cut/paste from
> genphy_read_status().
> 

I think I can fold the fixed speed case in the auto negotiation case:
The PHYSCR has always the correct values for fixed settings.
I was initially unsure if I should look at it while autonegotiation is
not complete, but as you pointed out, that is the generally accepted
practice.


Thanks
Bernd.


>From 2e101aed8466b314251972d1eaccfb43cf177078 Mon Sep 17 00:00:00 2001
From: Bernd Edlinger <bernd.edlin...@hotmail.de>
Date: Thu, 21 Sep 2017 15:46:16 +0200
Subject: [PATCH 2/5] Add a driver for Renesas uPD60620 and uPD60620A PHYs.

Signed-off-by: Bernd Edlinger <bernd.edlin...@hotmail.de>
---
 drivers/net/p

[PATCH] Add a driver for Renesas uPD60620 and uPD60620A PHYs

2017-09-22 Thread Bernd Edlinger
Signed-off-by: Bernd Edlinger <bernd.edlin...@hotmail.de>
---
  drivers/net/phy/Kconfig|   5 +
  drivers/net/phy/Makefile   |   1 +
  drivers/net/phy/uPD60620.c | 226 
+
  3 files changed, 232 insertions(+)
  create mode 100644 drivers/net/phy/uPD60620.c

diff --git a/drivers/net/phy/Kconfig b/drivers/net/phy/Kconfig
index a9d16a3..25089f0 100644
--- a/drivers/net/phy/Kconfig
+++ b/drivers/net/phy/Kconfig
@@ -287,6 +287,11 @@ config DP83867_PHY
---help---
  Currently supports the DP83867 PHY.

+config RENESAS_PHY
+   tristate "Driver for Renesas PHYs"
+   ---help---
+ Supports the uPD60620 and uPD60620A PHYs.
+
  config FIXED_PHY
tristate "MDIO Bus/PHY emulation with fixed speed/link PHYs"
depends on PHYLIB
diff --git a/drivers/net/phy/Makefile b/drivers/net/phy/Makefile
index 416df92..1404ad3 100644
--- a/drivers/net/phy/Makefile
+++ b/drivers/net/phy/Makefile
@@ -72,6 +72,7 @@ obj-$(CONFIG_MICROSEMI_PHY)   += mscc.o
  obj-$(CONFIG_NATIONAL_PHY)+= national.o
  obj-$(CONFIG_QSEMI_PHY)   += qsemi.o
  obj-$(CONFIG_REALTEK_PHY) += realtek.o
+obj-$(CONFIG_RENESAS_PHY)  += uPD60620.o
  obj-$(CONFIG_ROCKCHIP_PHY)+= rockchip.o
  obj-$(CONFIG_SMSC_PHY)+= smsc.o
  obj-$(CONFIG_STE10XP) += ste10Xp.o
diff --git a/drivers/net/phy/uPD60620.c b/drivers/net/phy/uPD60620.c
new file mode 100644
index 000..b3d900c
--- /dev/null
+++ b/drivers/net/phy/uPD60620.c
@@ -0,0 +1,226 @@
+/*
+ * Driver for the Renesas PHY uPD60620.
+ *
+ * Copyright (C) 2015 Softing Industrial Automation GmbH
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *
+ */
+
+#include 
+#include 
+#include 
+
+#define UPD60620_PHY_ID0xb8242824
+
+/* Extended Registers and values */
+/* PHY Special Control/Status*/
+#define PHY_PHYSCR 0x1F  /* PHY.31 */
+#define PHY_PHYSCR_10MB0x0004/* PHY speed = 10mb */
+#define PHY_PHYSCR_100MB   0x0008/* PHY speed = 100mb */
+#define PHY_PHYSCR_DUPLEX  0x0010/* PHY Duplex */
+#define PHY_PHYSCR_RSVD5   0x0020/* Reserved Bit 5 */
+#define PHY_PHYSCR_MIIMOD  0x0040/* Enable 4B5B MII mode */
+#define PHY_PHYSCR_RSVD7   0x0080/* Reserved Bit 7 */
+#define PHY_PHYSCR_RSVD8   0x0100/* Reserved Bit 8 */
+#define PHY_PHYSCR_RSVD9   0x0200/* Reserved Bit 9 */
+#define PHY_PHYSCR_RSVD10  0x0400/* Reserved Bit 10 */
+#define PHY_PHYSCR_RSVD11  0x0800/* Reserved Bit 11 */
+#define PHY_PHYSCR_ANDONE  0x1000/* Auto negotiation done */
+#define PHY_PHYSCR_RSVD13  0x2000/* Reserved Bit 13 */
+#define PHY_PHYSCR_RSVD14  0x4000/* Reserved Bit 14 */
+#define PHY_PHYSCR_RSVD15  0x8000/* Reserved Bit 15 */
+
+/* PHY Global Config Mapping */
+#define PHY_GLOBAL_CONFIG  0x07
+/* PHY GPIO Config Register 1 */
+#define PHY_GPIO_CONFIG1   0x01 /* PHY 7.1 */
+#define PHY_GPIO4_INT0 0x000d   /* GPIO4 configuration */
+#define PHY_GPIO5_INT1 0x00d0   /* GPIO5 configuration */
+
+/* PHY Interrupt Control Register */
+#define PHY_ICR0x1e  /* PHY.30 */
+#define PHY_ICR_RSVD0  0x0001/* Reserved bit 0 */
+#define PHY_ICR_ANCPRRN0x0002/* Auto negotiation paged received */
+#define PHY_ICR_PDFEN  0x0004/* Parallel detection fault */
+#define PHY_ICR_ANCLPAEN   0x0008/* Auto negotiation last page ack */
+#define PHY_ICR_LNKINTEN   0x0010/* Link down */
+#define PHY_ICR_REMFD  0x0020/* Remote fault detected */
+#define PHY_ICR_ANCINTEN   0x0040/* Auto negotiation complete */
+#define PHY_ICR_EOEN   0x0080/* Energy on generated */
+#define PHY_ICR_RSVD8  0x0100/* Reserved bit 8 */
+#define PHY_ICR_FEQTRGEN   0x0200/* FEQ Trigger */
+#define PHY_ICR_BERTRGEN   0x0400/* BER Counter Trigger */
+#define PHY_ICR_MLINTEN0x0800/* Maxlvl */
+#define PHY_ICR_CLPINTEN   0x1000/* Clipping */
+#define PHY_ICR_RSVD13 0x2000/* Reserved bit 13 */
+#define PHY_ICR_RSVD14 0x4000/* Reserved bit 14 */
+#define PHY_ICR_RSVD15 0x8000/* Reserved bit 15 */
+
+/* PHY Interrupt Status Register */
+#define PHY_ISR0x1d  /* PHY.29 */
+#define PHY_ISR_DUPINT 0x/* Placeholder for Duplex/Speed 
intr */
+#define PHY_ISR_RSVD0  0x0001/* Reserved bit 0 */
+#define PHY_ISR_ANCPR  0x0002/* Auto negotiation paged received */
+#define PHY_ISR_PDF0x0004/* Parallel detection fault */
+#define PHY_ISR_ANCLPA 0x0008/* Auto negotiation last page ack */
+#define PHY_ISR_LNKINT 0x0010/* Link down */
+#define PHY_ISR_REMFD  0x0020/* Remote fault detected */
+#define PHY_ISR_ANCINT 0x0040/* Auto negotiation compl