On Mon, Apr 13, 2020 at 09:36:04PM +0200, Mark Kettenis wrote:
> > From: "Theo de Raadt" <dera...@openbsd.org>
> > cc: Patrick Wildt <patr...@blueri.se>
> > Comments: In-reply-to Mikolaj Kucharski <miko...@kucharski.name>
> >    message dated "Mon, 13 Apr 2020 18:55:37 -0000."
> > Content-Type: text/plain; charset="us-ascii"
> > Content-ID: <61132.158680562...@cvs.openbsd.org>
> > Date: Mon, 13 Apr 2020 13:20:27 -0600
> > 
> > Mikolaj Kucharski <miko...@kucharski.name> wrote:
> > 
> > > On Mon, Apr 13, 2020 at 12:44:54PM -0600, Theo de Raadt wrote:
> > > > Then you need to look at why this crazy value is composed here in this
> > > > loop:
> > > > 
> > > >         actlen = 0;
> > > >         for (sqtd = ex->sqtdstart; sqtd != NULL; sqtd = sqtd->nextqtd) {
> > > >                 usb_syncmem(&sqtd->dma, sqtd->offs, sizeof(sqtd->qtd),
> > > >                     BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
> > > >                 nstatus = letoh32(sqtd->qtd.qtd_status);
> > > >                 if (nstatus & EHCI_QTD_ACTIVE)
> > > >                         break;
> > > > 
> > > >                 status = nstatus;
> > > >                 /* halt is ok if descriptor is last, and complete */
> > > >                 if (sqtd->qtd.qtd_next == htole32(EHCI_LINK_TERMINATE) 
> > > > &&
> > > >                     EHCI_QTD_GET_BYTES(status) == 0)
> > > >                         status &= ~EHCI_QTD_HALTED;
> > > >                 if (EHCI_QTD_GET_PID(status) != EHCI_QTD_PID_SETUP)
> > > >                         actlen += sqtd->len - 
> > > > EHCI_QTD_GET_BYTES(status);
> > > >         }
> > > 
> > > But I just described that in one of my previous emails few minutes ago.
> > > 
> > > In my diff I'm using second loop of the same code, but I guess I can
> > > provide more surgurucal diff to be more explicit. What I wrote in my
> > > previous email can be written also as follows:
> > > 
> > >   actlen += sqtd->len - EHCI_QTD_GET_BYTES(status);
> > > 
> > > In above equation, on first for loop iteration:
> > > 
> > > actlen is 0
> > > EHCI_QTD_GET_BYTES(status) is 16000
> > > sqtd->len is 8
> > > 
> > > actlen += 8 - 1600;
> > > 
> > > Which results of actlen being 4294951304, from that moment we are
> > > heading to kernel panic.
> > 
> > Then next step is to figure out why the sqtd is incoherent.
> 
> I actually suspect that the 16000 here is bogus.

Exactly.  I looked at it yesterday, without his additional info, and
realized that in this case the calculated actlen for that control
transfer must be broken.

xfer->length was 8, xfer->actlen was 15996, so something was doing
(0 - 4), or maybe (4 - 1600), which actually makes much more sense,
since otherwise sqtd->len would have been 0, which would be very
weird.

So now, why does EHCI_QTD_GET_BYTES return 16000...

> Can you print the status (full 32 bits) of that particular QTD?

Yeah, I wish I could see the status field for each sqtd in that
chain.

On the bright side:  This is not a bug in my DMA diff!  But it
exposed a bug in the actlen calculation.

Patrick

Reply via email to