All of lore.kernel.org
 help / color / mirror / Atom feed
* [Qemu-devel] [PULL 00/37] usb patch queue
@ 2012-06-07  9:30 Gerd Hoffmann
  2012-06-07  9:30 ` [Qemu-devel] [PATCH 01/37] uhci: fix bandwidth management Gerd Hoffmann
                   ` (37 more replies)
  0 siblings, 38 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

  Hi,

Here are a bunch of usb patches.  There are four groups in there which
are independant and have been posted as separate series for review ~ two
weeks ago:

  (1) uhci: various little fixes and improvements.
  (2) usb-storage: live migration support.
  (3) xhci: tracing support.
  (4) ehci: pipelining (have multiple packets per endpoint in flight),
      schedule & timer handling improvements to reduce wakeup rate.

please pull,
  Gerd

The following changes since commit 349417004a0f7cf5518a998dca755cd06f6c212b:

  Merge remote-tracking branch 'qmp/queue/qmp' into staging (2012-06-06 20:57:56 +0800)

are available in the git repository at:

  git://git.kraxel.org/qemu usb.52

Gerd Hoffmann (36):
      uhci: fix bandwidth management
      uhci: use bottom half
      uhci: make bandwidth tunable
      uhci: fix trace format strings
      uhci: zap uhci_pre_save
      uhci: fix irq routing
      scsi: prepare migration code for usb-storage support
      usb-storage: remove MSDState->residue
      usb-storage: add usb_msd_packet_complete()
      usb-storage: add scsi_off, remove scsi_buf
      usb-storage: migration support
      xhci: trace: mmio reads+writes
      xhci: trace: run+stop
      xhci: trace: irq + events
      xhci: trace: ring fetch
      xhci: trace: endpoints
      xhci: trace: transfers
      xhci: trace: slots
      ehci: add EHCIPacket
      ehci: make ehci_execute work on EHCIPacket instead of EHCIQueue
      ehci: cache USBDevice in EHCIQueue
      ehci: move ehci_flush_qh
      ehci: add queuing support
      ehci: tweak queue initialization
      ehci: add async field to EHCIQueue
      ehci: move async schedule to bottom half
      ehci: schedule async bh on async packet completion
      ehci: kick async schedule on wakeup
      ehci: fix reset
      ehci: add ehci_*_enabled() helpers
      ehci: update status bits in ehci_set_state
      ehci: fix halt status handling
      ehci: remove unused attach_poll_counter
      ehci: create ehci_update_frindex
      ehci: adaptive wakeup rate.
      ehci: rework frame skipping

Jan Kiszka (1):
      xhci: Clean up reset function

 hw/scsi-bus.c        |    8 +-
 hw/scsi-disk.c       |   16 ++-
 hw/usb/dev-storage.c |   69 ++++--
 hw/usb/hcd-ehci.c    |  610 +++++++++++++++++++++++++++++++++-----------------
 hw/usb/hcd-uhci.c    |   67 ++++--
 hw/usb/hcd-xhci.c    |  251 ++++++++++++----------
 trace-events         |   46 ++++-
 7 files changed, 695 insertions(+), 372 deletions(-)

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

* [Qemu-devel] [PATCH 01/37] uhci: fix bandwidth management
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
@ 2012-06-07  9:30 ` Gerd Hoffmann
  2012-06-07  9:30 ` [Qemu-devel] [PATCH 02/37] uhci: use bottom half Gerd Hoffmann
                   ` (36 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

uhci_process_frame() can be invoked multiple times per frame, so
accounting usb bandwith in a local variable doesn't fly, use a variable
in UHCIState instead.  Also check the limit more frequently.

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

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 9e211a0..48ad35c 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -131,6 +131,7 @@ struct UHCIState {
     uint8_t status2; /* bit 0 and 1 are used to generate UHCI_STS_USBINT */
     int64_t expire_time;
     QEMUTimer *frame_timer;
+    uint32_t frame_bytes;
     UHCIPort ports[NB_PORTS];
 
     /* Interrupts that should be raised at the end of the current frame.  */
@@ -985,7 +986,7 @@ static void uhci_fill_queue(UHCIState *s, UHCI_TD *td)
 static void uhci_process_frame(UHCIState *s)
 {
     uint32_t frame_addr, link, old_td_ctrl, val, int_mask;
-    uint32_t curr_qh, td_count = 0, bytes_count = 0;
+    uint32_t curr_qh, td_count = 0;
     int cnt, ret;
     UHCI_TD td;
     UHCI_QH qh;
@@ -1002,6 +1003,12 @@ static void uhci_process_frame(UHCIState *s)
     qhdb_reset(&qhdb);
 
     for (cnt = FRAME_MAX_LOOPS; is_valid(link) && cnt; cnt--) {
+        if (s->frame_bytes >= 1280) {
+            /* We've reached the usb 1.1 bandwidth, which is
+               1280 bytes/frame, stop processing */
+            trace_usb_uhci_frame_stop_bandwidth();
+            break;
+        }
         if (is_qh(link)) {
             /* QH */
             trace_usb_uhci_qh_load(link & ~0xf);
@@ -1011,18 +1018,12 @@ static void uhci_process_frame(UHCIState *s)
                  * We're going in circles. Which is not a bug because
                  * HCD is allowed to do that as part of the BW management.
                  *
-                 * Stop processing here if
-                 *  (a) no transaction has been done since we've been
-                 *      here last time, or
-                 *  (b) we've reached the usb 1.1 bandwidth, which is
-                 *      1280 bytes/frame.
+                 * Stop processing here if no transaction has been done
+                 * since we've been here last time.
                  */
                 if (td_count == 0) {
                     trace_usb_uhci_frame_loop_stop_idle();
                     break;
-                } else if (bytes_count >= 1280) {
-                    trace_usb_uhci_frame_loop_stop_bandwidth();
-                    break;
                 } else {
                     trace_usb_uhci_frame_loop_continue();
                     td_count = 0;
@@ -1085,7 +1086,7 @@ static void uhci_process_frame(UHCIState *s)
             trace_usb_uhci_td_complete(curr_qh & ~0xf, link & ~0xf);
             link = td.link;
             td_count++;
-            bytes_count += (td.ctrl & 0x7ff) + 1;
+            s->frame_bytes += (td.ctrl & 0x7ff) + 1;
 
             if (curr_qh) {
                 /* update QH element link */
@@ -1118,6 +1119,7 @@ static void uhci_frame_timer(void *opaque)
 
     /* prepare the timer for the next frame */
     s->expire_time += (get_ticks_per_sec() / FRAME_TIMER_FREQ);
+    s->frame_bytes = 0;
 
     if (!(s->cmd & UHCI_CMD_RS)) {
         /* Full stop */
diff --git a/trace-events b/trace-events
index 45c6bc1..560e57b 100644
--- a/trace-events
+++ b/trace-events
@@ -263,8 +263,8 @@ usb_uhci_reset(void) "=== RESET ==="
 usb_uhci_schedule_start(void) ""
 usb_uhci_schedule_stop(void) ""
 usb_uhci_frame_start(uint32_t num) "nr %d"
+usb_uhci_frame_stop_bandwidth(void) ""
 usb_uhci_frame_loop_stop_idle(void) ""
-usb_uhci_frame_loop_stop_bandwidth(void) ""
 usb_uhci_frame_loop_continue(void) ""
 usb_uhci_mmio_readw(uint32_t addr, uint32_t val) "addr %04x, ret 0x04%x"
 usb_uhci_mmio_writew(uint32_t addr, uint32_t val) "addr %04x, val 0x04%x"
-- 
1.7.1

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

* [Qemu-devel] [PATCH 02/37] uhci: use bottom half
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
  2012-06-07  9:30 ` [Qemu-devel] [PATCH 01/37] uhci: fix bandwidth management Gerd Hoffmann
