Commit b3f98404 authored by David S. Miller's avatar David S. Miller

Merge branch 'dsa-devres'

Vladimir Oltean says:

====================
Fix mdiobus users with devres

Commit ac3a68d5 ("net: phy: don't abuse devres in
devm_mdiobus_register()") by Bartosz Golaszewski has introduced two
classes of potential bugs by making the devres callback of
devm_mdiobus_alloc stop calling mdiobus_unregister.

The exact buggy circumstances are presented in the individual commit
messages. I have searched the tree for other occurrences, but at the
moment:

- for issue (a) I have no concrete proof that other buses except SPI and
  I2C suffer from it, and the only SPI or I2C device drivers that call
  of_mdiobus_alloc are the DSA drivers that leave a NULL
  ds->slave_mii_bus and a non-NULL ds->ops->phy_read, aka ksz9477,
  ksz8795, lan9303_i2c, vsc73xx-spi.

- for issue (b), all drivers which call of_mdiobus_alloc either use
  of_mdiobus_register too, or call mdiobus_unregister sometime within
  the ->remove path.

Although at this point I've seen enough strangeness caused by this
"device_del during ->shutdown" that I'm just going to copy the SPI and
I2C subsystem maintainers to this patch series, to get their feedback
whether they've had reports about things like this before. I don't think
other buses behave in this way, it forces SPI and I2C devices to have to
protect themselves from a really strange set of issues.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 3e95cfa2 74b6d7d1
...@@ -368,7 +368,7 @@ int realtek_smi_setup_mdio(struct realtek_smi *smi) ...@@ -368,7 +368,7 @@ int realtek_smi_setup_mdio(struct realtek_smi *smi)
smi->slave_mii_bus->parent = smi->dev; smi->slave_mii_bus->parent = smi->dev;
smi->ds->slave_mii_bus = smi->slave_mii_bus; smi->ds->slave_mii_bus = smi->slave_mii_bus;
ret = of_mdiobus_register(smi->slave_mii_bus, mdio_np); ret = devm_of_mdiobus_register(smi->dev, smi->slave_mii_bus, mdio_np);
if (ret) { if (ret) {
dev_err(smi->dev, "unable to register MDIO bus %s\n", dev_err(smi->dev, "unable to register MDIO bus %s\n",
smi->slave_mii_bus->id); smi->slave_mii_bus->id);
......
...@@ -880,7 +880,7 @@ static int dsa_switch_setup(struct dsa_switch *ds) ...@@ -880,7 +880,7 @@ static int dsa_switch_setup(struct dsa_switch *ds)
devlink_params_publish(ds->devlink); devlink_params_publish(ds->devlink);
if (!ds->slave_mii_bus && ds->ops->phy_read) { if (!ds->slave_mii_bus && ds->ops->phy_read) {
ds->slave_mii_bus = devm_mdiobus_alloc(ds->dev); ds->slave_mii_bus = mdiobus_alloc();
if (!ds->slave_mii_bus) { if (!ds->slave_mii_bus) {
err = -ENOMEM; err = -ENOMEM;
goto teardown; goto teardown;
...@@ -890,13 +890,16 @@ static int dsa_switch_setup(struct dsa_switch *ds) ...@@ -890,13 +890,16 @@ static int dsa_switch_setup(struct dsa_switch *ds)
err = mdiobus_register(ds->slave_mii_bus); err = mdiobus_register(ds->slave_mii_bus);
if (err < 0) if (err < 0)
goto teardown; goto free_slave_mii_bus;
} }
ds->setup = true; ds->setup = true;
return 0; return 0;
free_slave_mii_bus:
if (ds->slave_mii_bus && ds->ops->phy_read)
mdiobus_free(ds->slave_mii_bus);
teardown: teardown:
if (ds->ops->teardown) if (ds->ops->teardown)
ds->ops->teardown(ds); ds->ops->teardown(ds);
...@@ -921,8 +924,11 @@ static void dsa_switch_teardown(struct dsa_switch *ds) ...@@ -921,8 +924,11 @@ static void dsa_switch_teardown(struct dsa_switch *ds)
if (!ds->setup) if (!ds->setup)
return; return;
if (ds->slave_mii_bus && ds->ops->phy_read) if (ds->slave_mii_bus && ds->ops->phy_read) {
mdiobus_unregister(ds->slave_mii_bus); mdiobus_unregister(ds->slave_mii_bus);
mdiobus_free(ds->slave_mii_bus);
ds->slave_mii_bus = NULL;
}
dsa_switch_unregister_notifier(ds); dsa_switch_unregister_notifier(ds);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment