Skip to content

Commit a9342bd

Browse files
Udipto Goswamigregkh
Udipto Goswami
authored andcommitted
usb: dwc3: debugfs: Resume dwc3 before accessing registers
commit 614ce6a upstream. When the dwc3 device is runtime suspended, various required clocks are in disabled state and it is not guaranteed that access to any registers would work. Depending on the SoC glue, a register read could be as benign as returning 0 or be fatal enough to hang the system. In order to prevent such scenarios of fatal errors, make sure to resume dwc3 then allow the function to proceed. Fixes: 72246da ("usb: Introduce DesignWare USB3 DRD Driver") Cc: [email protected] #3.2: 30332ee: debugfs: regset32: Add Runtime PM support Signed-off-by: Udipto Goswami <[email protected]> Reviewed-by: Johan Hovold <[email protected]> Tested-by: Johan Hovold <[email protected]> Acked-by: Thinh Nguyen <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent ad43004 commit a9342bd

File tree

1 file changed

+109
-0
lines changed

1 file changed

+109
-0
lines changed

drivers/usb/dwc3/debugfs.c

+109
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,11 @@ static int dwc3_lsp_show(struct seq_file *s, void *unused)
327327
unsigned int current_mode;
328328
unsigned long flags;
329329
u32 reg;
330+
int ret;
331+
332+
ret = pm_runtime_resume_and_get(dwc->dev);
333+
if (ret < 0)
334+
return ret;
330335

331336
spin_lock_irqsave(&dwc->lock, flags);
332337
reg = dwc3_readl(dwc->regs, DWC3_GSTS);
@@ -345,6 +350,8 @@ static int dwc3_lsp_show(struct seq_file *s, void *unused)
345350
}
346351
spin_unlock_irqrestore(&dwc->lock, flags);
347352

353+
pm_runtime_put_sync(dwc->dev);
354+
348355
return 0;
349356
}
350357

@@ -390,6 +397,11 @@ static int dwc3_mode_show(struct seq_file *s, void *unused)
390397
struct dwc3 *dwc = s->private;
391398
unsigned long flags;
392399
u32 reg;
400+
int ret;
401+
402+
ret = pm_runtime_resume_and_get(dwc->dev);
403+
if (ret < 0)
404+
return ret;
393405

394406
spin_lock_irqsave(&dwc->lock, flags);
395407
reg = dwc3_readl(dwc->regs, DWC3_GCTL);
@@ -409,6 +421,8 @@ static int dwc3_mode_show(struct seq_file *s, void *unused)
409421
seq_printf(s, "UNKNOWN %08x\n", DWC3_GCTL_PRTCAP(reg));
410422
}
411423

424+
pm_runtime_put_sync(dwc->dev);
425+
412426
return 0;
413427
}
414428

@@ -458,6 +472,11 @@ static int dwc3_testmode_show(struct seq_file *s, void *unused)
458472
struct dwc3 *dwc = s->private;
459473
unsigned long flags;
460474
u32 reg;
475+
int ret;
476+
477+
ret = pm_runtime_resume_and_get(dwc->dev);
478+
if (ret < 0)
479+
return ret;
461480

462481
spin_lock_irqsave(&dwc->lock, flags);
463482
reg = dwc3_readl(dwc->regs, DWC3_DCTL);
@@ -488,6 +507,8 @@ static int dwc3_testmode_show(struct seq_file *s, void *unused)
488507
seq_printf(s, "UNKNOWN %d\n", reg);
489508
}
490509

510+
pm_runtime_put_sync(dwc->dev);
511+
491512
return 0;
492513
}
493514

@@ -504,6 +525,7 @@ static ssize_t dwc3_testmode_write(struct file *file,
504525
unsigned long flags;
505526
u32 testmode = 0;
506527
char buf[32];
528+
int ret;
507529

508530
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
509531
return -EFAULT;
@@ -521,10 +543,16 @@ static ssize_t dwc3_testmode_write(struct file *file,
521543
else
522544
testmode = 0;
523545

546+
ret = pm_runtime_resume_and_get(dwc->dev);
547+
if (ret < 0)
548+
return ret;
549+
524550
spin_lock_irqsave(&dwc->lock, flags);
525551
dwc3_gadget_set_test_mode(dwc, testmode);
526552
spin_unlock_irqrestore(&dwc->lock, flags);
527553

554+
pm_runtime_put_sync(dwc->dev);
555+
528556
return count;
529557
}
530558

@@ -543,12 +571,18 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused)
543571
enum dwc3_link_state state;
544572
u32 reg;
545573
u8 speed;
574+
int ret;
575+
576+
ret = pm_runtime_resume_and_get(dwc->dev);
577+
if (ret < 0)
578+
return ret;
546579

547580
spin_lock_irqsave(&dwc->lock, flags);
548581
reg = dwc3_readl(dwc->regs, DWC3_GSTS);
549582
if (DWC3_GSTS_CURMOD(reg) != DWC3_GSTS_CURMOD_DEVICE) {
550583
seq_puts(s, "Not available\n");
551584
spin_unlock_irqrestore(&dwc->lock, flags);
585+
pm_runtime_put_sync(dwc->dev);
552586
return 0;
553587
}
554588

