diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-08-27 00:10:06 +0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-08-27 00:10:06 +0400 |
commit | 7a54f5e19f90342340112939ef592fff20fc370c (patch) | |
tree | bbd73403916cfc404da1ca5401dcd1d9239e22be /drivers/usb/host/xhci.c | |
parent | efe45ab1ee04551936f8343bd4ca1ff02ffc23bb (diff) | |
parent | c96fbdd0ab97235f930ebf24b38fa42a2e3458cf (diff) | |
download | linux-7a54f5e19f90342340112939ef592fff20fc370c.tar.xz |
Merge branch 'usb-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6
* 'usb-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/usb-2.6: (30 commits)
USB: ftdi_sio: add Calao reference board support
USB option driver K3765/K4505 avoid CDC_DATA interface
USB: option: add YUGA device id to driver
usb: s5p-ehci: fix a NULL pointer deference
USB: EHCI: Do not rely on PORT_SUSPEND to stop USB resuming in ehci_bus_resume().
USB option driver add PID of Huawei Vodafone K4605
USB option driver add PID of Huawei Vodafone K3806
xhci: Handle zero-length isochronous packets.
USB: Avoid NULL pointer deref in usb_hcd_alloc_bandwidth.
usb: musb: gadget: fix error path
usb: gadget: f_phonet: unlock in error case
usb: musb: blackfin: include prefetch head file
usb: musb: tusb6010: fix compilation
usb: gadget: renesas_usbhs: fix DMA build by including dma-mapping.h
usb: musb: cppi: fix build errors due to DBG and missing musb variable
usb: musb: ux500: replace missing DBG with dev_dbg
usb: musb: ux500: set dma config for both src and dst
usb: musb: fix oops on musb_gadget_pullup
usb: host: ehci-omap: fix .remove and failure handling path of .probe(v1)
usb: gadget: hid: don't STALL when processing a HID Descriptor request
...
Diffstat (limited to 'drivers/usb/host/xhci.c')
-rw-r--r-- | drivers/usb/host/xhci.c | 28 |
1 files changed, 24 insertions, 4 deletions
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c index 1c4432d8fc10..3a0f695138f4 100644 --- a/drivers/usb/host/xhci.c +++ b/drivers/usb/host/xhci.c @@ -1085,8 +1085,11 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) if (urb->dev->speed == USB_SPEED_FULL) { ret = xhci_check_maxpacket(xhci, slot_id, ep_index, urb); - if (ret < 0) + if (ret < 0) { + xhci_urb_free_priv(xhci, urb_priv); + urb->hcpriv = NULL; return ret; + } } /* We have a spinlock and interrupts disabled, so we must pass @@ -1097,6 +1100,8 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) goto dying; ret = xhci_queue_ctrl_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index); + if (ret) + goto free_priv; spin_unlock_irqrestore(&xhci->lock, flags); } else if (usb_endpoint_xfer_bulk(&urb->ep->desc)) { spin_lock_irqsave(&xhci->lock, flags); @@ -1117,6 +1122,8 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) ret = xhci_queue_bulk_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index); } + if (ret) + goto free_priv; spin_unlock_irqrestore(&xhci->lock, flags); } else if (usb_endpoint_xfer_int(&urb->ep->desc)) { spin_lock_irqsave(&xhci->lock, flags); @@ -1124,6 +1131,8 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) goto dying; ret = xhci_queue_intr_tx(xhci, GFP_ATOMIC, urb, slot_id, ep_index); + if (ret) + goto free_priv; spin_unlock_irqrestore(&xhci->lock, flags); } else { spin_lock_irqsave(&xhci->lock, flags); @@ -1131,18 +1140,22 @@ int xhci_urb_enqueue(struct usb_hcd *hcd, struct urb *urb, gfp_t mem_flags) goto dying; ret = xhci_queue_isoc_tx_prepare(xhci, GFP_ATOMIC, urb, slot_id, ep_index); + if (ret) + goto free_priv; spin_unlock_irqrestore(&xhci->lock, flags); } exit: return ret; dying: - xhci_urb_free_priv(xhci, urb_priv); - urb->hcpriv = NULL; xhci_dbg(xhci, "Ep 0x%x: URB %p submitted for " "non-responsive xHCI host.\n", urb->ep->desc.bEndpointAddress, urb); + ret = -ESHUTDOWN; +free_priv: + xhci_urb_free_priv(xhci, urb_priv); + urb->hcpriv = NULL; spin_unlock_irqrestore(&xhci->lock, flags); - return -ESHUTDOWN; + return ret; } /* Get the right ring for the given URB. @@ -1239,6 +1252,13 @@ int xhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) if (temp == 0xffffffff || (xhci->xhc_state & XHCI_STATE_HALTED)) { xhci_dbg(xhci, "HW died, freeing TD.\n"); urb_priv = urb->hcpriv; + for (i = urb_priv->td_cnt; i < urb_priv->length; i++) { + td = urb_priv->td[i]; + if (!list_empty(&td->td_list)) + list_del_init(&td->td_list); + if (!list_empty(&td->cancelled_td_list)) + list_del_init(&td->cancelled_td_list); + } usb_hcd_unlink_urb_from_ep(hcd, urb); spin_unlock_irqrestore(&xhci->lock, flags); |