diff options
author | Maciej W. Rozycki <macro@linux-mips.org> | 2007-09-29 01:42:12 -0400 |
---|---|---|
committer | David S. Miller <davem@sunset.davemloft.net> | 2007-10-10 19:53:54 -0400 |
commit | 9ff8c68b3c722f732c7a13d6631b149cca8c7091 (patch) | |
tree | ec0dd0762f9652d30fff30228406bcd0417f6063 /drivers/net/phy/phy.c | |
parent | 1f8f4559f8c5829348a010a9e0bbb423310060d1 (diff) |
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: Maciej W. Rozycki <macro@linux-mips.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Jeff Garzik <jeff@garzik.org>
Diffstat (limited to 'drivers/net/phy/phy.c')
-rw-r--r-- | drivers/net/phy/phy.c | 24 |
1 files changed, 12 insertions, 12 deletions
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c index 17c1e1555d80..4da993dfcfd8 100644 --- a/drivers/net/phy/phy.c +++ b/drivers/net/phy/phy.c | |||
@@ -424,7 +424,7 @@ int phy_start_aneg(struct phy_device *phydev) | |||
424 | { | 424 | { |
425 | int err; | 425 | int err; |
426 | 426 | ||
427 | spin_lock(&phydev->lock); | 427 | spin_lock_bh(&phydev->lock); |
428 | 428 | ||
429 | if (AUTONEG_DISABLE == phydev->autoneg) | 429 | if (AUTONEG_DISABLE == phydev->autoneg) |
430 | phy_sanitize_settings(phydev); | 430 | phy_sanitize_settings(phydev); |
@@ -445,7 +445,7 @@ int phy_start_aneg(struct phy_device *phydev) | |||
445 | } | 445 | } |
446 | 446 | ||
447 | out_unlock: | 447 | out_unlock: |
448 | spin_unlock(&phydev->lock); | 448 | spin_unlock_bh(&phydev->lock); |
449 | return err; | 449 | return err; |
450 | } | 450 | } |
451 | EXPORT_SYMBOL(phy_start_aneg); | 451 | EXPORT_SYMBOL(phy_start_aneg); |
@@ -490,10 +490,10 @@ void phy_stop_machine(struct phy_device *phydev) | |||
490 | { | 490 | { |
491 | del_timer_sync(&phydev->phy_timer); | 491 | del_timer_sync(&phydev->phy_timer); |
492 | 492 | ||
493 | spin_lock(&phydev->lock); | 493 | spin_lock_bh(&phydev->lock); |
494 | if (phydev->state > PHY_UP) | 494 | if (phydev->state > PHY_UP) |
495 | phydev->state = PHY_UP; | 495 | phydev->state = PHY_UP; |
496 | spin_unlock(&phydev->lock); | 496 | spin_unlock_bh(&phydev->lock); |
497 | 497 | ||
498 | phydev->adjust_state = NULL; | 498 | phydev->adjust_state = NULL; |
499 | } | 499 | } |
@@ -537,9 +537,9 @@ static void phy_force_reduction(struct phy_device *phydev) | |||
537 | */ | 537 | */ |
538 | void phy_error(struct phy_device *phydev) | 538 | void phy_error(struct phy_device *phydev) |
539 | { | 539 | { |
540 | spin_lock(&phydev->lock); | 540 | spin_lock_bh(&phydev->lock); |
541 | phydev->state = PHY_HALTED; | 541 | phydev->state = PHY_HALTED; |
542 | spin_unlock(&phydev->lock); | 542 | spin_unlock_bh(&phydev->lock); |
543 | } | 543 | } |
544 | 544 | ||
545 | /** | 545 | /** |
@@ -690,10 +690,10 @@ static void phy_change(struct work_struct *work) | |||
690 | if (err) | 690 | if (err) |
691 | goto phy_err; | 691 | goto phy_err; |
692 | 692 | ||
693 | spin_lock(&phydev->lock); | 693 | spin_lock_bh(&phydev->lock); |
694 | if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state)) | 694 | if ((PHY_RUNNING == phydev->state) || (PHY_NOLINK == phydev->state)) |
695 | phydev->state = PHY_CHANGELINK; | 695 | phydev->state = PHY_CHANGELINK; |
696 | spin_unlock(&phydev->lock); | 696 | spin_unlock_bh(&phydev->lock); |
697 | 697 | ||
698 | enable_irq(phydev->irq); | 698 | enable_irq(phydev->irq); |
699 | 699 | ||
@@ -718,7 +718,7 @@ phy_err: | |||
718 | */ | 718 | */ |
719 | void phy_stop(struct phy_device *phydev) | 719 | void phy_stop(struct phy_device *phydev) |
720 | { | 720 | { |
721 | spin_lock(&phydev->lock); | 721 | spin_lock_bh(&phydev->lock); |
722 | 722 | ||
723 | if (PHY_HALTED == phydev->state) | 723 | if (PHY_HALTED == phydev->state) |
724 | goto out_unlock; | 724 | goto out_unlock; |
@@ -734,7 +734,7 @@ void phy_stop(struct phy_device *phydev) | |||
734 | } | 734 | } |
735 | 735 | ||
736 | out_unlock: | 736 | out_unlock: |
737 | spin_unlock(&phydev->lock); | 737 | spin_unlock_bh(&phydev->lock); |
738 | 738 | ||
739 | /* | 739 | /* |
740 | * Cannot call flush_scheduled_work() here as desired because | 740 | * Cannot call flush_scheduled_work() here as desired because |
@@ -782,7 +782,7 @@ static void phy_timer(unsigned long data) | |||
782 | int needs_aneg = 0; | 782 | int needs_aneg = 0; |
783 | int err = 0; | 783 | int err = 0; |
784 | 784 | ||
785 | spin_lock(&phydev->lock); | 785 | spin_lock_bh(&phydev->lock); |
786 | 786 | ||
787 | if (phydev->adjust_state) | 787 | if (phydev->adjust_state) |
788 | phydev->adjust_state(phydev->attached_dev); | 788 | phydev->adjust_state(phydev->attached_dev); |
@@ -948,7 +948,7 @@ static void phy_timer(unsigned long data) | |||
948 | break; | 948 | break; |
949 | } | 949 | } |
950 | 950 | ||
951 | spin_unlock(&phydev->lock); | 951 | spin_unlock_bh(&phydev->lock); |
952 | 952 | ||
953 | if (needs_aneg) | 953 | if (needs_aneg) |
954 | err = phy_start_aneg(phydev); | 954 | err = phy_start_aneg(phydev); |