* [PATCH 2/4] net: dsa: realtek: fix support for MDIO-connected switches
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-22 2:07 ` Alvin Šipraga
2023-12-22 2:07 ` [PATCH 3/4] net: dsa: realtek: unify ds_ops Alvin Šipraga
` (2 subsequent siblings)
4 siblings, 0 replies; 7+ messages in thread
From: Alvin Šipraga @ 2023-12-22 2:07 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX
Cc: Vladimir Oltean, Luiz Angelo Daros de Luca, Alvin Šipraga
From: Alvin Šipraga <alsi@bang-olufsen.dk>
DSA offers drivers the option to have the core register an MDIO bus,
intended for platforms which do not have a specific OF node for the MDIO
bus or corresponding phy-handle properties on the switch port nodes.
This logic works OK, but is incidentally broken in barebox because the
dsa_switch::phys_mii_mask field is not being set. That means all reads
and writes to the internal PHYs are dropped before anything goes out on
the bus.
Notwithstanding that barebox issue, there is an ongoing discussion [1]
on the Linux mailing list as to the virtues (or lack thereof) of
realtek-mdio opting into this core functionality to begin with. The fact
is that, for SMI-connected switches, realtek-smi absolutely expects an
MDIO bus node. And the device tree bindings strongly (albeit not
strictly) assert that this node for both MDIO and SMI connected
switches. In the specific case of barebox, the driver likely has even
fewer users, and realtek-mdio is currently broken, so there is nothing
to break by strictly enforcing the presence of an MDIO node.
The same discussion [1] centers around an effort to actually unify
large, common parts of the SMI and MDIO drivers, and ditching the
asymmetric MDIO bus registration would make this effort even easier.
To that end, add a little bit more code in order to bury this particular
issue once and for all in barebox. Further cleanup can be done to reduce
the overall quantity of code, probably following whatever ends up in
Linux.
A slice dependency is also added to the parent MDIO bus to prevent the
PHY status polling from interleaving MDIO accesses during switch
management.
Link: https://lore.kernel.org/all/20231221174746.hylsmr3f7g5byrsi@skbuf/ [1]
Fixes: f9f31a9a21e4 ("net: dsa: add Realtek (rtl8365mb/rtl8366rb) switch support")
Signed-off-by: Alvin Šipraga <alsi@bang-olufsen.dk>
---
drivers/net/realtek-dsa/realtek-mdio.c | 103 ++++++++++++++++++++++++++-------
drivers/net/realtek-dsa/rtl8365mb.c | 13 -----
drivers/net/realtek-dsa/rtl8366rb.c | 13 -----
3 files changed, 81 insertions(+), 48 deletions(-)
diff --git a/drivers/net/realtek-dsa/realtek-mdio.c b/drivers/net/realtek-dsa/realtek-mdio.c
index 463757711198..2b8661b95677 100644
--- a/drivers/net/realtek-dsa/realtek-mdio.c
+++ b/drivers/net/realtek-dsa/realtek-mdio.c
@@ -47,22 +47,27 @@ static int realtek_mdio_write(void *ctx, u32 reg, u32 val)
struct mii_bus *bus = priv->bus;
int ret;
- ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL0_REG, REALTEK_MDIO_ADDR_OP);
+ ret = mdiobus_write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL0_REG,
+ REALTEK_MDIO_ADDR_OP);
if (ret)
- goto out_unlock;
+ return ret;
- ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_ADDRESS_REG, reg);
+ ret = mdiobus_write(bus, priv->mdio_addr, REALTEK_MDIO_ADDRESS_REG,
+ reg);
if (ret)
- goto out_unlock;
+ return ret;
- ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_DATA_WRITE_REG, val);
+ ret = mdiobus_write(bus, priv->mdio_addr, REALTEK_MDIO_DATA_WRITE_REG,
+ val);
if (ret)
- goto out_unlock;
+ return ret;
- ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL1_REG, REALTEK_MDIO_WRITE_OP);
+ ret = mdiobus_write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL1_REG,
+ REALTEK_MDIO_WRITE_OP);
+ if (ret)
+ return ret;
-out_unlock:
- return ret;
+ return 0;
}
static int realtek_mdio_read(void *ctx, u32 reg, u32 *val)
@@ -71,26 +76,43 @@ static int realtek_mdio_read(void *ctx, u32 reg, u32 *val)
struct mii_bus *bus = priv->bus;
int ret;
- ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL0_REG, REALTEK_MDIO_ADDR_OP);
+ ret = mdiobus_write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL0_REG,
+ REALTEK_MDIO_ADDR_OP);
if (ret)
- goto out_unlock;
+ return ret;
- ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_ADDRESS_REG, reg);
+ ret = mdiobus_write(bus, priv->mdio_addr, REALTEK_MDIO_ADDRESS_REG,
+ reg);
if (ret)
- goto out_unlock;
+ return ret;
- ret = bus->write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL1_REG, REALTEK_MDIO_READ_OP);
+ ret = mdiobus_write(bus, priv->mdio_addr, REALTEK_MDIO_CTRL1_REG,
+ REALTEK_MDIO_READ_OP);
if (ret)
- goto out_unlock;
+ return ret;
- ret = bus->read(bus, priv->mdio_addr, REALTEK_MDIO_DATA_READ_REG);
- if (ret >= 0) {
- *val = ret;
- ret = 0;
- }
+ ret = mdiobus_read(bus, priv->mdio_addr, REALTEK_MDIO_DATA_READ_REG);
+ if (ret < 0)
+ return ret;
-out_unlock:
- return ret;
+ *val = ret;
+
+ return 0;
+}
+
+static int realtek_mdio_mdio_write(struct mii_bus *bus, int addr, int regnum,
+ u16 val)
+{
+ struct realtek_priv *priv = bus->priv;
+
+ return priv->ops->phy_write(priv, addr, regnum, val);
+}
+
+static int realtek_mdio_mdio_read(struct mii_bus *bus, int addr, int regnum)
+{
+ struct realtek_priv *priv = bus->priv;
+
+ return priv->ops->phy_read(priv, addr, regnum);
}
static const struct regmap_config realtek_mdio_regmap_config = {
@@ -107,6 +129,42 @@ static const struct regmap_bus realtek_mdio_regmap_bus = {
.reg_read = realtek_mdio_read,
};
+static int realtek_mdio_setup_mdio(struct dsa_switch *ds)
+{
+ struct realtek_priv *priv = ds->priv;
+ struct device_node *np;
+ int ret;
+
+ np = of_get_child_by_name(priv->dev->of_node, "mdio");
+ if (!np) {
+ dev_err(priv->dev, "missing 'mdio' child node\n");
+ return -ENODEV;
+ }
+
+ priv->slave_mii_bus->priv = priv;
+ priv->slave_mii_bus->read = realtek_mdio_mdio_read;
+ priv->slave_mii_bus->write = realtek_mdio_mdio_write;
+ priv->slave_mii_bus->dev.of_node = np;
+ priv->slave_mii_bus->parent = priv->dev;
+
+ ret = mdiobus_register(priv->slave_mii_bus);
+ if (ret) {
+ dev_err(priv->dev, "unable to register MDIO bus %pOF\n", np);
+ goto err_put_node;
+ }
+
+ /* Avoid interleaved MDIO access during PHY status polling */
+ slice_depends_on(mdiobus_slice(priv->slave_mii_bus),
+ mdiobus_slice(priv->bus));
+
+ return 0;
+
+err_put_node:
+ of_node_put(np);
+
+ return ret;
+}
+
static int realtek_mdio_probe(struct phy_device *mdiodev)
{
struct realtek_priv *priv;
@@ -142,6 +200,7 @@ static int realtek_mdio_probe(struct phy_device *mdiodev)
priv->cmd_write = var->cmd_write;
priv->ops = var->ops;
+ priv->setup_interface = realtek_mdio_setup_mdio;
priv->write_reg_noack = realtek_mdio_write;
np = dev->of_node;
diff --git a/drivers/net/realtek-dsa/rtl8365mb.c b/drivers/net/realtek-dsa/rtl8365mb.c
index 700773ffa657..0f4c471715d1 100644
--- a/drivers/net/realtek-dsa/rtl8365mb.c
+++ b/drivers/net/realtek-dsa/rtl8365mb.c
@@ -649,17 +649,6 @@ static int rtl8365mb_phy_write(struct realtek_priv *priv, int phy, int regnum,
return 0;
}
-static int rtl8365mb_dsa_phy_read(struct dsa_switch *ds, int phy, int regnum)
-{
- return rtl8365mb_phy_read(ds->priv, phy, regnum);
-}
-
-static int rtl8365mb_dsa_phy_write(struct dsa_switch *ds, int phy, int regnum,
- u16 val)
-{
- return rtl8365mb_phy_write(ds->priv, phy, regnum, val);
-}
-
static const struct rtl8365mb_extint *
rtl8365mb_get_port_extint(struct realtek_priv *priv, int port)
{
@@ -1246,8 +1235,6 @@ static const struct dsa_switch_ops rtl8365mb_switch_ops_mdio = {
.port_pre_enable = rtl8365mb_phylink_mac_config,
.port_disable = rtl8365mb_phylink_mac_link_down,
.port_enable = rtl8365mb_phylink_mac_link_up,
- .phy_read = rtl8365mb_dsa_phy_read,
- .phy_write = rtl8365mb_dsa_phy_write,
};
static const struct realtek_ops rtl8365mb_ops = {
diff --git a/drivers/net/realtek-dsa/rtl8366rb.c b/drivers/net/realtek-dsa/rtl8366rb.c
index 26f036dfe570..6fd2b1852159 100644
--- a/drivers/net/realtek-dsa/rtl8366rb.c
+++ b/drivers/net/realtek-dsa/rtl8366rb.c
@@ -1021,17 +1021,6 @@ static int rtl8366rb_phy_write(struct realtek_priv *priv, int phy, int regnum,
return ret;
}
-static int rtl8366rb_dsa_phy_read(struct dsa_switch *ds, int phy, int regnum)
-{
- return rtl8366rb_phy_read(ds->priv, phy, regnum);
-}
-
-static int rtl8366rb_dsa_phy_write(struct dsa_switch *ds, int phy, int regnum,
- u16 val)
-{
- return rtl8366rb_phy_write(ds->priv, phy, regnum, val);
-}
-
static int rtl8366rb_reset_chip(struct realtek_priv *priv)
{
int timeout = 10;
@@ -1096,8 +1085,6 @@ static const struct dsa_switch_ops rtl8366rb_switch_ops_smi = {
};
static const struct dsa_switch_ops rtl8366rb_switch_ops_mdio = {
- .phy_read = rtl8366rb_dsa_phy_read,
- .phy_write = rtl8366rb_dsa_phy_write,
.port_enable = rtl8366rb_port_enable,
.port_disable = rtl8366rb_port_disable,
};
--
2.43.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 3/4] net: dsa: realtek: unify ds_ops
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-22 2:07 ` [PATCH 2/4] net: dsa: realtek: fix support for MDIO-connected switches Alvin Šipraga
@ 2023-12-22 2:07 ` Alvin Šipraga
2023-12-22 2:07 ` [PATCH 4/4] net: mdio_bus: associate OF nodes with their devices Alvin Šipraga
2024-01-02 9:01 ` [PATCH 0/4] fix barebox support for MDIO-connected Realtek Ethernet switches Sascha Hauer
4 siblings, 0 replies; 7+ messages in thread
From: Alvin Šipraga @ 2023-12-22 2:07 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX
Cc: Vladimir Oltean, Luiz Angelo Daros de Luca, Alvin Šipraga
From: Alvin Šipraga <alsi@bang-olufsen.dk>
Now that neither interface driver requires .phy_read or .phy_write, the
ops are the same and some code can be deleted. No functional change.
Signed-off-by: Alvin Šipraga <alsi@bang-olufsen.dk>
---
drivers/net/realtek-dsa/realtek-mdio.c | 2 +-
drivers/net/realtek-dsa/realtek-smi.c | 2 +-
drivers/net/realtek-dsa/realtek.h | 3 +--
drivers/net/realtek-dsa/rtl8365mb.c | 11 ++---------
drivers/net/realtek-dsa/rtl8366rb.c | 10 ++--------
5 files changed, 7 insertions(+), 21 deletions(-)
diff --git a/drivers/net/realtek-dsa/realtek-mdio.c b/drivers/net/realtek-dsa/realtek-mdio.c
index 2b8661b95677..4fc2295b1b5f 100644
--- a/drivers/net/realtek-dsa/realtek-mdio.c
+++ b/drivers/net/realtek-dsa/realtek-mdio.c
@@ -236,7 +236,7 @@ static int realtek_mdio_probe(struct phy_device *mdiodev)
priv->ds->dev = dev;
priv->ds->num_ports = priv->num_ports;
priv->ds->priv = priv;
- priv->ds->ops = var->ds_ops_mdio;
+ priv->ds->ops = var->ds_ops;
ret = realtek_dsa_init_tagger(priv);
if (ret)
diff --git a/drivers/net/realtek-dsa/realtek-smi.c b/drivers/net/realtek-dsa/realtek-smi.c
index f93024ace516..da150dbc5d8b 100644
--- a/drivers/net/realtek-dsa/realtek-smi.c
+++ b/drivers/net/realtek-dsa/realtek-smi.c
@@ -450,7 +450,7 @@ static int realtek_smi_probe(struct device *dev)
priv->ds->dev = dev;
priv->ds->num_ports = priv->num_ports;
priv->ds->priv = priv;
- priv->ds->ops = var->ds_ops_smi;
+ priv->ds->ops = var->ds_ops;
ret = realtek_dsa_init_tagger(priv);
if (ret)
diff --git a/drivers/net/realtek-dsa/realtek.h b/drivers/net/realtek-dsa/realtek.h
index ac84b18cdd14..dbca9494627a 100644
--- a/drivers/net/realtek-dsa/realtek.h
+++ b/drivers/net/realtek-dsa/realtek.h
@@ -69,8 +69,7 @@ struct realtek_ops {
};
struct realtek_variant {
- const struct dsa_switch_ops *ds_ops_smi;
- const struct dsa_switch_ops *ds_ops_mdio;
+ const struct dsa_switch_ops *ds_ops;
const struct realtek_ops *ops;
unsigned int clk_delay;
u8 cmd_read;
diff --git a/drivers/net/realtek-dsa/rtl8365mb.c b/drivers/net/realtek-dsa/rtl8365mb.c
index 0f4c471715d1..588998235827 100644
--- a/drivers/net/realtek-dsa/rtl8365mb.c
+++ b/drivers/net/realtek-dsa/rtl8365mb.c
@@ -1225,13 +1225,7 @@ static int rtl8365mb_detect(struct realtek_priv *priv)
return 0;
}
-static const struct dsa_switch_ops rtl8365mb_switch_ops_smi = {
- .port_pre_enable = rtl8365mb_phylink_mac_config,
- .port_disable = rtl8365mb_phylink_mac_link_down,
- .port_enable = rtl8365mb_phylink_mac_link_up,
-};
-
-static const struct dsa_switch_ops rtl8365mb_switch_ops_mdio = {
+static const struct dsa_switch_ops rtl8365mb_switch_ops = {
.port_pre_enable = rtl8365mb_phylink_mac_config,
.port_disable = rtl8365mb_phylink_mac_link_down,
.port_enable = rtl8365mb_phylink_mac_link_up,
@@ -1247,8 +1241,7 @@ static const struct realtek_ops rtl8365mb_ops = {
};
const struct realtek_variant rtl8365mb_variant = {
- .ds_ops_smi = &rtl8365mb_switch_ops_smi,
- .ds_ops_mdio = &rtl8365mb_switch_ops_mdio,
+ .ds_ops = &rtl8365mb_switch_ops,
.ops = &rtl8365mb_ops,
.clk_delay = 10,
.cmd_read = 0xb9,
diff --git a/drivers/net/realtek-dsa/rtl8366rb.c b/drivers/net/realtek-dsa/rtl8366rb.c
index 6fd2b1852159..35028d319ecd 100644
--- a/drivers/net/realtek-dsa/rtl8366rb.c
+++ b/drivers/net/realtek-dsa/rtl8366rb.c
@@ -1079,12 +1079,7 @@ static int rtl8366rb_detect(struct realtek_priv *priv)
return rtl8366rb_reset_chip(priv);
}
-static const struct dsa_switch_ops rtl8366rb_switch_ops_smi = {
- .port_enable = rtl8366rb_port_enable,
- .port_disable = rtl8366rb_port_disable,
-};
-
-static const struct dsa_switch_ops rtl8366rb_switch_ops_mdio = {
+static const struct dsa_switch_ops rtl8366rb_switch_ops = {
.port_enable = rtl8366rb_port_enable,
.port_disable = rtl8366rb_port_disable,
};
@@ -1098,8 +1093,7 @@ static const struct realtek_ops rtl8366rb_ops = {
};
const struct realtek_variant rtl8366rb_variant = {
- .ds_ops_smi = &rtl8366rb_switch_ops_smi,
- .ds_ops_mdio = &rtl8366rb_switch_ops_mdio,
+ .ds_ops = &rtl8366rb_switch_ops,
.ops = &rtl8366rb_ops,
.clk_delay = 10,
.cmd_read = 0xa9,
--
2.43.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH 4/4] net: mdio_bus: associate OF nodes with their devices
2023-12-22 2:07 [PATCH 0/4] fix barebox support for MDIO-connected Realtek Ethernet switches Alvin Šipraga
` (2 preceding siblings ...)
2023-12-22 2:07 ` [PATCH 3/4] net: dsa: realtek: unify ds_ops Alvin Šipraga
@ 2023-12-22 2:07 ` Alvin Šipraga
2024-01-02 9:01 ` [PATCH 0/4] fix barebox support for MDIO-connected Realtek Ethernet switches Sascha Hauer
4 siblings, 0 replies; 7+ messages in thread
From: Alvin Šipraga @ 2023-12-22 2:07 UTC (permalink / raw)
To: Sascha Hauer, BAREBOX
Cc: Vladimir Oltean, Luiz Angelo Daros de Luca, Alvin Šipraga,
realtek-smi 30be0000.ethernet
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
^ permalink raw reply [flat|nested] 7+ messages in thread