From e4ab05df573834b8c70d19db426b7d6286782c1d Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Wed, 16 Sep 2009 16:42:30 -0700 Subject: USB: xhci: Stop debugging polling loop when HC dies. If the host controller card is removed from the system, stop the timer function to debug the xHCI rings. Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hcd.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'drivers/usb/host/xhci-hcd.c') diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c index 99911e727e0..8719a3f6851 100644 --- a/drivers/usb/host/xhci-hcd.c +++ b/drivers/usb/host/xhci-hcd.c @@ -335,6 +335,12 @@ void xhci_event_ring_work(unsigned long arg) spin_lock_irqsave(&xhci->lock, flags); temp = xhci_readl(xhci, &xhci->op_regs->status); xhci_dbg(xhci, "op reg status = 0x%x\n", temp); + if (temp == 0xffffffff) { + xhci_dbg(xhci, "HW died, polling stopped.\n"); + spin_unlock_irqrestore(&xhci->lock, flags); + return; + } + temp = xhci_readl(xhci, &xhci->ir_set->irq_pending); xhci_dbg(xhci, "ir_set 0 pending = 0x%x\n", temp); xhci_dbg(xhci, "No-op commands handled = %d\n", xhci->noops_handled); -- cgit v1.2.3-70-g09d2 From e34b2fbf28741310d1d59a217d34e050ce7867e8 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Mon, 28 Sep 2009 17:21:37 -0700 Subject: USB: xhci: Handle canceled URBs when HC dies. When the host controller dies (e.g. it is removed from a PCI card slot), the xHCI driver cannot expect commands to complete. The buggy code this patch fixes would mark an URB as canceled and then expect the URB to be completed when the stop endpoint command completed. That would never happen if the host controller was dead, so the USB core would just hang in the disconnect code. If the host controller died, and the driver asks to cancel an URB, free any structures associated with that URB and immediately give it back. Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hcd.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'drivers/usb/host/xhci-hcd.c') diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c index 8719a3f6851..592e742c5f3 100644 --- a/drivers/usb/host/xhci-hcd.c +++ b/drivers/usb/host/xhci-hcd.c @@ -782,6 +782,7 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) { unsigned long flags; int ret; + u32 temp; struct xhci_hcd *xhci; struct xhci_td *td; unsigned int ep_index; @@ -794,6 +795,17 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) ret = usb_hcd_check_unlink_urb(hcd, urb, status); if (ret || !urb->hcpriv) goto done; + temp = xhci_readl(xhci, &xhci->op_regs->status); + if (temp == 0xffffffff) { + xhci_dbg(xhci, "HW died, freeing TD.\n"); + td = (struct xhci_td *) urb->hcpriv; + + usb_hcd_unlink_urb_from_ep(hcd, urb); + spin_unlock_irqrestore(&xhci->lock, flags); + usb_hcd_giveback_urb(xhci_to_hcd(xhci), urb, -ESHUTDOWN); + kfree(td); + return ret; + } xhci_dbg(xhci, "Cancel URB %p\n", urb); xhci_dbg(xhci, "Event ring:\n"); -- cgit v1.2.3-70-g09d2 From c526d0d4fc9707816b407d2d3336267d3271db2b Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Wed, 16 Sep 2009 16:42:39 -0700 Subject: USB: xhci: Don't wait for a disable slot cmd when HC dies. When the host controller dies or is removed while a device is plugged in, the USB core will attempt to deallocate the struct usb_device. That will call into xhci_free_dev(). This function used to attempt to submit a disable slot command to the host controller and clean up the device structures when that command returned. Change xhci_free_dev() to skip the command submission and just free the memory if the host controller died. Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hcd.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'drivers/usb/host/xhci-hcd.c') diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c index 592e742c5f3..d61c49f90f4 100644 --- a/drivers/usb/host/xhci-hcd.c +++ b/drivers/usb/host/xhci-hcd.c @@ -1428,11 +1428,20 @@ void xhci_free_dev(struct usb_hcd *hcd, struct usb_device *udev) { struct xhci_hcd *xhci = hcd_to_xhci(hcd); unsigned long flags; + u32 state; if (udev->slot_id == 0) return; spin_lock_irqsave(&xhci->lock, flags); + /* Don't disable the slot if the host controller is dead. */ + state = xhci_readl(xhci, &xhci->op_regs->status); + if (state == 0xffffffff) { + xhci_free_virt_device(xhci, udev->slot_id); + spin_unlock_irqrestore(&xhci->lock, flags); + return; + } + if (xhci_queue_slot_control(xhci, TRB_DISABLE_SLOT, udev->slot_id)) { spin_unlock_irqrestore(&xhci->lock, flags); xhci_dbg(xhci, "FIXME: allocate a command ring segment\n"); -- cgit v1.2.3-70-g09d2 From 0a023c6cf10c63d2ce68a2816d90c2f0f1ad2763 Mon Sep 17 00:00:00 2001 From: Sarah Sharp Date: Fri, 18 Sep 2009 08:55:12 -0700 Subject: USB: xhci: Fix dropping endpoints from the xHC schedule. When an endpoint is to be dropped from the hardware bandwidth schedule, we want to clear its add flag. Signed-off-by: Sarah Sharp Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'drivers/usb/host/xhci-hcd.c') diff --git a/drivers/usb/host/xhci-hcd.c b/drivers/usb/host/xhci-hcd.c index d61c49f90f4..932f9993848 100644 --- a/drivers/usb/host/xhci-hcd.c +++ b/drivers/usb/host/xhci-hcd.c @@ -895,7 +895,7 @@ int xhci_drop_endpoint(struct usb_hcd *hcd, struct usb_device *udev, ctrl_ctx->drop_flags |= drop_flag; new_drop_flags = ctrl_ctx->drop_flags; - ctrl_ctx->add_flags = ~drop_flag; + ctrl_ctx->add_flags &= ~drop_flag; new_add_flags = ctrl_ctx->add_flags; last_ctx = xhci_last_valid_endpoint(ctrl_ctx->add_flags); -- cgit v1.2.3-70-g09d2