Merge branch 'net-phy-fix-locking-issue'
Heiner Kallweit says: ==================== net: phy: fix locking issue Russell pointed out that the locking used in phy_is_started() isn't needed and misleading. This locking also contributes to a race fixed with patch 2. ==================== Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
commit
61c4c0bcff
@ -553,7 +553,7 @@ int phy_start_aneg(struct phy_device *phydev)
|
|||||||
if (err < 0)
|
if (err < 0)
|
||||||
goto out_unlock;
|
goto out_unlock;
|
||||||
|
|
||||||
if (__phy_is_started(phydev)) {
|
if (phy_is_started(phydev)) {
|
||||||
if (phydev->autoneg == AUTONEG_ENABLE) {
|
if (phydev->autoneg == AUTONEG_ENABLE) {
|
||||||
err = phy_check_link_status(phydev);
|
err = phy_check_link_status(phydev);
|
||||||
} else {
|
} else {
|
||||||
@ -709,7 +709,7 @@ void phy_stop_machine(struct phy_device *phydev)
|
|||||||
cancel_delayed_work_sync(&phydev->state_queue);
|
cancel_delayed_work_sync(&phydev->state_queue);
|
||||||
|
|
||||||
mutex_lock(&phydev->lock);
|
mutex_lock(&phydev->lock);
|
||||||
if (__phy_is_started(phydev))
|
if (phy_is_started(phydev))
|
||||||
phydev->state = PHY_UP;
|
phydev->state = PHY_UP;
|
||||||
mutex_unlock(&phydev->lock);
|
mutex_unlock(&phydev->lock);
|
||||||
}
|
}
|
||||||
@ -839,15 +839,14 @@ EXPORT_SYMBOL(phy_stop_interrupts);
|
|||||||
*/
|
*/
|
||||||
void phy_stop(struct phy_device *phydev)
|
void phy_stop(struct phy_device *phydev)
|
||||||
{
|
{
|
||||||
mutex_lock(&phydev->lock);
|
if (!phy_is_started(phydev)) {
|
||||||
|
|
||||||
if (!__phy_is_started(phydev)) {
|
|
||||||
WARN(1, "called from state %s\n",
|
WARN(1, "called from state %s\n",
|
||||||
phy_state_to_str(phydev->state));
|
phy_state_to_str(phydev->state));
|
||||||
mutex_unlock(&phydev->lock);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex_lock(&phydev->lock);
|
||||||
|
|
||||||
if (phy_interrupt_is_valid(phydev))
|
if (phy_interrupt_is_valid(phydev))
|
||||||
phy_disable_interrupts(phydev);
|
phy_disable_interrupts(phydev);
|
||||||
|
|
||||||
@ -986,8 +985,10 @@ void phy_state_machine(struct work_struct *work)
|
|||||||
* state machine would be pointless and possibly error prone when
|
* state machine would be pointless and possibly error prone when
|
||||||
* called from phy_disconnect() synchronously.
|
* called from phy_disconnect() synchronously.
|
||||||
*/
|
*/
|
||||||
|
mutex_lock(&phydev->lock);
|
||||||
if (phy_polling_mode(phydev) && phy_is_started(phydev))
|
if (phy_polling_mode(phydev) && phy_is_started(phydev))
|
||||||
phy_queue_state_machine(phydev, PHY_STATE_TIME);
|
phy_queue_state_machine(phydev, PHY_STATE_TIME);
|
||||||
|
mutex_unlock(&phydev->lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -674,26 +674,13 @@ phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
|
|||||||
size_t phy_speeds(unsigned int *speeds, size_t size,
|
size_t phy_speeds(unsigned int *speeds, size_t size,
|
||||||
unsigned long *mask);
|
unsigned long *mask);
|
||||||
|
|
||||||
static inline bool __phy_is_started(struct phy_device *phydev)
|
|
||||||
{
|
|
||||||
WARN_ON(!mutex_is_locked(&phydev->lock));
|
|
||||||
|
|
||||||
return phydev->state >= PHY_UP;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* phy_is_started - Convenience function to check whether PHY is started
|
* phy_is_started - Convenience function to check whether PHY is started
|
||||||
* @phydev: The phy_device struct
|
* @phydev: The phy_device struct
|
||||||
*/
|
*/
|
||||||
static inline bool phy_is_started(struct phy_device *phydev)
|
static inline bool phy_is_started(struct phy_device *phydev)
|
||||||
{
|
{
|
||||||
bool started;
|
return phydev->state >= PHY_UP;
|
||||||
|
|
||||||
mutex_lock(&phydev->lock);
|
|
||||||
started = __phy_is_started(phydev);
|
|
||||||
mutex_unlock(&phydev->lock);
|
|
||||||
|
|
||||||
return started;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void phy_resolve_aneg_linkmode(struct phy_device *phydev);
|
void phy_resolve_aneg_linkmode(struct phy_device *phydev);
|
||||||
|
Loading…
Reference in New Issue
Block a user