Skip to content

Commit 1335648

Browse files
committed
Merge branch 'more-dsa-fixes-for-devres-mdiobus_-alloc-register'
Vladimir Oltean says: ==================== More DSA fixes for devres + mdiobus_{alloc,register} The initial patch series "[net,0/2] Fix mdiobus users with devres" https://patchwork.kernel.org/project/netdevbpf/cover/20210920214209.1733768-1-vladimir.oltean@nxp.com/ fixed some instances where DSA drivers on slow buses (SPI, I2C) trigger a panic (changed since then to a warn) in mdiobus_free. That was due to devres calling mdiobus_free() with no prior mdiobus_unregister(), which again was due to commit ac3a68d ("net: phy: don't abuse devres in devm_mdiobus_register()") by Bartosz Golaszewski. Rafael Richter and Daniel Klauer report yet another variation on that theme, but this time it applies to any DSA switch driver, not just those on buses which have a "->shutdown() calls ->remove() which unregisters children" sequence. Their setup is that of an LX2160A DPAA2 SoC driving a Marvell DSA switch (MDIO). DPAA2 Ethernet drivers probe on the "fsl-mc" bus (drivers/bus/fsl-mc/fsl-mc-bus.c). This bus is meant to be the kernel-side representation of the networking objects kept by the Management Complex (MC) firmware. The fsl-mc bus driver has this pattern: static void fsl_mc_bus_shutdown(struct platform_device *pdev) { fsl_mc_bus_remove(pdev); } which proceeds to remove the children on the bus. Among those children, the dpaa2-eth network driver. When dpaa2-eth is a DSA master, this removal of the master on shutdown trips up the device link created by dsa_master_setup(), and as such, the Marvell switch is also removed. From this point on, readers can revisit the description of commits 74b6d7d ("net: dsa: realtek: register the MDIO bus under devres") 5135e96 ("net: dsa: don't allocate the slave_mii_bus using devres") since the prerequisites for the BUG_ON in mdiobus_free() have been accomplished if there is a devres mismatch between mdiobus_alloc() and mdiobus_register(). Most DSA drivers have this kind of mismatch, and upon my initial assessment I had not realized the possibility described above, so I didn't fix it. This patch series walks through all drivers and makes them use either fully devres, or no devres. I am aware that there are DSA drivers that are only known to be tested with a single DSA master, so some patches are probably overkill for them. But code is copy-pasted from so many sources without fully understanding the differences, that I think it's better to not leave an in-tree source of inspiration that may lead to subtle breakage if not adapted properly. ==================== Link: https://lore.kernel.org/r/20220207161553.579933-1-vladimir.oltean@nxp.com Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2 parents 23de0d7 + 0d120df commit 1335648

File tree

7 files changed

+32
-14
lines changed

7 files changed

+32
-14
lines changed

drivers/net/dsa/bcm_sf2.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -621,7 +621,7 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds)
621621
get_device(&priv->master_mii_bus->dev);
622622
priv->master_mii_dn = dn;
623623

624-
priv->slave_mii_bus = devm_mdiobus_alloc(ds->dev);
624+
priv->slave_mii_bus = mdiobus_alloc();
625625
if (!priv->slave_mii_bus) {
626626
of_node_put(dn);
627627
return -ENOMEM;
@@ -681,15 +681,18 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds)
681681
}
682682

683683
err = mdiobus_register(priv->slave_mii_bus);
684-
if (err && dn)
684+
if (err && dn) {
685+
mdiobus_free(priv->slave_mii_bus);
685686
of_node_put(dn);
687+
}
686688

687689
return err;
688690
}
689691

690692
static void bcm_sf2_mdio_unregister(struct bcm_sf2_priv *priv)
691693
{
692694
mdiobus_unregister(priv->slave_mii_bus);
695+
mdiobus_free(priv->slave_mii_bus);
693696
of_node_put(priv->master_mii_dn);
694697
}
695698

