Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OHCI: MMIO coherency/sync issue #2687

Open
1 task done
Ryzee119 opened this issue Jun 22, 2024 · 0 comments
Open
1 task done

OHCI: MMIO coherency/sync issue #2687

Ryzee119 opened this issue Jun 22, 2024 · 0 comments
Labels

Comments

@Ryzee119
Copy link
Contributor

Operating System

Windows 11

Board

OHCI

Firmware

class/hid_host/c
portable/ohci/ohci.c

What happened ?

After random lengths of time OHCI transfers will not fire the completion interrupt. I traced this to garbage being in hcca.done_head.

The garbage was similar to the address of the TD but was partically corrupt or missing. The root cause was writing to td_head directly here

p_ed->td_head.address |= (uint32_t) _phys_addr(p_gtd);

I can see exactly why we are doing this; which to prevent having to allocate dummy TDs for every ED, but the OHCI spec implies you cannot do this.

Section 4.6 of OHCI has this; I have a feeling I am getting the coherency/sync issue described here.

Software queues to the list by using the value of TailP to obtain the physical address of the last
TD queued to the ED. Since the TD pointed to by TailP is not accessed by the HC, the Host
Controller Driver can initialize that TD and link at least one other to it without creating a
coherency or synchronization problem.
Software may not alter in any way any of the
TDs it has queued prior to the one pointed to by TailP until the Host Controller completes
processing of the TD or the Host Controller Driver ensures that queue processing for the ED has
been halted.

I have found two fixes below:

  1. Stop ED while we modify it to queue the transfer, but this is not an ideal solution waiting 1ms every transaction; although maybe not too bad and a sacrifice that can be made to Tiny USB to keep it small. This would be okay for interrupt and bulk ultimately and isochronous can be handled differently (I am currently adding it)
+p_ed->skip = 1;
+osal_task_delay(1); // Wait one frame to ensure OHCI is not processing ED
p_ed->td_head.address |= (uint32_t) _phys_addr(p_gtd); // Write it
+p_ed->skip = 0;
  1. The 'correct' way and I can confirm it resolved the issue was by creating a dummy TD that is linked to the ED head and tail on hcd_open. Then in hcd_edpt_xfer I populated this TD, allocate a new dummy then update the ED tail to pointer to the new TD which triggers the transfer. This is exactly what the OHCI recomends and the issue no longer occurs. The big problem is ofcourse this basically doubles the memory used by TDs.

image

I was not able to replicate with control transfers, as I think we use the control list filled bit to trigger the transfer and only every have one control transfer at a time.

How to reproduce ?

Its pretty random and took usually a minute or two to occur, Just i had interrupt transferings firing every millisecond so activitely was high.

td_head = _virt_addr(td_head);

This assert picked it up fairly quickly

static ohci_td_item_t* list_reverse(ohci_td_item_t* td_head)
{
  ohci_td_item_t* td_reverse_head = NULL;
  while(td_head != NULL)
  {
      td_head = _virt_addr(td_head);
+     // Check if the td address is atleast within the ohci data struct. If not something is really wrong!
+     TU_ASSERT((uintptr_t)&ohci_data < (uintptr_t)td_head  < ((uintptr_t)(&ohci_data) + sizeof(ohci_data)));
      uint32_t next = td_head->next;

Debug Log as txt file (LOG/CFG_TUSB_DEBUG=2)

Already root caused this problem.

Its possibly it only occurs on certain hardware depending how caching and clocks are handled.

Screenshots

No response

I have checked existing issues, dicussion and documentation

  • I confirm I have checked existing issues, dicussion and documentation.
@Ryzee119 Ryzee119 changed the title OHCI: MMIO coherency/synch issue OHCI: MMIO coherency/sync issue Jun 22, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant