diff options
author | Jon Mason <jon.mason@broadcom.com> | 2017-05-10 11:20:27 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2017-05-11 12:32:43 -0400 |
commit | b60161668199ac62011c024adc9e66713b9554e7 (patch) | |
tree | 47c486ace32fbd0d1ebd4c9711f615035e7eb1b3 /drivers/net/phy | |
parent | 83eaddab4378db256d00d295bda6ca997cd13a52 (diff) | |
download | linux-b60161668199ac62011c024adc9e66713b9554e7.tar.bz2 |
mdio: mux: Correct mdio_mux_init error path issues
There is a potential unnecessary refcount decrement on error path of
put_device(&pb->mii_bus->dev), as it is possible to avoid the
of_mdio_find_bus() call if mux_bus is specified by the calling function.
The same put_device() is not called in the error path if the
devm_kzalloc of pb fails. This caused the variable used in the
put_device() to be changed, as the pb pointer was obviously not set up.
There is an unnecessary of_node_get() on child_bus_node if the
of_mdiobus_register() is successful, as the
for_each_available_child_of_node() automatically increments this.
Thus the refcount on this node will always be +1 more than it should be.
There is no of_node_put() on child_bus_node if the of_mdiobus_register()
call fails.
Finally, it is lacking devm_kfree() of pb in the error path. While this
might not be technically necessary, it was present in other parts of the
function. So, I am adding it where necessary to make it uniform.
Signed-off-by: Jon Mason <jon.mason@broadcom.com>
Fixes: f20e6657a875 ("mdio: mux: Enhanced MDIO mux framework for integrated multiplexers")
Fixes: 0ca2997d1452 ("netdev/of/phy: Add MDIO bus multiplexer support.")
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/phy')
-rw-r--r-- | drivers/net/phy/mdio-mux.c | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/drivers/net/phy/mdio-mux.c b/drivers/net/phy/mdio-mux.c index 963838d4fac1..6943c5ece44a 100644 --- a/drivers/net/phy/mdio-mux.c +++ b/drivers/net/phy/mdio-mux.c @@ -122,10 +122,9 @@ int mdio_mux_init(struct device *dev, pb = devm_kzalloc(dev, sizeof(*pb), GFP_KERNEL); if (pb == NULL) { ret_val = -ENOMEM; - goto err_parent_bus; + goto err_pb_kz; } - pb->switch_data = data; pb->switch_fn = switch_fn; pb->current_child = -1; @@ -154,6 +153,7 @@ int mdio_mux_init(struct device *dev, cb->mii_bus = mdiobus_alloc(); if (!cb->mii_bus) { ret_val = -ENOMEM; + devm_kfree(dev, cb); of_node_put(child_bus_node); break; } @@ -169,8 +169,8 @@ int mdio_mux_init(struct device *dev, if (r) { mdiobus_free(cb->mii_bus); devm_kfree(dev, cb); + of_node_put(child_bus_node); } else { - of_node_get(child_bus_node); cb->next = pb->children; pb->children = cb; } @@ -181,9 +181,11 @@ int mdio_mux_init(struct device *dev, return 0; } + devm_kfree(dev, pb); +err_pb_kz: /* balance the reference of_mdio_find_bus() took */ - put_device(&pb->mii_bus->dev); - + if (!mux_bus) + put_device(&parent_bus->dev); err_parent_bus: of_node_put(parent_bus_node); return ret_val; |