diff options
Diffstat (limited to 'drivers/usb')
-rw-r--r-- | drivers/usb/host/hwa-hc.c | 2 | ||||
-rw-r--r-- | drivers/usb/wusbcore/wa-hc.h | 2 | ||||
-rw-r--r-- | drivers/usb/wusbcore/wa-xfer.c | 26 |
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 */ |
333 | extern int wa_urb_enqueue(struct wahc *, struct usb_host_endpoint *, | 333 | extern int wa_urb_enqueue(struct wahc *, struct usb_host_endpoint *, |
334 | struct urb *, gfp_t); | 334 | struct urb *, gfp_t); |
335 | extern int wa_urb_dequeue(struct wahc *, struct urb *); | 335 | extern int wa_urb_dequeue(struct wahc *, struct urb *, int); |
336 | extern void wa_handle_notif_xfer(struct wahc *, struct wa_notif_hdr *); | 336 | extern 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, | |||
1777 | error_dequeued: | 1787 | error_dequeued: |
1778 | kfree(xfer); | 1788 | kfree(xfer); |
1779 | error_kmalloc: | 1789 | error_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); | ||
1793 | error_link_urb: | ||
1780 | return result; | 1794 | return result; |
1781 | } | 1795 | } |
1782 | EXPORT_SYMBOL_GPL(wa_urb_enqueue); | 1796 | EXPORT_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 | */ |
1802 | int wa_urb_dequeue(struct wahc *wa, struct urb *urb) | 1816 | int 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 | ||
2173 | error_bad_seg: | 2195 | error_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)) { |