drivers/net/dsa/lantiq_gswip.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -498,8 +498,9 @@ static int gswip_mdio_rd(struct mii_bus *bus, int addr, int reg)
498498
static int gswip_mdio(struct gswip_priv *priv, struct device_node *mdio_np)
499499
{
500500
struct dsa_switch *ds = priv->ds;
501+
int err;
501502

502-
ds->slave_mii_bus = devm_mdiobus_alloc(priv->dev);
503+
ds->slave_mii_bus = mdiobus_alloc();
503504
if (!ds->slave_mii_bus)
504505
return -ENOMEM;
505506

@@ -512,7 +513,11 @@ static int gswip_mdio(struct gswip_priv *priv, struct device_node *mdio_np)
512513
ds->slave_mii_bus->parent = priv->dev;
513514
ds->slave_mii_bus->phy_mask = ~ds->phys_mii_mask;
514515

515-
return of_mdiobus_register(ds->slave_mii_bus, mdio_np);
516+
err = of_mdiobus_register(ds->slave_mii_bus, mdio_np);
517+
if (err)
518+
mdiobus_free(ds->slave_mii_bus);
519+
520+
return err;
516521
}
517522

518523
static int gswip_pce_table_entry_read(struct gswip_priv *priv,
@@ -2145,8 +2150,10 @@ static int gswip_probe(struct platform_device *pdev)
21452150
gswip_mdio_mask(priv, GSWIP_MDIO_GLOB_ENABLE, 0, GSWIP_MDIO_GLOB);
21462151
dsa_unregister_switch(priv->ds);
21472152
mdio_bus:
2148-
if (mdio_np)
2153+
if (mdio_np) {
21492154
mdiobus_unregister(priv->ds->slave_mii_bus);
2155+
mdiobus_free(priv->ds->slave_mii_bus);
2156+
}
21502157
put_mdio_node:
21512158
of_node_put(mdio_np);
21522159
for (i = 0; i < priv->num_gphy_fw; i++)
@@ -2169,6 +2176,7 @@ static int gswip_remove(struct platform_device *pdev)
21692176

21702177
if (priv->ds->slave_mii_bus) {
21712178
mdiobus_unregister(priv->ds->slave_mii_bus);
2179+
mdiobus_free(priv->ds->slave_mii_bus);
21722180
of_node_put(priv->ds->slave_mii_bus->dev.of_node);
21732181
}
21742182

drivers/net/dsa/mt7530.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2074,7 +2074,7 @@ mt7530_setup_mdio(struct mt7530_priv *priv)
20742074
if (priv->irq)
20752075
mt7530_setup_mdio_irq(priv);
20762076

2077-
ret = mdiobus_register(bus);
2077+
ret = devm_mdiobus_register(dev, bus);
20782078
if (ret) {
20792079
dev_err(dev, "failed to register MDIO bus: %d\n", ret);
20802080
if (priv->irq)

drivers/net/dsa/mv88e6xxx/chip.c

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3399,7 +3399,7 @@ static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip,
33993399
return err;
34003400
}
34013401

3402-
bus = devm_mdiobus_alloc_size(chip->dev, sizeof(*mdio_bus));
3402+
bus = mdiobus_alloc_size(sizeof(*mdio_bus));
34033403
if (!bus)
34043404
return -ENOMEM;
34053405

@@ -3424,14 +3424,14 @@ static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip,
34243424
if (!external) {
34253425
err = mv88e6xxx_g2_irq_mdio_setup(chip, bus);
34263426
if (err)
3427-
return err;
3427+
goto out;
34283428
}
34293429

34303430
err = of_mdiobus_register(bus, np);
34313431
if (err) {
34323432
dev_err(chip->dev, "Cannot register MDIO bus (%d)\n", err);
34333433
mv88e6xxx_g2_irq_mdio_free(chip, bus);
3434-
return err;
3434+
goto out;
34353435
}
34363436

34373437
if (external)
@@ -3440,6 +3440,10 @@ static int mv88e6xxx_mdio_register(struct mv88e6xxx_chip *chip,
34403440
list_add(&mdio_bus->list, &chip->mdios);
34413441

34423442
return 0;
3443+
3444+
out:
3445+
mdiobus_free(bus);
3446+
return err;
34433447
}
34443448

34453449
static void mv88e6xxx_mdios_unregister(struct mv88e6xxx_chip *chip)
@@ -3455,6 +3459,7 @@ static void mv88e6xxx_mdios_unregister(struct mv88e6xxx_chip *chip)
34553459
mv88e6xxx_g2_irq_mdio_free(chip, bus);
34563460

34573461
mdiobus_unregister(bus);
3462+
mdiobus_free(bus);
34583463
}
34593464
}
34603465

