NetBSD-Bugs archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
Re: port-evbarm/54696: Kernel panic in bus_dma.c on Raspberry Pi 3B/3B+
The following reply was made to PR port-evbarm/54696; it has been noted by GNATS.
From: sc.dying%gmail.com@localhost
To: Tetsuya Isaki <isaki%pastel-flower.jp@localhost>, gnats-bugs%netbsd.org@localhost
Cc: port-evbarm-maintainer%netbsd.org@localhost, gnats-admin%netbsd.org@localhost,
netbsd-bugs%netbsd.org@localhost, dhop%nwlink.com@localhost
Subject: Re: port-evbarm/54696: Kernel panic in bus_dma.c on Raspberry Pi
3B/3B+
Date: Thu, 14 Nov 2019 22:29:55 +0000
On 2019/11/14 08:39, Tetsuya Isaki wrote:
> At Wed, 13 Nov 2019 21:05:01 +0000 (UTC),
> Michael van Elst wrote:
>> >[ 153.534940] panic: kernel diagnostic assertion "len > 0 && offset + len <= map->dm_mapsize" failed: file "/usr/src/sys/arch/arm/arm32/bus_dma.c", line 1058 len 0 offset 0 mapsize 8192
>>
>> A zero length transfer. In that case it would be a uaudio (or audio?) bug.
>>
>> No idea why that should be aarch64-specific.
>
> I think it's dwc2's issue.
Seconded.
>
> According to report, calling usb_syncmem() with len == 0 in
> dwc2_device_start() caused a panic.
>
> sys/external/bsd/dwc2/dwc2.c:
> 929 dwc2_device_start(struct usbd_xfer *xfer)
> 930 {
> :
> 966 if (xfertype == UE_CONTROL) {
> :
> 990 } else {
> :
> 995 len = xfer->ux_length;
> 996 }
> :
> 1027 if (!(xfertype == UE_CONTROL && len == 0)) {
> 1028 dwc2_urb->usbdma = &xfer->ux_dmabuf;
> 1029 dwc2_urb->buf = KERNADDR(dwc2_urb->usbdma, 0);
> 1030 dwc2_urb->dma = DMAADDR(dwc2_urb->usbdma, 0);
> 1031
> 1032 usb_syncmem(&xfer->ux_dmabuf, 0, len,
> 1033 dir == UE_DIR_IN ?
> 1034 BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
>
> Here len passed to usb_syncmem() is xfer->ux_length.
>
> According to reported backtrace,
> - dwc2_device_start(xfer) is called from dwc2_device_isoc_transfer(xfer).
> - dwc2_device_isoc_transfer(xfer) is called from usbd_transfer(xfer) as
> up_methods->upm_transfer.
> - usbd_transfer(xfer) seems be called from uaudio_chan_rtransfer(ch)
> and uaudio_chan_rtransfer(ch) seems be inline-expanded in
> uaudio_trigger_input().
>
> sys/dev/usb/uaudio.c:
> 2838 uaudio_chan_rtransfer(struct chan *ch)
> 2839 {
> :
> 2874 usbd_setup_isoc_xfer(cb->xfer, cb, cb->sizes, UAUDIO_NFRAMES, 0,
> 2875 uaudio_chan_rintr);
> 2876
> 2877 (void)usbd_transfer(cb->xfer);
> 2878 }
>
> usbd_setup_isoc_xfer() initializes ux_length == 0.
>
> 592 usbd_setup_isoc_xfer(struct usbd_xfer *xfer, void *priv, uint16_t
> *frlengths,
> 593 uint32_t nframes, uint16_t flags, usbd_callback callback)
> 594 {
> 595 xfer->ux_priv = priv;
> 596 xfer->ux_buffer = NULL;
> 597 xfer->ux_length = 0;
>
> And then see also similar (the same?) PR port-arm/54615,
> sc.dying%gmail.com@localhost wrote:
>> At line 1032 of sys/external/bsd/dwc2/dwc2.c usb_syncmem is called.
>>
>>> usb_syncmem(&xfer->ux_dmabuf, 0, len,
>>> dir == UE_DIR_IN ?
>>> BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE);
>>
>> len = xfer->ux_length, however, ux_length is always 0 for isoc transfers.
>
> I just read source code and I have no environment. But if my
> understanding is correct, I think that dwc2_device_start() needs
> to handle length == 0 properly.
This bug can be solved by wrapping above usb_syncmem with if (len != 0) {}
or by changing arm/arm32/bus_dma.c accept zero length sync like x86 does.
But the transfer length of isoc xfer is sum of xfer->ux_frlengths[i]
where i = 0.. xfer->ux_nframes - 1, not zero.
dwc2 should do this usb_syncmem if xfertype == UE_{INTERRUPT,BULK},
UE_CONTROL that has data phase (that is, len != 0), or if xfertype ==
UE_ISOCHRONOUS, should do usb_syncmem for each chunk of ux_frlengths.
However, the uaudio works with dwc2 even if avobe usb_syncmem is ignored.
I think dwc2 does usb_syncmem for isoc data buf somewhere else, but
I'm not sure where it is.
>
> Thanks,
> ---
> Tetsuya Isaki <isaki%pastel-flower.jp@localhost / isaki%NetBSD.org@localhost>
>
Home |
Main Index |
Thread Index |
Old Index