On Tue, Feb 04, 2014 at 10:01:32AM +0100, Gerd Hoffmann wrote:
Hi,
I looked through the QEMU hcd-uhci.c code, and I think QEMU is buggy here. QEMU keeps a mapping of queues that are indexed by the usb device address and endpoint (see uhci_queue_new() ). When the usb device has address 0, it creates an entry in this mapping and the entry remains even after the device is given a new address. Later, when the next device also has address 0, QEMU attempts to use that mapping even though the 0 address now corresponds with a different device.
Nice spotting. Does the attached patch help?
Doesn't help for me either. It's not hard to reproduce for me - I just run qemu with "-usb -device usb-kbd -device usb-net" and don't run with seabios debugging directed to stdout (as that seems to add some delays which can make things work) - it locks up the keyboard most times for me.
The qemu patch below does fix it for me. I think clearing the cache on reset is probably simpler then trying to verify the cache later on. It would be even better to clear the cache on a set_address command (to cover the admittedly obscure case of an OS changing a device's address later on). But, I'm not familiar enough with the QEMU code to attempt that.
-Kevin
--- a/hw/usb/hcd-uhci.c +++ b/hw/usb/hcd-uhci.c @@ -550,6 +552,13 @@ static void uhci_port_write(void *opaque, hwaddr addr, !(port->ctrl & UHCI_PORT_RESET) ) { usb_device_reset(dev); } + UHCIQueue *queue, *nq; + + QTAILQ_FOREACH_SAFE(queue, &s->queues, next, nq) { + if (queue->token == 0) { + uhci_queue_free(queue, "reset-port"); + } + } } port->ctrl &= UHCI_PORT_READ_ONLY; /* enabled may only be set if a device is connected */