9ae3a8
From d6c5ce73edbc928cce19a095a27e2feff9db8884 Mon Sep 17 00:00:00 2001
9ae3a8
From: Gerd Hoffmann <kraxel@redhat.com>
9ae3a8
Date: Fri, 11 Jul 2014 14:20:52 +0200
9ae3a8
Subject: [PATCH 18/43] xhci: Add a few missing checks for disconnected devices
9ae3a8
9ae3a8
Message-id: <1405088470-24115-20-git-send-email-kraxel@redhat.com>
9ae3a8
Patchwork-id: 59827
9ae3a8
O-Subject: [RHEL-7.1 qemu-kvm PATCH 19/37] xhci: Add a few missing checks for disconnected devices
9ae3a8
Bugzilla: 980833
9ae3a8
RH-Acked-by: Dr. David Alan Gilbert (git) <dgilbert@redhat.com>
9ae3a8
RH-Acked-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
RH-Acked-by: Laszlo Ersek <lersek@redhat.com>
9ae3a8
9ae3a8
From: Hans de Goede <hdegoede@redhat.com>
9ae3a8
9ae3a8
One of the reworks of qemu's usb core made changes to usb-port's disconnect
9ae3a8
handling. Now ports with a device will always have a non 0 dev member, but
9ae3a8
if the device is not attached (which is possible with usb redirection),
9ae3a8
dev->attached will be 0.
9ae3a8
9ae3a8
So supplement all checks for dev to also check dev->attached, and add an
9ae3a8
extra check in a path where a device check was completely missing.
9ae3a8
9ae3a8
This fixes various crashes (asserts triggering) I've been seeing when xhci
9ae3a8
attached usb devices get disconnected at the wrong time.
9ae3a8
9ae3a8
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
9ae3a8
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
9ae3a8
(cherry picked from commit de9de157fbb9aa66380ab1973dd6ecf12fbd8b25)
9ae3a8
---
9ae3a8
 hw/usb/hcd-xhci.c | 13 +++++++++++--
9ae3a8
 1 file changed, 11 insertions(+), 2 deletions(-)
9ae3a8
9ae3a8
Signed-off-by: Miroslav Rezanina <mrezanin@redhat.com>
9ae3a8
---
9ae3a8
 hw/usb/hcd-xhci.c | 13 +++++++++++--
9ae3a8
 1 file changed, 11 insertions(+), 2 deletions(-)
9ae3a8
9ae3a8
diff --git a/hw/usb/hcd-xhci.c b/hw/usb/hcd-xhci.c
9ae3a8
index ef0c073..944b255 100644
9ae3a8
--- a/hw/usb/hcd-xhci.c
9ae3a8
+++ b/hw/usb/hcd-xhci.c
9ae3a8
@@ -1498,7 +1498,8 @@ static TRBCCode xhci_reset_ep(XHCIState *xhci, unsigned int slotid,
9ae3a8
     }
9ae3a8
 
9ae3a8
     if (!xhci->slots[slotid-1].uport ||
9ae3a8
-        !xhci->slots[slotid-1].uport->dev) {
9ae3a8
+        !xhci->slots[slotid-1].uport->dev ||
9ae3a8
+        !xhci->slots[slotid-1].uport->dev->attached) {
9ae3a8
         return CC_USB_TRANSACTION_ERROR;
9ae3a8
     }
9ae3a8
 
9ae3a8
@@ -1985,6 +1986,14 @@ static void xhci_kick_ep(XHCIState *xhci, unsigned int slotid,
9ae3a8
         return;
9ae3a8
     }
9ae3a8
 
9ae3a8
+    /* If the device has been detached, but the guest has not noticed this
9ae3a8
+       yet the 2 above checks will succeed, but we must NOT continue */
9ae3a8
+    if (!xhci->slots[slotid - 1].uport ||
9ae3a8
+        !xhci->slots[slotid - 1].uport->dev ||
9ae3a8
+        !xhci->slots[slotid - 1].uport->dev->attached) {
9ae3a8
+        return;
9ae3a8
+    }
9ae3a8
+
9ae3a8
     if (epctx->retry) {
9ae3a8
         XHCITransfer *xfer = epctx->retry;
9ae3a8
 
9ae3a8
@@ -2209,7 +2218,7 @@ static TRBCCode xhci_address_slot(XHCIState *xhci, unsigned int slotid,
9ae3a8
     trace_usb_xhci_slot_address(slotid, uport->path);
9ae3a8
 
9ae3a8
     dev = uport->dev;
9ae3a8
-    if (!dev) {
9ae3a8
+    if (!dev || !dev->attached) {
9ae3a8
         fprintf(stderr, "xhci: port %s not connected\n", uport->path);
9ae3a8
         return CC_USB_TRANSACTION_ERROR;
9ae3a8
     }
9ae3a8
-- 
9ae3a8
1.8.3.1
9ae3a8