Commit 2319b9c8 authored by Xiaolei Wang's avatar Xiaolei Wang Committed by Greg Kroah-Hartman

usb: cdns3: Put the cdns set active part outside the spin lock

The device may be scheduled during the resume process,
so this cannot appear in atomic operations. Since
pm_runtime_set_active will resume suppliers, put set
active outside the spin lock, which is only used to
protect the struct cdns data structure, otherwise the
kernel will report the following warning:

  BUG: sleeping function called from invalid context at drivers/base/power/runtime.c:1163
  in_atomic(): 1, irqs_disabled(): 0, non_block: 0, pid: 651, name: sh
  preempt_count: 1, expected: 0
  RCU nest depth: 0, expected: 0
  CPU: 0 PID: 651 Comm: sh Tainted: G        WC         6.1.20 #1
  Hardware name: Freescale i.MX8QM MEK (DT)
  Call trace:
    dump_backtrace.part.0+0xe0/0xf0
    show_stack+0x18/0x30
    dump_stack_lvl+0x64/0x80
    dump_stack+0x1c/0x38
    __might_resched+0x1fc/0x240
    __might_sleep+0x68/0xc0
    __pm_runtime_resume+0x9c/0xe0
    rpm_get_suppliers+0x68/0x1b0
    __pm_runtime_set_status+0x298/0x560
    cdns_resume+0xb0/0x1c0
    cdns3_controller_resume.isra.0+0x1e0/0x250
    cdns3_plat_resume+0x28/0x40
Signed-off-by: default avatarXiaolei Wang <xiaolei.wang@windriver.com>
Acked-by: default avatarPeter Chen <peter.chen@kernel.org>
Link: https://lore.kernel.org/r/20230616021952.1025854-1-xiaolei.wang@windriver.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6eaae198
...@@ -255,9 +255,10 @@ static int cdns3_controller_resume(struct device *dev, pm_message_t msg) ...@@ -255,9 +255,10 @@ static int cdns3_controller_resume(struct device *dev, pm_message_t msg)
cdns3_set_platform_suspend(cdns->dev, false, false); cdns3_set_platform_suspend(cdns->dev, false, false);
spin_lock_irqsave(&cdns->lock, flags); spin_lock_irqsave(&cdns->lock, flags);
cdns_resume(cdns, !PMSG_IS_AUTO(msg)); cdns_resume(cdns);
cdns->in_lpm = false; cdns->in_lpm = false;
spin_unlock_irqrestore(&cdns->lock, flags); spin_unlock_irqrestore(&cdns->lock, flags);
cdns_set_active(cdns, !PMSG_IS_AUTO(msg));
if (cdns->wakeup_pending) { if (cdns->wakeup_pending) {
cdns->wakeup_pending = false; cdns->wakeup_pending = false;
enable_irq(cdns->wakeup_irq); enable_irq(cdns->wakeup_irq);
......
...@@ -208,8 +208,9 @@ static int __maybe_unused cdnsp_pci_resume(struct device *dev) ...@@ -208,8 +208,9 @@ static int __maybe_unused cdnsp_pci_resume(struct device *dev)
int ret; int ret;
spin_lock_irqsave(&cdns->lock, flags); spin_lock_irqsave(&cdns->lock, flags);
ret = cdns_resume(cdns, 1); ret = cdns_resume(cdns);
spin_unlock_irqrestore(&cdns->lock, flags); spin_unlock_irqrestore(&cdns->lock, flags);
cdns_set_active(cdns, 1);
return ret; return ret;
} }
......
...@@ -522,9 +522,8 @@ int cdns_suspend(struct cdns *cdns) ...@@ -522,9 +522,8 @@ int cdns_suspend(struct cdns *cdns)
} }
EXPORT_SYMBOL_GPL(cdns_suspend); EXPORT_SYMBOL_GPL(cdns_suspend);
int cdns_resume(struct cdns *cdns, u8 set_active) int cdns_resume(struct cdns *cdns)
{ {
struct device *dev = cdns->dev;
enum usb_role real_role; enum usb_role real_role;
bool role_changed = false; bool role_changed = false;
int ret = 0; int ret = 0;
...@@ -556,15 +555,23 @@ int cdns_resume(struct cdns *cdns, u8 set_active) ...@@ -556,15 +555,23 @@ int cdns_resume(struct cdns *cdns, u8 set_active)
if (cdns->roles[cdns->role]->resume) if (cdns->roles[cdns->role]->resume)
cdns->roles[cdns->role]->resume(cdns, cdns_power_is_lost(cdns)); cdns->roles[cdns->role]->resume(cdns, cdns_power_is_lost(cdns));
return 0;
}
EXPORT_SYMBOL_GPL(cdns_resume);
void cdns_set_active(struct cdns *cdns, u8 set_active)
{
struct device *dev = cdns->dev;
if (set_active) { if (set_active) {
pm_runtime_disable(dev); pm_runtime_disable(dev);
pm_runtime_set_active(dev); pm_runtime_set_active(dev);
pm_runtime_enable(dev); pm_runtime_enable(dev);
} }
return 0; return;
} }
EXPORT_SYMBOL_GPL(cdns_resume); EXPORT_SYMBOL_GPL(cdns_set_active);
#endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM_SLEEP */
MODULE_AUTHOR("Peter Chen <peter.chen@nxp.com>"); MODULE_AUTHOR("Peter Chen <peter.chen@nxp.com>");
......
...@@ -125,10 +125,13 @@ int cdns_init(struct cdns *cdns); ...@@ -125,10 +125,13 @@ int cdns_init(struct cdns *cdns);
int cdns_remove(struct cdns *cdns); int cdns_remove(struct cdns *cdns);
#ifdef CONFIG_PM_SLEEP #ifdef CONFIG_PM_SLEEP
int cdns_resume(struct cdns *cdns, u8 set_active); int cdns_resume(struct cdns *cdns);
int cdns_suspend(struct cdns *cdns); int cdns_suspend(struct cdns *cdns);
void cdns_set_active(struct cdns *cdns, u8 set_active);
#else /* CONFIG_PM_SLEEP */ #else /* CONFIG_PM_SLEEP */
static inline int cdns_resume(struct cdns *cdns, u8 set_active) static inline int cdns_resume(struct cdns *cdns)
{ return 0; }
static inline int cdns_set_active(struct cdns *cdns, u8 set_active)
{ return 0; } { return 0; }
static inline int cdns_suspend(struct cdns *cdns) static inline int cdns_suspend(struct cdns *cdns)
{ return 0; } { return 0; }
......
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