aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin O'Connor <kevin@koconnor.net>2017-10-03 11:29:12 -0400
committerKevin O'Connor <kevin@koconnor.net>2017-10-09 20:54:13 -0400
commit5c1a2c75951c4a59f1bf2d3c82ca7447244513ad (patch)
tree037ca9d23f7b8c8880e2a9c5da5ee4295612048c
parentf703604b30958312e64a5b7fc74c606a2ececc15 (diff)
downloadseabios-5c1a2c75951c4a59f1bf2d3c82ca7447244513ad.tar.gz
xhci: Verify the device is still present in xhci_cmd_submit()
Make sure the USB device is still present before altering the xhci "slot" for it. It appears some controllers will hang if a request is sent to a port no longer connected. Signed-off-by: Kevin O'Connor <kevin@koconnor.net>
-rw-r--r--src/hw/usb-xhci.c11
1 files changed, 11 insertions, 0 deletions
diff --git a/src/hw/usb-xhci.c b/src/hw/usb-xhci.c
index 0f717c6c..08d1e321 100644
--- a/src/hw/usb-xhci.c
+++ b/src/hw/usb-xhci.c
@@ -780,6 +780,17 @@ static void xhci_trb_queue(struct xhci_ring *ring,
static int xhci_cmd_submit(struct usb_xhci_s *xhci, struct xhci_inctx *inctx
, u32 flags)
{
+ if (inctx) {
+ struct xhci_slotctx *slot = (void*)&inctx[1 << xhci->context64];
+ u32 port = ((slot->ctx[1] >> 16) & 0xff) - 1;
+ u32 portsc = readl(&xhci->pr[port].portsc);
+ if (!(portsc & XHCI_PORTSC_CCS)) {
+ // Device no longer connected?!
+ xhci_print_port_state(1, __func__, port, portsc);
+ return -1;
+ }
+ }
+
mutex_lock(&xhci->cmds->lock);
xhci_trb_queue(xhci->cmds, inctx, 0, flags);
xhci_doorbell(xhci, 0, 0);