From: "Alvin Šipraga" <alvin@pqrs.dk>
To: Sascha Hauer <s.hauer@pengutronix.de>,
BAREBOX <barebox@lists.infradead.org>
Cc: "Vladimir Oltean" <olteanv@gmail.com>,
"Luiz Angelo Daros de Luca" <luizluca@gmail.com>,
"Alvin Šipraga" <alsi@bang-olufsen.dk>,
"realtek-smi 30be0000.ethernet"@30be0000
Subject: [PATCH 4/4] net: mdio_bus: associate OF nodes with their devices
Date: Fri, 22 Dec 2023 03:07:28 +0100 [thread overview]
Message-ID: <20231222-realtek-mdio-fix-v1-4-6bbf80d6a756@bang-olufsen.dk> (raw)
In-Reply-To: <20231222-realtek-mdio-fix-v1-0-6bbf80d6a756@bang-olufsen.dk>
From: Alvin Šipraga <alsi@bang-olufsen.dk>
barebox deep-probe will walk the device tree to ensure dependent devices
have been probed. In so doing, it uses the device_node::dev pointer to
check whether a given node has a device; if not, a device is created on
demand. The behaviour is recursive, so parent nodes without an
associated device will also have devices created on their behalf. The
recursion stops when a parent with a device is found.
Weird behaviour can ensure if, when devices with a device_node are
registered, the device_node::dev field is not populated. This patch
addresses a niche, benign, but also noisy error observed as a result of
this behaviour.
One mostly harmless consequence is that spurious devices can get created
when a suitable one already exists. In my case, I have an MDIO-connected
Ethernet switch with an internal MDIO bus and some internal PHYs. With
deep-probe, but without these changes, the devinfo output looks as
follows:
`-- 30be0000.ethernet@30be0000.of
`-- eth0
`-- miibus0
`-- mdio0-dev1d
`-- 0x00000000-0x0000003f ( 64 Bytes): /dev/mdio0-phy1d
`-- 30be0000.ethernet@30be0000:mdio:ethernet-switch@1d:ports:port@6.of
`-- 30be0000.ethernet@30be0000:mdio:ethernet-switch@1d:ports:port@0.of
`-- eth1
`-- 30be0000.ethernet@30be0000:mdio:ethernet-switch@1d:ports:port@1.of
`-- eth2
`-- 30be0000.ethernet@30be0000:mdio:ethernet-switch@1d:ports:port@2.of
`-- eth3
`-- 30be0000.ethernet@30be0000:mdio:ethernet-switch@1d:ports:port@3.of
`-- eth4
`-- miibus1
`-- mdio1-phy00
`-- 0x00000000-0x0000003f ( 64 Bytes): /dev/mdio1-phy00
`-- mdio1-phy01
`-- 0x00000000-0x0000003f ( 64 Bytes): /dev/mdio1-phy01
`-- mdio1-phy02
`-- 0x00000000-0x0000003f ( 64 Bytes): /dev/mdio1-phy02
`-- mdio1-phy03
`-- 0x00000000-0x0000003f ( 64 Bytes): /dev/mdio1-phy03
`-- 30be0000.ethernet@30be0000:mdio.of
`-- 30be0000.ethernet@30be0000:mdio:ethernet-switch@1d.of
`-- 30be0000.ethernet@30be0000:mdio:ethernet-switch@1d:mdio.of
Notice the last three devices with generic names; they are spurious
creations of the deep-probe algorithm. In fact, the devices have already
been created:
real dev spurious dev
-------- ------------
miibus0 30be0000.ethernet@30be0000:mdio.of
mdio0-devid1d 30be0000.ethernet@30be0000:mdio:ethernet-switch@1d.of
miibus1 30be0000.ethernet@30be0000:mdio:ethernet-switch@1d:mdio.of
The only reason there aren't even more spurious devices created is that
deep-probe stopped at 30be0000.ethernet@30be0000.of, a platform device
whose device_node had its dev field populated correctly. But these
so-called real devices are all created by mdio_bus, which only links one
way, i.e. sets device::of_node, but not device_node::dev.
This issue probably goes unnoticed on most boards because, while the
call to of_device_ensure_probed() returns -ENODEV on the bottom listed
node, the code in phy.c doesn't check the return code, and the real
devices have already been probed, so no harm is done.
I observed much more surprising behaviour on my board because the switch
I am using, an RTL8365MB, has multiple possible management interfaces,
for which barebox has two drivers: realtek-smi and realtek-mdio (for
SMI- and MDIO-connected switches, respectively). The compatible strings
are the same, "realtek,rtl8365mb", but the bus types are different: the
former is a platform driver, the latter a phy (read: mdio) driver. In my
bootloader I have both drivers built in, because some of my boards use
SMI while others use MDIO.
When I would run the command 'boot bnet', bringing up my network
interface, DSA would call phy_device_connect() to connect my edev with
its corresponding phy, and a deep-probe would kick off because the phy's
parent's device_node::dev field was not populated. And during the
creation of the spurious device for my (already probed) Ethernet switch,
the platform code would find a compatible string match with realtek-smi
and try to probe the device with that driver:
Booting entry 'bnet'
ERROR: gpiolib: _gpio_request: gpio-233 (30be0000.ethernet@30be0000:mdio:ethernet-switch@1d.of-reset) status -16
ERROR: realtek-smi 30be0000.ethernet@30be0000:mdio:ethernet-switch@1d.of: error Device or resource busy: failed to get RESET GPIO
ERROR: realtek-smi 30be0000.ethernet@30be0000:mdio:ethernet-switch@1d.of: probe failed: Device or resource busy
As stated above, my switch is connected over MDIO, not SMI, so I really
should not be seeing any "realtek-smi" in my log. Nevertheless, because
phy.c doesn't check for errors, the errors are benign and my network
boot runs just fine.
Dumping the stack around the above error print in the realtek-smi driver
reveals exactly why things are going wrong:
ERROR: gpiolib: _gpio_request: gpio-233 (30be0000.ethernet@30be0000:mdio:ethernet-switch@1d.of-reset) status -16
Call trace:
[<7dd8f400>] (unwind_backtrace+0x0/0x90)
[<7dd8f4a0>] (dump_stack+0x10/0x18)
[<7dd2d4d4>] (realtek_smi_probe+0x16c/0x2f4)
[<7dd1da28>] (platform_probe+0x48/0x4c)
[<7dd1cf24>] (device_probe+0x80/0x13c)
[<7dd1d028>] (match+0x48/0x58)
[<7dd1d3c8>] (register_device+0x178/0x184)
[<7dd1da80>] (platform_device_register+0x18/0x20)
[<7dd5501c>] (of_platform_device_create+0x2b8/0x2e0)
[<7dd55170>] (of_device_create_on_demand+0x84/0xc0)
[<7dd5513c>] (of_device_create_on_demand+0x50/0xc0)
[<7dd552e0>] (of_device_ensure_probed+0x40/0x6c)
[<7dd21398>] (phy_device_connect+0x174/0x230)
[<7dd1fd74>] (dsa_port_start+0x60/0x1f0)
[<7dd7a0e4>] (eth_open+0x24/0x44)
[<7dd7d7e4>] (ifup_edev+0x9c/0x2ec)
[<7dd7dbe4>] (ifup_all+0x110/0x204)
[<7dd7dd2c>] (do_ifup+0x54/0xd4)
[<7dd09e78>] (execute_command+0x44/0x8c)
...
The whole mess is rectified if the proper linking is done by mdio_bus,
since it is responsible for creating all of the devices to begin with.
So, make sure that the device_node::dev field is populated in all cases
there.
Note that while I also make this change in of_mdiobus_register_phy(), I
did not actually observe any unwanted behaviour by not doing so - the
problem above is specifically because it's not done in
of_mdiobus_register() or of_mdiobus_register_device(). But this is only
because of the way phys are looked up to begin with, so it seemed
reasonable to do it for them as well.
Signed-off-by: Alvin Šipraga <alsi@bang-olufsen.dk>
---
drivers/net/phy/mdio_bus.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/phy/mdio_bus.c b/drivers/net/phy/mdio_bus.c
index 332db6c05b11..94123ef6141c 100644
--- a/drivers/net/phy/mdio_bus.c
+++ b/drivers/net/phy/mdio_bus.c
@@ -119,6 +119,7 @@ static int of_mdiobus_register_phy(struct mii_bus *mdio, struct device_node *chi
* Associate the OF node with the device structure so it
* can be looked up later
*/
+ child->dev = &phy->dev;
phy->dev.of_node = child;
/*
@@ -145,6 +146,7 @@ static int of_mdiobus_register_device(struct mii_bus *mdio,
if (IS_ERR(mdiodev))
return PTR_ERR(mdiodev);
+ child->dev = &mdiodev->dev;
mdiodev->dev.of_node = child;
ret = mdio_register_device(mdiodev);
@@ -315,6 +317,8 @@ int mdiobus_register(struct mii_bus *bus)
pr_info("%s: probed\n", dev_name(&bus->dev));
if (bus->dev.of_node) {
+ bus->dev.of_node->dev = &bus->dev;
+
/* Register PHY's as child node to mdio node */
of_mdiobus_register(bus, bus->dev.of_node);
}
--
2.43.0
next prev parent reply other threads:[~2023-12-22 2:09 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-12-22 2:07 [PATCH 0/4] fix barebox support for MDIO-connected Realtek Ethernet switches Alvin Šipraga
2023-12-22 2:07 ` [PATCH 1/4] net: fec_imx: reverse registration order of mdiobus and edev Alvin Šipraga
2023-12-24 9:27 ` Ahmad Fatoum
2023-12-22 2:07 ` [PATCH 2/4] net: dsa: realtek: fix support for MDIO-connected switches Alvin Šipraga
2023-12-22 2:07 ` [PATCH 3/4] net: dsa: realtek: unify ds_ops Alvin Šipraga
2023-12-22 2:07 ` Alvin Šipraga [this message]
2024-01-02 9:01 ` [PATCH 0/4] fix barebox support for MDIO-connected Realtek Ethernet switches Sascha Hauer
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231222-realtek-mdio-fix-v1-4-6bbf80d6a756@bang-olufsen.dk \
--to=alvin@pqrs.dk \
--cc="realtek-smi 30be0000.ethernet"@30be0000 \
--cc=alsi@bang-olufsen.dk \
--cc=barebox@lists.infradead.org \
--cc=luizluca@gmail.com \
--cc=olteanv@gmail.com \
--cc=s.hauer@pengutronix.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox