Blame SOURCES/kvm-Introduce-new-no_guest_reset-parameter-for-usb-host-.patch

ae23c9
From 7efd1d899d2478ad9fffcf0584907f38cd6d20ff Mon Sep 17 00:00:00 2001
ae23c9
From: Gerd Hoffmann <kraxel@redhat.com>
ae23c9
Date: Tue, 4 Jun 2019 05:12:43 +0100
ae23c9
Subject: [PATCH 1/8] Introduce new "no_guest_reset" parameter for usb-host
ae23c9
 device
ae23c9
ae23c9
RH-Author: Gerd Hoffmann <kraxel@redhat.com>
ae23c9
Message-id: <20190604051246.11374-2-kraxel@redhat.com>
ae23c9
Patchwork-id: 88470
ae23c9
O-Subject: [RHEL-8.1.0 qemu-kvm PATCH 1/4] Introduce new "no_guest_reset" parameter for usb-host device
ae23c9
Bugzilla: 1713677
ae23c9
RH-Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com>
ae23c9
RH-Acked-by: Max Reitz <mreitz@redhat.com>
ae23c9
RH-Acked-by: Danilo de Paula <ddepaula@redhat.com>
ae23c9
ae23c9
From: Alexander Kappner <agk@godking.net>
ae23c9
ae23c9
With certain USB devices passed through via usb-host, a guest attempting to
ae23c9
reset a usb-host device can trigger a reset loop that renders the USB device
ae23c9
unusable. In my use case, the device was an iPhone XR that was passed through to
ae23c9
a Mac OS X Mojave guest. Upon connecting the device, the following happens:
ae23c9
ae23c9
1) Guest recognizes new device, sends reset to emulated USB host
ae23c9
2) QEMU's USB host sends reset to host kernel
ae23c9
3) Host kernel resets device
ae23c9
4) After reset, host kernel determines that some part of the device descriptor
ae23c9
has changed ("device firmware changed" in dmesg), so host kernel decides to
ae23c9
re-enumerate the device.
ae23c9
5) Re-enumeration causes QEMU to disconnect and reconnect the device in the
ae23c9
guest.
ae23c9
6) goto 1)
ae23c9
ae23c9
Here's from the host kernel (note the "device firmware changed" lines")
ae23c9
ae23c9
[3677704.473050] usb 1-1.3: new high-speed USB device number 53 using ehci-pci
ae23c9
[3677704.555594] usb 1-1.3: New USB device found, idVendor=05ac, idProduct=12a8, bcdDevice=11.08
ae23c9
[3677704.555599] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
ae23c9
[3677704.555602] usb 1-1.3: Product: iPhone
ae23c9
[3677704.555605] usb 1-1.3: Manufacturer: Apple Inc.
ae23c9
[3677704.555607] usb 1-1.3: SerialNumber: [[removed]]
ae23c9
[3677709.401040] usb 1-1.3: reset high-speed USB device number 53 using ehci-pci
ae23c9
[3677709.479486] usb 1-1.3: device firmware changed
ae23c9
[3677709.479842] usb 1-1.3: USB disconnect, device number 53
ae23c9
[3677709.546039] usb 1-1.3: new high-speed USB device number 54 using ehci-pci
ae23c9
[3677709.627471] usb 1-1.3: New USB device found, idVendor=05ac, idProduct=12a8, bcdDevice=11.08
ae23c9
[3677709.627476] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
ae23c9
[3677709.627479] usb 1-1.3: Product: iPhone
ae23c9
[3677709.627481] usb 1-1.3: Manufacturer: Apple Inc.
ae23c9
[3677709.627483] usb 1-1.3: SerialNumber: [[removed]]
ae23c9
[3677762.320044] usb 1-1.3: reset high-speed USB device number 54 using ehci-pci
ae23c9
[3677762.615630] usb 1-1.3: USB disconnect, device number 54
ae23c9
[3677762.787043] usb 1-1.3: new high-speed USB device number 55 using ehci-pci
ae23c9
[3677762.869016] usb 1-1.3: New USB device found, idVendor=05ac, idProduct=12a8, bcdDevice=11.08
ae23c9
[3677762.869024] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
ae23c9
[3677762.869028] usb 1-1.3: Product: iPhone
ae23c9
[3677762.869032] usb 1-1.3: Manufacturer: Apple Inc.
ae23c9
[3677762.869035] usb 1-1.3: SerialNumber: [[removed]]
ae23c9
[3677815.662036] usb 1-1.3: reset high-speed USB device number 55 using ehci-pci
ae23c9
ae23c9
Here's from QEMU:
ae23c9
ae23c9
libusb: error [_get_usbfs_fd] libusb couldn't open USB device /dev/bus/usb/005/022: No such file or directory
ae23c9
libusb: error [udev_hotplug_event] ignoring udev action bind
ae23c9
libusb: error [udev_hotplug_event] ignoring udev action bind
ae23c9
libusb: error [_open_sysfs_attr] open /sys/bus/usb/devices/5-1/bConfigurationValue failed ret=-1 errno=2
ae23c9
libusb: error [_get_usbfs_fd] File doesn't exist, wait 10 ms and try again
ae23c9
ae23c9
libusb: error [_get_usbfs_fd] libusb couldn't open USB device /dev/bus/usb/005/024: No such file or directory
ae23c9
libusb: error [udev_hotplug_event] ignoring udev action bind
ae23c9
libusb: error [udev_hotplug_event] ignoring udev action bind
ae23c9
libusb: error [_open_sysfs_attr] open /sys/bus/usb/devices/5-1/bConfigurationValue failed ret=-1 errno=2
ae23c9
libusb: error [_get_usbfs_fd] File doesn't exist, wait 10 ms and try again
ae23c9
ae23c9
libusb: error [_get_usbfs_fd] libusb couldn't open USB device /dev/bus/usb/005/026: No such file or directory
ae23c9
ae23c9
The result of this is that the device remains permanently unusable in the guest.
ae23c9
The same problem has been previously reported for an iPad:
ae23c9
https://stackoverflow.com/questions/52617634/how-do-i-get-qemu-usb-passthrough-to-work-for-ipad-iphone
ae23c9
ae23c9
This problem can be elegantly solved by interrupting step 2) above. Instead of
ae23c9
passing through the reset, QEMU simply ignores it. To allow this to be
ae23c9
configured on a per-device level,  a new parameter "no_guest_reset" is
ae23c9
introduced for the usb-host device. I can confirm that the configuration
ae23c9
described above (iPhone XS + Mojave guest) works flawlessly with
ae23c9
no_guest_reset=True specified.
ae23c9
ae23c9
Working command line for my scenario:
ae23c9
device_add usb-host,vendorid=0x05ac,productid=0x12a8,no_guest_reset=True,id=iphone
ae23c9
ae23c9
Best regards
ae23c9
Alexander
ae23c9
ae23c9
Signed-off-by: Alexander Kappner <agk@godking.net>
ae23c9
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
ae23c9
Message-id: 20190128140027.9448-1-kraxel@redhat.com
ae23c9
ae23c9
[ kraxel: rename parameter to "guest-reset" ]
ae23c9
ae23c9
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
ae23c9
(cherry picked from commit ba4c735b4fc74e309ce4b2551d258e442ef513a5)
ae23c9
Signed-off-by: Danilo C. L. de Paula <ddepaula@redhat.com>
ae23c9
---
ae23c9
 hw/usb/host-libusb.c | 7 ++++++-
ae23c9
 1 file changed, 6 insertions(+), 1 deletion(-)
ae23c9
ae23c9
diff --git a/hw/usb/host-libusb.c b/hw/usb/host-libusb.c
ae23c9
index f31e9cb..d82a10a 100644
ae23c9
--- a/hw/usb/host-libusb.c
ae23c9
+++ b/hw/usb/host-libusb.c
ae23c9
@@ -82,7 +82,7 @@ struct USBHostDevice {
ae23c9
     uint32_t                         options;
ae23c9
     uint32_t                         loglevel;
ae23c9
     bool                             needs_autoscan;
ae23c9
-
ae23c9
+    bool                             allow_guest_reset;
ae23c9
     /* state */
ae23c9
     QTAILQ_ENTRY(USBHostDevice)      next;
ae23c9
     int                              seen, errcount;
ae23c9
@@ -1451,6 +1451,10 @@ static void usb_host_handle_reset(USBDevice *udev)
ae23c9
     USBHostDevice *s = USB_HOST_DEVICE(udev);
ae23c9
     int rc;
ae23c9
 
ae23c9
+    if (!s->allow_guest_reset) {
ae23c9
+        return;
ae23c9
+    }
ae23c9
+
ae23c9
     trace_usb_host_reset(s->bus_num, s->addr);
ae23c9
 
ae23c9
     rc = libusb_reset_device(s->dh);
ae23c9
@@ -1568,6 +1572,7 @@ static Property usb_host_dev_properties[] = {
ae23c9
     DEFINE_PROP_UINT32("productid", USBHostDevice, match.product_id, 0),
ae23c9
     DEFINE_PROP_UINT32("isobufs",  USBHostDevice, iso_urb_count,    4),
ae23c9
     DEFINE_PROP_UINT32("isobsize", USBHostDevice, iso_urb_frames,   32),
ae23c9
+    DEFINE_PROP_BOOL("guest-reset", USBHostDevice, allow_guest_reset, true),
ae23c9
     DEFINE_PROP_UINT32("loglevel",  USBHostDevice, loglevel,
ae23c9
                        LIBUSB_LOG_LEVEL_WARNING),
ae23c9
     DEFINE_PROP_BIT("pipeline",    USBHostDevice, options,
ae23c9
-- 
ae23c9
1.8.3.1
ae23c9