From 8865ab79a0a9ce0d55082854fb29cc26535c8722 Mon Sep 17 00:00:00 2001
Message-Id: <8865ab79a0a9ce0d55082854fb29cc26535c8722.1346940159.git.minovotn@redhat.com>
In-Reply-To: <c629acdc74c5b775c5cf7a7a3cb20ac833bcd0cc.1346940159.git.minovotn@redhat.com>
References: <c629acdc74c5b775c5cf7a7a3cb20ac833bcd0cc.1346940159.git.minovotn@redhat.com>
From: Gerd Hoffmann <kraxel@redhat.com>
Date: Thu, 16 Aug 2012 11:39:09 +0200
Subject: [PATCH 07/18] ehci: add live migration support

RH-Author: Gerd Hoffmann <kraxel@redhat.com>
Message-id: <1345117160-21046-8-git-send-email-kraxel@redhat.com>
Patchwork-id: 40930
O-Subject: [RHEL-6.4 qemu-kvm PATCH 07/18] ehci: add live migration support
Bugzilla: 805172
RH-Acked-by: Paolo Bonzini <pbonzini@redhat.com>
RH-Acked-by: Hans de Goede <hdegoede@redhat.com>
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>

[ rhel6: add pre_save & post_load to convert last_run_ns <=> last_run_usec ]

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
(cherry picked from commit 9a77340827cd48c5c9b6daab614009a0594abf38)

Conflicts:

	hw/usb-ehci.c
---
 hw/usb-ehci.c |   75 ++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 files changed, 69 insertions(+), 6 deletions(-)

Signed-off-by: Michal Novotny <minovotn@redhat.com>
---
 hw/usb-ehci.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 69 insertions(+), 6 deletions(-)

diff --git a/hw/usb-ehci.c b/hw/usb-ehci.c
index 46b51ec..aa0afbf 100644
--- a/hw/usb-ehci.c
+++ b/hw/usb-ehci.c
@@ -403,16 +403,17 @@ 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
+    uint32_t astate;                        // Current state in asynchronous schedule
+    uint32_t pstate;                        // Current state in periodic schedule
     USBPort ports[NB_PORTS];
     USBPort *companion_ports[NB_PORTS];
     uint32_t usbsts_pending;
     EHCIQueueHead aqueues;
     EHCIQueueHead pqueues;
 
-    uint32_t a_fetch_addr;   // which address to look at next
-    uint32_t p_fetch_addr;   // which address to look at next
+    /* which address to look at next */
+    uint32_t a_fetch_addr;
+    uint32_t p_fetch_addr;
 
     USBPacket ipacket;
     uint8_t ibuffer[BUFF_SIZE];
@@ -420,6 +421,10 @@ struct EHCIState {
 
     uint32_t last_run_usec;
     uint32_t frame_end_usec;
+
+    /* for migration compatibility with upstream */
+    uint64_t last_run_ns;
+    uint32_t async_stepdown;
 };
 
 #define SET_LAST_RUN_CLOCK(s) \
@@ -2215,9 +2220,67 @@ static USBBusOps ehci_bus_ops = {
     .register_companion = ehci_register_companion,
 };
 
+static void usb_ehci_pre_save(void *opaque)
+{
+    EHCIState *s = opaque;
+
+    s->last_run_ns = (uint64_t)(s->last_run_usec) * 1000;
+}
+
+static int usb_ehci_post_load(void *opaque, int version_id)
+{
+    EHCIState *s = opaque;
+    int i;
+
+    for (i = 0; i < NB_PORTS; i++) {
+        USBPort *companion = s->companion_ports[i];
+        if (companion == NULL) {
+            continue;
+        }
+        if (s->portsc[i] & PORTSC_POWNER) {
+            companion->dev = s->ports[i].dev;
+        } else {
+            companion->dev = NULL;
+        }
+    }
+
+    s->last_run_usec = s->last_run_ns / 1000;
+    return 0;
+}
+
 static const VMStateDescription vmstate_ehci = {
-    .name = "ehci",
-    .unmigratable = 1,
+    .name        = "ehci",
+    .version_id  = 1,
+    .pre_save    = usb_ehci_pre_save,
+    .post_load   = usb_ehci_post_load,
+    .fields      = (VMStateField[]) {
+        VMSTATE_PCI_DEVICE(dev, EHCIState),
+        /* mmio registers */
+        VMSTATE_UINT32(usbcmd, EHCIState),
+        VMSTATE_UINT32(usbsts, EHCIState),
+        VMSTATE_UINT32(usbintr, EHCIState),
+        VMSTATE_UINT32(frindex, EHCIState),
+        VMSTATE_UINT32(ctrldssegment, EHCIState),
+        VMSTATE_UINT32(periodiclistbase, EHCIState),
+        VMSTATE_UINT32(asynclistaddr, EHCIState),
+        VMSTATE_UINT32(configflag, EHCIState),
+        VMSTATE_UINT32(portsc[0], EHCIState),
+        VMSTATE_UINT32(portsc[1], EHCIState),
+        VMSTATE_UINT32(portsc[2], EHCIState),
+        VMSTATE_UINT32(portsc[3], EHCIState),
+        VMSTATE_UINT32(portsc[4], EHCIState),
+        VMSTATE_UINT32(portsc[5], EHCIState),
+        /* frame timer */
+        VMSTATE_TIMER(frame_timer, EHCIState),
+        VMSTATE_UINT64(last_run_ns, EHCIState),
+        VMSTATE_UINT32(async_stepdown, EHCIState),
+        /* schedule state */
+        VMSTATE_UINT32(astate, EHCIState),
+        VMSTATE_UINT32(pstate, EHCIState),
+        VMSTATE_UINT32(a_fetch_addr, EHCIState),
+        VMSTATE_UINT32(p_fetch_addr, EHCIState),
+        VMSTATE_END_OF_LIST()
+    }
 };
 
 static Property ehci_properties[] = {
-- 
1.7.11.4

