| From 11ba203517cc28be513ac31c12762c4519e98ee5 Mon Sep 17 00:00:00 2001 |
| From: Gerd Hoffmann <kraxel@redhat.com> |
| Date: Fri, 31 Aug 2012 15:30:51 +0200 |
| Subject: [PATCH 351/366] xhci: pick target interrupter |
| |
| Pick the correct interrupter when queuing an event. |
| |
| Signed-off-by: Gerd Hoffmann <kraxel@redhat.com> |
| |
| hw/usb/hcd-xhci.c | 22 ++++++++++++++++------ |
| 1 file changed, 16 insertions(+), 6 deletions(-) |
| |
| diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c |
| index 68a19ab..d6ab0c6 100644 |
| |
| |
| @@ -264,6 +264,10 @@ typedef enum TRBCCode { |
| |
| #define TRB_LK_TC (1<<1) |
| |
| +#define TRB_INTR_SHIFT 22 |
| +#define TRB_INTR_MASK 0x3ff |
| +#define TRB_INTR(t) (((t).status >> TRB_INTR_SHIFT) & TRB_INTR_MASK) |
| + |
| #define EP_TYPE_MASK 0x7 |
| #define EP_TYPE_SHIFT 3 |
| |
| @@ -806,10 +810,16 @@ static void xhci_events_update(XHCIState *xhci, int v) |
| |
| static void xhci_event(XHCIState *xhci, XHCIEvent *event, int v) |
| { |
| - XHCIInterrupter *intr = &xhci->intr[v]; |
| + XHCIInterrupter *intr; |
| dma_addr_t erdp; |
| unsigned int dp_idx; |
| |
| + if (v >= MAXINTRS) { |
| + DPRINTF("intr nr out of range (%d >= %d)\n", v, MAXINTRS); |
| + return; |
| + } |
| + intr = &xhci->intr[v]; |
| + |
| if (intr->er_full) { |
| DPRINTF("xhci_event(): ER full, queueing\n"); |
| if (((intr->ev_buffer_put+1) % EV_QUEUE) == intr->ev_buffer_get) { |
| @@ -1377,7 +1387,7 @@ static void xhci_xfer_report(XHCITransfer *xfer) |
| DPRINTF("xhci_xfer_data: EDTLA=%d\n", event.length); |
| edtla = 0; |
| } |
| - xhci_event(xhci, &event, 0 /* FIXME */); |
| + xhci_event(xhci, &event, TRB_INTR(*trb)); |
| reported = 1; |
| if (xfer->status != CC_SUCCESS) { |
| return; |
| @@ -2255,7 +2265,7 @@ static void xhci_process_commands(XHCIState *xhci) |
| break; |
| } |
| event.slotid = slotid; |
| - xhci_event(xhci, &event, 0 /* FIXME */); |
| + xhci_event(xhci, &event, 0); |
| } |
| } |
| |
| @@ -2285,7 +2295,7 @@ static void xhci_update_port(XHCIState *xhci, XHCIPort *port, int is_detach) |
| port->portsc |= PORTSC_CSC; |
| XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, |
| port->portnr << 24}; |
| - xhci_event(xhci, &ev, 0 /* FIXME */); |
| + xhci_event(xhci, &ev, 0); |
| DPRINTF("xhci: port change event for port %d\n", port->portnr); |
| } |
| } |
| @@ -2564,7 +2574,7 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val) |
| if (xhci->crcr_low & (CRCR_CA|CRCR_CS) && (xhci->crcr_low & CRCR_CRR)) { |
| XHCIEvent event = {ER_COMMAND_COMPLETE, CC_COMMAND_RING_STOPPED}; |
| xhci->crcr_low &= ~CRCR_CRR; |
| - xhci_event(xhci, &event, 0 /* FIXME */); |
| + xhci_event(xhci, &event, 0); |
| DPRINTF("xhci: command ring stopped (CRCR=%08x)\n", xhci->crcr_low); |
| } else { |
| dma_addr_t base = xhci_addr64(xhci->crcr_low & ~0x3f, val); |
| @@ -2807,7 +2817,7 @@ static void xhci_wakeup(USBPort *usbport) |
| return; |
| } |
| port->portsc |= PORTSC_PLC; |
| - xhci_event(xhci, &ev, 0 /* FIXME */); |
| + xhci_event(xhci, &ev, 0); |
| } |
| |
| static void xhci_complete(USBPort *port, USBPacket *packet) |
| -- |
| 1.7.12 |
| |