Commit a1364421 authored by Russell King's avatar Russell King Committed by David S. Miller

phy: fix of_mdio_find_bus() device refcount leak

of_mdio_find_bus() leaks a struct device refcount, caused by using
class_find_device() and not realising that the device reference has
its refcount incremented:

 * Note, you will need to drop the reference with put_device() after use.
...
        while ((dev = class_dev_iter_next(&iter))) {
                if (match(dev, data)) {
                        get_device(dev);
                        break;
                }

Update the comment, and arrange for the phy code to drop this refcount
when disposing of a reference to it.
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 17a10c92
...@@ -113,18 +113,18 @@ int mdio_mux_init(struct device *dev, ...@@ -113,18 +113,18 @@ int mdio_mux_init(struct device *dev,
if (!parent_bus_node) if (!parent_bus_node)
return -ENODEV; return -ENODEV;
parent_bus = of_mdio_find_bus(parent_bus_node);
if (parent_bus == NULL) {
ret_val = -EPROBE_DEFER;
goto err_parent_bus;
}
pb = devm_kzalloc(dev, sizeof(*pb), GFP_KERNEL); pb = devm_kzalloc(dev, sizeof(*pb), GFP_KERNEL);
if (pb == NULL) { if (pb == NULL) {
ret_val = -ENOMEM; ret_val = -ENOMEM;
goto err_parent_bus; goto err_parent_bus;
} }
parent_bus = of_mdio_find_bus(parent_bus_node);
if (parent_bus == NULL) {
ret_val = -EPROBE_DEFER;
goto err_parent_bus;
}
pb->switch_data = data; pb->switch_data = data;
pb->switch_fn = switch_fn; pb->switch_fn = switch_fn;
pb->current_child = -1; pb->current_child = -1;
...@@ -173,6 +173,10 @@ int mdio_mux_init(struct device *dev, ...@@ -173,6 +173,10 @@ int mdio_mux_init(struct device *dev,
dev_info(dev, "Version " DRV_VERSION "\n"); dev_info(dev, "Version " DRV_VERSION "\n");
return 0; return 0;
} }
/* balance the reference of_mdio_find_bus() took */
put_device(&pb->mii_bus->dev);
err_parent_bus: err_parent_bus:
of_node_put(parent_bus_node); of_node_put(parent_bus_node);
return ret_val; return ret_val;
...@@ -189,6 +193,9 @@ void mdio_mux_uninit(void *mux_handle) ...@@ -189,6 +193,9 @@ void mdio_mux_uninit(void *mux_handle)
mdiobus_free(cb->mii_bus); mdiobus_free(cb->mii_bus);
cb = cb->next; cb = cb->next;
} }
/* balance the reference of_mdio_find_bus() in mdio_mux_init() took */
put_device(&pb->mii_bus->dev);
} }
EXPORT_SYMBOL_GPL(mdio_mux_uninit); EXPORT_SYMBOL_GPL(mdio_mux_uninit);
......
...@@ -167,7 +167,9 @@ static int of_mdio_bus_match(struct device *dev, const void *mdio_bus_np) ...@@ -167,7 +167,9 @@ static int of_mdio_bus_match(struct device *dev, const void *mdio_bus_np)
* of_mdio_find_bus - Given an mii_bus node, find the mii_bus. * of_mdio_find_bus - Given an mii_bus node, find the mii_bus.
* @mdio_bus_np: Pointer to the mii_bus. * @mdio_bus_np: Pointer to the mii_bus.
* *
* Returns a pointer to the mii_bus, or NULL if none found. * Returns a reference to the mii_bus, or NULL if none found. The
* embedded struct device will have its reference count incremented,
* and this must be put once the bus is finished with.
* *
* Because the association of a device_node and mii_bus is made via * Because the association of a device_node and mii_bus is made via
* of_mdiobus_register(), the mii_bus cannot be found before it is * of_mdiobus_register(), the mii_bus cannot be found before it is
......
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