@@ -561,6 +595,8 @@ static int dwc3_link_state_show(struct seq_file *s, void *unused)
561595
dwc3_gadget_hs_link_string(state));
562596
spin_unlock_irqrestore(&dwc->lock, flags);
563597

598+
pm_runtime_put_sync(dwc->dev);
599+
564600
return 0;
565601
}
566602

@@ -579,6 +615,7 @@ static ssize_t dwc3_link_state_write(struct file *file,
579615
char buf[32];
580616
u32 reg;
581617
u8 speed;
618+
int ret;
582619

583620
if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count)))
584621
return -EFAULT;
@@ -598,10 +635,15 @@ static ssize_t dwc3_link_state_write(struct file *file,
598635
else
599636
return -EINVAL;
600637

638+
ret = pm_runtime_resume_and_get(dwc->dev);
639+
if (ret < 0)
640+
return ret;
641+
601642
spin_lock_irqsave(&dwc->lock, flags);
602643
reg = dwc3_readl(dwc->regs, DWC3_GSTS);
603644
if (DWC3_GSTS_CURMOD(reg) != DWC3_GSTS_CURMOD_DEVICE) {
604645
spin_unlock_irqrestore(&dwc->lock, flags);
646+
pm_runtime_put_sync(dwc->dev);
605647
return -EINVAL;
606648
}
607649

@@ -611,12 +653,15 @@ static ssize_t dwc3_link_state_write(struct file *file,
611653
if (speed < DWC3_DSTS_SUPERSPEED &&
612654
state != DWC3_LINK_STATE_RECOV) {
613655
spin_unlock_irqrestore(&dwc->lock, flags);
656+
pm_runtime_put_sync(dwc->dev);
614657
return -EINVAL;
615658
}
616659

617660
dwc3_gadget_set_link_state(dwc, state);
618661
spin_unlock_irqrestore(&dwc->lock, flags);
619662

663+
pm_runtime_put_sync(dwc->dev);
664+
620665
return count;
621666
}
622667

@@ -640,6 +685,11 @@ static int dwc3_tx_fifo_size_show(struct seq_file *s, void *unused)
640685
unsigned long flags;
641686
u32 mdwidth;
642687
u32 val;
688+
int ret;
689+
690+
ret = pm_runtime_resume_and_get(dwc->dev);
691+
if (ret < 0)
692+
return ret;
643693

644694
spin_lock_irqsave(&dwc->lock, flags);
645695
val = dwc3_core_fifo_space(dep, DWC3_TXFIFO);
@@ -652,6 +702,8 @@ static int dwc3_tx_fifo_size_show(struct seq_file *s, void *unused)
652702
seq_printf(s, "%u\n", val);
653703
spin_unlock_irqrestore(&dwc->lock, flags);
654704

705+
pm_runtime_put_sync(dwc->dev);
706+
655707
return 0;
656708
}
657709

@@ -662,6 +714,11 @@ static int dwc3_rx_fifo_size_show(struct seq_file *s, void *unused)
662714
unsigned long flags;
663715
u32 mdwidth;
664716
u32 val;
717+
int ret;
718+
719+
ret = pm_runtime_resume_and_get(dwc->dev);
720+
if (ret < 0)
721+
return ret;
665722

666723
spin_lock_irqsave(&dwc->lock, flags);
667724
val = dwc3_core_fifo_space(dep, DWC3_RXFIFO);
@@ -674,6 +731,8 @@ static int dwc3_rx_fifo_size_show(struct seq_file *s, void *unused)
674731
seq_printf(s, "%u\n", val);
675732
spin_unlock_irqrestore(&dwc->lock, flags);
676733

734+
pm_runtime_put_sync(dwc->dev);
735+
677736
return 0;
678737
}
679738

@@ -683,12 +742,19 @@ static int dwc3_tx_request_queue_show(struct seq_file *s, void *unused)
683742
struct dwc3 *dwc = dep->dwc;
684743
unsigned long flags;
685744
u32 val;
745+
int ret;
746+
747+
ret = pm_runtime_resume_and_get(dwc->dev);
748+
if (ret < 0)
749+
return ret;
686750

687751
spin_lock_irqsave(&dwc->lock, flags);
688752
val = dwc3_core_fifo_space(dep, DWC3_TXREQQ);
689753
seq_printf(s, "%u\n", val);
690754
spin_unlock_irqrestore(&dwc->lock, flags);
691755

756+
pm_runtime_put_sync(dwc->dev);
757+
692758
return 0;
693759
}
694760

@@ -698,12 +764,19 @@ static int dwc3_rx_request_queue_show(struct seq_file *s, void *unused)
698764
struct dwc3 *dwc = dep->dwc;
699765
unsigned long flags;
700766
u32 val;
767+
int ret;
768+
769+
ret = pm_runtime_resume_and_get(dwc->dev);
770+
if (ret < 0)
771+
return ret;
701772

