diff options
-rw-r--r-- | drivers/staging/usbip/vhci.h | 3 | ||||
-rw-r--r-- | drivers/staging/usbip/vhci_hcd.c | 24 | ||||
-rw-r--r-- | drivers/staging/usbip/vhci_rx.c | 15 |
3 files changed, 35 insertions, 7 deletions
diff --git a/drivers/staging/usbip/vhci.h b/drivers/staging/usbip/vhci.h index 41a1fe5138f..2cfd00ec116 100644 --- a/drivers/staging/usbip/vhci.h +++ b/drivers/staging/usbip/vhci.h | |||
@@ -119,6 +119,9 @@ void rh_port_disconnect(int rhport); | |||
119 | void vhci_rx_loop(struct usbip_task *ut); | 119 | void vhci_rx_loop(struct usbip_task *ut); |
120 | void vhci_tx_loop(struct usbip_task *ut); | 120 | void vhci_tx_loop(struct usbip_task *ut); |
121 | 121 | ||
122 | struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, | ||
123 | __u32 seqnum); | ||
124 | |||
122 | #define hardware (&the_controller->pdev.dev) | 125 | #define hardware (&the_controller->pdev.dev) |
123 | 126 | ||
124 | static inline struct vhci_device *port_to_vdev(__u32 port) | 127 | static inline struct vhci_device *port_to_vdev(__u32 port) |
diff --git a/drivers/staging/usbip/vhci_hcd.c b/drivers/staging/usbip/vhci_hcd.c index 5f1e2b0a628..3a22f65b66d 100644 --- a/drivers/staging/usbip/vhci_hcd.c +++ b/drivers/staging/usbip/vhci_hcd.c | |||
@@ -808,7 +808,6 @@ static int vhci_urb_dequeue(struct usb_hcd *hcd, struct urb *urb, int status) | |||
808 | return 0; | 808 | return 0; |
809 | } | 809 | } |
810 | 810 | ||
811 | |||
812 | static void vhci_device_unlink_cleanup(struct vhci_device *vdev) | 811 | static void vhci_device_unlink_cleanup(struct vhci_device *vdev) |
813 | { | 812 | { |
814 | struct vhci_unlink *unlink, *tmp; | 813 | struct vhci_unlink *unlink, *tmp; |
@@ -816,11 +815,34 @@ static void vhci_device_unlink_cleanup(struct vhci_device *vdev) | |||
816 | spin_lock(&vdev->priv_lock); | 815 | spin_lock(&vdev->priv_lock); |
817 | 816 | ||
818 | list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) { | 817 | list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) { |
818 | usbip_uinfo("unlink cleanup tx %lu\n", unlink->unlink_seqnum); | ||
819 | list_del(&unlink->list); | 819 | list_del(&unlink->list); |
820 | kfree(unlink); | 820 | kfree(unlink); |
821 | } | 821 | } |
822 | 822 | ||
823 | list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) { | 823 | list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) { |
824 | struct urb *urb; | ||
825 | |||
826 | /* give back URB of unanswered unlink request */ | ||
827 | usbip_uinfo("unlink cleanup rx %lu\n", unlink->unlink_seqnum); | ||
828 | |||
829 | urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum); | ||
830 | if (!urb) { | ||
831 | usbip_uinfo("the urb (seqnum %lu) was already given back\n", | ||
832 | unlink->unlink_seqnum); | ||
833 | list_del(&unlink->list); | ||
834 | kfree(unlink); | ||
835 | continue; | ||
836 | } | ||
837 | |||
838 | urb->status = -ENODEV; | ||
839 | |||
840 | spin_lock(&the_controller->lock); | ||
841 | usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb); | ||
842 | spin_unlock(&the_controller->lock); | ||
843 | |||
844 | usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status); | ||
845 | |||
824 | list_del(&unlink->list); | 846 | list_del(&unlink->list); |
825 | kfree(unlink); | 847 | kfree(unlink); |
826 | } | 848 | } |
diff --git a/drivers/staging/usbip/vhci_rx.c b/drivers/staging/usbip/vhci_rx.c index 8147d7202b2..bdbedd25690 100644 --- a/drivers/staging/usbip/vhci_rx.c +++ b/drivers/staging/usbip/vhci_rx.c | |||
@@ -23,16 +23,14 @@ | |||
23 | #include "vhci.h" | 23 | #include "vhci.h" |
24 | 24 | ||
25 | 25 | ||
26 | /* get URB from transmitted urb queue */ | 26 | /* get URB from transmitted urb queue. caller must hold vdev->priv_lock */ |
27 | static struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, | 27 | struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, |
28 | __u32 seqnum) | 28 | __u32 seqnum) |
29 | { | 29 | { |
30 | struct vhci_priv *priv, *tmp; | 30 | struct vhci_priv *priv, *tmp; |
31 | struct urb *urb = NULL; | 31 | struct urb *urb = NULL; |
32 | int status; | 32 | int status; |
33 | 33 | ||
34 | spin_lock(&vdev->priv_lock); | ||
35 | |||
36 | list_for_each_entry_safe(priv, tmp, &vdev->priv_rx, list) { | 34 | list_for_each_entry_safe(priv, tmp, &vdev->priv_rx, list) { |
37 | if (priv->seqnum == seqnum) { | 35 | if (priv->seqnum == seqnum) { |
38 | urb = priv->urb; | 36 | urb = priv->urb; |
@@ -63,8 +61,6 @@ static struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, | |||
63 | } | 61 | } |
64 | } | 62 | } |
65 | 63 | ||
66 | spin_unlock(&vdev->priv_lock); | ||
67 | |||
68 | return urb; | 64 | return urb; |
69 | } | 65 | } |
70 | 66 | ||
@@ -74,9 +70,11 @@ static void vhci_recv_ret_submit(struct vhci_device *vdev, | |||
74 | struct usbip_device *ud = &vdev->ud; | 70 | struct usbip_device *ud = &vdev->ud; |
75 | struct urb *urb; | 71 | struct urb *urb; |
76 | 72 | ||
73 | spin_lock(&vdev->priv_lock); | ||
77 | 74 | ||
78 | urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum); | 75 | urb = pickup_urb_and_free_priv(vdev, pdu->base.seqnum); |
79 | 76 | ||
77 | spin_unlock(&vdev->priv_lock); | ||
80 | 78 | ||
81 | if (!urb) { | 79 | if (!urb) { |
82 | usbip_uerr("cannot find a urb of seqnum %u\n", | 80 | usbip_uerr("cannot find a urb of seqnum %u\n", |
@@ -161,7 +159,12 @@ static void vhci_recv_ret_unlink(struct vhci_device *vdev, | |||
161 | return; | 159 | return; |
162 | } | 160 | } |
163 | 161 | ||
162 | spin_lock(&vdev->priv_lock); | ||
163 | |||
164 | urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum); | 164 | urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum); |
165 | |||
166 | spin_unlock(&vdev->priv_lock); | ||
167 | |||
165 | if (!urb) { | 168 | if (!urb) { |
166 | /* | 169 | /* |
167 | * I get the result of a unlink request. But, it seems that I | 170 | * I get the result of a unlink request. But, it seems that I |