staging: usbip: vhci: give back URBs from in-flight unlink requests

If we never received a RET_UNLINK because the TCP
connection broke the pending URBs still need to be
unlinked and given back.

Previously processes would be stuck trying to kill
the URB even after the device was detached.

Signed-off-by: Max Vozeler <max@vozeler.com>
Tested-by: Mark Wehby <MWehby@luxotticaRetail.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by Max Vozeler and committed by Greg Kroah-Hartman b92a5e23 7606ee8a

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