drivers/net/dsa/ocelot/felix_vsc9959.c

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1061,7 +1061,7 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
10611061
return PTR_ERR(hw);
10621062
}
10631063

1064-
bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv));
1064+
bus = mdiobus_alloc_size(sizeof(*mdio_priv));
10651065
if (!bus)
10661066
return -ENOMEM;
10671067

@@ -1081,6 +1081,7 @@ static int vsc9959_mdio_bus_alloc(struct ocelot *ocelot)
10811081
rc = mdiobus_register(bus);
10821082
if (rc < 0) {
10831083
dev_err(dev, "failed to register MDIO bus\n");
1084+
mdiobus_free(bus);
10841085
return rc;
10851086
}
10861087

@@ -1132,6 +1133,7 @@ static void vsc9959_mdio_bus_free(struct ocelot *ocelot)
11321133
lynx_pcs_destroy(phylink_pcs);
11331134
}
11341135
mdiobus_unregister(felix->imdio);
1136+
mdiobus_free(felix->imdio);
11351137
}
11361138

11371139
static void vsc9959_sched_speed_set(struct ocelot *ocelot, int port,

drivers/net/dsa/ocelot/seville_vsc9953.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1029,7 +1029,7 @@ static int vsc9953_mdio_bus_alloc(struct ocelot *ocelot)
10291029
}
10301030

10311031
/* Needed in order to initialize the bus mutex lock */
1032-
rc = of_mdiobus_register(bus, NULL);
1032+
rc = devm_of_mdiobus_register(dev, bus, NULL);
10331033
if (rc < 0) {
10341034
dev_err(dev, "failed to register MDIO bus\n");
10351035
return rc;
@@ -1083,7 +1083,8 @@ static void vsc9953_mdio_bus_free(struct ocelot *ocelot)
10831083
mdio_device_free(mdio_device);
10841084
lynx_pcs_destroy(phylink_pcs);
10851085
}
1086-
mdiobus_unregister(felix->imdio);
1086+
1087+
/* mdiobus_unregister and mdiobus_free handled by devres */
10871088
}
10881089

10891090
static const struct felix_info seville_info_vsc9953 = {

drivers/net/dsa/qca/ar9331.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -378,7 +378,7 @@ static int ar9331_sw_mbus_init(struct ar9331_sw_priv *priv)
378378
if (!mnp)
379379
return -ENODEV;
380380

381-
ret = of_mdiobus_register(mbus, mnp);
381+
ret = devm_of_mdiobus_register(dev, mbus, mnp);
382382
of_node_put(mnp);
383383
if (ret)
384384
return ret;
@@ -1091,7 +1091,6 @@ static void ar9331_sw_remove(struct mdio_device *mdiodev)
10911091
}
10921092

10931093
irq_domain_remove(priv->irqdomain);
1094-
mdiobus_unregister(priv->mbus);
10951094
dsa_unregister_switch(&priv->ds);
10961095

10971096
reset_control_assert(priv->sw_reset);

0 commit comments

Comments
 (0)