Commit 68e1010c authored by Vladimir Oltean's avatar Vladimir Oltean Committed by David S. Miller

net: dsa: qca8k: put MDIO bus OF node on qca8k_mdio_register() failure

of_get_child_by_name() gives us an OF node with an elevated refcount,
which should be dropped when we're done with it. This is so that,
if (of_node_check_flag(node, OF_DYNAMIC)) is true, the node's memory can
eventually be freed.

There are 2 distinct paths to be considered in qca8k_mdio_register():

- devm_of_mdiobus_register() succeeds: since commit 3b73a7b8 ("net:
  mdio_bus: add refcounting for fwnodes to mdiobus"), the MDIO core
  treats this well.

- devm_of_mdiobus_register() or anything up to that point fails: it is
  the duty of the qca8k driver to release the OF node.

This change addresses the second case by making sure that the OF node
reference is not leaked.

The "mdio" node may be NULL, but of_node_put(NULL) is safe.
Signed-off-by: default avatarVladimir Oltean <vladimir.oltean@nxp.com>
Reviewed-by: default avatarAlvin Šipraga <alsi@bang-olufsen.dk>
Reviewed-by: default avatarFlorian Fainelli <florian.fainelli@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 7a898539
...@@ -949,10 +949,15 @@ qca8k_mdio_register(struct qca8k_priv *priv) ...@@ -949,10 +949,15 @@ qca8k_mdio_register(struct qca8k_priv *priv)
struct dsa_switch *ds = priv->ds; struct dsa_switch *ds = priv->ds;
struct device_node *mdio; struct device_node *mdio;
struct mii_bus *bus; struct mii_bus *bus;
int err;
mdio = of_get_child_by_name(priv->dev->of_node, "mdio");
bus = devm_mdiobus_alloc(ds->dev); bus = devm_mdiobus_alloc(ds->dev);
if (!bus) if (!bus) {
return -ENOMEM; err = -ENOMEM;
goto out_put_node;
}
bus->priv = (void *)priv; bus->priv = (void *)priv;
snprintf(bus->id, MII_BUS_ID_SIZE, "qca8k-%d.%d", snprintf(bus->id, MII_BUS_ID_SIZE, "qca8k-%d.%d",
...@@ -962,12 +967,12 @@ qca8k_mdio_register(struct qca8k_priv *priv) ...@@ -962,12 +967,12 @@ qca8k_mdio_register(struct qca8k_priv *priv)
ds->user_mii_bus = bus; ds->user_mii_bus = bus;
/* Check if the devicetree declare the port:phy mapping */ /* Check if the devicetree declare the port:phy mapping */
mdio = of_get_child_by_name(priv->dev->of_node, "mdio");
if (of_device_is_available(mdio)) { if (of_device_is_available(mdio)) {
bus->name = "qca8k user mii"; bus->name = "qca8k user mii";
bus->read = qca8k_internal_mdio_read; bus->read = qca8k_internal_mdio_read;
bus->write = qca8k_internal_mdio_write; bus->write = qca8k_internal_mdio_write;
return devm_of_mdiobus_register(priv->dev, bus, mdio); err = devm_of_mdiobus_register(priv->dev, bus, mdio);
goto out_put_node;
} }
/* If a mapping can't be found the legacy mapping is used, /* If a mapping can't be found the legacy mapping is used,
...@@ -976,7 +981,13 @@ qca8k_mdio_register(struct qca8k_priv *priv) ...@@ -976,7 +981,13 @@ qca8k_mdio_register(struct qca8k_priv *priv)
bus->name = "qca8k-legacy user mii"; bus->name = "qca8k-legacy user mii";
bus->read = qca8k_legacy_mdio_read; bus->read = qca8k_legacy_mdio_read;
bus->write = qca8k_legacy_mdio_write; bus->write = qca8k_legacy_mdio_write;
return devm_mdiobus_register(priv->dev, bus);
err = devm_mdiobus_register(priv->dev, bus);
out_put_node:
of_node_put(mdio);
return err;
} }
static int static int
......
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