Re: Comment #135 for bugzilla 237666 : a USB3-handling problem with a investigatory fix for a cortex-a72 context

Mark Millard via freebsd-arm <[email protected]>
Newsgroups gmane.os.freebsd.devel.arm
Message-ID <[email protected]>
> On 2020-Sep-19, at 12:18, Mark Millard <[email protected]> wrote:
> 
> In the below I've cut out text without always indicating
> where so that code looks complete that is complete. I've
> also included some text from another reply of yours that
> fills in some specifics of what you were after.
> 
> On 2020-Sep-19, at 04:46, Hans Petter Selasky <hps at selasky.org> wrote:
>> 
>>>>> . . .
>>>>> 
>>>>> Your finding indicate a problem in usb_pc_cpu_flush() and
>>>>> 
>>>>> bus_dmamap_sync(pc->tag, pc->map, BUS_DMASYNC_PREWRITE);
>>>>> 
>>>>> Try to put the dsb only after dmamap_sync.
>>>>> 
>>>>> void
>>>>> usb_pc_cpu_flush(struct usb_page_cache *pc)
>>>>> {
>>>>>      if (pc->page_offset_end == pc->page_offset_buf) {
>>>>>              /* nothing has been loaded into this page cache! */
>>>>>              return;
>>>>>      }
>>>>>      bus_dmamap_sync(pc->tag, pc->map, BUS_DMASYNC_PREWRITE);
>>>>> }
>>>>> . . .
>>>> After adding a couple of more DSB ST instructions and rebuilding
>>>> (cross build), installing, and booting, I started a self-hosted,
>>>> from-scratch, buildworld buildlkernel and intend to installkernel
>>>> installworld and reboot if it appears to go well. (Better than
>>>> just a boot test for if things seem at least sufficient, even if
>>>> overkill.) But it will be hours before buildworld build kernel is
>>>> done (-j3). (I'll sleep during much of that time.)
> 
> The buildworld buildkernel, installkernel installworld, reboot
> sequence seems to have gone fine.
> 
>>>> . . .
>>>>       phwr = buf_res.buffer;
>>>>       addr = buf_res.physaddr;
>>>>       addr += (uintptr_t)&((struct xhci_hw_root *)0)->hwr_events[0];
>>>>                /* reset hardware root structure */
>>>>       memset(phwr, 0, sizeof(*phwr));
>>>>                phwr->hwr_ring_seg[0].qwEvrsTablePtr = htole64(addr);
>>>>       phwr->hwr_ring_seg[0].dwEvrsTableSize = htole32(XHCI_MAX_EVENTS);
>>>>                DPRINTF("ERDP(0)=0x%016llx\n", (unsigned long long)addr);
>>>> #ifdef __aarch64__
>>>> __asm __volatile("dsb st" : : : "memory");
>>>> #endif
>>>>       XWRITE4(sc, runt, XHCI_ERDP_LO(0), (uint32_t)addr);
>>>>       XWRITE4(sc, runt, XHCI_ERDP_HI(0), (uint32_t)(addr >> 32));
>>>>                addr = buf_res.physaddr;
>>>>                DPRINTF("ERSTBA(0)=0x%016llx\n", (unsigned long long)addr);
>>>>       XWRITE4(sc, runt, XHCI_ERSTBA_LO(0), (uint32_t)addr);
>>>>       XWRITE4(sc, runt, XHCI_ERSTBA_HI(0), (uint32_t)(addr >> 32));
>>> . . .
>>> Probably same bug in the USB invalidate function.
> 
>>> On 2020-09-19 11:31, Mark Millard wrote:
>>>> #ifdef __aarch64__
>>>> __asm __volatile("dsb ld" : : : "memory");
>>>> #endif
>>>>                temp = le32toh(phwr->hwr_events[i].dwTrb3);
>>>> 
>>> 
>>> 
>>> If you look a few lines up you'll find the:
>>> 
>>>       usb_pc_cpu_invalidate(&sc->sc_hw.root_pc);
>>> 
>>> That's where this instruction belongs.
> 
>>> Try to patch those generic flush/invalidate functions instead. I've been very careful about those.
>> 
>> Sure.
>> 
>>>>               temp = le32toh(phwr->hwr_events[i].dwTrb3);
>>>>                        k = (temp & XHCI_TRB_3_CYCLE_BIT) ? 1 : 0;
>>>>                        if (j != k)
>>>>                       break;
>>>> always took the break because temp was always zero, k was always zero,
>>>> and j was 1. I expect this is because the wrong qwEvrsTablePtr and
>>>> dwEvrsTableSize content was in use by the xhci (fixed by the DSB ST).
>>>> . . .
>>> 
>>> It smells like a generic problem in the busdma synchronize code.
>>> 
>>>> (Pe means "executing processor".)
>>>> I expect the removal of that specific DSB ST to result in
>>>> xhci_interrupt_poll's code again taking the break every time,
>>>> just based on event ring behavior alone.
>>> 
>>> Again, try to patch both
>>> usb_pc_cpu_flush()
>>> and
>>> usb_pc_cpu_invalidate()
>> 
>> Sure.
>> 
> 
> Unfortunately, it fails the same old way as far as
> what is seen on the console.
> 
> So the steps used were:
> 
> I reverted /usr/src/sys/dev/usb/controller/xhci.c .
> 
> Then changed things so that:
> 
> # svnlite diff /usr/src/sys/dev/usb/usb_busdma.c
> Index: /usr/src/sys/dev/usb/usb_busdma.c
> ===================================================================
> --- /usr/src/sys/dev/usb/usb_busdma.c	(revision 363590)
> +++ /usr/src/sys/dev/usb/usb_busdma.c	(working copy)
> @@ -737,6 +737,9 @@
> 	 */
> 	bus_dmamap_sync(pc->tag, pc->map, BUS_DMASYNC_POSTREAD);
> 	bus_dmamap_sync(pc->tag, pc->map, BUS_DMASYNC_PREREAD);
> +#ifdef __aarch64__
> +__asm __volatile("dsb ld" : : : "memory");
> +#endif
> }
> 
> /*------------------------------------------------------------------------*
> @@ -750,6 +753,9 @@
> 		return;
> 	}
> 	bus_dmamap_sync(pc->tag, pc->map, BUS_DMASYNC_PREWRITE);
> +#ifdef __aarch64__
> +__asm __volatile("dsb st" : : : "memory");
> +#endif
> }
> 
> /*------------------------------------------------------------------------*
> 
> 
> As I expected, the resulting build fails to boot the same old
> way: a sequence messages that repeats indefinitely and
> involves "xhci0: Resetting controller" and no root file system
> mount happens.
> 
> So I put back the just last change that had previously lead to
> the successful booting (given the prior DSB ST / DSB LD
> additions). I did so exactly as I originally had it:
> 
> # svnlite diff /usr/src/sys/dev/usb/controller/xhci.c
> Index: /usr/src/sys/dev/usb/controller/xhci.c
> ===================================================================
> --- /usr/src/sys/dev/usb/controller/xhci.c	(revision 363590)
> +++ /usr/src/sys/dev/usb/controller/xhci.c	(working copy)
> @@ -406,6 +406,9 @@
> 
> 	addr = buf_res.physaddr;
> 
> +#ifdef __aarch64__
> +__asm __volatile("dsb st" : : : "memory");
> +#endif
> 	XWRITE4(sc, oper, XHCI_DCBAAP_LO, (uint32_t)addr);
> 	XWRITE4(sc, oper, XHCI_DCBAAP_HI, (uint32_t)(addr >> 32));
> 	XWRITE4(sc, oper, XHCI_DCBAAP_LO, (uint32_t)addr);
> 
> The result still fails. So more is required.

The controller/xhci.c change above was the wrong one: I grabbed
the wrong text. Retrying with:

# svnlite diff /usr/src/sys/dev/usb/controller/xhci.c
Index: /usr/src/sys/dev/usb/controller/xhci.c
===================================================================
--- /usr/src/sys/dev/usb/controller/xhci.c	(revision 363590)
+++ /usr/src/sys/dev/usb/controller/xhci.c	(working copy)
@@ -441,6 +441,9 @@
 
 	DPRINTF("ERSTBA(0)=0x%016llx\n", (unsigned long long)addr);
 
+#ifdef __aarch64__
+__asm __volatile("dsb st" : : : "memory");
+#endif
 	XWRITE4(sc, runt, XHCI_ERSTBA_LO(0), (uint32_t)addr);
 	XWRITE4(sc, runt, XHCI_ERSTBA_HI(0), (uint32_t)(addr >> 32));
 
booted just fine. This is what I expected relative to
initializing for the event ring.




===
Mark Millard
marklmi at yahoo.com
( dsl-only.net went
away in early 2018-Mar)

_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-arm
To unsubscribe, send any mail to "[email protected]"
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.