@ 2012-06-07  9:30 ` Gerd Hoffmann
  2012-06-07  9:30 ` [Qemu-devel] [PATCH 03/37] uhci: make bandwidth tunable Gerd Hoffmann
                   ` (35 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Schedule bottom half on completion of async packets instead of calling
uhci_process_frame directly.  This way we run uhci_process_frame only
once in case multiple packets finish in a row.  Also check whenever
there is bandwidth left before scheduling uhci_process_frame.

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

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 48ad35c..91bcc7e 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -131,6 +131,7 @@ struct UHCIState {
     uint8_t status2; /* bit 0 and 1 are used to generate UHCI_STS_USBINT */
     int64_t expire_time;
     QEMUTimer *frame_timer;
+    QEMUBH *bh;
     uint32_t frame_bytes;
     UHCIPort ports[NB_PORTS];
 
@@ -370,6 +371,7 @@ static void uhci_reset(void *opaque)
     }
 
     uhci_async_cancel_all(s);
+    qemu_bh_cancel(s->bh);
     uhci_update_irq(s);
 }
 
@@ -906,7 +908,9 @@ static void uhci_async_complete(USBPort *port, USBPacket *packet)
         uhci_async_free(async);
     } else {
         async->done = 1;
-        uhci_process_frame(s);
+        if (s->frame_bytes < 1280) {
+            qemu_bh_schedule(s->bh);
+        }
     }
 }
 
@@ -1113,6 +1117,12 @@ out:
     s->pending_int_mask |= int_mask;
 }
 
+static void uhci_bh(void *opaque)
+{
+    UHCIState *s = opaque;
+    uhci_process_frame(s);
+}
+
 static void uhci_frame_timer(void *opaque)
 {
     UHCIState *s = opaque;
@@ -1120,6 +1130,7 @@ static void uhci_frame_timer(void *opaque)
     /* prepare the timer for the next frame */
     s->expire_time += (get_ticks_per_sec() / FRAME_TIMER_FREQ);
     s->frame_bytes = 0;
+    qemu_bh_cancel(s->bh);
 
     if (!(s->cmd & UHCI_CMD_RS)) {
         /* Full stop */
@@ -1206,6 +1217,7 @@ static int usb_uhci_common_initfn(PCIDevice *dev)
                               USB_SPEED_MASK_LOW | USB_SPEED_MASK_FULL);
         }
     }
+    s->bh = qemu_bh_new(uhci_bh, s);
     s->frame_timer = qemu_new_timer_ns(vm_clock, uhci_frame_timer, s);
     s->num_ports_vmstate = NB_PORTS;
     QTAILQ_INIT(&s->queues);
-- 
1.7.1

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

* [Qemu-devel] [PATCH 03/37] uhci: make bandwidth tunable
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
  2012-06-07  9:30 ` [Qemu-devel] [PATCH 01/37] uhci: fix bandwidth management Gerd Hoffmann
  2012-06-07  9:30 ` [Qemu-devel] [PATCH 02/37] uhci: use bottom half Gerd Hoffmann
@ 2012-06-07  9:30 ` Gerd Hoffmann
  2012-06-07  9:30 ` [Qemu-devel] [PATCH 04/37] uhci: fix trace format strings Gerd Hoffmann
                   ` (34 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add a property for the uhci bandwidth.  Can be used to make uhci
emulation run faster than real hardware.

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

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 91bcc7e..2e7c8f9 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -133,6 +133,7 @@ struct UHCIState {
     QEMUTimer *frame_timer;
     QEMUBH *bh;
     uint32_t frame_bytes;
+    uint32_t frame_bandwidth;
     UHCIPort ports[NB_PORTS];
 
     /* Interrupts that should be raised at the end of the current frame.  */
@@ -908,7 +909,7 @@ static void uhci_async_complete(USBPort *port, USBPacket *packet)
         uhci_async_free(async);
     } else {
         async->done = 1;
-        if (s->frame_bytes < 1280) {
+        if (s->frame_bytes < s->frame_bandwidth) {
             qemu_bh_schedule(s->bh);
         }
     }
@@ -1007,7 +1008,7 @@ static void uhci_process_frame(UHCIState *s)
     qhdb_reset(&qhdb);
 
     for (cnt = FRAME_MAX_LOOPS; is_valid(link) && cnt; cnt--) {
-        if (s->frame_bytes >= 1280) {
+        if (s->frame_bytes >= s->frame_bandwidth) {
             /* We've reached the usb 1.1 bandwidth, which is
                1280 bytes/frame, stop processing */
             trace_usb_uhci_frame_stop_bandwidth();
@@ -1258,6 +1259,7 @@ static int usb_uhci_exit(PCIDevice *dev)
 static Property uhci_properties[] = {
     DEFINE_PROP_STRING("masterbus", UHCIState, masterbus),
     DEFINE_PROP_UINT32("firstport", UHCIState, firstport, 0),
+    DEFINE_PROP_UINT32("bandwidth", UHCIState, frame_bandwidth, 1280),
     DEFINE_PROP_END_OF_LIST(),
 };
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH 04/37] uhci: fix trace format strings
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (2 preceding siblings ...)
  2012-06-07  9:30 ` [Qemu-devel] [PATCH 03/37] uhci: make bandwidth tunable Gerd Hoffmann
@ 2012-06-07  9:30 ` Gerd Hoffmann
  2012-06-07  9:30 ` [Qemu-devel] [PATCH 05/37] uhci: zap uhci_pre_save Gerd Hoffmann
                   ` (33 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 trace-events |    8 ++++----
 1 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/trace-events b/trace-events
index 560e57b..dd057bc 100644
--- a/trace-events
+++ b/trace-events
@@ -266,10 +266,10 @@ usb_uhci_frame_start(uint32_t num) "nr %d"
 usb_uhci_frame_stop_bandwidth(void) ""
 usb_uhci_frame_loop_stop_idle(void) ""
 usb_uhci_frame_loop_continue(void) ""
-usb_uhci_mmio_readw(uint32_t addr, uint32_t val) "addr %04x, ret 0x04%x"
-usb_uhci_mmio_writew(uint32_t addr, uint32_t val) "addr %04x, val 0x04%x"
-usb_uhci_mmio_readl(uint32_t addr, uint32_t val) "addr %04x, ret 0x08%x"
-usb_uhci_mmio_writel(uint32_t addr, uint32_t val) "addr %04x, val 0x08%x"
+usb_uhci_mmio_readw(uint32_t addr, uint32_t val) "addr 0x%04x, ret 0x%04x"
+usb_uhci_mmio_writew(uint32_t addr, uint32_t val) "addr 0x%04x, val 0x%04x"
+usb_uhci_mmio_readl(uint32_t addr, uint32_t val) "addr 0x%04x, ret 0x%08x"
+usb_uhci_mmio_writel(uint32_t addr, uint32_t val) "addr 0x%04x, val 0x%08x"
 usb_uhci_queue_add(uint32_t token) "token 0x%x"
 usb_uhci_queue_del(uint32_t token) "token 0x%x"
 usb_uhci_packet_add(uint32_t token, uint32_t addr) "token 0x%x, td 0x%x"
-- 
1.7.1

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

* [Qemu-devel] [PATCH 05/37] uhci: zap uhci_pre_save
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (3 preceding siblings ...)
  2012-06-07  9:30 ` [Qemu-devel] [PATCH 04/37] uhci: fix trace format strings Gerd Hoffmann
@ 2012-06-07  9:30 ` Gerd Hoffmann
  2012-06-07  9:30 ` [Qemu-devel] [PATCH 06/37] uhci: fix irq routing Gerd Hoffmann
                   ` (32 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Cancel transactions before saving vmstate is pretty pointless and just
causes disruptions.  We need to cancel them before *loading* vmstate,
but in that case uhci_reset() handles it already and no special action
is needed.

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

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 2e7c8f9..3ea388c 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -376,13 +376,6 @@ static void uhci_reset(void *opaque)
     uhci_update_irq(s);
 }
 
-static void uhci_pre_save(void *opaque)
-{
-    UHCIState *s = opaque;
-
-    uhci_async_cancel_all(s);
-}
-
 static const VMStateDescription vmstate_uhci_port = {
     .name = "uhci port",
     .version_id = 1,
@@ -399,7 +392,6 @@ static const VMStateDescription vmstate_uhci = {
     .version_id = 2,
     .minimum_version_id = 1,
     .minimum_version_id_old = 1,
-    .pre_save = uhci_pre_save,
     .fields      = (VMStateField []) {
         VMSTATE_PCI_DEVICE(dev, UHCIState),
         VMSTATE_UINT8_EQUAL(num_ports_vmstate, UHCIState),
-- 
1.7.1

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

* [Qemu-devel] [PATCH 06/37] uhci: fix irq routing
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (4 preceding siblings ...)
  2012-06-07  9:30 ` [Qemu-devel] [PATCH 05/37] uhci: zap uhci_pre_save Gerd Hoffmann
@ 2012-06-07  9:30 ` Gerd Hoffmann
  2012-06-07  9:30 ` [Qemu-devel] [PATCH 07/37] scsi: prepare migration code for usb-storage support Gerd Hoffmann
                   ` (31 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

The multifunction ich9 ehci controller with uhci companions uses a
different interrupt pin for each function.  The three uhci devices
get pins A, B and C, whereas ehci uses pin D.  This way the guest
can assign different IRQ lines to each controller.

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

diff --git a/hw/usb/hcd-uhci.c b/hw/usb/hcd-uhci.c
index 3ea388c..9871e24 100644
--- a/hw/usb/hcd-uhci.c
+++ b/hw/usb/hcd-uhci.c
@@ -138,6 +138,7 @@ struct UHCIState {
 
     /* Interrupts that should be raised at the end of the current frame.  */
     uint32_t pending_int_mask;
+    int irq_pin;
 
     /* Active packets */
     QTAILQ_HEAD(, UHCIQueue) queues;
@@ -340,7 +341,7 @@ static void uhci_update_irq(UHCIState *s)
     } else {
         level = 0;
     }
-    qemu_set_irq(s->dev.irq[3], level);
+    qemu_set_irq(s->dev.irq[s->irq_pin], level);
 }
 
 static void uhci_reset(void *opaque)
@@ -1184,15 +1185,31 @@ static USBBusOps uhci_bus_ops = {
 
 static int usb_uhci_common_initfn(PCIDevice *dev)
 {
+    PCIDeviceClass *pc = PCI_DEVICE_GET_CLASS(dev);
     UHCIState *s = DO_UPCAST(UHCIState, dev, dev);
     uint8_t *pci_conf = s->dev.config;
     int i;
 
     pci_conf[PCI_CLASS_PROG] = 0x00;
     /* TODO: reset value should be 0. */
-    pci_conf[PCI_INTERRUPT_PIN] = 4; /* interrupt pin D */
     pci_conf[USB_SBRN] = USB_RELEASE_1; // release number
 
+    switch (pc->device_id) {
+    case PCI_DEVICE_ID_INTEL_82801I_UHCI1:
+        s->irq_pin = 0;  /* A */
+        break;
+    case PCI_DEVICE_ID_INTEL_82801I_UHCI2:
+        s->irq_pin = 1;  /* B */
+        break;
+    case PCI_DEVICE_ID_INTEL_82801I_UHCI3:
+        s->irq_pin = 2;  /* C */
+        break;
+    default:
+        s->irq_pin = 3;  /* D */
+        break;
+    }
+    pci_config_set_interrupt_pin(pci_conf, s->irq_pin + 1);
+
     if (s->masterbus) {
         USBPort *ports[NB_PORTS];
         for(i = 0; i < NB_PORTS; i++) {
-- 
1.7.1

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

* [Qemu-devel] [PATCH 07/37] scsi: prepare migration code for usb-storage support
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (5 preceding siblings ...)
  2012-06-07  9:30 ` [Qemu-devel] [PATCH 06/37] uhci: fix irq routing Gerd Hoffmann
@ 2012-06-07  9:30 ` Gerd Hoffmann
  2012-06-07  9:30 ` [Qemu-devel] [PATCH 08/37] usb-storage: remove MSDState->residue Gerd Hoffmann
                   ` (30 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: Paolo Bonzini, Gerd Hoffmann

usb-storage can't handle requests in one go as the data transfer can be
splitted into lots of usb packets.  Because of that there can be
normal in-flight requests at savevm time and we need to handle that.
With other scsi hba's this happens only in case i/o is stopped due to
errors and there are pending requests which need to be restarted
(req->retry = true).

So, first we need to save req->retry and then handle the req->retry =
false case.  Write requests are handled fine already.  For read requests
we have to save the buffer as we will not restart the request (and thus
not refill the buffer) on the target host.

Cc: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 hw/scsi-bus.c  |    8 ++++----
 hw/scsi-disk.c |   16 ++++++++++++++--
 2 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/hw/scsi-bus.c b/hw/scsi-bus.c
index f10f3ec..4a79821 100644
--- a/hw/scsi-bus.c
+++ b/hw/scsi-bus.c
@@ -1507,10 +1507,9 @@ static void put_scsi_requests(QEMUFile *f, void *pv, size_t size)
     QTAILQ_FOREACH(req, &s->requests, next) {
         assert(!req->io_canceled);
         assert(req->status == -1);
-        assert(req->retry);
         assert(req->enqueued);
 
-        qemu_put_sbyte(f, 1);
+        qemu_put_sbyte(f, req->retry ? 1 : 2);
         qemu_put_buffer(f, req->cmd.buf, sizeof(req->cmd.buf));
         qemu_put_be32s(f, &req->tag);
         qemu_put_be32s(f, &req->lun);
@@ -1528,8 +1527,9 @@ static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
 {
     SCSIDevice *s = pv;
     SCSIBus *bus = DO_UPCAST(SCSIBus, qbus, s->qdev.parent_bus);
+    int8_t sbyte;
 
-    while (qemu_get_sbyte(f)) {
+    while ((sbyte = qemu_get_sbyte(f)) > 0) {
         uint8_t buf[SCSI_CMD_BUF_SIZE];
         uint32_t tag;
         uint32_t lun;
@@ -1539,6 +1539,7 @@ static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
         qemu_get_be32s(f, &tag);
         qemu_get_be32s(f, &lun);
         req = scsi_req_new(s, tag, lun, buf, NULL);
+        req->retry = (sbyte == 1);
         if (bus->info->load_request) {
             req->hba_private = bus->info->load_request(f, req);
         }
@@ -1547,7 +1548,6 @@ static int get_scsi_requests(QEMUFile *f, void *pv, size_t size)
         }
 
         /* Just restart it later.  */
-        req->retry = true;
         scsi_req_enqueue_internal(req);
 
         /* At this point, the request will be kept alive by the reference
diff --git a/hw/scsi-disk.c b/hw/scsi-disk.c
index 045c764..1691491 100644
--- a/hw/scsi-disk.c
+++ b/hw/scsi-disk.c
@@ -132,8 +132,14 @@ static void scsi_disk_save_request(QEMUFile *f, SCSIRequest *req)
     qemu_put_be64s(f, &r->sector);
     qemu_put_be32s(f, &r->sector_count);
     qemu_put_be32s(f, &r->buflen);
-    if (r->buflen && r->req.cmd.mode == SCSI_XFER_TO_DEV) {
-        qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
+    if (r->buflen) {
+        if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
+            qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
+        } else if (!req->retry) {
+            uint32_t len = r->iov.iov_len;
+            qemu_put_be32s(f, &len);
+            qemu_put_buffer(f, r->iov.iov_base, r->iov.iov_len);
+        }
     }
 }
 
@@ -148,6 +154,12 @@ static void scsi_disk_load_request(QEMUFile *f, SCSIRequest *req)
         scsi_init_iovec(r, r->buflen);
         if (r->req.cmd.mode == SCSI_XFER_TO_DEV) {
             qemu_get_buffer(f, r->iov.iov_base, r->iov.iov_len);
+        } else if (!r->req.retry) {
+            uint32_t len;
+            qemu_get_be32s(f, &len);
+            r->iov.iov_len = len;
+            assert(r->iov.iov_len <= r->buflen);
+            qemu_get_buffer(f, r->iov.iov_base, r->iov.iov_len);
         }
     }
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH 08/37] usb-storage: remove MSDState->residue
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (6 preceding siblings ...)
  2012-06-07  9:30 ` [Qemu-devel] [PATCH 07/37] scsi: prepare migration code for usb-storage support Gerd Hoffmann
@ 2012-06-07  9:30 ` Gerd Hoffmann
  2012-06-07  9:30 ` [Qemu-devel] [PATCH 09/37] usb-storage: add usb_msd_packet_complete() Gerd Hoffmann
                   ` (29 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

We have the field twice, once in MSDState directly and one in the status
word struct.  Drop one.

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

diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index a96c0b9..e6652f9 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -51,7 +51,6 @@ typedef struct {
     uint32_t scsi_len;
     uint8_t *scsi_buf;
     uint32_t data_len;
-    uint32_t residue;
     struct usb_msd_csw csw;
     SCSIRequest *req;
     SCSIBus bus;
@@ -229,11 +228,10 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t r
     USBPacket *p = s->packet;
 
     DPRINTF("Command complete %d tag 0x%x\n", status, req->tag);
-    s->residue = s->data_len;
 
     s->csw.sig = cpu_to_le32(0x53425355);
     s->csw.tag = cpu_to_le32(req->tag);
-    s->csw.residue = cpu_to_le32(s->residue);
+    s->csw.residue = cpu_to_le32(s->data_len);
     s->csw.status = status != 0;
 
     if (s->packet) {
@@ -378,7 +376,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
             }
             DPRINTF("Command tag 0x%x flags %08x len %d data %d\n",
                     tag, cbw.flags, cbw.cmd_len, s->data_len);
-            s->residue = 0;
+            assert(le32_to_cpu(s->csw.residue) == 0);
             s->scsi_len = 0;
             s->req = scsi_req_new(s->scsi_dev, tag, 0, cbw.cmd, NULL);
             scsi_req_enqueue(s->req);
@@ -397,7 +395,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
             if (s->scsi_len) {
                 usb_msd_copy_data(s, p);
             }
-            if (s->residue) {
+            if (le32_to_cpu(s->csw.residue)) {
                 int len = p->iov.size - p->result;
                 if (len) {
                     usb_packet_skip(p, len);
@@ -458,7 +456,7 @@ static int usb_msd_handle_data(USBDevice *dev, USBPacket *p)
             if (s->scsi_len) {
                 usb_msd_copy_data(s, p);
             }
-            if (s->residue) {
+            if (le32_to_cpu(s->csw.residue)) {
                 int len = p->iov.size - p->result;
                 if (len) {
                     usb_packet_skip(p, len);
-- 
1.7.1

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

* [Qemu-devel] [PATCH 09/37] usb-storage: add usb_msd_packet_complete()
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (7 preceding siblings ...)
  2012-06-07  9:30 ` [Qemu-devel] [PATCH 08/37] usb-storage: remove MSDState->residue Gerd Hoffmann
@ 2012-06-07  9:30 ` Gerd Hoffmann
  2012-06-07  9:30 ` [Qemu-devel] [PATCH 10/37] usb-storage: add scsi_off, remove scsi_buf Gerd Hoffmann
                   ` (28 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Factor out packet completion to a separate function which
cares to get the MSDState->packet update right.

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

diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index e6652f9..924a86f 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -200,6 +200,18 @@ static void usb_msd_send_status(MSDState *s, USBPacket *p)
     memset(&s->csw, 0, sizeof(s->csw));
 }
 
+static void usb_msd_packet_complete(MSDState *s)
+{
+    USBPacket *p = s->packet;
+
+    /* Set s->packet to NULL before calling usb_packet_complete
+       because another request may be issued before
+       usb_packet_complete returns.  */
+    DPRINTF("Packet complete %p\n", p);
+    s->packet = NULL;
+    usb_packet_complete(&s->dev, p);
+}
+
 static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
 {
     MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
@@ -212,12 +224,7 @@ static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
         usb_msd_copy_data(s, p);
         p = s->packet;
         if (p && p->result == p->iov.size) {
-            /* Set s->packet to NULL before calling usb_packet_complete
-               because another request may be issued before
-               usb_packet_complete returns.  */
-            DPRINTF("Packet complete %p\n", p);
-            s->packet = NULL;
-            usb_packet_complete(&s->dev, p);
+            usb_msd_packet_complete(s);
         }
     }
 }
@@ -250,8 +257,7 @@ static void usb_msd_command_complete(SCSIRequest *req, uint32_t status, size_t r
                 s->mode = USB_MSDM_CSW;
             }
         }
-        s->packet = NULL;
-        usb_packet_complete(&s->dev, p);
+        usb_msd_packet_complete(s);
     } else if (s->data_len == 0) {
         s->mode = USB_MSDM_CSW;
     }
@@ -281,10 +287,8 @@ static void usb_msd_handle_reset(USBDevice *dev)
     assert(s->req == NULL);
 
     if (s->packet) {
-        USBPacket *p = s->packet;
-        s->packet = NULL;
-        p->result = USB_RET_STALL;
-        usb_packet_complete(dev, p);
+        s->packet->result = USB_RET_STALL;
+        usb_msd_packet_complete(s);
     }
 
     s->mode = USB_MSDM_CBW;
-- 
1.7.1

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

* [Qemu-devel] [PATCH 10/37] usb-storage: add scsi_off, remove scsi_buf
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (8 preceding siblings ...)
  2012-06-07  9:30 ` [Qemu-devel] [PATCH 09/37] usb-storage: add usb_msd_packet_complete() Gerd Hoffmann
@ 2012-06-07  9:30 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 11/37] usb-storage: migration support Gerd Hoffmann
                   ` (27 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:30 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Repace the running buffer pointer (scsi_buf) with a buffer offset
field (scsi_off).  The later is alot easier to live-migrate.

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

diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index 924a86f..5b9a286 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -48,8 +48,8 @@ struct usb_msd_csw {
 typedef struct {
     USBDevice dev;
     enum USBMSDMode mode;
+    uint32_t scsi_off;
     uint32_t scsi_len;
-    uint8_t *scsi_buf;
     uint32_t data_len;
     struct usb_msd_csw csw;
     SCSIRequest *req;
@@ -178,9 +178,9 @@ static void usb_msd_copy_data(MSDState *s, USBPacket *p)
     len = p->iov.size - p->result;
     if (len > s->scsi_len)
         len = s->scsi_len;
-    usb_packet_copy(p, s->scsi_buf, len);
+    usb_packet_copy(p, scsi_req_get_buf(s->req) + s->scsi_off, len);
     s->scsi_len -= len;
-    s->scsi_buf += len;
+    s->scsi_off += len;
     s->data_len -= len;
     if (s->scsi_len == 0 || s->data_len == 0) {
         scsi_req_continue(s->req);
@@ -219,7 +219,7 @@ static void usb_msd_transfer_data(SCSIRequest *req, uint32_t len)
 
     assert((s->mode == USB_MSDM_DATAOUT) == (req->cmd.mode == SCSI_XFER_TO_DEV));
     s->scsi_len = len;
-    s->scsi_buf = scsi_req_get_buf(req);
+    s->scsi_off = 0;
     if (p) {
         usb_msd_copy_data(s, p);
         p = s->packet;
-- 
1.7.1

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

* [Qemu-devel] [PATCH 11/37] usb-storage: migration support
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (9 preceding siblings ...)
  2012-06-07  9:30 ` [Qemu-devel] [PATCH 10/37] usb-storage: add scsi_off, remove scsi_buf Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 12/37] xhci: Clean up reset function Gerd Hoffmann
                   ` (26 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

With all scsi migration support bits in place the
final step is pretty simple ;)

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

diff --git a/hw/usb/dev-storage.c b/hw/usb/dev-storage.c
index 5b9a286..097d7b4 100644
--- a/hw/usb/dev-storage.c
+++ b/hw/usb/dev-storage.c
@@ -506,6 +506,17 @@ static void usb_msd_password_cb(void *opaque, int err)
         qdev_unplug(&s->dev.qdev, NULL);
 }
 
+static void *usb_msd_load_request(QEMUFile *f, SCSIRequest *req)
+{
+    MSDState *s = DO_UPCAST(MSDState, dev.qdev, req->bus->qbus.parent);
+
+    /* nothing to load, just store req in our state struct */
+    assert(s->req == NULL);
+    scsi_req_ref(req);
+    s->req = req;
+    return NULL;
+}
+
 static const struct SCSIBusInfo usb_msd_scsi_info = {
     .tcq = false,
     .max_target = 0,
@@ -513,7 +524,8 @@ static const struct SCSIBusInfo usb_msd_scsi_info = {
 
     .transfer_data = usb_msd_transfer_data,
     .complete = usb_msd_command_complete,
-    .cancel = usb_msd_request_cancelled
+    .cancel = usb_msd_request_cancelled,
+    .load_request = usb_msd_load_request,
 };
 
 static int usb_msd_initfn(USBDevice *dev)
@@ -633,11 +645,18 @@ static USBDevice *usb_msd_init(USBBus *bus, const char *filename)
 
 static const VMStateDescription vmstate_usb_msd = {
     .name = "usb-storage",
-    .unmigratable = 1, /* FIXME: handle transactions which are in flight */
     .version_id = 1,
     .minimum_version_id = 1,
     .fields = (VMStateField []) {
         VMSTATE_USB_DEVICE(dev, MSDState),
+        VMSTATE_UINT32(mode, MSDState),
+        VMSTATE_UINT32(scsi_len, MSDState),
+        VMSTATE_UINT32(scsi_off, MSDState),
+        VMSTATE_UINT32(data_len, MSDState),
+        VMSTATE_UINT32(csw.sig, MSDState),
+        VMSTATE_UINT32(csw.tag, MSDState),
+        VMSTATE_UINT32(csw.residue, MSDState),
+        VMSTATE_UINT8(csw.status, MSDState),
         VMSTATE_END_OF_LIST()
     }
 };
-- 
1.7.1

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

* [Qemu-devel] [PATCH 12/37] xhci: Clean up reset function
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (10 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 11/37] usb-storage: migration support Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 13/37] xhci: trace: mmio reads+writes Gerd Hoffmann
                   ` (25 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Jan Kiszka, Gerd Hoffmann

From: Jan Kiszka <jan.kiszka@siemens.com>

Properly register reset function via the device class.

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

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 5cf1a64..4bc1e0e 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -2296,9 +2296,9 @@ static void xhci_update_port(XHCIState *xhci, XHCIPort *port, int is_detach)
     }
 }
 
-static void xhci_reset(void *opaque)
+static void xhci_reset(DeviceState *dev)
 {
-    XHCIState *xhci = opaque;
+    XHCIState *xhci = DO_UPCAST(XHCIState, pci_dev.qdev, dev);
     int i;
 
     DPRINTF("xhci: full reset\n");
@@ -2506,7 +2506,7 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val)
         }
         xhci->usbcmd = val & 0xc0f;
         if (val & USBCMD_HCRST) {
-            xhci_reset(xhci);
+            xhci_reset(&xhci->pci_dev.qdev);
         }
         xhci_irq_update(xhci);
         break;
@@ -2831,8 +2831,6 @@ static void usb_xhci_init(XHCIState *xhci, DeviceState *dev)
     for (i = 0; i < MAXSLOTS; i++) {
         xhci->slots[i].enabled = 0;
     }
-
-    qemu_register_reset(xhci_reset, xhci);
 }
 
 static int usb_xhci_initfn(struct PCIDevice *dev)
@@ -2895,6 +2893,7 @@ static void xhci_class_init(ObjectClass *klass, void *data)
 
     dc->vmsd    = &vmstate_xhci;
     dc->props   = xhci_properties;
+    dc->reset   = xhci_reset;
     k->init         = usb_xhci_initfn;
     k->vendor_id    = PCI_VENDOR_ID_NEC;
     k->device_id    = PCI_DEVICE_ID_NEC_UPD720200;
-- 
1.7.1

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

* [Qemu-devel] [PATCH 13/37] xhci: trace: mmio reads+writes
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (11 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 12/37] xhci: Clean up reset function Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 14/37] xhci: trace: run+stop Gerd Hoffmann
                   ` (24 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

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

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 4bc1e0e..84d714a 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 "trace.h"
 
 //#define DEBUG_XHCI
 //#define DEBUG_DATA
@@ -2301,7 +2302,7 @@ static void xhci_reset(DeviceState *dev)
     XHCIState *xhci = DO_UPCAST(XHCIState, pci_dev.qdev, dev);
     int i;
 
-    DPRINTF("xhci: full reset\n");
+    trace_usb_xhci_reset();
     if (!(xhci->usbsts & USBSTS_HCH)) {
         fprintf(stderr, "xhci: reset while running!\n");
     }
@@ -2342,77 +2343,98 @@ static void xhci_reset(DeviceState *dev)
 
 static uint32_t xhci_cap_read(XHCIState *xhci, uint32_t reg)
 {
-    DPRINTF("xhci_cap_read(0x%x)\n", reg);
+    uint32_t ret;
 
     switch (reg) {
     case 0x00: /* HCIVERSION, CAPLENGTH */
-        return 0x01000000 | LEN_CAP;
+        ret = 0x01000000 | LEN_CAP;
+        break;
     case 0x04: /* HCSPARAMS 1 */
-        return (MAXPORTS<<24) | (MAXINTRS<<8) | MAXSLOTS;
+        ret = (MAXPORTS<<24) | (MAXINTRS<<8) | MAXSLOTS;
+        break;
     case 0x08: /* HCSPARAMS 2 */
-        return 0x0000000f;
+        ret = 0x0000000f;
+        break;
     case 0x0c: /* HCSPARAMS 3 */
-        return 0x00000000;
+        ret = 0x00000000;
+        break;
     case 0x10: /* HCCPARAMS */
-#if TARGET_PHYS_ADDR_BITS > 32
-        return 0x00081001;
-#else
-        return 0x00081000;
-#endif
+        if (sizeof(dma_addr_t) == 4) {
+            ret = 0x00081000;
+        } else {
+            ret = 0x00081001;
+        }
+        break;
     case 0x14: /* DBOFF */
-        return OFF_DOORBELL;
+        ret = OFF_DOORBELL;
+        break;
     case 0x18: /* RTSOFF */
-        return OFF_RUNTIME;
+        ret = OFF_RUNTIME;
+        break;
 
     /* extended capabilities */
     case 0x20: /* Supported Protocol:00 */
-#if USB3_PORTS > 0
-        return 0x02000402; /* USB 2.0 */
-#else
-        return 0x02000002; /* USB 2.0 */
-#endif
+        ret = 0x02000402; /* USB 2.0 */
+        break;
     case 0x24: /* Supported Protocol:04 */
-        return 0x20425455; /* "USB " */
+        ret = 0x20425455; /* "USB " */
+        break;
     case 0x28: /* Supported Protocol:08 */
-        return 0x00000001 | (USB2_PORTS<<8);
+        ret = 0x00000001 | (USB2_PORTS<<8);
+        break;
     case 0x2c: /* Supported Protocol:0c */
-        return 0x00000000; /* reserved */
-#if USB3_PORTS > 0
+        ret = 0x00000000; /* reserved */
+        break;
     case 0x30: /* Supported Protocol:00 */
-        return 0x03000002; /* USB 3.0 */
+        ret = 0x03000002; /* USB 3.0 */
+        break;
     case 0x34: /* Supported Protocol:04 */
-        return 0x20425455; /* "USB " */
+        ret = 0x20425455; /* "USB " */
+        break;
     case 0x38: /* Supported Protocol:08 */
-        return 0x00000000 | (USB2_PORTS+1) | (USB3_PORTS<<8);
+        ret = 0x00000000 | (USB2_PORTS+1) | (USB3_PORTS<<8);
+        break;
     case 0x3c: /* Supported Protocol:0c */
-        return 0x00000000; /* reserved */
-#endif
+        ret = 0x00000000; /* reserved */
+        break;
     default:
         fprintf(stderr, "xhci_cap_read: reg %d unimplemented\n", reg);
+        ret = 0;
     }
-    return 0;
+
+    trace_usb_xhci_cap_read(reg, ret);
+    return ret;
 }
 
 static uint32_t xhci_port_read(XHCIState *xhci, uint32_t reg)
 {
     uint32_t port = reg >> 4;
+    uint32_t ret;
+
     if (port >= MAXPORTS) {
         fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port);
-        return 0;
+        ret = 0;
+        goto out;
     }
 
     switch (reg & 0xf) {
     case 0x00: /* PORTSC */
-        return xhci->ports[port].portsc;
+        ret = xhci->ports[port].portsc;
+        break;
     case 0x04: /* PORTPMSC */
     case 0x08: /* PORTLI */
-        return 0;
+        ret = 0;
+        break;
     case 0x0c: /* reserved */
     default:
         fprintf(stderr, "xhci_port_read (port %d): reg 0x%x unimplemented\n",
                 port, reg);
-        return 0;
+        ret = 0;
     }
+
+out:
+    trace_usb_xhci_port_read(port, reg & 0x0f, ret);
+    return ret;
 }
 
 static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
@@ -2420,6 +2442,8 @@ static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
     uint32_t port = reg >> 4;
     uint32_t portsc;
 
+    trace_usb_xhci_port_write(port, reg & 0x0f, val);
+
     if (port >= MAXPORTS) {
         fprintf(stderr, "xhci_port_read: port %d out of bounds\n", port);
         return;
@@ -2457,7 +2481,7 @@ static void xhci_port_write(XHCIState *xhci, uint32_t reg, uint32_t val)
 
 static uint32_t xhci_oper_read(XHCIState *xhci, uint32_t reg)
 {
-    DPRINTF("xhci_oper_read(0x%x)\n", reg);
+    uint32_t ret;
 
     if (reg >= 0x400) {
         return xhci_port_read(xhci, reg - 0x400);
@@ -2465,38 +2489,50 @@ static uint32_t xhci_oper_read(XHCIState *xhci, uint32_t reg)
 
     switch (reg) {
     case 0x00: /* USBCMD */
-        return xhci->usbcmd;
+        ret = xhci->usbcmd;
+        break;
     case 0x04: /* USBSTS */
-        return xhci->usbsts;
+        ret = xhci->usbsts;
+        break;
     case 0x08: /* PAGESIZE */
-        return 1; /* 4KiB */
+        ret = 1; /* 4KiB */
+        break;
     case 0x14: /* DNCTRL */
-        return xhci->dnctrl;
+        ret = xhci->dnctrl;
+        break;
     case 0x18: /* CRCR low */
-        return xhci->crcr_low & ~0xe;
+        ret = xhci->crcr_low & ~0xe;
+        break;
     case 0x1c: /* CRCR high */
-        return xhci->crcr_high;
+        ret = xhci->crcr_high;
+        break;
     case 0x30: /* DCBAAP low */
-        return xhci->dcbaap_low;
+        ret = xhci->dcbaap_low;
+        break;
     case 0x34: /* DCBAAP high */
-        return xhci->dcbaap_high;
+        ret = xhci->dcbaap_high;
+        break;
     case 0x38: /* CONFIG */
-        return xhci->config;
+        ret = xhci->config;
+        break;
     default:
         fprintf(stderr, "xhci_oper_read: reg 0x%x unimplemented\n", reg);
+        ret = 0;
     }
-    return 0;
+
+    trace_usb_xhci_oper_read(reg, ret);
+    return ret;
 }
 
 static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val)
 {
-    DPRINTF("xhci_oper_write(0x%x, 0x%08x)\n", reg, val);
-
     if (reg >= 0x400) {
         xhci_port_write(xhci, reg - 0x400, val);
         return;
     }
 
+    trace_usb_xhci_oper_write(reg, val);
+
     switch (reg) {
     case 0x00: /* USBCMD */
         if ((val & USBCMD_RS) && !(xhci->usbcmd & USBCMD_RS)) {
@@ -2552,35 +2588,46 @@ static void xhci_oper_write(XHCIState *xhci, uint32_t reg, uint32_t val)
 
 static uint32_t xhci_runtime_read(XHCIState *xhci, uint32_t reg)
 {
-    DPRINTF("xhci_runtime_read(0x%x)\n", reg);
+    uint32_t ret;
 
     switch (reg) {
     case 0x00: /* MFINDEX */
         fprintf(stderr, "xhci_runtime_read: MFINDEX not yet implemented\n");
-        return xhci->mfindex;
+        ret = xhci->mfindex;
+        break;
     case 0x20: /* IMAN */
-        return xhci->iman;
+        ret = xhci->iman;
+        break;
     case 0x24: /* IMOD */
-        return xhci->imod;
+        ret = xhci->imod;
+        break;
     case 0x28: /* ERSTSZ */
-        return xhci->erstsz;
+        ret = xhci->erstsz;
+        break;
     case 0x30: /* ERSTBA low */
-        return xhci->erstba_low;
+        ret = xhci->erstba_low;
+        break;
     case 0x34: /* ERSTBA high */
-        return xhci->erstba_high;
+        ret = xhci->erstba_high;
+        break;
     case 0x38: /* ERDP low */
-        return xhci->erdp_low;
+        ret = xhci->erdp_low;
+        break;
     case 0x3c: /* ERDP high */
-        return xhci->erdp_high;
+        ret = xhci->erdp_high;
+        break;
     default:
         fprintf(stderr, "xhci_runtime_read: reg 0x%x unimplemented\n", reg);
+        ret = 0;
     }
-    return 0;
+
+    trace_usb_xhci_runtime_read(reg, ret);
+    return ret;
 }
 
 static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val)
 {
-    DPRINTF("xhci_runtime_write(0x%x, 0x%08x)\n", reg, val);
+    trace_usb_xhci_runtime_read(reg, val);
 
     switch (reg) {
     case 0x20: /* IMAN */
@@ -2623,14 +2670,14 @@ static void xhci_runtime_write(XHCIState *xhci, uint32_t reg, uint32_t val)
 
 static uint32_t xhci_doorbell_read(XHCIState *xhci, uint32_t reg)
 {
-    DPRINTF("xhci_doorbell_read(0x%x)\n", reg);
     /* 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)
 {
-    DPRINTF("xhci_doorbell_write(0x%x, 0x%08x)\n", reg, val);
+    trace_usb_xhci_doorbell_write(reg, val);
 
     if (!xhci_running(xhci)) {
         fprintf(stderr, "xhci: wrote doorbell while xHC stopped or paused\n");
diff --git a/trace-events b/trace-events
index dd057bc..b70b161 100644
--- a/trace-events
+++ b/trace-events
@@ -289,6 +289,18 @@ usb_uhci_td_nextqh(uint32_t qh, uint32_t td) "qh 0x%x, td 0x%x"
 usb_uhci_td_async(uint32_t qh, uint32_t td) "qh 0x%x, td 0x%x"
 usb_uhci_td_complete(uint32_t qh, uint32_t td) "qh 0x%x, td 0x%x"
 
+# hw/usb/hcd-xhci.c
+usb_xhci_reset(void) "=== RESET ==="
+usb_xhci_cap_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
+usb_xhci_oper_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
+usb_xhci_port_read(uint32_t port, uint32_t off, uint32_t val) "port %d, off 0x%04x, ret 0x%08x"
+usb_xhci_runtime_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
+usb_xhci_doorbell_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
+usb_xhci_oper_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
+usb_xhci_port_write(uint32_t port, uint32_t off, uint32_t val) "port %d, off 0x%04x, val 0x%08x"
+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"
+
 # hw/usb/desc.c
 usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
 usb_desc_device_qualifier(int addr, int len, int ret) "dev %d query device qualifier, len %d, ret %d"
-- 
1.7.1

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

* [Qemu-devel] [PATCH 14/37] xhci: trace: run+stop
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (12 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 13/37] xhci: trace: mmio reads+writes Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 15/37] xhci: trace: irq + events Gerd Hoffmann
                   ` (23 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

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

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 84d714a..43875aa 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -813,14 +813,13 @@ static void xhci_er_reset(XHCIState *xhci)
 
 static void xhci_run(XHCIState *xhci)
 {
-    DPRINTF("xhci_run()\n");
-
+    trace_usb_xhci_run();
     xhci->usbsts &= ~USBSTS_HCH;
 }
 
 static void xhci_stop(XHCIState *xhci)
 {
-    DPRINTF("xhci_stop()\n");
+    trace_usb_xhci_stop();
     xhci->usbsts |= USBSTS_HCH;
     xhci->crcr_low &= ~CRCR_CRR;
 }
diff --git a/trace-events b/trace-events
index b70b161..1b2db05 100644
--- a/trace-events
+++ b/trace-events
@@ -291,6 +291,8 @@ usb_uhci_td_complete(uint32_t qh, uint32_t td) "qh 0x%x, td 0x%x"
 
 # hw/usb/hcd-xhci.c
 usb_xhci_reset(void) "=== RESET ==="
+usb_xhci_run(void) ""
+usb_xhci_stop(void) ""
 usb_xhci_cap_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
 usb_xhci_oper_read(uint32_t off, uint32_t val) "off 0x%04x, ret 0x%08x"
 usb_xhci_port_read(uint32_t port, uint32_t off, uint32_t val) "port %d, off 0x%04x, ret 0x%08x"
-- 
1.7.1

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

* [Qemu-devel] [PATCH 15/37] xhci: trace: irq + events
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (13 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 14/37] xhci: trace: run+stop Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 16/37] xhci: trace: ring fetch Gerd Hoffmann
                   ` (22 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

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

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 43875aa..6890888 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -422,7 +422,6 @@ typedef struct XHCIEvRingSeg {
     uint32_t rsvd;
 } XHCIEvRingSeg;
 
-#ifdef DEBUG_XHCI
 static const char *TRBType_names[] = {
     [TRB_RESERVED]                     = "TRB_RESERVED",
     [TR_NORMAL]                        = "TR_NORMAL",
@@ -474,7 +473,6 @@ static const char *trb_name(XHCITRB *trb)
     return lookup_name(TRB_TYPE(*trb), TRBType_names,
                        ARRAY_SIZE(TRBType_names));
 }
-#endif
 
 static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
                          unsigned int epid);
@@ -506,14 +504,13 @@ static void xhci_irq_update(XHCIState *xhci)
         level = 1;
     }
 
-    DPRINTF("xhci_irq_update(): %d\n", level);
-
     if (xhci->msi && msi_enabled(&xhci->pci_dev)) {
         if (level) {
-            DPRINTF("xhci_irq_update(): MSI signal\n");
+            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);
     }
 }
@@ -543,9 +540,8 @@ static void xhci_write_event(XHCIState *xhci, XHCIEvent *event)
     }
     ev_trb.control = cpu_to_le32(ev_trb.control);
 
-    DPRINTF("xhci_write_event(): [%d] %016"PRIx64" %08x %08x %s\n",
-            xhci->er_ep_idx, ev_trb.parameter, ev_trb.status, ev_trb.control,
-            trb_name(&ev_trb));
+    trace_usb_xhci_queue_event(xhci->er_ep_idx, trb_name(&ev_trb),
+                               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 1b2db05..974e5a3 100644
--- a/trace-events
+++ b/trace-events
@@ -302,6 +302,9 @@ usb_xhci_oper_write(uint32_t off, uint32_t val) "off 0x%04x, val 0x%08x"
 usb_xhci_port_write(uint32_t port, uint32_t off, uint32_t val) "port %d, off 0x%04x, val 0x%08x"
 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"
 
 # hw/usb/desc.c
 usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
-- 
1.7.1

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

* [Qemu-devel] [PATCH 16/37] xhci: trace: ring fetch
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (14 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 15/37] xhci: trace: irq + events Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 17/37] xhci: trace: endpoints Gerd Hoffmann
                   ` (21 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

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

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 6890888..08fdf94 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -701,10 +701,8 @@ static TRBType xhci_ring_fetch(XHCIState *xhci, XHCIRing *ring, XHCITRB *trb,
         le32_to_cpus(&trb->status);
         le32_to_cpus(&trb->control);
 
-        DPRINTF("xhci: TRB fetched [" DMA_ADDR_FMT "]: "
-                "%016" PRIx64 " %08x %08x %s\n",
-                ring->dequeue, trb->parameter, trb->status, trb->control,
-                trb_name(trb));
+        trace_usb_xhci_fetch_trb(ring->dequeue, trb_name(trb),
+                                 trb->parameter, trb->status, trb->control);
 
         if ((trb->control & TRB_C) != ring->ccs) {
             return 0;
@@ -743,10 +741,6 @@ static int xhci_ring_chain_length(XHCIState *xhci, const XHCIRing *ring)
         le32_to_cpus(&trb.status);
         le32_to_cpus(&trb.control);
 
-        DPRINTF("xhci: TRB peeked [" DMA_ADDR_FMT "]: "
-                "%016" PRIx64 " %08x %08x\n",
-                dequeue, trb.parameter, trb.status, trb.control);
-
         if ((trb.control & TRB_C) != ccs) {
             return -length;
         }
diff --git a/trace-events b/trace-events
index 974e5a3..09ed109 100644
--- a/trace-events
+++ b/trace-events
@@ -305,6 +305,7 @@ 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_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"
 
 # hw/usb/desc.c
 usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
-- 
1.7.1

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

* [Qemu-devel] [PATCH 17/37] xhci: trace: endpoints
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (15 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 16/37] xhci: trace: ring fetch Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 18/37] xhci: trace: transfers Gerd Hoffmann
                   ` (20 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

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

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 08fdf94..c50e407 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -842,11 +842,10 @@ static TRBCCode xhci_enable_ep(XHCIState *xhci, unsigned int slotid,
     dma_addr_t dequeue;
     int i;
 
+    trace_usb_xhci_ep_enable(slotid, epid);
     assert(slotid >= 1 && slotid <= MAXSLOTS);
     assert(epid >= 1 && epid <= 31);
 
-    DPRINTF("xhci_enable_ep(%d, %d)\n", slotid, epid);
-
     slot = &xhci->slots[slotid-1];
     if (slot->eps[epid-1]) {
         fprintf(stderr, "xhci: slot %d ep %d already enabled!\n", slotid, epid);
@@ -961,11 +960,10 @@ static TRBCCode xhci_disable_ep(XHCIState *xhci, unsigned int slotid,
     XHCISlot *slot;
     XHCIEPContext *epctx;
 
+    trace_usb_xhci_ep_disable(slotid, epid);
     assert(slotid >= 1 && slotid <= MAXSLOTS);
     assert(epid >= 1 && epid <= 31);
 
-    DPRINTF("xhci_disable_ep(%d, %d)\n", slotid, epid);
-
     slot = &xhci->slots[slotid-1];
 
     if (!slot->eps[epid-1]) {
@@ -991,8 +989,7 @@ static TRBCCode xhci_stop_ep(XHCIState *xhci, unsigned int slotid,
     XHCISlot *slot;
     XHCIEPContext *epctx;
 
-    DPRINTF("xhci_stop_ep(%d, %d)\n", slotid, epid);
-
+    trace_usb_xhci_ep_stop(slotid, epid);
     assert(slotid >= 1 && slotid <= MAXSLOTS);
 
     if (epid < 1 || epid > 31) {
@@ -1026,10 +1023,9 @@ static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid,
     XHCIEPContext *epctx;
     USBDevice *dev;
 
+    trace_usb_xhci_ep_reset(slotid, epid);
     assert(slotid >= 1 && slotid <= MAXSLOTS);
 
-    DPRINTF("xhci_reset_ep(%d, %d)\n", slotid, epid);
-
     if (epid < 1 || epid > 31) {
         fprintf(stderr, "xhci: bad ep %d\n", epid);
         return CC_TRB_ERROR;
@@ -1654,9 +1650,9 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
     int length;
     int i;
 
+    trace_usb_xhci_ep_kick(slotid, epid);
     assert(slotid >= 1 && slotid <= MAXSLOTS);
     assert(epid >= 1 && epid <= 31);
-    DPRINTF("xhci_kick_ep(%d, %d)\n", slotid, epid);
 
     if (!xhci->slots[slotid-1].enabled) {
         fprintf(stderr, "xhci: xhci_kick_ep for disabled slot %d\n", slotid);
@@ -1698,21 +1694,14 @@ 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) {
-            DPRINTF("xhci: ep is busy (#%d,%d,%d,%d)\n",
-                    epctx->next_xfer, xfer->running_async,
-                    xfer->running_retry, xfer->backgrounded);
             break;
-        } else {
-            DPRINTF("xhci: ep: using #%d\n", epctx->next_xfer);
         }
         length = xhci_ring_chain_length(xhci, &epctx->ring);
         if (length < 0) {
-            DPRINTF("xhci: incomplete TD (%d TRBs)\n", -length);
             break;
         } else if (length == 0) {
             break;
         }
-        DPRINTF("xhci: fetching %d-TRB TD\n", length);
         if (xfer->trbs && xfer->trb_alloced < length) {
             xfer->trb_count = 0;
             xfer->trb_alloced = 0;
@@ -1747,7 +1736,6 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
         }
 
         if (epctx->state == EP_HALTED) {
-            DPRINTF("xhci: ep halted, stopping schedule\n");
             break;
         }
         if (xfer->running_retry) {
diff --git a/trace-events b/trace-events
index 09ed109..74fdf6a 100644
--- a/trace-events
+++ b/trace-events
@@ -306,6 +306,11 @@ 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_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_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_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"
 
 # hw/usb/desc.c
 usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
-- 
1.7.1

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

* [Qemu-devel] [PATCH 18/37] xhci: trace: transfers
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (16 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 17/37] xhci: trace: endpoints Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 19/37] xhci: trace: slots Gerd Hoffmann
                   ` (19 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

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

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index c50e407..7e823da 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -1402,12 +1402,14 @@ static int xhci_setup_packet(XHCITransfer *xfer, USBDevice *dev)
 static int xhci_complete_packet(XHCITransfer *xfer, int ret)
 {
     if (ret == USB_RET_ASYNC) {
+        trace_usb_xhci_xfer_async(xfer);
         xfer->running_async = 1;
         xfer->running_retry = 0;
         xfer->complete = 0;
         xfer->cancelled = 0;
         return 0;
     } else if (ret == USB_RET_NAK) {
+        trace_usb_xhci_xfer_nak(xfer);
         xfer->running_async = 0;
         xfer->running_retry = 1;
         xfer->complete = 0;
@@ -1422,10 +1424,12 @@ static int xhci_complete_packet(XHCITransfer *xfer, int ret)
     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);
         return 0;
     }
 
     /* error */
+    trace_usb_xhci_xfer_error(xfer, ret);
     switch (ret) {
     case USB_RET_NODEV:
         xfer->status = CC_USB_TRANSACTION_ERROR;
@@ -1461,11 +1465,12 @@ static int xhci_fire_ctl_transfer(XHCIState *xhci, XHCITransfer *xfer)
     USBDevice *dev;
     int ret;
 
-    DPRINTF("xhci_fire_ctl_transfer(slot=%d)\n", xfer->slotid);
-
     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);
+
     /* at most one Event Data TRB allowed after STATUS */
     if (TRB_TYPE(*trb_status) == TR_EVDATA && xfer->trb_count > 2) {
         trb_status--;
@@ -1606,15 +1611,14 @@ static int xhci_fire_transfer(XHCIState *xhci, XHCITransfer *xfer, XHCIEPContext
     unsigned int length = 0;
     XHCITRB *trb;
 
-    DPRINTF("xhci_fire_transfer(slotid=%d,epid=%d)\n", xfer->slotid, xfer->epid);
-
     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;
         }
     }
-    DPRINTF("xhci: total TD length=%d\n", length);
+
+    trace_usb_xhci_xfer_start(xfer, xfer->slotid, xfer->epid, length);
 
     if (!epctx->has_bg) {
         xfer->data_length = length;
@@ -1670,15 +1674,13 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
         XHCITransfer *xfer = epctx->retry;
         int result;
 
-        DPRINTF("xhci: retry nack'ed transfer ...\n");
+        trace_usb_xhci_xfer_retry(xfer);
         assert(xfer->running_retry);
         xhci_setup_packet(xfer, xfer->packet.ep->dev);
         result = usb_handle_packet(xfer->packet.ep->dev, &xfer->packet);
         if (result == USB_RET_NAK) {
-            DPRINTF("xhci: ... xfer still nacked\n");
             return;
         }
-        DPRINTF("xhci: ... result %d\n", result);
         xhci_complete_packet(xfer, result);
         assert(!xfer->running_retry);
         epctx->retry = NULL;
diff --git a/trace-events b/trace-events
index 74fdf6a..74f661c 100644
--- a/trace-events
+++ b/trace-events
@@ -311,6 +311,12 @@ 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_async(void *xfer) "%p"
+usb_xhci_xfer_nak(void *xfer) "%p"
+usb_xhci_xfer_retry(void *xfer) "%p"
+usb_xhci_xfer_success(void *xfer, uint32_t bytes) "%p: len %d"
+usb_xhci_xfer_error(void *xfer, uint32_t ret) "%p: ret %d"
 
 # hw/usb/desc.c
 usb_desc_device(int addr, int len, int ret) "dev %d query device, len %d, ret %d"
-- 
1.7.1

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

* [Qemu-devel] [PATCH 19/37] xhci: trace: slots
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (17 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 18/37] xhci: trace: transfers Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 20/37] ehci: add EHCIPacket Gerd Hoffmann
                   ` (18 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

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

diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
index 7e823da..6c2ff02 100644
--- a/hw/usb/hcd-xhci.c
+++ b/hw/usb/hcd-xhci.c
@@ -1750,8 +1750,8 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid, unsigned int epid
 
 static TRBCCode xhci_enable_slot(XHCIState *xhci, unsigned int slotid)
 {
+    trace_usb_xhci_slot_enable(slotid);
     assert(slotid >= 1 && slotid <= MAXSLOTS);
-    DPRINTF("xhci_enable_slot(%d)\n", slotid);
     xhci->slots[slotid-1].enabled = 1;
     xhci->slots[slotid-1].port = 0;
     memset(xhci->slots[slotid-1].eps, 0, sizeof(XHCIEPContext*)*31);
@@ -1763,8 +1763,8 @@ static TRBCCode xhci_disable_slot(XHCIState *xhci, unsigned int slotid)
 {
     int i;
 
+    trace_usb_xhci_slot_disable(slotid);
     assert(slotid >= 1 && slotid <= MAXSLOTS);
-    DPRINTF("xhci_disable_slot(%d)\n", slotid);
 
     for (i = 1; i <= 31; i++) {
         if (xhci->slots[slotid-1].eps[i-1]) {
@@ -1790,8 +1790,8 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
     int i;
     TRBCCode res;
 
+    trace_usb_xhci_slot_address(slotid);
     assert(slotid >= 1 && slotid <= MAXSLOTS);
-    DPRINTF("xhci_address_slot(%d)\n", slotid);
 
     dcbaap = xhci_addr64(xhci->dcbaap_low, xhci->dcbaap_high);
     pci_dma_read(&xhci->pci_dev, dcbaap + 8*slotid, &poctx, sizeof(poctx));
@@ -1877,8 +1877,8 @@ static TRBCCode xhci_configure_slot(XHCIState *xhci, unsigned int slotid,
     int i;
     TRBCCode res;
 
+    trace_usb_xhci_slot_configure(slotid);
     assert(slotid >= 1 && slotid <= MAXSLOTS);
-    DPRINTF("xhci_configure_slot(%d)\n", slotid);
 
     ictx = xhci_mask64(pictx);
     octx = xhci->slots[slotid-1].ctx;
@@ -1965,8 +1965,8 @@ static TRBCCode xhci_evaluate_slot(XHCIState *xhci, unsigned int slotid,
     uint32_t islot_ctx[4];
     uint32_t slot_ctx[4];
 
+    trace_usb_xhci_slot_evaluate(slotid);
     assert(slotid >= 1 && slotid <= MAXSLOTS);
-    DPRINTF("xhci_evaluate_slot(%d)\n", slotid);
 
     ictx = xhci_mask64(pictx);
     octx = xhci->slots[slotid-1].ctx;
@@ -2028,8 +2028,8 @@ static TRBCCode xhci_reset_slot(XHCIState *xhci, unsigned int slotid)
     dma_addr_t octx;
     int i;
 
+    trace_usb_xhci_slot_reset(slotid);
     assert(slotid >= 1 && slotid <= MAXSLOTS);
-    DPRINTF("xhci_reset_slot(%d)\n", slotid);
 
     octx = xhci->slots[slotid-1].ctx;
 
diff --git a/trace-events b/trace-events
index 74f661c..293eddb 100644
--- a/trace-events
+++ b/trace-events
@@ -306,6 +306,12 @@ 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_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"
+usb_xhci_slot_address(uint32_t slotid) "slotid %d"
+usb_xhci_slot_configure(uint32_t slotid) "slotid %d"
+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_kick(uint32_t slotid, uint32_t epid) "slotid %d, epid %d"
-- 
1.7.1

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

* [Qemu-devel] [PATCH 20/37] ehci: add EHCIPacket
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (18 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 19/37] xhci: trace: slots Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 21/37] ehci: make ehci_execute work on EHCIPacket instead of EHCIQueue Gerd Hoffmann
                   ` (17 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add a separate EHCIPacket struct and move fields over from EHCIQueue.
Preparing for supporting multiple packets per queue being in flight at
the same time.  No functional changes yet.

Fix some codestyle issues along the way.

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

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index e759c99..03ae09f 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -334,6 +334,7 @@ typedef struct EHCIfstn {
     uint32_t backptr;                 // Standard next link pointer
 } EHCIfstn;
 
+typedef struct EHCIPacket EHCIPacket;
 typedef struct EHCIQueue EHCIQueue;
 typedef struct EHCIState EHCIState;
 
@@ -343,6 +344,21 @@ enum async_state {
     EHCI_ASYNC_FINISHED,
 };
 
+struct EHCIPacket {
+    EHCIQueue *queue;
+    QTAILQ_ENTRY(EHCIPacket) next;
+
+    EHCIqtd qtd;           /* copy of current QTD (being worked on) */
+    uint32_t qtdaddr;      /* address QTD read from                 */
+
+    USBPacket packet;
+    QEMUSGList sgl;
+    int pid;
+    uint32_t tbytes;
+    enum async_state async;
+    int usb_status;
+};
+
 struct EHCIQueue {
     EHCIState *ehci;
     QTAILQ_ENTRY(EHCIQueue) next;
@@ -352,17 +368,10 @@ struct EHCIQueue {
     /* cached data from guest - needs to be flushed
      * when guest removes an entry (doorbell, handshake sequence)
      */
-    EHCIqh qh;             // copy of current QH (being worked on)
-    uint32_t qhaddr;       // address QH read from
-    EHCIqtd qtd;           // copy of current QTD (being worked on)
-    uint32_t qtdaddr;      // address QTD read from
-
-    USBPacket packet;
-    QEMUSGList sgl;
-    int pid;
-    uint32_t tbytes;
-    enum async_state async;
-    int usb_status;
+    EHCIqh qh;             /* copy of current QH (being worked on) */
+    uint32_t qhaddr;       /* address QH read from                 */
+    uint32_t qtdaddr;      /* address QTD read from                */
+    QTAILQ_HEAD(, EHCIPacket) packets;
 };
 
 typedef QTAILQ_HEAD(EHCIQueueHead, EHCIQueue) EHCIQueueHead;
@@ -655,6 +664,35 @@ static void ehci_trace_sitd(EHCIState *s, target_phys_addr_t addr,
                         (bool)(sitd->results & SITD_RESULTS_ACTIVE));
 }
 
+/* packet management */
+
+static EHCIPacket *ehci_alloc_packet(EHCIQueue *q)
+{
+    EHCIPacket *p;
+
+#if 1
+    /* temporary, we don't handle multiple packets per queue (yet) */
+    assert(QTAILQ_EMPTY(&q->packets));
+#endif
+    p = g_new0(EHCIPacket, 1);
+    p->queue = q;
+    usb_packet_init(&p->packet);
+    QTAILQ_INSERT_TAIL(&q->packets, p, next);
+    trace_usb_ehci_packet_action(p->queue, p, "alloc");
+    return p;
+}
+
+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);
+    }
+    QTAILQ_REMOVE(&p->queue->packets, p, next);
+    usb_packet_cleanup(&p->packet);
+    g_free(p);
+}
+
 /* queue management */
 
 static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async)
@@ -664,7 +702,7 @@ static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async)
 
     q = g_malloc0(sizeof(*q));
     q->ehci = ehci;
-    usb_packet_init(&q->packet);
+    QTAILQ_INIT(&q->packets);
     QTAILQ_INSERT_HEAD(head, q, next);
     trace_usb_ehci_queue_action(q, "alloc");
     return q;
@@ -673,9 +711,11 @@ static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async)
 static void ehci_free_queue(EHCIQueue *q, int async)
 {
     EHCIQueueHead *head = async ? &q->ehci->aqueues : &q->ehci->pqueues;
+    EHCIPacket *p;
+
     trace_usb_ehci_queue_action(q, "free");
-    if (q->async == EHCI_ASYNC_INFLIGHT) {
-        usb_cancel_packet(&q->packet);
+    while ((p = QTAILQ_FIRST(&q->packets)) != NULL) {
+        ehci_free_packet(p);
     }
     QTAILQ_REMOVE(head, q, next);
     g_free(q);
@@ -718,10 +758,11 @@ static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
 {
     EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
     EHCIQueue *q, *tmp;
+    int addr;
 
     QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
-        if (!usb_packet_is_inflight(&q->packet) ||
-            q->packet.ep->dev != dev) {
+        addr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);
+        if (addr != dev->addr) {
             continue;
         }
         ehci_free_queue(q, async);
@@ -1169,21 +1210,25 @@ static inline int put_dwords(EHCIState *ehci, uint32_t addr,
 
 static int ehci_qh_do_overlay(EHCIQueue *q)
 {
+    EHCIPacket *p = QTAILQ_FIRST(&q->packets);
     int i;
     int dtoggle;
     int ping;
     int eps;
     int reload;
 
+    assert(p != NULL);
+    assert(p->qtdaddr == q->qtdaddr);
+
     // remember values in fields to preserve in qh after overlay
 
     dtoggle = q->qh.token & QTD_TOKEN_DTOGGLE;
     ping    = q->qh.token & QTD_TOKEN_PING;
 
-    q->qh.current_qtd = q->qtdaddr;
-    q->qh.next_qtd    = q->qtd.next;
-    q->qh.altnext_qtd = q->qtd.altnext;
-    q->qh.token       = q->qtd.token;
+    q->qh.current_qtd = p->qtdaddr;
+    q->qh.next_qtd    = p->qtd.next;
+    q->qh.altnext_qtd = p->qtd.altnext;
+    q->qh.token       = p->qtd.token;
 
 
     eps = get_field(q->qh.epchar, QH_EPCHAR_EPS);
@@ -1196,7 +1241,7 @@ static int ehci_qh_do_overlay(EHCIQueue *q)
     set_field(&q->qh.altnext_qtd, reload, QH_ALTNEXT_NAKCNT);
 
     for (i = 0; i < 5; i++) {
-        q->qh.bufptr[i] = q->qtd.bufptr[i];
+        q->qh.bufptr[i] = p->qtd.bufptr[i];
     }
 
     if (!(q->qh.epchar & QH_EPCHAR_DTC)) {
@@ -1214,15 +1259,15 @@ static int ehci_qh_do_overlay(EHCIQueue *q)
     return 0;
 }
 
-static int ehci_init_transfer(EHCIQueue *q)
+static int ehci_init_transfer(EHCIPacket *p)
 {
     uint32_t cpage, offset, bytes, plen;
     dma_addr_t page;
 
-    cpage  = get_field(q->qh.token, QTD_TOKEN_CPAGE);
-    bytes  = get_field(q->qh.token, QTD_TOKEN_TBYTES);
-    offset = q->qh.bufptr[0] & ~QTD_BUFPTR_MASK;
-    pci_dma_sglist_init(&q->sgl, &q->ehci->dev, 5);
+    cpage  = get_field(p->qtd.token, QTD_TOKEN_CPAGE);
+    bytes  = get_field(p->qtd.token, QTD_TOKEN_TBYTES);
+    offset = p->qtd.bufptr[0] & ~QTD_BUFPTR_MASK;
+    pci_dma_sglist_init(&p->sgl, &p->queue->ehci->dev, 5);
 
     while (bytes > 0) {
         if (cpage > 4) {
@@ -1230,7 +1275,7 @@ static int ehci_init_transfer(EHCIQueue *q)
             return USB_RET_PROCERR;
         }
 
-        page  = q->qh.bufptr[cpage] & QTD_BUFPTR_MASK;
+        page  = p->qtd.bufptr[cpage] & QTD_BUFPTR_MASK;
         page += offset;
         plen  = bytes;
         if (plen > 4096 - offset) {
@@ -1239,7 +1284,7 @@ static int ehci_init_transfer(EHCIQueue *q)
             cpage++;
         }
 
-        qemu_sglist_add(&q->sgl, page, plen);
+        qemu_sglist_add(&p->sgl, page, plen);
         bytes -= plen;
     }
     return 0;
@@ -1249,8 +1294,6 @@ static void ehci_finish_transfer(EHCIQueue *q, int status)
 {
     uint32_t cpage, offset;
 
-    qemu_sglist_destroy(&q->sgl);
-
     if (status > 0) {
         /* update cpage & offset */
         cpage  = get_field(q->qh.token, QTD_TOKEN_CPAGE);
@@ -1268,7 +1311,7 @@ static void ehci_finish_transfer(EHCIQueue *q, int status)
 
 static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
 {
-    EHCIQueue *q;
+    EHCIPacket *p;
     EHCIState *s = port->opaque;
     uint32_t portsc = s->portsc[port->index];
 
@@ -1278,23 +1321,27 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
         return;
     }
 
-    q = container_of(packet, EHCIQueue, packet);
-    trace_usb_ehci_queue_action(q, "wakeup");
-    assert(q->async == EHCI_ASYNC_INFLIGHT);
-    q->async = EHCI_ASYNC_FINISHED;
-    q->usb_status = packet->result;
+    p = container_of(packet, EHCIPacket, packet);
+    trace_usb_ehci_packet_action(p->queue, p, "wakeup");
+    assert(p->async == EHCI_ASYNC_INFLIGHT);
+    p->async = EHCI_ASYNC_FINISHED;
+    p->usb_status = packet->result;
 }
 
 static void ehci_execute_complete(EHCIQueue *q)
 {
-    assert(q->async != EHCI_ASYNC_INFLIGHT);
-    q->async = EHCI_ASYNC_NONE;
+    EHCIPacket *p = QTAILQ_FIRST(&q->packets);
+
+    assert(p != NULL);
+    assert(p->qtdaddr == q->qtdaddr);
+    assert(p->async != EHCI_ASYNC_INFLIGHT);
+    p->async = EHCI_ASYNC_NONE;
 
     DPRINTF("execute_complete: qhaddr 0x%x, next %x, qtdaddr 0x%x, status %d\n",
             q->qhaddr, q->qh.next, q->qtdaddr, q->usb_status);
 
-    if (q->usb_status < 0) {
-        switch(q->usb_status) {
+    if (p->usb_status < 0) {
+        switch (p->usb_status) {
         case USB_RET_IOERROR:
         case USB_RET_NODEV:
             q->qh.token |= (QTD_TOKEN_HALT | QTD_TOKEN_XACTERR);
@@ -1314,28 +1361,29 @@ static void ehci_execute_complete(EHCIQueue *q)
             break;
         default:
             /* should not be triggerable */
-            fprintf(stderr, "USB invalid response %d to handle\n", q->usb_status);
+            fprintf(stderr, "USB invalid response %d\n", p->usb_status);
             assert(0);
             break;
         }
-    } else if ((q->usb_status > q->tbytes) && (q->pid == USB_TOKEN_IN)) {
-        q->usb_status = USB_RET_BABBLE;
+    } 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_record_interrupt(q->ehci, USBSTS_ERRINT);
     } else {
         // TODO check 4.12 for splits
 
-        if (q->tbytes && q->pid == USB_TOKEN_IN) {
-            q->tbytes -= q->usb_status;
+        if (p->tbytes && p->pid == USB_TOKEN_IN) {
+            p->tbytes -= p->usb_status;
         } else {
-            q->tbytes = 0;
+            p->tbytes = 0;
         }
 
-        DPRINTF("updating tbytes to %d\n", q->tbytes);
-        set_field(&q->qh.token, q->tbytes, QTD_TOKEN_TBYTES);
+        DPRINTF("updating tbytes to %d\n", p->tbytes);
+        set_field(&q->qh.token, p->tbytes, QTD_TOKEN_TBYTES);
     }
-    ehci_finish_transfer(q, q->usb_status);
-    usb_packet_unmap(&q->packet);
+    ehci_finish_transfer(q, p->usb_status);
+    qemu_sglist_destroy(&p->sgl);
+    usb_packet_unmap(&p->packet);
 
     q->qh.token ^= QTD_TOKEN_DTOGGLE;
     q->qh.token &= ~QTD_TOKEN_ACTIVE;
@@ -1349,32 +1397,44 @@ static void ehci_execute_complete(EHCIQueue *q)
 
 static int ehci_execute(EHCIQueue *q)
 {
+    EHCIPacket *p = QTAILQ_FIRST(&q->packets);
     USBDevice *dev;
     USBEndpoint *ep;
     int ret;
     int endp;
     int devadr;
 
+    assert(p != NULL);
+    assert(p->qtdaddr == q->qtdaddr);
+
     if ( !(q->qh.token & QTD_TOKEN_ACTIVE)) {
         fprintf(stderr, "Attempting to execute inactive QH\n");
         return USB_RET_PROCERR;
     }
 
-    q->tbytes = (q->qh.token & QTD_TOKEN_TBYTES_MASK) >> QTD_TOKEN_TBYTES_SH;
-    if (q->tbytes > BUFF_SIZE) {
+    p->tbytes = (q->qh.token & QTD_TOKEN_TBYTES_MASK) >> QTD_TOKEN_TBYTES_SH;
+    if (p->tbytes > BUFF_SIZE) {
         fprintf(stderr, "Request for more bytes than allowed\n");
         return USB_RET_PROCERR;
     }
 
-    q->pid = (q->qh.token & QTD_TOKEN_PID_MASK) >> QTD_TOKEN_PID_SH;
-    switch(q->pid) {
-        case 0: q->pid = USB_TOKEN_OUT; break;
-        case 1: q->pid = USB_TOKEN_IN; break;
-        case 2: q->pid = USB_TOKEN_SETUP; break;
-        default: fprintf(stderr, "bad token\n"); break;
+    p->pid = (q->qh.token & QTD_TOKEN_PID_MASK) >> QTD_TOKEN_PID_SH;
+    switch (p->pid) {
+    case 0:
+        p->pid = USB_TOKEN_OUT;
+        break;
+    case 1:
+        p->pid = USB_TOKEN_IN;
+        break;
+    case 2:
+        p->pid = USB_TOKEN_SETUP;
+        break;
+    default:
+        fprintf(stderr, "bad token\n");
+        break;
     }
 
-    if (ehci_init_transfer(q) != 0) {
+    if (ehci_init_transfer(p) != 0) {
         return USB_RET_PROCERR;
     }
 
@@ -1383,12 +1443,12 @@ static int ehci_execute(EHCIQueue *q)
 
     /* TODO: associating device with ehci port */
     dev = ehci_find_device(q->ehci, devadr);
-    ep = usb_ep_get(dev, q->pid, endp);
+    ep = usb_ep_get(dev, p->pid, endp);
 
-    usb_packet_setup(&q->packet, q->pid, ep);
-    usb_packet_map(&q->packet, &q->sgl);
+    usb_packet_setup(&p->packet, p->pid, ep);
+    usb_packet_map(&p->packet, &p->sgl);
 
-    ret = usb_handle_packet(dev, &q->packet);
+    ret = usb_handle_packet(dev, &p->packet);
     DPRINTF("submit: qh %x next %x qtd %x pid %x len %zd "
             "(total %d) endp %x ret %d\n",
             q->qhaddr, q->qh.next, q->qtdaddr, q->pid,
@@ -1601,6 +1661,7 @@ out:
 
 static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
 {
+    EHCIPacket *p;
     uint32_t entry;
     EHCIQueue *q;
 
@@ -1609,6 +1670,7 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
     if (NULL == q) {
         q = ehci_alloc_queue(ehci, async);
     }
+    p = QTAILQ_FIRST(&q->packets);
     q->qhaddr = entry;
     q->seen++;
 
@@ -1623,12 +1685,12 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
                (uint32_t *) &q->qh, sizeof(EHCIqh) >> 2);
     ehci_trace_qh(q, NLPTR_GET(q->qhaddr), &q->qh);
 
-    if (q->async == EHCI_ASYNC_INFLIGHT) {
+    if (p && p->async == EHCI_ASYNC_INFLIGHT) {
         /* I/O still in progress -- skip queue */
         ehci_set_state(ehci, async, EST_HORIZONTALQH);
         goto out;
     }
-    if (q->async == EHCI_ASYNC_FINISHED) {
+    if (p && p->async == EHCI_ASYNC_FINISHED) {
         /* I/O finished -- continue processing queue */
         trace_usb_ehci_queue_action(q, "resume");
         ehci_set_state(ehci, async, EST_EXECUTING);
@@ -1767,13 +1829,18 @@ static int ehci_state_advqueue(EHCIQueue *q, int async)
 /* Section 4.10.2 - paragraph 4 */
 static int ehci_state_fetchqtd(EHCIQueue *q, int async)
 {
+    EHCIqtd qtd;
+    EHCIPacket *p;
     int again = 0;
 
-    get_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &q->qtd,
+    get_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &qtd,
                sizeof(EHCIqtd) >> 2);
-    ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), &q->qtd);
+    ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), &qtd);
 
-    if (q->qtd.token & QTD_TOKEN_ACTIVE) {
+    if (qtd.token & QTD_TOKEN_ACTIVE) {
+        p = ehci_alloc_packet(q);
+        p->qtdaddr = q->qtdaddr;
+        p->qtd = qtd;
         ehci_set_state(q->ehci, async, EST_EXECUTE);
         again = 1;
     } else {
@@ -1818,8 +1885,12 @@ static void ehci_flush_qh(EHCIQueue *q)
 
 static int ehci_state_execute(EHCIQueue *q, int async)
 {
+    EHCIPacket *p = QTAILQ_FIRST(&q->packets);
     int again = 0;
 
+    assert(p != NULL);
+    assert(p->qtdaddr == q->qtdaddr);
+
     if (ehci_qh_do_overlay(q) != 0) {
         return -1;
     }
@@ -1841,15 +1912,15 @@ static int ehci_state_execute(EHCIQueue *q, int async)
         ehci_set_usbsts(q->ehci, USBSTS_REC);
     }
 
-    q->usb_status = ehci_execute(q);
-    if (q->usb_status == USB_RET_PROCERR) {
+    p->usb_status = ehci_execute(q);
+    if (p->usb_status == USB_RET_PROCERR) {
         again = -1;
         goto out;
     }
-    if (q->usb_status == USB_RET_ASYNC) {
+    if (p->usb_status == USB_RET_ASYNC) {
         ehci_flush_qh(q);
         trace_usb_ehci_queue_action(q, "suspend");
-        q->async = EHCI_ASYNC_INFLIGHT;
+        p->async = EHCI_ASYNC_INFLIGHT;
         ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
         again = 1;
         goto out;
@@ -1864,13 +1935,17 @@ out:
 
 static int ehci_state_executing(EHCIQueue *q, int async)
 {
+    EHCIPacket *p = QTAILQ_FIRST(&q->packets);
     int again = 0;
 
+    assert(p != NULL);
+    assert(p->qtdaddr == q->qtdaddr);
+
     ehci_execute_complete(q);
-    if (q->usb_status == USB_RET_ASYNC) {
+    if (p->usb_status == USB_RET_ASYNC) {
         goto out;
     }
-    if (q->usb_status == USB_RET_PROCERR) {
+    if (p->usb_status == USB_RET_PROCERR) {
         again = -1;
         goto out;
     }
@@ -1885,7 +1960,7 @@ static int ehci_state_executing(EHCIQueue *q, int async)
     }
 
     /* 4.10.5 */
-    if (q->usb_status == USB_RET_NAK) {
+    if (p->usb_status == USB_RET_NAK) {
         ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
     } else {
         ehci_set_state(q->ehci, async, EST_WRITEBACK);
@@ -1901,12 +1976,17 @@ out:
 
 static int ehci_state_writeback(EHCIQueue *q, int async)
 {
+    EHCIPacket *p = QTAILQ_FIRST(&q->packets);
     int again = 0;
 
     /*  Write back the QTD from the QH area */
-    ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), (EHCIqtd*) &q->qh.next_qtd);
-    put_dwords(q->ehci, NLPTR_GET(q->qtdaddr), (uint32_t *) &q->qh.next_qtd,
+    assert(p != NULL);
+    assert(p->qtdaddr == q->qtdaddr);
+
+    ehci_trace_qtd(q, NLPTR_GET(p->qtdaddr), (EHCIqtd *) &q->qh.next_qtd);
+    put_dwords(q->ehci, NLPTR_GET(p->qtdaddr), (uint32_t *) &q->qh.next_qtd,
                sizeof(EHCIqtd) >> 2);
+    ehci_free_packet(p);
 
     /*
      * EHCI specs say go horizontal here.
diff --git a/trace-events b/trace-events
index 293eddb..f70523c 100644
--- a/trace-events
+++ b/trace-events
@@ -257,6 +257,7 @@ usb_ehci_port_detach(uint32_t port) "detach port #%d"
 usb_ehci_port_reset(uint32_t port, int enable) "reset port #%d - %d"
 usb_ehci_data(int rw, uint32_t cpage, uint32_t offset, uint32_t addr, uint32_t len, uint32_t bufpos) "write %d, cpage %d, offset 0x%03x, addr 0x%08x, len %d, bufpos %d"
 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"
 
 # hw/usb/hcd-uhci.c
 usb_uhci_reset(void) "=== RESET ==="
-- 
1.7.1

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

* [Qemu-devel] [PATCH 21/37] ehci: make ehci_execute work on EHCIPacket instead of EHCIQueue
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (19 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 20/37] ehci: add EHCIPacket Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 22/37] ehci: cache USBDevice in EHCIQueue Gerd Hoffmann
                   ` (16 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

This way it is possible to use ehci_execute to submit others than the
first EHCIPacket of the EHCIQueue.

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

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 03ae09f..a7cf282 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -1395,30 +1395,26 @@ static void ehci_execute_complete(EHCIQueue *q)
 
 // 4.10.3
 
-static int ehci_execute(EHCIQueue *q)
+static int ehci_execute(EHCIPacket *p)
 {
-    EHCIPacket *p = QTAILQ_FIRST(&q->packets);
     USBDevice *dev;
     USBEndpoint *ep;
     int ret;
     int endp;
     int devadr;
 
-    assert(p != NULL);
-    assert(p->qtdaddr == q->qtdaddr);
-
-    if ( !(q->qh.token & QTD_TOKEN_ACTIVE)) {
-        fprintf(stderr, "Attempting to execute inactive QH\n");
+    if (!(p->qtd.token & QTD_TOKEN_ACTIVE)) {
+        fprintf(stderr, "Attempting to execute inactive qtd\n");
         return USB_RET_PROCERR;
     }
 
-    p->tbytes = (q->qh.token & QTD_TOKEN_TBYTES_MASK) >> QTD_TOKEN_TBYTES_SH;
+    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");
         return USB_RET_PROCERR;
     }
 
-    p->pid = (q->qh.token & QTD_TOKEN_PID_MASK) >> QTD_TOKEN_PID_SH;
+    p->pid = (p->qtd.token & QTD_TOKEN_PID_MASK) >> QTD_TOKEN_PID_SH;
     switch (p->pid) {
     case 0:
         p->pid = USB_TOKEN_OUT;
@@ -1438,11 +1434,11 @@ static int ehci_execute(EHCIQueue *q)
         return USB_RET_PROCERR;
     }
 
-    endp = get_field(q->qh.epchar, QH_EPCHAR_EP);
-    devadr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);
+    endp = get_field(p->queue->qh.epchar, QH_EPCHAR_EP);
+    devadr = get_field(p->queue->qh.epchar, QH_EPCHAR_DEVADDR);
 
     /* TODO: associating device with ehci port */
-    dev = ehci_find_device(q->ehci, devadr);
+    dev = ehci_find_device(p->queue->ehci, devadr);
     ep = usb_ep_get(dev, p->pid, endp);
 
     usb_packet_setup(&p->packet, p->pid, ep);
@@ -1912,7 +1908,7 @@ static int ehci_state_execute(EHCIQueue *q, int async)
         ehci_set_usbsts(q->ehci, USBSTS_REC);
     }
 
-    p->usb_status = ehci_execute(q);
+    p->usb_status = ehci_execute(p);
     if (p->usb_status == USB_RET_PROCERR) {
         again = -1;
         goto out;
-- 
1.7.1

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

* [Qemu-devel] [PATCH 22/37] ehci: cache USBDevice in EHCIQueue
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (20 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 21/37] ehci: make ehci_execute work on EHCIPacket instead of EHCIQueue Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 23/37] ehci: move ehci_flush_qh Gerd Hoffmann
                   ` (15 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Keep a USBDevice pointer in EHCIQueue so we don't have to lookup the
device on each usb packet submission.

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

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index a7cf282..d7131bd 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -371,6 +371,7 @@ struct EHCIQueue {
     EHCIqh qh;             /* copy of current QH (being worked on) */
     uint32_t qhaddr;       /* address QH read from                 */
     uint32_t qtdaddr;      /* address QTD read from                */
+    USBDevice *dev;
     QTAILQ_HEAD(, EHCIPacket) packets;
 };
 
@@ -758,11 +759,9 @@ static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
 {
     EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
     EHCIQueue *q, *tmp;
-    int addr;
 
     QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
-        addr = get_field(q->qh.epchar, QH_EPCHAR_DEVADDR);
-        if (addr != dev->addr) {
+        if (q->dev != dev) {
             continue;
         }
         ehci_free_queue(q, async);
@@ -1397,11 +1396,9 @@ static void ehci_execute_complete(EHCIQueue *q)
 
 static int ehci_execute(EHCIPacket *p)
 {
-    USBDevice *dev;
     USBEndpoint *ep;
     int ret;
     int endp;
-    int devadr;
 
     if (!(p->qtd.token & QTD_TOKEN_ACTIVE)) {
         fprintf(stderr, "Attempting to execute inactive qtd\n");
@@ -1435,16 +1432,12 @@ static int ehci_execute(EHCIPacket *p)
     }
 
     endp = get_field(p->queue->qh.epchar, QH_EPCHAR_EP);
-    devadr = get_field(p->queue->qh.epchar, QH_EPCHAR_DEVADDR);
-
-    /* TODO: associating device with ehci port */
-    dev = ehci_find_device(p->queue->ehci, devadr);
-    ep = usb_ep_get(dev, p->pid, endp);
+    ep = usb_ep_get(p->queue->dev, p->pid, endp);
 
     usb_packet_setup(&p->packet, p->pid, ep);
     usb_packet_map(&p->packet, &p->sgl);
 
-    ret = usb_handle_packet(dev, &p->packet);
+    ret = usb_handle_packet(p->queue->dev, &p->packet);
     DPRINTF("submit: qh %x next %x qtd %x pid %x len %zd "
             "(total %d) endp %x ret %d\n",
             q->qhaddr, q->qh.next, q->qtdaddr, q->pid,
@@ -1658,7 +1651,7 @@ out:
 static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
 {
     EHCIPacket *p;
-    uint32_t entry;
+    uint32_t entry, devaddr;
     EHCIQueue *q;
 
     entry = ehci_get_fetch_addr(ehci, async);
@@ -1681,6 +1674,20 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
                (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);
+    if (q->dev != NULL && q->dev->addr != devaddr) {
+        if (!QTAILQ_EMPTY(&q->packets)) {
+            /* should not happen (guest bug) */
+            while ((p = QTAILQ_FIRST(&q->packets)) != NULL) {
+                ehci_free_packet(p);
+            }
+        }
+        q->dev = NULL;
+    }
+    if (q->dev == NULL) {
+        q->dev = ehci_find_device(q->ehci, devaddr);
+    }
+
     if (p && p->async == EHCI_ASYNC_INFLIGHT) {
         /* I/O still in progress -- skip queue */
         ehci_set_state(ehci, async, EST_HORIZONTALQH);
-- 
1.7.1

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

* [Qemu-devel] [PATCH 23/37] ehci: move ehci_flush_qh
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (21 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 22/37] ehci: cache USBDevice in EHCIQueue Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 24/37] ehci: add queuing support Gerd Hoffmann
                   ` (14 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Move ehci_flush_qh() function up in the source code.
No code change.

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

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index d7131bd..f21b4be 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -1553,6 +1553,24 @@ static int ehci_process_itd(EHCIState *ehci,
     return 0;
 }
 
+
+/*
+ *  Write the qh back to guest physical memory.  This step isn't
+ *  in the EHCI spec but we need to do it since we don't share
+ *  physical memory with our guest VM.
+ *
+ *  The first three dwords are read-only for the EHCI, so skip them
+ *  when writing back the qh.
+ */
+static void ehci_flush_qh(EHCIQueue *q)
+{
+    uint32_t *qh = (uint32_t *) &q->qh;
+    uint32_t dwords = sizeof(EHCIqh) >> 2;
+    uint32_t addr = NLPTR_GET(q->qhaddr);
+
+    put_dwords(q->ehci, addr + 3 * sizeof(uint32_t), qh + 3, dwords - 3);
+}
+
 /*  This state is the entry point for asynchronous schedule
  *  processing.  Entry here consitutes a EHCI start event state (4.8.5)
  */
@@ -1869,23 +1887,6 @@ static int ehci_state_horizqh(EHCIQueue *q, int async)
     return again;
 }
 
-/*
- *  Write the qh back to guest physical memory.  This step isn't
- *  in the EHCI spec but we need to do it since we don't share
- *  physical memory with our guest VM.
- *
- *  The first three dwords are read-only for the EHCI, so skip them
- *  when writing back the qh.
- */
-static void ehci_flush_qh(EHCIQueue *q)
-{
-    uint32_t *qh = (uint32_t *) &q->qh;
-    uint32_t dwords = sizeof(EHCIqh) >> 2;
-    uint32_t addr = NLPTR_GET(q->qhaddr);
-
-    put_dwords(q->ehci, addr + 3 * sizeof(uint32_t), qh + 3, dwords - 3);
-}
-
 static int ehci_state_execute(EHCIQueue *q, int async)
 {
     EHCIPacket *p = QTAILQ_FIRST(&q->packets);
-- 
1.7.1

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

* [Qemu-devel] [PATCH 24/37] ehci: add queuing support
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (22 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 23/37] ehci: move ehci_flush_qh Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 25/37] ehci: tweak queue initialization Gerd Hoffmann
                   ` (13 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add packet queuing.  Follow the qTD chain to see if there are more
packets we can submit.  Improves performance on larger transfers,
especially with usb-host, as we don't have to wait for a packet to
finish before sending the next one to the host for processing.

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

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index f21b4be..ccaa947 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -671,10 +671,6 @@ static EHCIPacket *ehci_alloc_packet(EHCIQueue *q)
 {
     EHCIPacket *p;
 
-#if 1
-    /* temporary, we don't handle multiple packets per queue (yet) */
-    assert(QTAILQ_EMPTY(&q->packets));
-#endif
     p = g_new0(EHCIPacket, 1);
     p->queue = q;
     usb_packet_init(&p->packet);
@@ -1394,7 +1390,7 @@ static void ehci_execute_complete(EHCIQueue *q)
 
 // 4.10.3
 
-static int ehci_execute(EHCIPacket *p)
+static int ehci_execute(EHCIPacket *p, const char *action)
 {
     USBEndpoint *ep;
     int ret;
@@ -1437,6 +1433,7 @@ static int ehci_execute(EHCIPacket *p)
     usb_packet_setup(&p->packet, p->pid, ep);
     usb_packet_map(&p->packet, &p->sgl);
 
+    trace_usb_ehci_packet_action(p->queue, p, action);
     ret = usb_handle_packet(p->queue->dev, &p->packet);
     DPRINTF("submit: qh %x next %x qtd %x pid %x len %zd "
             "(total %d) endp %x ret %d\n",
@@ -1713,7 +1710,7 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
     }
     if (p && p->async == EHCI_ASYNC_FINISHED) {
         /* I/O finished -- continue processing queue */
-        trace_usb_ehci_queue_action(q, "resume");
+        trace_usb_ehci_packet_action(p->queue, p, "complete");
         ehci_set_state(ehci, async, EST_EXECUTING);
         goto out;
     }
@@ -1858,7 +1855,22 @@ static int ehci_state_fetchqtd(EHCIQueue *q, int async)
                sizeof(EHCIqtd) >> 2);
     ehci_trace_qtd(q, NLPTR_GET(q->qtdaddr), &qtd);
 
-    if (qtd.token & QTD_TOKEN_ACTIVE) {
+    p = QTAILQ_FIRST(&q->packets);
+    while (p != NULL && p->qtdaddr != q->qtdaddr) {
+        /* should not happen (guest bug) */
+        ehci_free_packet(p);
+        p = QTAILQ_FIRST(&q->packets);
+    }
+    if (p != NULL) {
+        ehci_qh_do_overlay(q);
+        ehci_flush_qh(q);
+        if (p->async == EHCI_ASYNC_INFLIGHT) {
+            ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+        } else {
+            ehci_set_state(q->ehci, async, EST_EXECUTING);
+        }
+        again = 1;
+    } else if (qtd.token & QTD_TOKEN_ACTIVE) {
         p = ehci_alloc_packet(q);
         p->qtdaddr = q->qtdaddr;
         p->qtd = qtd;
@@ -1887,6 +1899,35 @@ static int ehci_state_horizqh(EHCIQueue *q, int async)
     return again;
 }
 
+static void ehci_fill_queue(EHCIPacket *p, int async)
+{
+    EHCIQueue *q = p->queue;
+    EHCIqtd qtd = p->qtd;
+    uint32_t qtdaddr;
+
+    for (;;) {
+        if (NLPTR_TBIT(qtd.altnext) == 0) {
+            break;
+        }
+        if (NLPTR_TBIT(qtd.next) != 0) {
+            break;
+        }
+        qtdaddr = qtd.next;
+        get_dwords(q->ehci, NLPTR_GET(qtdaddr),
+                   (uint32_t *) &qtd, sizeof(EHCIqtd) >> 2);
+        ehci_trace_qtd(q, NLPTR_GET(qtdaddr), &qtd);
+        if (!(qtd.token & QTD_TOKEN_ACTIVE)) {
+            break;
+        }
+        p = ehci_alloc_packet(q);
+        p->qtdaddr = qtdaddr;
+        p->qtd = qtd;
+        p->usb_status = ehci_execute(p, "queue");
+        assert(p->usb_status = USB_RET_ASYNC);
+        p->async = EHCI_ASYNC_INFLIGHT;
+    }
+}
+
 static int ehci_state_execute(EHCIQueue *q, int async)
 {
     EHCIPacket *p = QTAILQ_FIRST(&q->packets);
@@ -1916,17 +1957,18 @@ static int ehci_state_execute(EHCIQueue *q, int async)
         ehci_set_usbsts(q->ehci, USBSTS_REC);
     }
 
-    p->usb_status = ehci_execute(p);
+    p->usb_status = ehci_execute(p, "process");
     if (p->usb_status == USB_RET_PROCERR) {
         again = -1;
         goto out;
     }
     if (p->usb_status == USB_RET_ASYNC) {
         ehci_flush_qh(q);
-        trace_usb_ehci_queue_action(q, "suspend");
+        trace_usb_ehci_packet_action(p->queue, p, "async");
         p->async = EHCI_ASYNC_INFLIGHT;
         ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
         again = 1;
+        ehci_fill_queue(p, async);
         goto out;
     }
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH 25/37] ehci: tweak queue initialization
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (23 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 24/37] ehci: add queuing support Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 26/37] ehci: add async field to EHCIQueue Gerd Hoffmann
                   ` (12 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Little tweak for the queue initialization, set the QH address in the
allocation function.

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

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index ccaa947..aa67af6 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -692,13 +692,14 @@ static void ehci_free_packet(EHCIPacket *p)
 
 /* queue management */
 
-static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, int async)
+static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, uint32_t addr, int async)
 {
     EHCIQueueHead *head = async ? &ehci->aqueues : &ehci->pqueues;
     EHCIQueue *q;
 
     q = g_malloc0(sizeof(*q));
     q->ehci = ehci;
+    q->qhaddr = addr;
     QTAILQ_INIT(&q->packets);
     QTAILQ_INSERT_HEAD(head, q, next);
     trace_usb_ehci_queue_action(q, "alloc");
@@ -1672,12 +1673,11 @@ static EHCIQueue *ehci_state_fetchqh(EHCIState *ehci, int async)
     entry = ehci_get_fetch_addr(ehci, async);
     q = ehci_find_queue_by_qh(ehci, entry, async);
     if (NULL == q) {
-        q = ehci_alloc_queue(ehci, async);
+        q = ehci_alloc_queue(ehci, entry, async);
     }
     p = QTAILQ_FIRST(&q->packets);
-    q->qhaddr = entry;
-    q->seen++;
 
+    q->seen++;
     if (q->seen > 1) {
         /* we are going in circles -- stop processing */
         ehci_set_state(ehci, async, EST_ACTIVE);
-- 
1.7.1

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

* [Qemu-devel] [PATCH 26/37] ehci: add async field to EHCIQueue
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (24 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 25/37] ehci: tweak queue initialization Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 27/37] ehci: move async schedule to bottom half Gerd Hoffmann
                   ` (11 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Keep track whenever a EHCIQueue is part of the async or periodic
schedule.  This way we don't have to pass around the async flag
everywhere but can look it up from the EHCIQueue struct when needed.

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

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index aa67af6..f363f14 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -364,6 +364,7 @@ struct EHCIQueue {
     QTAILQ_ENTRY(EHCIQueue) next;
     uint32_t seen;
     uint64_t ts;
+    int async;
 
     /* cached data from guest - needs to be flushed
      * when guest removes an entry (doorbell, handshake sequence)
@@ -700,15 +701,16 @@ static EHCIQueue *ehci_alloc_queue(EHCIState *ehci, uint32_t addr, int async)
     q = g_malloc0(sizeof(*q));
     q->ehci = ehci;
     q->qhaddr = addr;
+    q->async = async;
     QTAILQ_INIT(&q->packets);
     QTAILQ_INSERT_HEAD(head, q, next);
     trace_usb_ehci_queue_action(q, "alloc");
     return q;
 }
 
-static void ehci_free_queue(EHCIQueue *q, int async)
+static void ehci_free_queue(EHCIQueue *q)
 {
-    EHCIQueueHead *head = async ? &q->ehci->aqueues : &q->ehci->pqueues;
+    EHCIQueueHead *head = q->async ? &q->ehci->aqueues : &q->ehci->pqueues;
     EHCIPacket *p;
 
     trace_usb_ehci_queue_action(q, "free");
@@ -748,7 +750,7 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
             /* allow 0.25 sec idle */
             continue;
         }
-        ehci_free_queue(q, async);
+        ehci_free_queue(q);
     }
 }
 
@@ -761,7 +763,7 @@ static void ehci_queues_rip_device(EHCIState *ehci, USBDevice *dev, int async)
         if (q->dev != dev) {
             continue;
         }
-        ehci_free_queue(q, async);
+        ehci_free_queue(q);
     }
 }
 
@@ -771,7 +773,7 @@ static void ehci_queues_rip_all(EHCIState *ehci, int async)
     EHCIQueue *q, *tmp;
 
     QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
-        ehci_free_queue(q, async);
+        ehci_free_queue(q);
     }
 }
 
@@ -1806,7 +1808,7 @@ static int ehci_state_fetchsitd(EHCIState *ehci, int async)
 }
 
 /* Section 4.10.2 - paragraph 3 */
-static int ehci_state_advqueue(EHCIQueue *q, int async)
+static int ehci_state_advqueue(EHCIQueue *q)
 {
 #if 0
     /* TO-DO: 4.10.2 - paragraph 2
@@ -1825,27 +1827,27 @@ static int ehci_state_advqueue(EHCIQueue *q, int async)
     if (((q->qh.token & QTD_TOKEN_TBYTES_MASK) != 0) &&
         (NLPTR_TBIT(q->qh.altnext_qtd) == 0)) {
         q->qtdaddr = q->qh.altnext_qtd;
-        ehci_set_state(q->ehci, async, EST_FETCHQTD);
+        ehci_set_state(q->ehci, q->async, EST_FETCHQTD);
 
     /*
      *  next qTD is valid
      */
     } else if (NLPTR_TBIT(q->qh.next_qtd) == 0) {
         q->qtdaddr = q->qh.next_qtd;
-        ehci_set_state(q->ehci, async, EST_FETCHQTD);
+        ehci_set_state(q->ehci, q->async, EST_FETCHQTD);
 
     /*
      *  no valid qTD, try next QH
      */
     } else {
-        ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+        ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
     }
 
     return 1;
 }
 
 /* Section 4.10.2 - paragraph 4 */
-static int ehci_state_fetchqtd(EHCIQueue *q, int async)
+static int ehci_state_fetchqtd(EHCIQueue *q)
 {
     EHCIqtd qtd;
     EHCIPacket *p;
@@ -1865,41 +1867,41 @@ static int ehci_state_fetchqtd(EHCIQueue *q, int async)
         ehci_qh_do_overlay(q);
         ehci_flush_qh(q);
         if (p->async == EHCI_ASYNC_INFLIGHT) {
-            ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+            ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
         } else {
-            ehci_set_state(q->ehci, async, EST_EXECUTING);
+            ehci_set_state(q->ehci, q->async, EST_EXECUTING);
         }
         again = 1;
     } else if (qtd.token & QTD_TOKEN_ACTIVE) {
         p = ehci_alloc_packet(q);
         p->qtdaddr = q->qtdaddr;
         p->qtd = qtd;
-        ehci_set_state(q->ehci, async, EST_EXECUTE);
+        ehci_set_state(q->ehci, q->async, EST_EXECUTE);
         again = 1;
     } else {
-        ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+        ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
         again = 1;
     }
 
     return again;
 }
 
-static int ehci_state_horizqh(EHCIQueue *q, int async)
+static int ehci_state_horizqh(EHCIQueue *q)
 {
     int again = 0;
 
-    if (ehci_get_fetch_addr(q->ehci, async) != q->qh.next) {
-        ehci_set_fetch_addr(q->ehci, async, q->qh.next);
-        ehci_set_state(q->ehci, async, EST_FETCHENTRY);
+    if (ehci_get_fetch_addr(q->ehci, q->async) != q->qh.next) {
+        ehci_set_fetch_addr(q->ehci, q->async, q->qh.next);
+        ehci_set_state(q->ehci, q->async, EST_FETCHENTRY);
         again = 1;
     } else {
-        ehci_set_state(q->ehci, async, EST_ACTIVE);
+        ehci_set_state(q->ehci, q->async, EST_ACTIVE);
     }
 
     return again;
 }
 
-static void ehci_fill_queue(EHCIPacket *p, int async)
+static void ehci_fill_queue(EHCIPacket *p)
 {
     EHCIQueue *q = p->queue;
     EHCIqtd qtd = p->qtd;
@@ -1928,7 +1930,7 @@ static void ehci_fill_queue(EHCIPacket *p, int async)
     }
 }
 
-static int ehci_state_execute(EHCIQueue *q, int async)
+static int ehci_state_execute(EHCIQueue *q)
 {
     EHCIPacket *p = QTAILQ_FIRST(&q->packets);
     int again = 0;
@@ -1944,16 +1946,16 @@ static int ehci_state_execute(EHCIQueue *q, int async)
     // TODO write back ptr to async list when done or out of time
     // TODO Windows does not seem to ever set the MULT field
 
-    if (!async) {
+    if (!q->async) {
         int transactCtr = get_field(q->qh.epcap, QH_EPCAP_MULT);
         if (!transactCtr) {
-            ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+            ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
             again = 1;
             goto out;
         }
     }
 
-    if (async) {
+    if (q->async) {
         ehci_set_usbsts(q->ehci, USBSTS_REC);
     }
 
@@ -1966,20 +1968,20 @@ static int ehci_state_execute(EHCIQueue *q, int async)
         ehci_flush_qh(q);
         trace_usb_ehci_packet_action(p->queue, p, "async");
         p->async = EHCI_ASYNC_INFLIGHT;
-        ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+        ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
         again = 1;
-        ehci_fill_queue(p, async);
+        ehci_fill_queue(p);
         goto out;
     }
 
-    ehci_set_state(q->ehci, async, EST_EXECUTING);
+    ehci_set_state(q->ehci, q->async, EST_EXECUTING);
     again = 1;
 
 out:
     return again;
 }
 
-static int ehci_state_executing(EHCIQueue *q, int async)
+static int ehci_state_executing(EHCIQueue *q)
 {
     EHCIPacket *p = QTAILQ_FIRST(&q->packets);
     int again = 0;
@@ -1997,7 +1999,7 @@ static int ehci_state_executing(EHCIQueue *q, int async)
     }
 
     // 4.10.3
-    if (!async) {
+    if (!q->async) {
         int transactCtr = get_field(q->qh.epcap, QH_EPCAP_MULT);
         transactCtr--;
         set_field(&q->qh.epcap, transactCtr, QH_EPCAP_MULT);
@@ -2007,9 +2009,9 @@ static int ehci_state_executing(EHCIQueue *q, int async)
 
     /* 4.10.5 */
     if (p->usb_status == USB_RET_NAK) {
-        ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+        ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
     } else {
-        ehci_set_state(q->ehci, async, EST_WRITEBACK);
+        ehci_set_state(q->ehci, q->async, EST_WRITEBACK);
     }
 
     again = 1;
@@ -2020,7 +2022,7 @@ out:
 }
 
 
-static int ehci_state_writeback(EHCIQueue *q, int async)
+static int ehci_state_writeback(EHCIQueue *q)
 {
     EHCIPacket *p = QTAILQ_FIRST(&q->packets);
     int again = 0;
@@ -2043,10 +2045,10 @@ static int ehci_state_writeback(EHCIQueue *q, int async)
      * bit is clear.
      */
     if (q->qh.token & QTD_TOKEN_HALT) {
-        ehci_set_state(q->ehci, async, EST_HORIZONTALQH);
+        ehci_set_state(q->ehci, q->async, EST_HORIZONTALQH);
         again = 1;
     } else {
-        ehci_set_state(q->ehci, async, EST_ADVANCEQUEUE);
+        ehci_set_state(q->ehci, q->async, EST_ADVANCEQUEUE);
         again = 1;
     }
     return again;
@@ -2056,8 +2058,7 @@ static int ehci_state_writeback(EHCIQueue *q, int async)
  * This is the state machine that is common to both async and periodic
  */
 
-static void ehci_advance_state(EHCIState *ehci,
-                               int async)
+static void ehci_advance_state(EHCIState *ehci, int async)
 {
     EHCIQueue *q = NULL;
     int again;
@@ -2074,7 +2075,12 @@ static void ehci_advance_state(EHCIState *ehci,
 
         case EST_FETCHQH:
             q = ehci_state_fetchqh(ehci, async);
-            again = q ? 1 : 0;
+            if (q != NULL) {
+                assert(q->async == async);
+                again = 1;
+            } else {
+                again = 0;
+            }
             break;
 
         case EST_FETCHITD:
@@ -2086,29 +2092,29 @@ static void ehci_advance_state(EHCIState *ehci,
             break;
 
         case EST_ADVANCEQUEUE:
-            again = ehci_state_advqueue(q, async);
+            again = ehci_state_advqueue(q);
             break;
 
         case EST_FETCHQTD:
-            again = ehci_state_fetchqtd(q, async);
+            again = ehci_state_fetchqtd(q);
             break;
 
         case EST_HORIZONTALQH:
-            again = ehci_state_horizqh(q, async);
+            again = ehci_state_horizqh(q);
             break;
 
         case EST_EXECUTE:
-            again = ehci_state_execute(q, async);
+            again = ehci_state_execute(q);
             break;
 
         case EST_EXECUTING:
             assert(q != NULL);
-            again = ehci_state_executing(q, async);
+            again = ehci_state_executing(q);
             break;
 
         case EST_WRITEBACK:
             assert(q != NULL);
-            again = ehci_state_writeback(q, async);
+            again = ehci_state_writeback(q);
             break;
 
         default:
-- 
1.7.1

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

* [Qemu-devel] [PATCH 27/37] ehci: move async schedule to bottom half
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (25 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 26/37] ehci: add async field to EHCIQueue Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 28/37] ehci: schedule async bh on async packet completion Gerd Hoffmann
                   ` (10 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

This way we can kick the async schedule independant from the
periodic frame timer.

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

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index f363f14..16627d3 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -414,6 +414,7 @@ struct EHCIState {
      *  Internal states, shadow registers, etc
      */
     QEMUTimer *frame_timer;
+    QEMUBH *async_bh;
     int attach_poll_counter;
     int astate;                        // Current state in asynchronous schedule
     int pstate;                        // Current state in periodic schedule
@@ -959,6 +960,7 @@ static void ehci_reset(void *opaque)
     ehci_queues_rip_all(s, 0);
     ehci_queues_rip_all(s, 1);
     qemu_del_timer(s->frame_timer);
+    qemu_bh_cancel(s->async_bh);
 }
 
 static uint32_t ehci_mem_readb(void *ptr, target_phys_addr_t addr)
@@ -1111,6 +1113,7 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
 
         if (!(val & USBCMD_RUNSTOP) && (s->usbcmd & USBCMD_RUNSTOP)) {
             qemu_del_timer(s->frame_timer);
+            qemu_bh_cancel(s->async_bh);
             ehci_queues_rip_all(s, 0);
             ehci_queues_rip_all(s, 1);
             ehci_set_usbsts(s, USBSTS_HALT);
@@ -2290,11 +2293,16 @@ static void ehci_frame_timer(void *opaque)
     /*  Async is not inside loop since it executes everything it can once
      *  called
      */
-    ehci_advance_async_state(ehci);
+    qemu_bh_schedule(ehci->async_bh);
 
     qemu_mod_timer(ehci->frame_timer, expire_time);
 }
 
+static void ehci_async_bh(void *opaque)
+{
+    EHCIState *ehci = opaque;
+    ehci_advance_async_state(ehci);
+}
 
 static const MemoryRegionOps ehci_mem_ops = {
     .old_mmio = {
@@ -2430,6 +2438,7 @@ static int usb_ehci_initfn(PCIDevice *dev)
     }
 
     s->frame_timer = qemu_new_timer_ns(vm_clock, ehci_frame_timer, s);
+    s->async_bh = qemu_bh_new(ehci_async_bh, s);
     QTAILQ_INIT(&s->aqueues);
     QTAILQ_INIT(&s->pqueues);
 
-- 
1.7.1

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

* [Qemu-devel] [PATCH 28/37] ehci: schedule async bh on async packet completion
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (26 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 27/37] ehci: move async schedule to bottom half Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 29/37] ehci: kick async schedule on wakeup Gerd Hoffmann
                   ` (9 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

When a packet completes which happens to be part of the async schedule
kick the async bottom half for processing,

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

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 16627d3..8b2dfed 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -1327,6 +1327,10 @@ static void ehci_async_complete_packet(USBPort *port, USBPacket *packet)
     assert(p->async == EHCI_ASYNC_INFLIGHT);
     p->async = EHCI_ASYNC_FINISHED;
     p->usb_status = packet->result;
+
+    if (p->queue->async) {
+        qemu_bh_schedule(p->queue->ehci->async_bh);
+    }
 }
 
 static void ehci_execute_complete(EHCIQueue *q)
-- 
1.7.1

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

* [Qemu-devel] [PATCH 29/37] ehci: kick async schedule on wakeup
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (27 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 28/37] ehci: schedule async bh on async packet completion Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-07-06 14:30   ` Hans de Goede
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 30/37] ehci: fix reset Gerd Hoffmann
                   ` (8 subsequent siblings)
  37 siblings, 1 reply; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Kick async schedule when we get a wakeup
notification from a usb device.

Signed-off-by: Gerd Hoffmann <kraxel@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 8b2dfed..f8ed80d 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -852,6 +852,8 @@ static void ehci_wakeup(USBPort *port)
         USBPort *companion = s->companion_ports[port->index];
         if (companion->ops->wakeup) {
             companion->ops->wakeup(companion);
+        } else {
+            qemu_bh_schedule(s->async_bh);
         }
     }
 }
-- 
1.7.1

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

* [Qemu-devel] [PATCH 30/37] ehci: fix reset
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (28 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 29/37] ehci: kick async schedule on wakeup Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 31/37] ehci: add ehci_*_enabled() helpers Gerd Hoffmann
                   ` (7 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Check for the reset bit first when processing USBCMD register writes.
Also break out of the switch, there is no need to check the other bits.

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

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index f8ed80d..3b602b0 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -1107,6 +1107,12 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
     /* Do any register specific pre-write processing here.  */
     switch(addr) {
     case USBCMD:
+        if (val & USBCMD_HCRESET) {
+            ehci_reset(s);
+            val = s->usbcmd;
+            break;
+        }
+
         if ((val & USBCMD_RUNSTOP) && !(s->usbcmd & USBCMD_RUNSTOP)) {
             qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
             SET_LAST_RUN_CLOCK(s);
@@ -1121,10 +1127,6 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
             ehci_set_usbsts(s, USBSTS_HALT);
         }
 
-        if (val & USBCMD_HCRESET) {
-            ehci_reset(s);
-            val = s->usbcmd;
-        }
 
         /* not supporting dynamic frame list size at the moment */
         if ((val & USBCMD_FLS) && !(s->usbcmd & USBCMD_FLS)) {
-- 
1.7.1

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

* [Qemu-devel] [PATCH 31/37] ehci: add ehci_*_enabled() helpers
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (29 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 30/37] ehci: fix reset Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 32/37] ehci: update status bits in ehci_set_state Gerd Hoffmann
                   ` (6 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Add helper functions to query whenever the async / periodic schedule
is enabled or not.  Put them into use too.

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

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 3b602b0..d9c0f0f 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -667,6 +667,21 @@ static void ehci_trace_sitd(EHCIState *s, target_phys_addr_t addr,
                         (bool)(sitd->results & SITD_RESULTS_ACTIVE));
 }
 
+static inline bool ehci_enabled(EHCIState *s)
+{
+    return s->usbcmd & USBCMD_RUNSTOP;
+}
+
+static inline bool ehci_async_enabled(EHCIState *s)
+{
+    return ehci_enabled(s) && (s->usbcmd & USBCMD_ASE);
+}
+
+static inline bool ehci_periodic_enabled(EHCIState *s)
+{
+    return ehci_enabled(s) && (s->usbcmd & USBCMD_PSE);
+}
+
 /* packet management */
 
 static EHCIPacket *ehci_alloc_packet(EHCIQueue *q)
@@ -1160,7 +1175,7 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
         break;
 
     case PERIODICLISTBASE:
-        if ((s->usbcmd & USBCMD_PSE) && (s->usbcmd & USBCMD_RUNSTOP)) {
+        if (ehci_periodic_enabled(s)) {
             fprintf(stderr,
               "ehci: PERIODIC list base register set while periodic schedule\n"
               "      is enabled and HC is enabled\n");
@@ -1168,7 +1183,7 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
         break;
 
     case ASYNCLISTADDR:
-        if ((s->usbcmd & USBCMD_ASE) && (s->usbcmd & USBCMD_RUNSTOP)) {
+        if (ehci_async_enabled(s)) {
             fprintf(stderr,
               "ehci: ASYNC list address register set while async schedule\n"
               "      is enabled and HC is enabled\n");
@@ -2152,7 +2167,7 @@ static void ehci_advance_async_state(EHCIState *ehci)
 
     switch(ehci_get_state(ehci, async)) {
     case EST_INACTIVE:
-        if (!(ehci->usbcmd & USBCMD_ASE)) {
+        if (!ehci_async_enabled(ehci)) {
             break;
         }
         ehci_set_usbsts(ehci, USBSTS_ASS);
@@ -2160,7 +2175,7 @@ static void ehci_advance_async_state(EHCIState *ehci)
         // No break, fall through to ACTIVE
 
     case EST_ACTIVE:
-        if ( !(ehci->usbcmd & USBCMD_ASE)) {
+        if (!ehci_async_enabled(ehci)) {
             ehci_queues_rip_all(ehci, async);
             ehci_clear_usbsts(ehci, USBSTS_ASS);
             ehci_set_state(ehci, async, EST_INACTIVE);
@@ -2213,7 +2228,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
 
     switch(ehci_get_state(ehci, async)) {
     case EST_INACTIVE:
-        if ( !(ehci->frindex & 7) && (ehci->usbcmd & USBCMD_PSE)) {
+        if (!(ehci->frindex & 7) && ehci_periodic_enabled(ehci)) {
             ehci_set_usbsts(ehci, USBSTS_PSS);
             ehci_set_state(ehci, async, EST_ACTIVE);
             // No break, fall through to ACTIVE
@@ -2221,7 +2236,7 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
             break;
 
     case EST_ACTIVE:
-        if ( !(ehci->frindex & 7) && !(ehci->usbcmd & USBCMD_PSE)) {
+        if (!(ehci->frindex & 7) && !ehci_periodic_enabled(ehci)) {
             ehci_queues_rip_all(ehci, async);
             ehci_clear_usbsts(ehci, USBSTS_PSS);
             ehci_set_state(ehci, async, EST_INACTIVE);
-- 
1.7.1

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

* [Qemu-devel] [PATCH 32/37] ehci: update status bits in ehci_set_state
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (30 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 31/37] ehci: add ehci_*_enabled() helpers Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 33/37] ehci: fix halt status handling Gerd Hoffmann
                   ` (5 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Update the status register in the ehci_set_state function, to make sure
the guest-visible register is in sync with our internal schedule state.

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

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index d9c0f0f..0a550f9 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -591,9 +591,19 @@ static void ehci_set_state(EHCIState *s, int async, int state)
     if (async) {
         trace_usb_ehci_state("async", state2str(state));
         s->astate = state;
+        if (s->astate == EST_INACTIVE) {
+            ehci_clear_usbsts(s, USBSTS_ASS);
+        } else {
+            ehci_set_usbsts(s, USBSTS_ASS);
+        }
     } else {
         trace_usb_ehci_state("periodic", state2str(state));
         s->pstate = state;
+        if (s->pstate == EST_INACTIVE) {
+            ehci_clear_usbsts(s, USBSTS_PSS);
+        } else {
+            ehci_set_usbsts(s, USBSTS_PSS);
+        }
     }
 }
 
@@ -2170,14 +2180,12 @@ static void ehci_advance_async_state(EHCIState *ehci)
         if (!ehci_async_enabled(ehci)) {
             break;
         }
-        ehci_set_usbsts(ehci, USBSTS_ASS);
         ehci_set_state(ehci, async, EST_ACTIVE);
         // No break, fall through to ACTIVE
 
     case EST_ACTIVE:
         if (!ehci_async_enabled(ehci)) {
             ehci_queues_rip_all(ehci, async);
-            ehci_clear_usbsts(ehci, USBSTS_ASS);
             ehci_set_state(ehci, async, EST_INACTIVE);
             break;
         }
@@ -2229,7 +2237,6 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
     switch(ehci_get_state(ehci, async)) {
     case EST_INACTIVE:
         if (!(ehci->frindex & 7) && ehci_periodic_enabled(ehci)) {
-            ehci_set_usbsts(ehci, USBSTS_PSS);
             ehci_set_state(ehci, async, EST_ACTIVE);
             // No break, fall through to ACTIVE
         } else
@@ -2238,7 +2245,6 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
     case EST_ACTIVE:
         if (!(ehci->frindex & 7) && !ehci_periodic_enabled(ehci)) {
             ehci_queues_rip_all(ehci, async);
-            ehci_clear_usbsts(ehci, USBSTS_PSS);
             ehci_set_state(ehci, async, EST_INACTIVE);
             break;
         }
-- 
1.7.1

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

* [Qemu-devel] [PATCH 33/37] ehci: fix halt status handling
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (31 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 32/37] ehci: update status bits in ehci_set_state Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 34/37] ehci: remove unused attach_poll_counter Gerd Hoffmann
                   ` (4 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

When the enable bits for controller / async schedule / periodic schedule
change just make sure we kick the frame timer and let
ehci_advance_periodic_state and ehci_advance_async_state handle the
controller state changes.

This will make ehci set USBSTS_HALT when the controller shutdown is
actually done, once both schedules are in inactive state and the
USBSTS_PSS and USBSTS_ASS bits are clear.

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

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index 0a550f9..f77a26d 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -586,6 +586,17 @@ static inline void ehci_commit_interrupt(EHCIState *s)
     s->usbsts_pending = 0;
 }
 
+static void ehci_update_halt(EHCIState *s)
+{
+    if (s->usbcmd & USBCMD_RUNSTOP) {
+        ehci_clear_usbsts(s, USBSTS_HALT);
+    } else {
+        if (s->astate == EST_INACTIVE && s->pstate == EST_INACTIVE) {
+            ehci_set_usbsts(s, USBSTS_HALT);
+        }
+    }
+}
+
 static void ehci_set_state(EHCIState *s, int async, int state)
 {
     if (async) {
@@ -593,6 +604,7 @@ static void ehci_set_state(EHCIState *s, int async, int state)
         s->astate = state;
         if (s->astate == EST_INACTIVE) {
             ehci_clear_usbsts(s, USBSTS_ASS);
+            ehci_update_halt(s);
         } else {
             ehci_set_usbsts(s, USBSTS_ASS);
         }
@@ -601,6 +613,7 @@ static void ehci_set_state(EHCIState *s, int async, int state)
         s->pstate = state;
         if (s->pstate == EST_INACTIVE) {
             ehci_clear_usbsts(s, USBSTS_PSS);
+            ehci_update_halt(s);
         } else {
             ehci_set_usbsts(s, USBSTS_PSS);
         }
@@ -1138,21 +1151,15 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
             break;
         }
 
-        if ((val & USBCMD_RUNSTOP) && !(s->usbcmd & USBCMD_RUNSTOP)) {
-            qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
-            SET_LAST_RUN_CLOCK(s);
-            ehci_clear_usbsts(s, USBSTS_HALT);
-        }
-
-        if (!(val & USBCMD_RUNSTOP) && (s->usbcmd & USBCMD_RUNSTOP)) {
-            qemu_del_timer(s->frame_timer);
-            qemu_bh_cancel(s->async_bh);
-            ehci_queues_rip_all(s, 0);
-            ehci_queues_rip_all(s, 1);
-            ehci_set_usbsts(s, USBSTS_HALT);
+        if (((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & val) !=
+            ((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & s->usbcmd)) {
+            if (!ehci_enabled(s)) {
+                qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
+                SET_LAST_RUN_CLOCK(s);
+            }
+            ehci_update_halt(s);
         }
 
-
         /* not supporting dynamic frame list size at the moment */
         if ((val & USBCMD_FLS) && !(s->usbcmd & USBCMD_FLS)) {
             fprintf(stderr, "attempt to set frame list size -- value %d\n",
@@ -2291,7 +2298,7 @@ static void ehci_frame_timer(void *opaque)
     frames = ns_elapsed / FRAME_TIMER_NS;
 
     for (i = 0; i < frames; i++) {
-        if ( !(ehci->usbsts & USBSTS_HALT)) {
+        if (ehci_enabled(ehci)) {
             ehci->frindex += 8;
 
             if (ehci->frindex == 0x00002000) {
@@ -2324,7 +2331,9 @@ static void ehci_frame_timer(void *opaque)
      */
     qemu_bh_schedule(ehci->async_bh);
 
-    qemu_mod_timer(ehci->frame_timer, expire_time);
+    if (ehci_enabled(ehci)) {
+        qemu_mod_timer(ehci->frame_timer, expire_time);
+    }
 }
 
 static void ehci_async_bh(void *opaque)
-- 
1.7.1

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

* [Qemu-devel] [PATCH 34/37] ehci: remove unused attach_poll_counter
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (32 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 33/37] ehci: fix halt status handling Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 35/37] ehci: create ehci_update_frindex Gerd Hoffmann
                   ` (3 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

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

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index f77a26d..ee7420f 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -415,7 +415,6 @@ struct EHCIState {
      */
     QEMUTimer *frame_timer;
     QEMUBH *async_bh;
-    int attach_poll_counter;
     int astate;                        // Current state in asynchronous schedule
     int pstate;                        // Current state in periodic schedule
     USBPort ports[NB_PORTS];
@@ -984,7 +983,6 @@ static void ehci_reset(void *opaque)
 
     s->astate = EST_INACTIVE;
     s->pstate = EST_INACTIVE;
-    s->attach_poll_counter = 0;
 
     for(i = 0; i < NB_PORTS; i++) {
         if (s->companion_ports[i]) {
-- 
1.7.1

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

* [Qemu-devel] [PATCH 35/37] ehci: create ehci_update_frindex
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (33 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 34/37] ehci: remove unused attach_poll_counter Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 36/37] ehci: adaptive wakeup rate Gerd Hoffmann
                   ` (2 subsequent siblings)
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Factor out code from ehci_frame_timer.

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

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index ee7420f..c15dbee 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -2280,6 +2280,28 @@ static void ehci_advance_periodic_state(EHCIState *ehci)
     }
 }
 
+static void ehci_update_frindex(EHCIState *ehci, int frames)
+{
+    int i;
+
+    if (!ehci_enabled(ehci)) {
+        return;
+    }
+
+    for (i = 0; i < frames; i++) {
+        ehci->frindex += 8;
+
+        if (ehci->frindex == 0x00002000) {
+            ehci_set_interrupt(ehci, USBSTS_FLR);
+        }
+
+        if (ehci->frindex == 0x00004000) {
+            ehci_set_interrupt(ehci, USBSTS_FLR);
+            ehci->frindex = 0;
+        }
+    }
+}
+
 static void ehci_frame_timer(void *opaque)
 {
     EHCIState *ehci = opaque;
@@ -2296,18 +2318,7 @@ static void ehci_frame_timer(void *opaque)
     frames = ns_elapsed / FRAME_TIMER_NS;
 
     for (i = 0; i < frames; i++) {
-        if (ehci_enabled(ehci)) {
-            ehci->frindex += 8;
-
-            if (ehci->frindex == 0x00002000) {
-                ehci_set_interrupt(ehci, USBSTS_FLR);
-            }
-
-            if (ehci->frindex == 0x00004000) {
-                ehci_set_interrupt(ehci, USBSTS_FLR);
-                ehci->frindex = 0;
-            }
-        }
+        ehci_update_frindex(ehci, 1);
 
         if (frames - i > ehci->maxframes) {
             skipped_frames++;
-- 
1.7.1

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

* [Qemu-devel] [PATCH 36/37] ehci: adaptive wakeup rate.
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (34 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 35/37] ehci: create ehci_update_frindex Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 37/37] ehci: rework frame skipping Gerd Hoffmann
  2012-06-11 18:27 ` [Qemu-devel] [PULL 00/37] usb patch queue Anthony Liguori
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Adapt the frame timer sleeps according to the actual needs.  With the
periodic schedule being active we'll have to wakeup 1000 times per
second and go check for work.  In case only the async schedule is active
we can be more lazy though.  When idle ehci will increate the sleep time
step by step, so qemu has to wake up less frequently.  When we'll see
transactions on the bus or the guest fiddles with the schedule
enable/disable bits we'll return to a 1000 Hz wakeup rate and full
speed.  With both schedules disabled we stop wakeups altogether.

This patch also drops the freq property (configures wakeup rate
manually) which is obsoleted by this patch.

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

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index c15dbee..d97c539 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -386,7 +386,6 @@ struct EHCIState {
     int companion_count;
 
     /* properties */
-    uint32_t freq;
     uint32_t maxframes;
 
     /*
@@ -430,6 +429,7 @@ struct EHCIState {
     QEMUSGList isgl;
 
     uint64_t last_run_ns;
+    uint32_t async_stepdown;
 };
 
 #define SET_LAST_RUN_CLOCK(s) \
@@ -776,6 +776,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;
+    uint64_t maxage = FRAME_TIMER_NS * ehci->maxframes * 4;
     EHCIQueue *q, *tmp;
 
     QTAILQ_FOREACH_SAFE(q, head, next, tmp) {
@@ -784,8 +785,7 @@ static void ehci_queues_rip_unused(EHCIState *ehci, int async, int flush)
             q->ts = ehci->last_run_ns;
             continue;
         }
-        if (!flush && ehci->last_run_ns < q->ts + 250000000) {
-            /* allow 0.25 sec idle */
+        if (!flush && ehci->last_run_ns < q->ts + maxage) {
             continue;
         }
         ehci_free_queue(q);
@@ -1151,11 +1151,12 @@ static void ehci_mem_writel(void *ptr, target_phys_addr_t addr, uint32_t val)
 
         if (((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & val) !=
             ((USBCMD_RUNSTOP | USBCMD_PSE | USBCMD_ASE) & s->usbcmd)) {
-            if (!ehci_enabled(s)) {
-                qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
+            if (s->pstate == EST_INACTIVE) {
                 SET_LAST_RUN_CLOCK(s);
             }
             ehci_update_halt(s);
+            s->async_stepdown = 0;
+            qemu_mod_timer(s->frame_timer, qemu_get_clock_ns(vm_clock));
         }
 
         /* not supporting dynamic frame list size at the moment */
@@ -2146,10 +2147,16 @@ static void ehci_advance_state(EHCIState *ehci, int async)
 
         case EST_EXECUTE:
             again = ehci_state_execute(q);
+            if (async) {
+                ehci->async_stepdown = 0;
+            }
             break;
 
         case EST_EXECUTING:
             assert(q != NULL);
+            if (async) {
+                ehci->async_stepdown = 0;
+            }
             again = ehci_state_executing(q);
             break;
 
@@ -2305,6 +2312,7 @@ static void ehci_update_frindex(EHCIState *ehci, int frames)
 static void ehci_frame_timer(void *opaque)
 {
     EHCIState *ehci = opaque;
+    int schedules = 0;
     int64_t expire_time, t_now;
     uint64_t ns_elapsed;
     int frames;
@@ -2312,21 +2320,32 @@ static void ehci_frame_timer(void *opaque)
     int skipped_frames = 0;
 
     t_now = qemu_get_clock_ns(vm_clock);
-    expire_time = t_now + (get_ticks_per_sec() / ehci->freq);
-
     ns_elapsed = t_now - ehci->last_run_ns;
     frames = ns_elapsed / FRAME_TIMER_NS;
 
-    for (i = 0; i < frames; i++) {
-        ehci_update_frindex(ehci, 1);
+    if (ehci_periodic_enabled(ehci) || ehci->pstate != EST_INACTIVE) {
+        schedules++;
+        expire_time = t_now + (get_ticks_per_sec() / FRAME_TIMER_FREQ);
 
-        if (frames - i > ehci->maxframes) {
-            skipped_frames++;
-        } else {
-            ehci_advance_periodic_state(ehci);
-        }
+        for (i = 0; i < frames; i++) {
+            ehci_update_frindex(ehci, 1);
 
-        ehci->last_run_ns += FRAME_TIMER_NS;
+            if (frames - i > ehci->maxframes) {
+                skipped_frames++;
+            } else {
+                ehci_advance_periodic_state(ehci);
+            }
+
+            ehci->last_run_ns += FRAME_TIMER_NS;
+        }
+    } else {
+        if (ehci->async_stepdown < ehci->maxframes / 2) {
+            ehci->async_stepdown++;
+        }
+        expire_time = t_now + (get_ticks_per_sec()
+                               * ehci->async_stepdown / FRAME_TIMER_FREQ);
+        ehci_update_frindex(ehci, frames);
+        ehci->last_run_ns += FRAME_TIMER_NS * frames;
     }
 
 #if 0
@@ -2338,9 +2357,12 @@ static void ehci_frame_timer(void *opaque)
     /*  Async is not inside loop since it executes everything it can once
      *  called
      */
-    qemu_bh_schedule(ehci->async_bh);
+    if (ehci_async_enabled(ehci) || ehci->astate != EST_INACTIVE) {
+        schedules++;
+        qemu_bh_schedule(ehci->async_bh);
+    }
 
-    if (ehci_enabled(ehci)) {
+    if (schedules) {
         qemu_mod_timer(ehci->frame_timer, expire_time);
     }
 }
@@ -2379,7 +2401,6 @@ static const VMStateDescription vmstate_ehci = {
 };
 
 static Property ehci_properties[] = {
-    DEFINE_PROP_UINT32("freq",      EHCIState, freq, FRAME_TIMER_FREQ),
     DEFINE_PROP_UINT32("maxframes", EHCIState, maxframes, 128),
     DEFINE_PROP_END_OF_LIST(),
 };
-- 
1.7.1

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

* [Qemu-devel] [PATCH 37/37] ehci: rework frame skipping
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (35 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 36/37] ehci: adaptive wakeup rate Gerd Hoffmann
@ 2012-06-07  9:31 ` Gerd Hoffmann
  2012-06-11 18:27 ` [Qemu-devel] [PULL 00/37] usb patch queue Anthony Liguori
  37 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-06-07  9:31 UTC (permalink / raw)
  To: qemu-devel; +Cc: Gerd Hoffmann

Move the framecount check out of the loop and use the new
ehci_update_frindex function to skip frames if needed.

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

diff --git a/hw/usb/hcd-ehci.c b/hw/usb/hcd-ehci.c
index d97c539..5298204 100644
--- a/hw/usb/hcd-ehci.c
+++ b/hw/usb/hcd-ehci.c
@@ -2315,9 +2315,8 @@ static void ehci_frame_timer(void *opaque)
     int schedules = 0;
     int64_t expire_time, t_now;
     uint64_t ns_elapsed;
-    int frames;
+    int frames, skipped_frames;
     int i;
-    int skipped_frames = 0;
 
     t_now = qemu_get_clock_ns(vm_clock);
     ns_elapsed = t_now - ehci->last_run_ns;
@@ -2327,15 +2326,17 @@ static void ehci_frame_timer(void *opaque)
         schedules++;
         expire_time = t_now + (get_ticks_per_sec() / FRAME_TIMER_FREQ);
 
+        if (frames > ehci->maxframes) {
+            skipped_frames = frames - ehci->maxframes;
+            ehci_update_frindex(ehci, skipped_frames);
+            ehci->last_run_ns += FRAME_TIMER_NS * skipped_frames;
+            frames -= skipped_frames;
+            DPRINTF("WARNING - EHCI skipped %d frames\n", skipped_frames);
+        }
+
         for (i = 0; i < frames; i++) {
             ehci_update_frindex(ehci, 1);
-
-            if (frames - i > ehci->maxframes) {
-                skipped_frames++;
-            } else {
-                ehci_advance_periodic_state(ehci);
-            }
-
+            ehci_advance_periodic_state(ehci);
             ehci->last_run_ns += FRAME_TIMER_NS;
         }
     } else {
@@ -2348,12 +2349,6 @@ static void ehci_frame_timer(void *opaque)
         ehci->last_run_ns += FRAME_TIMER_NS * frames;
     }
 
-#if 0
-    if (skipped_frames) {
-        DPRINTF("WARNING - EHCI skipped %d frames\n", skipped_frames);
-    }
-#endif
-
     /*  Async is not inside loop since it executes everything it can once
      *  called
      */
-- 
1.7.1

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

* Re: [Qemu-devel] [PULL 00/37] usb patch queue
  2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
                   ` (36 preceding siblings ...)
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 37/37] ehci: rework frame skipping Gerd Hoffmann
@ 2012-06-11 18:27 ` Anthony Liguori
  37 siblings, 0 replies; 42+ messages in thread
From: Anthony Liguori @ 2012-06-11 18:27 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

On 06/07/2012 04:30 AM, Gerd Hoffmann wrote:
>    Hi,
>
> Here are a bunch of usb patches.  There are four groups in there which
> are independant and have been posted as separate series for review ~ two
> weeks ago:
>
>    (1) uhci: various little fixes and improvements.
>    (2) usb-storage: live migration support.
>    (3) xhci: tracing support.
>    (4) ehci: pipelining (have multiple packets per endpoint in flight),
>        schedule&  timer handling improvements to reduce wakeup rate.

Pulled.  Thanks.

Regards,

Anthony Liguori

>
> please pull,
>    Gerd
>
> The following changes since commit 349417004a0f7cf5518a998dca755cd06f6c212b:
>
>    Merge remote-tracking branch 'qmp/queue/qmp' into staging (2012-06-06 20:57:56 +0800)
>
> are available in the git repository at:
>
>    git://git.kraxel.org/qemu usb.52
>
> Gerd Hoffmann (36):
>        uhci: fix bandwidth management
>        uhci: use bottom half
>        uhci: make bandwidth tunable
>        uhci: fix trace format strings
>        uhci: zap uhci_pre_save
>        uhci: fix irq routing
>        scsi: prepare migration code for usb-storage support
>        usb-storage: remove MSDState->residue
>        usb-storage: add usb_msd_packet_complete()
>        usb-storage: add scsi_off, remove scsi_buf
>        usb-storage: migration support
>        xhci: trace: mmio reads+writes
>        xhci: trace: run+stop
>        xhci: trace: irq + events
>        xhci: trace: ring fetch
>        xhci: trace: endpoints
>        xhci: trace: transfers
>        xhci: trace: slots
>        ehci: add EHCIPacket
>        ehci: make ehci_execute work on EHCIPacket instead of EHCIQueue
>        ehci: cache USBDevice in EHCIQueue
>        ehci: move ehci_flush_qh
>        ehci: add queuing support
>        ehci: tweak queue initialization
>        ehci: add async field to EHCIQueue
>        ehci: move async schedule to bottom half
>        ehci: schedule async bh on async packet completion
>        ehci: kick async schedule on wakeup
>        ehci: fix reset
>        ehci: add ehci_*_enabled() helpers
>        ehci: update status bits in ehci_set_state
>        ehci: fix halt status handling
>        ehci: remove unused attach_poll_counter
>        ehci: create ehci_update_frindex
>        ehci: adaptive wakeup rate.
>        ehci: rework frame skipping
>
> Jan Kiszka (1):
>        xhci: Clean up reset function
>
>   hw/scsi-bus.c        |    8 +-
>   hw/scsi-disk.c       |   16 ++-
>   hw/usb/dev-storage.c |   69 ++++--
>   hw/usb/hcd-ehci.c    |  610 +++++++++++++++++++++++++++++++++-----------------
>   hw/usb/hcd-uhci.c    |   67 ++++--
>   hw/usb/hcd-xhci.c    |  251 ++++++++++++----------
>   trace-events         |   46 ++++-
>   7 files changed, 695 insertions(+), 372 deletions(-)
>
>

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

* Re: [Qemu-devel] [PATCH 29/37] ehci: kick async schedule on wakeup
  2012-06-07  9:31 ` [Qemu-devel] [PATCH 29/37] ehci: kick async schedule on wakeup Gerd Hoffmann
@ 2012-07-06 14:30   ` Hans de Goede
  2012-07-06 14:54     ` Hans de Goede
  0 siblings, 1 reply; 42+ messages in thread
From: Hans de Goede @ 2012-07-06 14:30 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

Hi,

On 06/07/2012 11:31 AM, Gerd Hoffmann wrote:
> Kick async schedule when we get a wakeup
> notification from a usb device.
>
> Signed-off-by: Gerd Hoffmann <kraxel@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 8b2dfed..f8ed80d 100644
> --- a/hw/usb/hcd-ehci.c
> +++ b/hw/usb/hcd-ehci.c
> @@ -852,6 +852,8 @@ static void ehci_wakeup(USBPort *port)
>           USBPort *companion = s->companion_ports[port->index];
>           if (companion->ops->wakeup) {
>               companion->ops->wakeup(companion);
> +        } else {
> +            qemu_bh_schedule(s->async_bh);
>           }
>       }
>   }
>

This is wrong, this puts the added else inside the
"if (portsc & PORTSC_POWNER) {" block, iow it will only
trigger when the port is redirected to the companion controller,
it should be the else of the "if (portsc & PORTSC_POWNER)" so that
the async schedule gets kicked on wakeup when the device is connected
to the ehci (rather then to an companion uhci).

Notice how the if where the else now belongs to is unconditionally
dereferencing companion in the form of companion->ops, it can do
this because the "if (portsc & PORTSC_POWNER)" check ensures there is
a companion port for this device, the second level if is to see if
the companion has wakeup support.

Regards,

Hans

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

* Re: [Qemu-devel] [PATCH 29/37] ehci: kick async schedule on wakeup
  2012-07-06 14:30   ` Hans de Goede
@ 2012-07-06 14:54     ` Hans de Goede
  2012-07-09  8:02       ` Gerd Hoffmann
  0 siblings, 1 reply; 42+ messages in thread
From: Hans de Goede @ 2012-07-06 14:54 UTC (permalink / raw)
  To: Gerd Hoffmann; +Cc: qemu-devel

Hi,

On 07/06/2012 04:30 PM, Hans de Goede wrote:
> Hi,
>
> On 06/07/2012 11:31 AM, Gerd Hoffmann wrote:
>> Kick async schedule when we get a wakeup
>> notification from a usb device.
>>
>> Signed-off-by: Gerd Hoffmann <kraxel@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 8b2dfed..f8ed80d 100644
>> --- a/hw/usb/hcd-ehci.c
>> +++ b/hw/usb/hcd-ehci.c
>> @@ -852,6 +852,8 @@ static void ehci_wakeup(USBPort *port)
>>           USBPort *companion = s->companion_ports[port->index];
>>           if (companion->ops->wakeup) {
>>               companion->ops->wakeup(companion);
>> +        } else {
>> +            qemu_bh_schedule(s->async_bh);
>>           }
>>       }
>>   }
>>
>
> This is wrong, this puts the added else inside the
> "if (portsc & PORTSC_POWNER) {" block, iow it will only
> trigger when the port is redirected to the companion controller,
> it should be the else of the "if (portsc & PORTSC_POWNER)" so that
> the async schedule gets kicked on wakeup when the device is connected
> to the ehci (rather then to an companion uhci).
>
> Notice how the if where the else now belongs to is unconditionally
> dereferencing companion in the form of companion->ops, it can do
> this because the "if (portsc & PORTSC_POWNER)" check ensures there is
> a companion port for this device, the second level if is to see if
> the companion has wakeup support.

I've just send a patch fixing this. One last remark though, do we
support wakeup in the EHCI-code at all?

Regards,

Hans

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

* Re: [Qemu-devel] [PATCH 29/37] ehci: kick async schedule on wakeup
  2012-07-06 14:54     ` Hans de Goede
@ 2012-07-09  8:02       ` Gerd Hoffmann
  0 siblings, 0 replies; 42+ messages in thread
From: Gerd Hoffmann @ 2012-07-09  8:02 UTC (permalink / raw)
  To: Hans de Goede; +Cc: qemu-devel

  Hi,

> do we
> support wakeup in the EHCI-code at all?

uhci and ohci do, could be ehci doesn't, all our hid emulated devices
which need remote wakeup most are usb 1.1 devices ...

cheers,
  Gerd

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

end of thread, other threads:[~2012-07-09  8:02 UTC | newest]

Thread overview: 42+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-06-07  9:30 [Qemu-devel] [PULL 00/37] usb patch queue Gerd Hoffmann
2012-06-07  9:30 ` [Qemu-devel] [PATCH 01/37] uhci: fix bandwidth management Gerd Hoffmann
2012-06-07  9:30 ` [Qemu-devel] [PATCH 02/37] uhci: use bottom half Gerd Hoffmann
2012-06-07  9:30 ` [Qemu-devel] [PATCH 03/37] uhci: make bandwidth tunable Gerd Hoffmann
2012-06-07  9:30 ` [Qemu-devel] [PATCH 04/37] uhci: fix trace format strings Gerd Hoffmann
2012-06-07  9:30 ` [Qemu-devel] [PATCH 05/37] uhci: zap uhci_pre_save Gerd Hoffmann
2012-06-07  9:30 ` [Qemu-devel] [PATCH 06/37] uhci: fix irq routing Gerd Hoffmann
2012-06-07  9:30 ` [Qemu-devel] [PATCH 07/37] scsi: prepare migration code for usb-storage support Gerd Hoffmann
2012-06-07  9:30 ` [Qemu-devel] [PATCH 08/37] usb-storage: remove MSDState->residue Gerd Hoffmann
2012-06-07  9:30 ` [Qemu-devel] [PATCH 09/37] usb-storage: add usb_msd_packet_complete() Gerd Hoffmann
2012-06-07  9:30 ` [Qemu-devel] [PATCH 10/37] usb-storage: add scsi_off, remove scsi_buf Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 11/37] usb-storage: migration support Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 12/37] xhci: Clean up reset function Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 13/37] xhci: trace: mmio reads+writes Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 14/37] xhci: trace: run+stop Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 15/37] xhci: trace: irq + events Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 16/37] xhci: trace: ring fetch Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 17/37] xhci: trace: endpoints Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 18/37] xhci: trace: transfers Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 19/37] xhci: trace: slots Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 20/37] ehci: add EHCIPacket Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 21/37] ehci: make ehci_execute work on EHCIPacket instead of EHCIQueue Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 22/37] ehci: cache USBDevice in EHCIQueue Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 23/37] ehci: move ehci_flush_qh Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 24/37] ehci: add queuing support Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 25/37] ehci: tweak queue initialization Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 26/37] ehci: add async field to EHCIQueue Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 27/37] ehci: move async schedule to bottom half Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 28/37] ehci: schedule async bh on async packet completion Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 29/37] ehci: kick async schedule on wakeup Gerd Hoffmann
2012-07-06 14:30   ` Hans de Goede
2012-07-06 14:54     ` Hans de Goede
2012-07-09  8:02       ` Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 30/37] ehci: fix reset Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 31/37] ehci: add ehci_*_enabled() helpers Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 32/37] ehci: update status bits in ehci_set_state Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 33/37] ehci: fix halt status handling Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 34/37] ehci: remove unused attach_poll_counter Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 35/37] ehci: create ehci_update_frindex Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 36/37] ehci: adaptive wakeup rate Gerd Hoffmann
2012-06-07  9:31 ` [Qemu-devel] [PATCH 37/37] ehci: rework frame skipping Gerd Hoffmann
2012-06-11 18:27 ` [Qemu-devel] [PULL 00/37] usb patch queue Anthony Liguori

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.