On Thu, Apr 14, 2022 at 10:00:35PM +0200, Mark Kettenis wrote: > > Date: Thu, 14 Apr 2022 20:16:13 +0200 > > From: Marcus Glocker <mar...@nazgul.ch> > > > > I did hit this panic when trying to stream audio through > > uaudio(4) / dwctwo(4): > > > > panic: _dmamap_sync: ran off map! > > Stopped at panic+0x160: cmp w21, #0x0 > > TID PID UID PRFLAGS PFLAGS CPU COMMAND > > *421282 69103 0 0x2 0x4000000 0K ld > > db_enter() at panic+0x15c > > panic() at _dmamap_sync+0x10c > > _dmamap_sync() at dwc2_xfercomp_isoc_split_in+0xe0 > > dwc2_xfercomp_isoc_split_in() at dwc2_hc_xfercomp_intr+0xf4 > > dwc2_hc_xfercomp_intr() at dwc2_hc_n_intr+0x1d4 > > dwc2_hc_n_intr() at dwc2_handle_hcd_intr+0x1e4 > > dwc2_handle_hcd_intr() at dwc2_intr+0xb8 > > > > Obviously usb_syncmem() expects an integer offset as second argument, > > not a memory address. Looks like a typo to me ... > > > > OK? > > Hmm, that doesn't look right. > > > > > > > Index: sys/dev/usb/dwc2/dwc2_hcdintr.c > > =================================================================== > > RCS file: /cvs/src/sys/dev/usb/dwc2/dwc2_hcdintr.c,v > > retrieving revision 1.13 > > diff -u -p -u -p -r1.13 dwc2_hcdintr.c > > --- sys/dev/usb/dwc2/dwc2_hcdintr.c 4 Sep 2021 10:19:28 -0000 1.13 > > +++ sys/dev/usb/dwc2/dwc2_hcdintr.c 14 Apr 2022 17:48:08 -0000 > > @@ -975,11 +975,11 @@ STATIC int dwc2_xfercomp_isoc_split_in(s > > > > if (chan->align_buf) { > > dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); > > - usb_syncmem(qtd->urb->usbdma, chan->qh->dw_align_buf_dma, > > + usb_syncmem(qtd->urb->usbdma, 0, > > chan->qh->dw_align_buf_size, BUS_DMASYNC_POSTREAD); > > memcpy(qtd->urb->buf + frame_desc->offset + > > qtd->isoc_split_offset, chan->qh->dw_align_buf, len); > > - usb_syncmem(qtd->urb->usbdma, chan->qh->dw_align_buf_dma, > > + usb_syncmem(qtd->urb->usbdma, 0, > > chan->qh->dw_align_buf_size, BUS_DMASYNC_PREREAD); > > } > > When chan->align_buf is set we're doing DMA into dw_align_buf, and I > think that means we need to use dw_align_buf_usbdma as the first > argument to usb_syncmem since we need to make sure that the memory > we're doing DMA into is coherent with the cache. So I think this > should be something like: > > if (chan->align_buf) { > struct usb_dma *ud = &chan->qh->dw_align_buf_usbdma; > > dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); > usb_syncmem(ud, 0, chan->qh->dw_align_buf_size, > BUS_DMASYNC_POSTREAD); > memcpy(qtd->urb->buf + frame_desc->offset + > qtd->isoc_split_offset, chan->qh->dw_align_buf, len); > usb_syncmem(qtd->urb->usbdma, chan->qh->dw_align_buf_dma, > usb_syncmem(ud, 0, chan->qh->dw_align_buf_size, > BUS_DMASYNC_PREREAD); > > I think that means the code in dwc2_update_uwb_state() is wrong too. > But then I never fully understood this code...
I guess you're right. Also looking at the other usb_syncmem() calls when dw_align_buf is involved. As well the comment for struct dwc2_qh says: * @dw_align_buf_size: Size of dw_align_buf * @dw_align_buf_dma: DMA address for dw_align_buf I've tested the following diff. Panic is gone, sound still crackles, but still partially plays. I think there are other issues related to the ISOC transfers which need to be investigated further. Index: sys/dev/usb/dwc2/dwc2_hcdintr.c =================================================================== RCS file: /cvs/src/sys/dev/usb/dwc2/dwc2_hcdintr.c,v retrieving revision 1.13 diff -u -p -u -p -r1.13 dwc2_hcdintr.c --- sys/dev/usb/dwc2/dwc2_hcdintr.c 4 Sep 2021 10:19:28 -0000 1.13 +++ sys/dev/usb/dwc2/dwc2_hcdintr.c 15 Apr 2022 07:25:42 -0000 @@ -493,13 +493,15 @@ STATIC int dwc2_update_urb_state(struct /* Non DWORD-aligned buffer case handling */ if (chan->align_buf && xfer_length) { dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); - usb_syncmem(urb->usbdma, 0, chan->qh->dw_align_buf_size, + struct usb_dma *ud = &chan->qh->dw_align_buf_usbdma; + + usb_syncmem(ud, 0, chan->qh->dw_align_buf_size, chan->ep_is_in ? BUS_DMASYNC_POSTREAD : BUS_DMASYNC_POSTWRITE); if (chan->ep_is_in) memcpy(urb->buf + urb->actual_length, chan->qh->dw_align_buf, xfer_length); - usb_syncmem(urb->usbdma, 0, chan->qh->dw_align_buf_size, + usb_syncmem(ud, 0, chan->qh->dw_align_buf_size, chan->ep_is_in ? BUS_DMASYNC_PREREAD : BUS_DMASYNC_PREWRITE); } @@ -975,12 +977,14 @@ STATIC int dwc2_xfercomp_isoc_split_in(s if (chan->align_buf) { dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); - usb_syncmem(qtd->urb->usbdma, chan->qh->dw_align_buf_dma, - chan->qh->dw_align_buf_size, BUS_DMASYNC_POSTREAD); + struct usb_dma *ud = &chan->qh->dw_align_buf_usbdma; + + usb_syncmem(ud, 0, chan->qh->dw_align_buf_size, + BUS_DMASYNC_POSTREAD); memcpy(qtd->urb->buf + frame_desc->offset + qtd->isoc_split_offset, chan->qh->dw_align_buf, len); - usb_syncmem(qtd->urb->usbdma, chan->qh->dw_align_buf_dma, - chan->qh->dw_align_buf_size, BUS_DMASYNC_PREREAD); + usb_syncmem(ud, 0, chan->qh->dw_align_buf_size, + BUS_DMASYNC_PREREAD); } qtd->isoc_split_offset += len; @@ -1207,7 +1211,6 @@ STATIC void dwc2_update_urb_state_abn(st /* Non DWORD-aligned buffer case handling */ if (chan->align_buf && xfer_length && chan->ep_is_in) { dev_vdbg(hsotg->dev, "%s(): non-aligned buffer\n", __func__); - struct usb_dma *ud = &chan->qh->dw_align_buf_usbdma; usb_syncmem(ud, 0, chan->qh->dw_align_buf_size,