linux/drivers/net/phy
Anton Vorontsov 541cd3ee00 phylib: Fix deadlock on resume
Sometimes kernel hangs on resume with the following trace:

 ucc_geth e0102000.ucc: resume
 INFO: task bash:1764 blocked for more than 120 seconds.
 "echo 0 > /proc/sys/kernel/hung_task_timeout_secs" disables this message.
 bash          D 0fecf43c     0  1764   1763 0x00000000
 Call Trace:
 [cf9a7c10] [c0012868] ret_from_except+0x0/0x14 (unreliable)
 --- Exception: cf9a7ce0 at __switch_to+0x4c/0x6c
     LR = 0xcf9a7cc0
 [cf9a7cd0] [c0008c14] __switch_to+0x4c/0x6c (unreliable)
 [cf9a7ce0] [c028bcfc] schedule+0x158/0x260
 [cf9a7d10] [c028c720] __mutex_lock_slowpath+0x80/0xd8
 [cf9a7d40] [c01cf388] phy_stop+0x20/0x70
 [cf9a7d50] [c01d514c] ugeth_resume+0x6c/0x13c
 [...]

Here is why.

On suspend:

- PM core starts suspending devices, ucc_geth_suspend gets called;

- ucc_geth calls phy_stop() on suspend. Note that phy_stop() is
  mostly asynchronous so it doesn't block ucc_geth's suspend routine,
  it just sets PHY_HALTED state and disables PHY's interrupts;

- Suddenly the state machine gets scheduled, it grabs the phydev->lock
  mutex and tries to process the PHY_HALTED state, so it calls
  phydev->adjust_link(phydev->attached_dev). In ucc_geth case
  adjust_link() calls msleep(), which reschedules the code flow back to
  PM core, which now finishes suspend and so we end up sleeping with
  phydev->lock mutex held.

On resume:

- PM core starts resuming devices (notice that nobody rescheduled
  the state machine yet, so the mutex is still held), the core calls
  ucc_geth's resume routine;

- ucc_geth_resume restarts the PHY with phy_stop()/phy_start()
  sequence, and the phy_*() calls are trying to grab the phydev->lock
  mutex. Here comes the deadlock.

This patch fixes the issue by stopping the state machine on suspend
and starting it again on resume.

Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
2009-12-30 22:03:41 -08:00
..
bcm63xx.c MIPS: BCM63XX: Add integrated ethernet PHY support for phylib. 2009-07-07 19:23:51 -07:00
broadcom.c broadcom: bcm54xx_shadow_read() errors ignored in bcm54xx_adjust_rxrefclk() 2009-12-18 20:16:10 -08:00
cicada.c
davicom.c
et1011c.c
fixed.c phy: error handling for platform_device_register_simple() 2009-04-11 01:52:29 -07:00
icplus.c
Kconfig MIPS: BCM63XX: Add integrated ethernet PHY support for phylib. 2009-07-07 19:23:51 -07:00
lxt.c
Makefile MIPS: BCM63XX: Add integrated ethernet PHY support for phylib. 2009-07-07 19:23:51 -07:00
marvell.c phy/marvell: Make non-aneg speed/duplex forcing work for 88E1111 PHYs 2009-09-11 12:54:38 -07:00
mdio_bus.c phylib: Fix deadlock on resume 2009-12-30 22:03:41 -08:00
mdio-bitbang.c
mdio-gpio.c net: fix mdio section mismatch warning 2009-11-17 04:04:40 -08:00
national.c
phy_device.c NET: phy_device, fix lock imbalance 2009-07-14 12:03:39 -07:00
phy.c drivers/net: Move && and || to end of previous line 2009-12-03 13:18:01 -08:00
qsemi.c
realtek.c
smsc.c phy: add new LAN8710 and LAN8720 device ids to smsc phy driver 2009-03-23 15:17:31 -07:00
ste10Xp.c
vitesse.c