All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 00/54] usb patch queue
@ 2012-09-06  7:12 Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 01/54] usb: controllers do not need to check for babble themselves Gerd Hoffmann
                   ` (54 more replies)
  0 siblings, 55 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

  Hi,

Here comes the usb patch queue with a bunch of new goodies accumulated
while qemu was in freeze for the 1.2 release:

 * ehci gets more tracepoints & improvements in the queuing code and
   minor bugfixes (the important fixes where a last minute 1.2 pull).
 * usbredir goes make use of the new queues in the usb core instead
   of managing its own.  Also a bunch of preparations for live
   migration support.
 * xhci gets a bunch of fixes and improvements: port handling fixes,
   fix & enable msi/msix support, support for multiple interrupters,
   support for iso transfers, tracing improvemnets, cleanups & fixes.
 * usb core got support for creating usb3 descriptors.
 * usb3 emulation is enabled for usb-storage, so when hooking up
   usb-storage to xhci it shows up as usb3 device in the guest.
 * Little fixes here and there.

cheers,
  Gerd

The following changes since commit 8db972cfa469b4e4afd9c65e54e796b83b5ce3a2:

  Update version for 1.2.0 (2012-09-05 07:50:01 -0500)

are available in the git repository at:
  git://git.kraxel.org/qemu usb.62

Gerd Hoffmann (28):
      ehci: check for EHCI_ASYNC_FINISHED first in ehci_free_packet
      ehci: trace guest bugs
      ehci: add doorbell trace events
      usb-audio: fix usb version
      xhci: rip out background transfer code
      xhci: drop buffering
      xhci: move device lookup into xhci_setup_packet
      xhci: implement mfindex
      xhci: iso xfer support
      xhci: trace cc codes in cleartext
      xhci: add trace_usb_xhci_ep_set_dequeue
      xhci: fix runtime write tracepoint
      xhci: update register layout
      xhci: update port handling
      usb3: superspeed descriptors
      usb3: superspeed endpoint companion
      usb3: bos decriptor
      usb-storage: usb3 support
      xhci: fix & cleanup msi.
      xhci: rework interrupt handling
      xhci: add msix support
      xhci: move register update into xhci_intr_raise
      xhci: add XHCIInterrupter
      xhci: prepare xhci_runtime_{read,write} for multiple interrupters
      xhci: pick target interrupter
      xhci: support multiple interrupters
      xhci: kill xhci_mem_{read,write} dispatcher functions
      xhci: allow bytewise capability register reads

Hans de Goede (25):
      usb: controllers do not need to check for babble themselves
      usb-core: Don't set packet state to complete on a nak
      usb-core: Add a usb_ep_find_packet_by_id() helper function
      usb-core: Allow the first packet of a pipelined ep to complete immediately
      Revert "ehci: don't flush cache on doorbell rings."
      ehci: Validate qh is not changed unexpectedly by the guest
      ehci: Update copyright headers to reflect recent work
      ehci: Properly cleanup packets on cancel
      ehci: Properly report completed but not yet processed packets to the guest
      ehci: Add some additional ehci_trace_guest_bug() calls
      ehci: Fix memory leak in handling of NAK-ed packets
      ehci: Handle USB_RET_PROCERR in ehci_fill_queue
      ehci: Correct a comment in fetchqtd packet processing
      usb-redir: Never return USB_RET_NAK for async handled packets
      usb-redir: Don't delay handling of open events to a bottom half
      usb-redir: Get rid of async-struct get member
      usb-redir: Get rid of local shadow copy of packet headers
      usb-redir: Get rid of unused async-struct dev member
      usb-redir: Move to core packet id and queue handling
      usb-redir: Return babble when getting more bulk data then requested
      usb-redir: Convert to new libusbredirparser 0.5 API
      usb-redir: Set ep max_packet_size if available
      usb-redir: Add a usbredir_reject_device helper function
      usb-redir: Ensure our peer has the necessary caps when redirecting to XHCI
      usb-redir: Enable pipelining for bulk endpoints

Samuel Thibault (1):
      Better name usb braille device

 configure            |    2 +-
 hw/usb.h             |    9 +
 hw/usb/core.c        |   23 +-
 hw/usb/desc.c        |  174 ++++++-
 hw/usb/desc.h        |   52 ++-
 hw/usb/dev-audio.c   |    2 +-
 hw/usb/dev-serial.c  |    2 +-
 hw/usb/dev-storage.c |   46 ++-
 hw/usb/hcd-ehci.c    |  180 ++++---
 hw/usb/hcd-uhci.c    |    5 -
 hw/usb/hcd-xhci.c    | 1432 ++++++++++++++++++++++++++------------------------
 hw/usb/redirect.c    |  477 ++++++++---------
 trace-events         |   12 +-
 13 files changed, 1376 insertions(+), 1040 deletions(-)

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

* [Qemu-devel] [PATCH 01/54] usb: controllers do not need to check for babble themselves
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 02/54] usb-core: Don't set packet state to complete on a nak Gerd Hoffmann
                   ` (53 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede, Gerd Hoffmann

From: Hans de Goede <hdegoede@redhat.com>

If an (emulated) usb-device tries to write more data to a packet then
its iov len, this will trigger an assert in usb_packet_copy(), and if
a driver somehow circumvents that check and writes more data to the
iov then there is space, we have a much bigger problem then not correctly
reporting babble to the guest.

In practice babble will only happen with (real) redirected devices, and there
both the usb-host os and the qemu usb-device code already check for it.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-ehci.c |    4 ----
 hw/usb/hcd-uhci.c |    5 -----
 2 files changed, 0 insertions(+), 9 deletions(-)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 017342b..9523247 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -1481,10 +1481,6 @@ static void ehci_execute_complete(EHCIQueue *q)
             assert(0);
             break;
         }
-    } else if ((p->usb_status > p->tbytes) && (p->pid == USB_TOKEN_IN)) {
-        p->usb_status = USB_RET_BABBLE;
-        q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_BABBLE);
-        ehci_raise_irq(q->ehci, USBSTS_ERRINT);
     } else {
         // TODO check 4.12 for splits
 
diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index b0db921..c7c8786 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -729,11 +729,6 @@ static int uhci_complete_td(UHCIState *s, UHCI_TD *td, UHCIAsync *async, uint32_
         *int_mask |= 0x01;
 
     if (pid == USB_TOKEN_IN) {
-        if (len > max_len) {
-            ret = USB_RET_BABBLE;
-            goto out;
-        }
-
         if ((td->ctrl & TD_CTRL_SPD) && len < max_len) {
             *int_mask |= 0x02;
             /* short packet: do not update QH */
-- 
1.7.1

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

* [Qemu-devel] [PATCH 02/54] usb-core: Don't set packet state to complete on a nak
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 01/54] usb: controllers do not need to check for babble themselves Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 03/54] usb-core: Add a usb_ep_find_packet_by_id() helper function Gerd Hoffmann
                   ` (52 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede, Gerd Hoffmann

From: Hans de Goede <hdegoede@redhat.com>

This way the hcd can re-use the same packet to retry without needing
to re-init it.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/core.c |    6 ++++--
 1 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/hw/usb/core.c b/hw/usb/core.c
index 2da38e7..be6d936 100644
--- a/hw/usb/core.c
+++ b/hw/usb/core.c
@@ -399,8 +399,10 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
              * otherwise packets can complete out of order!
              */
             assert(!p->ep->pipeline);
-            p->result = ret;
-            usb_packet_set_state(p, USB_PACKET_COMPLETE);
+            if (ret != USB_RET_NAK) {
+                p->result = ret;
+                usb_packet_set_state(p, USB_PACKET_COMPLETE);
+            }
         }
     } else {
         ret = USB_RET_ASYNC;
-- 
1.7.1

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

* [Qemu-devel] [PATCH 03/54] usb-core: Add a usb_ep_find_packet_by_id() helper function
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 01/54] usb: controllers do not need to check for babble themselves Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 02/54] usb-core: Don't set packet state to complete on a nak Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 04/54] usb-core: Allow the first packet of a pipelined ep to complete immediately Gerd Hoffmann
                   ` (51 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede, Gerd Hoffmann

From: Hans de Goede <hdegoede@redhat.com>

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb.h      |    2 ++
 hw/usb/core.c |   15 +++++++++++++++
 2 files changed, 17 insertions(+), 0 deletions(-)

diff --git a/hw/usb.h b/hw/usb.h
index b8fceec..684e3f4 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -377,6 +377,8 @@ void usb_ep_set_max_packet_size(USBDevice *dev, int pid, int ep,
                                 uint16_t raw);
 int usb_ep_get_max_packet_size(USBDevice *dev, int pid, int ep);
 void usb_ep_set_pipeline(USBDevice *dev, int pid, int ep, bool enabled);
+USBPacket *usb_ep_find_packet_by_id(USBDevice *dev, int pid, int ep,
+                                    uint64_t id);
 
 void usb_attach(USBPort *port);
 void usb_detach(USBPort *port);
diff --git a/hw/usb/core.c b/hw/usb/core.c
index be6d936..fe431d0 100644
--- a/hw/usb/core.c
+++ b/hw/usb/core.c
@@ -726,3 +726,18 @@ void usb_ep_set_pipeline(USBDevice *dev, int pid, int ep, bool enabled)
     struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
     uep->pipeline = enabled;
 }
+
+USBPacket *usb_ep_find_packet_by_id(USBDevice *dev, int pid, int ep,
+                                    uint64_t id)
+{
+    struct USBEndpoint *uep = usb_ep_get(dev, pid, ep);
+    USBPacket *p;
+
+    while ((p = QTAILQ_FIRST(&uep->queue)) != NULL) {
+        if (p->id == id) {
+            return p;
+        }
+    }
+
+    return NULL;
+}
-- 
1.7.1

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

* [Qemu-devel] [PATCH 04/54] usb-core: Allow the first packet of a pipelined ep to complete immediately
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (2 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 03/54] usb-core: Add a usb_ep_find_packet_by_id() helper function Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 05/54] Revert "ehci: don't flush cache on doorbell rings." Gerd Hoffmann
                   ` (50 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede, Gerd Hoffmann

From: Hans de Goede <hdegoede@redhat.com>

This can happen with usb-redir live-migration when the packet gets re-queued
after the migration and the original queuing from the migration source side
has already finished.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/core.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/hw/usb/core.c b/hw/usb/core.c
index fe431d0..b9f1f7a 100644
--- a/hw/usb/core.c
+++ b/hw/usb/core.c
@@ -398,7 +398,7 @@ int usb_handle_packet(USBDevice *dev, USBPacket *p)
              * When pipelining is enabled usb-devices must always return async,
              * otherwise packets can complete out of order!
              */
-            assert(!p->ep->pipeline);
+            assert(!p->ep->pipeline || QTAILQ_EMPTY(&p->ep->queue));
             if (ret != USB_RET_NAK) {
                 p->result = ret;
                 usb_packet_set_state(p, USB_PACKET_COMPLETE);
-- 
1.7.1

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

* [Qemu-devel] [PATCH 05/54] Revert "ehci: don't flush cache on doorbell rings."
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (3 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 04/54] usb-core: Allow the first packet of a pipelined ep to complete immediately Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 06/54] ehci: Validate qh is not changed unexpectedly by the guest Gerd Hoffmann
                   ` (49 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede

From: Hans de Goede <hdegoede@redhat.com>

This reverts commit 9bc3a3a216e2689bfcdd36c3e079333bbdbf3ba0, which got
added to fix an issue where the real, underlying cause was not stopping
the ep queue on an error.

Now that the underlying cause is fixed by the "usb: Halt ep queue and
cancel pending packets on a packet error" patch, the "don't flush" fix
is no longer needed.

Not only is it not needed, it causes us to see cancellations (unlinks)
done by the Linux EHCI driver too late, which in combination with the new
usb-core packet-id generation where qtd addresses are used as ids, causes
duplicate ids for in flight packets.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 hw/usb/hcd-ehci.c |   35 ++++++-----------------------------
 1 files changed, 6 insertions(+), 29 deletions(-)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 9523247..e7c36f4 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -365,7 +365,6 @@ struct EHCIQueue {
     uint32_t seen;
     uint64_t ts;
     int async;
-    int revalidate;
 
     /* cached data from guest - needs to be flushed
      * when guest removes an entry (doorbell, handshake sequence)
@@ -805,18 +804,7 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
     return NULL;
 }
 
-static void ehci_queues_tag_unused_async(EHCIState *ehci)
-{
-    EHCIQueue *q;
-
-    QTAILQ_FOREACH(q, &ehci->aqueues, next) {
-        if (!q->seen) {
-            q->revalidate = 1;
-        }
-    }
-}
-
-static void ehci_queues_rip_unused(EHCIState *ehci, int async)
+static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
 {
     EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
     uint64_t maxage = FRAME_TIMER_NS * ehci->maxframes * 4;
@@ -828,7 +816,7 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async)
             q->ts = ehci->last_run_ns;
             continue;
         }
-        if (ehci->last_run_ns < q->ts + maxage) {
+        if (!flush && ehci->last_run_ns < q->ts + maxage) {
             continue;
         }
         ehci_free_queue(q);
@@ -1684,7 +1672,7 @@ static int ehci_state_waitlisthead(EHCIState *ehci,  int async)
         ehci_set_usbsts(ehci, USBSTS_REC);
     }
 
-    ehci_queues_rip_unused(ehci, async);
+    ehci_queues_rip_unused(ehci, async, 0);
 
     /*  Find the head of the list (4.9.1.1) */
     for(i = 0; i < MAX_QH; i++) {
@@ -1769,7 +1757,6 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
     EHCIPacket *p;
     uint32_t entry, devaddr;
     EHCIQueue *q;
-    EHCIqh qh;
 
     entry = ehci_get_fetch_addr(ehci, async);
     q = ehci_find_queue_by_qh(ehci, entry, async);
@@ -1787,17 +1774,7 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
     }
 
     get_dwords(ehci, NLPTR_GET(q->qhaddr),
-               (uint32_t *) &qh, sizeof(EHCIqh) >> 2);
-    if (q->revalidate && (q->qh.epchar      != qh.epchar ||
-                          q->qh.epcap       != qh.epcap  ||
-                          q->qh.current_qtd != qh.current_qtd)) {
-        ehci_free_queue(q);
-        q = ehci_alloc_queue(ehci, entry, async);
-        q->seen++;
-        p = NULL;
-    }
-    q->qh = qh;
-    q->revalidate = 0;
+               (uint32_t *) &q->qh, sizeof(EHCIqh) >> 2);
     ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &q->qh);
 
     devaddr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);
@@ -2306,7 +2283,7 @@ static void ehci_advance_async_state(EHCIState *ehci)
          */
         if (ehci->usbcmd & USBCMD_IAAD) {
             /* Remove all unseen qhs from the async qhs queue */
-            ehci_queues_tag_unused_async(ehci);
+            ehci_queues_rip_unused(ehci, async, 1);
             DPRINTF("ASYNC: doorbell request acknowledged\n");
             ehci->usbcmd &= ~USBCMD_IAAD;
             ehci_raise_irq(ehci, USBSTS_IAA);
@@ -2359,7 +2336,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
         ehci_set_fetch_addr(ehci, async,entry);
         ehci_set_state(ehci, async, EST_FETCHENTRY);
         ehci_advance_state(ehci, async);
-        ehci_queues_rip_unused(ehci, async);
+        ehci_queues_rip_unused(ehci, async, 0);
         break;
 
     default:
-- 
1.7.1

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

* [Qemu-devel] [PATCH 06/54] ehci: Validate qh is not changed unexpectedly by the guest
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (4 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 05/54] Revert "ehci: don't flush cache on doorbell rings." Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 07/54] ehci: Update copyright headers to reflect recent work Gerd Hoffmann
                   ` (48 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede

From: Hans de Goede <hdegoede@redhat.com>

-combine the qh check with the check for devaddr changes
-also ensure that p gets set to NULL when the queue gets cancelled on
 devaddr change, which was not done properly before this patch

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 hw/usb/hcd-ehci.c |   41 +++++++++++++++++++++++++++++------------
 1 files changed, 29 insertions(+), 12 deletions(-)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index e7c36f4..35eb441 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -780,6 +780,14 @@ static void ehci_cancel_queue(EHCIQueue *q)
     } while ((p = QTAILQ_FIRST(&q->packets)) != NULL);
 }
 
+static void ehci_reset_queue(EHCIQueue *q)
+{
+    trace_usb_ehci_queue_action(q, "reset");
+    ehci_cancel_queue(q);
+    q->dev = NULL;
+    q->qtdaddr = 0;
+}
+
 static void ehci_free_queue(EHCIQueue *q)
 {
     EHCIQueueHead *head = q->async ? &q->ehci->aqueues : &q->ehci->pqueues;
@@ -1755,8 +1763,9 @@ out:
 static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
 {
     EHCIPacket *p;
-    uint32_t entry, devaddr;
+    uint32_t entry, devaddr, endp;
     EHCIQueue *q;
+    EHCIqh qh;
 
     entry = ehci_get_fetch_addr(ehci, async);
     q = ehci_find_queue_by_qh(ehci, entry, async);
@@ -1774,17 +1783,25 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
     }
 
     get_dwords(ehci, NLPTR_GET(q->qhaddr),
-               (uint32_t *) &q->qh, sizeof(EHCIqh) >> 2);
-    ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &q->qh);
+               (uint32_t *) &qh, sizeof(EHCIqh) >> 2);
+    ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &qh);
+
+    /*
+     * The overlay area of the qh should never be changed by the guest,
+     * except when idle, in which case the reset is a nop.
+     */
+    devaddr = get_field(qh.epchar, QH_EPCHAR_DEVADDR);
+    endp    = get_field(qh.epchar, QH_EPCHAR_EP);
+    if ((devaddr != get_field(q->qh.epchar, QH_EPCHAR_DEVADDR)) ||
+        (endp    != get_field(q->qh.epchar, QH_EPCHAR_EP)) ||
+        (memcmp(&qh.current_qtd, &q->qh.current_qtd,
+                                 9 * sizeof(uint32_t)) != 0) ||
+        (q->dev != NULL && q->dev->addr != devaddr)) {
+        ehci_reset_queue(q);
+        p = NULL;
+    }
+    q->qh = qh;
 
-    devaddr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);
-    if (q->dev != NULL && q->dev->addr != devaddr) {
-        if (!QTAILQ_EMPTY(&q->packets)) {
-            /* should not happen (guest bug) */
-            ehci_cancel_queue(q);
-        }
-        q->dev = NULL;
-    }
     if (q->dev == NULL) {
         q->dev = ehci_find_device(q->ehci, devaddr);
     }
-- 
1.7.1

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

* [Qemu-devel] [PATCH 07/54] ehci: Update copyright headers to reflect recent work
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (5 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 06/54] ehci: Validate qh is not changed unexpectedly by the guest Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 08/54] ehci: Properly cleanup packets on cancel Gerd Hoffmann
                   ` (47 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede

From: Hans de Goede <hdegoede@redhat.com>

Update copyright headers to reflect all the work Gerd and I have been doing
on the EHCI emulation.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 hw/usb/hcd-ehci.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 35eb441..78a248f 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -2,6 +2,11 @@
  * QEMU USB EHCI Emulation
  *
  * Copyright(c) 2008  Emutex Ltd. (address@hidden)
+ * Copyright(c) 2011-2012 Red Hat, Inc.
+ *
+ * Red Hat Authors:
+ * Gerd Hoffmann <kraxel@redhat.com>
+ * Hans de Goede <hdegoede@redhat.com>
  *
  * EHCI project was started by Mark Burkley, with contributions by
  * Niels de Vos.  David S. Ahern continued working on it.  Kevin Wolf,
-- 
1.7.1

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

* [Qemu-devel] [PATCH 08/54] ehci: Properly cleanup packets on cancel
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (6 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 07/54] ehci: Update copyright headers to reflect recent work Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 09/54] ehci: Properly report completed but not yet processed packets to the guest Gerd Hoffmann
                   ` (46 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede

From: Hans de Goede <hdegoede@redhat.com>

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 hw/usb/hcd-ehci.c |    2 ++
 1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 78a248f..4fe85c8 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -747,6 +747,8 @@ static void ehci_free_packet(EHCIPacket *p)
     trace_usb_ehci_packet_action(p->queue, p, "free");
     if (p->async == EHCI_ASYNC_INFLIGHT) {
         usb_cancel_packet(&p->packet);
+        usb_packet_unmap(&p->packet, &p->sgl);
+        qemu_sglist_destroy(&p->sgl);
     }
     QTAILQ_REMOVE(&p->queue->packets, p, next);
     usb_packet_cleanup(&p->packet);
-- 
1.7.1

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

* [Qemu-devel] [PATCH 09/54] ehci: Properly report completed but not yet processed packets to the guest
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (7 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 08/54] ehci: Properly cleanup packets on cancel Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 10/54] ehci: check for EHCI_ASYNC_FINISHED first in ehci_free_packet Gerd Hoffmann
                   ` (45 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede

From: Hans de Goede <hdegoede@redhat.com>

Reported packets which have completed before being cancelled as such to the
host. Note that the new code path this patch adds is untested since it I've
been unable to actually trigger the race which needs this code path.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
---
 hw/usb/hcd-ehci.c |   13 +++++++++++++
 1 files changed, 13 insertions(+), 0 deletions(-)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 4fe85c8..0a6c9ef 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -489,6 +489,9 @@ static const char *ehci_mmio_names[] = {
     [CONFIGFLAG]        = "CONFIGFLAG",
 };
 
+static int ehci_state_executing(EHCIQueue *q);
+static int ehci_state_writeback(EHCIQueue *q);
+
 static const char *nr2str(const char **n, size_t len, uint32_t nr)
 {
     if (nr < len && n[nr] != NULL) {
@@ -750,6 +753,16 @@ static void ehci_free_packet(EHCIPacket *p)
         usb_packet_unmap(&p->packet, &p->sgl);
         qemu_sglist_destroy(&p->sgl);
     }
+    if (p->async == EHCI_ASYNC_FINISHED) {
+        int state = ehci_get_state(p->queue->ehci, p->queue->async);
+        /* This is a normal, but rare condition (cancel racing completion) */
+        fprintf(stderr, "EHCI: Warning packet completed but not processed\n");
+        ehci_state_executing(p->queue);
+        ehci_state_writeback(p->queue);
+        ehci_set_state(p->queue->ehci, p->queue->async, state);
+        /* state_writeback recurses into us with async == EHCI_ASYNC_NONE!! */
+        return;
+    }
     QTAILQ_REMOVE(&p->queue->packets, p, next);
     usb_packet_cleanup(&p->packet);
     g_free(p);
-- 
1.7.1

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

* [Qemu-devel] [PATCH 10/54] ehci: check for EHCI_ASYNC_FINISHED first in ehci_free_packet
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (8 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 09/54] ehci: Properly report completed but not yet processed packets to the guest Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 11/54] ehci: trace guest bugs Gerd Hoffmann
                   ` (44 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Otherwise we'll see the packet free twice in the trace log even though
it actually happens only once.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-ehci.c |   12 ++++++------
 1 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 0a6c9ef..23221d0 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -747,12 +747,6 @@ static EHCIPacket *ehci_alloc_packet(EHCIQueue *q)
 
 static void ehci_free_packet(EHCIPacket *p)
 {
-    trace_usb_ehci_packet_action(p->queue, p, "free");
-    if (p->async == EHCI_ASYNC_INFLIGHT) {
-        usb_cancel_packet(&p->packet);
-        usb_packet_unmap(&p->packet, &p->sgl);
-        qemu_sglist_destroy(&p->sgl);
-    }
     if (p->async == EHCI_ASYNC_FINISHED) {
         int state = ehci_get_state(p->queue->ehci, p->queue->async);
         /* This is a normal, but rare condition (cancel racing completion) */
@@ -763,6 +757,12 @@ static void ehci_free_packet(EHCIPacket *p)
         /* state_writeback recurses into us with async == EHCI_ASYNC_NONE!! */
         return;
     }
+    trace_usb_ehci_packet_action(p->queue, p, "free");
+    if (p->async == EHCI_ASYNC_INFLIGHT) {
+        usb_cancel_packet(&p->packet);
+        usb_packet_unmap(&p->packet, &p->sgl);
+        qemu_sglist_destroy(&p->sgl);
+    }
     QTAILQ_REMOVE(&p->queue->packets, p, next);
     usb_packet_cleanup(&p->packet);
     g_free(p);
-- 
1.7.1

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

* [Qemu-devel] [PATCH 11/54] ehci: trace guest bugs
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (9 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 10/54] ehci: check for EHCI_ASYNC_FINISHED first in ehci_free_packet Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 12/54] ehci: add doorbell trace events Gerd Hoffmann
                   ` (43 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

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>
---
 hw/usb/hcd-ehci.c |   26 ++++++++++++++++++++------
 trace-events      |    1 +
 2 files changed, 21 insertions(+), 6 deletions(-)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 23221d0..4564615 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -716,6 +716,12 @@ static void ehci_trace_sitd(EHCIState *s, target_phys_addr_t addr,
                         (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;
@@ -785,27 +791,33 @@ static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, uint32_t addr, int async)
     return q;
 }
 
-static void ehci_cancel_queue(EHCIQueue *q)
+static int ehci_cancel_queue(EHCIQueue *q)
 {
     EHCIPacket *p;
+    int packets = 0;
 
     p = QTAILQ_FIRST(&q->packets);
     if (p == NULL) {
-        return;
+        return 0;
     }
 
     trace_usb_ehci_queue_action(q, "cancel");
     do {
         ehci_free_packet(p);
+        packets++;
     } while ((p = QTAILQ_FIRST(&q->packets)) != NULL);
+    return packets;
 }
 
-static void ehci_reset_queue(EHCIQueue *q)
+static int ehci_reset_queue(EHCIQueue *q)
 {
+    int packets;
+
     trace_usb_ehci_queue_action(q, "reset");
-    ehci_cancel_queue(q);
+    packets = ehci_cancel_queue(q);
     q->dev = NULL;
     q->qtdaddr = 0;
+    return packets;
 }
 
 static void ehci_free_queue(EHCIQueue *q)
@@ -1817,7 +1829,9 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
         (memcmp(&qh.current_qtd, &q->qh.current_qtd,
                                  9 * sizeof(uint32_t)) != 0) ||
         (q->dev != NULL && q->dev->addr != devaddr)) {
-        ehci_reset_queue(q);
+        if (ehci_reset_queue(q) > 0) {
+            ehci_trace_guest_bug(ehci, "guest updated active QH");
+        }
         p = NULL;
     }
     q->qh = qh;
@@ -1979,8 +1993,8 @@ static int ehci_state_fetchqtd(EHCIQueue *q)
             (!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_cancel_queue(q);
+            ehci_trace_guest_bug(q->ehci, "guest updated active QH or qTD");
             p = NULL;
         } else {
             p->qtd = qtd;
diff --git a/trace-events b/trace-events
index 04b0723..0c7ffc7 100644
--- a/trace-events
+++ b/trace-events
@@ -263,6 +263,7 @@ usb_ehci_data(int rw, uint32_t cpage, uint32_t offset, uint32_t addr, uint32_t l
 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 ==="
-- 
1.7.1

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

* [Qemu-devel] [PATCH 12/54] ehci: add doorbell trace events
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (10 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 11/54] ehci: trace guest bugs Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 13/54] ehci: Add some additional ehci_trace_guest_bug() calls Gerd Hoffmann
                   ` (42 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-ehci.c |    3 ++-
 trace-events      |    2 ++
 2 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 4564615..398f5e0 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -1241,6 +1241,7 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
              */
             s->async_stepdown = 0;
             qemu_bh_schedule(s->async_bh);
+            trace_usb_ehci_doorbell_ring();
         }
 
         if (((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & val) !=
@@ -2335,7 +2336,7 @@ static void ehci_advance_async_state(EHCIState *ehci)
         if (ehci->usbcmd & USBCMD_IAAD) {
             /* Remove all unseen qhs from the async qhs queue */
             ehci_queues_rip_unused(ehci, async, 1);
-            DPRINTF("ASYNC: doorbell request acknowledged\n");
+            trace_usb_ehci_doorbell_ack();
             ehci->usbcmd &= ~USBCMD_IAAD;
             ehci_raise_irq(ehci, USBSTS_IAA);
         }
diff --git a/trace-events b/trace-events
index 0c7ffc7..8dc4f45 100644
--- a/trace-events
+++ b/trace-events
@@ -264,6 +264,8 @@ 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"
+usb_ehci_doorbell_ring(void) ""
+usb_ehci_doorbell_ack(void) ""
 
 # hw/usb/hcd-uhci.c
 usb_uhci_reset(void) "=== RESET ==="
-- 
1.7.1

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

* [Qemu-devel] [PATCH 13/54] ehci: Add some additional ehci_trace_guest_bug() calls
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (11 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 12/54] ehci: add doorbell trace events Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 14/54] ehci: Fix memory leak in handling of NAK-ed packets Gerd Hoffmann
                   ` (41 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede, Gerd Hoffmann

From: Hans de Goede <hdegoede@redhat.com>

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-ehci.c |   19 +++++++++++++------
 1 files changed, 13 insertions(+), 6 deletions(-)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 398f5e0..5a88268 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -820,12 +820,16 @@ static int ehci_reset_queue(EHCIQueue *q)
     return packets;
 }
 
-static void ehci_free_queue(EHCIQueue *q)
+static void ehci_free_queue(EHCIQueue *q, const char *warn)
 {
     EHCIQueueHead *head = q->async ? &q->ehci->aqueues : &q->ehci->pqueues;
+    int cancelled;
 
     trace_usb_ehci_queue_action(q, "free");
-    ehci_cancel_queue(q);
+    cancelled = ehci_cancel_queue(q);
+    if (warn && cancelled > 0) {
+        ehci_trace_guest_bug(q->ehci, warn);
+    }
     QTAILQ_REMOVE(head, q, next);
     g_free(q);
 }
@@ -847,6 +851,7 @@ static EHCIQueue *ehci_find_queue_by_qh(EHCIState *ehci, uint32_t addr,
 static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
 {
     EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
+    const char *warn = (async && !flush) ? "guest unlinked busy QH" : NULL;
     uint64_t maxage = FRAME_TIMER_NS * ehci->maxframes * 4;
     EHCIQueue *q, *tmp;
 
@@ -859,7 +864,7 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
         if (!flush && ehci->last_run_ns < q->ts + maxage) {
             continue;
         }
-        ehci_free_queue(q);
+        ehci_free_queue(q, warn);
     }
 }
 
@@ -872,17 +877,18 @@ static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
         if (q->dev != dev) {
             continue;
         }
-        ehci_free_queue(q);
+        ehci_free_queue(q, NULL);
     }
 }
 
 static void ehci_queues_rip_all(EHCIState *ehci, int async)
 {
     EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
+    const char *warn = async ? "guest stopped busy async schedule" : NULL;
     EHCIQueue *q, *tmp;
 
     QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
-        ehci_free_queue(q);
+        ehci_free_queue(q, warn);
     }
 }
 
