Skip to content

Commit d3f372e

Browse files
xiaoleiwang123456gregkh
authored andcommitted
usb: cdns3: Put the cdns set active part outside the spin lock
[ Upstream commit 2319b9c ] 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: Xiaolei Wang <[email protected]> Acked-by: Peter Chen <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]> Signed-off-by: Sasha Levin <[email protected]>
1 parent dfd46f7 commit d3f372e

File tree

4 files changed

+20
-8
lines changed

4 files changed

+20
-8
lines changed

drivers/usb/cdns3/cdns3-plat.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -255,9 +255,10 @@ static int cdns3_controller_resume(struct device *dev, pm_message_t msg)
255255
cdns3_set_platform_suspend(cdns->dev, false, false);
256256

257257
spin_lock_irqsave(&cdns->lock, flags);
258-
cdns_resume(cdns, !PMSG_IS_AUTO(msg));
258+
cdns_resume(cdns);
259259
cdns->in_lpm = false;
260260
spin_unlock_irqrestore(&cdns->lock, flags);
261+
cdns_set_active(cdns, !PMSG_IS_AUTO(msg));
261262
if (cdns->wakeup_pending) {
262263
cdns->wakeup_pending = false;
263264
enable_irq(cdns->wakeup_irq);

drivers/usb/cdns3/cdnsp-pci.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,8 +208,9 @@ static int __maybe_unused cdnsp_pci_resume(struct device *dev)
208208
int ret;
209209

210210
spin_lock_irqsave(&cdns->lock, flags);
211-
ret = cdns_resume(cdns, 1);
211+
ret = cdns_resume(cdns);
212212
spin_unlock_irqrestore(&cdns->lock, flags);
213+
cdns_set_active(cdns, 1);
213214

214215
return ret;
215216
}

drivers/usb/cdns3/core.c

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -522,9 +522,8 @@ int cdns_suspend(struct cdns *cdns)
522522
}
523523
EXPORT_SYMBOL_GPL(cdns_suspend);
524524

525-
int cdns_resume(struct cdns *cdns, u8 set_active)
525+
int cdns_resume(struct cdns *cdns)
526526
{
527-
struct device *dev = cdns->dev;
528527
enum usb_role real_role;
529528
bool role_changed = false;
530529
int ret = 0;
@@ -556,15 +555,23 @@ int cdns_resume(struct cdns *cdns, u8 set_active)
556555
if (cdns->roles[cdns->role]->resume)
557556
cdns->roles[cdns->role]->resume(cdns, cdns_power_is_lost(cdns));
558557

558+
return 0;
559+
}
560+
EXPORT_SYMBOL_GPL(cdns_resume);
561+
562+
void cdns_set_active(struct cdns *cdns, u8 set_active)
563+
{
564+
struct device *dev = cdns->dev;
565+
559566
if (set_active) {
560567
pm_runtime_disable(dev);
561568
pm_runtime_set_active(dev);
562569
pm_runtime_enable(dev);
563570
}
564571

565-
return 0;
572+
return;
566573
}
567-
EXPORT_SYMBOL_GPL(cdns_resume);
574+
EXPORT_SYMBOL_GPL(cdns_set_active);
568575
#endif /* CONFIG_PM_SLEEP */
569576

570577
MODULE_AUTHOR("Peter Chen <[email protected]>");

drivers/usb/cdns3/core.h

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -125,10 +125,13 @@ int cdns_init(struct cdns *cdns);
125125
int cdns_remove(struct cdns *cdns);
126126

127127
#ifdef CONFIG_PM_SLEEP
128-
int cdns_resume(struct cdns *cdns, u8 set_active);
128+
int cdns_resume(struct cdns *cdns);
129129
int cdns_suspend(struct cdns *cdns);
130+
void cdns_set_active(struct cdns *cdns, u8 set_active);
130131
#else /* CONFIG_PM_SLEEP */
131-
static inline int cdns_resume(struct cdns *cdns, u8 set_active)
132+
static inline int cdns_resume(struct cdns *cdns)
133+
{ return 0; }
134+
static inline int cdns_set_active(struct cdns *cdns, u8 set_active)
132135
{ return 0; }
133136
static inline int cdns_suspend(struct cdns *cdns)
134137
{ return 0; }

0 commit comments

Comments
 (0)