[PATCH v2 0/6] Call phy_config at port probe time for the Felix DSA driver

Changes in v2: Rebased on top of the master branch (solves this conflict: https://patchwork.ozlabs.org/project/uboot/patch/20210629170839.2583797-4-ol... with Tim Harvey's patch to make DSA masters promiscuous)
This series makes the Felix DSA driver initialize all its connected PHYs regardless of whether those will be used for networking or not. This is in order to satisfy the expectations of some software in later boot stages.
To make this work, it is necessary to introduce a new method in struct dsa_ops: .port_probe().
There is some further refactoring/cleanup along the way.
Vladimir Oltean (6): net: dsa: felix: felix_init() can be static net: dsa: use "err" instead of "ret" in dsa_port_probe net: dsa: refactor the code to set the port MAC address into a dedicated function net: dsa: introduce a .port_probe() method in struct dsa_ops net: dsa: felix: call phy_config at .port_probe() time net: dsa: felix: propagate the error code from phy_startup()
drivers/net/mscc_eswitch/felix_switch.c | 28 ++++++----- include/net/dsa.h | 5 +- net/dsa-uclass.c | 62 +++++++++++++++---------- 3 files changed, 59 insertions(+), 36 deletions(-)

No one is calling this function from outside felix_switch.c.
Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Reviewed-by: Ramon Fried rfried.dev@gmail.com Tested-by: Michael Walle michael@walle.cc --- drivers/net/mscc_eswitch/felix_switch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/mscc_eswitch/felix_switch.c b/drivers/net/mscc_eswitch/felix_switch.c index f20e84e0f10c..75073880cf87 100644 --- a/drivers/net/mscc_eswitch/felix_switch.c +++ b/drivers/net/mscc_eswitch/felix_switch.c @@ -233,7 +233,7 @@ static void felix_start_pcs(struct udevice *dev, int port, } }
-void felix_init(struct udevice *dev) +static void felix_init(struct udevice *dev) { struct dsa_pdata *pdata = dev_get_uclass_plat(dev); struct felix_priv *priv = dev_get_priv(dev);

On Tue, Aug 24, 2021 at 3:01 PM Vladimir Oltean vladimir.oltean@nxp.com wrote:
No one is calling this function from outside felix_switch.c.
Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Reviewed-by: Ramon Fried rfried.dev@gmail.com Tested-by: Michael Walle michael@walle.cc
drivers/net/mscc_eswitch/felix_switch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/mscc_eswitch/felix_switch.c b/drivers/net/mscc_eswitch/felix_switch.c index f20e84e0f10c..75073880cf87 100644 --- a/drivers/net/mscc_eswitch/felix_switch.c +++ b/drivers/net/mscc_eswitch/felix_switch.c @@ -233,7 +233,7 @@ static void felix_start_pcs(struct udevice *dev, int port, } }
-void felix_init(struct udevice *dev) +static void felix_init(struct udevice *dev) { struct dsa_pdata *pdata = dev_get_uclass_plat(dev); struct felix_priv *priv = dev_get_priv(dev); -- 2.25.1
Applied to u-boot-net/network-master Thanks, Ramon.

DM DSA uses "err" for error code values, so use this consistently.
Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Reviewed-by: Ramon Fried rfried.dev@gmail.com Tested-by: Michael Walle michael@walle.cc --- net/dsa-uclass.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c index 694664d81bbb..f279ca7d2d6c 100644 --- a/net/dsa-uclass.c +++ b/net/dsa-uclass.c @@ -248,7 +248,7 @@ static int dsa_port_probe(struct udevice *pdev) struct dsa_port_pdata *port_pdata; struct dsa_priv *dsa_priv; struct udevice *master; - int ret; + int err;
port_pdata = dev_get_parent_plat(pdev); dsa_priv = dev_get_uclass_priv(dev); @@ -268,9 +268,9 @@ static int dsa_port_probe(struct udevice *pdev) * TODO: we assume the master device is always there and doesn't get * removed during runtime. */ - ret = device_probe(master); - if (ret) - return ret; + err = device_probe(master); + if (err) + return err;
/* * Inherit port's hwaddr from the DSA master, unless the port already

On Tue, Aug 24, 2021 at 3:01 PM Vladimir Oltean vladimir.oltean@nxp.com wrote:
DM DSA uses "err" for error code values, so use this consistently.
Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Reviewed-by: Ramon Fried rfried.dev@gmail.com Tested-by: Michael Walle michael@walle.cc
net/dsa-uclass.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c index 694664d81bbb..f279ca7d2d6c 100644 --- a/net/dsa-uclass.c +++ b/net/dsa-uclass.c @@ -248,7 +248,7 @@ static int dsa_port_probe(struct udevice *pdev) struct dsa_port_pdata *port_pdata; struct dsa_priv *dsa_priv; struct udevice *master;
int ret;
int err; port_pdata = dev_get_parent_plat(pdev); dsa_priv = dev_get_uclass_priv(dev);
@@ -268,9 +268,9 @@ static int dsa_port_probe(struct udevice *pdev) * TODO: we assume the master device is always there and doesn't get * removed during runtime. */
ret = device_probe(master);
if (ret)
return ret;
err = device_probe(master);
if (err)
return err; /* * Inherit port's hwaddr from the DSA master, unless the port already
-- 2.25.1
Applied to u-boot-net/network-master Thanks, Ramon.

This snippet of code has a bothering "if (...) return 0" in it which assumes it is the last piece of code running in dsa_port_probe().
This makes it difficult to add further code at the end of dsa_port_probe() which does not depend on MAC address stuff.
So move the code to a dedicated function which returns void and let the code flow through.
Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Reviewed-by: Ramon Fried rfried.dev@gmail.com Tested-by: Michael Walle michael@walle.cc --- net/dsa-uclass.c | 50 +++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 22 deletions(-)
diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c index f279ca7d2d6c..dbd8558b6486 100644 --- a/net/dsa-uclass.c +++ b/net/dsa-uclass.c @@ -240,11 +240,36 @@ static const struct eth_ops dsa_port_ops = { .free_pkt = dsa_port_free_pkt, };
-static int dsa_port_probe(struct udevice *pdev) +/* + * Inherit port's hwaddr from the DSA master, unless the port already has a + * unique MAC address specified in the environment. + */ +static void dsa_port_set_hwaddr(struct udevice *pdev, struct udevice *master) { - struct udevice *dev = dev_get_parent(pdev); struct eth_pdata *eth_pdata, *master_pdata; unsigned char env_enetaddr[ARP_HLEN]; + + eth_env_get_enetaddr_by_index("eth", dev_seq(pdev), env_enetaddr); + if (!is_zero_ethaddr(env_enetaddr)) { + /* individual port mac addrs require master to be promisc */ + struct eth_ops *eth_ops = eth_get_ops(master); + + if (eth_ops->set_promisc) + eth_ops->set_promisc(master, 1); + + return; + } + + master_pdata = dev_get_plat(master); + eth_pdata = dev_get_plat(pdev); + memcpy(eth_pdata->enetaddr, master_pdata->enetaddr, ARP_HLEN); + eth_env_set_enetaddr_by_index("eth", dev_seq(pdev), + master_pdata->enetaddr); +} + +static int dsa_port_probe(struct udevice *pdev) +{ + struct udevice *dev = dev_get_parent(pdev); struct dsa_port_pdata *port_pdata; struct dsa_priv *dsa_priv; struct udevice *master; @@ -272,26 +297,7 @@ static int dsa_port_probe(struct udevice *pdev) if (err) return err;
- /* - * Inherit port's hwaddr from the DSA master, unless the port already - * has a unique MAC address specified in the environment. - */ - eth_env_get_enetaddr_by_index("eth", dev_seq(pdev), env_enetaddr); - if (!is_zero_ethaddr(env_enetaddr)) { - /* individual port mac addrs require master to be promisc */ - struct eth_ops *eth_ops = eth_get_ops(master); - - if (eth_ops->set_promisc) - eth_ops->set_promisc(master, 1); - - return 0; - } - - master_pdata = dev_get_plat(master); - eth_pdata = dev_get_plat(pdev); - memcpy(eth_pdata->enetaddr, master_pdata->enetaddr, ARP_HLEN); - eth_env_set_enetaddr_by_index("eth", dev_seq(pdev), - master_pdata->enetaddr); + dsa_port_set_hwaddr(pdev, master);
return 0; }

On Tue, Aug 24, 2021 at 3:01 PM Vladimir Oltean vladimir.oltean@nxp.com wrote:
This snippet of code has a bothering "if (...) return 0" in it which assumes it is the last piece of code running in dsa_port_probe().
This makes it difficult to add further code at the end of dsa_port_probe() which does not depend on MAC address stuff.
So move the code to a dedicated function which returns void and let the code flow through.
Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Reviewed-by: Ramon Fried rfried.dev@gmail.com Tested-by: Michael Walle michael@walle.cc
net/dsa-uclass.c | 50 +++++++++++++++++++++++++++--------------------- 1 file changed, 28 insertions(+), 22 deletions(-)
diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c index f279ca7d2d6c..dbd8558b6486 100644 --- a/net/dsa-uclass.c +++ b/net/dsa-uclass.c @@ -240,11 +240,36 @@ static const struct eth_ops dsa_port_ops = { .free_pkt = dsa_port_free_pkt, };
-static int dsa_port_probe(struct udevice *pdev) +/*
- Inherit port's hwaddr from the DSA master, unless the port already has a
- unique MAC address specified in the environment.
- */
+static void dsa_port_set_hwaddr(struct udevice *pdev, struct udevice *master) {
struct udevice *dev = dev_get_parent(pdev); struct eth_pdata *eth_pdata, *master_pdata; unsigned char env_enetaddr[ARP_HLEN];
eth_env_get_enetaddr_by_index("eth", dev_seq(pdev), env_enetaddr);
if (!is_zero_ethaddr(env_enetaddr)) {
/* individual port mac addrs require master to be promisc */
struct eth_ops *eth_ops = eth_get_ops(master);
if (eth_ops->set_promisc)
eth_ops->set_promisc(master, 1);
return;
}
master_pdata = dev_get_plat(master);
eth_pdata = dev_get_plat(pdev);
memcpy(eth_pdata->enetaddr, master_pdata->enetaddr, ARP_HLEN);
eth_env_set_enetaddr_by_index("eth", dev_seq(pdev),
master_pdata->enetaddr);
+}
+static int dsa_port_probe(struct udevice *pdev) +{
struct udevice *dev = dev_get_parent(pdev); struct dsa_port_pdata *port_pdata; struct dsa_priv *dsa_priv; struct udevice *master;
@@ -272,26 +297,7 @@ static int dsa_port_probe(struct udevice *pdev) if (err) return err;
/*
* Inherit port's hwaddr from the DSA master, unless the port already
* has a unique MAC address specified in the environment.
*/
eth_env_get_enetaddr_by_index("eth", dev_seq(pdev), env_enetaddr);
if (!is_zero_ethaddr(env_enetaddr)) {
/* individual port mac addrs require master to be promisc */
struct eth_ops *eth_ops = eth_get_ops(master);
if (eth_ops->set_promisc)
eth_ops->set_promisc(master, 1);
return 0;
}
master_pdata = dev_get_plat(master);
eth_pdata = dev_get_plat(pdev);
memcpy(eth_pdata->enetaddr, master_pdata->enetaddr, ARP_HLEN);
eth_env_set_enetaddr_by_index("eth", dev_seq(pdev),
master_pdata->enetaddr);
dsa_port_set_hwaddr(pdev, master); return 0;
}
2.25.1
Applied to u-boot-net/network-master Thanks, Ramon.

Some drivers might want to execute code for each port at probe time, as opposed to executing code just-in-time for the port selected for networking.
To cater to that use case, introduce a .port_probe() callback method into the DSA switch operations which is called for each available port, at the end of dsa_port_probe().
Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Reviewed-by: Ramon Fried rfried.dev@gmail.com Tested-by: Michael Walle michael@walle.cc --- include/net/dsa.h | 5 ++++- net/dsa-uclass.c | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/include/net/dsa.h b/include/net/dsa.h index 0f31a908c9d1..ab2a9dfbea2d 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -57,7 +57,8 @@ /** * struct dsa_ops - DSA operations * - * @port_enable: Initialize a switch port for I/O. + * @port_probe: Initialize a switch port. + * @port_enable: Enable I/O for a port. * @port_disable: Disable I/O for a port. * @xmit: Insert the DSA tag for transmission. * DSA drivers receive a copy of the packet with headroom and @@ -69,6 +70,8 @@ * master including any additional headers. */ struct dsa_ops { + int (*port_probe)(struct udevice *dev, int port, + struct phy_device *phy); int (*port_enable)(struct udevice *dev, int port, struct phy_device *phy); void (*port_disable)(struct udevice *dev, int port, diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c index dbd8558b6486..9b8ae1e82b92 100644 --- a/net/dsa-uclass.c +++ b/net/dsa-uclass.c @@ -270,6 +270,7 @@ static void dsa_port_set_hwaddr(struct udevice *pdev, struct udevice *master) static int dsa_port_probe(struct udevice *pdev) { struct udevice *dev = dev_get_parent(pdev); + struct dsa_ops *ops = dsa_get_ops(dev); struct dsa_port_pdata *port_pdata; struct dsa_priv *dsa_priv; struct udevice *master; @@ -299,6 +300,13 @@ static int dsa_port_probe(struct udevice *pdev)
dsa_port_set_hwaddr(pdev, master);
+ if (ops->port_probe) { + err = ops->port_probe(dev, port_pdata->index, + port_pdata->phy); + if (err) + return err; + } + return 0; }

On Tue, Aug 24, 2021 at 3:01 PM Vladimir Oltean vladimir.oltean@nxp.com wrote:
Some drivers might want to execute code for each port at probe time, as opposed to executing code just-in-time for the port selected for networking.
To cater to that use case, introduce a .port_probe() callback method into the DSA switch operations which is called for each available port, at the end of dsa_port_probe().
Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Reviewed-by: Ramon Fried rfried.dev@gmail.com Tested-by: Michael Walle michael@walle.cc
include/net/dsa.h | 5 ++++- net/dsa-uclass.c | 8 ++++++++ 2 files changed, 12 insertions(+), 1 deletion(-)
diff --git a/include/net/dsa.h b/include/net/dsa.h index 0f31a908c9d1..ab2a9dfbea2d 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -57,7 +57,8 @@ /**
- struct dsa_ops - DSA operations
- @port_enable: Initialize a switch port for I/O.
- @port_probe: Initialize a switch port.
- @port_enable: Enable I/O for a port.
- @port_disable: Disable I/O for a port.
- @xmit: Insert the DSA tag for transmission.
DSA drivers receive a copy of the packet with headroom and
@@ -69,6 +70,8 @@
master including any additional headers.
*/ struct dsa_ops {
int (*port_probe)(struct udevice *dev, int port,
struct phy_device *phy); int (*port_enable)(struct udevice *dev, int port, struct phy_device *phy); void (*port_disable)(struct udevice *dev, int port,
diff --git a/net/dsa-uclass.c b/net/dsa-uclass.c index dbd8558b6486..9b8ae1e82b92 100644 --- a/net/dsa-uclass.c +++ b/net/dsa-uclass.c @@ -270,6 +270,7 @@ static void dsa_port_set_hwaddr(struct udevice *pdev, struct udevice *master) static int dsa_port_probe(struct udevice *pdev) { struct udevice *dev = dev_get_parent(pdev);
struct dsa_ops *ops = dsa_get_ops(dev); struct dsa_port_pdata *port_pdata; struct dsa_priv *dsa_priv; struct udevice *master;
@@ -299,6 +300,13 @@ static int dsa_port_probe(struct udevice *pdev)
dsa_port_set_hwaddr(pdev, master);
if (ops->port_probe) {
err = ops->port_probe(dev, port_pdata->index,
port_pdata->phy);
if (err)
return err;
}
return 0;
}
-- 2.25.1
Applied to u-boot-net/network-master Thanks, Ramon.

It is an unfortunate reality that some PHY settings done by U-Boot persist even after the PHY is reset and taken over by Linux, and even more unfortunate that Linux has come to depend on things being set in a certain way.
For example, on the NXP LS1028A-RDB, the felix switch ports are connected to a VSC8514 QSGMII PHY. Between the switch port PCS and the PHY, the U-Boot drivers enable in-band auto-negotiation which makes the copper-side negotiated speed and duplex be transmitted from the PHY to the MAC automatically.
The PHY driver portion that does this is in vsc8514_config():
/* Enable Serdes Auto-negotiation */ phy_write(phydev, MDIO_DEVAD_NONE, PHY_EXT_PAGE_ACCESS, PHY_EXT_PAGE_ACCESS_EXTENDED3); val = phy_read(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_MAC_SERDES_CON); val = val | MIIM_VSC8574_MAC_SERDES_ANEG; phy_write(phydev, MDIO_DEVAD_NONE, MIIM_VSC8514_MAC_SERDES_CON, val);
The point is that in-band autoneg should be turned on in both the PHY and the MAC, or off in both the PHY and the MAC, otherwise the QSGMII link will be broken.
And because phy_config() is currently called at .port_enable() time, the result is that ports on which traffic has been sent in U-Boot will have in-band autoneg enabled, and the rest won't.
It can be argued that the Linux kernel should not assume one way or another and just reinitialize everything according to what it expects, and that is completely fair. In fact, I've already started an attempt to remove this dependency, although admittedly I am making slow progress at it: https://patchwork.kernel.org/project/netdevbpf/cover/20210212172341.3489046-...
Nonetheless, the sad reality is that NXP also has, apart from kernel drivers, some user space networking (DPDK), and for some reason, the expectation there is that somebody else initializes the PHYs. The kernel can't do it because the device ownership doesn't belong to the kernel, so what remains is for the bootloader to do it (especially since other drivers generally call phy_config() at probe time). This is a really weak guarantee that might break at any time, but apparently that is enough for some.
Since initializing the ports and PHYs at probe time does not break anything, we can just do that.
Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Reviewed-by: Ramon Fried rfried.dev@gmail.com Tested-by: Michael Walle michael@walle.cc --- drivers/net/mscc_eswitch/felix_switch.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-)
diff --git a/drivers/net/mscc_eswitch/felix_switch.c b/drivers/net/mscc_eswitch/felix_switch.c index 75073880cf87..c8ecf4f19442 100644 --- a/drivers/net/mscc_eswitch/felix_switch.c +++ b/drivers/net/mscc_eswitch/felix_switch.c @@ -317,10 +317,23 @@ static int felix_probe(struct udevice *dev) return 0; }
+static int felix_port_probe(struct udevice *dev, int port, + struct phy_device *phy) +{ + int supported = PHY_GBIT_FEATURES | SUPPORTED_2500baseX_Full; + struct felix_priv *priv = dev_get_priv(dev); + + phy->supported &= supported; + phy->advertising &= supported; + + felix_start_pcs(dev, port, phy, &priv->imdio); + + return phy_config(phy); +} + static int felix_port_enable(struct udevice *dev, int port, struct phy_device *phy) { - int supported = PHY_GBIT_FEATURES | SUPPORTED_2500baseX_Full; struct felix_priv *priv = dev_get_priv(dev); void *base = priv->regs_base;
@@ -339,12 +352,6 @@ static int felix_port_enable(struct udevice *dev, int port, FELIX_QSYS_SYSTEM_SW_PORT_LOSSY | FELIX_QSYS_SYSTEM_SW_PORT_SCH(1));
- felix_start_pcs(dev, port, phy, &priv->imdio); - - phy->supported &= supported; - phy->advertising &= supported; - phy_config(phy); - phy_startup(phy);
return 0; @@ -392,6 +399,7 @@ static int felix_rcv(struct udevice *dev, int *pidx, void *packet, int length) }
static const struct dsa_ops felix_dsa_ops = { + .port_probe = felix_port_probe, .port_enable = felix_port_enable, .port_disable = felix_port_disable, .xmit = felix_xmit,

Make sure that the link status returned by phy_startup() is propagated to the .start() method of struct eth_ops.
Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Reviewed-by: Ramon Fried rfried.dev@gmail.com Tested-by: Michael Walle michael@walle.cc --- drivers/net/mscc_eswitch/felix_switch.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/net/mscc_eswitch/felix_switch.c b/drivers/net/mscc_eswitch/felix_switch.c index c8ecf4f19442..6aa79784460d 100644 --- a/drivers/net/mscc_eswitch/felix_switch.c +++ b/drivers/net/mscc_eswitch/felix_switch.c @@ -352,9 +352,7 @@ static int felix_port_enable(struct udevice *dev, int port, FELIX_QSYS_SYSTEM_SW_PORT_LOSSY | FELIX_QSYS_SYSTEM_SW_PORT_SCH(1));
- phy_startup(phy); - - return 0; + return phy_startup(phy); }
static void felix_port_disable(struct udevice *dev, int pidx,

On Tue, Aug 24, 2021 at 3:01 PM Vladimir Oltean vladimir.oltean@nxp.com wrote:
Make sure that the link status returned by phy_startup() is propagated to the .start() method of struct eth_ops.
Signed-off-by: Vladimir Oltean vladimir.oltean@nxp.com Reviewed-by: Ramon Fried rfried.dev@gmail.com Tested-by: Michael Walle michael@walle.cc
drivers/net/mscc_eswitch/felix_switch.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/net/mscc_eswitch/felix_switch.c b/drivers/net/mscc_eswitch/felix_switch.c index c8ecf4f19442..6aa79784460d 100644 --- a/drivers/net/mscc_eswitch/felix_switch.c +++ b/drivers/net/mscc_eswitch/felix_switch.c @@ -352,9 +352,7 @@ static int felix_port_enable(struct udevice *dev, int port, FELIX_QSYS_SYSTEM_SW_PORT_LOSSY | FELIX_QSYS_SYSTEM_SW_PORT_SCH(1));
phy_startup(phy);
return 0;
return phy_startup(phy);
}
static void felix_port_disable(struct udevice *dev, int pidx,
2.25.1
Applied to u-boot-net/network-master Thanks, Ramon.

On Tue, Aug 24, 2021 at 03:00:37PM +0300, Vladimir Oltean wrote:
Changes in v2: Rebased on top of the master branch (solves this conflict: https://patchwork.ozlabs.org/project/uboot/patch/20210629170839.2583797-4-ol... with Tim Harvey's patch to make DSA masters promiscuous)
This series makes the Felix DSA driver initialize all its connected PHYs regardless of whether those will be used for networking or not. This is in order to satisfy the expectations of some software in later boot stages.
To make this work, it is necessary to introduce a new method in struct dsa_ops: .port_probe().
There is some further refactoring/cleanup along the way.
Vladimir Oltean (6): net: dsa: felix: felix_init() can be static net: dsa: use "err" instead of "ret" in dsa_port_probe net: dsa: refactor the code to set the port MAC address into a dedicated function net: dsa: introduce a .port_probe() method in struct dsa_ops net: dsa: felix: call phy_config at .port_probe() time net: dsa: felix: propagate the error code from phy_startup()
drivers/net/mscc_eswitch/felix_switch.c | 28 ++++++----- include/net/dsa.h | 5 +- net/dsa-uclass.c | 62 +++++++++++++++---------- 3 files changed, 59 insertions(+), 36 deletions(-)
-- 2.25.1
It would be nice if these patches could go in through the networking tree, I would like to send one more DM_DSA driver and it also needs the new "port_probe" method introduced by this change set. Thanks.
participants (2)
-
Ramon Fried
-
Vladimir Oltean