@@ -1549,7 +1555,8 @@ static int ehci_execute(EHCIPacket *p, const char *action)
 
     p->tbytes = (p->qtd.token & QTD_TOKEN_TBYTES_MASK) >> QTD_TOKEN_TBYTES_SH;
     if (p->tbytes > BUFF_SIZE) {
-        fprintf(stderr, "Request for more bytes than allowed\n");
+        ehci_trace_guest_bug(p->queue->ehci,
+                             "guest requested more bytes than allowed");
         return USB_RET_PROCERR;
     }
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH 14/54] ehci: Fix memory leak in handling of NAK-ed packets
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (12 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 13/54] ehci: Add some additional ehci_trace_guest_bug() calls Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 15/54] ehci: Handle USB_RET_PROCERR in ehci_fill_queue Gerd Hoffmann
                   ` (40 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede, Gerd Hoffmann

From: Hans de Goede <hdegoede@redhat.com>

Currently each time we try to execute a NAK-ed packet we redo
ehci_init_transfer, and usb_packet_map, re-allocing (without freeing) the
sg list every time.

This patch fixes this, it does this by introducing another async state, so
that we also properly cleanup a NAK-ed packet on cancel.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-ehci.c |   38 +++++++++++++++++++++++++++-----------
 1 files changed, 27 insertions(+), 11 deletions(-)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 5a88268..d87aca8 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -345,6 +345,7 @@ typedef struct EHCIState EHCIState;
 
 enum async_state {
     EHCI_ASYNC_NONE = 0,
+    EHCI_ASYNC_INITIALIZED,
     EHCI_ASYNC_INFLIGHT,
     EHCI_ASYNC_FINISHED,
 };
@@ -764,6 +765,10 @@ static void ehci_free_packet(EHCIPacket *p)
         return;
     }
     trace_usb_ehci_packet_action(p->queue, p, "free");
+    if (p->async == EHCI_ASYNC_INITIALIZED) {
+        usb_packet_unmap(&p->packet, &p->sgl);
+        qemu_sglist_destroy(&p->sgl);
+    }
     if (p->async == EHCI_ASYNC_INFLIGHT) {
         usb_cancel_packet(&p->packet);
         usb_packet_unmap(&p->packet, &p->sgl);
@@ -1485,8 +1490,8 @@ static void ehci_execute_complete(EHCIQueue *q)
 
     assert(p != NULL);
     assert(p->qtdaddr == q->qtdaddr);
-    assert(p->async != EHCI_ASYNC_INFLIGHT);
-    p->async = EHCI_ASYNC_NONE;
+    assert(p->async == EHCI_ASYNC_INITIALIZED ||
+           p->async == EHCI_ASYNC_FINISHED);
 
     DPRINTF("execute_complete: qhaddr 0x%x, next %x, qtdaddr 0x%x, status %d\n",
             q->qhaddr, q->qh.next, q->qtdaddr, q->usb_status);
@@ -1531,6 +1536,7 @@ static void ehci_execute_complete(EHCIQueue *q)
     ehci_finish_transfer(q, p->usb_status);
     usb_packet_unmap(&p->packet, &p->sgl);
     qemu_sglist_destroy(&p->sgl);
+    p->async = EHCI_ASYNC_NONE;
 
     q->qh.token ^= QTD_TOKEN_DTOGGLE;
     q->qh.token &= ~QTD_TOKEN_ACTIVE;
@@ -1548,6 +1554,9 @@ static int ehci_execute(EHCIPacket *p, const char *action)
     int ret;
     int endp;
 
+    assert(p->async == EHCI_ASYNC_NONE ||
+           p->async == EHCI_ASYNC_INITIALIZED);
+
     if (!(p->qtd.token & QTD_TOKEN_ACTIVE)) {
         fprintf(stderr, "Attempting to execute inactive qtd\n");
         return USB_RET_PROCERR;
@@ -1576,15 +1585,18 @@ static int ehci_execute(EHCIPacket *p, const char *action)
         break;
     }
 
-    if (ehci_init_transfer(p) != 0) {
-        return USB_RET_PROCERR;
-    }
-
     endp = get_field(p->queue->qh.epchar, QH_EPCHAR_EP);
     ep = usb_ep_get(p->queue->dev, p->pid, endp);
 
-    usb_packet_setup(&p->packet, p->pid, ep, p->qtdaddr);
-    usb_packet_map(&p->packet, &p->sgl);
+    if (p->async == EHCI_ASYNC_NONE) {
+        if (ehci_init_transfer(p) != 0) {
+            return USB_RET_PROCERR;
+        }
+
+        usb_packet_setup(&p->packet, p->pid, ep, p->qtdaddr);
+        usb_packet_map(&p->packet, &p->sgl);
+        p->async = EHCI_ASYNC_INITIALIZED;
+    }
 
     trace_usb_ehci_packet_action(p->queue, p, action);
     ret = usb_handle_packet(p->queue->dev, &p->packet);
@@ -2021,11 +2033,15 @@ static int ehci_state_fetchqtd(EHCIQueue *q)
     } else if (p != NULL) {
         switch (p->async) {
         case EHCI_ASYNC_NONE:
+            /* Should never happen packet should at least be initialized */
+            assert(0);
+            break;
+        case EHCI_ASYNC_INITIALIZED:
             /* Previously nacked packet (likely interrupt ep) */
-           ehci_set_state(q->ehci, q->async, EST_EXECUTE);
-           break;
+            ehci_set_state(q->ehci, q->async, EST_EXECUTE);
+            break;
         case EHCI_ASYNC_INFLIGHT:
-            /* Unfinyshed async handled packet, go horizontal */
+            /* Unfinished async handled packet, go horizontal */
             ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
             break;
         case EHCI_ASYNC_FINISHED:
-- 
1.7.1

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

* [Qemu-devel] [PATCH 15/54] ehci: Handle USB_RET_PROCERR in ehci_fill_queue
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (13 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 14/54] ehci: Fix memory leak in handling of NAK-ed packets Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 16/54] ehci: Correct a comment in fetchqtd packet processing Gerd Hoffmann
                   ` (39 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede, Gerd Hoffmann

From: Hans de Goede <hdegoede@redhat.com>

USB_RET_PROCERR can be triggered by the guest (by for example requesting more
then BUFFSIZE bytes), so don't assert on it.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-ehci.c |    9 ++++++---
 1 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index d87aca8..2534394 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -2076,7 +2076,7 @@ static int ehci_state_horizqh(EHCIQueue *q)
     return again;
 }
 
-static void ehci_fill_queue(EHCIPacket *p)
+static int ehci_fill_queue(EHCIPacket *p)
 {
     EHCIQueue *q = p->queue;
     EHCIqtd qtd = p->qtd;
@@ -2100,9 +2100,13 @@ static void ehci_fill_queue(EHCIPacket *p)
         p->qtdaddr = qtdaddr;
         p->qtd = qtd;
         p->usb_status = ehci_execute(p, "queue");
+        if (p->usb_status == USB_RET_PROCERR) {
+            break;
+        }
         assert(p->usb_status == USB_RET_ASYNC);
         p->async = EHCI_ASYNC_INFLIGHT;
     }
+    return p->usb_status;
 }
 
 static int ehci_state_execute(EHCIQueue *q)
@@ -2144,8 +2148,7 @@ static int ehci_state_execute(EHCIQueue *q)
         trace_usb_ehci_packet_action(p->queue, p, "async");
         p->async = EHCI_ASYNC_INFLIGHT;
         ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
