On Tue, Apr 14, 2020 at 11:06:00AM +0200, Patrick Wildt wrote:
> On Mon, Apr 13, 2020 at 09:36:04PM +0200, Mark Kettenis wrote:
> > 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.
XXX #1# ehci_idone: len=4 actlen=4294951308, xf_actlen=0, status=0x8d00,
sqtd_count=3
XXX #2# ehci_idone: x_actlen=4294951304, sqtd_len=8, ehci_qtd_len=16000,
status=0xbe808d00, qtd_status=0xbe808d00, sqtd_count=1
XXX #2# ehci_idone: x_actlen=4294951308, sqtd_len=4, ehci_qtd_len=0,
status=0xc00, qtd_status=0xc00, sqtd_count=2
XXX #2# ehci_idone: x_actlen=4294951308, sqtd_len=0, ehci_qtd_len=0,
status=0x8d00, qtd_status=0x8d00, sqtd_count=3
panic: _dmamap_sync: ran off map!
Above are my debug lines in dmesg generated just before panic.
The code which prints those lines is below. It's similar for-loop to
what is currently in CVS in ehci_idone() function. I'm doing this
for-loop twice. First version of for-loop is executed as is in CVS
and record condition that panic will happen, then below for-loop is
executed again with more debug output, otherwise printf() will slow
the code path so mutch that I will not be able to trigger error
condition.
With below code (lines from 1 to 29) I already know panic condition is
met and I'm executing code with printf()s added.
sqtd_count=3 means that for-loop from line 6 to 28 was executed 3 times.
XXX #1# ehci_idone: len=4 actlen=4294951308, xf_actlen=0, status=0x8d00,
sqtd_count=3
Above message is from line 2 of the code listed below.
Then we enter the for-loop at line 6, which iterates 3 times. Each
iteration gives following results:
XXX #2# ehci_idone: x_actlen=4294951304, sqtd_len=8, ehci_qtd_len=16000,
status=0xbe808d00, qtd_status=0xbe808d00, sqtd_count=1
XXX #2# ehci_idone: x_actlen=4294951308, sqtd_len=4, ehci_qtd_len=0,
status=0xc00, qtd_status=0xc00, sqtd_count=2
XXX #2# ehci_idone: x_actlen=4294951308, sqtd_len=0, ehci_qtd_len=0,
status=0x8d00, qtd_status=0x8d00, sqtd_count=3
then code proceeds and triggers panic.
1 if (xfer->length < actlen) {
2 printf("XXX #1# ehci_idone: len=%u, actlen=%u,
xf_actlen=%u, "
3 "status=0x%x, sqtd_count=%d\n", xfer->length,
actlen, xfer->actlen, status, sqtd_count);
4 x_actlen = 0;
5 sqtd_count = 0;
6 for (sqtd = ex->sqtdstart; sqtd != NULL; sqtd = sqtd->nextqtd) {
7 sqtd_count++;
8 usb_syncmem(&sqtd->dma, sqtd->offs, sizeof(sqtd->qtd),
9 BUS_DMASYNC_POSTWRITE | BUS_DMASYNC_POSTREAD);
10 nstatus = letoh32(sqtd->qtd.qtd_status);
11 qtd_status = nstatus;
12 if (nstatus & EHCI_QTD_ACTIVE)
13 break;
14
15 status = nstatus;
16 /* halt is ok if descriptor is last, and complete */
17 if (sqtd->qtd.qtd_next == htole32(EHCI_LINK_TERMINATE)
&&
18 EHCI_QTD_GET_BYTES(status) == 0)
19 status &= ~EHCI_QTD_HALTED;
20 if (EHCI_QTD_GET_PID(status) != EHCI_QTD_PID_SETUP) {
21 sqtd_len = sqtd->len;
22 ehci_qtd_len = EHCI_QTD_GET_BYTES(status);
23 x_actlen += sqtd_len - ehci_qtd_len;
24 printf("XXX #2# ehci_idone: x_actlen=%u,
sqtd_len=%u, ehci_qtd_len=%u, "
25 "status=0x%x, qtd_status=0x%x,
sqtd_count=%d\n",
26 x_actlen, sqtd_len, ehci_qtd_len,
status, qtd_status, sqtd_count);
27 }
28 }
29 }
I can provide full patch if someone is interested what exactly I am
doing.
--
Regards,
Mikolaj