#define HUB_DEBOUNCE_STEP 25
#define HUB_DEBOUNCE_STABLE 100
-
+static void hub_release(struct kref *kref);
static int usb_reset_and_verify_device(struct usb_device *udev);
static inline char *portspeed(int portstatus)
unsigned delay;
/* Continue a partial initialization */
- if (type == HUB_INIT2)
- goto init2;
- if (type == HUB_INIT3)
+ if (type == HUB_INIT2 || type == HUB_INIT3) {
+ down(&hub->intfdev->sem);
+
+ /* Was the hub disconnected while we were waiting? */
+ if (hub->disconnected) {
+ up(&hub->intfdev->sem);
+ kref_put(&hub->kref, hub_release);
+ return;
+ }
+ if (type == HUB_INIT2)
+ goto init2;
goto init3;
+ }
+ kref_get(&hub->kref);
/* After a resume, port power should still be on.
* For any other type of activation, turn it on.
PREPARE_DELAYED_WORK(&hub->init_work, hub_init_func3);
schedule_delayed_work(&hub->init_work,
msecs_to_jiffies(delay));
+ up(&hub->intfdev->sem);
return; /* Continues at init3: below */
} else {
msleep(delay);
/* Scan all ports that need attention */
kick_khubd(hub);
+
+ if (type == HUB_INIT2 || type == HUB_INIT3)
+ up(&hub->intfdev->sem);
+
+ kref_put(&hub->kref, hub_release);
}
/* Implement the continuations for the delays above */