Re: [PATCH 2/3] rockchip: fix wrong PCI range address in rk3568 dtsi

2024-07-07 Thread Etienne Dublé




Le 25/06/2024 à 13:31, Etienne Dublé a écrit :

The bus addresses should be isolated to each pci controller if I am not
mistaken, so changing the bus address was probably just done as a
workaround because of some other unknown bug.


OK.


Hum, could be an issue in pci core of U-Boot that expect unique bus
addresses across all pci controllers.

Will run some quick tests on my R5C later.


OK, thanks for looking at it.



Hello Jonas,

Could you have a look at this issue with the 2nd interface on the nanopi 
r5c, and your idea about a possible issue in U-Boot core about 
non-unique PCI bus addresses?


Thanks,
Etienne


--
Etienne Dublé
CNRS / LIG - Bâtiment IMAG
700 avenue Centrale - 38401 St Martin d'Hères
Bureau 426 - Tel 0457421431



Re: [PATCH 1/3] net: give a different name to rtl8169 interfaces

2024-06-27 Thread Etienne Dublé



Hi Quentin,

Le 27/06/2024 à 14:27, Quentin Schulz a écrit :

Hi Etienne,

On 6/25/24 1:42 PM, Etienne Dublé wrote:


Hello,

Le 25/06/2024 à 12:25, Dragan Simic a écrit :
Another option may be to name them "rtl8169@", with "" 
reflecting the PCI region address (so it is unique and stable). 
What do you think?


I guess that's one way, I'm also wondering how systemd renames those
to be unique but stable on the same machine, maybe we could take some
inspiration from them for that?


Systemd also allows renaming of network interfaces using some rules
predefined by the user, so there's also the possibility to rename the
interfaces in U-Boot to ethernet0 and ethernet1, using fixed rules
that would be based on the PCI region address.


OK but the renaming occurs in the rtl8169 driver, that is used by 
several boards, whereas the PCI region addresses come from the 
device-tree, so they differ from board to board.




I'm of the opinion that we only care about stability for the same 
product, not for different products with the same Ethernet PHY on 
different SoCs/products.


I agree, but my comment was more about how u-boot code is structured 
(network interface naming is done in the driver, and the driver code 
should probably not include board-specific code, so we are quite limited).
In theory we could just name the interfaces ethernet0, ethernet1, etc., 
by using the PCI region address as the sort key, and maybe this is what 
Dragan was suggesting. But in practice when driver->bind() is called we 
don't know if more interfaces will be discovered next; and renaming the 
1st interface when the 2nd one is discovered with a lower address is 
probably not the kind of code u-boot code experts would like...


Cheers,
Etienne Dublé

--
Etienne Dublé
CNRS / LIG - Bâtiment IMAG
700 avenue Centrale - 38401 St Martin d'Hères
Bureau 426 - Tel 0457421431


Re: [PATCH 1/3] net: give a different name to rtl8169 interfaces

2024-06-25 Thread Etienne Dublé



Hello,

Le 25/06/2024 à 12:25, Dragan Simic a écrit :
Another option may be to name them "rtl8169@", with "" 
reflecting the PCI region address (so it is unique and stable). What 
do you think?


I guess that's one way, I'm also wondering how systemd renames those
to be unique but stable on the same machine, maybe we could take some
inspiration from them for that?


Systemd also allows renaming of network interfaces using some rules
predefined by the user, so there's also the possibility to rename the
interfaces in U-Boot to ethernet0 and ethernet1, using fixed rules
that would be based on the PCI region address.


OK but the renaming occurs in the rtl8169 driver, that is used by 
several boards, whereas the PCI region addresses come from the 
device-tree, so they differ from board to board.


Regards,
Etienne

--
Etienne Dublé
CNRS / LIG - Bâtiment IMAG
700 avenue Centrale - 38401 St Martin d'Hères
Bureau 426 - Tel 0457421431


Re: [PATCH 2/3] rockchip: fix wrong PCI range address in rk3568 dtsi