702773
spin_lock_irqsave(&dwc->lock, flags);
703774
val = dwc3_core_fifo_space(dep, DWC3_RXREQQ);
704775
seq_printf(s, "%u\n", val);
705776
spin_unlock_irqrestore(&dwc->lock, flags);
706777

778+
pm_runtime_put_sync(dwc->dev);
779+
707780
return 0;
708781
}
709782

@@ -713,12 +786,19 @@ static int dwc3_rx_info_queue_show(struct seq_file *s, void *unused)
713786
struct dwc3 *dwc = dep->dwc;
714787
unsigned long flags;
715788
u32 val;
789+
int ret;
790+
791+
ret = pm_runtime_resume_and_get(dwc->dev);
792+
if (ret < 0)
793+
return ret;
716794

717795
spin_lock_irqsave(&dwc->lock, flags);
718796
val = dwc3_core_fifo_space(dep, DWC3_RXINFOQ);
719797
seq_printf(s, "%u\n", val);
720798
spin_unlock_irqrestore(&dwc->lock, flags);
721799

800+
pm_runtime_put_sync(dwc->dev);
801+
722802
return 0;
723803
}
724804

@@ -728,12 +808,19 @@ static int dwc3_descriptor_fetch_queue_show(struct seq_file *s, void *unused)
728808
struct dwc3 *dwc = dep->dwc;
729809
unsigned long flags;
730810
u32 val;
811+
int ret;
812+
813+
ret = pm_runtime_resume_and_get(dwc->dev);
814+
if (ret < 0)
815+
return ret;
731816

732817
spin_lock_irqsave(&dwc->lock, flags);
733818
val = dwc3_core_fifo_space(dep, DWC3_DESCFETCHQ);
734819
seq_printf(s, "%u\n", val);
735820
spin_unlock_irqrestore(&dwc->lock, flags);
736821

822+
pm_runtime_put_sync(dwc->dev);
823+
737824
return 0;
738825
}
739826

@@ -743,12 +830,19 @@ static int dwc3_event_queue_show(struct seq_file *s, void *unused)
743830
struct dwc3 *dwc = dep->dwc;
744831
unsigned long flags;
745832
u32 val;
833+
int ret;
834+
835+
ret = pm_runtime_resume_and_get(dwc->dev);
836+
if (ret < 0)
837+
return ret;
746838

747839
spin_lock_irqsave(&dwc->lock, flags);
748840
val = dwc3_core_fifo_space(dep, DWC3_EVENTQ);
749841
seq_printf(s, "%u\n", val);
750842
spin_unlock_irqrestore(&dwc->lock, flags);
751843

844+
pm_runtime_put_sync(dwc->dev);
845+
752846
return 0;
753847
}
754848

@@ -793,6 +887,11 @@ static int dwc3_trb_ring_show(struct seq_file *s, void *unused)
793887
struct dwc3 *dwc = dep->dwc;
794888
unsigned long flags;
795889
int i;
890+
int ret;
891+
892+
ret = pm_runtime_resume_and_get(dwc->dev);
893+
if (ret < 0)
894+
return ret;
796895

797896
spin_lock_irqsave(&dwc->lock, flags);
798897
if (dep->number <= 1) {
@@ -822,6 +921,8 @@ static int dwc3_trb_ring_show(struct seq_file *s, void *unused)
822921
out:
823922
spin_unlock_irqrestore(&dwc->lock, flags);
824923

924+
pm_runtime_put_sync(dwc->dev);
925+
825926
return 0;
826927
}
827928

@@ -834,6 +935,11 @@ static int dwc3_ep_info_register_show(struct seq_file *s, void *unused)
834935
u32 lower_32_bits;
835936
u32 upper_32_bits;
836937
u32 reg;
938+
int ret;
939+
940+
ret = pm_runtime_resume_and_get(dwc->dev);
941+
if (ret < 0)
942+
return ret;
837943

838944
spin_lock_irqsave(&dwc->lock, flags);
839945
reg = DWC3_GDBGLSPMUX_EPSELECT(dep->number);
@@ -846,6 +952,8 @@ static int dwc3_ep_info_register_show(struct seq_file *s, void *unused)
846952
seq_printf(s, "0x%016llx\n", ep_info);
847953
spin_unlock_irqrestore(&dwc->lock, flags);
848954

955+
pm_runtime_put_sync(dwc->dev);
956+
849957
return 0;
850958
}
851959

@@ -905,6 +1013,7 @@ void dwc3_debugfs_init(struct dwc3 *dwc)
9051013
dwc->regset->regs = dwc3_regs;
9061014
dwc->regset->nregs = ARRAY_SIZE(dwc3_regs);
9071015
dwc->regset->base = dwc->regs - DWC3_GLOBALS_REGS_START;
1016+
dwc->regset->dev = dwc->dev;
9081017

9091018
root = debugfs_create_dir(dev_name(dwc->dev), usb_debug_root);
9101019
dwc->debug_root = root;

0 commit comments

Comments
 (0)