net: thunderx: Don't leak phy device references on -EPROBE_DEFER condition.
It is possible, although unlikely, that probing will find the phy_device for the first LMAC of a thunder BGX device, but then need to fail with -EPROBE_DEFER on a subsequent LMAC. In this case, we need to call put_device() on each of the phy_devices that were obtained, but will be unused due to returning -EPROBE_DEFER. Also, since we can break out of the probing loop early, we need to explicitly call of_node_put() outside of the loop. Signed-off-by: David Daney <david.daney@cavium.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
9277a4f875
commit
b7d3e3d3d2
@ -974,17 +974,18 @@ static int bgx_init_acpi_phy(struct bgx *bgx)
|
|||||||
static int bgx_init_of_phy(struct bgx *bgx)
|
static int bgx_init_of_phy(struct bgx *bgx)
|
||||||
{
|
{
|
||||||
struct fwnode_handle *fwn;
|
struct fwnode_handle *fwn;
|
||||||
|
struct device_node *node = NULL;
|
||||||
u8 lmac = 0;
|
u8 lmac = 0;
|
||||||
const char *mac;
|
|
||||||
|
|
||||||
device_for_each_child_node(&bgx->pdev->dev, fwn) {
|
device_for_each_child_node(&bgx->pdev->dev, fwn) {
|
||||||
struct phy_device *pd;
|
struct phy_device *pd;
|
||||||
struct device_node *phy_np;
|
struct device_node *phy_np;
|
||||||
struct device_node *node = to_of_node(fwn);
|
const char *mac;
|
||||||
|
|
||||||
/* Should always be an OF node. But if it is not, we
|
/* Should always be an OF node. But if it is not, we
|
||||||
* cannot handle it, so exit the loop.
|
* cannot handle it, so exit the loop.
|
||||||
*/
|
*/
|
||||||
|
node = to_of_node(fwn);
|
||||||
if (!node)
|
if (!node)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1005,17 +1006,30 @@ static int bgx_init_of_phy(struct bgx *bgx)
|
|||||||
/* Wait until the phy drivers are available */
|
/* Wait until the phy drivers are available */
|
||||||
pd = of_phy_find_device(phy_np);
|
pd = of_phy_find_device(phy_np);
|
||||||
if (!pd)
|
if (!pd)
|
||||||
return -EPROBE_DEFER;
|
goto defer;
|
||||||
bgx->lmac[lmac].phydev = pd;
|
bgx->lmac[lmac].phydev = pd;
|
||||||
}
|
}
|
||||||
|
|
||||||
lmac++;
|
lmac++;
|
||||||
if (lmac == MAX_LMAC_PER_BGX) {
|
if (lmac == MAX_LMAC_PER_BGX)
|
||||||
of_node_put(node);
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
of_node_put(node);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
defer:
|
||||||
|
/* We are bailing out, try not to leak device reference counts
|
||||||
|
* for phy devices we may have already found.
|
||||||
|
*/
|
||||||
|
while (lmac) {
|
||||||
|
if (bgx->lmac[lmac].phydev) {
|
||||||
|
put_device(&bgx->lmac[lmac].phydev->mdio.dev);
|
||||||
|
bgx->lmac[lmac].phydev = NULL;
|
||||||
|
}
|
||||||
|
lmac--;
|
||||||
|
}
|
||||||
|
of_node_put(node);
|
||||||
|
return -EPROBE_DEFER;
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
Loading…
x
Reference in New Issue
Block a user