usbnet: smsc95xx: Fix deadlock on runtime resume
[ Upstream commit
ec329b85655bab4711472789d5f524a867f1e7ad ]
Commit
2bdbf5a23dc6 ("smsc95xx: add phylib support") amended
smsc95xx_resume() to call phy_init_hw(). That function waits for the
device to runtime resume even though it is placed in the runtime resume
path, causing a deadlock.
The problem is that phy_init_hw() calls down to smsc95xx_mdiobus_read(),
which never uses the _nopm variant of usbnet_read_cmd().
Commit
0fe16173902d ("usbnet: smsc95xx: add reset_resume function with
reset operation") causes a similar deadlock on resume if the device was
already runtime suspended when entering system sleep:
That's because the commit introduced smsc95xx_reset_resume(), which
calls down to smsc95xx_reset(), which neglects to use _nopm accessors.
Fix by auto-detecting whether a device access is performed by the
suspend/resume task_struct and use the _nopm variant if so. This works
because the PM core guarantees that suspend/resume callbacks are run in
task context.
Stacktrace for posterity:
INFO: task kworker/2:1:49 blocked for more than 122 seconds.
Workqueue: usb_hub_wq hub_event
schedule
rpm_resume
__pm_runtime_resume
usb_autopm_get_interface
usbnet_read_cmd
__smsc95xx_read_reg
__smsc95xx_phy_wait_not_busy
__smsc95xx_mdio_read
smsc95xx_mdiobus_read
__mdiobus_read
mdiobus_read
smsc_phy_reset
phy_init_hw
smsc95xx_resume
usb_resume_interface
usb_resume_both
usb_runtime_resume
__rpm_callback
rpm_callback
rpm_resume
__pm_runtime_resume
usb_autoresume_device
hub_event
process_one_work
Fixes: 0fe16173902d ("usbnet: smsc95xx: add reset_resume function with reset operation")
Signed-off-by: Lukas Wunner <lukas@wunner.de>
Cc: stable@vger.kernel.org # v3.16+
Cc: Andre Edich <andre.edich@microchip.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Sasha Levin <sashal@kernel.org>