aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/staging/usbip/vhci.h3
-rw-r--r--drivers/staging/usbip/vhci_hcd.c24
-rw-r--r--drivers/staging/usbip/vhci_rx.c15
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);
119void vhci_rx_loop(struct usbip_task *ut); 119void vhci_rx_loop(struct usbip_task *ut);
120void vhci_tx_loop(struct usbip_task *ut); 120void vhci_tx_loop(struct usbip_task *ut);
121 121
122struct 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
124static inline struct vhci_device *port_to_vdev(__u32 port) 127static 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
812static void vhci_device_unlink_cleanup(struct vhci_device *vdev) 811static 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 */
27static struct urb *pickup_urb_and_free_priv(struct vhci_device *vdev, 27struct 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