Commit 9ff8c68b authored by Maciej W. Rozycki's avatar Maciej W. Rozycki Committed by David S. Miller

PHYLIB: Spinlock fixes for softirqs

Use spin_lock_bh()/spin_unlock_bh() for the phydev lock throughout as it
is used in phy_timer() that is called as a softirq and all the other
operations may happen in the user context.

There has been a change recently that did such a conversion for some of the
operations on the lock, but some have been left intact.  Many of them,
perhaps all, may be called in the user context and I was able to trigger
recursive spinlock acquisition indeed, so I think for the sake of long-term
maintenance it is best to convert them all, even if unnecessarily for one
or two -- better safe than sorry.

Perhaps one in phy_timer() could actually be skipped as only called as a
softirq -- I can send an update if that sounds like a good idea.

Checked with checkpatch.pl and at the runtime.
Signed-off-by: default avatarMaciej W. Rozycki <macro@linux-mips.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarJeff Garzik <jeff@garzik.org>
parent 1f8f4559
...@@ -424,7 +424,7 @@ int phy_start_aneg(struct phy_device *phydev) ...@@ -424,7 +424,7 @@ int phy_start_aneg(struct phy_device *phydev)
{ {
int err; int err;
spin_lock(&phydev->lock); spin_lock_bh(&phydev->lock);
if (AUTONEG_DISABLE == phydev->autoneg) if (AUTONEG_DISABLE == phydev->autoneg)
phy_sanitize_settings(phydev); phy_sanitize_settings(phydev);
...@@ -445,7 +445,7 @@ int phy_start_aneg(struct phy_device *phydev) ...@@ -445,7 +445,7 @@ int phy_start_aneg(struct phy_device *phydev)
} }
out_unlock: out_unlock:
spin_unlock(&phydev->lock); spin_unlock_bh(&phydev->lock);
return err; return err;
} }
EXPORT_SYMBOL(phy_start_aneg); EXPORT_SYMBOL(phy_start_aneg);
...@@ -490,10 +490,10 @@ void phy_stop_machine(struct phy_device *phydev) ...@@ -490,10 +490,10 @@ void phy_stop_machine(struct phy_device *phydev)
{ {
del_timer_sync(&phydev->phy_timer); del_timer_sync(&phydev->phy_timer);
spin_lock(&phydev->lock); spin_lock_bh(&phydev->lock);
if (phydev->state > PHY_UP) if (phydev->state > PHY_UP)
phydev->state = PHY_UP; phydev->state = PHY_UP;
spin_unlock(&phydev->lock); spin_unlock_bh(&phydev->lock);
phydev->adjust_state = NULL; phydev->adjust_state = NULL;
} }
...@@ -537,9 +537,9 @@ static void phy_force_reduction(struct phy_device *phydev) ...@@ -537,9 +537,9 @@ static void phy_force_reduction(struct phy_device *phydev)
*/ */
void phy_error(struct phy_device *phydev) void phy_error(struct phy_device *phydev)
{ {
spin_lock(&phydev->lock); spin_lock_bh(&phydev->lock);
phydev->state = PHY_HALTED; phydev->state = PHY_HALTED;
spin_unlock(&phydev->lock); spin_unlock_bh(&phydev->lock);
} }
/** /**
...@@ -690,10 +690,10 @@ static void phy_change(struct work_struct *work) ...@@ -690,10 +690,10 @@ static void phy_change(struct work_struct *work)
if (err) if (err)
goto phy_err; goto phy_err;
spin_lock(&phydev->lock); spin_lock_bh(&phydev->lock);
if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state)) if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state))
phydev->state = PHY_CHANGELINK; phydev->state = PHY_CHANGELINK;
spin_unlock(&phydev->lock); spin_unlock_bh(&phydev->lock);
enable_irq(phydev->irq); enable_irq(phydev->irq);
...@@ -718,7 +718,7 @@ static void phy_change(struct work_struct *work) ...@@ -718,7 +718,7 @@ static void phy_change(struct work_struct *work)
*/ */
void phy_stop(struct phy_device *phydev) void phy_stop(struct phy_device *phydev)
{ {
spin_lock(&phydev->lock); spin_lock_bh(&phydev->lock);
if (PHY_HALTED == phydev->state) if (PHY_HALTED == phydev->state)
goto out_unlock; goto out_unlock;
...@@ -734,7 +734,7 @@ void phy_stop(struct phy_device *phydev) ...@@ -734,7 +734,7 @@ void phy_stop(struct phy_device *phydev)
} }
out_unlock: out_unlock:
spin_unlock(&phydev->lock); spin_unlock_bh(&phydev->lock);
/* /*
* Cannot call flush_scheduled_work() here as desired because * Cannot call flush_scheduled_work() here as desired because
...@@ -782,7 +782,7 @@ static void phy_timer(unsigned long data) ...@@ -782,7 +782,7 @@ static void phy_timer(unsigned long data)
int needs_aneg = 0; int needs_aneg = 0;
int err = 0; int err = 0;
spin_lock(&phydev->lock); spin_lock_bh(&phydev->lock);
if (phydev->adjust_state) if (phydev->adjust_state)
phydev->adjust_state(phydev->attached_dev); phydev->adjust_state(phydev->attached_dev);
...@@ -948,7 +948,7 @@ static void phy_timer(unsigned long data) ...@@ -948,7 +948,7 @@ static void phy_timer(unsigned long data)
break; break;
} }
spin_unlock(&phydev->lock); spin_unlock_bh(&phydev->lock);
if (needs_aneg) if (needs_aneg)
err = phy_start_aneg(phydev); err = phy_start_aneg(phydev);
......
...@@ -670,9 +670,9 @@ static int phy_remove(struct device *dev) ...@@ -670,9 +670,9 @@ static int phy_remove(struct device *dev)
phydev = to_phy_device(dev); phydev = to_phy_device(dev);
spin_lock(&phydev->lock); spin_lock_bh(&phydev->lock);
phydev->state = PHY_DOWN; phydev->state = PHY_DOWN;
spin_unlock(&phydev->lock); spin_unlock_bh(&phydev->lock);
if (phydev->drv->remove) if (phydev->drv->remove)
phydev->drv->remove(phydev); phydev->drv->remove(phydev);
......
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