[PATCH] USB: Fix bus-list root-hub race
There are a few places where the code enumerates through all the USB devices on all the buses, starting with each bus's root hub and working down. However a bus does not always have a root hub, and the code does not check that the root_hub pointer is non-NULL. This patch fixes the problem, using the usb_bus_list_lock semaphore to synchronize access when root hubs are added or removed. In addition it seemed like a good idea to minimize the time that a non-fully-configured root hub is accessible through the bus's pointer. So this patch delays setting the pointer and holds usb_bus_list_lock while configuring a root hub. It turned out that a bunch of things needed to be changed for all this to work: Check for NULL root_hub pointer in usb_device_read() and usb_find_device(). Pass the root-hub device as a separate argument to hcd_register_root(). Make usb_register_root_hub() acquire the usb_bus_list_lock and set the bus->root_hub pointer. For consistency's sake, move the place where the children[] pointer to a non-root-hub device gets stored as close as possible to where usb_new_device() is called. Make usb_disconnect() acquire the usb_bus_list_lock when removing a root hub. Change usb_hcd_pci_remove() and the non-PCI host drivers so that they call usb_disconnect() with a pointer to the bus's root_hub pointer, not a pointer to a temporary variable. Change all the host controller drivers not to store the root_hub pointer in the bus structure but instead to pass it as a new argument to hcd_register_root(). I made some attempt to update the hc_sl811 driver along with the rest, but it's pretty clear that driver won't work in the current framework. Among other things, it never reads the root hub's device descriptor. To what extent is the driver really supported? Signed-off-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Greg Kroah-Hartman <greg@kroah.com>
Showing
Please register or sign in to comment