aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/host/hwa-hc.c2
-rw-r--r--drivers/usb/wusbcore/wa-hc.h2
-rw-r--r--drivers/usb/wusbcore/wa-xfer.c26
3 files changed, 26 insertions, 4 deletions
diff --git a/drivers/usb/host/hwa-hc.c b/drivers/usb/host/hwa-hc.c
index ada0a52797b1..a4ec9e6c0f86 100644
--- a/drivers/usb/host/hwa-hc.c
+++ b/drivers/usb/host/hwa-hc.c
@@ -224,7 +224,7 @@ static int hwahc_op_urb_dequeue(struct usb_hcd *usb_hcd, struct urb *urb,
224 struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd); 224 struct wusbhc *wusbhc = usb_hcd_to_wusbhc(usb_hcd);
225 struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc); 225 struct hwahc *hwahc = container_of(wusbhc, struct hwahc, wusbhc);
226 226
227 return wa_urb_dequeue(&hwahc->wa, urb); 227 return wa_urb_dequeue(&hwahc->wa, urb, status);
228} 228}
229 229
230/* 230/*
diff --git a/drivers/usb/wusbcore/wa-hc.h b/drivers/usb/wusbcore/wa-hc.h
index e614f02f0cf2..5b6ae3a4a755 100644
--- a/drivers/usb/wusbcore/wa-hc.h
+++ b/drivers/usb/wusbcore/wa-hc.h
@@ -332,7 +332,7 @@ static inline int rpipe_avail_inc(struct wa_rpipe *rpipe)
332/* Transferring data */ 332/* Transferring data */
333extern int wa_urb_enqueue(struct wahc *, struct usb_host_endpoint *, 333extern int wa_urb_enqueue(struct wahc *, struct usb_host_endpoint *,
334 struct urb *, gfp_t); 334 struct urb *, gfp_t);
335extern int wa_urb_dequeue(struct wahc *, struct urb *); 335extern int wa_urb_dequeue(struct wahc *, struct urb *, int);
336extern void wa_handle_notif_xfer(struct wahc *, struct wa_notif_hdr *); 336extern void wa_handle_notif_xfer(struct wahc *, struct wa_notif_hdr *);
337 337
338 338
diff --git a/drivers/usb/wusbcore/wa-xfer.c b/drivers/usb/wusbcore/wa-xfer.c
index ed5abe87b049..5957e486591a 100644
--- a/drivers/usb/wusbcore/wa-xfer.c
+++ b/drivers/usb/wusbcore/wa-xfer.c
@@ -282,6 +282,7 @@ static void wa_xfer_giveback(struct wa_xfer *xfer)
282 282
283 spin_lock_irqsave(&xfer->wa->xfer_list_lock, flags); 283 spin_lock_irqsave(&xfer->wa->xfer_list_lock, flags);
284 list_del_init(&xfer->list_node); 284 list_del_init(&xfer->list_node);
285 usb_hcd_unlink_urb_from_ep(&(xfer->wa->wusb->usb_hcd), xfer->urb);
285 spin_unlock_irqrestore(&xfer->wa->xfer_list_lock, flags); 286 spin_unlock_irqrestore(&xfer->wa->xfer_list_lock, flags);
286 /* FIXME: segmentation broken -- kills DWA */ 287 /* FIXME: segmentation broken -- kills DWA */
287 wusbhc_giveback_urb(xfer->wa->wusb, xfer->urb, xfer->result); 288 wusbhc_giveback_urb(xfer->wa->wusb, xfer->urb, xfer->result);
@@ -1730,6 +1731,12 @@ int wa_urb_enqueue(struct wahc *wa, struct usb_host_endpoint *ep,
1730 dump_stack(); 1731 dump_stack();
1731 } 1732 }
1732 1733
1734 spin_lock_irqsave(&wa->xfer_list_lock, my_flags);
1735 result = usb_hcd_link_urb_to_ep(&(wa->wusb->usb_hcd), urb);
1736 spin_unlock_irqrestore(&wa->xfer_list_lock, my_flags);
1737 if (result < 0)
1738 goto error_link_urb;
1739
1733 result = -ENOMEM; 1740 result = -ENOMEM;
1734 xfer = kzalloc(sizeof(*xfer), gfp); 1741 xfer = kzalloc(sizeof(*xfer), gfp);
1735 if (xfer == NULL) 1742 if (xfer == NULL)
@@ -1769,6 +1776,9 @@ int wa_urb_enqueue(struct wahc *wa, struct usb_host_endpoint *ep,
1769 __func__, result); 1776 __func__, result);
1770 wa_put(xfer->wa); 1777 wa_put(xfer->wa);
1771 wa_xfer_put(xfer); 1778 wa_xfer_put(xfer);
1779 spin_lock_irqsave(&wa->xfer_list_lock, my_flags);
1780 usb_hcd_unlink_urb_from_ep(&(wa->wusb->usb_hcd), urb);
1781 spin_unlock_irqrestore(&wa->xfer_list_lock, my_flags);
1772 return result; 1782 return result;
1773 } 1783 }
1774 } 1784 }
@@ -1777,6 +1787,10 @@ int wa_urb_enqueue(struct wahc *wa, struct usb_host_endpoint *ep,
1777error_dequeued: 1787error_dequeued:
1778 kfree(xfer); 1788 kfree(xfer);
1779error_kmalloc: 1789error_kmalloc:
1790 spin_lock_irqsave(&wa->xfer_list_lock, my_flags);
1791 usb_hcd_unlink_urb_from_ep(&(wa->wusb->usb_hcd), urb);
1792 spin_unlock_irqrestore(&wa->xfer_list_lock, my_flags);
1793error_link_urb:
1780 return result; 1794 return result;
1781} 1795}
1782EXPORT_SYMBOL_GPL(wa_urb_enqueue); 1796EXPORT_SYMBOL_GPL(wa_urb_enqueue);
@@ -1799,7 +1813,7 @@ EXPORT_SYMBOL_GPL(wa_urb_enqueue);
1799 * asynch request] and then make sure we cancel each segment. 1813 * asynch request] and then make sure we cancel each segment.
1800 * 1814 *
1801 */ 1815 */
1802int wa_urb_dequeue(struct wahc *wa, struct urb *urb) 1816int wa_urb_dequeue(struct wahc *wa, struct urb *urb, int status)
1803{ 1817{
1804 unsigned long flags, flags2; 1818 unsigned long flags, flags2;
1805 struct wa_xfer *xfer; 1819 struct wa_xfer *xfer;
@@ -1807,6 +1821,14 @@ int wa_urb_dequeue(struct wahc *wa, struct urb *urb)
1807 struct wa_rpipe *rpipe; 1821 struct wa_rpipe *rpipe;
1808 unsigned cnt, done = 0, xfer_abort_pending; 1822 unsigned cnt, done = 0, xfer_abort_pending;
1809 unsigned rpipe_ready = 0; 1823 unsigned rpipe_ready = 0;
1824 int result;
1825
1826 /* check if it is safe to unlink. */
1827 spin_lock_irqsave(&wa->xfer_list_lock, flags);
1828 result = usb_hcd_check_unlink_urb(&(wa->wusb->usb_hcd), urb, status);
1829 spin_unlock_irqrestore(&wa->xfer_list_lock, flags);
1830 if (result)
1831 return result;
1810 1832
1811 xfer = urb->hcpriv; 1833 xfer = urb->hcpriv;
1812 if (xfer == NULL) { 1834 if (xfer == NULL) {
@@ -2172,7 +2194,7 @@ error_complete:
2172 2194
2173error_bad_seg: 2195error_bad_seg:
2174 spin_unlock_irqrestore(&xfer->lock, flags); 2196 spin_unlock_irqrestore(&xfer->lock, flags);
2175 wa_urb_dequeue(wa, xfer->urb); 2197 wa_urb_dequeue(wa, xfer->urb, -ENOENT);
2176 if (printk_ratelimit()) 2198 if (printk_ratelimit())
2177 dev_err(dev, "xfer %p#%u: bad segment\n", xfer, seg_idx); 2199 dev_err(dev, "xfer %p#%u: bad segment\n", xfer, seg_idx);
2178 if (edc_inc(&wa->dti_edc, EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) { 2200 if (edc_inc(&wa->dti_edc, EDC_MAX_ERRORS, EDC_ERROR_TIMEFRAME)) {