Patch 2.6.32.28 to 2.6.32.32
/drivers/staging/usbip/vhci_hcd.c
blob:1c173195c5162d3671ebd70bb911131e3d8a4241 -> blob:c2018029059c5ce35b17a1965b443f586c1ceec7
--- drivers/staging/usbip/vhci_hcd.c
+++ drivers/staging/usbip/vhci_hcd.c
@@ -137,6 +137,8 @@ void rh_port_connect(int rhport, enum us
* the_controller->vdev[rhport].ud.status = VDEV_CONNECT;
* spin_unlock(&the_controller->vdev[rhport].ud.lock); */
+ the_controller->pending_port = rhport;
+
spin_unlock_irqrestore(&the_controller->lock, flags);
usb_hcd_poll_rh_status(vhci_to_hcd(the_controller));
@@ -556,7 +558,6 @@ static int vhci_urb_enqueue(struct usb_h
struct device *dev = &urb->dev->dev;
int ret = 0;
unsigned long flags;
- struct vhci_device *vdev;
usbip_dbg_vhci_hc("enter, usb_hcd %p urb %p mem_flags %d\n",
hcd, urb, mem_flags);
@@ -572,18 +573,6 @@ static int vhci_urb_enqueue(struct usb_h
return urb->status;
}
- vdev = port_to_vdev(urb->dev->portnum-1);
-
- /* refuse enqueue for dead connection */
- spin_lock(&vdev->ud.lock);
- if (vdev->ud.status == VDEV_ST_NULL || vdev->ud.status == VDEV_ST_ERROR) {
- usbip_uerr("enqueue for inactive port %d\n", vdev->rhport);
- spin_unlock(&vdev->ud.lock);
- spin_unlock_irqrestore(&the_controller->lock, flags);
- return -ENODEV;
- }
- spin_unlock(&vdev->ud.lock);
-
ret = usb_hcd_link_urb_to_ep(hcd, urb);
if (ret)
goto no_need_unlink;
@@ -602,6 +591,8 @@ static int vhci_urb_enqueue(struct usb_h
__u8 type = usb_pipetype(urb->pipe);
struct usb_ctrlrequest *ctrlreq =
(struct usb_ctrlrequest *) urb->setup_packet;
+ struct vhci_device *vdev =
+ port_to_vdev(the_controller->pending_port);
if (type != PIPE_CONTROL || !ctrlreq) {
dev_err(dev, "invalid request to devnum 0\n");
@@ -615,9 +606,7 @@ static int vhci_urb_enqueue(struct usb_h
dev_info(dev, "SetAddress Request (%d) to port %d\n",
ctrlreq->wValue, vdev->rhport);
- if (vdev->udev)
- usb_put_dev(vdev->udev);
- vdev->udev = usb_get_dev(urb->dev);
+ vdev->udev = urb->dev;
spin_lock(&vdev->ud.lock);
vdev->ud.status = VDEV_ST_USED;
@@ -637,9 +626,8 @@ static int vhci_urb_enqueue(struct usb_h
"Get_Descriptor to device 0 "
"(get max pipe size)\n");
- if (vdev->udev)
- usb_put_dev(vdev->udev);
- vdev->udev = usb_get_dev(urb->dev);
+ /* FIXME: reference count? (usb_get_dev()) */
+ vdev->udev = urb->dev;
goto out;
default:
@@ -810,12 +798,27 @@ static int vhci_urb_dequeue(struct usb_h
spin_unlock_irqrestore(&vdev->priv_lock, flags2);
}
+
+ if (!vdev->ud.tcp_socket) {
+ /* tcp connection is closed */
+ usbip_uinfo("vhci_hcd: vhci_urb_dequeue() gives back urb %p\n",
+ urb);
+
+ usb_hcd_unlink_urb_from_ep(hcd, urb);
+
+ spin_unlock_irqrestore(&the_controller->lock, flags);
+ usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb,
+ urb->status);
+ spin_lock_irqsave(&the_controller->lock, flags);
+ }
+
spin_unlock_irqrestore(&the_controller->lock, flags);
usbip_dbg_vhci_hc("leave\n");
return 0;
}
+
static void vhci_device_unlink_cleanup(struct vhci_device *vdev)
{
struct vhci_unlink *unlink, *tmp;
@@ -823,34 +826,11 @@ static void vhci_device_unlink_cleanup(s
spin_lock(&vdev->priv_lock);
list_for_each_entry_safe(unlink, tmp, &vdev->unlink_tx, list) {
- usbip_uinfo("unlink cleanup tx %lu\n", unlink->unlink_seqnum);
list_del(&unlink->list);
kfree(unlink);
}
list_for_each_entry_safe(unlink, tmp, &vdev->unlink_rx, list) {
- struct urb *urb;
-
- /* give back URB of unanswered unlink request */
- usbip_uinfo("unlink cleanup rx %lu\n", unlink->unlink_seqnum);
-
- urb = pickup_urb_and_free_priv(vdev, unlink->unlink_seqnum);
- if (!urb) {
- usbip_uinfo("the urb (seqnum %lu) was already given back\n",
- unlink->unlink_seqnum);
- list_del(&unlink->list);
- kfree(unlink);
- continue;
- }
-
- urb->status = -ENODEV;
-
- spin_lock(&the_controller->lock);
- usb_hcd_unlink_urb_from_ep(vhci_to_hcd(the_controller), urb);
- spin_unlock(&the_controller->lock);
-
- usb_hcd_giveback_urb(vhci_to_hcd(the_controller), urb, urb->status);
-
list_del(&unlink->list);
kfree(unlink);
}
@@ -920,10 +900,6 @@ static void vhci_device_reset(struct usb
vdev->speed = 0;
vdev->devid = 0;
- if (vdev->udev)
- usb_put_dev(vdev->udev);
- vdev->udev = NULL;
-
ud->tcp_socket = NULL;
ud->status = VDEV_ST_NULL;