make qemu_queue_{cancel,reset} return the number of packets released,
so the caller can figure whenever there have been active packets even
though there shouldn't have been any. Add tracepoint to log this.
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(bool)(sitd->results & SITD_RESULTS_ACTIVE));
}
(bool)(sitd->results & SITD_RESULTS_ACTIVE));
}
+static void ehci_trace_guest_bug(EHCIState *s, const char *message)
+{
+ trace_usb_ehci_guest_bug(message);
+ fprintf(stderr, "ehci warning: %s\n", message);
+}
+
static inline bool ehci_enabled(EHCIState *s)
{
return s->usbcmd & USBCMD_RUNSTOP;
static inline bool ehci_enabled(EHCIState *s)
{
return s->usbcmd & USBCMD_RUNSTOP;
-static void ehci_cancel_queue(EHCIQueue *q)
+static int ehci_cancel_queue(EHCIQueue *q)
p = QTAILQ_FIRST(&q->packets);
if (p == NULL) {
p = QTAILQ_FIRST(&q->packets);
if (p == NULL) {
}
trace_usb_ehci_queue_action(q, "cancel");
do {
ehci_free_packet(p);
}
trace_usb_ehci_queue_action(q, "cancel");
do {
ehci_free_packet(p);
} while ((p = QTAILQ_FIRST(&q->packets)) != NULL);
} while ((p = QTAILQ_FIRST(&q->packets)) != NULL);
-static void ehci_reset_queue(EHCIQueue *q)
+static int ehci_reset_queue(EHCIQueue *q)
trace_usb_ehci_queue_action(q, "reset");
trace_usb_ehci_queue_action(q, "reset");
+ packets = ehci_cancel_queue(q);
q->dev = NULL;
q->qtdaddr = 0;
q->dev = NULL;
q->qtdaddr = 0;
}
static void ehci_free_queue(EHCIQueue *q)
}
static void ehci_free_queue(EHCIQueue *q)
(memcmp(&qh.current_qtd, &q->qh.current_qtd,
9 * sizeof(uint32_t)) != 0) ||
(q->dev != NULL && q->dev->addr != devaddr)) {
(memcmp(&qh.current_qtd, &q->qh.current_qtd,
9 * sizeof(uint32_t)) != 0) ||
(q->dev != NULL && q->dev->addr != devaddr)) {
+ if (ehci_reset_queue(q) > 0) {
+ ehci_trace_guest_bug(ehci, "guest updated active QH");
+ }
(!NLPTR_TBIT(p->qtd.next) && (p->qtd.next != qtd.next)) ||
(!NLPTR_TBIT(p->qtd.altnext) && (p->qtd.altnext != qtd.altnext)) ||
p->qtd.bufptr[0] != qtd.bufptr[0]) {
(!NLPTR_TBIT(p->qtd.next) && (p->qtd.next != qtd.next)) ||
(!NLPTR_TBIT(p->qtd.altnext) && (p->qtd.altnext != qtd.altnext)) ||
p->qtd.bufptr[0] != qtd.bufptr[0]) {
- /* guest bug: guest updated active QH or qTD underneath us */
+ ehci_trace_guest_bug(q->ehci, "guest updated active QH or qTD");
p = NULL;
} else {
p->qtd = qtd;
p = NULL;
} else {
p->qtd = qtd;
usb_ehci_queue_action(void *q, const char *action) "q %p: %s"
usb_ehci_packet_action(void *q, void *p, const char *action) "q %p p %p: %s"
usb_ehci_irq(uint32_t level, uint32_t frindex, uint32_t sts, uint32_t mask) "level %d, frindex 0x%04x, sts 0x%x, mask 0x%x"
usb_ehci_queue_action(void *q, const char *action) "q %p: %s"
usb_ehci_packet_action(void *q, void *p, const char *action) "q %p p %p: %s"
usb_ehci_irq(uint32_t level, uint32_t frindex, uint32_t sts, uint32_t mask) "level %d, frindex 0x%04x, sts 0x%x, mask 0x%x"
+usb_ehci_guest_bug(const char *reason) "%s"
# hw/usb/hcd-uhci.c
usb_uhci_reset(void) "=== RESET ==="
# hw/usb/hcd-uhci.c
usb_uhci_reset(void) "=== RESET ==="