Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 7322967b authored by Russell King's avatar Russell King Committed by David S. Miller
Browse files

phy: add proper phy struct device refcounting



Take a refcount on the phy struct device when the phy device is attached
to a network device, and drop it after it's detached.  This ensures that
a refcount is held on the phy device while the device is being used by
a network device, thereby preventing the phy_device from being
unexpectedly kfree()'d by phy_device_release().

Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 3e3aaf64
Loading
Loading
Loading
Loading
+12 −0
Original line number Original line Diff line number Diff line
@@ -578,6 +578,7 @@ EXPORT_SYMBOL(phy_init_hw);
 *     generic driver is used.  The phy_device is given a ptr to
 *     generic driver is used.  The phy_device is given a ptr to
 *     the attaching device, and given a callback for link status
 *     the attaching device, and given a callback for link status
 *     change.  The phy_device is returned to the attaching driver.
 *     change.  The phy_device is returned to the attaching driver.
 *     This function takes a reference on the phy device.
 */
 */
int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
		      u32 flags, phy_interface_t interface)
		      u32 flags, phy_interface_t interface)
@@ -591,6 +592,8 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
		return -EIO;
		return -EIO;
	}
	}


	get_device(d);

	/* Assume that if there is no driver, that it doesn't
	/* Assume that if there is no driver, that it doesn't
	 * exist, and we should use the genphy driver.
	 * exist, and we should use the genphy driver.
	 */
	 */
@@ -636,6 +639,7 @@ int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
	return err;
	return err;


error:
error:
	put_device(d);
	module_put(bus->owner);
	module_put(bus->owner);
	return err;
	return err;
}
}
@@ -679,6 +683,9 @@ EXPORT_SYMBOL(phy_attach);
/**
/**
 * phy_detach - detach a PHY device from its network device
 * phy_detach - detach a PHY device from its network device
 * @phydev: target phy_device struct
 * @phydev: target phy_device struct
 *
 * This detaches the phy device from its network device and the phy
 * driver, and drops the reference count taken in phy_attach_direct().
 */
 */
void phy_detach(struct phy_device *phydev)
void phy_detach(struct phy_device *phydev)
{
{
@@ -701,8 +708,13 @@ void phy_detach(struct phy_device *phydev)
		}
		}
	}
	}


	/*
	 * The phydev might go away on the put_device() below, so avoid
	 * a use-after-free bug by reading the underlying bus first.
	 */
	bus = phydev->bus;
	bus = phydev->bus;


	put_device(&phydev->dev);
	module_put(bus->owner);
	module_put(bus->owner);
}
}
EXPORT_SYMBOL(phy_detach);
EXPORT_SYMBOL(phy_detach);