2024-06-25 Thread Etienne Dublé



Hello Jonas,

Le 25/06/2024 à 12:46, Jonas Karlman a écrit :

Ahh, linux is still missing a patch to be able to use full address ranges
as a root complex.

Will re-run some tests on my R5C on both u-boot and linux to see if I can
replicate your issue.


OK.
To use the second interface in u-boot, you first need to provide a 
".bind()" member function in the rtl8169 driver, otherwise both 
interfaces have the same name (this is my [PATCH 1/3]).

Then :

Hit any key to stop autoboot:  0
=> pci enum
=> net list
eth0 : RTL8169#0 52:e8:a1:60:81:e7 active
eth1 : RTL8169#1 52:e8:a1:60:81:e6
=> setenv ethact "RTL8169#1"
=> dhcp

The issue appears when sending the first packet. When activating 
DEBUG_RTL8169_TX in rtl8169.c it prints "tx timeout/error".



The issue may be that U-Boot is not fully capable of having overlapping
bus addresses for multiple pci controllers.

To my knowledge these addresses should be internal to the pci controller
and its devices.

The addresses below tells us that system memory address 0x34000+,
and 0x38000+ is mapped to bus address 0x4000+ of each pci
controller.


I see.


[...]
So I verified in the downstream repository of the board vendor
(https://github.com/friendlyarm/uboot-rockchip/blob/nanopi5-v2017.09/arch/arm/dts/rk3568.dtsi#L1754C21-L1754C31
and the second address there was replaced with "*0x0* *0x8000*".
Then, updating this was enough to make the second interface work in u-boot.

The bus addresses should be isolated to each pci controller if I am not
mistaken, so changing the bus address was probably just done as a
workaround because of some other unknown bug.


OK.


Hum, could be an issue in pci core of U-Boot that expect unique bus
addresses across all pci controllers.

Will run some quick tests on my R5C later.


OK, thanks for looking at it. Regards, Etienne

--
Etienne Dublé
CNRS / LIG - Bâtiment IMAG
700 avenue Centrale - 38401 St Martin d'Hères
Bureau 426 - Tel 0457421431



Re: [PATCH 2/3] rockchip: fix wrong PCI range address in rk3568 dtsi

2024-06-25 Thread Etienne Dublé



Hello Jonas,

Le 25/06/2024 à 10:29, Jonas Karlman a écrit :

I do not understand the need for such/this patch. The changed address is
the internal io address that is shared with the pci controller and
devices.

Do you have any issue in linux or is it only in U-Boot?, I suspect this
change is only a workaround to an issue only found in U-Boot.


On my board (Nanopi R5C with two RTL-8125B interfaces) both RTL-8125B 
interfaces work in Linux, and only the first one works in u-boot.
But Linux is apparently using the second PCI region and u-boot is using 
the third (with the suspected address). These PCI regions are of the 
same type.



The rtl8169 driver or pci system of U-Boot may be of fault and should
probably be fixed instead of changing io addresses to work around issues
in software. E.g rtl8169 has a static ioaddr that is shared between all
drivers, something that may cause issues.


I am not an expert, but I really believe the issue comes from this 
address in the device tree.

We have these pcie entries in rk3568.dtsi:


    pcie3x1: pcie@fe27 {
[...]
    ranges = <0x0100 0x0 0xf210 0x0 0xf210 0x0 
0x0010>,
 <0x0200 0x0 0xf220 0x0 0xf220 0x0 
0x01e0>,
 <0x0300 *0x0* *0x4000* 0x3 0x4000 
0x0 0x4000>;

[...]
    }
[...]
    pcie3x2: pcie@fe28 {
[...]
    ranges = <0x0100 0x0 0xf010 0x0 0xf010 0x0 
0x0010>,
 <0x0200 0x0 0xf020 0x0 0xf020 0x0 
0x01e0>,
 <0x0300 *0x0* *0x4000* 0x3 0x8000 
0x0 0x4000>;

[...]
    }


Again, I am not an expert, but it seemed suspicious to me that those two 
entries were sharing the same PCI address.
So I verified in the downstream repository of the board vendor 
(https://github.com/friendlyarm/uboot-rockchip/blob/nanopi5-v2017.09/arch/arm/dts/rk3568.dtsi#L1754C21-L1754C31), 
and the second address there was replaced with "*0x0* *0x8000*".

Then, updating this was enough to make the second interface work in u-boot.

Like you, I initially suspected the code of rtl8169.c, which has many 
global & static variables, so I actually spent quite a lot of time on 
refactoring it, moving things to the private struct, but could never 
make it work until I found this suspecting PCI address.


Cheers,
Etienne

--
Etienne Dublé
CNRS / LIG - Bâtiment IMAG
700 avenue Centrale - 38401 St Martin d'Hères
Bureau 426 - Tel 0457421431



Re: [PATCH 2/3] rockchip: fix wrong PCI range address in rk3568 dtsi

2024-06-24 Thread Etienne Dublé

Hi Quentin,

Le 24/06/2024 à 15:15, Quentin Schulz a écrit :

Hi Etienne,

On 6/24/24 2:40 PM, ETIENNE DUBLE wrote:

One of the PCI ranges was wrong in this device tree.
When testing with a FriendlyElec Nanopi R5C board, the
2nd ethernet interface (labelled "wan") was not working
in u-boot because of that.

With the correct value (found in FriendlyElec's downstream
u-boot repository), this 2nd ethernet interface now works.

Signed-off-by: Etienne Dublé 
---

  dts/upstream/src/arm64/rockchip/rk3568.dtsi | 2 +-


dts/upstream is only for patches coming from **merged** Linux kernel 
(i.e. releases or -rc releases or master branch from Linus Torvalds).


We do not accept U-Boot-only patches in dts/upstream.

Please submit the patch to the Linux kernel first and it will 
eventually make it to that directory either via a 
dts/update-dts-subtree.sh pull or dts/update-dts-subtree.sh pick. 
Depending on maintainer's opinion, fixing the range in 
arch/arm/dts/rk3568-u-boot.dtsi could be an option, but we really need 
the patch sent to upstream Linux kernel community first.


c.f. https://www.kernel.org/doc/html/v6.5/process/submitting-patches.html


I see, I will look at it.
In version 2 of the series I will remove this second patch and just 
mention that we are waiting for this problem to be fixed upstream, in 
the cover letter.


Cheers,
Etienne

--
Etienne Dublé
CNRS / LIG - Bâtiment IMAG
700 avenue Centrale - 38401 St Martin d'Hères
Bureau 426 - Tel 0457421431


Re: [PATCH 1/3] net: give a different name to rtl8169 interfaces

2024-06-24 Thread Etienne Dublé

Hi Quentin,

Thanks for reviewing my patches.

Le 24/06/2024 à 15:08, Quentin Schulz a écrit :

[...]


  1 file changed, 11 insertions(+)

diff --git a/drivers/net/rtl8169.c b/drivers/net/rtl8169.c
index 93e83661ce..b30d51731f 100644
--- a/drivers/net/rtl8169.c
+++ b/drivers/net/rtl8169.c
@@ -1091,6 +1091,16 @@ static int rtl8169_eth_probe(struct udevice *dev)
  return 0;
  }
  +static int rtl8169_eth_bind(struct udevice *dev)
+{
+    static int card_number;
+    char name[16];
+
+    sprintf(name, "RTL8169#%u", card_number++);
+
+    return device_set_name(dev, name);
+}
+


I don't think we can guarantee bind order so this may not be stable 
over time.


I'm wondering if there isn't a way to use the "ethernet" (ethernet0, 
ethernet1) alias in DT instead?


Actually the ethernet interfaces are not declared in the device tree, 
only PCI buses are (at least on this Nanopi board).

The ethernet interfaces are only detected when running "pci enum".

Another option may be to name them "rtl8169@", with "" 
reflecting the PCI region address (so it is unique and stable). What do 
you think?


Cheers,
Etienne


--
Etienne Dublé
CNRS / LIG - Bâtiment IMAG
700 avenue Centrale - 38401 St Martin d'Hères
Bureau 426 - Tel 0457421431



Re: [PATCH v2] watchdog: Add a watchdog driver for Raspberry Pi boards

2023-01-25 Thread Etienne Dublé

Hi Stefan,


+/* The hardware supports a maximum timeout value of 0xf ticks
+ * (just below 16 seconds).
+ * U-boot users specify the timeout as a number of milliseconds
+ * by using variable CONFIG_WATCHDOG_TIMEOUT_MSECS.
+ * The maximum value should be 15999 ms in our case.
+ * However, u-boot internally converts this config value to seconds,
+ * thus specifying 15999 actually means 15000 ms (0xf ticks).


means 15999 ms?


No, 15000 ms.
Actually I observed that whatever value 15xxx I set in .config, the 
driver code is called with value 15000.
I suppose this is due to the code in wdt-uclass.c which converts the 
config value to an integer number of seconds.
So the limit I wrote in the code (15000 ms, 0xf ticks) is actually 
"the max value the user can specify in configuration", whereas the 
hardware limit is a little higher (0xf ticks).


However, thinking twice it is probably not a good idea to deal with the 
behavior of higher layers here.
So I will change back the driver limit to 0xf ticks and replace this 
long explanation with a minimal comment.



+
+    writel(PM_PASSWORD | timeout_ticks, base + PM_WDOG);
+    cur = readl(base + PM_RSTC);
+    writel(PM_PASSWORD | (cur & PM_RSTC_WRCFG_CLR) |
+  PM_RSTC_WRCFG_FULL_RESET, base + PM_RSTC);


This does not seem to be aligned with the "(" from the line above.

BTW: Please use scripts/checkpatch.pl to see, if the patch has no more
issues.


I did run it, but apparently it did not catch this one.
I will fix it.


+
+    if (priv->timeout_ticks > PM_WDOG_MAX_TICKS) {
+    printf("WARNING: bcm2835_wdt cannot handle large timeout 
values.\n");

+    printf(" Setting the max value of 15000 ms instead.\n");
+    printf(" Set CONFIG_WATCHDOG_TIMEOUT_MSECS=15000 at most "
+    "to avoid this warning.\n");


This seems way too long for a warning from this driver. Please shorten
it to one line. The comment above already covers this limitation AFAICT.


OK.

Thanks,
Etienne

--
Etienne Dublé
CNRS / LIG - Bâtiment IMAG
700 avenue Centrale - 38401 St Martin d'Hères
Bureau 426 - Tel 0457421431


Re: [PATCH] watchdog: Add a watchdog driver for Raspberry Pi boards

2023-01-24 Thread Etienne Dublé

Hi Stefan,
Thanks for the feedback.
I will send a v2 to fix those issues.
Regards,
Etienne


Le 24/01/2023 à 14:38, Stefan Roese a écrit :

Hi Etienne,

On 1/24/23 14:20, Etienne Dublé wrote:

This driver supports the bcm2835 watchdog found on
Raspberry Pi boards.
It is derived from the Linux driver and was tested
on two Raspberry Pi board versions (B+ and 3B+).

Signed-off-by: Etienne Dublé 
---

  drivers/watchdog/Kconfig   |   9 +++
  drivers/watchdog/Makefile  |   1 +
  drivers/watchdog/bcm2835_wdt.c | 135 +
  3 files changed, 145 insertions(+)
  create mode 100644 drivers/watchdog/bcm2835_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index f1b1cf63ca..06c0d630c8 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -30,6 +30,7 @@ config WATCHDOG_TIMEOUT_MSECS
  default 128000 if ARCH_MX7 || ARCH_VF610
  default 3 if ARCH_SOCFPGA
  default 16000 if ARCH_SUNXI
+    default 15000 if ARCH_BCM283X
  default 6
  help
    Watchdog timeout in msec
@@ -326,6 +327,14 @@ config WDT_SUNXI
  help
    Enable support for the watchdog timer in Allwinner sunxi SoCs.
  +config WDT_BCM2835
+    bool "Broadcom 2835 watchdog timer support"


Your patch seems to have whitespace problems. Please make sure to send
it e.g. via git send-email.

More comments below...


+    depends on WDT && ARCH_BCM283X
+    default y
+    help
+  Enable support for the watchdog timer in Broadcom 283X SoCs such
+  as Raspberry Pi boards.
+
  config XILINX_TB_WATCHDOG
  bool "Xilinx Axi watchdog timer support"
  depends on WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 446d961d7d..f99915960c 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_WDT_APPLE) += apple_wdt.o
  obj-$(CONFIG_WDT_ARMADA_37XX) += armada-37xx-wdt.o
  obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o
  obj-$(CONFIG_WDT_AST2600) += ast2600_wdt.o
+obj-$(CONFIG_WDT_BCM2835) += bcm2835_wdt.o
  obj-$(CONFIG_WDT_BCM6345) += bcm6345_wdt.o
  obj-$(CONFIG_WDT_BOOKE) += booke_wdt.o
  obj-$(CONFIG_WDT_CORTINA) += cortina_wdt.o
diff --git a/drivers/watchdog/bcm2835_wdt.c 
b/drivers/watchdog/bcm2835_wdt.c

new file mode 100644
index 00..48535c003f
--- /dev/null
+++ b/drivers/watchdog/bcm2835_wdt.c
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2013 Lubomir Rintel 
+ * Copyright (C) 2023 Etienne Dublé (CNRS) 
+ *
+ * This code is mostly derived from the linux driver.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#define PM_RSTC    0x1c
+#define PM_WDOG    0x24
+
+#define PM_PASSWORD    0x5a00
+
+/* The hardware supports a maximum timeout value of 0xf ticks
+ * (just below 16 seconds).
+ * U-boot users specify the timeout as a number of milliseconds
+ * by using variable CONFIG_WATCHDOG_TIMEOUT_MSECS.
+ * The maximum value should be 15999 ms in our case.
+ * However, u-boot internally converts this config value to seconds,
+ * thus specifying 15999 actually means 15000 ms (0xf ticks).
+ */
+#define PM_WDOG_MAX_TICKS    0x000f
+#define PM_RSTC_WRCFG_CLR    0xffcf
+#define PM_RSTC_WRCFG_FULL_RESET    0x0020
+#define PM_RSTC_RESET    0x0102
+
+#define MS_TO_WDOG_TICKS(x) (((x) << 16) / 1000)
+
+struct bcm2835_wdt_priv {
+    void __iomem *base;
+};
+
+static u64 timeout_ticks = PM_WDOG_MAX_TICKS;


Is this static variable really needed? Why not add this variable (if
needed) into the priv struct above instead?


+
+static int bcm2835_wdt_start_ticks(struct udevice *dev,
+   u64 timeout_ticks, ulong flags)
+{
+    struct bcm2835_wdt_priv *priv = dev_get_priv(dev);
+    void __iomem *base = priv->base;
+    u32 cur;
+
+    writel(PM_PASSWORD | timeout_ticks, base + PM_WDOG);
+    cur = readl(base + PM_RSTC);
+    writel(PM_PASSWORD | (cur & PM_RSTC_WRCFG_CLR) |
+  PM_RSTC_WRCFG_FULL_RESET, base + PM_RSTC);
+
+    return 0;
+}
+
+static int bcm2835_wdt_start(struct udevice *dev, u64 timeout_ms, 
ulong flags)

+{
+    timeout_ticks = MS_TO_WDOG_TICKS(timeout_ms);


Again, there should be no need for this static variable. Please move it
to the priv struct instead.

Thanks,
Stefan


+
+    if (timeout_ticks > PM_WDOG_MAX_TICKS) {
+    printf("WARNING: bcm2835_wdt cannot handle large timeout 
values.\n");

+    printf(" Setting the max value of 15000 ms instead.\n");
+    printf(" Set CONFIG_WATCHDOG_TIMEOUT_MSECS=15000 at most "
+    "to avoid this warning.\n");
+    timeout_ticks = PM_WDOG_MAX_TICKS;
+    }
+
+    return bcm2835_wdt_start_ticks(dev, timeout_ticks, flags);
+}
+
+static int bcm2835_wdt_reset(struct udevice *dev)
+{
+    /* restart the timer with the static variable '

[PATCH] watchdog: Add a watchdog driver for Raspberry Pi boards

2023-01-24 Thread Etienne Dublé

This driver supports the bcm2835 watchdog found on
Raspberry Pi boards.
It is derived from the Linux driver and was tested
on two Raspberry Pi board versions (B+ and 3B+).

Signed-off-by: Etienne Dublé 
---

 drivers/watchdog/Kconfig   |   9 +++
 drivers/watchdog/Makefile  |   1 +
 drivers/watchdog/bcm2835_wdt.c | 135 +
 3 files changed, 145 insertions(+)
 create mode 100644 drivers/watchdog/bcm2835_wdt.c

diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig
index f1b1cf63ca..06c0d630c8 100644
--- a/drivers/watchdog/Kconfig
+++ b/drivers/watchdog/Kconfig
@@ -30,6 +30,7 @@ config WATCHDOG_TIMEOUT_MSECS
default 128000 if ARCH_MX7 || ARCH_VF610
default 3 if ARCH_SOCFPGA
default 16000 if ARCH_SUNXI
+   default 15000 if ARCH_BCM283X
default 6
help
  Watchdog timeout in msec
@@ -326,6 +327,14 @@ config WDT_SUNXI
help
  Enable support for the watchdog timer in Allwinner sunxi SoCs.
 +config WDT_BCM2835
+   bool "Broadcom 2835 watchdog timer support"
+   depends on WDT && ARCH_BCM283X
+   default y
+   help
+ Enable support for the watchdog timer in Broadcom 283X SoCs such
+ as Raspberry Pi boards.
+
 config XILINX_TB_WATCHDOG
bool "Xilinx Axi watchdog timer support"
depends on WDT
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile
index 446d961d7d..f99915960c 100644
--- a/drivers/watchdog/Makefile
+++ b/drivers/watchdog/Makefile
@@ -21,6 +21,7 @@ obj-$(CONFIG_WDT_APPLE) += apple_wdt.o
 obj-$(CONFIG_WDT_ARMADA_37XX) += armada-37xx-wdt.o
 obj-$(CONFIG_WDT_ASPEED) += ast_wdt.o
 obj-$(CONFIG_WDT_AST2600) += ast2600_wdt.o
+obj-$(CONFIG_WDT_BCM2835) += bcm2835_wdt.o
 obj-$(CONFIG_WDT_BCM6345) += bcm6345_wdt.o
 obj-$(CONFIG_WDT_BOOKE) += booke_wdt.o
 obj-$(CONFIG_WDT_CORTINA) += cortina_wdt.o
diff --git a/drivers/watchdog/bcm2835_wdt.c b/drivers/watchdog/bcm2835_wdt.c
new file mode 100644
index 00..48535c003f
--- /dev/null
+++ b/drivers/watchdog/bcm2835_wdt.c
@@ -0,0 +1,135 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Copyright (C) 2013 Lubomir Rintel 
+ * Copyright (C) 2023 Etienne Dublé (CNRS) 
+ *
+ * This code is mostly derived from the linux driver.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#define PM_RSTC0x1c
+#define PM_WDOG0x24
+
+#define PM_PASSWORD0x5a00
+
+/* The hardware supports a maximum timeout value of 0xf ticks
+ * (just below 16 seconds).
+ * U-boot users specify the timeout as a number of milliseconds
+ * by using variable CONFIG_WATCHDOG_TIMEOUT_MSECS.
+ * The maximum value should be 15999 ms in our case.
+ * However, u-boot internally converts this config value to seconds,
+ * thus specifying 15999 actually means 15000 ms (0xf ticks).
+ */
+#define PM_WDOG_MAX_TICKS  0x000f
+#define PM_RSTC_WRCFG_CLR  0xffcf
+#define PM_RSTC_WRCFG_FULL_RESET   0x0020
+#define PM_RSTC_RESET  0x0102
+
+#define MS_TO_WDOG_TICKS(x) (((x) << 16) / 1000)
+
+struct bcm2835_wdt_priv {
+   void __iomem *base;
+};
+
+static u64 timeout_ticks = PM_WDOG_MAX_TICKS;
+
+static int bcm2835_wdt_start_ticks(struct udevice *dev,
+  u64 timeout_ticks, ulong flags)
+{
+   struct bcm2835_wdt_priv *priv = dev_get_priv(dev);
+   void __iomem *base = priv->base;
+   u32 cur;
+
+   writel(PM_PASSWORD | timeout_ticks, base + PM_WDOG);
+   cur = readl(base + PM_RSTC);
+   writel(PM_PASSWORD | (cur & PM_RSTC_WRCFG_CLR) |
+ PM_RSTC_WRCFG_FULL_RESET, base + PM_RSTC);
+
+   return 0;
+}
+
+static int bcm2835_wdt_start(struct udevice *dev, u64 timeout_ms, ulong 
flags)

+{
+   timeout_ticks = MS_TO_WDOG_TICKS(timeout_ms);
+
+   if (timeout_ticks > PM_WDOG_MAX_TICKS) {
+   printf("WARNING: bcm2835_wdt cannot handle large timeout 
values.\n");
+   printf("Setting the max value of 15000 ms instead.\n");
+   printf("Set CONFIG_WATCHDOG_TIMEOUT_MSECS=15000 at most "
+   "to avoid this warning.\n");
+   timeout_ticks = PM_WDOG_MAX_TICKS;
+   }
+
+   return bcm2835_wdt_start_ticks(dev, timeout_ticks, flags);
+}
+
+static int bcm2835_wdt_reset(struct udevice *dev)
+{
+   /* restart the timer with the static variable 'timeout_ticks'
+* saved from the last bcm2835_wdt_start() call.
+*/
+   return bcm2835_wdt_start_ticks(dev, timeout_ticks, 0);
+}
+
+static int bcm2835_wdt_stop(struct udevice *dev)
+{
+   struct bcm2835_wdt_priv *priv = dev_get_priv(dev);
+   void __iomem *base = priv->base;
+
+   writel(PM_PASSWORD | PM_RSTC_R

Re: [PATCH] bcmgenet: fix DMA buffer management

2020-07-20 Thread Etienne Dublé
Hi Jason, 
Thanks for testing and for the additional fix. 
In my case (with dhcp followed by 3 TFTP transfers), the board booted fine 20 
times in a row with only my fix applied. Previously it was booting once in 10 
trials or so. 
The driver resets tx_index in bcmgenet_gmac_eth_send() if it is higher than 
256, and the same occurs for rx_index in bcmgenet_gmac_free_pkt(), so I suppose 
the issue you faced only occurs when the boundary case is reached between two 
commands? 
Anyway, thanks for the update. 
Cheers 
Etienne 



De: "Jason Wessel"  
À: "Etienne DUBLE" , "joe hershberger" 
 
Cc: u-boot@lists.denx.de, "ETIENNE DUBLE"  
Envoyé: Jeudi 16 Juillet 2020 18:02:11 
Objet: Re: [PATCH] bcmgenet: fix DMA buffer management 

On 7/16/20 7:02 AM, Jason Wessel wrote: 
> On 7/9/20 3:11 AM, etienne.du...@gmail.com wrote: 
>> From: Etienne Dublé  
>> 
>> This commit fixes a serious issue occuring when several network 
>> commands are run on a raspberry pi 4 board: for instance a "dhcp" 
>> command and then one or several "tftp" commands. In this case, 
>> packet recv callbacks were called several times on the same packets, 
>> and send function was failing most of the time. 
>> 
>> note: if the boot procedure is made of a single network 
>> command, the issue is not visible. 
>> 
>> The issue is related to management of the packet ring buffers 
>> (producer / consumer) and DMA. 
>> Each time a packet is received, the ethernet device stores it 
>> in the buffer and increments an index called RDMA_PROD_INDEX. 
>> Each time the driver outputs a received packet, it increments 
>> another index called RDMA_CONS_INDEX. 
>> 
>> Between each pair of network commands, as part of the driver 
>> 'start' function, previous code tried to reset both RDMA_CONS_INDEX 
>> and RDMA_PROD_INDEX to 0. But RDMA_PROD_INDEX cannot be written from 
>> driver side, thus its value was actually not updated, and only 
>> RDMA_CONS_INDEX was reset to 0. This was resulting in a major 
>> synchronization issue between the driver and the device. Most 
>> visible bahavior was that the driver seemed to receive again the 
>> packets from the previous commands (e.g. DHCP response packets 
>> "received" again when performing the first TFTP command). 
>> 
>> This fix consists in setting RDMA_CONS_INDEX to the same 
>> value as RDMA_PROD_INDEX, when resetting the driver. 
>> 
>> The same kind of fix was needed on the TX side, and a few variables 
>> had to be reset accordingly (c_index, tx_index, rx_index). 
> 
> 
> While there is some kind of problem with the driver, because I too 
> have observed a problem with multiple requests timing out or failing, 
> this patch makes the problem much worse. I was only able to complete 
> a single tftp request. 
> 
> In my case I am using a static IP address and serverip. 
> 
> Also your patch was missing the sign-off line. Please consider 
> running your patches through scripts/checkpatch.pl. 
> 
> Cheers, 
> Jason. 
> 
>> --- 
>> drivers/net/bcmgenet.c | 15 +++ 
>> 1 file changed, 7 insertions(+), 8 deletions(-) 
>> 
>> diff --git a/drivers/net/bcmgenet.c b/drivers/net/bcmgenet.c 
>> index 11b6148ab6..a4facfd63f 100644 
>> --- a/drivers/net/bcmgenet.c 
>> +++ b/drivers/net/bcmgenet.c 
>> @@ -378,8 +378,6 @@ static void rx_descs_init(struct bcmgenet_eth_priv 
>> *priv) 
>> u32 len_stat, i; 
>> void *desc_base = priv->rx_desc_base; 
>> 
>> - priv->c_index = 0; 
>> - 
>> len_stat = (RX_BUF_LENGTH << DMA_BUFLENGTH_SHIFT) | DMA_OWN; 
>> 
>> for (i = 0; i < RX_DESCS; i++) { 
>> @@ -403,8 +401,10 @@ static void rx_ring_init(struct bcmgenet_eth_priv 
>> *priv) 
>> writel(RX_DESCS * DMA_DESC_SIZE / 4 - 1, 
>> priv->mac_reg + RDMA_RING_REG_BASE + DMA_END_ADDR); 
>> 
>> - writel(0x0, priv->mac_reg + RDMA_PROD_INDEX); 
>> - writel(0x0, priv->mac_reg + RDMA_CONS_INDEX); 
>> + /* cannot init RDMA_PROD_INDEX to 0, so align RDMA_CONS_INDEX on it 
>> instead */ 
>> + priv->c_index = readl(priv->mac_reg + RDMA_PROD_INDEX); 
>> + writel(priv->c_index, priv->mac_reg + RDMA_CONS_INDEX); 
>> + priv->rx_index = priv->c_index; 


printf("before RX_IDX: 0x%x\n", priv->rx_index); 

I added a printf() like above for the RX and TX to see what is going on when 
I try and transfer a kernel Image file the second time. 


U-Boot> tftp ${loadaddr} bootfs/Image 
before RX_IDX: 0x0 
before TX_IDX: 0x0 
Using ethernet@7d58 device 
Filename 'bootfs/Image'. 
Load add