Commit 5106784c authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman

[PATCH] USB: Make hub driver use usb_kill_urb()

This is a rerun of as278, updated to match the current source.  It changes
the hub driver, replacing calls to synchronous usb_unlink_urb() with
usb_kill_urb() and removing the machinery formerly needed to synchronize
the status URB handler with the rest of the driver.
Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <greg@kroah.com>
parent 1d92d8c6
...@@ -234,18 +234,11 @@ static void hub_irq(struct urb *urb, struct pt_regs *regs) ...@@ -234,18 +234,11 @@ static void hub_irq(struct urb *urb, struct pt_regs *regs)
int i; int i;
unsigned long bits; unsigned long bits;
spin_lock(&hub_event_lock);
hub->urb_active = 0;
if (hub->urb_complete) { /* disconnect or rmmod */
complete(hub->urb_complete);
goto done;
}
switch (urb->status) { switch (urb->status) {
case -ENOENT: /* synchronous unlink */ case -ENOENT: /* synchronous unlink */
case -ECONNRESET: /* async unlink */ case -ECONNRESET: /* async unlink */
case -ESHUTDOWN: /* hardware going away */ case -ESHUTDOWN: /* hardware going away */
goto done; return;
default: /* presumably an error */ default: /* presumably an error */
/* Cause a hub reset after 10 consecutive errors */ /* Cause a hub reset after 10 consecutive errors */
...@@ -268,20 +261,17 @@ static void hub_irq(struct urb *urb, struct pt_regs *regs) ...@@ -268,20 +261,17 @@ static void hub_irq(struct urb *urb, struct pt_regs *regs)
hub->nerrors = 0; hub->nerrors = 0;
/* Something happened, let khubd figure it out */ /* Something happened, let khubd figure it out */
spin_lock(&hub_event_lock);
if (list_empty(&hub->event_list)) { if (list_empty(&hub->event_list)) {
list_add_tail(&hub->event_list, &hub_event_list); list_add_tail(&hub->event_list, &hub_event_list);
wake_up(&khubd_wait); wake_up(&khubd_wait);
} }
spin_unlock(&hub_event_lock);
resubmit: resubmit:
if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0 if ((status = usb_submit_urb (hub->urb, GFP_ATOMIC)) != 0
/* ENODEV means we raced disconnect() */ && status != -ENODEV && status != -EPERM)
&& status != -ENODEV)
dev_err (&hub->intf->dev, "resubmit --> %d\n", status); dev_err (&hub->intf->dev, "resubmit --> %d\n", status);
if (status == 0)
hub->urb_active = 1;
done:
spin_unlock(&hub_event_lock);
} }
/* USB 2.0 spec Section 11.24.2.3 */ /* USB 2.0 spec Section 11.24.2.3 */
...@@ -612,7 +602,6 @@ static int hub_configure(struct usb_hub *hub, ...@@ -612,7 +602,6 @@ static int hub_configure(struct usb_hub *hub,
message = "couldn't submit status urb"; message = "couldn't submit status urb";
goto fail; goto fail;
} }
hub->urb_active = 1;
/* Wake up khubd */ /* Wake up khubd */
wake_up(&khubd_wait); wake_up(&khubd_wait);
...@@ -640,7 +629,6 @@ static unsigned highspeed_hubs; ...@@ -640,7 +629,6 @@ static unsigned highspeed_hubs;
static void hub_disconnect(struct usb_interface *intf) static void hub_disconnect(struct usb_interface *intf)
{ {
struct usb_hub *hub = usb_get_intfdata (intf); struct usb_hub *hub = usb_get_intfdata (intf);
DECLARE_COMPLETION(urb_complete);
if (!hub) if (!hub)
return; return;
...@@ -649,12 +637,16 @@ static void hub_disconnect(struct usb_interface *intf) ...@@ -649,12 +637,16 @@ static void hub_disconnect(struct usb_interface *intf)
highspeed_hubs--; highspeed_hubs--;
usb_set_intfdata (intf, NULL); usb_set_intfdata (intf, NULL);
spin_lock_irq(&hub_event_lock);
hub->urb_complete = &urb_complete; if (hub->urb) {
usb_kill_urb(hub->urb);
usb_free_urb(hub->urb);
hub->urb = NULL;
}
/* Delete it and then reset it */ /* Delete it and then reset it */
spin_lock_irq(&hub_event_lock);
list_del_init(&hub->event_list); list_del_init(&hub->event_list);
spin_unlock_irq(&hub_event_lock); spin_unlock_irq(&hub_event_lock);
/* assuming we used keventd, it must quiesce too */ /* assuming we used keventd, it must quiesce too */
...@@ -663,14 +655,6 @@ static void hub_disconnect(struct usb_interface *intf) ...@@ -663,14 +655,6 @@ static void hub_disconnect(struct usb_interface *intf)
if (hub->has_indicators || hub->tt.hub) if (hub->has_indicators || hub->tt.hub)
flush_scheduled_work (); flush_scheduled_work ();
if (hub->urb) {
usb_unlink_urb(hub->urb);
if (hub->urb_active)
wait_for_completion(&urb_complete);
usb_free_urb(hub->urb);
hub->urb = NULL;
}
if (hub->descriptor) { if (hub->descriptor) {
kfree(hub->descriptor); kfree(hub->descriptor);
hub->descriptor = NULL; hub->descriptor = NULL;
...@@ -803,7 +787,7 @@ static int hub_reset(struct usb_hub *hub) ...@@ -803,7 +787,7 @@ static int hub_reset(struct usb_hub *hub)
/* Attempt to reset the hub */ /* Attempt to reset the hub */
if (hub->urb) if (hub->urb)
usb_unlink_urb(hub->urb); usb_kill_urb(hub->urb);
else else
return -1; return -1;
......
...@@ -188,8 +188,6 @@ extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe); ...@@ -188,8 +188,6 @@ extern void usb_hub_tt_clear_buffer (struct usb_device *dev, int pipe);
struct usb_hub { struct usb_hub {
struct usb_interface *intf; /* the "real" device */ struct usb_interface *intf; /* the "real" device */
struct urb *urb; /* for interrupt polling pipe */ struct urb *urb; /* for interrupt polling pipe */
struct completion *urb_complete; /* wait for urb to end */
unsigned int urb_active:1;
/* buffer for urb ... 1 bit each for hub and children, rounded up */ /* buffer for urb ... 1 bit each for hub and children, rounded up */
char (*buffer)[(USB_MAXCHILDREN + 1 + 7) / 8]; char (*buffer)[(USB_MAXCHILDREN + 1 + 7) / 8];
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment