qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* OHCI/usb pass through
@ 2021-10-01  1:31 BALATON Zoltan
  2021-10-01  4:39 ` Gerd Hoffmann
  0 siblings, 1 reply; 4+ messages in thread
From: BALATON Zoltan @ 2021-10-01  1:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Mark Cave-Ayland, Gerd Hoffmann, Howard Spoelstra

Hello,

We're trying to find out why passing through an usb sound card fails with 
MacOS/OS X on mac99 and came across some things in OHCI that I don't 
understand so some help from those who know more about USB handling in 
QEMU or OHCI would be needed.

From traces Howard collected we see that a packet is submitted to libusb 
which does not complete immediately so it gets recorded as async but never 
seems to complete afterwards. Meanwhile some isochronous traffic is 
happening on a different endpoint but it is then rejected with too many 
pending packets due to the waiting async packet and things seem to stop at 
this point.

There is a comment in hw/usb/hcd-ohci.c:1031 in ohci_service_td() that 
says this is something that is not modelled correctly as it should allow 
active packets per endpoint while we only have one packet per controller 
(but maybe there are other problems than this too). The problem seems to 
be that currently we have this active packet recorded in OHCIState in 
these fields:

[...]
     /* Active packets.  */
     uint32_t old_ctl;
     USBPacket usb_packet;
     uint8_t usb_buf[8192];
     uint32_t async_td;
     bool async_complete;

     void (*ohci_die)(struct OHCIState *ohci);
} OHCIState;

Then everything in hcd-ohci seems to reuse ohci->usb_packet and I wonder 
if it can happen that it's overwritten while an async packet is still 
using it. It seems to be reset calling usb_packet_setup() in two places: 
ohci_service_td() and ohci_service_iso_td(). While ohci_service_td() 
checks for ohci->async_td, ohci_service_iso_td() doesn't seem to so maybe 
it can break the pending async packet if an isochronous request comes in 
while the other endpoint is waiting for the async packet. If so maybe when 
the completion is called it won't notice because ohci->usb_packet is 
already a different packet overwritten by ohci_service_iso_td(). Did I 
miss some other checks elsewhere that prevent this from happening? (I 
don't know how USB is handled in QEMU or how OHCI works so it could be I'm 
not understing this correctly.)

In any case to both fix the device model and to avoid this possible 
problem described above it seems we would need to ditch the packet and 
async_td fields from OHCIState and move them to the endpoint to allow one 
active packet per endpoint. We can get the endpoint from a packet and from 
ohci so I wonder if we can get the active packet from ep->queue (and how 
to do that) and then can we find out if it's waiting by checking if this 
packet's status is USB_PACKET_ASYNC so we don't need to keep track of 
these in OHCIState. I don't understand this code enough to try to do it 
but maybe some hints could help.

Thanks,
BALATON Zoltan


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-10-01 12:25 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2021-10-01  1:31 OHCI/usb pass through BALATON Zoltan
2021-10-01  4:39 ` Gerd Hoffmann
2021-10-01 11:35   ` BALATON Zoltan
2021-10-01 12:22     ` Gerd Hoffmann

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).