Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 41330
b: refs/heads/master
c: c066475
h: refs/heads/master
v: v3
  • Loading branch information
Greg Kroah-Hartman committed Dec 1, 2006
1 parent a1ea58c commit 0d20c93
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 23 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 958e8741bf9ff5d0f0b82b7cef578e96c764a288
refs/heads/master: c066475e1fe3b3afbd613ddf5f1eca9be4fb6de0
15 changes: 15 additions & 0 deletions trunk/drivers/usb/core/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,21 @@ config USB_SUSPEND

If you are unsure about this, say N here.

config USB_MULTITHREAD_PROBE
bool "USB Multi-threaded probe (EXPERIMENTAL)"
depends on USB && EXPERIMENTAL
default n
help
Say Y here if you want the USB core to spawn a new thread for
every USB device that is probed. This can cause a small speedup
in boot times on systems with a lot of different USB devices.

This option should be safe to enable, but if any odd probing
problems are found, please disable it, or dynamically turn it
off in the /sys/module/usbcore/parameters/multithread_probe
file

When in doubt, say N.

config USB_OTG
bool
Expand Down
81 changes: 59 additions & 22 deletions trunk/drivers/usb/core/hub.c
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,16 @@ static DECLARE_WAIT_QUEUE_HEAD(khubd_wait);

static struct task_struct *khubd_task;

/* multithreaded probe logic */
static int multithread_probe =
#ifdef CONFIG_USB_MULTITHREAD_PROBE
1;
#else
0;
#endif
module_param(multithread_probe, bool, S_IRUGO);
MODULE_PARM_DESC(multithread_probe, "Run each USB device probe in a new thread");

/* cycle leds on hubs that aren't blinking for attention */
static int blinkenlights = 0;
module_param (blinkenlights, bool, S_IRUGO);
Expand Down Expand Up @@ -1238,29 +1248,17 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
static int __usb_port_suspend(struct usb_device *, int port1);
#endif

/**
* usb_new_device - perform initial device setup (usbcore-internal)
* @udev: newly addressed device (in ADDRESS state)
*
* This is called with devices which have been enumerated, but not yet
* configured. The device descriptor is available, but not descriptors
* for any device configuration. The caller must have locked either
* the parent hub (if udev is a normal device) or else the
* usb_bus_list_lock (if udev is a root hub). The parent's pointer to
* udev has already been installed, but udev is not yet visible through
* sysfs or other filesystem code.
*
* Returns 0 for success (device is configured and listed, with its
* interfaces, in sysfs); else a negative errno value.
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Only the hub driver or root-hub registrar should ever call this.
*/
int usb_new_device(struct usb_device *udev)
static int __usb_new_device(void *void_data)
{
struct usb_device *udev = void_data;
int err;

/* Lock ourself into memory in order to keep a probe sequence
* sleeping in a new thread from allowing us to be unloaded.
*/
if (!try_module_get(THIS_MODULE))
return -EINVAL;

err = usb_get_configuration(udev);
if (err < 0) {
dev_err(&udev->dev, "can't read configurations, error %d\n",
Expand Down Expand Up @@ -1356,13 +1354,52 @@ int usb_new_device(struct usb_device *udev)
goto fail;
}

return 0;
exit:
module_put(THIS_MODULE);
return err;

fail:
usb_set_device_state(udev, USB_STATE_NOTATTACHED);
return err;
goto exit;
}

/**
* usb_new_device - perform initial device setup (usbcore-internal)
* @udev: newly addressed device (in ADDRESS state)
*
* This is called with devices which have been enumerated, but not yet
* configured. The device descriptor is available, but not descriptors
* for any device configuration. The caller must have locked either
* the parent hub (if udev is a normal device) or else the
* usb_bus_list_lock (if udev is a root hub). The parent's pointer to
* udev has already been installed, but udev is not yet visible through
* sysfs or other filesystem code.
*
* The return value for this function depends on if the
* multithread_probe variable is set or not. If it's set, it will
* return a if the probe thread was successfully created or not. If the
* variable is not set, it will return if the device is configured
* properly or not. interfaces, in sysfs); else a negative errno value.
*
* This call is synchronous, and may not be used in an interrupt context.
*
* Only the hub driver or root-hub registrar should ever call this.
*/
int usb_new_device(struct usb_device *udev)
{
struct task_struct *probe_task;
int ret = 0;

if (multithread_probe) {
probe_task = kthread_run(__usb_new_device, udev,
"usb-probe-%s", udev->devnum);
if (IS_ERR(probe_task))
ret = PTR_ERR(probe_task);
} else
ret = __usb_new_device(udev);

return ret;
}

static int hub_port_status(struct usb_hub *hub, int port1,
u16 *status, u16 *change)
Expand Down

0 comments on commit 0d20c93

Please sign in to comment.