-        again = 1;
-        ehci_fill_queue(p);
+        again = (ehci_fill_queue(p) == USB_RET_PROCERR) ? -1 : 1;
         goto out;
     }
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH 16/54] ehci: Correct a comment in fetchqtd packet processing
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (14 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 15/54] ehci: Handle USB_RET_PROCERR in ehci_fill_queue Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 17/54] usb-redir: Never return USB_RET_NAK for async handled packets Gerd Hoffmann
                   ` (38 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede, Gerd Hoffmann

From: Hans de Goede <hdegoede@redhat.com>

Since my previous comment said "Should never happen", I tried changing the
next line to an assert(0), which did not go well, which as the new comments
explains is logical if you think about it for a moment.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-ehci.c |    5 ++++-
 1 files changed, 4 insertions(+), 1 deletions(-)

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 2534394..2f3e9c0 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -2045,7 +2045,10 @@ static int ehci_state_fetchqtd(EHCIQueue *q)
             ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
             break;
         case EHCI_ASYNC_FINISHED:
-            /* Should never happen, as this case is caught by fetchqh */
+            /*
+             * We get here when advqueue moves to a packet which is already
+             * finished, which can happen with packets queued up by fill_queue
+             */
             ehci_set_state(q->ehci, q->async, EST_EXECUTING);
             break;
         }
-- 
1.7.1

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

* [Qemu-devel] [PATCH 17/54] usb-redir: Never return USB_RET_NAK for async handled packets
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (15 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 16/54] ehci: Correct a comment in fetchqtd packet processing Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 18/54] usb-redir: Don't delay handling of open events to a bottom half Gerd Hoffmann
                   ` (37 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede, Gerd Hoffmann

From: Hans de Goede <hdegoede@redhat.com>

USB_RET_NAK is not a valid response for async handled packets (and will
trigger an assert as such).

Also drop the warning when receiving a status of cancelled for packets not
cancelled by qemu itself, this can happen when a device gets unredirected
by the usbredir-host while transfers are pending.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/redirect.c |    9 ++++++---
 1 files changed, 6 insertions(+), 3 deletions(-)

diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 10b4fbb..7f3719b 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -1028,11 +1028,14 @@ static int usbredir_handle_status(USBRedirDevice *dev,
     case usb_redir_stall:
         return USB_RET_STALL;
     case usb_redir_cancelled:
-        WARNING("returning cancelled packet to HC?\n");
-        return USB_RET_NAK;
+        /*
+         * When the usbredir-host unredirects a device, it will report a status
+         * of cancelled for all pending packets, followed by a disconnect msg.
+         */
+        return USB_RET_IOERROR;
     case usb_redir_inval:
         WARNING("got invalid param error from usb-host?\n");
-        return USB_RET_NAK;
+        return USB_RET_IOERROR;
     case usb_redir_babble:
         return USB_RET_BABBLE;
     case usb_redir_ioerror:
-- 
1.7.1

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

* [Qemu-devel] [PATCH 18/54] usb-redir: Don't delay handling of open events to a bottom half
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (16 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 17/54] usb-redir: Never return USB_RET_NAK for async handled packets Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 19/54] usb-redir: Get rid of async-struct get member Gerd Hoffmann
                   ` (36 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede, Gerd Hoffmann

From: Hans de Goede <hdegoede@redhat.com>

There is no need for this, and doing so means that a backend trying to
write immediately after an open event will see qemu_chr_be_can_write
returning 0, which not all backends handle well as there is no wakeup
mechanism to detect when the frontend does become writable.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/redirect.c |  100 ++++++++++++++++++++++++++++-------------------------
 1 files changed, 53 insertions(+), 47 deletions(-)

diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 7f3719b..5cc3334 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -79,8 +79,8 @@ struct USBRedirDevice {
     /* Data passed from chardev the fd_read cb to the usbredirparser read cb */
     const uint8_t *read_buf;
     int read_buf_size;
-    /* For async handling of open/close */
-    QEMUBH *open_close_bh;
+    /* For async handling of close */
+    QEMUBH *chardev_close_bh;
     /* To delay the usb attach in case of quick chardev close + open */
     QEMUTimer *attach_timer;
     int64_t next_attach_time;
@@ -784,18 +784,11 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
  * from within the USBDevice data / control packet callbacks and doing a
  * usb_detach from within these callbacks is not a good idea.
  *
- * So we use a bh handler to take care of close events. We also handle
- * open events from this callback to make sure that a close directly followed
- * by an open gets handled in the right order.
+ * So we use a bh handler to take care of close events.
  */
-static void usbredir_open_close_bh(void *opaque)
+static void usbredir_chardev_close_bh(void *opaque)
 {
     USBRedirDevice *dev = opaque;
-    uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, };
-    char version[32];
-
-    strcpy(version, "qemu usb-redir guest ");
-    pstrcat(version, sizeof(version), qemu_get_version());
 
     usbredir_device_disconnect(dev);
 
@@ -803,36 +796,47 @@ static void usbredir_open_close_bh(void *opaque)
         usbredirparser_destroy(dev->parser);
         dev->parser = NULL;
     }
+}
 
-    if (dev->cs->opened) {
-        dev->parser = qemu_oom_check(usbredirparser_create());
-        dev->parser->priv = dev;
-        dev->parser->log_func = usbredir_log;
-        dev->parser->read_func = usbredir_read;
-        dev->parser->write_func = usbredir_write;
-        dev->parser->hello_func = usbredir_hello;
-        dev->parser->device_connect_func = usbredir_device_connect;
-        dev->parser->device_disconnect_func = usbredir_device_disconnect;
-        dev->parser->interface_info_func = usbredir_interface_info;
-        dev->parser->ep_info_func = usbredir_ep_info;
-        dev->parser->configuration_status_func = usbredir_configuration_status;
-        dev->parser->alt_setting_status_func = usbredir_alt_setting_status;
-        dev->parser->iso_stream_status_func = usbredir_iso_stream_status;
-        dev->parser->interrupt_receiving_status_func =
-            usbredir_interrupt_receiving_status;
-        dev->parser->bulk_streams_status_func = usbredir_bulk_streams_status;
-        dev->parser->control_packet_func = usbredir_control_packet;
-        dev->parser->bulk_packet_func = usbredir_bulk_packet;
-        dev->parser->iso_packet_func = usbredir_iso_packet;
-        dev->parser->interrupt_packet_func = usbredir_interrupt_packet;
-        dev->read_buf = NULL;
-        dev->read_buf_size = 0;
+static void usbredir_chardev_open(USBRedirDevice *dev)
+{
+    uint32_t caps[USB_REDIR_CAPS_SIZE] = { 0, };
+    char version[32];
 
-        usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version);
-        usbredirparser_caps_set_cap(caps, usb_redir_cap_filter);
-        usbredirparser_init(dev->parser, version, caps, USB_REDIR_CAPS_SIZE, 0);
-        usbredirparser_do_write(dev->parser);
-    }
+    /* Make sure any pending closes are handled (no-op if none pending) */
+    usbredir_chardev_close_bh(dev);
+    qemu_bh_cancel(dev->chardev_close_bh);
+
+    strcpy(version, "qemu usb-redir guest ");
+    pstrcat(version, sizeof(version), qemu_get_version());
+
+    dev->parser = qemu_oom_check(usbredirparser_create());
+    dev->parser->priv = dev;
+    dev->parser->log_func = usbredir_log;
+    dev->parser->read_func = usbredir_read;
+    dev->parser->write_func = usbredir_write;
+    dev->parser->hello_func = usbredir_hello;
+    dev->parser->device_connect_func = usbredir_device_connect;
+    dev->parser->device_disconnect_func = usbredir_device_disconnect;
+    dev->parser->interface_info_func = usbredir_interface_info;
+    dev->parser->ep_info_func = usbredir_ep_info;
+    dev->parser->configuration_status_func = usbredir_configuration_status;
+    dev->parser->alt_setting_status_func = usbredir_alt_setting_status;
+    dev->parser->iso_stream_status_func = usbredir_iso_stream_status;
+    dev->parser->interrupt_receiving_status_func =
+        usbredir_interrupt_receiving_status;
+    dev->parser->bulk_streams_status_func = usbredir_bulk_streams_status;
+    dev->parser->control_packet_func = usbredir_control_packet;
+    dev->parser->bulk_packet_func = usbredir_bulk_packet;
+    dev->parser->iso_packet_func = usbredir_iso_packet;
+    dev->parser->interrupt_packet_func = usbredir_interrupt_packet;
+    dev->read_buf = NULL;
+    dev->read_buf_size = 0;
+
+    usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version);
+    usbredirparser_caps_set_cap(caps, usb_redir_cap_filter);
+    usbredirparser_init(dev->parser, version, caps, USB_REDIR_CAPS_SIZE, 0);
+    usbredirparser_do_write(dev->parser);
 }
 
 static void usbredir_do_attach(void *opaque)
@@ -856,13 +860,13 @@ static int usbredir_chardev_can_read(void *opaque)
 {
     USBRedirDevice *dev = opaque;
 
-    if (dev->parser) {
-        /* usbredir_parser_do_read will consume *all* data we give it */
-        return 1024 * 1024;
-    } else {
-        /* usbredir_open_close_bh hasn't handled the open event yet */
+    if (!dev->parser) {
+        WARNING("chardev_can_read called on non open chardev!\n");
         return 0;
     }
+
+    /* usbredir_parser_do_read will consume *all* data we give it */
+    return 1024 * 1024;
 }
 
 static void usbredir_chardev_read(void *opaque, const uint8_t *buf, int size)
@@ -886,8 +890,10 @@ static void usbredir_chardev_event(void *opaque, int event)
 
     switch (event) {
     case CHR_EVENT_OPENED:
+        usbredir_chardev_open(dev);
+        break;
     case CHR_EVENT_CLOSED:
-        qemu_bh_schedule(dev->open_close_bh);
+        qemu_bh_schedule(dev->chardev_close_bh);
         break;
     }
 }
@@ -917,7 +923,7 @@ static int usbredir_initfn(USBDevice *udev)
         }
     }
 
-    dev->open_close_bh = qemu_bh_new(usbredir_open_close_bh, dev);
+    dev->chardev_close_bh = qemu_bh_new(usbredir_chardev_close_bh, dev);
     dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev);
 
     QTAILQ_INIT(&dev->asyncq);
@@ -957,7 +963,7 @@ static void usbredir_handle_destroy(USBDevice *udev)
     qemu_chr_fe_close(dev->cs);
     qemu_chr_delete(dev->cs);
     /* Note must be done after qemu_chr_close, as that causes a close event */
-    qemu_bh_delete(dev->open_close_bh);
+    qemu_bh_delete(dev->chardev_close_bh);
 
     qemu_del_timer(dev->attach_timer);
     qemu_free_timer(dev->attach_timer);
-- 
1.7.1

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

* [Qemu-devel] [PATCH 19/54] usb-redir: Get rid of async-struct get member
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (17 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 18/54] usb-redir: Don't delay handling of open events to a bottom half Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 20/54] usb-redir: Get rid of local shadow copy of packet headers Gerd Hoffmann
                   ` (35 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede, Gerd Hoffmann

From: Hans de Goede <hdegoede@redhat.com>

This is a preparation patch for completely getting rid of the async-packet
struct in usb-redir, instead relying on the (new) per ep queues in the
qemu usb core.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/redirect.c |    9 +++------
 1 files changed, 3 insertions(+), 6 deletions(-)

diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 5cc3334..2cae8c5 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -1,7 +1,7 @@
 /*
  * USB redirector usb-guest
  *
- * Copyright (c) 2011 Red Hat, Inc.
+ * Copyright (c) 2011-2012 Red Hat, Inc.
  *
  * Red Hat Authors:
  * Hans de Goede <hdegoede@redhat.com>
@@ -99,7 +99,6 @@ struct AsyncURB {
     USBRedirDevice *dev;
     USBPacket *packet;
     uint32_t packet_id;
-    int get;
     union {
         struct usb_redir_control_packet_header control_packet;
         struct usb_redir_bulk_packet_header bulk_packet;
@@ -672,7 +671,6 @@ static int usbredir_get_config(USBRedirDevice *dev, USBPacket *p)
 
     DPRINTF("get config id %u\n", aurb->packet_id);
 
-    aurb->get = 1;
     usbredirparser_send_get_configuration(dev->parser, aurb->packet_id);
     usbredirparser_do_write(dev->parser);
     return USB_RET_ASYNC;
@@ -721,7 +719,6 @@ static int usbredir_get_interface(USBRedirDevice *dev, USBPacket *p,
     DPRINTF("get interface %d id %u\n", interface, aurb->packet_id);
 
     get_alt.interface = interface;
-    aurb->get = 1;
     usbredirparser_send_get_alt_setting(dev->parser, aurb->packet_id,
                                         &get_alt);
     usbredirparser_do_write(dev->parser);
@@ -1226,7 +1223,7 @@ static void usbredir_configuration_status(void *priv, uint32_t id,
         return;
     }
     if (aurb->packet) {
-        if (aurb->get) {
+        if (dev->dev.setup_buf[0] & USB_DIR_IN) {
             dev->dev.data_buf[0] = config_status->configuration;
             len = 1;
         }
@@ -1254,7 +1251,7 @@ static void usbredir_alt_setting_status(void *priv, uint32_t id,
         return;
     }
     if (aurb->packet) {
-        if (aurb->get) {
+        if (dev->dev.setup_buf[0] & USB_DIR_IN) {
             dev->dev.data_buf[0] = alt_setting_status->alt;
             len = 1;
         }
-- 
1.7.1

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

* [Qemu-devel] [PATCH 20/54] usb-redir: Get rid of local shadow copy of packet headers
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (18 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 19/54] usb-redir: Get rid of async-struct get member Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 21/54] usb-redir: Get rid of unused async-struct dev member Gerd Hoffmann
                   ` (34 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede, Gerd Hoffmann

From: Hans de Goede <hdegoede@redhat.com>

The shadow copy only serves as an extra check (besides the packet-id) to
ensure the packet we get back is a reply to the packet we think it is.

This check has never triggered in all the time usb-redir is in use now,
and since the verified data in the returned packet-header is not used
otherwise, removing the check does not open any possibilities for the
usbredirhost to confuse us.

This is a preparation patch for completely getting rid of the async-packet
struct in usb-redir, instead relying on the (new) per ep queues in the
qemu usb core.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/redirect.c |   27 ---------------------------
 1 files changed, 0 insertions(+), 27 deletions(-)

diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 2cae8c5..e4ef372 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -99,11 +99,6 @@ struct AsyncURB {
     USBRedirDevice *dev;
     USBPacket *packet;
     uint32_t packet_id;
-    union {
-        struct usb_redir_control_packet_header control_packet;
-        struct usb_redir_bulk_packet_header bulk_packet;
-        struct usb_redir_interrupt_packet_header interrupt_packet;
-    };
     QTAILQ_ENTRY(AsyncURB)next;
 };
 
@@ -500,7 +495,6 @@ static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
     bulk_packet.endpoint  = ep;
     bulk_packet.length    = p->iov.size;
     bulk_packet.stream_id = 0;
-    aurb->bulk_packet = bulk_packet;
 
     if (ep & USB_DIR_IN) {
         usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id,
@@ -581,7 +575,6 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
 
         interrupt_packet.endpoint  = ep;
         interrupt_packet.length    = p->iov.size;
-        aurb->interrupt_packet     = interrupt_packet;
 
         usb_packet_copy(p, buf, p->iov.size);
         usbredir_log_data(dev, "interrupt data out:", buf, p->iov.size);
@@ -762,7 +755,6 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
     control_packet.value       = value;
     control_packet.index       = index;
     control_packet.length      = length;
-    aurb->control_packet       = control_packet;
 
     if (control_packet.requesttype & USB_DIR_IN) {
         usbredirparser_send_control_packet(dev->parser, aurb->packet_id,
@@ -1326,14 +1318,6 @@ static void usbredir_control_packet(void *priv, uint32_t id,
         return;
     }
 
-    aurb->control_packet.status = control_packet->status;
-    aurb->control_packet.length = control_packet->length;
-    if (memcmp(&aurb->control_packet, control_packet,
-               sizeof(*control_packet))) {
-        ERROR("return control packet mismatch, please report this!\n");
-        len = USB_RET_NAK;
-    }
-
     if (aurb->packet) {
         len = usbredir_handle_status(dev, control_packet->status, len);
         if (len > 0) {
@@ -1371,12 +1355,6 @@ static void usbredir_bulk_packet(void *priv, uint32_t id,
         return;
     }
 
-    if (aurb->bulk_packet.endpoint != bulk_packet->endpoint ||
-            aurb->bulk_packet.stream_id != bulk_packet->stream_id) {
-        ERROR("return bulk packet mismatch, please report this!\n");
-        len = USB_RET_NAK;
-    }
-
     if (aurb->packet) {
         len = usbredir_handle_status(dev, bulk_packet->status, len);
         if (len > 0) {
@@ -1455,11 +1433,6 @@ static void usbredir_interrupt_packet(void *priv, uint32_t id,
             return;
         }
 
-        if (aurb->interrupt_packet.endpoint != interrupt_packet->endpoint) {
-            ERROR("return int packet mismatch, please report this!\n");
-            len = USB_RET_NAK;
-        }
-
         if (aurb->packet) {
             aurb->packet->result = usbredir_handle_status(dev,
                                                interrupt_packet->status, len);
-- 
1.7.1

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

* [Qemu-devel] [PATCH 21/54] usb-redir: Get rid of unused async-struct dev member
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (19 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 20/54] usb-redir: Get rid of local shadow copy of packet headers Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 22/54] usb-redir: Move to core packet id and queue handling Gerd Hoffmann
                   ` (33 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede, Gerd Hoffmann

From: Hans de Goede <hdegoede@redhat.com>

This is a preparation patch for completely getting rid of the async-packet
struct in usb-redir, instead relying on the (new) per ep queues in the
qemu usb core.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/redirect.c |    2 --
 1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index e4ef372..6593d50 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -96,7 +96,6 @@ struct USBRedirDevice {
 };
 
 struct AsyncURB {
-    USBRedirDevice *dev;
     USBPacket *packet;
     uint32_t packet_id;
     QTAILQ_ENTRY(AsyncURB)next;
@@ -245,7 +244,6 @@ static int usbredir_write(void *priv, uint8_t *data, int count)
 static AsyncURB *async_alloc(USBRedirDevice *dev, USBPacket *p)
 {
     AsyncURB *aurb = (AsyncURB *) g_malloc0(sizeof(AsyncURB));
-    aurb->dev = dev;
     aurb->packet = p;
     aurb->packet_id = dev->packet_id;
     QTAILQ_INSERT_TAIL(&dev->asyncq, aurb, next);
-- 
1.7.1

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

* [Qemu-devel] [PATCH 22/54] usb-redir: Move to core packet id and queue handling
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (20 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 21/54] usb-redir: Get rid of unused async-struct dev member Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 23/54] usb-redir: Return babble when getting more bulk data then requested Gerd Hoffmann
                   ` (32 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede, Gerd Hoffmann

From: Hans de Goede <hdegoede@redhat.com>

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/redirect.c |  226 ++++++++++++++++++++++-------------------------------
 1 files changed, 92 insertions(+), 134 deletions(-)

diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 6593d50..fd1f8cc 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -43,7 +43,7 @@
 #define EP2I(ep_address) (((ep_address & 0x80) >> 3) | (ep_address & 0x0f))
 #define I2EP(i) (((i & 0x10) << 3) | (i & 0x0f))
 
-typedef struct AsyncURB AsyncURB;
+typedef struct Cancelled Cancelled;
 typedef struct USBRedirDevice USBRedirDevice;
 
 /* Struct to hold buffered packets (iso or int input packets) */
@@ -86,8 +86,7 @@ struct USBRedirDevice {
     int64_t next_attach_time;
     struct usbredirparser *parser;
     struct endp_data endpoint[MAX_ENDPOINTS];
-    uint32_t packet_id;
-    QTAILQ_HEAD(, AsyncURB) asyncq;
+    QTAILQ_HEAD(, Cancelled) cancelled;
     /* Data for device filtering */
     struct usb_redir_device_connect_header device_info;
     struct usb_redir_interface_info_header interface_info;
@@ -95,10 +94,9 @@ struct USBRedirDevice {
     int filter_rules_count;
 };
 
-struct AsyncURB {
-    USBPacket *packet;
-    uint32_t packet_id;
-    QTAILQ_ENTRY(AsyncURB)next;
+struct Cancelled {
+    uint64_t id;
+    QTAILQ_ENTRY(Cancelled)next;
 };
 
 static void usbredir_hello(void *priv, struct usb_redir_hello_header *h);
@@ -238,57 +236,58 @@ static int usbredir_write(void *priv, uint8_t *data, int count)
 }
 
 /*
- * Async and buffered packets helpers
+ * Cancelled and buffered packets helpers
  */
 
-static AsyncURB *async_alloc(USBRedirDevice *dev, USBPacket *p)
+static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p)
 {
-    AsyncURB *aurb = (AsyncURB *) g_malloc0(sizeof(AsyncURB));
-    aurb->packet = p;
-    aurb->packet_id = dev->packet_id;
-    QTAILQ_INSERT_TAIL(&dev->asyncq, aurb, next);
-    dev->packet_id++;
+    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
+    Cancelled *c;
 
-    return aurb;
-}
+    DPRINTF("cancel packet id %"PRIu64"\n", p->id);
 
-static void async_free(USBRedirDevice *dev, AsyncURB *aurb)
-{
-    QTAILQ_REMOVE(&dev->asyncq, aurb, next);
-    g_free(aurb);
+    c = g_malloc0(sizeof(Cancelled));
+    c->id = p->id;
+    QTAILQ_INSERT_TAIL(&dev->cancelled, c, next);
+
+    usbredirparser_send_cancel_data_packet(dev->parser, p->id);
+    usbredirparser_do_write(dev->parser);
 }
 
-static AsyncURB *async_find(USBRedirDevice *dev, uint32_t packet_id)
+static int usbredir_is_cancelled(USBRedirDevice *dev, uint64_t id)
 {
-    AsyncURB *aurb;
+    Cancelled *c;
+
+    if (!dev->dev.attached) {
+        return 1; /* Treat everything as cancelled after a disconnect */
+    }
 
-    QTAILQ_FOREACH(aurb, &dev->asyncq, next) {
-        if (aurb->packet_id == packet_id) {
-            return aurb;
+    QTAILQ_FOREACH(c, &dev->cancelled, next) {
+        if (c->id == id) {
+            QTAILQ_REMOVE(&dev->cancelled, c, next);
+            g_free(c);
+            return 1;
         }
     }
-    DPRINTF("could not find async urb for packet_id %u\n", packet_id);
-    return NULL;
+    return 0;
 }
 
-static void usbredir_cancel_packet(USBDevice *udev, USBPacket *p)
+static USBPacket *usbredir_find_packet_by_id(USBRedirDevice *dev,
+    uint8_t ep, uint64_t id)
 {
-    USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
-    AsyncURB *aurb;
-
-    QTAILQ_FOREACH(aurb, &dev->asyncq, next) {
-        if (p != aurb->packet) {
-            continue;
-        }
+    USBPacket *p;
 
-        DPRINTF("async cancel id %u\n", aurb->packet_id);
-        usbredirparser_send_cancel_data_packet(dev->parser, aurb->packet_id);
-        usbredirparser_do_write(dev->parser);
+    if (usbredir_is_cancelled(dev, id)) {
+        return NULL;
+    }
 
-        /* Mark it as dead */
-        aurb->packet = NULL;
-        break;
+    p = usb_ep_find_packet_by_id(&dev->dev,
+                            (ep & USB_DIR_IN) ? USB_TOKEN_IN : USB_TOKEN_OUT,
+                            ep & 0x0f, id);
+    if (p == NULL) {
+        ERROR("could not find packet with id %"PRIu64"\n", id);
     }
+    return p;
 }
 
 static void bufp_alloc(USBRedirDevice *dev,
@@ -484,24 +483,22 @@ static void usbredir_stop_iso_stream(USBRedirDevice *dev, uint8_t ep)
 static int usbredir_handle_bulk_data(USBRedirDevice *dev, USBPacket *p,
                                       uint8_t ep)
 {
-    AsyncURB *aurb = async_alloc(dev, p);
     struct usb_redir_bulk_packet_header bulk_packet;
 
-    DPRINTF("bulk-out ep %02X len %zd id %u\n", ep,
-            p->iov.size, aurb->packet_id);
+    DPRINTF("bulk-out ep %02X len %zd id %"PRIu64"\n", ep, p->iov.size, p->id);
 
     bulk_packet.endpoint  = ep;
     bulk_packet.length    = p->iov.size;
     bulk_packet.stream_id = 0;
 
     if (ep & USB_DIR_IN) {
-        usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id,
+        usbredirparser_send_bulk_packet(dev->parser, p->id,
                                         &bulk_packet, NULL, 0);
     } else {
         uint8_t buf[p->iov.size];
         usb_packet_copy(p, buf, p->iov.size);
         usbredir_log_data(dev, "bulk data out:", buf, p->iov.size);
-        usbredirparser_send_bulk_packet(dev->parser, aurb->packet_id,
+        usbredirparser_send_bulk_packet(dev->parser, p->id,
                                         &bulk_packet, buf, p->iov.size);
     }
     usbredirparser_do_write(dev->parser);
@@ -564,19 +561,18 @@ static int usbredir_handle_interrupt_data(USBRedirDevice *dev,
         return len;
     } else {
         /* Output interrupt endpoint, normal async operation */
-        AsyncURB *aurb = async_alloc(dev, p);
         struct usb_redir_interrupt_packet_header interrupt_packet;
         uint8_t buf[p->iov.size];
 
-        DPRINTF("interrupt-out ep %02X len %zd id %u\n", ep, p->iov.size,
-                aurb->packet_id);
+        DPRINTF("interrupt-out ep %02X len %zd id %"PRIu64"\n", ep,
+                p->iov.size, p->id);
 
         interrupt_packet.endpoint  = ep;
         interrupt_packet.length    = p->iov.size;
 
         usb_packet_copy(p, buf, p->iov.size);
         usbredir_log_data(dev, "interrupt data out:", buf, p->iov.size);
-        usbredirparser_send_interrupt_packet(dev->parser, aurb->packet_id,
+        usbredirparser_send_interrupt_packet(dev->parser, p->id,
                                         &interrupt_packet, buf, p->iov.size);
         usbredirparser_do_write(dev->parser);
         return USB_RET_ASYNC;
@@ -630,10 +626,9 @@ static int usbredir_set_config(USBRedirDevice *dev, USBPacket *p,
                                 int config)
 {
     struct usb_redir_set_configuration_header set_config;
-    AsyncURB *aurb = async_alloc(dev, p);
     int i;
 
-    DPRINTF("set config %d id %u\n", config, aurb->packet_id);
+    DPRINTF("set config %d id %"PRIu64"\n", config, p->id);
 
     for (i = 0; i < MAX_ENDPOINTS; i++) {
         switch (dev->endpoint[i].type) {
@@ -650,19 +645,16 @@ static int usbredir_set_config(USBRedirDevice *dev, USBPacket *p,
     }
 
     set_config.configuration = config;
-    usbredirparser_send_set_configuration(dev->parser, aurb->packet_id,
-                                          &set_config);
+    usbredirparser_send_set_configuration(dev->parser, p->id, &set_config);
     usbredirparser_do_write(dev->parser);
     return USB_RET_ASYNC;
 }
 
 static int usbredir_get_config(USBRedirDevice *dev, USBPacket *p)
 {
-    AsyncURB *aurb = async_alloc(dev, p);
-
-    DPRINTF("get config id %u\n", aurb->packet_id);
+    DPRINTF("get config id %"PRIu64"\n", p->id);
 
-    usbredirparser_send_get_configuration(dev->parser, aurb->packet_id);
+    usbredirparser_send_get_configuration(dev->parser, p->id);
     usbredirparser_do_write(dev->parser);
     return USB_RET_ASYNC;
 }
@@ -671,11 +663,9 @@ static int usbredir_set_interface(USBRedirDevice *dev, USBPacket *p,
                                    int interface, int alt)
 {
     struct usb_redir_set_alt_setting_header set_alt;
-    AsyncURB *aurb = async_alloc(dev, p);
     int i;
 
-    DPRINTF("set interface %d alt %d id %u\n", interface, alt,
-            aurb->packet_id);
+    DPRINTF("set interface %d alt %d id %"PRIu64"\n", interface, alt, p->id);
 
     for (i = 0; i < MAX_ENDPOINTS; i++) {
         if (dev->endpoint[i].interface == interface) {
@@ -695,8 +685,7 @@ static int usbredir_set_interface(USBRedirDevice *dev, USBPacket *p,
 
     set_alt.interface = interface;
     set_alt.alt = alt;
-    usbredirparser_send_set_alt_setting(dev->parser, aurb->packet_id,
-                                        &set_alt);
+    usbredirparser_send_set_alt_setting(dev->parser, p->id, &set_alt);
     usbredirparser_do_write(dev->parser);
     return USB_RET_ASYNC;
 }
@@ -705,13 +694,11 @@ static int usbredir_get_interface(USBRedirDevice *dev, USBPacket *p,
                                    int interface)
 {
     struct usb_redir_get_alt_setting_header get_alt;
-    AsyncURB *aurb = async_alloc(dev, p);
 
-    DPRINTF("get interface %d id %u\n", interface, aurb->packet_id);
+    DPRINTF("get interface %d id %"PRIu64"\n", interface, p->id);
 
     get_alt.interface = interface;
-    usbredirparser_send_get_alt_setting(dev->parser, aurb->packet_id,
-                                        &get_alt);
+    usbredirparser_send_get_alt_setting(dev->parser, p->id, &get_alt);
     usbredirparser_do_write(dev->parser);
     return USB_RET_ASYNC;
 }
@@ -721,7 +708,6 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
 {
     USBRedirDevice *dev = DO_UPCAST(USBRedirDevice, dev, udev);
     struct usb_redir_control_packet_header control_packet;
-    AsyncURB *aurb;
 
     /* Special cases for certain standard device requests */
     switch (request) {
@@ -739,13 +725,10 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
         return usbredir_get_interface(dev, p, index);
     }
 
-    /* "Normal" ctrl requests */
-    aurb = async_alloc(dev, p);
-
-    /* Note request is (bRequestType << 8) | bRequest */
-    DPRINTF("ctrl-out type 0x%x req 0x%x val 0x%x index %d len %d id %u\n",
-            request >> 8, request & 0xff, value, index, length,
-            aurb->packet_id);
+    /* Normal ctrl requests, note request is (bRequestType << 8) | bRequest */
+    DPRINTF(
+        "ctrl-out type 0x%x req 0x%x val 0x%x index %d len %d id %"PRIu64"\n",
+        request >> 8, request & 0xff, value, index, length, p->id);
 
     control_packet.request     = request & 0xFF;
     control_packet.requesttype = request >> 8;
@@ -755,11 +738,11 @@ static int usbredir_handle_control(USBDevice *udev, USBPacket *p,
     control_packet.length      = length;
 
     if (control_packet.requesttype & USB_DIR_IN) {
-        usbredirparser_send_control_packet(dev->parser, aurb->packet_id,
+        usbredirparser_send_control_packet(dev->parser, p->id,
                                            &control_packet, NULL, 0);
     } else {
         usbredir_log_data(dev, "ctrl data out:", data, length);
-        usbredirparser_send_control_packet(dev->parser, aurb->packet_id,
+        usbredirparser_send_control_packet(dev->parser, p->id,
                                            &control_packet, data, length);
     }
     usbredirparser_do_write(dev->parser);
@@ -913,7 +896,7 @@ static int usbredir_initfn(USBDevice *udev)
     dev->chardev_close_bh = qemu_bh_new(usbredir_chardev_close_bh, dev);
     dev->attach_timer = qemu_new_timer_ms(vm_clock, usbredir_do_attach, dev);
 
-    QTAILQ_INIT(&dev->asyncq);
+    QTAILQ_INIT(&dev->cancelled);
     for (i = 0; i < MAX_ENDPOINTS; i++) {
         QTAILQ_INIT(&dev->endpoint[i].bufpq);
     }
@@ -932,11 +915,12 @@ static int usbredir_initfn(USBDevice *udev)
 
 static void usbredir_cleanup_device_queues(USBRedirDevice *dev)
 {
-    AsyncURB *aurb, *next_aurb;
+    Cancelled *c, *next_c;
     int i;
 
-    QTAILQ_FOREACH_SAFE(aurb, &dev->asyncq, next, next_aurb) {
-        async_free(dev, aurb);
+    QTAILQ_FOREACH_SAFE(c, &dev->cancelled, next, next_c) {
+        QTAILQ_REMOVE(&dev->cancelled, c, next);
+        g_free(c);
     }
     for (i = 0; i < MAX_ENDPOINTS; i++) {
         usbredir_free_bufpq(dev, I2EP(i));
@@ -1202,33 +1186,28 @@ static void usbredir_configuration_status(void *priv, uint32_t id,
     struct usb_redir_configuration_status_header *config_status)
 {
     USBRedirDevice *dev = priv;
-    AsyncURB *aurb;
+    USBPacket *p;
     int len = 0;
 
     DPRINTF("set config status %d config %d id %u\n", config_status->status,
             config_status->configuration, id);
 
-    aurb = async_find(dev, id);
-    if (!aurb) {
-        return;
-    }
-    if (aurb->packet) {
+    p = usbredir_find_packet_by_id(dev, 0, id);
+    if (p) {
         if (dev->dev.setup_buf[0] & USB_DIR_IN) {
             dev->dev.data_buf[0] = config_status->configuration;
             len = 1;
         }
-        aurb->packet->result =
-            usbredir_handle_status(dev, config_status->status, len);
-        usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
+        p->result = usbredir_handle_status(dev, config_status->status, len);
+        usb_generic_async_ctrl_complete(&dev->dev, p);
     }
-    async_free(dev, aurb);
 }
 
 static void usbredir_alt_setting_status(void *priv, uint32_t id,
     struct usb_redir_alt_setting_status_header *alt_setting_status)
 {
     USBRedirDevice *dev = priv;
-    AsyncURB *aurb;
+    USBPacket *p;
     int len = 0;
 
     DPRINTF("alt status %d intf %d alt %d id: %u\n",
@@ -1236,20 +1215,16 @@ static void usbredir_alt_setting_status(void *priv, uint32_t id,
             alt_setting_status->interface,
             alt_setting_status->alt, id);
 
-    aurb = async_find(dev, id);
-    if (!aurb) {
-        return;
-    }
-    if (aurb->packet) {
+    p = usbredir_find_packet_by_id(dev, 0, id);
+    if (p) {
         if (dev->dev.setup_buf[0] & USB_DIR_IN) {
             dev->dev.data_buf[0] = alt_setting_status->alt;
             len = 1;
         }
-        aurb->packet->result =
+        p->result =
             usbredir_handle_status(dev, alt_setting_status->status, len);
-        usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
+        usb_generic_async_ctrl_complete(&dev->dev, p);
     }
-    async_free(dev, aurb);
 }
 
 static void usbredir_iso_stream_status(void *priv, uint32_t id,
@@ -1304,19 +1279,14 @@ static void usbredir_control_packet(void *priv, uint32_t id,
     uint8_t *data, int data_len)
 {
     USBRedirDevice *dev = priv;
+    USBPacket *p;
     int len = control_packet->length;
-    AsyncURB *aurb;
 
     DPRINTF("ctrl-in status %d len %d id %u\n", control_packet->status,
             len, id);
 
-    aurb = async_find(dev, id);
-    if (!aurb) {
-        free(data);
-        return;
-    }
-
-    if (aurb->packet) {
+    p = usbredir_find_packet_by_id(dev, 0, id);
+    if (p) {
         len = usbredir_handle_status(dev, control_packet->status, len);
         if (len > 0) {
             usbredir_log_data(dev, "ctrl data in:", data, data_len);
@@ -1328,10 +1298,9 @@ static void usbredir_control_packet(void *priv, uint32_t id,
                 len = USB_RET_STALL;
             }
         }
-        aurb->packet->result = len;
-        usb_generic_async_ctrl_complete(&dev->dev, aurb->packet);
+        p->result = len;
+        usb_generic_async_ctrl_complete(&dev->dev, p);
     }
-    async_free(dev, aurb);
     free(data);
 }
 
@@ -1342,33 +1311,27 @@ static void usbredir_bulk_packet(void *priv, uint32_t id,
     USBRedirDevice *dev = priv;
     uint8_t ep = bulk_packet->endpoint;
     int len = bulk_packet->length;
-    AsyncURB *aurb;
+    USBPacket *p;
 
     DPRINTF("bulk-in status %d ep %02X len %d id %u\n", bulk_packet->status,
             ep, len, id);
 
-    aurb = async_find(dev, id);
-    if (!aurb) {
-        free(data);
-        return;
-    }
-
-    if (aurb->packet) {
+    p = usbredir_find_packet_by_id(dev, ep, id);
+    if (p) {
         len = usbredir_handle_status(dev, bulk_packet->status, len);
         if (len > 0) {
             usbredir_log_data(dev, "bulk data in:", data, data_len);
-            if (data_len <= aurb->packet->iov.size) {
-                usb_packet_copy(aurb->packet, data, data_len);
+            if (data_len <= p->iov.size) {
+                usb_packet_copy(p, data, data_len);
             } else {
                 ERROR("bulk buffer too small (%d > %zd)\n", data_len,
-                      aurb->packet->iov.size);
+                      p->iov.size);
                 len = USB_RET_STALL;
             }
         }
-        aurb->packet->result = len;
-        usb_packet_complete(&dev->dev, aurb->packet);
+        p->result = len;
+        usb_packet_complete(&dev->dev, p);
     }
-    async_free(dev, aurb);
     free(data);
 }
 
@@ -1426,17 +1389,12 @@ static void usbredir_interrupt_packet(void *priv, uint32_t id,
     } else {
         int len = interrupt_packet->length;
 
-        AsyncURB *aurb = async_find(dev, id);
-        if (!aurb) {
-            return;
-        }
-
-        if (aurb->packet) {
-            aurb->packet->result = usbredir_handle_status(dev,
+        USBPacket *p = usbredir_find_packet_by_id(dev, ep, id);
+        if (p) {
+            p->result = usbredir_handle_status(dev,
                                                interrupt_packet->status, len);
-            usb_packet_complete(&dev->dev, aurb->packet);
+            usb_packet_complete(&dev->dev, p);
         }
-        async_free(dev, aurb);
     }
 }
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH 23/54] usb-redir: Return babble when getting more bulk data then requested
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (21 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 22/54] usb-redir: Move to core packet id and queue handling Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 24/54] usb-redir: Convert to new libusbredirparser 0.5 API Gerd Hoffmann
                   ` (31 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede, Gerd Hoffmann

From: Hans de Goede <hdegoede@redhat.com>

Babble is the appropriate error in this case (rather then signalling a stall).

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/redirect.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index fd1f8cc..ee75217 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -1324,9 +1324,9 @@ static void usbredir_bulk_packet(void *priv, uint32_t id,
             if (data_len <= p->iov.size) {
                 usb_packet_copy(p, data, data_len);
             } else {
-                ERROR("bulk buffer too small (%d > %zd)\n", data_len,
-                      p->iov.size);
-                len = USB_RET_STALL;
+                ERROR("bulk got more data then requested (%d > %zd)\n",
+                      data_len, p->iov.size);
+                len = USB_RET_BABBLE;
             }
         }
         p->result = len;
-- 
1.7.1

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

* [Qemu-devel] [PATCH 24/54] usb-redir: Convert to new libusbredirparser 0.5 API
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (22 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 23/54] usb-redir: Return babble when getting more bulk data then requested Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 25/54] usb-redir: Set ep max_packet_size if available Gerd Hoffmann
                   ` (30 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede, Gerd Hoffmann

From: Hans de Goede <hdegoede@redhat.com>

This gives us support for 64 bit ids which is needed for using XHCI with
the new hcd generated ids.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 configure         |    2 +-
 hw/usb/redirect.c |   62 ++++++++++++++++++++++++++--------------------------
 2 files changed, 32 insertions(+), 32 deletions(-)

diff --git a/configure b/configure
index d97fd81..ea2925b 100755
--- a/configure
+++ b/configure
@@ -2750,7 +2750,7 @@ fi
 
 # check for usbredirparser for usb network redirection support
 if test "$usb_redir" != "no" ; then
-    if $pkg_config --atleast-version=0.3.4 libusbredirparser >/dev/null 2>&1 ; then
+    if $pkg_config --atleast-version=0.5 libusbredirparser >/dev/null 2>&1 ; then
         usb_redir="yes"
         usb_redir_cflags=$($pkg_config --cflags libusbredirparser 2>/dev/null)
         usb_redir_libs=$($pkg_config --libs libusbredirparser 2>/dev/null)
diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index ee75217..eeeb003 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -107,27 +107,27 @@ static void usbredir_interface_info(void *priv,
     struct usb_redir_interface_info_header *interface_info);
 static void usbredir_ep_info(void *priv,
     struct usb_redir_ep_info_header *ep_info);
-static void usbredir_configuration_status(void *priv, uint32_t id,
+static void usbredir_configuration_status(void *priv, uint64_t id,
     struct usb_redir_configuration_status_header *configuration_status);
-static void usbredir_alt_setting_status(void *priv, uint32_t id,
+static void usbredir_alt_setting_status(void *priv, uint64_t id,
     struct usb_redir_alt_setting_status_header *alt_setting_status);
-static void usbredir_iso_stream_status(void *priv, uint32_t id,
+static void usbredir_iso_stream_status(void *priv, uint64_t id,
     struct usb_redir_iso_stream_status_header *iso_stream_status);
-static void usbredir_interrupt_receiving_status(void *priv, uint32_t id,
+static void usbredir_interrupt_receiving_status(void *priv, uint64_t id,
     struct usb_redir_interrupt_receiving_status_header
     *interrupt_receiving_status);
-static void usbredir_bulk_streams_status(void *priv, uint32_t id,
+static void usbredir_bulk_streams_status(void *priv, uint64_t id,
     struct usb_redir_bulk_streams_status_header *bulk_streams_status);
-static void usbredir_control_packet(void *priv, uint32_t id,
+static void usbredir_control_packet(void *priv, uint64_t id,
     struct usb_redir_control_packet_header *control_packet,
     uint8_t *data, int data_len);
-static void usbredir_bulk_packet(void *priv, uint32_t id,
+static void usbredir_bulk_packet(void *priv, uint64_t id,
     struct usb_redir_bulk_packet_header *bulk_packet,
     uint8_t *data, int data_len);
-static void usbredir_iso_packet(void *priv, uint32_t id,
+static void usbredir_iso_packet(void *priv, uint64_t id,
     struct usb_redir_iso_packet_header *iso_packet,
     uint8_t *data, int data_len);
-static void usbredir_interrupt_packet(void *priv, uint32_t id,
+static void usbredir_interrupt_packet(void *priv, uint64_t id,
     struct usb_redir_interrupt_packet_header *interrupt_header,
     uint8_t *data, int data_len);
 
@@ -805,6 +805,7 @@ static void usbredir_chardev_open(USBRedirDevice *dev)
 
     usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version);
     usbredirparser_caps_set_cap(caps, usb_redir_cap_filter);
+    usbredirparser_caps_set_cap(caps, usb_redir_cap_64bits_ids);
     usbredirparser_init(dev->parser, version, caps, USB_REDIR_CAPS_SIZE, 0);
     usbredirparser_do_write(dev->parser);
 }
@@ -1182,15 +1183,15 @@ static void usbredir_ep_info(void *priv,
     }
 }
 
-static void usbredir_configuration_status(void *priv, uint32_t id,
+static void usbredir_configuration_status(void *priv, uint64_t id,
     struct usb_redir_configuration_status_header *config_status)
 {
     USBRedirDevice *dev = priv;
     USBPacket *p;
     int len = 0;
 
-    DPRINTF("set config status %d config %d id %u\n", config_status->status,
-            config_status->configuration, id);
+    DPRINTF("set config status %d config %d id %"PRIu64"\n",
+            config_status->status, config_status->configuration, id);
 
     p = usbredir_find_packet_by_id(dev, 0, id);
     if (p) {
@@ -1203,16 +1204,15 @@ static void usbredir_configuration_status(void *priv, uint32_t id,
     }
 }
 
-static void usbredir_alt_setting_status(void *priv, uint32_t id,
+static void usbredir_alt_setting_status(void *priv, uint64_t id,
     struct usb_redir_alt_setting_status_header *alt_setting_status)
 {
     USBRedirDevice *dev = priv;
     USBPacket *p;
     int len = 0;
 
-    DPRINTF("alt status %d intf %d alt %d id: %u\n",
-            alt_setting_status->status,
-            alt_setting_status->interface,
+    DPRINTF("alt status %d intf %d alt %d id: %"PRIu64"\n",
+            alt_setting_status->status, alt_setting_status->interface,
             alt_setting_status->alt, id);
 
     p = usbredir_find_packet_by_id(dev, 0, id);
@@ -1227,13 +1227,13 @@ static void usbredir_alt_setting_status(void *priv, uint32_t id,
     }
 }
 
-static void usbredir_iso_stream_status(void *priv, uint32_t id,
+static void usbredir_iso_stream_status(void *priv, uint64_t id,
     struct usb_redir_iso_stream_status_header *iso_stream_status)
 {
     USBRedirDevice *dev = priv;
     uint8_t ep = iso_stream_status->endpoint;
 
-    DPRINTF("iso status %d ep %02X id %u\n", iso_stream_status->status,
+    DPRINTF("iso status %d ep %02X id %"PRIu64"\n", iso_stream_status->status,
             ep, id);
 
     if (!dev->dev.attached || !dev->endpoint[EP2I(ep)].iso_started) {
@@ -1247,14 +1247,14 @@ static void usbredir_iso_stream_status(void *priv, uint32_t id,
     }
 }
 
-static void usbredir_interrupt_receiving_status(void *priv, uint32_t id,
+static void usbredir_interrupt_receiving_status(void *priv, uint64_t id,
     struct usb_redir_interrupt_receiving_status_header
     *interrupt_receiving_status)
 {
     USBRedirDevice *dev = priv;
     uint8_t ep = interrupt_receiving_status->endpoint;
 
-    DPRINTF("interrupt recv status %d ep %02X id %u\n",
+    DPRINTF("interrupt recv status %d ep %02X id %"PRIu64"\n",
             interrupt_receiving_status->status, ep, id);
 
     if (!dev->dev.attached || !dev->endpoint[EP2I(ep)].interrupt_started) {
@@ -1269,12 +1269,12 @@ static void usbredir_interrupt_receiving_status(void *priv, uint32_t id,
     }
 }
 
-static void usbredir_bulk_streams_status(void *priv, uint32_t id,
+static void usbredir_bulk_streams_status(void *priv, uint64_t id,
     struct usb_redir_bulk_streams_status_header *bulk_streams_status)
 {
 }
 
-static void usbredir_control_packet(void *priv, uint32_t id,
+static void usbredir_control_packet(void *priv, uint64_t id,
     struct usb_redir_control_packet_header *control_packet,
     uint8_t *data, int data_len)
 {
@@ -1282,7 +1282,7 @@ static void usbredir_control_packet(void *priv, uint32_t id,
     USBPacket *p;
     int len = control_packet->length;
 
-    DPRINTF("ctrl-in status %d len %d id %u\n", control_packet->status,
+    DPRINTF("ctrl-in status %d len %d id %"PRIu64"\n", control_packet->status,
             len, id);
 
     p = usbredir_find_packet_by_id(dev, 0, id);
@@ -1304,7 +1304,7 @@ static void usbredir_control_packet(void *priv, uint32_t id,
     free(data);
 }
 
-static void usbredir_bulk_packet(void *priv, uint32_t id,
+static void usbredir_bulk_packet(void *priv, uint64_t id,
     struct usb_redir_bulk_packet_header *bulk_packet,
     uint8_t *data, int data_len)
 {
@@ -1313,8 +1313,8 @@ static void usbredir_bulk_packet(void *priv, uint32_t id,
     int len = bulk_packet->length;
     USBPacket *p;
 
-    DPRINTF("bulk-in status %d ep %02X len %d id %u\n", bulk_packet->status,
-            ep, len, id);
+    DPRINTF("bulk-in status %d ep %02X len %d id %"PRIu64"\n",
+            bulk_packet->status, ep, len, id);
 
     p = usbredir_find_packet_by_id(dev, ep, id);
     if (p) {
@@ -1335,15 +1335,15 @@ static void usbredir_bulk_packet(void *priv, uint32_t id,
     free(data);
 }
 
-static void usbredir_iso_packet(void *priv, uint32_t id,
+static void usbredir_iso_packet(void *priv, uint64_t id,
     struct usb_redir_iso_packet_header *iso_packet,
     uint8_t *data, int data_len)
 {
     USBRedirDevice *dev = priv;
     uint8_t ep = iso_packet->endpoint;
 
-    DPRINTF2("iso-in status %d ep %02X len %d id %u\n", iso_packet->status, ep,
-             data_len, id);
+    DPRINTF2("iso-in status %d ep %02X len %d id %"PRIu64"\n",
+             iso_packet->status, ep, data_len, id);
 
     if (dev->endpoint[EP2I(ep)].type != USB_ENDPOINT_XFER_ISOC) {
         ERROR("received iso packet for non iso endpoint %02X\n", ep);
@@ -1361,14 +1361,14 @@ static void usbredir_iso_packet(void *priv, uint32_t id,
     bufp_alloc(dev, data, data_len, iso_packet->status, ep);
 }
 
-static void usbredir_interrupt_packet(void *priv, uint32_t id,
+static void usbredir_interrupt_packet(void *priv, uint64_t id,
     struct usb_redir_interrupt_packet_header *interrupt_packet,
     uint8_t *data, int data_len)
 {
     USBRedirDevice *dev = priv;
     uint8_t ep = interrupt_packet->endpoint;
 
-    DPRINTF("interrupt-in status %d ep %02X len %d id %u\n",
+    DPRINTF("interrupt-in status %d ep %02X len %d id %"PRIu64"\n",
             interrupt_packet->status, ep, data_len, id);
 
     if (dev->endpoint[EP2I(ep)].type != USB_ENDPOINT_XFER_INT) {
-- 
1.7.1

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

* [Qemu-devel] [PATCH 25/54] usb-redir: Set ep max_packet_size if available
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (23 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 24/54] usb-redir: Convert to new libusbredirparser 0.5 API Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 26/54] usb-redir: Add a usbredir_reject_device helper function Gerd Hoffmann
                   ` (29 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede, Gerd Hoffmann

From: Hans de Goede <hdegoede@redhat.com>

This is needed for usb-redir to work properly with the xhci emulation.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/redirect.c |    5 +++++
 1 files changed, 5 insertions(+), 0 deletions(-)

diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index eeeb003..a91e073 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -805,6 +805,7 @@ static void usbredir_chardev_open(USBRedirDevice *dev)
 
     usbredirparser_caps_set_cap(caps, usb_redir_cap_connect_device_version);
     usbredirparser_caps_set_cap(caps, usb_redir_cap_filter);
+    usbredirparser_caps_set_cap(caps, usb_redir_cap_ep_info_max_packet_size);
     usbredirparser_caps_set_cap(caps, usb_redir_cap_64bits_ids);
     usbredirparser_init(dev->parser, version, caps, USB_REDIR_CAPS_SIZE, 0);
     usbredirparser_do_write(dev->parser);
@@ -1180,6 +1181,10 @@ static void usbredir_ep_info(void *priv,
                             i & 0x0f);
         usb_ep->type = dev->endpoint[i].type;
         usb_ep->ifnum = dev->endpoint[i].interface;
+        if (usbredirparser_peer_has_cap(dev->parser,
+                                     usb_redir_cap_ep_info_max_packet_size)) {
+            usb_ep->max_packet_size = ep_info->max_packet_size[i];
+        }
     }
 }
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH 26/54] usb-redir: Add a usbredir_reject_device helper function
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (24 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 25/54] usb-redir: Set ep max_packet_size if available Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 27/54] usb-redir: Ensure our peer has the necessary caps when redirecting to XHCI Gerd Hoffmann
                   ` (28 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede, Gerd Hoffmann

From: Hans de Goede <hdegoede@redhat.com>

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/redirect.c |   21 +++++++++++----------
 1 files changed, 11 insertions(+), 10 deletions(-)

diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index a91e073..c518201 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -811,16 +811,21 @@ static void usbredir_chardev_open(USBRedirDevice *dev)
     usbredirparser_do_write(dev->parser);
 }
 
+static void usbredir_reject_device(USBRedirDevice *dev)
+{
+    usbredir_device_disconnect(dev);
+    if (usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_filter)) {
+        usbredirparser_send_filter_reject(dev->parser);
+        usbredirparser_do_write(dev->parser);
+    }
+}
+
 static void usbredir_do_attach(void *opaque)
 {
     USBRedirDevice *dev = opaque;
 
     if (usb_device_attach(&dev->dev) != 0) {
-        usbredir_device_disconnect(dev);
-        if (usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_filter)) {
-            usbredirparser_send_filter_reject(dev->parser);
-            usbredirparser_do_write(dev->parser);
-        }
+        usbredir_reject_device(dev);
     }
 }
 
@@ -986,11 +991,7 @@ static int usbredir_check_filter(USBRedirDevice *dev)
     return 0;
 
 error:
-    usbredir_device_disconnect(dev);
-    if (usbredirparser_peer_has_cap(dev->parser, usb_redir_cap_filter)) {
-        usbredirparser_send_filter_reject(dev->parser);
-        usbredirparser_do_write(dev->parser);
-    }
+    usbredir_reject_device(dev);
     return -1;
 }
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH 27/54] usb-redir: Ensure our peer has the necessary caps when redirecting to XHCI
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (25 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 26/54] usb-redir: Add a usbredir_reject_device helper function Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 28/54] usb-redir: Enable pipelining for bulk endpoints Gerd Hoffmann
                   ` (27 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede, Gerd Hoffmann

From: Hans de Goede <hdegoede@redhat.com>

In order for redirection to work properly when redirecting to an emulated
XHCI controller, the usb-redir-host must support both
usb_redir_cap_ep_info_max_packet_size and usb_redir_cap_64bits_ids,
reject any devices redirected to an XHCI controller when these are not
supported.

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/redirect.c |   11 +++++++++++
 1 files changed, 11 insertions(+), 0 deletions(-)

diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index c518201..7fb0fb3 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -824,6 +824,17 @@ static void usbredir_do_attach(void *opaque)
 {
     USBRedirDevice *dev = opaque;
 
+    /* In order to work properly with XHCI controllers we need these caps */
+    if ((dev->dev.port->speedmask & USB_SPEED_MASK_SUPER) && !(
+        usbredirparser_peer_has_cap(dev->parser,
+                                    usb_redir_cap_ep_info_max_packet_size) &&
+        usbredirparser_peer_has_cap(dev->parser,
+                                    usb_redir_cap_64bits_ids))) {
+        ERROR("usb-redir-host lacks capabilities needed for use with XHCI\n");
+        usbredir_reject_device(dev);
+        return;
+    }
+
     if (usb_device_attach(&dev->dev) != 0) {
         usbredir_reject_device(dev);
     }
-- 
1.7.1

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

* [Qemu-devel] [PATCH 28/54] usb-redir: Enable pipelining for bulk endpoints
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (26 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 27/54] usb-redir: Ensure our peer has the necessary caps when redirecting to XHCI Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 29/54] Better name usb braille device Gerd Hoffmann
                   ` (26 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Hans de Goede, Gerd Hoffmann

From: Hans de Goede <hdegoede@redhat.com>

Signed-off-by: Hans de Goede <hdegoede@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/redirect.c |    3 +++
 1 files changed, 3 insertions(+), 0 deletions(-)

diff --git a/hw/usb/redirect.c b/hw/usb/redirect.c
index 7fb0fb3..5301a69 100644
--- a/hw/usb/redirect.c
+++ b/hw/usb/redirect.c
@@ -1197,6 +1197,9 @@ static void usbredir_ep_info(void *priv,
                                      usb_redir_cap_ep_info_max_packet_size)) {
             usb_ep->max_packet_size = ep_info->max_packet_size[i];
         }
+        if (ep_info->type[i] == usb_redir_type_bulk) {
+            usb_ep->pipeline = true;
+        }
     }
 }
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH 29/54] Better name usb braille device
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (27 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 28/54] usb-redir: Enable pipelining for bulk endpoints Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 30/54] usb-audio: fix usb version Gerd Hoffmann
                   ` (25 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Samuel Thibault, Gerd Hoffmann

From: Samuel Thibault <samuel.thibault@ens-lyon.org>

Windows users need to know that they have to use the Baum driver to make
the qemu braille device work.

Signed-off-by: Samuel Thibault <samuel.thibault@ens-lyon.org>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/dev-serial.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/hw/usb/dev-serial.c b/hw/usb/dev-serial.c
index 8aa6552..69b6e48 100644
--- a/hw/usb/dev-serial.c
+++ b/hw/usb/dev-serial.c
@@ -113,7 +113,7 @@ enum {
 static const USBDescStrings desc_strings = {
     [STR_MANUFACTURER]    = "QEMU",
     [STR_PRODUCT_SERIAL]  = "QEMU USB SERIAL",
-    [STR_PRODUCT_BRAILLE] = "QEMU USB BRAILLE",
+    [STR_PRODUCT_BRAILLE] = "QEMU USB BAUM BRAILLE",
     [STR_SERIALNUMBER]    = "1",
 };
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH 30/54] usb-audio: fix usb version
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (28 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 29/54] Better name usb braille device Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 31/54] xhci: rip out background transfer code Gerd Hoffmann
                   ` (24 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

usb-audio is a full speed (1.1) device,
but bcdUSB claims it is usb 2.0.  Fix it.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/dev-audio.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/hw/usb/dev-audio.c b/hw/usb/dev-audio.c
index 79b75fb..2594c78 100644
--- a/hw/usb/dev-audio.c
+++ b/hw/usb/dev-audio.c
@@ -217,7 +217,7 @@ static const USBDescIface desc_iface[] = {
 };
 
 static const USBDescDevice desc_device = {
-    .bcdUSB                        = 0x0200,
+    .bcdUSB                        = 0x0100,
     .bMaxPacketSize0               = 64,
     .bNumConfigurations            = 1,
     .confs = (USBDescConfig[]) {
-- 
1.7.1

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

* [Qemu-devel] [PATCH 31/54] xhci: rip out background transfer code
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (29 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 30/54] usb-audio: fix usb version Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 32/54] xhci: drop buffering Gerd Hoffmann
                   ` (23 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

original xhci code (the one which used libusb directly) used to use
'background transfers' for iso streams.  In upstream qemu the iso
stream buffering is handled by usb-host & usb-redir, so we will
never ever need this.  It has been left in as reference, but is dead
code anyway.  Rip it out.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-xhci.c |  223 +----------------------------------------------------
 1 files changed, 4 insertions(+), 219 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 3eb27fa..c0a2476 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -45,8 +45,6 @@
 #define MAXPORTS (USB2_PORTS+USB3_PORTS)
 
 #define TD_QUEUE 24
-#define BG_XFERS 8
-#define BG_PKTS 8
 
 /* Very pessimistic, let's hope it's enough for all cases */
 #define EV_QUEUE (((3*TD_QUEUE)+16)*MAXSLOTS)
@@ -311,13 +309,11 @@ typedef struct XHCITransfer {
     bool running_retry;
     bool cancelled;
     bool complete;
-    bool backgrounded;
     unsigned int iso_pkts;
     unsigned int slotid;
     unsigned int epid;
     bool in_xfer;
     bool iso_xfer;
-    bool bg_xfer;
 
     unsigned int trb_count;
     unsigned int trb_alloced;
@@ -340,14 +336,9 @@ typedef struct XHCIEPContext {
     unsigned int comp_xfer;
     XHCITransfer transfers[TD_QUEUE];
     XHCITransfer *retry;
-    bool bg_running;
-    bool bg_updating;
-    unsigned int next_bg;
-    XHCITransfer bg_transfers[BG_XFERS];
     EPType type;
     dma_addr_t pctx;
     unsigned int max_psize;
-    bool has_bg;
     uint32_t state;
 } XHCIEPContext;
 
@@ -866,10 +857,6 @@ static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid,
     epctx->pctx = pctx;
     epctx->max_psize = ctx[1]>>16;
     epctx->max_psize *= 1+((ctx[1]>>8)&0xff);
-    epctx->has_bg = false;
-    if (epctx->type == ET_ISO_IN) {
-        epctx->has_bg = true;
-    }
     DPRINTF("xhci: endpoint %d.%d max transaction (burst) size is %d\n",
             epid/2, epid%2, epctx->max_psize);
     for (i = 0; i < ARRAY_SIZE(epctx->transfers); i++) {
@@ -916,9 +903,6 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid,
             t->running_retry = 0;
             epctx->retry = NULL;
         }
-        if (t->backgrounded) {
-            t->backgrounded = 0;
-        }
         if (t->trbs) {
             g_free(t->trbs);
         }
@@ -932,25 +916,6 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid,
         t->data_length = t->data_alloced = 0;
         xferi = (xferi + 1) % TD_QUEUE;
     }
-    if (epctx->has_bg) {
-        xferi = epctx->next_bg;
-        for (i = 0; i < BG_XFERS; i++) {
-            XHCITransfer *t = &epctx->bg_transfers[xferi];
-            if (t->running_async) {
-                usb_cancel_packet(&t->packet);
-                t->running_async = 0;
-                t->cancelled = 1;
-                DPRINTF("xhci: cancelling bg transfer %d, waiting for it to complete...\n", i);
-                killed++;
-            }
-            if (t->data) {
-                g_free(t->data);
-            }
-
-            t->data = NULL;
-            xferi = (xferi + 1) % BG_XFERS;
-        }
-    }
     return killed;
 }
 
@@ -1231,160 +1196,6 @@ static void xhci_stall_ep(XHCITransfer *xfer)
 static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer,
                        XHCIEPContext *epctx);
 
-static void xhci_bg_update(XHCIState *xhci, XHCIEPContext *epctx)
-{
-    if (epctx->bg_updating) {
-        return;
-    }
-    DPRINTF("xhci_bg_update(%p, %p)\n", xhci, epctx);
-    assert(epctx->has_bg);
-    DPRINTF("xhci: fg=%d bg=%d\n", epctx->comp_xfer, epctx->next_bg);
-    epctx->bg_updating = 1;
-    while (epctx->transfers[epctx->comp_xfer].backgrounded &&
-           epctx->bg_transfers[epctx->next_bg].complete) {
-        XHCITransfer *fg = &epctx->transfers[epctx->comp_xfer];
-        XHCITransfer *bg = &epctx->bg_transfers[epctx->next_bg];
-#if 0
-        DPRINTF("xhci: completing fg %d from bg %d.%d (stat: %d)\n",
-                epctx->comp_xfer, epctx->next_bg, bg->cur_pkt,
-                bg->usbxfer->iso_packet_desc[bg->cur_pkt].status
-               );
-#endif
-        assert(epctx->type == ET_ISO_IN);
-        assert(bg->iso_xfer);
-        assert(bg->in_xfer);
-        uint8_t *p = bg->data + bg->cur_pkt * bg->pktsize;
-#if 0
-        int len = bg->usbxfer->iso_packet_desc[bg->cur_pkt].actual_length;
-        fg->status = libusb_to_ccode(bg->usbxfer->iso_packet_desc[bg->cur_pkt].status);
-#else
-        int len = 0;
-        FIXME();
-#endif
-        fg->complete = 1;
-        fg->backgrounded = 0;
-
-        if (fg->status == CC_STALL_ERROR) {
-            xhci_stall_ep(fg);
-        }
-
-        xhci_xfer_data(fg, p, len, 1, 0, 1);
-
-        epctx->comp_xfer++;
-        if (epctx->comp_xfer == TD_QUEUE) {
-            epctx->comp_xfer = 0;
-        }
-        DPRINTF("next fg xfer: %d\n", epctx->comp_xfer);
-        bg->cur_pkt++;
-        if (bg->cur_pkt == bg->pkts) {
-            bg->complete = 0;
-            if (xhci_submit(xhci, bg, epctx) < 0) {
-                fprintf(stderr, "xhci: bg resubmit failed\n");
-            }
-            epctx->next_bg++;
-            if (epctx->next_bg == BG_XFERS) {
-                epctx->next_bg = 0;
-            }
-            DPRINTF("next bg xfer: %d\n", epctx->next_bg);
-
-        xhci_kick_ep(xhci, fg->slotid, fg->epid);
-        }
-    }
-    epctx->bg_updating = 0;
-}
-
-#if 0
-static void xhci_xfer_cb(struct libusb_transfer *transfer)
-{
-    XHCIState *xhci;
-    XHCITransfer *xfer;
-
-    xfer = (XHCITransfer *)transfer->user_data;
-    xhci = xfer->xhci;
-
-    DPRINTF("xhci_xfer_cb(slot=%d, ep=%d, status=%d)\n", xfer->slotid,
-            xfer->epid, transfer->status);
-
-    assert(xfer->slotid >= 1 && xfer->slotid <= MAXSLOTS);
-    assert(xfer->epid >= 1 && xfer->epid <= 31);
-
-    if (xfer->cancelled) {
-        DPRINTF("xhci: transfer cancelled, not reporting anything\n");
-        xfer->running = 0;
-        return;
-    }
-
-    XHCIEPContext *epctx;
-    XHCISlot *slot;
-    slot = &xhci->slots[xfer->slotid-1];
-    assert(slot->eps[xfer->epid-1]);
-    epctx = slot->eps[xfer->epid-1];
-
-    if (xfer->bg_xfer) {
-        DPRINTF("xhci: background transfer, updating\n");
-        xfer->complete = 1;
-        xfer->running = 0;
-        xhci_bg_update(xhci, epctx);
-        return;
-    }
-
-    if (xfer->iso_xfer) {
-        transfer->status = transfer->iso_packet_desc[0].status;
-        transfer->actual_length = transfer->iso_packet_desc[0].actual_length;
-    }
-
-    xfer->status = libusb_to_ccode(transfer->status);
-
-    xfer->complete = 1;
-    xfer->running = 0;
-
-    if (transfer->status == LIBUSB_TRANSFER_STALL)
-        xhci_stall_ep(xhci, epctx, xfer);
-
-    DPRINTF("xhci: transfer actual length = %d\n", transfer->actual_length);
-
-    if (xfer->in_xfer) {
-        if (xfer->epid == 1) {
-            xhci_xfer_data(xhci, xfer, xfer->data + 8,
-                           transfer->actual_length, 1, 0, 1);
-        } else {
-            xhci_xfer_data(xhci, xfer, xfer->data,
-                           transfer->actual_length, 1, 0, 1);
-        }
-    } else {
-        xhci_xfer_data(xhci, xfer, NULL, transfer->actual_length, 0, 0, 1);
-    }
-
-    xhci_kick_ep(xhci, xfer->slotid, xfer->epid);
-}
-
-static int xhci_hle_control(XHCIState *xhci, XHCITransfer *xfer,
-                            uint8_t bmRequestType, uint8_t bRequest,
-                            uint16_t wValue, uint16_t wIndex, uint16_t wLength)
-{
-    uint16_t type_req = (bmRequestType << 8) | bRequest;
-
-    switch (type_req) {
-        case 0x0000 | USB_REQ_SET_CONFIGURATION:
-            DPRINTF("xhci: HLE switch configuration\n");
-            return xhci_switch_config(xhci, xfer->slotid, wValue) == 0;
-        case 0x0100 | USB_REQ_SET_INTERFACE:
-            DPRINTF("xhci: HLE set interface altsetting\n");
-            return xhci_set_iface_alt(xhci, xfer->slotid, wIndex, wValue) == 0;
-        case 0x0200 | USB_REQ_CLEAR_FEATURE:
-            if (wValue == 0) { // endpoint halt
-                DPRINTF("xhci: HLE clear halt\n");
-                return xhci_clear_halt(xhci, xfer->slotid, wIndex);
-            }
-        case 0x0000 | USB_REQ_SET_ADDRESS:
-            fprintf(stderr, "xhci: warn: illegal SET_ADDRESS request\n");
-            return 0;
-        default:
-            return 0;
-    }
-}
-#endif
-
 static int xhci_setup_packet(XHCITransfer *xfer, USBDevice *dev)
 {
     USBEndpoint *ep;
@@ -1559,9 +1370,7 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
         xfer->data_alloced = xfer->data_length;
     }
     if (epctx->type == ET_ISO_IN || epctx->type == ET_ISO_OUT) {
-        if (!xfer->bg_xfer) {
-            xfer->pkts = 1;
-        }
+        xfer->pkts = 1;
     } else {
         xfer->pkts = 0;
     }
@@ -1620,32 +1429,8 @@ static int xhci_fire_transfer(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext
 
     trace_usb_xhci_xfer_start(xfer, xfer->slotid, xfer->epid, length);
 
-    if (!epctx->has_bg) {
-        xfer->data_length = length;
-        xfer->backgrounded = 0;
-        return xhci_submit(xhci, xfer, epctx);
-    } else {
-        if (!epctx->bg_running) {
-            for (i = 0; i < BG_XFERS; i++) {
-                XHCITransfer *t = &epctx->bg_transfers[i];
-                t->xhci = xhci;
-                t->epid = xfer->epid;
-                t->slotid = xfer->slotid;
-                t->pkts = BG_PKTS;
-                t->pktsize = epctx->max_psize;
-                t->data_length = t->pkts * t->pktsize;
-                t->bg_xfer = 1;
-                if (xhci_submit(xhci, t, epctx) < 0) {
-                    fprintf(stderr, "xhci: bg submit failed\n");
-                    return -1;
-                }
-            }
-            epctx->bg_running = 1;
-        }
-        xfer->backgrounded = 1;
-        xhci_bg_update(xhci, epctx);
-        return 0;
-    }
+    xfer->data_length = length;
+    return xhci_submit(xhci, xfer, epctx);
 }
 
 static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid)
@@ -1695,7 +1480,7 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
 
     while (1) {
         XHCITransfer *xfer = &epctx->transfers[epctx->next_xfer];
-        if (xfer->running_async || xfer->running_retry || xfer->backgrounded) {
+        if (xfer->running_async || xfer->running_retry) {
             break;
         }
         length = xhci_ring_chain_length(xhci, &epctx->ring);
-- 
1.7.1

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

* [Qemu-devel] [PATCH 32/54] xhci: drop buffering
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (30 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 31/54] xhci: rip out background transfer code Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 33/54] xhci: move device lookup into xhci_setup_packet Gerd Hoffmann
                   ` (22 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

This patch splits the xhci_xfer_data function into three.
The xhci_xfer_data function used to do does two things:

  (1) copy transfer data between guest memory and a temporary buffer.
  (2) report transfer results to the guest using events.

Now we three functions to handle this:

  (1) xhci_xfer_map creates a scatter list for the transfer and
      uses that (instead of the temporary buffer) to build a
      USBPacket.
  (2) xhci_xfer_unmap undoes the mapping.
  (3) xhci_xfer_report sends out events.

The patch also fixes reporting of transaction errors which must be
reported unconditinally, not only in case the guest asks for it
using the ISP flag.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-xhci.c |  183 +++++++++++++++++++++--------------------------------
 trace-events      |    2 +-
 2 files changed, 72 insertions(+), 113 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index c0a2476..c858b6d 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -305,6 +305,7 @@ typedef struct XHCIState XHCIState;
 typedef struct XHCITransfer {
     XHCIState *xhci;
     USBPacket packet;
+    QEMUSGList sgl;
     bool running_async;
     bool running_retry;
     bool cancelled;
@@ -319,10 +320,6 @@ typedef struct XHCITransfer {
     unsigned int trb_alloced;
     XHCITRB *trbs;
 
-    unsigned int data_length;
-    unsigned int data_alloced;
-    uint8_t *data;
-
     TRBCCode status;
 
     unsigned int pkts;
@@ -906,14 +903,9 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid,
         if (t->trbs) {
             g_free(t->trbs);
         }
-        if (t->data) {
-            g_free(t->data);
-        }
 
         t->trbs = NULL;
-        t->data = NULL;
         t->trb_count = t->trb_alloced = 0;
-        t->data_length = t->data_alloced = 0;
         xferi = (xferi + 1) % TD_QUEUE;
     }
     return killed;
@@ -1072,24 +1064,13 @@ static TRBCCode xhci_set_ep_dequeue(XHCIState *xhci, unsigned int slotid,
     return CC_SUCCESS;
 }
 
-static int xhci_xfer_data(XHCITransfer *xfer, uint8_t *data,
-                          unsigned int length, bool in_xfer, bool out_xfer,
-                          bool report)
+static int xhci_xfer_map(XHCITransfer *xfer)
 {
-    int i;
-    uint32_t edtla = 0;
-    unsigned int transferred = 0;
-    unsigned int left = length;
-    bool reported = 0;
-    bool shortpkt = 0;
-    XHCIEvent event = {ER_TRANSFER, CC_SUCCESS};
+    int in_xfer = (xfer->packet.pid == USB_TOKEN_IN);
     XHCIState *xhci = xfer->xhci;
+    int i;
 
-    DPRINTF("xhci_xfer_data(len=%d, in_xfer=%d, out_xfer=%d, report=%d)\n",
-            length, in_xfer, out_xfer, report);
-
-    assert(!(in_xfer && out_xfer));
-
+    pci_dma_sglist_init(&xfer->sgl, &xhci->pci_dev, xfer->trb_count);
     for (i = 0; i < xfer->trb_count; i++) {
         XHCITRB *trb = &xfer->trbs[i];
         dma_addr_t addr;
@@ -1099,54 +1080,70 @@ static int xhci_xfer_data(XHCITransfer *xfer, uint8_t *data,
         case TR_DATA:
             if ((!(trb->control & TRB_TR_DIR)) != (!in_xfer)) {
                 fprintf(stderr, "xhci: data direction mismatch for TR_DATA\n");
-                xhci_die(xhci);
-                return transferred;
+                goto err;
             }
             /* fallthrough */
         case TR_NORMAL:
         case TR_ISOCH:
             addr = xhci_mask64(trb->parameter);
             chunk = trb->status & 0x1ffff;
+            if (trb->control & TRB_TR_IDT) {
+                if (chunk > 8 || in_xfer) {
+                    fprintf(stderr, "xhci: invalid immediate data TRB\n");
+                    goto err;
+                }
+                qemu_sglist_add(&xfer->sgl, trb->addr, chunk);
+            } else {
+                qemu_sglist_add(&xfer->sgl, addr, chunk);
+            }
+            break;
+        }
+    }
+
+    usb_packet_map(&xfer->packet, &xfer->sgl);
+    return 0;
+
+err:
+    qemu_sglist_destroy(&xfer->sgl);
+    xhci_die(xhci);
+    return -1;
+}
+
+static void xhci_xfer_unmap(XHCITransfer *xfer)
+{
+    usb_packet_unmap(&xfer->packet, &xfer->sgl);
+    qemu_sglist_destroy(&xfer->sgl);
+}
+
+static void xhci_xfer_report(XHCITransfer *xfer)
+{
+    uint32_t edtla = 0;
+    unsigned int left;
+    bool reported = 0;
+    bool shortpkt = 0;
+    XHCIEvent event = {ER_TRANSFER, CC_SUCCESS};
+    XHCIState *xhci = xfer->xhci;
+    int i;
+
+    left = xfer->packet.result < 0 ? 0 : xfer->packet.result;
+
+    for (i = 0; i < xfer->trb_count; i++) {
+        XHCITRB *trb = &xfer->trbs[i];
+        unsigned int chunk = 0;
+
+        switch (TRB_TYPE(*trb)) {
+        case TR_DATA:
+        case TR_NORMAL:
+        case TR_ISOCH:
+            chunk = trb->status & 0x1ffff;
             if (chunk > left) {
                 chunk = left;
-                shortpkt = 1;
-            }
-            if (in_xfer || out_xfer) {
-                if (trb->control & TRB_TR_IDT) {
-                    uint64_t idata;
-                    if (chunk > 8 || in_xfer) {
-                        fprintf(stderr, "xhci: invalid immediate data TRB\n");
-                        xhci_die(xhci);
-                        return transferred;
-                    }
-                    idata = le64_to_cpu(trb->parameter);
-                    memcpy(data, &idata, chunk);
-                } else {
-                    DPRINTF("xhci_xfer_data: r/w(%d) %d bytes at "
-                            DMA_ADDR_FMT "\n", in_xfer, chunk, addr);
-                    if (in_xfer) {
-                        pci_dma_write(&xhci->pci_dev, addr, data, chunk);
-                    } else {
-                        pci_dma_read(&xhci->pci_dev, addr, data, chunk);
-                    }
-#ifdef DEBUG_DATA
-                    unsigned int count = chunk;
-                    int i;
-                    if (count > 16) {
-                        count = 16;
-                    }
-                    DPRINTF(" ::");
-                    for (i = 0; i < count; i++) {
-                        DPRINTF(" %02x", data[i]);
-                    }
-                    DPRINTF("\n");
-#endif
+                if (xfer->status == CC_SUCCESS) {
+                    shortpkt = 1;
                 }
             }
             left -= chunk;
-            data += chunk;
             edtla += chunk;
-            transferred += chunk;
             break;
         case TR_STATUS:
             reported = 0;
@@ -1154,8 +1151,9 @@ static int xhci_xfer_data(XHCITransfer *xfer, uint8_t *data,
             break;
         }
 
-        if (report && !reported && (trb->control & TRB_TR_IOC ||
-            (shortpkt && (trb->control & TRB_TR_ISP)))) {
+        if (!reported && ((trb->control & TRB_TR_IOC) ||
+                          (shortpkt && (trb->control & TRB_TR_ISP)) ||
+                          (xfer->status != CC_SUCCESS))) {
             event.slotid = xfer->slotid;
             event.epid = xfer->epid;
             event.length = (trb->status & 0x1ffff) - chunk;
@@ -1175,9 +1173,11 @@ static int xhci_xfer_data(XHCITransfer *xfer, uint8_t *data,
             }
             xhci_event(xhci, &event);
             reported = 1;
+            if (xfer->status != CC_SUCCESS) {
+                return;
+            }
         }
     }
-    return transferred;
 }
 
 static void xhci_stall_ep(XHCITransfer *xfer)
@@ -1204,7 +1204,7 @@ static int xhci_setup_packet(XHCITransfer *xfer, USBDevice *dev)
     dir = xfer->in_xfer ? USB_TOKEN_IN : USB_TOKEN_OUT;
     ep = usb_ep_get(dev, dir, xfer->epid >> 1);
     usb_packet_setup(&xfer->packet, dir, ep, xfer->trbs[0].addr);
-    usb_packet_addbuf(&xfer->packet, xfer->data, xfer->data_length);
+    xhci_xfer_map(xfer);
     DPRINTF("xhci: setup packet pid 0x%x addr %d ep %d\n",
             xfer->packet.pid, dev->addr, ep->nr);
     return 0;
@@ -1230,12 +1230,13 @@ static int xhci_complete_packet(XHCITransfer *xfer, int ret)
         xfer->running_async = 0;
         xfer->running_retry = 0;
         xfer->complete = 1;
+        xhci_xfer_unmap(xfer);
     }
 
     if (ret >= 0) {
-        xfer->status = CC_SUCCESS;
-        xhci_xfer_data(xfer, xfer->data, ret, xfer->in_xfer, 0, 1);
         trace_usb_xhci_xfer_success(xfer, ret);
+        xfer->status = CC_SUCCESS;
+        xhci_xfer_report(xfer);
         return 0;
     }
 
@@ -1244,12 +1245,12 @@ static int xhci_complete_packet(XHCITransfer *xfer, int ret)
     switch (ret) {
     case USB_RET_NODEV:
         xfer->status = CC_USB_TRANSACTION_ERROR;
-        xhci_xfer_data(xfer, xfer->data, 0, xfer->in_xfer, 0, 1);
+        xhci_xfer_report(xfer);
         xhci_stall_ep(xfer);
         break;
     case USB_RET_STALL:
         xfer->status = CC_STALL_ERROR;
-        xhci_xfer_data(xfer, xfer->data, 0, xfer->in_xfer, 0, 1);
+        xhci_xfer_report(xfer);
         xhci_stall_ep(xfer);
         break;
     default:
@@ -1279,8 +1280,7 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
     trb_setup = &xfer->trbs[0];
     trb_status = &xfer->trbs[xfer->trb_count-1];
 
-    trace_usb_xhci_xfer_start(xfer, xfer->slotid, xfer->epid,
-                              trb_setup->parameter >> 48);
+    trace_usb_xhci_xfer_start(xfer, xfer->slotid, xfer->epid);
 
     /* at most one Event Data TRB allowed after STATUS */
     if (TRB_TYPE(*trb_status) == TR_EVDATA && xfer->trb_count > 2) {
@@ -1311,18 +1311,6 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
     bmRequestType = trb_setup->parameter;
     wLength = trb_setup->parameter >> 48;
 
-    if (xfer->data && xfer->data_alloced < wLength) {
-        xfer->data_alloced = 0;
-        g_free(xfer->data);
-        xfer->data = NULL;
-    }
-    if (!xfer->data) {
-        DPRINTF("xhci: alloc %d bytes data\n", wLength);
-        xfer->data = g_malloc(wLength+1);
-        xfer->data_alloced = wLength;
-    }
-    xfer->data_length = wLength;
-
     port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1];
     dev = xhci_find_device(port, xhci->slots[xfer->slotid-1].devaddr);
     if (!dev) {
@@ -1336,9 +1324,6 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
 
     xhci_setup_packet(xfer, dev);
     xfer->packet.parameter = trb_setup->parameter;
-    if (!xfer->in_xfer) {
-        xhci_xfer_data(xfer, xfer->data, wLength, 0, 1, 0);
-    }
 
     ret = usb_handle_packet(dev, &xfer->packet);
 
@@ -1359,16 +1344,6 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
 
     xfer->in_xfer = epctx->type>>2;
 
-    if (xfer->data && xfer->data_alloced < xfer->data_length) {
-        xfer->data_alloced = 0;
-        g_free(xfer->data);
-        xfer->data = NULL;
-    }
-    if (!xfer->data && xfer->data_length) {
-        DPRINTF("xhci: alloc %d bytes data\n", xfer->data_length);
-        xfer->data = g_malloc(xfer->data_length);
-        xfer->data_alloced = xfer->data_length;
-    }
     if (epctx->type == ET_ISO_IN || epctx->type == ET_ISO_OUT) {
         xfer->pkts = 1;
     } else {
@@ -1402,9 +1377,6 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
         return -1;
     }
 
-    if (!xfer->in_xfer) {
-        xhci_xfer_data(xfer, xfer->data, xfer->data_length, 0, 1, 0);
-    }
     ret = usb_handle_packet(dev, &xfer->packet);
 
     xhci_complete_packet(xfer, ret);
@@ -1416,20 +1388,7 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
 
 static int xhci_fire_transfer(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx)
 {
-    int i;
-    unsigned int length = 0;
-    XHCITRB *trb;
-
-    for (i = 0; i < xfer->trb_count; i++) {
-        trb = &xfer->trbs[i];
-        if (TRB_TYPE(*trb) == TR_NORMAL || TRB_TYPE(*trb) == TR_ISOCH) {
-            length += trb->status & 0x1ffff;
-        }
-    }
-
-    trace_usb_xhci_xfer_start(xfer, xfer->slotid, xfer->epid, length);
-
-    xfer->data_length = length;
+    trace_usb_xhci_xfer_start(xfer, xfer->slotid, xfer->epid);
     return xhci_submit(xhci, xfer, epctx);
 }
 
diff --git a/trace-events b/trace-events
index 8dc4f45..ba4b112 100644
--- a/trace-events
+++ b/trace-events
@@ -326,7 +326,7 @@ usb_xhci_ep_disable(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
 usb_xhci_ep_kick(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
 usb_xhci_ep_stop(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
 usb_xhci_ep_reset(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
-usb_xhci_xfer_start(void *xfer, uint32_t slotid, uint32_t epid, uint32_t length) "%p: slotid %d, epid %d, length %d"
+usb_xhci_xfer_start(void *xfer, uint32_t slotid, uint32_t epid) "%p: slotid %d, epid %d"
 usb_xhci_xfer_async(void *xfer) "%p"
 usb_xhci_xfer_nak(void *xfer) "%p"
 usb_xhci_xfer_retry(void *xfer) "%p"
-- 
1.7.1

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

* [Qemu-devel] [PATCH 33/54] xhci: move device lookup into xhci_setup_packet
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (31 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 32/54] xhci: drop buffering Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 34/54] xhci: implement mfindex Gerd Hoffmann
                   ` (21 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-xhci.c |   74 +++++++++++++++++++++++++++-------------------------
 1 files changed, 38 insertions(+), 36 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index c858b6d..303e1ac 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -1196,13 +1196,38 @@ static void xhci_stall_ep(XHCITransfer *xfer)
 static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer,
                        XHCIEPContext *epctx);
 
-static int xhci_setup_packet(XHCITransfer *xfer, USBDevice *dev)
+static USBDevice *xhci_find_device(XHCIPort *port, uint8_t addr)
 {
+    if (!(port->portsc & PORTSC_PED)) {
+        return NULL;
+    }
+    return usb_find_device(&port->port, addr);
+}
+
+static int xhci_setup_packet(XHCITransfer *xfer)
+{
+    XHCIState *xhci = xfer->xhci;
+    XHCIPort *port;
+    USBDevice *dev;
     USBEndpoint *ep;
     int dir;
 
     dir = xfer->in_xfer ? USB_TOKEN_IN : USB_TOKEN_OUT;
-    ep = usb_ep_get(dev, dir, xfer->epid >> 1);
+
+    if (xfer->packet.ep) {
+        ep = xfer->packet.ep;
+        dev = ep->dev;
+    } else {
+        port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1];
+        dev = xhci_find_device(port, xhci->slots[xfer->slotid-1].devaddr);
+        if (!dev) {
+            fprintf(stderr, "xhci: slot %d port %d has no device\n",
+                    xfer->slotid, xhci->slots[xfer->slotid-1].port);
+            return -1;
+        }
+        ep = usb_ep_get(dev, dir, xfer->epid >> 1);
+    }
+
     usb_packet_setup(&xfer->packet, dir, ep, xfer->trbs[0].addr);
     xhci_xfer_map(xfer);
     DPRINTF("xhci: setup packet pid 0x%x addr %d ep %d\n",
@@ -1260,21 +1285,11 @@ static int xhci_complete_packet(XHCITransfer *xfer, int ret)
     return 0;
 }
 
-static USBDevice *xhci_find_device(XHCIPort *port, uint8_t addr)
-{
-    if (!(port->portsc & PORTSC_PED)) {
-        return NULL;
-    }
-    return usb_find_device(&port->port, addr);
-}
-
 static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
 {
     XHCITRB *trb_setup, *trb_status;
     uint8_t bmRequestType;
     uint16_t wLength;
-    XHCIPort *port;
-    USBDevice *dev;
     int ret;
 
     trb_setup = &xfer->trbs[0];
@@ -1311,21 +1326,15 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
     bmRequestType = trb_setup->parameter;
     wLength = trb_setup->parameter >> 48;
 
-    port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1];
-    dev = xhci_find_device(port, xhci->slots[xfer->slotid-1].devaddr);
-    if (!dev) {
-        fprintf(stderr, "xhci: slot %d port %d has no device\n", xfer->slotid,
-                xhci->slots[xfer->slotid-1].port);
-        return -1;
-    }
-
     xfer->in_xfer = bmRequestType & USB_DIR_IN;
     xfer->iso_xfer = false;
 
-    xhci_setup_packet(xfer, dev);
+    if (xhci_setup_packet(xfer) < 0) {
+        return -1;
+    }
     xfer->packet.parameter = trb_setup->parameter;
 
-    ret = usb_handle_packet(dev, &xfer->packet);
+    ret = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
 
     xhci_complete_packet(xfer, ret);
     if (!xfer->running_async && !xfer->running_retry) {
@@ -1336,8 +1345,6 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
 
 static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx)
 {
-    XHCIPort *port;
-    USBDevice *dev;
     int ret;
 
     DPRINTF("xhci_submit(slotid=%d,epid=%d)\n", xfer->slotid, xfer->epid);
@@ -1350,16 +1357,6 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
         xfer->pkts = 0;
     }
 
-    port = &xhci->ports[xhci->slots[xfer->slotid-1].port-1];
-    dev = xhci_find_device(port, xhci->slots[xfer->slotid-1].devaddr);
-    if (!dev) {
-        fprintf(stderr, "xhci: slot %d port %d has no device\n", xfer->slotid,
-                xhci->slots[xfer->slotid-1].port);
-        return -1;
-    }
-
-    xhci_setup_packet(xfer, dev);
-
     switch(epctx->type) {
     case ET_INTR_OUT:
     case ET_INTR_IN:
@@ -1377,7 +1374,10 @@ static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx
         return -1;
     }
 
-    ret = usb_handle_packet(dev, &xfer->packet);
+    if (xhci_setup_packet(xfer) < 0) {
+        return -1;
+    }
+    ret = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
 
     xhci_complete_packet(xfer, ret);
     if (!xfer->running_async && !xfer->running_retry) {
@@ -1420,7 +1420,9 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
 
         trace_usb_xhci_xfer_retry(xfer);
         assert(xfer->running_retry);
-        xhci_setup_packet(xfer, xfer->packet.ep->dev);
+        if (xhci_setup_packet(xfer) < 0) {
+            return;
+        }
         result = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
         if (result == USB_RET_NAK) {
             return;
-- 
1.7.1

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

* [Qemu-devel] [PATCH 34/54] xhci: implement mfindex
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (32 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 33/54] xhci: move device lookup into xhci_setup_packet Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 35/54] xhci: iso xfer support Gerd Hoffmann
                   ` (20 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Implement mfindex register and mfindex wrap event.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-xhci.c |   53 ++++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 46 insertions(+), 7 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 303e1ac..9077cb3 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -380,8 +380,6 @@ struct XHCIState {
     XHCISlot slots[MAXSLOTS];
 
     /* Runtime Registers */
-    uint32_t mfindex;
-    /* note: we only support one interrupter */
     uint32_t iman;
     uint32_t imod;
     uint32_t erstsz;
@@ -390,6 +388,9 @@ struct XHCIState {
     uint32_t erdp_low;
     uint32_t erdp_high;
 
+    int64_t mfindex_start;
+    QEMUTimer *mfwrap_timer;
+
     dma_addr_t er_start;
     uint32_t er_size;
     bool er_pcs;
@@ -410,6 +411,11 @@ typedef struct XHCIEvRingSeg {
     uint32_t rsvd;
 } XHCIEvRingSeg;
 
+static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
+                         unsigned int epid);
+static void xhci_event(XHCIState *xhci, XHCIEvent *event);
+static void xhci_write_event(XHCIState *xhci, XHCIEvent *event);
+
 static const char *TRBType_names[] = {
     [TRB_RESERVED]                     = "TRB_RESERVED",
     [TR_NORMAL]                        = "TR_NORMAL",
@@ -462,8 +468,36 @@ static const char *trb_name(XHCITRB *trb)
                        ARRAY_SIZE(TRBType_names));
 }
 
-static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
-                         unsigned int epid);
+static uint64_t xhci_mfindex_get(XHCIState *xhci)
+{
+    int64_t now = qemu_get_clock_ns(vm_clock);
+    return (now - xhci->mfindex_start) / 125000;
+}
+
+static void xhci_mfwrap_update(XHCIState *xhci)
+{
+    const uint32_t bits = USBCMD_RS | USBCMD_EWE;
+    uint32_t mfindex, left;
+    int64_t now;
+
+    if ((xhci->usbcmd & bits) == bits) {
+        now = qemu_get_clock_ns(vm_clock);
+        mfindex = ((now - xhci->mfindex_start) / 125000) & 0x3fff;
+        left = 0x4000 - mfindex;
+        qemu_mod_timer(xhci->mfwrap_timer, now + left * 125000);
+    } else {
+        qemu_del_timer(xhci->mfwrap_timer);
+    }
+}
+
+static void xhci_mfwrap_timer(void *opaque)
+{
+    XHCIState *xhci = opaque;
+    XHCIEvent wrap = { ER_MFINDEX_WRAP, CC_SUCCESS };
+
+    xhci_event(xhci, &wrap);
+    xhci_mfwrap_update(xhci);
+}
 
 static inline dma_addr_t xhci_addr64(uint32_t low, uint32_t high)
 {
@@ -793,6 +827,7 @@ static void xhci_run(XHCIState *xhci)
 {
     trace_usb_xhci_run();
     xhci->usbsts &= ~USBSTS_HCH;
+    xhci->mfindex_start = qemu_get_clock_ns(vm_clock);
 }
 
 static void xhci_stop(XHCIState *xhci)
@@ -2050,7 +2085,6 @@ static void xhci_reset(DeviceState *dev)
         xhci_update_port(xhci, xhci->ports + i, 0);
     }
 
-    xhci->mfindex = 0;
     xhci->iman = 0;
     xhci->imod = 0;
     xhci->erstsz = 0;
@@ -2064,6 +2098,9 @@ static void xhci_reset(DeviceState *dev)
     xhci->er_full = 0;
     xhci->ev_buffer_put = 0;
     xhci->ev_buffer_get = 0;
+
+    xhci->mfindex_start = qemu_get_clock_ns(vm_clock);
+    xhci_mfwrap_update(xhci);
 }
 
 static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg)
@@ -2266,6 +2303,7 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val)
             xhci_stop(xhci);
         }
         xhci->usbcmd = val & 0xc0f;
+        xhci_mfwrap_update(xhci);
         if (val & USBCMD_HCRST) {
             xhci_reset(&xhci->pci_dev.qdev);
         }
@@ -2317,8 +2355,7 @@ static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg)
 
     switch (reg) {
     case 0x00: /* MFINDEX */
-        fprintf(stderr, "xhci_runtime_read: MFINDEX not yet implemented\n");
-        ret = xhci->mfindex;
+        ret = xhci_mfindex_get(xhci) & 0x3fff;
         break;
     case 0x20: /* IMAN */
         ret = xhci->iman;
@@ -2618,6 +2655,8 @@ static int usb_xhci_initfn(struct PCIDevice *dev)
 
     usb_xhci_init(xhci, &dev->qdev);
 
+    xhci->mfwrap_timer = qemu_new_timer_ns(vm_clock, xhci_mfwrap_timer, xhci);
+
     xhci->irq = xhci->pci_dev.irq[0];
 
     memory_region_init_io(&xhci->mem, &xhci_mem_ops, xhci,
-- 
1.7.1

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

* [Qemu-devel] [PATCH 35/54] xhci: iso xfer support
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (33 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 34/54] xhci: implement mfindex Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 36/54] xhci: trace cc codes in cleartext Gerd Hoffmann
                   ` (19 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add support for iso transfers.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-xhci.c |  117 +++++++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 101 insertions(+), 16 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 9077cb3..3c61bb8 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -325,9 +325,15 @@ typedef struct XHCITransfer {
     unsigned int pkts;
     unsigned int pktsize;
     unsigned int cur_pkt;
+
+    uint64_t mfindex_kick;
 } XHCITransfer;
 
 typedef struct XHCIEPContext {
+    XHCIState *xhci;
+    unsigned int slotid;
+    unsigned int epid;
+
     XHCIRing ring;
     unsigned int next_xfer;
     unsigned int comp_xfer;
@@ -337,6 +343,11 @@ typedef struct XHCIEPContext {
     dma_addr_t pctx;
     unsigned int max_psize;
     uint32_t state;
+
+    /* iso xfer scheduling */
+    unsigned int interval;
+    int64_t mfindex_last;
+    QEMUTimer *kick_timer;
 } XHCIEPContext;
 
 typedef struct XHCISlot {
@@ -856,6 +867,12 @@ static void xhci_set_ep_state(XHCIState *xhci, XHCIEPContext *epctx,
     epctx->state = state;
 }
 
+static void xhci_ep_kick_timer(void *opaque)
+{
+    XHCIEPContext *epctx = opaque;
+    xhci_kick_ep(epctx->xhci, epctx->slotid, epctx->epid);
+}
+
 static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid,
                                unsigned int epid, dma_addr_t pctx,
                                uint32_t *ctx)
@@ -877,6 +894,9 @@ static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid,
 
     epctx = g_malloc(sizeof(XHCIEPContext));
     memset(epctx, 0, sizeof(XHCIEPContext));
+    epctx->xhci = xhci;
+    epctx->slotid = slotid;
+    epctx->epid = epid;
 
     slot->eps[epid-1] = epctx;
 
@@ -895,6 +915,10 @@ static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid,
         usb_packet_init(&epctx->transfers[i].packet);
     }
 
+    epctx->interval = 1 << (ctx[0] >> 16) & 0xff;
+    epctx->mfindex_last = 0;
+    epctx->kick_timer = qemu_new_timer_ns(vm_clock, xhci_ep_kick_timer, epctx);
+
     epctx->state = EP_RUNNING;
     ctx[0] &= ~EP_STATE_MASK;
     ctx[0] |= EP_RUNNING;
@@ -934,6 +958,7 @@ static int xhci_ep_nuke_xfers(XHCIState *xhci, unsigned int slotid,
         if (t->running_retry) {
             t->running_retry = 0;
             epctx->retry = NULL;
+            qemu_del_timer(epctx->kick_timer);
         }
         if (t->trbs) {
             g_free(t->trbs);
@@ -969,6 +994,7 @@ static TRBCCode xhci_disable_ep(XHCIState *xhci, unsigned int slotid,
 
     xhci_set_ep_state(xhci, epctx, EP_DISABLED);
 
+    qemu_free_timer(epctx->kick_timer);
     g_free(epctx);
     slot->eps[epid-1] = NULL;
 
@@ -1378,29 +1404,70 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
     return 0;
 }
 
+static void xhci_calc_iso_kick(XHCIState *xhci, XHCITransfer *xfer,
+                               XHCIEPContext *epctx, uint64_t mfindex)
+{
+    if (xfer->trbs[0].control & TRB_TR_SIA) {
+        uint64_t asap = ((mfindex + epctx->interval - 1) &
+                         ~(epctx->interval-1));
+        if (asap >= epctx->mfindex_last &&
+            asap <= epctx->mfindex_last + epctx->interval * 4) {
+            xfer->mfindex_kick = epctx->mfindex_last + epctx->interval;
+        } else {
+            xfer->mfindex_kick = asap;
+        }
+    } else {
+        xfer->mfindex_kick = (xfer->trbs[0].control >> TRB_TR_FRAMEID_SHIFT)
+            & TRB_TR_FRAMEID_MASK;
+        xfer->mfindex_kick |= mfindex & ~0x3fff;
+        if (xfer->mfindex_kick < mfindex) {
+            xfer->mfindex_kick += 0x4000;
+        }
+    }
+}
+
+static void xhci_check_iso_kick(XHCIState *xhci, XHCITransfer *xfer,
+                                XHCIEPContext *epctx, uint64_t mfindex)
+{
+    if (xfer->mfindex_kick > mfindex) {
+        qemu_mod_timer(epctx->kick_timer, qemu_get_clock_ns(vm_clock) +
+                       (xfer->mfindex_kick - mfindex) * 125000);
+        xfer->running_retry = 1;
+    } else {
+        epctx->mfindex_last = xfer->mfindex_kick;
+        qemu_del_timer(epctx->kick_timer);
+        xfer->running_retry = 0;
+    }
+}
+
+
 static int xhci_submit(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext *epctx)
 {
+    uint64_t mfindex;
     int ret;
 
     DPRINTF("xhci_submit(slotid=%d,epid=%d)\n", xfer->slotid, xfer->epid);
 
     xfer->in_xfer = epctx->type>>2;
 
-    if (epctx->type == ET_ISO_IN || epctx->type == ET_ISO_OUT) {
-        xfer->pkts = 1;
-    } else {
-        xfer->pkts = 0;
-    }
-
     switch(epctx->type) {
     case ET_INTR_OUT:
     case ET_INTR_IN:
     case ET_BULK_OUT:
     case ET_BULK_IN:
+        xfer->pkts = 0;
+        xfer->iso_xfer = false;
         break;
     case ET_ISO_OUT:
     case ET_ISO_IN:
-        FIXME();
+        xfer->pkts = 1;
+        xfer->iso_xfer = true;
+        mfindex = xhci_mfindex_get(xhci);
+        xhci_calc_iso_kick(xhci, xfer, epctx, mfindex);
+        xhci_check_iso_kick(xhci, xfer, epctx, mfindex);
+        if (xfer->running_retry) {
+            return -1;
+        }
         break;
     default:
         fprintf(stderr, "xhci: unknown or unhandled EP "
@@ -1430,6 +1497,7 @@ static int xhci_fire_transfer(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext
 static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid)
 {
     XHCIEPContext *epctx;
+    uint64_t mfindex;
     int length;
     int i;
 
@@ -1449,20 +1517,35 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
     }
 
     if (epctx->retry) {
-        /* retry nak'ed transfer */
         XHCITransfer *xfer = epctx->retry;
         int result;
 
         trace_usb_xhci_xfer_retry(xfer);
         assert(xfer->running_retry);
-        if (xhci_setup_packet(xfer) < 0) {
-            return;
-        }
-        result = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
-        if (result == USB_RET_NAK) {
-            return;
+        if (xfer->iso_xfer) {
+            /* retry delayed iso transfer */
+            mfindex = xhci_mfindex_get(xhci);
+            xhci_check_iso_kick(xhci, xfer, epctx, mfindex);
+            if (xfer->running_retry) {
+                return;
+            }
+            if (xhci_setup_packet(xfer) < 0) {
+                return;
+            }
+            result = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
+            assert(result != USB_RET_NAK);
+            xhci_complete_packet(xfer, result);
+        } else {
+            /* retry nak'ed transfer */
+            if (xhci_setup_packet(xfer) < 0) {
+                return;
+            }
+            result = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
+            if (result == USB_RET_NAK) {
+                return;
+            }
+            xhci_complete_packet(xfer, result);
         }
-        xhci_complete_packet(xfer, result);
         assert(!xfer->running_retry);
         epctx->retry = NULL;
     }
@@ -1514,7 +1597,9 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
             if (xhci_fire_transfer(xhci, xfer, epctx) >= 0) {
                 epctx->next_xfer = (epctx->next_xfer + 1) % TD_QUEUE;
             } else {
-                fprintf(stderr, "xhci: error firing data transfer\n");
+                if (!xfer->iso_xfer) {
+                    fprintf(stderr, "xhci: error firing data transfer\n");
+                }
             }
         }
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH 36/54] xhci: trace cc codes in cleartext
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (34 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 35/54] xhci: iso xfer support Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 37/54] xhci: add trace_usb_xhci_ep_set_dequeue Gerd Hoffmann
                   ` (18 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-xhci.c |   48 +++++++++++++++++++++++++++++++++++++++++++++++-
 trace-events      |    2 +-
 2 files changed, 48 insertions(+), 2 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 3c61bb8..ab32a7b 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -465,6 +465,45 @@ static const char *TRBType_names[] = {
     [CR_VENDOR_NEC_CHALLENGE_RESPONSE] = "CR_VENDOR_NEC_CHALLENGE_RESPONSE",
 };
 
+static const char *TRBCCode_names[] = {
+    [CC_INVALID]                       = "CC_INVALID",
+    [CC_SUCCESS]                       = "CC_SUCCESS",
+    [CC_DATA_BUFFER_ERROR]             = "CC_DATA_BUFFER_ERROR",
+    [CC_BABBLE_DETECTED]               = "CC_BABBLE_DETECTED",
+    [CC_USB_TRANSACTION_ERROR]         = "CC_USB_TRANSACTION_ERROR",
+    [CC_TRB_ERROR]                     = "CC_TRB_ERROR",
+    [CC_STALL_ERROR]                   = "CC_STALL_ERROR",
+    [CC_RESOURCE_ERROR]                = "CC_RESOURCE_ERROR",
+    [CC_BANDWIDTH_ERROR]               = "CC_BANDWIDTH_ERROR",
+    [CC_NO_SLOTS_ERROR]                = "CC_NO_SLOTS_ERROR",
+    [CC_INVALID_STREAM_TYPE_ERROR]     = "CC_INVALID_STREAM_TYPE_ERROR",
+    [CC_SLOT_NOT_ENABLED_ERROR]        = "CC_SLOT_NOT_ENABLED_ERROR",
+    [CC_EP_NOT_ENABLED_ERROR]          = "CC_EP_NOT_ENABLED_ERROR",
+    [CC_SHORT_PACKET]                  = "CC_SHORT_PACKET",
+    [CC_RING_UNDERRUN]                 = "CC_RING_UNDERRUN",
+    [CC_RING_OVERRUN]                  = "CC_RING_OVERRUN",
+    [CC_VF_ER_FULL]                    = "CC_VF_ER_FULL",
+    [CC_PARAMETER_ERROR]               = "CC_PARAMETER_ERROR",
+    [CC_BANDWIDTH_OVERRUN]             = "CC_BANDWIDTH_OVERRUN",
+    [CC_CONTEXT_STATE_ERROR]           = "CC_CONTEXT_STATE_ERROR",
+    [CC_NO_PING_RESPONSE_ERROR]        = "CC_NO_PING_RESPONSE_ERROR",
+    [CC_EVENT_RING_FULL_ERROR]         = "CC_EVENT_RING_FULL_ERROR",
+    [CC_INCOMPATIBLE_DEVICE_ERROR]     = "CC_INCOMPATIBLE_DEVICE_ERROR",
+    [CC_MISSED_SERVICE_ERROR]          = "CC_MISSED_SERVICE_ERROR",
+    [CC_COMMAND_RING_STOPPED]          = "CC_COMMAND_RING_STOPPED",
+    [CC_COMMAND_ABORTED]               = "CC_COMMAND_ABORTED",
+    [CC_STOPPED]                       = "CC_STOPPED",
+    [CC_STOPPED_LENGTH_INVALID]        = "CC_STOPPED_LENGTH_INVALID",
+    [CC_MAX_EXIT_LATENCY_TOO_LARGE_ERROR]
+    = "CC_MAX_EXIT_LATENCY_TOO_LARGE_ERROR",
+    [CC_ISOCH_BUFFER_OVERRUN]          = "CC_ISOCH_BUFFER_OVERRUN",
+    [CC_EVENT_LOST_ERROR]              = "CC_EVENT_LOST_ERROR",
+    [CC_UNDEFINED_ERROR]               = "CC_UNDEFINED_ERROR",
+    [CC_INVALID_STREAM_ID_ERROR]       = "CC_INVALID_STREAM_ID_ERROR",
+    [CC_SECONDARY_BANDWIDTH_ERROR]     = "CC_SECONDARY_BANDWIDTH_ERROR",
+    [CC_SPLIT_TRANSACTION_ERROR]       = "CC_SPLIT_TRANSACTION_ERROR",
+};
+
 static const char *lookup_name(uint32_t index, const char **list, uint32_t llen)
 {
     if (index >= llen || list[index] == NULL) {
@@ -479,6 +518,12 @@ static const char *trb_name(XHCITRB *trb)
                        ARRAY_SIZE(TRBType_names));
 }
 
+static const char *event_name(XHCIEvent *event)
+{
+    return lookup_name(event->ccode, TRBCCode_names,
+                       ARRAY_SIZE(TRBCCode_names));
+}
+
 static uint64_t xhci_mfindex_get(XHCIState *xhci)
 {
     int64_t now = qemu_get_clock_ns(vm_clock);
@@ -574,7 +619,8 @@ static void xhci_write_event(XHCIState *xhci, XHCIEvent *event)
     ev_trb.control = cpu_to_le32(ev_trb.control);
 
     trace_usb_xhci_queue_event(xhci->er_ep_idx, trb_name(&ev_trb),
-                               ev_trb.parameter, ev_trb.status, ev_trb.control);
+                               event_name(event), ev_trb.parameter,
+                               ev_trb.status, ev_trb.control);
 
     addr = xhci->er_start + TRB_SIZE*xhci->er_ep_idx;
     pci_dma_write(&xhci->pci_dev, addr, &ev_trb, TRB_SIZE);
diff --git a/trace-events b/trace-events
index ba4b112..a642fad 100644
--- a/trace-events
+++ b/trace-events
@@ -313,7 +313,7 @@ usb_xhci_runtime_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
 usb_xhci_doorbell_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
 usb_xhci_irq_intx(uint32_t level) "level %d"
 usb_xhci_irq_msi(uint32_t nr) "nr %d"
-usb_xhci_queue_event(uint32_t idx, const char *name, uint64_t param, uint32_t status, uint32_t control) "idx %d, %s, p %016" PRIx64 ", s %08x, c 0x%08x"
+usb_xhci_queue_event(uint32_t idx, const char *trb, const char *evt, uint64_t param, uint32_t status, uint32_t control) "idx %d, %s, %s, p %016" PRIx64 ", s %08x, c 0x%08x"
 usb_xhci_fetch_trb(uint64_t addr, const char *name, uint64_t param, uint32_t status, uint32_t control) "addr %016" PRIx64 ", %s, p %016" PRIx64 ", s %08x, c 0x%08x"
 usb_xhci_slot_enable(uint32_t slotid) "slotid %d"
 usb_xhci_slot_disable(uint32_t slotid) "slotid %d"
-- 
1.7.1

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

* [Qemu-devel] [PATCH 37/54] xhci: add trace_usb_xhci_ep_set_dequeue
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (35 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 36/54] xhci: trace cc codes in cleartext Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 38/54] xhci: fix runtime write tracepoint Gerd Hoffmann
                   ` (17 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-xhci.c |    2 +-
 trace-events      |    1 +
 2 files changed, 2 insertions(+), 1 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index ab32a7b..5cdaf76 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -1145,7 +1145,7 @@ static TRBCCode xhci_set_ep_dequeue(XHCIState *xhci, unsigned int slotid,
         return CC_TRB_ERROR;
     }
 
-    DPRINTF("xhci_set_ep_dequeue(%d, %d, %016"PRIx64")\n", slotid, epid, pdequeue);
+    trace_usb_xhci_ep_set_dequeue(slotid, epid, pdequeue);
     dequeue = xhci_mask64(pdequeue);
 
     slot = &xhci->slots[slotid-1];
diff --git a/trace-events b/trace-events
index a642fad..8fa683d 100644
--- a/trace-events
+++ b/trace-events
@@ -323,6 +323,7 @@ usb_xhci_slot_evaluate(uint32_t slotid) "slotid %d"
 usb_xhci_slot_reset(uint32_t slotid) "slotid %d"
 usb_xhci_ep_enable(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
 usb_xhci_ep_disable(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
+usb_xhci_ep_set_dequeue(uint32_t slotid, uint32_t epid, uint64_t param) "slotid %d, epid %d, ptr %016" PRIx64
 usb_xhci_ep_kick(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
 usb_xhci_ep_stop(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
 usb_xhci_ep_reset(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
-- 
1.7.1

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

* [Qemu-devel] [PATCH 38/54] xhci: fix runtime write tracepoint
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (36 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 37/54] xhci: add trace_usb_xhci_ep_set_dequeue Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 39/54] xhci: update register layout Gerd Hoffmann
                   ` (16 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-xhci.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 5cdaf76..e8d2372 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -2520,7 +2520,7 @@ static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg)
 
 static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val)
 {
-    trace_usb_xhci_runtime_read(reg, val);
+    trace_usb_xhci_runtime_write(reg, val);
 
     switch (reg) {
     case 0x20: /* IMAN */
-- 
1.7.1

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

* [Qemu-devel] [PATCH 39/54] xhci: update register layout
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (37 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 38/54] xhci: fix runtime write tracepoint Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 40/54] xhci: update port handling Gerd Hoffmann
                   ` (15 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Change the register layout to be a bit more sparse and also not depend
on the number of ports.  Useful when for making the number of ports
runtime-configurable.
---
 hw/usb/hcd-xhci.c |   21 +++++++++++++--------
 1 files changed, 13 insertions(+), 8 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index e8d2372..414b633 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -36,13 +36,12 @@
 #define FIXME() do { fprintf(stderr, "FIXME %s:%d\n", \
                              __func__, __LINE__); abort(); } while (0)
 
-#define MAXSLOTS 8
-#define MAXINTRS 1
-
 #define USB2_PORTS 4
 #define USB3_PORTS 4
 
 #define MAXPORTS (USB2_PORTS+USB3_PORTS)
+#define MAXSLOTS MAXPORTS
+#define MAXINTRS 1 /* MAXPORTS */
 
 #define TD_QUEUE 24
 
@@ -53,16 +52,22 @@
 #define ER_FULL_HACK
 
 #define LEN_CAP         0x40
-#define OFF_OPER        LEN_CAP
 #define LEN_OPER        (0x400 + 0x10 * MAXPORTS)
-#define OFF_RUNTIME     ((OFF_OPER + LEN_OPER + 0x20) & ~0x1f)
-#define LEN_RUNTIME     (0x20 + MAXINTRS * 0x20)
-#define OFF_DOORBELL    (OFF_RUNTIME + LEN_RUNTIME)
+#define LEN_RUNTIME     ((MAXINTRS + 1) * 0x20)
 #define LEN_DOORBELL    ((MAXSLOTS + 1) * 0x20)
 
+#define OFF_OPER        LEN_CAP
+#define OFF_RUNTIME     0x1000
+#define OFF_DOORBELL    0x2000
 /* must be power of 2 */
-#define LEN_REGS        0x2000
+#define LEN_REGS        0x4000
 
+#if (OFF_OPER + LEN_OPER) > OFF_RUNTIME
+#error Increase OFF_RUNTIME
+#endif
+#if (OFF_RUNTIME + LEN_RUNTIME) > OFF_DOORBELL
+#error Increase OFF_DOORBELL
+#endif
 #if (OFF_DOORBELL + LEN_DOORBELL) > LEN_REGS
 # error Increase LEN_REGS
 #endif
-- 
1.7.1

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

* [Qemu-devel] [PATCH 40/54] xhci: update port handling
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (38 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 39/54] xhci: update register layout Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 41/54] usb3: superspeed descriptors Gerd Hoffmann
                   ` (14 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

This patch changes the way xhci ports are linked to USBPorts.  The fixed
1:1 relationship between xhci ports and USBPorts is gone.  Now each
USBPort represents a physical plug which has usually two xhci ports
assigned: one usb2 and ond usb3 port.  usb devices show up at one or the
other, depending on whenever they support superspeed or not.

This patch also makes the number of usb2 and usb3 ports runtime
configurable by adding 'p2' and 'p3' properties.  It is allowed to
have different numbers of usb2 and usb3 ports.  Specifying p2=4,p3=2
will give you an xhci adapter which supports all speeds on physical
ports 1+2 and usb2 only on ports 3+4.
---
 hw/usb/hcd-xhci.c |  137 +++++++++++++++++++++++++++++++++++++---------------
 1 files changed, 97 insertions(+), 40 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 414b633..e08312e 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -36,10 +36,10 @@
 #define FIXME() do { fprintf(stderr, "FIXME %s:%d\n", \
                              __func__, __LINE__); abort(); } while (0)
 
-#define USB2_PORTS 4
-#define USB3_PORTS 4
+#define MAXPORTS_2 8
+#define MAXPORTS_3 8
 
-#define MAXPORTS (USB2_PORTS+USB3_PORTS)
+#define MAXPORTS (MAXPORTS_2+MAXPORTS_3)
 #define MAXSLOTS MAXPORTS
 #define MAXINTRS 1 /* MAXPORTS */
 
@@ -300,8 +300,10 @@ typedef struct XHCIRing {
 } XHCIRing;
 
 typedef struct XHCIPort {
-    USBPort port;
     uint32_t portsc;
+    uint32_t portnr;
+    USBPort  *uport;
+    uint32_t speedmask;
 } XHCIPort;
 
 struct XHCIState;
@@ -379,9 +381,13 @@ struct XHCIState {
     qemu_irq irq;
     MemoryRegion mem;
     const char *name;
-    uint32_t msi;
     unsigned int devaddr;
 
+    /* properties */
+    uint32_t numports_2;
+    uint32_t numports_3;
+    uint32_t msi;
+
     /* Operational Registers */
     uint32_t usbcmd;
     uint32_t usbsts;
@@ -392,8 +398,10 @@ struct XHCIState {
     uint32_t dcbaap_high;
     uint32_t config;
 
+    USBPort  uports[MAX(MAXPORTS_2, MAXPORTS_3)];
     XHCIPort ports[MAXPORTS];
     XHCISlot slots[MAXSLOTS];
+    uint32_t numports;
 
     /* Runtime Registers */
     uint32_t iman;
@@ -578,6 +586,28 @@ static inline dma_addr_t xhci_mask64(uint64_t addr)
     }
 }
 
+static XHCIPort *xhci_lookup_port(XHCIState *xhci, struct USBPort *uport)
+{
+    int index;
+
+    if (!uport->dev) {
+        return NULL;
+    }
+    switch (uport->dev->speed) {
+    case USB_SPEED_LOW:
+    case USB_SPEED_FULL:
+    case USB_SPEED_HIGH:
+        index = uport->index;
+        break;
+    case USB_SPEED_SUPER:
+        index = uport->index + xhci->numports_2;
+        break;
+    default:
+        return NULL;
+    }
+    return &xhci->ports[index];
+}
+
 static void xhci_irq_update(XHCIState *xhci)
 {
     int level = 0;
@@ -1126,7 +1156,7 @@ static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid,
         ep |= 0x80;
     }
 
-    dev = xhci->ports[xhci->slots[slotid-1].port-1].port.dev;
+    dev = xhci->ports[xhci->slots[slotid-1].port-1].uport->dev;
     if (!dev) {
         return CC_USB_TRANSACTION_ERROR;
     }
@@ -1313,7 +1343,7 @@ static USBDevice *xhci_find_device(XHCIPort *port, uint8_t addr)
     if (!(port->portsc & PORTSC_PED)) {
         return NULL;
     }
-    return usb_find_device(&port->port, addr);
+    return usb_find_device(port->uport, addr);
 }
 
 static int xhci_setup_packet(XHCITransfer *xfer)
@@ -1736,9 +1766,9 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
             ep0_ctx[0], ep0_ctx[1], ep0_ctx[2], ep0_ctx[3], ep0_ctx[4]);
 
     port = (slot_ctx[1]>>16) & 0xFF;
-    dev = xhci->ports[port-1].port.dev;
+    dev = xhci->ports[port-1].uport->dev;
 
-    if (port < 1 || port > MAXPORTS) {
+    if (port < 1 || port > xhci->numports) {
         fprintf(stderr, "xhci: bad port %d\n", port);
         return CC_TRB_ERROR;
     } else if (!dev) {
@@ -1987,7 +2017,7 @@ static unsigned int xhci_get_slot(XHCIState *xhci, XHCIEvent *event, XHCITRB *tr
 static TRBCCode xhci_get_port_bandwidth(XHCIState *xhci, uint64_t pctx)
 {
     dma_addr_t ctx;
-    uint8_t bw_ctx[MAXPORTS+1];
+    uint8_t bw_ctx[xhci->numports+1];
 
     DPRINTF("xhci_get_port_bandwidth()\n");
 
@@ -1997,7 +2027,7 @@ static TRBCCode xhci_get_port_bandwidth(XHCIState *xhci, uint64_t pctx)
 
     /* TODO: actually implement real values here */
     bw_ctx[0] = 0;
-    memset(&bw_ctx[1], 80, MAXPORTS); /* 80% */
+    memset(&bw_ctx[1], 80, xhci->numports); /* 80% */
     pci_dma_write(&xhci->pci_dev, ctx, bw_ctx, sizeof(bw_ctx));
 
     return CC_SUCCESS;
@@ -2167,12 +2197,11 @@ static void xhci_process_commands(XHCIState *xhci)
 
 static void xhci_update_port(XHCIState *xhci, XHCIPort *port, int is_detach)
 {
-    int nr = port->port.index + 1;
-
     port->portsc = PORTSC_PP;
-    if (port->port.dev && port->port.dev->attached && !is_detach) {
+    if (port->uport->dev && port->uport->dev->attached && !is_detach &&
+        (1 << port->uport->dev->speed) & port->speedmask) {
         port->portsc |= PORTSC_CCS;
-        switch (port->port.dev->speed) {
+        switch (port->uport->dev->speed) {
         case USB_SPEED_LOW:
             port->portsc |= PORTSC_SPEED_LOW;
             break;
@@ -2182,14 +2211,18 @@ static void xhci_update_port(XHCIState *xhci, XHCIPort *port, int is_detach)
         case USB_SPEED_HIGH:
             port->portsc |= PORTSC_SPEED_HIGH;
             break;
+        case USB_SPEED_SUPER:
+            port->portsc |= PORTSC_SPEED_SUPER;
+            break;
         }
     }
 
     if (xhci_running(xhci)) {
         port->portsc |= PORTSC_CSC;
-        XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, nr << 24};
+        XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS,
+                         port->portnr << 24};
         xhci_event(xhci, &ev);
-        DPRINTF("xhci: port change event for port %d\n", nr);
+        DPRINTF("xhci: port change event for port %d\n", port->portnr);
     }
 }
 
@@ -2217,7 +2250,7 @@ static void xhci_reset(DeviceState *dev)
         xhci_disable_slot(xhci, i+1);
     }
 
-    for (i = 0; i < MAXPORTS; i++) {
+    for (i = 0; i < xhci->numports; i++) {
         xhci_update_port(xhci, xhci->ports + i, 0);
     }
 
@@ -2248,7 +2281,8 @@ static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg)
         ret = 0x01000000 | LEN_CAP;
         break;
     case 0x04: /* HCSPARAMS 1 */
-        ret = (MAXPORTS<<24) | (MAXINTRS<<8) | MAXSLOTS;
+        ret = ((xhci->numports_2+xhci->numports_3)<<24)
+            | (MAXINTRS<<8) | MAXSLOTS;
         break;
     case 0x08: /* HCSPARAMS 2 */
         ret = 0x0000000f;
@@ -2278,7 +2312,7 @@ static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg)
         ret = 0x20425455; /* "USB " */
         break;
     case 0x28: /* Supported Protocol:08 */
-        ret = 0x00000001 | (USB2_PORTS<<8);
+        ret = 0x00000001 | (xhci->numports_2<<8);
         break;
     case 0x2c: /* Supported Protocol:0c */
         ret = 0x00000000; /* reserved */
@@ -2290,7 +2324,7 @@ static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg)
         ret = 0x20425455; /* "USB " */
         break;
     case 0x38: /* Supported Protocol:08 */
-        ret = 0x00000000 | (USB2_PORTS+1) | (USB3_PORTS<<8);
+        ret = 0x00000000 | (xhci->numports_2+1) | (xhci->numports_3<<8);
         break;
     case 0x3c: /* Supported Protocol:0c */
         ret = 0x00000000; /* reserved */
@@ -2309,7 +2343,7 @@ static uint32_t xhci_port_read(XHCIState *xhci, uint32_t reg)
     uint32_t port = reg >> 4;
     uint32_t ret;
 
-    if (port >= MAXPORTS) {
+    if (port >= xhci->numports) {
         fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port);
         ret = 0;
         goto out;
@@ -2342,7 +2376,7 @@ static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
 
     trace_usb_xhci_port_write(port, reg & 0x0f, val);
 
-    if (port >= MAXPORTS) {
+    if (port >= xhci->numports) {
         fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port);
         return;
     }
@@ -2364,7 +2398,7 @@ static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
         /* write-1-to-start bits */
         if (val & PORTSC_PR) {
             DPRINTF("xhci: port %d reset\n", port);
-            usb_device_reset(xhci->ports[port].port.dev);
+            usb_device_reset(xhci->ports[port].uport->dev);
             portsc |= PORTSC_PRC | PORTSC_PED;
         }
         xhci->ports[port].portsc = portsc;
@@ -2659,7 +2693,7 @@ static const MemoryRegionOps xhci_mem_ops = {
 static void xhci_attach(USBPort *usbport)
 {
     XHCIState *xhci = usbport->opaque;
-    XHCIPort *port = &xhci->ports[usbport->index];
+    XHCIPort *port = xhci_lookup_port(xhci, usbport);
 
     xhci_update_port(xhci, port, 0);
 }
@@ -2667,7 +2701,7 @@ static void xhci_attach(USBPort *usbport)
 static void xhci_detach(USBPort *usbport)
 {
     XHCIState *xhci = usbport->opaque;
-    XHCIPort *port = &xhci->ports[usbport->index];
+    XHCIPort *port = xhci_lookup_port(xhci, usbport);
 
     xhci_update_port(xhci, port, 1);
 }
@@ -2675,9 +2709,9 @@ static void xhci_detach(USBPort *usbport)
 static void xhci_wakeup(USBPort *usbport)
 {
     XHCIState *xhci = usbport->opaque;
-    XHCIPort *port = &xhci->ports[usbport->index];
-    int nr = port->port.index + 1;
-    XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS, nr << 24};
+    XHCIPort *port = xhci_lookup_port(xhci, usbport);
+    XHCIEvent ev = { ER_PORT_STATUS_CHANGE, CC_SUCCESS,
+                     port->portnr << 24};
     uint32_t pls;
 
     pls = (port->portsc >> PORTSC_PLS_SHIFT) & PORTSC_PLS_MASK;
@@ -2759,22 +2793,43 @@ static USBBusOps xhci_bus_ops = {
 
 static void usb_xhci_init(XHCIState *xhci, DeviceState *dev)
 {
-    int i;
+    XHCIPort *port;
+    int i, usbports, speedmask;
 
     xhci->usbsts = USBSTS_HCH;
 
+    if (xhci->numports_2 > MAXPORTS_2) {
+        xhci->numports_2 = MAXPORTS_2;
+    }
+    if (xhci->numports_3 > MAXPORTS_3) {
+        xhci->numports_3 = MAXPORTS_3;
+    }
+    usbports = MAX(xhci->numports_2, xhci->numports_3);
+    xhci->numports = xhci->numports_2 + xhci->numports_3;
+
     usb_bus_new(&xhci->bus, &xhci_bus_ops, &xhci->pci_dev.qdev);
 
-    for (i = 0; i < MAXPORTS; i++) {
-        memset(&xhci->ports[i], 0, sizeof(xhci->ports[i]));
-        usb_register_port(&xhci->bus, &xhci->ports[i].port, xhci, i,
-                          &xhci_port_ops,
-                          USB_SPEED_MASK_LOW  |
-                          USB_SPEED_MASK_FULL |
-                          USB_SPEED_MASK_HIGH);
-    }
-    for (i = 0; i < MAXSLOTS; i++) {
-        xhci->slots[i].enabled = 0;
+    for (i = 0; i < usbports; i++) {
+        speedmask = 0;
+        if (i < xhci->numports_2) {
+            port = &xhci->ports[i];
+            port->portnr = i + 1;
+            port->uport = &xhci->uports[i];
+            port->speedmask =
+                USB_SPEED_MASK_LOW  |
+                USB_SPEED_MASK_FULL |
+                USB_SPEED_MASK_HIGH;
+            speedmask |= port->speedmask;
+        }
+        if (i < xhci->numports_3) {
+            port = &xhci->ports[i + xhci->numports_2];
+            port->portnr = i + 1 + xhci->numports_2;
+            port->uport = &xhci->uports[i];
+            port->speedmask = USB_SPEED_MASK_SUPER;
+            speedmask |= port->speedmask;
+        }
+        usb_register_port(&xhci->bus, &xhci->uports[i], xhci, i,
+                          &xhci_port_ops, speedmask);
     }
 }
 
@@ -2830,6 +2885,8 @@ static const VMStateDescription vmstate_xhci = {
 
 static Property xhci_properties[] = {
     DEFINE_PROP_UINT32("msi", XHCIState, msi, 0),
+    DEFINE_PROP_UINT32("p2",  XHCIState, numports_2, 4),
+    DEFINE_PROP_UINT32("p3",  XHCIState, numports_3, 4),
     DEFINE_PROP_END_OF_LIST(),
 };
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH 41/54] usb3: superspeed descriptors
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (39 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 40/54] xhci: update port handling Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 42/54] usb3: superspeed endpoint companion Gerd Hoffmann
                   ` (13 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add superspeed descriptor entry to USBDesc,
advertise superspeed support when present.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/desc.c |   10 +++++++++-
 hw/usb/desc.h |    1 +
 2 files changed, 10 insertions(+), 1 deletions(-)

diff --git a/hw/usb/desc.c b/hw/usb/desc.c
index 0a9d3c9..3e8c6cb 100644
--- a/hw/usb/desc.c
+++ b/hw/usb/desc.c
@@ -359,6 +359,9 @@ static void usb_desc_setdefaults(USBDevice *dev)
     case USB_SPEED_HIGH:
         dev->device = desc->high;
         break;
+    case USB_SPEED_SUPER:
+        dev->device = desc->super;
+        break;
     }
     usb_desc_set_config(dev, 0);
 }
@@ -376,6 +379,9 @@ void usb_desc_init(USBDevice *dev)
     if (desc->high) {
         dev->speedmask |= USB_SPEED_MASK_HIGH;
     }
+    if (desc->super) {
+        dev->speedmask |= USB_SPEED_MASK_SUPER;
+    }
     usb_desc_setdefaults(dev);
 }
 
@@ -384,7 +390,9 @@ void usb_desc_attach(USBDevice *dev)
     const USBDesc *desc = usb_device_get_usb_desc(dev);
 
     assert(desc != NULL);
-    if (desc->high && (dev->port->speedmask & USB_SPEED_MASK_HIGH)) {
+    if (desc->super && (dev->port->speedmask & USB_SPEED_MASK_SUPER)) {
+        dev->speed = USB_SPEED_SUPER;
+    } else if (desc->high && (dev->port->speedmask & USB_SPEED_MASK_HIGH)) {
         dev->speed = USB_SPEED_HIGH;
     } else if (desc->full && (dev->port->speedmask & USB_SPEED_MASK_FULL)) {
         dev->speed = USB_SPEED_FULL;
diff --git a/hw/usb/desc.h b/hw/usb/desc.h
index 7cf5442..d89fa41 100644
--- a/hw/usb/desc.h
+++ b/hw/usb/desc.h
@@ -152,6 +152,7 @@ struct USBDesc {
     USBDescID                 id;
     const USBDescDevice       *full;
     const USBDescDevice       *high;
+    const USBDescDevice       *super;
     const char* const         *str;
 };
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH 42/54] usb3: superspeed endpoint companion
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (40 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 41/54] usb3: superspeed descriptors Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 43/54] usb3: bos decriptor Gerd Hoffmann
                   ` (12 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add support for building superspeed endpoint companion descriptors,
create them for superspeed usb devices.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb.h      |    1 +
 hw/usb/desc.c |   55 ++++++++++++++++++++++++++++++++++++++++---------------
 hw/usb/desc.h |   26 +++++++++++++++++++++-----
 3 files changed, 62 insertions(+), 20 deletions(-)

diff --git a/hw/usb.h b/hw/usb.h
index 684e3f4..78ffdf4 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -137,6 +137,7 @@
 #define USB_DT_INTERFACE_ASSOC          0x0B
 #define USB_DT_CS_INTERFACE             0x24
 #define USB_DT_CS_ENDPOINT              0x25
+#define USB_DT_ENDPOINT_COMPANION       0x30
 
 #define USB_ENDPOINT_XFER_CONTROL	0
 #define USB_ENDPOINT_XFER_ISOC		1
diff --git a/hw/usb/desc.c b/hw/usb/desc.c
index 3e8c6cb..8f5a8e5 100644
--- a/hw/usb/desc.c
+++ b/hw/usb/desc.c
@@ -76,7 +76,8 @@ int usb_desc_device_qualifier(const USBDescDevice *dev,
     return bLength;
 }
 
-int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len)
+int usb_desc_config(const USBDescConfig *conf, int flags,
+                    uint8_t *dest, size_t len)
 {
     uint8_t  bLength = 0x09;
     uint16_t wTotalLength = 0;
@@ -99,7 +100,7 @@ int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len)
 
     /* handle grouped interfaces if any */
     for (i = 0; i < conf->nif_groups; i++) {
-        rc = usb_desc_iface_group(&(conf->if_groups[i]),
+        rc = usb_desc_iface_group(&(conf->if_groups[i]), flags,
                                   dest + wTotalLength,
                                   len - wTotalLength);
         if (rc < 0) {
@@ -110,7 +111,8 @@ int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len)
 
     /* handle normal (ungrouped / no IAD) interfaces if any */
     for (i = 0; i < conf->nif; i++) {
-        rc = usb_desc_iface(conf->ifs + i, dest + wTotalLength, len - wTotalLength);
+        rc = usb_desc_iface(conf->ifs + i, flags,
+                            dest + wTotalLength, len - wTotalLength);
         if (rc < 0) {
             return rc;
         }
@@ -122,8 +124,8 @@ int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len)
     return wTotalLength;
 }
 
-int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest,
-                         size_t len)
+int usb_desc_iface_group(const USBDescIfaceAssoc *iad, int flags,
+                         uint8_t *dest, size_t len)
 {
     int pos = 0;
     int i = 0;
@@ -147,7 +149,7 @@ int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest,
 
     /* handle associated interfaces in this group */
     for (i = 0; i < iad->nif; i++) {
-        int rc = usb_desc_iface(&(iad->ifs[i]), dest + pos, len - pos);
+        int rc = usb_desc_iface(&(iad->ifs[i]), flags, dest + pos, len - pos);
         if (rc < 0) {
             return rc;
         }
@@ -157,7 +159,8 @@ int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest,
     return pos;
 }
 
-int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len)
+int usb_desc_iface(const USBDescIface *iface, int flags,
+                   uint8_t *dest, size_t len)
 {
     uint8_t bLength = 0x09;
     int i, rc, pos = 0;
@@ -188,7 +191,7 @@ int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len)
     }
 
     for (i = 0; i < iface->bNumEndpoints; i++) {
-        rc = usb_desc_endpoint(iface->eps + i, dest + pos, len - pos);
+        rc = usb_desc_endpoint(iface->eps + i, flags, dest + pos, len - pos);
         if (rc < 0) {
             return rc;
         }
@@ -198,13 +201,15 @@ int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len)
     return pos;
 }
 
-int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len)
+int usb_desc_endpoint(const USBDescEndpoint *ep, int flags,
+                      uint8_t *dest, size_t len)
 {
     uint8_t bLength = ep->is_audio ? 0x09 : 0x07;
     uint8_t extralen = ep->extra ? ep->extra[0] : 0;
+    uint8_t superlen = (flags & USB_DESC_FLAG_SUPER) ? 0x06 : 0;
     USBDescriptor *d = (void *)dest;
 
-    if (len < bLength + extralen) {
+    if (len < bLength + extralen + superlen) {
         return -1;
     }
 
@@ -224,7 +229,21 @@ int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len)
         memcpy(dest + bLength, ep->extra, extralen);
     }
 
-    return bLength + extralen;
+    if (superlen) {
+        USBDescriptor *d = (void *)(dest + bLength + extralen);
+
+        d->bLength                       = 0x06;
+        d->bDescriptorType               = USB_DT_ENDPOINT_COMPANION;
+
+        d->u.super_endpoint.bMaxBurst    = ep->bMaxBurst;
+        d->u.super_endpoint.bmAttributes = ep->bmAttributes_super;
+        d->u.super_endpoint.wBytesPerInterval_lo =
+            usb_lo(ep->wBytesPerInterval);
+        d->u.super_endpoint.wBytesPerInterval_hi =
+            usb_hi(ep->wBytesPerInterval);
+    }
+
+    return bLength + extralen + superlen;
 }
 
 int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
@@ -509,7 +528,7 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
     uint8_t buf[256];
     uint8_t type = value >> 8;
     uint8_t index = value & 0xff;
-    int ret = -1;
+    int flags, ret = -1;
 
     if (dev->speed == USB_SPEED_HIGH) {
         other_dev = usb_device_get_usb_desc(dev)->full;
@@ -517,6 +536,11 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
         other_dev = usb_device_get_usb_desc(dev)->high;
     }
 
+    flags = 0;
+    if (dev->device->bcdUSB >= 0x0300) {
+        flags |= USB_DESC_FLAG_SUPER;
+    }
+
     switch(type) {
     case USB_DT_DEVICE:
         ret = usb_desc_device(&desc->id, dev->device, buf, sizeof(buf));
@@ -524,7 +548,8 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
         break;
     case USB_DT_CONFIG:
         if (index < dev->device->bNumConfigurations) {
-            ret = usb_desc_config(dev->device->confs + index, buf, sizeof(buf));
+            ret = usb_desc_config(dev->device->confs + index, flags,
+                                  buf, sizeof(buf));
         }
         trace_usb_desc_config(dev->addr, index, len, ret);
         break;
@@ -532,7 +557,6 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
         ret = usb_desc_string(dev, index, buf, sizeof(buf));
         trace_usb_desc_string(dev->addr, index, len, ret);
         break;
-
     case USB_DT_DEVICE_QUALIFIER:
         if (other_dev != NULL) {
             ret = usb_desc_device_qualifier(other_dev, buf, sizeof(buf));
@@ -541,7 +565,8 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
         break;
     case USB_DT_OTHER_SPEED_CONFIG:
         if (other_dev != NULL && index < other_dev->bNumConfigurations) {
-            ret = usb_desc_config(other_dev->confs + index, buf, sizeof(buf));
+            ret = usb_desc_config(other_dev->confs + index, flags,
+                                  buf, sizeof(buf));
             buf[0x01] = USB_DT_OTHER_SPEED_CONFIG;
         }
         trace_usb_desc_other_speed_config(dev->addr, index, len, ret);
diff --git a/hw/usb/desc.h b/hw/usb/desc.h
index d89fa41..4b5e88d 100644
--- a/hw/usb/desc.h
+++ b/hw/usb/desc.h
@@ -63,6 +63,12 @@ typedef struct USBDescriptor {
             uint8_t           bRefresh;        /* only audio ep */
             uint8_t           bSynchAddress;   /* only audio ep */
         } endpoint;
+        struct {
+            uint8_t           bMaxBurst;
+            uint8_t           bmAttributes;
+            uint8_t           wBytesPerInterval_lo;
+            uint8_t           wBytesPerInterval_hi;
+        } super_endpoint;
     } u;
 } QEMU_PACKED USBDescriptor;
 
@@ -139,6 +145,11 @@ struct USBDescEndpoint {
 
     uint8_t                   is_audio; /* has bRefresh + bSynchAddress */
     uint8_t                   *extra;
+
+    /* superspeed endpoint companion */
+    uint8_t                   bMaxBurst;
+    uint8_t                   bmAttributes_super;
+    uint16_t                  wBytesPerInterval;
 };
 
 struct USBDescOther {
@@ -156,16 +167,21 @@ struct USBDesc {
     const char* const         *str;
 };
 
+#define USB_DESC_FLAG_SUPER (1 << 1)
+
 /* generate usb packages from structs */
 int usb_desc_device(const USBDescID *id, const USBDescDevice *dev,
                     uint8_t *dest, size_t len);
 int usb_desc_device_qualifier(const USBDescDevice *dev,
                               uint8_t *dest, size_t len);
-int usb_desc_config(const USBDescConfig *conf, uint8_t *dest, size_t len);
-int usb_desc_iface_group(const USBDescIfaceAssoc *iad, uint8_t *dest,
-                         size_t len);
-int usb_desc_iface(const USBDescIface *iface, uint8_t *dest, size_t len);
-int usb_desc_endpoint(const USBDescEndpoint *ep, uint8_t *dest, size_t len);
+int usb_desc_config(const USBDescConfig *conf, int flags,
+                    uint8_t *dest, size_t len);
+int usb_desc_iface_group(const USBDescIfaceAssoc *iad, int flags,
+                         uint8_t *dest, size_t len);
+int usb_desc_iface(const USBDescIface *iface, int flags,
+                   uint8_t *dest, size_t len);
+int usb_desc_endpoint(const USBDescEndpoint *ep, int flags,
+                      uint8_t *dest, size_t len);
 int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len);
 
 /* control message emulation helpers */
-- 
1.7.1

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

* [Qemu-devel] [PATCH 43/54] usb3: bos decriptor
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (41 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 42/54] usb3: superspeed endpoint companion Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 44/54] usb-storage: usb3 support Gerd Hoffmann
                   ` (11 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add support for creating BOS descriptor and
device cappability descriptors.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb.h      |    6 +++
 hw/usb/desc.c |  109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 hw/usb/desc.h |   25 +++++++++++++
 trace-events  |    1 +
 4 files changed, 141 insertions(+), 0 deletions(-)

diff --git a/hw/usb.h b/hw/usb.h
index 78ffdf4..48c8926 100644
--- a/hw/usb.h
+++ b/hw/usb.h
@@ -135,10 +135,16 @@
 #define USB_DT_OTHER_SPEED_CONFIG       0x07
 #define USB_DT_DEBUG                    0x0A
 #define USB_DT_INTERFACE_ASSOC          0x0B
+#define USB_DT_BOS                      0x0F
+#define USB_DT_DEVICE_CAPABILITY        0x10
 #define USB_DT_CS_INTERFACE             0x24
 #define USB_DT_CS_ENDPOINT              0x25
 #define USB_DT_ENDPOINT_COMPANION       0x30
 
+#define USB_DEV_CAP_WIRELESS            0x01
+#define USB_DEV_CAP_USB2_EXT            0x02
+#define USB_DEV_CAP_SUPERSPEED          0x03
+
 #define USB_ENDPOINT_XFER_CONTROL	0
 #define USB_ENDPOINT_XFER_ISOC		1
 #define USB_ENDPOINT_XFER_BULK		2
diff --git a/hw/usb/desc.c b/hw/usb/desc.c
index 8f5a8e5..1f12eae 100644
--- a/hw/usb/desc.c
+++ b/hw/usb/desc.c
@@ -258,6 +258,111 @@ int usb_desc_other(const USBDescOther *desc, uint8_t *dest, size_t len)
     return bLength;
 }
 
+static int usb_desc_cap_usb2_ext(const USBDesc *desc, uint8_t *dest, size_t len)
+{
+    uint8_t  bLength = 0x07;
+    USBDescriptor *d = (void *)dest;
+
+    if (len < bLength) {
+        return -1;
+    }
+
+    d->bLength                          = bLength;
+    d->bDescriptorType                  = USB_DT_DEVICE_CAPABILITY;
+    d->u.cap.bDevCapabilityType         = USB_DEV_CAP_USB2_EXT;
+
+    d->u.cap.u.usb2_ext.bmAttributes_1  = (1 << 1);  /* LPM */
+    d->u.cap.u.usb2_ext.bmAttributes_2  = 0;
+    d->u.cap.u.usb2_ext.bmAttributes_3  = 0;
+    d->u.cap.u.usb2_ext.bmAttributes_4  = 0;
+
+    return bLength;
+}
+
+static int usb_desc_cap_super(const USBDesc *desc, uint8_t *dest, size_t len)
+{
+    uint8_t  bLength = 0x0a;
+    USBDescriptor *d = (void *)dest;
+
+    if (len < bLength) {
+        return -1;
+    }
+
+    d->bLength                           = bLength;
+    d->bDescriptorType                   = USB_DT_DEVICE_CAPABILITY;
+    d->u.cap.bDevCapabilityType          = USB_DEV_CAP_SUPERSPEED;
+
+    d->u.cap.u.super.bmAttributes        = 0;
+    d->u.cap.u.super.wSpeedsSupported_lo = 0;
+    d->u.cap.u.super.wSpeedsSupported_hi = 0;
+    d->u.cap.u.super.bFunctionalitySupport = 0;
+    d->u.cap.u.super.bU1DevExitLat       = 0x0a;
+    d->u.cap.u.super.wU2DevExitLat_lo    = 0x20;
+    d->u.cap.u.super.wU2DevExitLat_hi    = 0;
+
+    if (desc->full) {
+        d->u.cap.u.super.wSpeedsSupported_lo |= (1 << 1);
+        d->u.cap.u.super.bFunctionalitySupport = 1;
+    }
+    if (desc->high) {
+        d->u.cap.u.super.wSpeedsSupported_lo |= (1 << 2);
+        if (!d->u.cap.u.super.bFunctionalitySupport) {
+            d->u.cap.u.super.bFunctionalitySupport = 2;
+        }
+    }
+    if (desc->super) {
+        d->u.cap.u.super.wSpeedsSupported_lo |= (1 << 3);
+        if (!d->u.cap.u.super.bFunctionalitySupport) {
+            d->u.cap.u.super.bFunctionalitySupport = 3;
+        }
+    }
+
+    return bLength;
+}
+
+static int usb_desc_bos(const USBDesc *desc, uint8_t *dest, size_t len)
+{
+    uint8_t  bLength = 0x05;
+    uint16_t wTotalLength = 0;
+    uint8_t  bNumDeviceCaps = 0;
+    USBDescriptor *d = (void *)dest;
+    int rc;
+
+    if (len < bLength) {
+        return -1;
+    }
+
+    d->bLength                      = bLength;
+    d->bDescriptorType              = USB_DT_BOS;
+
+    wTotalLength += bLength;
+
+    if (desc->high != NULL) {
+        rc = usb_desc_cap_usb2_ext(desc, dest + wTotalLength,
+                                   len - wTotalLength);
+        if (rc < 0) {
+            return rc;
+        }
+        wTotalLength += rc;
+        bNumDeviceCaps++;
+    }
+
+    if (desc->super != NULL) {
+        rc = usb_desc_cap_super(desc, dest + wTotalLength,
+                                len - wTotalLength);
+        if (rc < 0) {
+            return rc;
+        }
+        wTotalLength += rc;
+        bNumDeviceCaps++;
+    }
+
+    d->u.bos.wTotalLength_lo = usb_lo(wTotalLength);
+    d->u.bos.wTotalLength_hi = usb_hi(wTotalLength);
+    d->u.bos.bNumDeviceCaps  = bNumDeviceCaps;
+    return wTotalLength;
+}
+
 /* ------------------------------------------------------------------ */
 
 static void usb_desc_ep_init(USBDevice *dev)
@@ -571,6 +676,10 @@ int usb_desc_get_descriptor(USBDevice *dev, int value, uint8_t *dest, size_t len
         }
         trace_usb_desc_other_speed_config(dev->addr, index, len, ret);
         break;
+    case USB_DT_BOS:
+        ret = usb_desc_bos(desc, buf, sizeof(buf));
+        trace_usb_desc_bos(dev->addr, len, ret);
+        break;
 
     case USB_DT_DEBUG:
         /* ignore silently */
diff --git a/hw/usb/desc.h b/hw/usb/desc.h
index 4b5e88d..68bb570 100644
--- a/hw/usb/desc.h
+++ b/hw/usb/desc.h
@@ -69,6 +69,31 @@ typedef struct USBDescriptor {
             uint8_t           wBytesPerInterval_lo;
             uint8_t           wBytesPerInterval_hi;
         } super_endpoint;
+        struct {
+            uint8_t           wTotalLength_lo;
+            uint8_t           wTotalLength_hi;
+            uint8_t           bNumDeviceCaps;
+        } bos;
+        struct {
+            uint8_t           bDevCapabilityType;
+            union {
+                struct {
+                    uint8_t   bmAttributes_1;
+                    uint8_t   bmAttributes_2;
+                    uint8_t   bmAttributes_3;
+                    uint8_t   bmAttributes_4;
+                } usb2_ext;
+                struct {
+                    uint8_t   bmAttributes;
+                    uint8_t   wSpeedsSupported_lo;
+                    uint8_t   wSpeedsSupported_hi;
+                    uint8_t   bFunctionalitySupport;
+                    uint8_t   bU1DevExitLat;
+                    uint8_t   wU2DevExitLat_lo;
+                    uint8_t   wU2DevExitLat_hi;
+                } super;
+            } u;
+        } cap;
     } u;
 } QEMU_PACKED USBDescriptor;
 
diff --git a/trace-events b/trace-events
index 8fa683d..09972ad 100644
--- a/trace-events
+++ b/trace-events
@@ -340,6 +340,7 @@ usb_desc_device_qualifier(int addr, int len, int ret) "dev %d query device quali
 usb_desc_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d"
 usb_desc_other_speed_config(int addr, int index, int len, int ret) "dev %d query config %d, len %d, ret %d"
 usb_desc_string(int addr, int index, int len, int ret) "dev %d query string %d, len %d, ret %d"
+usb_desc_bos(int addr, int len, int ret) "dev %d bos, len %d, ret %d"
 usb_set_addr(int addr) "dev %d"
 usb_set_config(int addr, int config, int ret) "dev %d, config %d, ret %d"
 usb_set_interface(int addr, int iface, int alt, int ret) "dev %d, interface %d, altsetting %d, ret %d"
-- 
1.7.1

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

* [Qemu-devel] [PATCH 44/54] usb-storage: usb3 support
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (42 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 43/54] usb3: bos decriptor Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 45/54] xhci: fix & cleanup msi Gerd Hoffmann
                   ` (10 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add usb3 descriptors to usb-storage, so it shows up as superspeed
device when connected to xhci.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/dev-storage.c |   46 +++++++++++++++++++++++++++++++++++++++++++---
 1 files changed, 43 insertions(+), 3 deletions(-)

diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index ff48d91..e732191 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -78,6 +78,7 @@ enum {
     STR_SERIALNUMBER,
     STR_CONFIG_FULL,
     STR_CONFIG_HIGH,
+    STR_CONFIG_SUPER,
 };
 
 static const USBDescStrings desc_strings = {
@@ -86,6 +87,7 @@ static const USBDescStrings desc_strings = {
     [STR_SERIALNUMBER] = "1",
     [STR_CONFIG_FULL]  = "Full speed config (usb 1.1)",
     [STR_CONFIG_HIGH]  = "High speed config (usb 2.0)",
+    [STR_CONFIG_SUPER] = "Super speed config (usb 3.0)",
 };
 
 static const USBDescIface desc_iface_full = {
@@ -158,6 +160,43 @@ static const USBDescDevice desc_device_high = {
     },
 };
 
+static const USBDescIface desc_iface_super = {
+    .bInterfaceNumber              = 0,
+    .bNumEndpoints                 = 2,
+    .bInterfaceClass               = USB_CLASS_MASS_STORAGE,
+    .bInterfaceSubClass            = 0x06, /* SCSI */
+    .bInterfaceProtocol            = 0x50, /* Bulk */
+    .eps = (USBDescEndpoint[]) {
+        {
+            .bEndpointAddress      = USB_DIR_IN | 0x01,
+            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize        = 1024,
+            .bMaxBurst             = 15,
+        },{
+            .bEndpointAddress      = USB_DIR_OUT | 0x02,
+            .bmAttributes          = USB_ENDPOINT_XFER_BULK,
+            .wMaxPacketSize        = 1024,
+            .bMaxBurst             = 15,
+        },
+    }
+};
+
+static const USBDescDevice desc_device_super = {
+    .bcdUSB                        = 0x0300,
+    .bMaxPacketSize0               = 9,
+    .bNumConfigurations            = 1,
+    .confs = (USBDescConfig[]) {
+        {
+            .bNumInterfaces        = 1,
+            .bConfigurationValue   = 1,
+            .iConfiguration        = STR_CONFIG_SUPER,
+            .bmAttributes          = 0xc0,
+            .nif = 1,
+            .ifs = &desc_iface_super,
+        },
+    },
+};
+
 static const USBDesc desc = {
     .id = {
         .idVendor          = 0x46f4, /* CRC16() of "QEMU" */
@@ -167,9 +206,10 @@ static const USBDesc desc = {
         .iProduct          = STR_PRODUCT,
         .iSerialNumber     = STR_SERIALNUMBER,
     },
-    .full = &desc_device_full,
-    .high = &desc_device_high,
-    .str  = desc_strings,
+    .full  = &desc_device_full,
+    .high  = &desc_device_high,
+    .super = &desc_device_super,
+    .str   = desc_strings,
 };
 
 static void usb_msd_copy_data(MSDState *s, USBPacket *p)
-- 
1.7.1

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

* [Qemu-devel] [PATCH 45/54] xhci: fix & cleanup msi.
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (43 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 44/54] usb-storage: usb3 support Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 46/54] xhci: rework interrupt handling Gerd Hoffmann
                   ` (9 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Drop custom write_config function which isn't needed any more.
Make the msi property a bit property so it accepts 'on' & 'off'.
Enable MSI by default.

TODO: add compat property to disable on old machine types.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-xhci.c |   27 +++++++++------------------
 1 files changed, 9 insertions(+), 18 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index e08312e..e1d5d2a 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -386,7 +386,7 @@ struct XHCIState {
     /* properties */
     uint32_t numports_2;
     uint32_t numports_3;
-    uint32_t msi;
+    uint32_t flags;
 
     /* Operational Registers */
     uint32_t usbcmd;
@@ -435,6 +435,10 @@ typedef struct XHCIEvRingSeg {
     uint32_t rsvd;
 } XHCIEvRingSeg;
 
+enum xhci_flags {
+    XHCI_FLAG_USE_MSI = 1,
+};
+
 static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
                          unsigned int epid);
 static void xhci_event(XHCIState *xhci, XHCIEvent *event);
@@ -617,7 +621,7 @@ static void xhci_irq_update(XHCIState *xhci)
         level = 1;
     }
 
-    if (xhci->msi && msi_enabled(&xhci->pci_dev)) {
+    if (msi_enabled(&xhci->pci_dev)) {
         if (level) {
             trace_usb_xhci_irq_msi(0);
             msi_notify(&xhci->pci_dev, 0);
@@ -2859,32 +2863,20 @@ static int usb_xhci_initfn(struct PCIDevice *dev)
     ret = pcie_cap_init(&xhci->pci_dev, 0xa0, PCI_EXP_TYPE_ENDPOINT, 0);
     assert(ret >= 0);
 
-    if (xhci->msi) {
-        ret = msi_init(&xhci->pci_dev, 0x70, 1, true, false);
-        assert(ret >= 0);
+    if (xhci->flags & (1 << XHCI_FLAG_USE_MSI)) {
+        msi_init(&xhci->pci_dev, 0x70, MAXINTRS, true, false);
     }
 
     return 0;
 }
 
-static void xhci_write_config(PCIDevice *dev, uint32_t addr, uint32_t val,
-                              int len)
-{
-    XHCIState *xhci = DO_UPCAST(XHCIState, pci_dev, dev);
-
-    pci_default_write_config(dev, addr, val, len);
-    if (xhci->msi) {
-        msi_write_config(dev, addr, val, len);
-    }
-}
-
 static const VMStateDescription vmstate_xhci = {
     .name = "xhci",
     .unmigratable = 1,
 };
 
 static Property xhci_properties[] = {
-    DEFINE_PROP_UINT32("msi", XHCIState, msi, 0),
+    DEFINE_PROP_BIT("msi",    XHCIState, flags, XHCI_FLAG_USE_MSI, true),
     DEFINE_PROP_UINT32("p2",  XHCIState, numports_2, 4),
     DEFINE_PROP_UINT32("p3",  XHCIState, numports_3, 4),
     DEFINE_PROP_END_OF_LIST(),
@@ -2904,7 +2896,6 @@ static void xhci_class_init(ObjectClass *klass, void *data)
     k->class_id     = PCI_CLASS_SERIAL_USB;
     k->revision     = 0x03;
     k->is_express   = 1;
-    k->config_write = xhci_write_config;
 }
 
 static TypeInfo xhci_info = {
-- 
1.7.1

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

* [Qemu-devel] [PATCH 46/54] xhci: rework interrupt handling
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (44 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 45/54] xhci: fix & cleanup msi Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 47/54] xhci: add msix support Gerd Hoffmann
                   ` (8 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Split xhci_irq_update into a function which handles intx updates
(including lowering the irq line once the guests acks the interrupt)
and one which is used for raising an irq only.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-xhci.c |   47 +++++++++++++++++++++++++++++++++--------------
 1 files changed, 33 insertions(+), 14 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index e1d5d2a..5eae32e 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -612,24 +612,43 @@ static XHCIPort *xhci_lookup_port(XHCIState *xhci, struct USBPort *uport)
     return &xhci->ports[index];
 }
 
-static void xhci_irq_update(XHCIState *xhci)
+static void xhci_intx_update(XHCIState *xhci)
 {
     int level = 0;
 
-    if (xhci->iman & IMAN_IP && xhci->iman & IMAN_IE &&
+    if (msi_enabled(&xhci->pci_dev)) {
+        return;
+    }
+
+    if (xhci->iman & IMAN_IP &&
+        xhci->iman & IMAN_IE &&
         xhci->usbcmd & USBCMD_INTE) {
         level = 1;
     }
 
+    trace_usb_xhci_irq_intx(level);
+    qemu_set_irq(xhci->irq, level);
+}
+
+static void xhci_intr_raise(XHCIState *xhci)
+{
+    if (!(xhci->iman & IMAN_IP) ||
+        !(xhci->iman & IMAN_IE)) {
+        return;
+    }
+
+    if (!(xhci->usbcmd & USBCMD_INTE)) {
+        return;
+    }
+
     if (msi_enabled(&xhci->pci_dev)) {
-        if (level) {
-            trace_usb_xhci_irq_msi(0);
-            msi_notify(&xhci->pci_dev, 0);
-        }
-    } else {
-        trace_usb_xhci_irq_intx(level);
-        qemu_set_irq(xhci->irq, level);
+        trace_usb_xhci_irq_msi(0);
+        msi_notify(&xhci->pci_dev, 0);
+        return;
     }
+
+    trace_usb_xhci_irq_intx(1);
+    qemu_set_irq(xhci->irq, 1);
 }
 
 static inline int xhci_running(XHCIState *xhci)
@@ -732,7 +751,7 @@ static void xhci_events_update(XHCIState *xhci)
         xhci->erdp_low |= ERDP_EHB;
         xhci->iman |= IMAN_IP;
         xhci->usbsts |= USBSTS_EINT;
-        xhci_irq_update(xhci);
+        xhci_intr_raise(xhci);
     }
 
     if (xhci->er_full && xhci->ev_buffer_put == xhci->ev_buffer_get) {
@@ -796,7 +815,7 @@ static void xhci_event(XHCIState *xhci, XHCIEvent *event)
     xhci->iman |= IMAN_IP;
     xhci->usbsts |= USBSTS_EINT;
 
-    xhci_irq_update(xhci);
+    xhci_intr_raise(xhci);
 }
 
 static void xhci_ring_init(XHCIState *xhci, XHCIRing *ring,
@@ -2481,13 +2500,13 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val)
         if (val & USBCMD_HCRST) {
             xhci_reset(&xhci->pci_dev.qdev);
         }
-        xhci_irq_update(xhci);
+        xhci_intx_update(xhci);
         break;
 
     case 0x04: /* USBSTS */
         /* these bits are write-1-to-clear */
         xhci->usbsts &= ~(val & (USBSTS_HSE|USBSTS_EINT|USBSTS_PCD|USBSTS_SRE));
-        xhci_irq_update(xhci);
+        xhci_intx_update(xhci);
         break;
 
     case 0x14: /* DNCTRL */
@@ -2572,7 +2591,7 @@ static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val)
         }
         xhci->iman &= ~IMAN_IE;
         xhci->iman |= val & IMAN_IE;
-        xhci_irq_update(xhci);
+        xhci_intx_update(xhci);
         break;
     case 0x24: /* IMOD */
         xhci->imod = val;
-- 
1.7.1

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

* [Qemu-devel] [PATCH 47/54] xhci: add msix support
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (45 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 46/54] xhci: rework interrupt handling Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 48/54] xhci: move register update into xhci_intr_raise Gerd Hoffmann
                   ` (7 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-xhci.c |   47 ++++++++++++++++++++++++++++++++++++++++++++++-
 trace-events      |    3 +++
 2 files changed, 49 insertions(+), 1 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 5eae32e..3bac99a 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -23,6 +23,7 @@
 #include "hw/usb.h"
 #include "hw/pci.h"
 #include "hw/msi.h"
+#include "hw/msix.h"
 #include "trace.h"
 
 //#define DEBUG_XHCI
@@ -59,6 +60,8 @@
 #define OFF_OPER        LEN_CAP
 #define OFF_RUNTIME     0x1000
 #define OFF_DOORBELL    0x2000
+#define OFF_MSIX_TABLE  0x3000
+#define OFF_MSIX_PBA    0x3800
 /* must be power of 2 */
 #define LEN_REGS        0x4000
 
@@ -411,6 +414,7 @@ struct XHCIState {
     uint32_t erstba_high;
     uint32_t erdp_low;
     uint32_t erdp_high;
+    bool     msix_used;
 
     int64_t mfindex_start;
     QEMUTimer *mfwrap_timer;
@@ -437,6 +441,7 @@ typedef struct XHCIEvRingSeg {
 
 enum xhci_flags {
     XHCI_FLAG_USE_MSI = 1,
+    XHCI_FLAG_USE_MSI_X,
 };
 
 static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
@@ -616,7 +621,8 @@ static void xhci_intx_update(XHCIState *xhci)
 {
     int level = 0;
 
-    if (msi_enabled(&xhci->pci_dev)) {
+    if (msix_enabled(&xhci->pci_dev) ||
+        msi_enabled(&xhci->pci_dev)) {
         return;
     }
 
@@ -630,6 +636,30 @@ static void xhci_intx_update(XHCIState *xhci)
     qemu_set_irq(xhci->irq, level);
 }
 
+static void xhci_msix_update(XHCIState *xhci)
+{
+    bool enabled;
+
+    if (!msix_enabled(&xhci->pci_dev)) {
+        return;
+    }
+
+    enabled = xhci->iman & IMAN_IE;
+    if (enabled == xhci->msix_used) {
+        return;
+    }
+
+    if (enabled) {
+        trace_usb_xhci_irq_msix_use(0);
+        msix_vector_use(&xhci->pci_dev, 0);
+        xhci->msix_used = true;
+    } else {
+        trace_usb_xhci_irq_msix_unuse(0);
+        msix_vector_unuse(&xhci->pci_dev, 0);
+        xhci->msix_used = false;
+    }
+}
+
 static void xhci_intr_raise(XHCIState *xhci)
 {
     if (!(xhci->iman & IMAN_IP) ||
@@ -641,6 +671,12 @@ static void xhci_intr_raise(XHCIState *xhci)
         return;
     }
 
+    if (msix_enabled(&xhci->pci_dev)) {
+        trace_usb_xhci_irq_msix(0);
+        msix_notify(&xhci->pci_dev, 0);
+        return;
+    }
+
     if (msi_enabled(&xhci->pci_dev)) {
         trace_usb_xhci_irq_msi(0);
         msi_notify(&xhci->pci_dev, 0);
@@ -2284,6 +2320,7 @@ static void xhci_reset(DeviceState *dev)
     xhci->erstba_high = 0;
     xhci->erdp_low = 0;
     xhci->erdp_high = 0;
+    xhci->msix_used = 0;
 
     xhci->er_ep_idx = 0;
     xhci->er_pcs = 1;
@@ -2592,6 +2629,7 @@ static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val)
         xhci->iman &= ~IMAN_IE;
         xhci->iman |= val & IMAN_IE;
         xhci_intx_update(xhci);
+        xhci_msix_update(xhci);
         break;
     case 0x24: /* IMOD */
         xhci->imod = val;
@@ -2885,6 +2923,12 @@ static int usb_xhci_initfn(struct PCIDevice *dev)
     if (xhci->flags & (1 << XHCI_FLAG_USE_MSI)) {
         msi_init(&xhci->pci_dev, 0x70, MAXINTRS, true, false);
     }
+    if (xhci->flags & (1 << XHCI_FLAG_USE_MSI_X)) {
+        msix_init(&xhci->pci_dev, MAXINTRS,
+                  &xhci->mem, 0, OFF_MSIX_TABLE,
+                  &xhci->mem, 0, OFF_MSIX_PBA,
+                  0x90);
+    }
 
     return 0;
 }
@@ -2896,6 +2940,7 @@ static const VMStateDescription vmstate_xhci = {
 
 static Property xhci_properties[] = {
     DEFINE_PROP_BIT("msi",    XHCIState, flags, XHCI_FLAG_USE_MSI, true),
+    DEFINE_PROP_BIT("msix",   XHCIState, flags, XHCI_FLAG_USE_MSI_X, true),
     DEFINE_PROP_UINT32("p2",  XHCIState, numports_2, 4),
     DEFINE_PROP_UINT32("p3",  XHCIState, numports_3, 4),
     DEFINE_PROP_END_OF_LIST(),
diff --git a/trace-events b/trace-events
index 09972ad..f03745c 100644
--- a/trace-events
+++ b/trace-events
@@ -313,6 +313,9 @@ usb_xhci_runtime_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
 usb_xhci_doorbell_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
 usb_xhci_irq_intx(uint32_t level) "level %d"
 usb_xhci_irq_msi(uint32_t nr) "nr %d"
+usb_xhci_irq_msix(uint32_t nr) "nr %d"
+usb_xhci_irq_msix_use(uint32_t nr) "nr %d"
+usb_xhci_irq_msix_unuse(uint32_t nr) "nr %d"
 usb_xhci_queue_event(uint32_t idx, const char *trb, const char *evt, uint64_t param, uint32_t status, uint32_t control) "idx %d, %s, %s, p %016" PRIx64 ", s %08x, c 0x%08x"
 usb_xhci_fetch_trb(uint64_t addr, const char *name, uint64_t param, uint32_t status, uint32_t control) "addr %016" PRIx64 ", %s, p %016" PRIx64 ", s %08x, c 0x%08x"
 usb_xhci_slot_enable(uint32_t slotid) "slotid %d"
-- 
1.7.1

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

* [Qemu-devel] [PATCH 48/54] xhci: move register update into xhci_intr_raise
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (46 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 47/54] xhci: add msix support Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 49/54] xhci: add XHCIInterrupter Gerd Hoffmann
                   ` (6 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Now that we have a separate function to raise an IRQ we can move
some comon code into the function.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-xhci.c |   14 +++++---------
 1 files changed, 5 insertions(+), 9 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 3bac99a..e39fe04 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -662,8 +662,11 @@ static void xhci_msix_update(XHCIState *xhci)
 
 static void xhci_intr_raise(XHCIState *xhci)
 {
-    if (!(xhci->iman & IMAN_IP) ||
-        !(xhci->iman & IMAN_IE)) {
+    xhci->erdp_low |= ERDP_EHB;
+    xhci->iman |= IMAN_IP;
+    xhci->usbsts |= USBSTS_EINT;
+
+    if (!(xhci->iman & IMAN_IE)) {
         return;
     }
 
@@ -784,9 +787,6 @@ static void xhci_events_update(XHCIState *xhci)
     }
 
     if (do_irq) {
-        xhci->erdp_low |= ERDP_EHB;
-        xhci->iman |= IMAN_IP;
-        xhci->usbsts |= USBSTS_EINT;
         xhci_intr_raise(xhci);
     }
 
@@ -847,10 +847,6 @@ static void xhci_event(XHCIState *xhci, XHCIEvent *event)
         xhci_write_event(xhci, event);
     }
 
-    xhci->erdp_low |= ERDP_EHB;
-    xhci->iman |= IMAN_IP;
-    xhci->usbsts |= USBSTS_EINT;
-
     xhci_intr_raise(xhci);
 }
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH 49/54] xhci: add XHCIInterrupter
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (47 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 48/54] xhci: move register update into xhci_intr_raise Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 50/54] xhci: prepare xhci_runtime_{read, write} for multiple interrupters Gerd Hoffmann
                   ` (5 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Move all state belonging to the (single) interrupter into a separate
struct.  First step in adding support for multiple interrupters.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-xhci.c |  307 ++++++++++++++++++++++++++++-------------------------
 trace-events      |    2 +-
 2 files changed, 161 insertions(+), 148 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index e39fe04..ddc3825 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -378,6 +378,27 @@ typedef struct XHCIEvent {
     uint8_t epid;
 } XHCIEvent;
 
+typedef struct XHCIInterrupter {
+    uint32_t iman;
+    uint32_t imod;
+    uint32_t erstsz;
+    uint32_t erstba_low;
+    uint32_t erstba_high;
+    uint32_t erdp_low;
+    uint32_t erdp_high;
+
+    bool msix_used, er_pcs, er_full;
+
+    dma_addr_t er_start;
+    uint32_t er_size;
+    unsigned int er_ep_idx;
+
+    XHCIEvent ev_buffer[EV_QUEUE];
+    unsigned int ev_buffer_put;
+    unsigned int ev_buffer_get;
+
+} XHCIInterrupter;
+
 struct XHCIState {
     PCIDevice pci_dev;
     USBBus bus;
@@ -407,27 +428,9 @@ struct XHCIState {
     uint32_t numports;
 
     /* Runtime Registers */
-    uint32_t iman;
-    uint32_t imod;
-    uint32_t erstsz;
-    uint32_t erstba_low;
-    uint32_t erstba_high;
-    uint32_t erdp_low;
-    uint32_t erdp_high;
-    bool     msix_used;
-
     int64_t mfindex_start;
     QEMUTimer *mfwrap_timer;
-
-    dma_addr_t er_start;
-    uint32_t er_size;
-    bool er_pcs;
-    unsigned int er_ep_idx;
-    bool er_full;
-
-    XHCIEvent ev_buffer[EV_QUEUE];
-    unsigned int ev_buffer_put;
-    unsigned int ev_buffer_get;
+    XHCIInterrupter intr[MAXINTRS];
 
     XHCIRing cmd_ring;
 };
@@ -446,8 +449,8 @@ enum xhci_flags {
 
 static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
                          unsigned int epid);
-static void xhci_event(XHCIState *xhci, XHCIEvent *event);
-static void xhci_write_event(XHCIState *xhci, XHCIEvent *event);
+static void xhci_event(XHCIState *xhci, XHCIEvent *event, int v);
+static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v);
 
 static const char *TRBType_names[] = {
     [TRB_RESERVED]                     = "TRB_RESERVED",
@@ -573,7 +576,7 @@ static void xhci_mfwrap_timer(void *opaque)
     XHCIState *xhci = opaque;
     XHCIEvent wrap = { ER_MFINDEX_WRAP, CC_SUCCESS };
 
-    xhci_event(xhci, &wrap);
+    xhci_event(xhci, &wrap, 0);
     xhci_mfwrap_update(xhci);
 }
 
@@ -626,8 +629,8 @@ static void xhci_intx_update(XHCIState *xhci)
         return;
     }
 
-    if (xhci->iman & IMAN_IP &&
-        xhci->iman & IMAN_IE &&
+    if (xhci->intr[0].iman & IMAN_IP &&
+        xhci->intr[0].iman & IMAN_IE &&
         xhci->usbcmd & USBCMD_INTE) {
         level = 1;
     }
@@ -636,7 +639,7 @@ static void xhci_intx_update(XHCIState *xhci)
     qemu_set_irq(xhci->irq, level);
 }
 
-static void xhci_msix_update(XHCIState *xhci)
+static void xhci_msix_update(XHCIState *xhci, int v)
 {
     bool enabled;
 
@@ -644,29 +647,29 @@ static void xhci_msix_update(XHCIState *xhci)
         return;
     }
 
-    enabled = xhci->iman & IMAN_IE;
-    if (enabled == xhci->msix_used) {
+    enabled = xhci->intr[v].iman & IMAN_IE;
+    if (enabled == xhci->intr[v].msix_used) {
         return;
     }
 
     if (enabled) {
-        trace_usb_xhci_irq_msix_use(0);
-        msix_vector_use(&xhci->pci_dev, 0);
-        xhci->msix_used = true;
+        trace_usb_xhci_irq_msix_use(v);
+        msix_vector_use(&xhci->pci_dev, v);
+        xhci->intr[v].msix_used = true;
     } else {
-        trace_usb_xhci_irq_msix_unuse(0);
-        msix_vector_unuse(&xhci->pci_dev, 0);
-        xhci->msix_used = false;
+        trace_usb_xhci_irq_msix_unuse(v);
+        msix_vector_unuse(&xhci->pci_dev, v);
+        xhci->intr[v].msix_used = false;
     }
 }
 
-static void xhci_intr_raise(XHCIState *xhci)
+static void xhci_intr_raise(XHCIState *xhci, int v)
 {
-    xhci->erdp_low |= ERDP_EHB;
-    xhci->iman |= IMAN_IP;
+    xhci->intr[v].erdp_low |= ERDP_EHB;
+    xhci->intr[v].iman |= IMAN_IP;
     xhci->usbsts |= USBSTS_EINT;
 
-    if (!(xhci->iman & IMAN_IE)) {
+    if (!(xhci->intr[v].iman & IMAN_IE)) {
         return;
     }
 
@@ -675,24 +678,26 @@ static void xhci_intr_raise(XHCIState *xhci)
     }
 
     if (msix_enabled(&xhci->pci_dev)) {
-        trace_usb_xhci_irq_msix(0);
-        msix_notify(&xhci->pci_dev, 0);
+        trace_usb_xhci_irq_msix(v);
+        msix_notify(&xhci->pci_dev, v);
         return;
     }
 
     if (msi_enabled(&xhci->pci_dev)) {
-        trace_usb_xhci_irq_msi(0);
-        msi_notify(&xhci->pci_dev, 0);
+        trace_usb_xhci_irq_msi(v);
+        msi_notify(&xhci->pci_dev, v);
         return;
     }
 
-    trace_usb_xhci_irq_intx(1);
-    qemu_set_irq(xhci->irq, 1);
+    if (v == 0) {
+        trace_usb_xhci_irq_intx(1);
+        qemu_set_irq(xhci->irq, 1);
+    }
 }
 
 static inline int xhci_running(XHCIState *xhci)
 {
-    return !(xhci->usbsts & USBSTS_HCH) && !xhci->er_full;
+    return !(xhci->usbsts & USBSTS_HCH) && !xhci->intr[0].er_full;
 }
 
 static void xhci_die(XHCIState *xhci)
@@ -701,8 +706,9 @@ static void xhci_die(XHCIState *xhci)
     fprintf(stderr, "xhci: asserted controller error\n");
 }
 
-static void xhci_write_event(XHCIState *xhci, XHCIEvent *event)
+static void xhci_write_event(XHCIState *xhci, XHCIEvent *event, int v)
 {
+    XHCIInterrupter *intr = &xhci->intr[v];
     XHCITRB ev_trb;
     dma_addr_t addr;
 
@@ -710,27 +716,28 @@ static void xhci_write_event(XHCIState *xhci, XHCIEvent *event)
     ev_trb.status = cpu_to_le32(event->length | (event->ccode << 24));
     ev_trb.control = (event->slotid << 24) | (event->epid << 16) |
                      event->flags | (event->type << TRB_TYPE_SHIFT);
-    if (xhci->er_pcs) {
+    if (intr->er_pcs) {
         ev_trb.control |= TRB_C;
     }
     ev_trb.control = cpu_to_le32(ev_trb.control);
 
-    trace_usb_xhci_queue_event(xhci->er_ep_idx, trb_name(&ev_trb),
+    trace_usb_xhci_queue_event(v, intr->er_ep_idx, trb_name(&ev_trb),
                                event_name(event), ev_trb.parameter,
                                ev_trb.status, ev_trb.control);
 
-    addr = xhci->er_start + TRB_SIZE*xhci->er_ep_idx;
+    addr = intr->er_start + TRB_SIZE*intr->er_ep_idx;
     pci_dma_write(&xhci->pci_dev, addr, &ev_trb, TRB_SIZE);
 
-    xhci->er_ep_idx++;
-    if (xhci->er_ep_idx >= xhci->er_size) {
-        xhci->er_ep_idx = 0;
-        xhci->er_pcs = !xhci->er_pcs;
+    intr->er_ep_idx++;
+    if (intr->er_ep_idx >= intr->er_size) {
+        intr->er_ep_idx = 0;
+        intr->er_pcs = !intr->er_pcs;
     }
 }
 
-static void xhci_events_update(XHCIState *xhci)
+static void xhci_events_update(XHCIState *xhci, int v)
 {
+    XHCIInterrupter *intr = &xhci->intr[v];
     dma_addr_t erdp;
     unsigned int dp_idx;
     bool do_irq = 0;
@@ -739,115 +746,116 @@ static void xhci_events_update(XHCIState *xhci)
         return;
     }
 
-    erdp = xhci_addr64(xhci->erdp_low, xhci->erdp_high);
-    if (erdp < xhci->er_start ||
-        erdp >= (xhci->er_start + TRB_SIZE*xhci->er_size)) {
+    erdp = xhci_addr64(intr->erdp_low, intr->erdp_high);
+    if (erdp < intr->er_start ||
+        erdp >= (intr->er_start + TRB_SIZE*intr->er_size)) {
         fprintf(stderr, "xhci: ERDP out of bounds: "DMA_ADDR_FMT"\n", erdp);
-        fprintf(stderr, "xhci: ER at "DMA_ADDR_FMT" len %d\n",
-                xhci->er_start, xhci->er_size);
+        fprintf(stderr, "xhci: ER[%d] at "DMA_ADDR_FMT" len %d\n",
+                v, intr->er_start, intr->er_size);
         xhci_die(xhci);
         return;
     }
-    dp_idx = (erdp - xhci->er_start) / TRB_SIZE;
-    assert(dp_idx < xhci->er_size);
+    dp_idx = (erdp - intr->er_start) / TRB_SIZE;
+    assert(dp_idx < intr->er_size);
 
     /* NEC didn't read section 4.9.4 of the spec (v1.0 p139 top Note) and thus
      * deadlocks when the ER is full. Hack it by holding off events until
      * the driver decides to free at least half of the ring */
-    if (xhci->er_full) {
-        int er_free = dp_idx - xhci->er_ep_idx;
+    if (intr->er_full) {
+        int er_free = dp_idx - intr->er_ep_idx;
         if (er_free <= 0) {
-            er_free += xhci->er_size;
+            er_free += intr->er_size;
         }
-        if (er_free < (xhci->er_size/2)) {
+        if (er_free < (intr->er_size/2)) {
             DPRINTF("xhci_events_update(): event ring still "
                     "more than half full (hack)\n");
             return;
         }
     }
 
-    while (xhci->ev_buffer_put != xhci->ev_buffer_get) {
-        assert(xhci->er_full);
-        if (((xhci->er_ep_idx+1) % xhci->er_size) == dp_idx) {
+    while (intr->ev_buffer_put != intr->ev_buffer_get) {
+        assert(intr->er_full);
+        if (((intr->er_ep_idx+1) % intr->er_size) == dp_idx) {
             DPRINTF("xhci_events_update(): event ring full again\n");
 #ifndef ER_FULL_HACK
             XHCIEvent full = {ER_HOST_CONTROLLER, CC_EVENT_RING_FULL_ERROR};
-            xhci_write_event(xhci, &full);
+            xhci_write_event(xhci, &full, v);
 #endif
             do_irq = 1;
             break;
         }
-        XHCIEvent *event = &xhci->ev_buffer[xhci->ev_buffer_get];
-        xhci_write_event(xhci, event);
-        xhci->ev_buffer_get++;
+        XHCIEvent *event = &intr->ev_buffer[intr->ev_buffer_get];
+        xhci_write_event(xhci, event, v);
+        intr->ev_buffer_get++;
         do_irq = 1;
-        if (xhci->ev_buffer_get == EV_QUEUE) {
-            xhci->ev_buffer_get = 0;
+        if (intr->ev_buffer_get == EV_QUEUE) {
+            intr->ev_buffer_get = 0;
         }
     }
 
     if (do_irq) {
-        xhci_intr_raise(xhci);
+        xhci_intr_raise(xhci, v);
     }
 
-    if (xhci->er_full && xhci->ev_buffer_put == xhci->ev_buffer_get) {
+    if (intr->er_full && intr->ev_buffer_put == intr->ev_buffer_get) {
         DPRINTF("xhci_events_update(): event ring no longer full\n");
-        xhci->er_full = 0;
+        intr->er_full = 0;
     }
     return;
 }
 
-static void xhci_event(XHCIState *xhci, XHCIEvent *event)
+static void xhci_event(XHCIState *xhci, XHCIEvent *event, int v)
 {
+    XHCIInterrupter *intr = &xhci->intr[v];
     dma_addr_t erdp;
     unsigned int dp_idx;
 
-    if (xhci->er_full) {
+    if (intr->er_full) {
         DPRINTF("xhci_event(): ER full, queueing\n");
-        if (((xhci->ev_buffer_put+1) % EV_QUEUE) == xhci->ev_buffer_get) {
+        if (((intr->ev_buffer_put+1) % EV_QUEUE) == intr->ev_buffer_get) {
             fprintf(stderr, "xhci: event queue full, dropping event!\n");
             return;
         }
-        xhci->ev_buffer[xhci->ev_buffer_put++] = *event;
-        if (xhci->ev_buffer_put == EV_QUEUE) {
-            xhci->ev_buffer_put = 0;
+        intr->ev_buffer[intr->ev_buffer_put++] = *event;
+        if (intr->ev_buffer_put == EV_QUEUE) {
+            intr->ev_buffer_put = 0;
         }
         return;
     }
 
-    erdp = xhci_addr64(xhci->erdp_low, xhci->erdp_high);
-    if (erdp < xhci->er_start ||
-        erdp >= (xhci->er_start + TRB_SIZE*xhci->er_size)) {
+    erdp = xhci_addr64(intr->erdp_low, intr->erdp_high);
+    if (erdp < intr->er_start ||
+        erdp >= (intr->er_start + TRB_SIZE*intr->er_size)) {
         fprintf(stderr, "xhci: ERDP out of bounds: "DMA_ADDR_FMT"\n", erdp);
-        fprintf(stderr, "xhci: ER at "DMA_ADDR_FMT" len %d\n",
-                xhci->er_start, xhci->er_size);
+        fprintf(stderr, "xhci: ER[%d] at "DMA_ADDR_FMT" len %d\n",
+                v, intr->er_start, intr->er_size);
         xhci_die(xhci);
         return;
     }
 
-    dp_idx = (erdp - xhci->er_start) / TRB_SIZE;
-    assert(dp_idx < xhci->er_size);
+    dp_idx = (erdp - intr->er_start) / TRB_SIZE;
+    assert(dp_idx < intr->er_size);
 
-    if ((xhci->er_ep_idx+1) % xhci->er_size == dp_idx) {
+    if ((intr->er_ep_idx+1) % intr->er_size == dp_idx) {
         DPRINTF("xhci_event(): ER full, queueing\n");
 #ifndef ER_FULL_HACK
         XHCIEvent full = {ER_HOST_CONTROLLER, CC_EVENT_RING_FULL_ERROR};
         xhci_write_event(xhci, &full);
 #endif
-        xhci->er_full = 1;
-        if (((xhci->ev_buffer_put+1) % EV_QUEUE) == xhci->ev_buffer_get) {
+        intr->er_full = 1;
+        if (((intr->ev_buffer_put+1) % EV_QUEUE) == intr->ev_buffer_get) {
             fprintf(stderr, "xhci: event queue full, dropping event!\n");
             return;
         }
-        xhci->ev_buffer[xhci->ev_buffer_put++] = *event;
-        if (xhci->ev_buffer_put == EV_QUEUE) {
-            xhci->ev_buffer_put = 0;
+        intr->ev_buffer[intr->ev_buffer_put++] = *event;
+        if (intr->ev_buffer_put == EV_QUEUE) {
+            intr->ev_buffer_put = 0;
         }
     } else {
-        xhci_write_event(xhci, event);
+        xhci_write_event(xhci, event, v);
     }
 
-    xhci_intr_raise(xhci);
+    xhci_intr_raise(xhci, v);
 }
 
 static void xhci_ring_init(XHCIState *xhci, XHCIRing *ring,
@@ -939,17 +947,18 @@ static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring)
     }
 }
 
-static void xhci_er_reset(XHCIState *xhci)
+static void xhci_er_reset(XHCIState *xhci, int v)
 {
+    XHCIInterrupter *intr = &xhci->intr[v];
     XHCIEvRingSeg seg;
 
     /* cache the (sole) event ring segment location */
-    if (xhci->erstsz != 1) {
-        fprintf(stderr, "xhci: invalid value for ERSTSZ: %d\n", xhci->erstsz);
+    if (intr->erstsz != 1) {
+        fprintf(stderr, "xhci: invalid value for ERSTSZ: %d\n", intr->erstsz);
         xhci_die(xhci);
         return;
     }
-    dma_addr_t erstba = xhci_addr64(xhci->erstba_low, xhci->erstba_high);
+    dma_addr_t erstba = xhci_addr64(intr->erstba_low, intr->erstba_high);
     pci_dma_read(&xhci->pci_dev, erstba, &seg, sizeof(seg));
     le32_to_cpus(&seg.addr_low);
     le32_to_cpus(&seg.addr_high);
@@ -959,15 +968,15 @@ static void xhci_er_reset(XHCIState *xhci)
         xhci_die(xhci);
         return;
     }
-    xhci->er_start = xhci_addr64(seg.addr_low, seg.addr_high);
-    xhci->er_size = seg.size;
+    intr->er_start = xhci_addr64(seg.addr_low, seg.addr_high);
+    intr->er_size = seg.size;
 
-    xhci->er_ep_idx = 0;
-    xhci->er_pcs = 1;
-    xhci->er_full = 0;
+    intr->er_ep_idx = 0;
+    intr->er_pcs = 1;
+    intr->er_full = 0;
 
-    DPRINTF("xhci: event ring:" DMA_ADDR_FMT " [%d]\n",
-            xhci->er_start, xhci->er_size);
+    DPRINTF("xhci: event ring[%d]:" DMA_ADDR_FMT " [%d]\n",
+            v, intr->er_start, intr->er_size);
 }
 
 static void xhci_run(XHCIState *xhci)
@@ -1368,7 +1377,7 @@ static void xhci_xfer_report(XHCITransfer *xfer)
                 DPRINTF("xhci_xfer_data: EDTLA=%d\n", event.length);
                 edtla = 0;
             }
-            xhci_event(xhci, &event);
+            xhci_event(xhci, &event, 0 /* FIXME */);
             reported = 1;
             if (xfer->status != CC_SUCCESS) {
                 return;
@@ -2246,7 +2255,7 @@ static void xhci_process_commands(XHCIState *xhci)
             break;
         }
         event.slotid = slotid;
-        xhci_event(xhci, &event);
+        xhci_event(xhci, &event, 0 /* FIXME */);
     }
 }
 
@@ -2276,7 +2285,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);
+        xhci_event(xhci, &ev, 0 /* FIXME */);
         DPRINTF("xhci: port change event for port %d\n", port->portnr);
     }
 }
@@ -2309,20 +2318,22 @@ static void xhci_reset(DeviceState *dev)
         xhci_update_port(xhci, xhci->ports + i, 0);
     }
 
-    xhci->iman = 0;
-    xhci->imod = 0;
-    xhci->erstsz = 0;
-    xhci->erstba_low = 0;
-    xhci->erstba_high = 0;
-    xhci->erdp_low = 0;
-    xhci->erdp_high = 0;
-    xhci->msix_used = 0;
+    for (i = 0; i < MAXINTRS; i++) {
+        xhci->intr[i].iman = 0;
+        xhci->intr[i].imod = 0;
+        xhci->intr[i].erstsz = 0;
+        xhci->intr[i].erstba_low = 0;
+        xhci->intr[i].erstba_high = 0;
+        xhci->intr[i].erdp_low = 0;
+        xhci->intr[i].erdp_high = 0;
+        xhci->intr[i].msix_used = 0;
 
-    xhci->er_ep_idx = 0;
-    xhci->er_pcs = 1;
-    xhci->er_full = 0;
-    xhci->ev_buffer_put = 0;
-    xhci->ev_buffer_get = 0;
+        xhci->intr[i].er_ep_idx = 0;
+        xhci->intr[i].er_pcs = 1;
+        xhci->intr[i].er_full = 0;
+        xhci->intr[i].ev_buffer_put = 0;
+        xhci->intr[i].ev_buffer_get = 0;
+    }
 
     xhci->mfindex_start = qemu_get_clock_ns(vm_clock);
     xhci_mfwrap_update(xhci);
@@ -2553,7 +2564,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);
+            xhci_event(xhci, &event, 0 /* FIXME */);
             DPRINTF("xhci: command ring stopped (CRCR=%08x)\n", xhci->crcr_low);
         } else {
             dma_addr_t base = xhci_addr64(xhci->crcr_low & ~0x3f, val);
@@ -2577,6 +2588,7 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val)
 
 static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg)
 {
+    XHCIInterrupter *intr = &xhci->intr[0];
     uint32_t ret;
 
     switch (reg) {
@@ -2584,25 +2596,25 @@ static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg)
         ret = xhci_mfindex_get(xhci) & 0x3fff;
         break;
     case 0x20: /* IMAN */
-        ret = xhci->iman;
+        ret = intr->iman;
         break;
     case 0x24: /* IMOD */
-        ret = xhci->imod;
+        ret = intr->imod;
         break;
     case 0x28: /* ERSTSZ */
-        ret = xhci->erstsz;
+        ret = intr->erstsz;
         break;
     case 0x30: /* ERSTBA low */
-        ret = xhci->erstba_low;
+        ret = intr->erstba_low;
         break;
     case 0x34: /* ERSTBA high */
-        ret = xhci->erstba_high;
+        ret = intr->erstba_high;
         break;
     case 0x38: /* ERDP low */
-        ret = xhci->erdp_low;
+        ret = intr->erdp_low;
         break;
     case 0x3c: /* ERDP high */
-        ret = xhci->erdp_high;
+        ret = intr->erdp_high;
         break;
     default:
         fprintf(stderr, "xhci_runtime_read: reg 0x%x unimplemented\n", reg);
@@ -2615,42 +2627,43 @@ static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg)
 
 static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val)
 {
+    XHCIInterrupter *intr = &xhci->intr[0];
     trace_usb_xhci_runtime_write(reg, val);
 
     switch (reg) {
     case 0x20: /* IMAN */
         if (val & IMAN_IP) {
-            xhci->iman &= ~IMAN_IP;
+            intr->iman &= ~IMAN_IP;
         }
-        xhci->iman &= ~IMAN_IE;
-        xhci->iman |= val & IMAN_IE;
+        intr->iman &= ~IMAN_IE;
+        intr->iman |= val & IMAN_IE;
         xhci_intx_update(xhci);
-        xhci_msix_update(xhci);
+        xhci_msix_update(xhci, 0);
         break;
     case 0x24: /* IMOD */
-        xhci->imod = val;
+        intr->imod = val;
         break;
     case 0x28: /* ERSTSZ */
-        xhci->erstsz = val & 0xffff;
+        intr->erstsz = val & 0xffff;
         break;
     case 0x30: /* ERSTBA low */
         /* XXX NEC driver bug: it doesn't align this to 64 bytes
-        xhci->erstba_low = val & 0xffffffc0; */
-        xhci->erstba_low = val & 0xfffffff0;
+        intr->erstba_low = val & 0xffffffc0; */
+        intr->erstba_low = val & 0xfffffff0;
         break;
     case 0x34: /* ERSTBA high */
-        xhci->erstba_high = val;
-        xhci_er_reset(xhci);
+        intr->erstba_high = val;
+        xhci_er_reset(xhci, 0);
         break;
     case 0x38: /* ERDP low */
         if (val & ERDP_EHB) {
-            xhci->erdp_low &= ~ERDP_EHB;
+            intr->erdp_low &= ~ERDP_EHB;
         }
-        xhci->erdp_low = (val & ~ERDP_EHB) | (xhci->erdp_low & ERDP_EHB);
+        intr->erdp_low = (val & ~ERDP_EHB) | (intr->erdp_low & ERDP_EHB);
         break;
     case 0x3c: /* ERDP high */
-        xhci->erdp_high = val;
-        xhci_events_update(xhci);
+        intr->erdp_high = val;
+        xhci_events_update(xhci, 0);
         break;
     default:
         fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", reg);
@@ -2780,7 +2793,7 @@ static void xhci_wakeup(USBPort *usbport)
         return;
     }
     port->portsc |= PORTSC_PLC;
-    xhci_event(xhci, &ev);
+    xhci_event(xhci, &ev, 0 /* FIXME */);
 }
 
 static void xhci_complete(USBPort *port, USBPacket *packet)
diff --git a/trace-events b/trace-events
index f03745c..1abaa5f 100644
--- a/trace-events
+++ b/trace-events
@@ -316,7 +316,7 @@ usb_xhci_irq_msi(uint32_t nr) "nr %d"
 usb_xhci_irq_msix(uint32_t nr) "nr %d"
 usb_xhci_irq_msix_use(uint32_t nr) "nr %d"
 usb_xhci_irq_msix_unuse(uint32_t nr) "nr %d"
-usb_xhci_queue_event(uint32_t idx, const char *trb, const char *evt, uint64_t param, uint32_t status, uint32_t control) "idx %d, %s, %s, p %016" PRIx64 ", s %08x, c 0x%08x"
+usb_xhci_queue_event(uint32_t vector, uint32_t idx, const char *trb, const char *evt, uint64_t param, uint32_t status, uint32_t control) "v %d, idx %d, %s, %s, p %016" PRIx64 ", s %08x, c 0x%08x"
 usb_xhci_fetch_trb(uint64_t addr, const char *name, uint64_t param, uint32_t status, uint32_t control) "addr %016" PRIx64 ", %s, p %016" PRIx64 ", s %08x, c 0x%08x"
 usb_xhci_slot_enable(uint32_t slotid) "slotid %d"
 usb_xhci_slot_disable(uint32_t slotid) "slotid %d"
-- 
1.7.1

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

* [Qemu-devel] [PATCH 50/54] xhci: prepare xhci_runtime_{read, write} for multiple interrupters
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (48 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 49/54] xhci: add XHCIInterrupter Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 51/54] xhci: pick target interrupter Gerd Hoffmann
                   ` (4 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Prepare xhci runtime register access function for multiple interrupters.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-xhci.c |  100 ++++++++++++++++++++++++++++++-----------------------
 1 files changed, 57 insertions(+), 43 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index ddc3825..68a19ab 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -2588,37 +2588,43 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val)
 
 static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg)
 {
-    XHCIInterrupter *intr = &xhci->intr[0];
-    uint32_t ret;
+    uint32_t ret = 0;
 
-    switch (reg) {
-    case 0x00: /* MFINDEX */
-        ret = xhci_mfindex_get(xhci) & 0x3fff;
-        break;
-    case 0x20: /* IMAN */
-        ret = intr->iman;
-        break;
-    case 0x24: /* IMOD */
-        ret = intr->imod;
-        break;
-    case 0x28: /* ERSTSZ */
-        ret = intr->erstsz;
-        break;
-    case 0x30: /* ERSTBA low */
-        ret = intr->erstba_low;
-        break;
-    case 0x34: /* ERSTBA high */
-        ret = intr->erstba_high;
-        break;
-    case 0x38: /* ERDP low */
-        ret = intr->erdp_low;
-        break;
-    case 0x3c: /* ERDP high */
-        ret = intr->erdp_high;
-        break;
-    default:
-        fprintf(stderr, "xhci_runtime_read: reg 0x%x unimplemented\n", reg);
-        ret = 0;
+    if (reg < 0x20) {
+        switch (reg) {
+        case 0x00: /* MFINDEX */
+            ret = xhci_mfindex_get(xhci) & 0x3fff;
+            break;
+        default:
+            fprintf(stderr, "xhci_runtime_read: reg 0x%x unimplemented\n", reg);
+            break;
+        }
+    } else {
+        int v = (reg - 0x20) / 0x20;
+        XHCIInterrupter *intr = &xhci->intr[v];
+        switch (reg & 0x1f) {
+        case 0x00: /* IMAN */
+            ret = intr->iman;
+            break;
+        case 0x04: /* IMOD */
+            ret = intr->imod;
+            break;
+        case 0x08: /* ERSTSZ */
+            ret = intr->erstsz;
+            break;
+        case 0x10: /* ERSTBA low */
+            ret = intr->erstba_low;
+            break;
+        case 0x14: /* ERSTBA high */
+            ret = intr->erstba_high;
+            break;
+        case 0x18: /* ERDP low */
+            ret = intr->erdp_low;
+            break;
+        case 0x1c: /* ERDP high */
+            ret = intr->erdp_high;
+            break;
+        }
     }
 
     trace_usb_xhci_runtime_read(reg, ret);
@@ -2627,43 +2633,51 @@ static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg)
 
 static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val)
 {
-    XHCIInterrupter *intr = &xhci->intr[0];
+    int v = (reg - 0x20) / 0x20;
+    XHCIInterrupter *intr = &xhci->intr[v];
     trace_usb_xhci_runtime_write(reg, val);
 
-    switch (reg) {
-    case 0x20: /* IMAN */
+    if (reg < 0x20) {
+        fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", reg);
+        return;
+    }
+
+    switch (reg & 0x1f) {
+    case 0x00: /* IMAN */
         if (val & IMAN_IP) {
             intr->iman &= ~IMAN_IP;
         }
         intr->iman &= ~IMAN_IE;
         intr->iman |= val & IMAN_IE;
-        xhci_intx_update(xhci);
-        xhci_msix_update(xhci, 0);
+        if (v == 0) {
+            xhci_intx_update(xhci);
+        }
+        xhci_msix_update(xhci, v);
         break;
-    case 0x24: /* IMOD */
+    case 0x04: /* IMOD */
         intr->imod = val;
         break;
-    case 0x28: /* ERSTSZ */
+    case 0x08: /* ERSTSZ */
         intr->erstsz = val & 0xffff;
         break;
-    case 0x30: /* ERSTBA low */
+    case 0x10: /* ERSTBA low */
         /* XXX NEC driver bug: it doesn't align this to 64 bytes
         intr->erstba_low = val & 0xffffffc0; */
         intr->erstba_low = val & 0xfffffff0;
         break;
-    case 0x34: /* ERSTBA high */
+    case 0x14: /* ERSTBA high */
         intr->erstba_high = val;
-        xhci_er_reset(xhci, 0);
+        xhci_er_reset(xhci, v);
         break;
-    case 0x38: /* ERDP low */
+    case 0x18: /* ERDP low */
         if (val & ERDP_EHB) {
             intr->erdp_low &= ~ERDP_EHB;
         }
         intr->erdp_low = (val & ~ERDP_EHB) | (intr->erdp_low & ERDP_EHB);
         break;
-    case 0x3c: /* ERDP high */
+    case 0x1c: /* ERDP high */
         intr->erdp_high = val;
-        xhci_events_update(xhci, 0);
+        xhci_events_update(xhci, v);
         break;
     default:
         fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", reg);
-- 
1.7.1

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

* [Qemu-devel] [PATCH 51/54] xhci: pick target interrupter
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (49 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 50/54] xhci: prepare xhci_runtime_{read, write} for multiple interrupters Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 52/54] xhci: support multiple interrupters Gerd Hoffmann
                   ` (3 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Pick the correct interrupter when queuing an event.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-xhci.c |   22 ++++++++++++++++------
 1 files changed, 16 insertions(+), 6 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 68a19ab..d6ab0c6 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -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.1

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

* [Qemu-devel] [PATCH 52/54] xhci: support multiple interrupters
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (50 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 51/54] xhci: pick target interrupter Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 53/54] xhci: kill xhci_mem_{read, write} dispatcher functions Gerd Hoffmann
                   ` (2 subsequent siblings)
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Everything is in place, flip the big switch now
and enable support for multiple interrupters.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-xhci.c |    6 +-----
 1 files changed, 1 insertions(+), 5 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index d6ab0c6..55e31ec 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -42,7 +42,7 @@
 
 #define MAXPORTS (MAXPORTS_2+MAXPORTS_3)
 #define MAXSLOTS MAXPORTS
-#define MAXINTRS 1 /* MAXPORTS */
+#define MAXINTRS MAXPORTS
 
 #define TD_QUEUE 24
 
@@ -75,10 +75,6 @@
 # error Increase LEN_REGS
 #endif
 
-#if MAXINTRS > 1
-# error TODO: only one interrupter supported
-#endif
-
 /* bit definitions */
 #define USBCMD_RS       (1<<0)
 #define USBCMD_HCRST    (1<<1)
-- 
1.7.1

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

* [Qemu-devel] [PATCH 53/54] xhci: kill xhci_mem_{read, write} dispatcher functions
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (51 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 52/54] xhci: support multiple interrupters Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 54/54] xhci: allow bytewise capability register reads Gerd Hoffmann
  2012-09-10 13:23 ` [Qemu-devel] [PULL 00/54] usb patch queue Aurelien Jarno
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

... and register subregions instead, so we offload the dispatching
to the the memory subsystem which is designed to handle it.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-xhci.c |  140 ++++++++++++++++++++++++++++------------------------
 1 files changed, 75 insertions(+), 65 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 55e31ec..500892d 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -404,6 +404,10 @@ struct XHCIState {
     USBBus bus;
     qemu_irq irq;
     MemoryRegion mem;
+    MemoryRegion mem_cap;
+    MemoryRegion mem_oper;
+    MemoryRegion mem_runtime;
+    MemoryRegion mem_doorbell;
     const char *name;
     unsigned int devaddr;
 
@@ -2345,8 +2349,9 @@ static void xhci_reset(DeviceState *dev)
     xhci_mfwrap_update(xhci);
 }
 
-static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg)
+static uint64_t xhci_cap_read(void *ptr, target_phys_addr_t reg, unsigned size)
 {
+    XHCIState *xhci = ptr;
     uint32_t ret;
 
     switch (reg) {
@@ -2403,7 +2408,7 @@ static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg)
         ret = 0x00000000; /* reserved */
         break;
     default:
-        fprintf(stderr, "xhci_cap_read: reg %d unimplemented\n", reg);
+        fprintf(stderr, "xhci_cap_read: reg %d unimplemented\n", (int)reg);
         ret = 0;
     }
 
@@ -2484,8 +2489,9 @@ static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
     }
 }
 
-static uint32_t xhci_oper_read(XHCIState *xhci, uint32_t reg)
+static uint64_t xhci_oper_read(void *ptr, target_phys_addr_t reg, unsigned size)
 {
+    XHCIState *xhci = ptr;
     uint32_t ret;
 
     if (reg >= 0x400) {
@@ -2521,7 +2527,7 @@ static uint32_t xhci_oper_read(XHCIState *xhci, uint32_t reg)
         ret = xhci->config;
         break;
     default:
-        fprintf(stderr, "xhci_oper_read: reg 0x%x unimplemented\n", reg);
+        fprintf(stderr, "xhci_oper_read: reg 0x%x unimplemented\n", (int)reg);
         ret = 0;
     }
 
@@ -2529,8 +2535,11 @@ static uint32_t xhci_oper_read(XHCIState *xhci, uint32_t reg)
     return ret;
 }
 
-static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val)
+static void xhci_oper_write(void *ptr, target_phys_addr_t reg,
+                            uint64_t val, unsigned size)
 {
+    XHCIState *xhci = ptr;
+
     if (reg >= 0x400) {
         xhci_port_write(xhci, reg - 0x400, val);
         return;
@@ -2588,12 +2597,14 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val)
         xhci->config = val & 0xff;
         break;
     default:
-        fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", reg);
+        fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", (int)reg);
     }
 }
 
-static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg)
+static uint64_t xhci_runtime_read(void *ptr, target_phys_addr_t reg,
+                                  unsigned size)
 {
+    XHCIState *xhci = ptr;
     uint32_t ret = 0;
 
     if (reg < 0x20) {
@@ -2602,7 +2613,8 @@ static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg)
             ret = xhci_mfindex_get(xhci) & 0x3fff;
             break;
         default:
-            fprintf(stderr, "xhci_runtime_read: reg 0x%x unimplemented\n", reg);
+            fprintf(stderr, "xhci_runtime_read: reg 0x%x unimplemented\n",
+                    (int)reg);
             break;
         }
     } else {
@@ -2637,14 +2649,16 @@ static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg)
     return ret;
 }
 
-static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val)
+static void xhci_runtime_write(void *ptr, target_phys_addr_t reg,
+                               uint64_t val, unsigned size)
 {
+    XHCIState *xhci = ptr;
     int v = (reg - 0x20) / 0x20;
     XHCIInterrupter *intr = &xhci->intr[v];
     trace_usb_xhci_runtime_write(reg, val);
 
     if (reg < 0x20) {
-        fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", reg);
+        fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", (int)reg);
         return;
     }
 
@@ -2686,19 +2700,24 @@ static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val)
         xhci_events_update(xhci, v);
         break;
     default:
-        fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n", reg);
+        fprintf(stderr, "xhci_oper_write: reg 0x%x unimplemented\n",
+                (int)reg);
     }
 }
 
-static uint32_t xhci_doorbell_read(XHCIState *xhci, uint32_t reg)
+static uint64_t xhci_doorbell_read(void *ptr, target_phys_addr_t reg,
+                                   unsigned size)
 {
     /* doorbells always read as 0 */
     trace_usb_xhci_doorbell_read(reg, 0);
     return 0;
 }
 
-static void xhci_doorbell_write(XHCIState *xhci, uint32_t reg, uint32_t val)
+static void xhci_doorbell_write(void *ptr, target_phys_addr_t reg,
+                                uint64_t val, unsigned size)
 {
+    XHCIState *xhci = ptr;
+
     trace_usb_xhci_doorbell_write(reg, val);
 
     if (!xhci_running(xhci)) {
@@ -2712,69 +2731,47 @@ static void xhci_doorbell_write(XHCIState *xhci, uint32_t reg, uint32_t val)
         if (val == 0) {
             xhci_process_commands(xhci);
         } else {
-            fprintf(stderr, "xhci: bad doorbell 0 write: 0x%x\n", val);
+            fprintf(stderr, "xhci: bad doorbell 0 write: 0x%x\n",
+                    (uint32_t)val);
         }
     } else {
         if (reg > MAXSLOTS) {
-            fprintf(stderr, "xhci: bad doorbell %d\n", reg);
+            fprintf(stderr, "xhci: bad doorbell %d\n", (int)reg);
         } else if (val > 31) {
-            fprintf(stderr, "xhci: bad doorbell %d write: 0x%x\n", reg, val);
+            fprintf(stderr, "xhci: bad doorbell %d write: 0x%x\n",
+                    (int)reg, (uint32_t)val);
         } else {
             xhci_kick_ep(xhci, reg, val);
         }
     }
 }
 
-static uint64_t xhci_mem_read(void *ptr, target_phys_addr_t addr,
-                              unsigned size)
-{
-    XHCIState *xhci = ptr;
-
-    /* Only aligned reads are allowed on xHCI */
-    if (addr & 3) {
-        fprintf(stderr, "xhci_mem_read: Mis-aligned read\n");
-        return 0;
-    }
-
-    if (addr < LEN_CAP) {
-        return xhci_cap_read(xhci, addr);
-    } else if (addr >= OFF_OPER && addr < (OFF_OPER + LEN_OPER)) {
-        return xhci_oper_read(xhci, addr - OFF_OPER);
-    } else if (addr >= OFF_RUNTIME && addr < (OFF_RUNTIME + LEN_RUNTIME)) {
-        return xhci_runtime_read(xhci, addr - OFF_RUNTIME);
-    } else if (addr >= OFF_DOORBELL && addr < (OFF_DOORBELL + LEN_DOORBELL)) {
-        return xhci_doorbell_read(xhci, addr - OFF_DOORBELL);
-    } else {
-        fprintf(stderr, "xhci_mem_read: Bad offset %x\n", (int)addr);
-        return 0;
-    }
-}
-
-static void xhci_mem_write(void *ptr, target_phys_addr_t addr,
-                           uint64_t val, unsigned size)
-{
-    XHCIState *xhci = ptr;
+static const MemoryRegionOps xhci_cap_ops = {
+    .read = xhci_cap_read,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
 
-    /* Only aligned writes are allowed on xHCI */
-    if (addr & 3) {
-        fprintf(stderr, "xhci_mem_write: Mis-aligned write\n");
-        return;
-    }
+static const MemoryRegionOps xhci_oper_ops = {
+    .read = xhci_oper_read,
+    .write = xhci_oper_write,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
 
-    if (addr >= OFF_OPER && addr < (OFF_OPER + LEN_OPER)) {
-        xhci_oper_write(xhci, addr - OFF_OPER, val);
-    } else if (addr >= OFF_RUNTIME && addr < (OFF_RUNTIME + LEN_RUNTIME)) {
-        xhci_runtime_write(xhci, addr - OFF_RUNTIME, val);
-    } else if (addr >= OFF_DOORBELL && addr < (OFF_DOORBELL + LEN_DOORBELL)) {
-        xhci_doorbell_write(xhci, addr - OFF_DOORBELL, val);
-    } else {
-        fprintf(stderr, "xhci_mem_write: Bad offset %x\n", (int)addr);
-    }
-}
+static const MemoryRegionOps xhci_runtime_ops = {
+    .read = xhci_runtime_read,
+    .write = xhci_runtime_write,
+    .valid.min_access_size = 4,
+    .valid.max_access_size = 4,
+    .endianness = DEVICE_LITTLE_ENDIAN,
+};
 
-static const MemoryRegionOps xhci_mem_ops = {
-    .read = xhci_mem_read,
-    .write = xhci_mem_write,
+static const MemoryRegionOps xhci_doorbell_ops = {
+    .read = xhci_doorbell_read,
+    .write = xhci_doorbell_write,
     .valid.min_access_size = 4,
     .valid.max_access_size = 4,
     .endianness = DEVICE_LITTLE_ENDIAN,
@@ -2940,8 +2937,21 @@ static int usb_xhci_initfn(struct PCIDevice *dev)
 
     xhci->irq = xhci->pci_dev.irq[0];
 
-    memory_region_init_io(&xhci->mem, &xhci_mem_ops, xhci,
-                          "xhci", LEN_REGS);
+    memory_region_init(&xhci->mem, "xhci", LEN_REGS);
+    memory_region_init_io(&xhci->mem_cap, &xhci_cap_ops, xhci,
+                          "capabilities", LEN_CAP);
+    memory_region_init_io(&xhci->mem_oper, &xhci_oper_ops, xhci,
+                          "operational", 0x400 + 0x10 * xhci->numports);
+    memory_region_init_io(&xhci->mem_runtime, &xhci_runtime_ops, xhci,
+                          "runtime", LEN_RUNTIME);
+    memory_region_init_io(&xhci->mem_doorbell, &xhci_doorbell_ops, xhci,
+                          "doorbell", LEN_DOORBELL);
+
+    memory_region_add_subregion(&xhci->mem, 0,            &xhci->mem_cap);
+    memory_region_add_subregion(&xhci->mem, OFF_OPER,     &xhci->mem_oper);
+    memory_region_add_subregion(&xhci->mem, OFF_RUNTIME,  &xhci->mem_runtime);
+    memory_region_add_subregion(&xhci->mem, OFF_DOORBELL, &xhci->mem_doorbell);
+
     pci_register_bar(&xhci->pci_dev, 0,
                      PCI_BASE_ADDRESS_SPACE_MEMORY|PCI_BASE_ADDRESS_MEM_TYPE_64,
                      &xhci->mem);
-- 
1.7.1

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

* [Qemu-devel] [PATCH 54/54] xhci: allow bytewise capability register reads
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (52 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 53/54] xhci: kill xhci_mem_{read, write} dispatcher functions Gerd Hoffmann
@ 2012-09-06  7:12 ` Gerd Hoffmann
  2012-09-10 13:23 ` [Qemu-devel] [PULL 00/54] usb patch queue Aurelien Jarno
  54 siblings, 0 replies; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-06  7:12 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Some guests need this according to
Alejandro Martinez Ruiz <alex@securiforest.com>

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/usb/hcd-xhci.c |    4 +++-
 1 files changed, 3 insertions(+), 1 deletions(-)

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 500892d..2918e64 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -2748,8 +2748,10 @@ static void xhci_doorbell_write(void *ptr, target_phys_addr_t reg,
 
 static const MemoryRegionOps xhci_cap_ops = {
     .read = xhci_cap_read,
-    .valid.min_access_size = 4,
+    .valid.min_access_size = 1,
     .valid.max_access_size = 4,
+    .impl.min_access_size = 4,
+    .impl.max_access_size = 4,
     .endianness = DEVICE_LITTLE_ENDIAN,
 };
 
-- 
1.7.1

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

* Re: [Qemu-devel] [PULL 00/54] usb patch queue
  2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
                   ` (53 preceding siblings ...)
  2012-09-06  7:12 ` [Qemu-devel] [PATCH 54/54] xhci: allow bytewise capability register reads Gerd Hoffmann
@ 2012-09-10 13:23 ` Aurelien Jarno
  2012-09-10 13:37   ` Gerd Hoffmann
  54 siblings, 1 reply; 61+ messages in thread
From: Aurelien Jarno @ 2012-09-10 13:23 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

On Thu, Sep 06, 2012 at 09:12:01AM +0200, Gerd Hoffmann wrote:
>   Hi,
> 
> Here comes the usb patch queue with a bunch of new goodies accumulated
> while qemu was in freeze for the 1.2 release:
> 
>  * ehci gets more tracepoints & improvements in the queuing code and
>    minor bugfixes (the important fixes where a last minute 1.2 pull).
>  * usbredir goes make use of the new queues in the usb core instead
>    of managing its own.  Also a bunch of preparations for live
>    migration support.
>  * xhci gets a bunch of fixes and improvements: port handling fixes,
>    fix & enable msi/msix support, support for multiple interrupters,
>    support for iso transfers, tracing improvemnets, cleanups & fixes.
>  * usb core got support for creating usb3 descriptors.
>  * usb3 emulation is enabled for usb-storage, so when hooking up
>    usb-storage to xhci it shows up as usb3 device in the guest.
>  * Little fixes here and there.
> 
> cheers,
>   Gerd
> 
> The following changes since commit 8db972cfa469b4e4afd9c65e54e796b83b5ce3a2:
> 
>   Update version for 1.2.0 (2012-09-05 07:50:01 -0500)
> 
> are available in the git repository at:
>   git://git.kraxel.org/qemu usb.62
> 
> Gerd Hoffmann (28):
>       ehci: check for EHCI_ASYNC_FINISHED first in ehci_free_packet
>       ehci: trace guest bugs
>       ehci: add doorbell trace events
>       usb-audio: fix usb version
>       xhci: rip out background transfer code
>       xhci: drop buffering
>       xhci: move device lookup into xhci_setup_packet
>       xhci: implement mfindex
>       xhci: iso xfer support
>       xhci: trace cc codes in cleartext
>       xhci: add trace_usb_xhci_ep_set_dequeue
>       xhci: fix runtime write tracepoint
>       xhci: update register layout
>       xhci: update port handling
>       usb3: superspeed descriptors
>       usb3: superspeed endpoint companion
>       usb3: bos decriptor
>       usb-storage: usb3 support
>       xhci: fix & cleanup msi.
>       xhci: rework interrupt handling
>       xhci: add msix support
>       xhci: move register update into xhci_intr_raise
>       xhci: add XHCIInterrupter
>       xhci: prepare xhci_runtime_{read,write} for multiple interrupters
>       xhci: pick target interrupter
>       xhci: support multiple interrupters
>       xhci: kill xhci_mem_{read,write} dispatcher functions
>       xhci: allow bytewise capability register reads
> 
> Hans de Goede (25):
>       usb: controllers do not need to check for babble themselves
>       usb-core: Don't set packet state to complete on a nak
>       usb-core: Add a usb_ep_find_packet_by_id() helper function
>       usb-core: Allow the first packet of a pipelined ep to complete immediately
>       Revert "ehci: don't flush cache on doorbell rings."
>       ehci: Validate qh is not changed unexpectedly by the guest
>       ehci: Update copyright headers to reflect recent work
>       ehci: Properly cleanup packets on cancel
>       ehci: Properly report completed but not yet processed packets to the guest
>       ehci: Add some additional ehci_trace_guest_bug() calls
>       ehci: Fix memory leak in handling of NAK-ed packets
>       ehci: Handle USB_RET_PROCERR in ehci_fill_queue
>       ehci: Correct a comment in fetchqtd packet processing
>       usb-redir: Never return USB_RET_NAK for async handled packets
>       usb-redir: Don't delay handling of open events to a bottom half
>       usb-redir: Get rid of async-struct get member
>       usb-redir: Get rid of local shadow copy of packet headers
>       usb-redir: Get rid of unused async-struct dev member
>       usb-redir: Move to core packet id and queue handling
>       usb-redir: Return babble when getting more bulk data then requested
>       usb-redir: Convert to new libusbredirparser 0.5 API
>       usb-redir: Set ep max_packet_size if available
>       usb-redir: Add a usbredir_reject_device helper function
>       usb-redir: Ensure our peer has the necessary caps when redirecting to XHCI
>       usb-redir: Enable pipelining for bulk endpoints
> 
> Samuel Thibault (1):
>       Better name usb braille device
> 
>  configure            |    2 +-
>  hw/usb.h             |    9 +
>  hw/usb/core.c        |   23 +-
>  hw/usb/desc.c        |  174 ++++++-
>  hw/usb/desc.h        |   52 ++-
>  hw/usb/dev-audio.c   |    2 +-
>  hw/usb/dev-serial.c  |    2 +-
>  hw/usb/dev-storage.c |   46 ++-
>  hw/usb/hcd-ehci.c    |  180 ++++---
>  hw/usb/hcd-uhci.c    |    5 -
>  hw/usb/hcd-xhci.c    | 1432 ++++++++++++++++++++++++++------------------------
>  hw/usb/redirect.c    |  477 ++++++++---------
>  trace-events         |   12 +-
>  13 files changed, 1376 insertions(+), 1040 deletions(-)
> 

This doesn't build:

| hw/usb/hcd-xhci.c: In function ‘xhci_fire_ctl_transfer’:
| hw/usb/hcd-xhci.c:1508:14: error: variable ‘wLength’ set but not used [-Werror=unused-but-set-variable]

-- 
Aurelien Jarno                          GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

* Re: [Qemu-devel] [PULL 00/54] usb patch queue
  2012-09-10 13:23 ` [Qemu-devel] [PULL 00/54] usb patch queue Aurelien Jarno
@ 2012-09-10 13:37   ` Gerd Hoffmann
  2012-09-10 15:08     ` Andreas Färber
  0 siblings, 1 reply; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-10 13:37 UTC (permalink / raw)
  To: Aurelien Jarno; +Cc: qemu-devel

  Hi,

> | hw/usb/hcd-xhci.c: In function ‘xhci_fire_ctl_transfer’:
> | hw/usb/hcd-xhci.c:1508:14: error: variable ‘wLength’ set but not used [-Werror=unused-but-set-variable]

Pushed updated branch usb.63 (same as usb.62 + one incremental fix).

cheers,
  Gerd

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

* Re: [Qemu-devel] [PULL 00/54] usb patch queue
  2012-09-10 13:37   ` Gerd Hoffmann
@ 2012-09-10 15:08     ` Andreas Färber
  2012-09-10 17:49       ` Anthony Liguori
  0 siblings, 1 reply; 61+ messages in thread
From: Andreas Färber @ 2012-09-10 15:08 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel, Aurelien Jarno

Am 10.09.2012 15:37, schrieb Gerd Hoffmann:
>   Hi,
> 
>> | hw/usb/hcd-xhci.c: In function ‘xhci_fire_ctl_transfer’:
>> | hw/usb/hcd-xhci.c:1508:14: error: variable ‘wLength’ set but not used [-Werror=unused-but-set-variable]
> 
> Pushed updated branch usb.63 (same as usb.62 + one incremental fix).

Can't you squash that for bisectability?

Andreas

-- 
SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

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

* Re: [Qemu-devel] [PULL 00/54] usb patch queue
  2012-09-10 15:08     ` Andreas Färber
@ 2012-09-10 17:49       ` Anthony Liguori
  2012-09-11  5:46         ` Gerd Hoffmann
  0 siblings, 1 reply; 61+ messages in thread
From: Anthony Liguori @ 2012-09-10 17:49 UTC (permalink / raw)
  To: Andreas Färber, Gerd Hoffmann; +Cc: qemu-devel, Aurelien Jarno

Andreas Färber <afaerber@suse.de> writes:

> Am 10.09.2012 15:37, schrieb Gerd Hoffmann:
>>   Hi,
>> 
>>> | hw/usb/hcd-xhci.c: In function ‘xhci_fire_ctl_transfer’:
>>> | hw/usb/hcd-xhci.c:1508:14: error: variable ‘wLength’ set but not used [-Werror=unused-but-set-variable]
>> 
>> Pushed updated branch usb.63 (same as usb.62 + one incremental fix).
>
> Can't you squash that for bisectability?

Yes, please do.

Regards,

Anthony Liguori

>
> Andreas
>
> -- 
> SUSE LINUX Products GmbH, Maxfeldstr. 5, 90409 Nürnberg, Germany
> GF: Jeff Hawn, Jennifer Guild, Felix Imendörffer; HRB 16746 AG Nürnberg

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

* Re: [Qemu-devel] [PULL 00/54] usb patch queue
  2012-09-10 17:49       ` Anthony Liguori
@ 2012-09-11  5:46         ` Gerd Hoffmann
  2012-09-11 17:22           ` Aurelien Jarno
  0 siblings, 1 reply; 61+ messages in thread
From: Gerd Hoffmann @ 2012-09-11  5:46 UTC (permalink / raw)
  To: Anthony Liguori; +Cc: Andreas Färber, Aurelien Jarno, qemu-devel

On 09/10/12 19:49, Anthony Liguori wrote:
> Andreas Färber <afaerber@suse.de> writes:
> 
>> Am 10.09.2012 15:37, schrieb Gerd Hoffmann:
>>>   Hi,
>>>
>>>> | hw/usb/hcd-xhci.c: In function ‘xhci_fire_ctl_transfer’:
>>>> | hw/usb/hcd-xhci.c:1508:14: error: variable ‘wLength’ set but not used [-Werror=unused-but-set-variable]
>>>
>>> Pushed updated branch usb.63 (same as usb.62 + one incremental fix).
>>
>> Can't you squash that for bisectability?
> 
> Yes, please do.

Squashed & rebased to master.
Pushed to git://git.kraxel.org/qemu usb.64

cheers,
  Gerd

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

* Re: [Qemu-devel] [PULL 00/54] usb patch queue
  2012-09-11  5:46         ` Gerd Hoffmann
@ 2012-09-11 17:22           ` Aurelien Jarno
  0 siblings, 0 replies; 61+ messages in thread
From: Aurelien Jarno @ 2012-09-11 17:22 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: Andreas Färber, Anthony Liguori, qemu-devel

On Tue, Sep 11, 2012 at 07:46:13AM +0200, Gerd Hoffmann wrote:
> On 09/10/12 19:49, Anthony Liguori wrote:
> > Andreas Färber <afaerber@suse.de> writes:
> > 
> >> Am 10.09.2012 15:37, schrieb Gerd Hoffmann:
> >>>   Hi,
> >>>
> >>>> | hw/usb/hcd-xhci.c: In function ‘xhci_fire_ctl_transfer’:
> >>>> | hw/usb/hcd-xhci.c:1508:14: error: variable ‘wLength’ set but not used [-Werror=unused-but-set-variable]
> >>>
> >>> Pushed updated branch usb.63 (same as usb.62 + one incremental fix).
> >>
> >> Can't you squash that for bisectability?
> > 
> > Yes, please do.
> 
> Squashed & rebased to master.
> Pushed to git://git.kraxel.org/qemu usb.64
> 

Pulled.

-- 
Aurelien Jarno	                        GPG: 1024D/F1BCDB73
aurelien@aurel32.net                 http://www.aurel32.net

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

end of thread, other threads:[~2012-09-11 17:22 UTC | newest]

Thread overview: 61+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-09-06  7:12 [Qemu-devel] [PULL 00/54] usb patch queue Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 01/54] usb: controllers do not need to check for babble themselves Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 02/54] usb-core: Don't set packet state to complete on a nak Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 03/54] usb-core: Add a usb_ep_find_packet_by_id() helper function Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 04/54] usb-core: Allow the first packet of a pipelined ep to complete immediately Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 05/54] Revert "ehci: don't flush cache on doorbell rings." Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 06/54] ehci: Validate qh is not changed unexpectedly by the guest Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 07/54] ehci: Update copyright headers to reflect recent work Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 08/54] ehci: Properly cleanup packets on cancel Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 09/54] ehci: Properly report completed but not yet processed packets to the guest Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 10/54] ehci: check for EHCI_ASYNC_FINISHED first in ehci_free_packet Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 11/54] ehci: trace guest bugs Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 12/54] ehci: add doorbell trace events Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 13/54] ehci: Add some additional ehci_trace_guest_bug() calls Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 14/54] ehci: Fix memory leak in handling of NAK-ed packets Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 15/54] ehci: Handle USB_RET_PROCERR in ehci_fill_queue Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 16/54] ehci: Correct a comment in fetchqtd packet processing Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 17/54] usb-redir: Never return USB_RET_NAK for async handled packets Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 18/54] usb-redir: Don't delay handling of open events to a bottom half Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 19/54] usb-redir: Get rid of async-struct get member Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 20/54] usb-redir: Get rid of local shadow copy of packet headers Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 21/54] usb-redir: Get rid of unused async-struct dev member Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 22/54] usb-redir: Move to core packet id and queue handling Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 23/54] usb-redir: Return babble when getting more bulk data then requested Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 24/54] usb-redir: Convert to new libusbredirparser 0.5 API Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 25/54] usb-redir: Set ep max_packet_size if available Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 26/54] usb-redir: Add a usbredir_reject_device helper function Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 27/54] usb-redir: Ensure our peer has the necessary caps when redirecting to XHCI Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 28/54] usb-redir: Enable pipelining for bulk endpoints Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 29/54] Better name usb braille device Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 30/54] usb-audio: fix usb version Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 31/54] xhci: rip out background transfer code Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 32/54] xhci: drop buffering Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 33/54] xhci: move device lookup into xhci_setup_packet Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 34/54] xhci: implement mfindex Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 35/54] xhci: iso xfer support Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 36/54] xhci: trace cc codes in cleartext Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 37/54] xhci: add trace_usb_xhci_ep_set_dequeue Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 38/54] xhci: fix runtime write tracepoint Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 39/54] xhci: update register layout Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 40/54] xhci: update port handling Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 41/54] usb3: superspeed descriptors Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 42/54] usb3: superspeed endpoint companion Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 43/54] usb3: bos decriptor Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 44/54] usb-storage: usb3 support Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 45/54] xhci: fix & cleanup msi Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 46/54] xhci: rework interrupt handling Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 47/54] xhci: add msix support Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 48/54] xhci: move register update into xhci_intr_raise Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 49/54] xhci: add XHCIInterrupter Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 50/54] xhci: prepare xhci_runtime_{read, write} for multiple interrupters Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 51/54] xhci: pick target interrupter Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 52/54] xhci: support multiple interrupters Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 53/54] xhci: kill xhci_mem_{read, write} dispatcher functions Gerd Hoffmann
2012-09-06  7:12 ` [Qemu-devel] [PATCH 54/54] xhci: allow bytewise capability register reads Gerd Hoffmann
2012-09-10 13:23 ` [Qemu-devel] [PULL 00/54] usb patch queue Aurelien Jarno
2012-09-10 13:37   ` Gerd Hoffmann
2012-09-10 15:08     ` Andreas Färber
2012-09-10 17:49       ` Anthony Liguori
2012-09-11  5:46         ` Gerd Hoffmann
2012-09-11 17:22           ` Aurelien Jarno

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.