小言_互联网的博客

【Linux】在Xilinx平台上实现UVC Gadget(2)- 解决dwc3驱动bug

519人阅读  评论(0)

一、bug描述

前文详情见
【Linux】在Xilinx平台上实现UVC Gadget(1)

在usb插入电脑时,开发板会瞬间报错,报错信息如下。
经过仔细研究,dwc3驱动drivers/usb/dwc3/gadget.c存在一个bug

在usb gadget 枚举过程中,会触发不需要的假中断,为了避免这个问题,
需要清除DWC3_DCTL_KEEP_CONNECT位,禁用DWC3_GCTL_GBLHIBERNATIONEN休眠中断

[  111.954284] ------------[ cut here ]------------
[  111.958916] WARNING: CPU: 0 PID: 1095 at drivers/usb/dwc3/gadget.c:3305 dwc3_stop_active_transfer.part.0+0xc4/0xd0
[  111.969247] Modules linked in: vivid v4l2_tpg cec g_webcam g_ffs zocl(O) dmaproxy(O) al5e(O) al5d(O) allegro(O) mali(O) xlnx_vcu regmap_mmio uio_pdrv_genirq [last unloaded: zocl]
[  111.985179] CPU: 0 PID: 1095 Comm: irq/92-dwc3 Tainted: G           O      5.10.0-xilinx-v2021.1 #1
[  111.994210] Hardware name: ZynqMP ZCU104 RevC (DT)
[  111.998987] pstate: 60000085 (nZCv daIf -PAN -UAO -TCO BTYPE=--)
[  112.004985] pc : dwc3_stop_active_transfer.part.0+0xc4/0xd0
[  112.010549] lr : dwc3_stop_active_transfer.part.0+0x60/0xd0
[  112.016110] sp : ffff80001239bc10
[  112.019409] x29: ffff80001239bc10 x28: 0000000000000000 
[  112.024712] x27: ffff000002249380 x26: ffff00000224e880 
[  112.030015] x25: ffff800011140568 x24: ffff000004934300 
[  112.035319] x23: ffffffffffff3f00 x22: 0000000000000001 
[  112.040622] x21: 0000000000000000 x20: ffff000004934300 
[  112.045926] x19: ffff000002249000 x18: fffffdfffff27a08 
[  112.051229] x17: 0000000000000000 x16: 000000000000000e 
[  112.056532] x15: 0000000000000000 x14: 000006160d349044 
[  112.061836] x13: 00000000bd08a39e x12: 00000000000002d2 
[  112.067139] x11: 0000000000000000 x10: 00000000000008e0 
[  112.072443] x9 : ffff80001239bd10 x8 : ffff000004934c40 
[  112.077747] x7 : 000000000000b68d x6 : 0000000000000000 
[  112.083050] x5 : 0000000000000508 x4 : 0000000000000000 
[  112.088353] x3 : ffffffffffff3f08 x2 : 0000000000000000 
[  112.093657] x1 : ffff800012f00200 x0 : 00000000ffffff92 
[  112.098961] Call trace:
[  112.101395]  dwc3_stop_active_transfer.part.0+0xc4/0xd0
[  112.106611]  dwc3_stop_active_transfer+0x2c/0x40
[  112.111219]  dwc3_gadget_enter_hibernation.part.0+0xc0/0x2e0
[  112.116860]  dwc3_gadget_enter_hibernation+0x2c/0x40
[  112.121809]  dwc3_thread_interrupt+0x2f0/0xe5c
[  112.126246]  irq_thread_fn+0x2c/0x90
[  112.129811]  irq_thread+0x248/0x370
[  112.133285]  kthread+0x124/0x130
[  112.136505]  ret_from_fork+0x10/0x3c
[  112.140069] ---[ end trace 5d566d21e39ee647 ]---
[  112.253848] dwc3-xilinx ff9d0000.usb0: Failed to set power state to D3
[  112.260367] dwc3-pmu-regulator: failed to disable: -EIO
[  112.265585] dwc3 fe200000.dwc3: dwc3_gadget_enter_hibernation: 373 Failed to enable dwc3_pmu supply
[  112.274619] dwc3 fe200000.dwc3: Fail in handling Hibernation Interrupt

 

二、具体修改方法

1. 找到内核源码位置并复制到其他目录

find . -name "gadget.c"

可以看到第1行是我们要的源代码,但是不能直接修改这个文件,因为Petalinux会自动恢复

LeoWang@u16:/opt/work/uvc-demo/xilinx-zcu104-2021.1$ find . -name "gadget.c"
./build/tmp/work-shared/zynqmp-generic/kernel-source/drivers/usb/dwc3/gadget.c
./build/tmp/work-shared/zynqmp-generic/kernel-source/drivers/usb/cdns3/gadget.c
./build/tmp/work-shared/zynqmp-generic/kernel-source/drivers/usb/dwc2/gadget.c
./build/tmp/work/zynqmp_generic-xilinx-linux/u-boot-xlnx/v2021.01-xilinx-v2021.1+gitAUTOINC+41fc08b3fe-r0/git/board/samsung/common/gadget.c
./build/tmp/work/zynqmp_generic-xilinx-linux/u-boot-xlnx/v2021.01-xilinx-v2021.1+gitAUTOINC+41fc08b3fe-r0/git/drivers/usb/dwc3/gadget.c
./build/tmp/work/zynqmp_generic-xilinx-linux/u-boot-xlnx/v2021.01-xilinx-v2021.1+gitAUTOINC+41fc08b3fe-r0/git/drivers/usb/cdns3/gadget.c

把./build/tmp/work-shared/zynqmp-generic/kernel-source复制到其他文件夹
比如我的工程目录是

/opt/work/uvc-demo/xilinx-zcu104-2021.1

内核源码目录是

/opt/work/uvc-demo/xilinx-zcu104-2021.1/build/tmp/work-shared/zynqmp-generic/kernel-source

最后把内核复制并改名到这个目录

/opt/work/uvc-demo/kernel-source_leo_wang5.10

2. Petalinux里面设置使用自定义内核源码

petalinux-config

1) 选第2个Linux Components Selection

2) 选linux-kernel,回车,选择ext-local-src

3) 设置External linux-kernel local source settings

回车输入自己内核源码的目录

3.修改gadget驱动源码

打开文件drivers/usb/dwc3/gadget.c,找到函数
static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
在if (DWC3_VER_IS_PRIOR(DWC3, 188A)) 和dwc3_reset_gadget(dwc)之间加上下面这一段

//add by LeoWang 2022.11.20
if (dwc->has_hibernation) {
   
	reg = dwc3_readl(dwc->regs, DWC3_DCTL);
	reg &= ~DWC3_DCTL_KEEP_CONNECT;
	dwc3_writel(dwc->regs, DWC3_DCTL, reg);
	reg = dwc3_readl(dwc->regs, DWC3_GCTL);
	reg &= ~DWC3_GCTL_GBLHIBERNATIONEN;
	dwc3_writel(dwc->regs, DWC3_GCTL, reg);
}

修改后的效果如下图

Ps:
确认在v2021.2还存在这个bug,在2022.1已经增加了这个修复
也就是版本<=2021.2的,必须手动修改


转载:https://blog.csdn.net/aatu/article/details/127944649
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场