From d346f693a6ce469099fa9c8733f5604be0d57e8f Mon Sep 17 00:00:00 2001 Message-Id: In-Reply-To: References: From: Gerd Hoffmann Date: Thu, 16 Aug 2012 11:39:20 +0200 Subject: [PATCH 18/18] usb-host: live migration support RH-Author: Gerd Hoffmann Message-id: <1345117160-21046-19-git-send-email-kraxel@redhat.com> Patchwork-id: 40934 O-Subject: [RHEL-6.4 qemu-kvm PATCH 18/18] usb-host: live migration support Bugzilla: 805172 RH-Acked-by: Paolo Bonzini RH-Acked-by: Hans de Goede RH-Acked-by: Laszlo Ersek Signed-off-by: Gerd Hoffmann (cherry picked from commit a229c0535bd336efaec786dd6e352a54e0a8187d) --- usb-linux.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 46 insertions(+), 1 deletions(-) Signed-off-by: Michal Novotny --- usb-linux.c | 47 ++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/usb-linux.c b/usb-linux.c index fdcc43d..cd1665b 100644 --- a/usb-linux.c +++ b/usb-linux.c @@ -128,6 +128,7 @@ typedef struct USBHostDevice { int closing; uint32_t iso_urb_count; Notifier exit; + QEMUBH *bh; struct endp_data ep_in[MAX_ENDPOINTS]; struct endp_data ep_out[MAX_ENDPOINTS]; @@ -1382,6 +1383,43 @@ static void usb_host_exit_notifier(struct Notifier *n, void *data) } } +/* + * This is *NOT* about restoring state. We have absolutely no idea + * what state the host device is in at the moment and whenever it is + * still present in the first place. Attemping to contine where we + * left off is impossible. + * + * What we are going to to to here is emulate a surprise removal of + * the usb device passed through, then kick host scan so the device + * will get re-attached (and re-initialized by the guest) in case it + * is still present. + * + * As the device removal will change the state of other devices (usb + * host controller, most likely interrupt controller too) we have to + * wait with it until *all* vmstate is loaded. Thus post_load just + * kicks a bottom half which then does the actual work. + */ +static void usb_host_post_load_bh(void *opaque) +{ + USBHostDevice *dev = opaque; + + if (dev->fd != -1) { + usb_host_close(dev); + } + if (dev->dev.attached) { + usb_device_detach(&dev->dev); + } + usb_host_auto_check(NULL); +} + +static int usb_host_post_load(void *opaque, int version_id) +{ + USBHostDevice *dev = opaque; + + qemu_bh_schedule(dev->bh); + return 0; +} + static int usb_host_initfn(USBDevice *dev) { USBHostDevice *s = DO_UPCAST(USBHostDevice, dev, dev); @@ -1393,6 +1431,7 @@ static int usb_host_initfn(USBDevice *dev) QTAILQ_INSERT_TAIL(&hostdevs, s, next); s->exit.notify = usb_host_exit_notifier; qemu_add_exit_notifier(&s->exit); + s->bh = qemu_bh_new(usb_host_post_load_bh, s); usb_host_auto_check(NULL); if (s->match.bus_num != 0 && s->match.port != NULL) { @@ -1403,7 +1442,13 @@ static int usb_host_initfn(USBDevice *dev) static const VMStateDescription vmstate_usb_host = { .name = "usb-host", - .unmigratable = 1, + .version_id = 1, + .minimum_version_id = 1, + .post_load = usb_host_post_load, + .fields = (VMStateField[]) { + VMSTATE_USB_DEVICE(dev, USBHostDevice), + VMSTATE_END_OF_LIST() + } }; static struct USBDeviceInfo usb_host_dev_info = { -- 1.7.11.4