Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9ad3d6cc authored by Alan Stern's avatar Alan Stern Committed by Greg Kroah-Hartman
Browse files

[PATCH] USB: Remove USB private semaphore



This patch (as605) removes the private udev->serialize semaphore,
relying instead on the locking provided by the embedded struct device's
semaphore.  The changes are confined to the core, except that the
usb_trylock_device routine now uses the return convention of
down_trylock rather than down_read_trylock (they return opposite values
for no good reason).

A couple of other associated changes are included as well:

	Now that we aren't concerned about HCDs that avoid using the
	hcd glue layer, usb_disconnect no longer needs to acquire the
	usb_bus_lock -- that can be done by usb_remove_hcd where it
	belongs.

	Devices aren't locked over the same scope of code in
	usb_new_device and hub_port_connect_change as they used to be.
	This shouldn't cause any trouble.

Along with the preceding driver core patch, this needs a lot of testing.

Signed-off-by: default avatarAlan Stern <stern@rowland.harvard.edu>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
parent 75318d2d
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -545,10 +545,10 @@ static ssize_t usb_device_dump(char __user **buffer, size_t *nbytes, loff_t *ski
		struct usb_device *childdev = usbdev->children[chix];

		if (childdev) {
			down(&childdev->serialize);
			usb_lock_device(childdev);
			ret = usb_device_dump(buffer, nbytes, skip_bytes, file_offset, childdev,
					bus, level + 1, chix, ++cnt);
			up(&childdev->serialize);
			usb_unlock_device(childdev);
			if (ret == -EFAULT)
				return total_written;
			total_written += ret;
+0 −2
Original line number Diff line number Diff line
@@ -1349,9 +1349,7 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
	/* let kernel drivers try to (re)bind to the interface */
	case USBDEVFS_CONNECT:
		usb_unlock_device(ps->dev);
		usb_lock_all_devices();
		bus_rescan_devices(intf->dev.bus);
		usb_unlock_all_devices();
		usb_lock_device(ps->dev);
		break;

+0 −4
Original line number Diff line number Diff line
@@ -432,9 +432,7 @@ int usb_register_driver(struct usb_driver *new_driver, struct module *owner)
	spin_lock_init(&new_driver->dynids.lock);
	INIT_LIST_HEAD(&new_driver->dynids.list);

	usb_lock_all_devices();
	retval = driver_register(&new_driver->driver);
	usb_unlock_all_devices();

	if (!retval) {
		pr_info("%s: registered new driver %s\n",
@@ -465,11 +463,9 @@ void usb_deregister(struct usb_driver *driver)
{
	pr_info("%s: deregistering driver %s\n", usbcore_name, driver->name);

	usb_lock_all_devices();
	usb_remove_newid_file(driver);
	usb_free_dynids(driver);
	driver_unregister(&driver->driver);
	usb_unlock_all_devices();

	usbfs_update_special();
}
+3 −2
Original line number Diff line number Diff line
@@ -857,9 +857,7 @@ static int register_root_hub (struct usb_device *usb_dev,
		return (retval < 0) ? retval : -EMSGSIZE;
	}

	usb_lock_device (usb_dev);
	retval = usb_new_device (usb_dev);
	usb_unlock_device (usb_dev);
	if (retval) {
		usb_dev->bus->root_hub = NULL;
		dev_err (parent_dev, "can't register root hub for %s, %d\n",
@@ -1891,7 +1889,10 @@ void usb_remove_hcd(struct usb_hcd *hcd)
	spin_lock_irq (&hcd_root_hub_lock);
	hcd->rh_registered = 0;
	spin_unlock_irq (&hcd_root_hub_lock);

	down(&usb_bus_list_lock);
	usb_disconnect(&hcd->self.root_hub);
	up(&usb_bus_list_lock);

	hcd->poll_rh = 0;
	del_timer_sync(&hcd->rh_timer);
+18 −30
Original line number Diff line number Diff line
@@ -32,7 +32,7 @@
#include "hub.h"

/* Protect struct usb_device->state and ->children members
 * Note: Both are also protected by ->serialize, except that ->state can
 * Note: Both are also protected by ->dev.sem, except that ->state can
 * change to USB_STATE_NOTATTACHED even when the semaphore isn't held. */
static DEFINE_SPINLOCK(device_state_lock);

@@ -975,8 +975,8 @@ static int locktree(struct usb_device *udev)
			/* when everyone grabs locks top->bottom,
			 * non-overlapping work may be concurrent
			 */
			down(&udev->serialize);
			up(&hdev->serialize);
			usb_lock_device(udev);
			usb_unlock_device(hdev);
			return t + 1;
		}
	}
@@ -1132,15 +1132,9 @@ void usb_disconnect(struct usb_device **pdev)
	 * this quiesces everyting except pending urbs.
	 */
	usb_set_device_state(udev, USB_STATE_NOTATTACHED);
	dev_info (&udev->dev, "USB disconnect, address %d\n", udev->devnum);

	/* lock the bus list on behalf of HCDs unregistering their root hubs */
	if (!udev->parent) {
		down(&usb_bus_list_lock);
	usb_lock_device(udev);
	} else
		down(&udev->serialize);

	dev_info (&udev->dev, "USB disconnect, address %d\n", udev->devnum);

	/* Free up all the children before we remove this device */
	for (i = 0; i < USB_MAXCHILDREN; i++) {
@@ -1169,11 +1163,7 @@ void usb_disconnect(struct usb_device **pdev)
	*pdev = NULL;
	spin_unlock_irq(&device_state_lock);

	if (!udev->parent) {
	usb_unlock_device(udev);
		up(&usb_bus_list_lock);
	} else
		up(&udev->serialize);

	device_unregister(&udev->dev);
}
@@ -1243,8 +1233,8 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
 *
 * 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 udev and
 * either the parent hub (if udev is a normal device) or else the
 * 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.
@@ -1254,8 +1244,7 @@ static inline void show_string(struct usb_device *udev, char *id, char *string)
 *
 * This call is synchronous, and may not be used in an interrupt context.
 *
 * Only the hub driver should ever call this; root hub registration
 * uses it indirectly.
 * Only the hub driver or root-hub registrar should ever call this.
 */
int usb_new_device(struct usb_device *udev)
{
@@ -1364,6 +1353,8 @@ int usb_new_device(struct usb_device *udev)
	}
	usb_create_sysfs_dev_files (udev);

	usb_lock_device(udev);

	/* choose and set the configuration. that registers the interfaces
	 * with the driver core, and lets usb device drivers bind to them.
	 */
@@ -1385,6 +1376,8 @@ int usb_new_device(struct usb_device *udev)
	/* USB device state == configured ... usable */
	usb_notify_add_device(udev);

	usb_unlock_device(udev);

	return 0;

fail:
@@ -1872,11 +1865,8 @@ int usb_resume_device(struct usb_device *udev)
	usb_unlock_device(udev);

	/* rebind drivers that had no suspend() */
	if (status == 0) {
		usb_lock_all_devices();
	if (status == 0)
		bus_rescan_devices(&usb_bus_type);
		usb_unlock_all_devices();
	}
	return status;
}

@@ -1889,14 +1879,14 @@ static int remote_wakeup(struct usb_device *udev)
	/* don't repeat RESUME sequence if this device
	 * was already woken up by some other task
	 */
	down(&udev->serialize);
	usb_lock_device(udev);
	if (udev->state == USB_STATE_SUSPENDED) {
		dev_dbg(&udev->dev, "RESUME (wakeup)\n");
		/* TRSMRCY = 10 msec */
		msleep(10);
		status = finish_device_resume(udev);
	}
	up(&udev->serialize);
	usb_unlock_device(udev);
#endif
	return status;
}
@@ -1997,7 +1987,7 @@ static int hub_resume(struct usb_interface *intf)

		if (!udev || status < 0)
			continue;
		down (&udev->serialize);
		usb_lock_device(udev);
		if (portstat & USB_PORT_STAT_SUSPEND)
			status = hub_port_resume(hub, port1, udev);
		else {
@@ -2008,7 +1998,7 @@ static int hub_resume(struct usb_interface *intf)
				hub_port_logical_disconnect(hub, port1);
			}
		}
		up(&udev->serialize);
		usb_unlock_device(udev);
	}
	}
#endif
@@ -2573,7 +2563,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
		 * udev becomes globally accessible, although presumably
		 * no one will look at it until hdev is unlocked.
		 */
		down (&udev->serialize);
		status = 0;

		/* We mustn't add new devices if the parent hub has
@@ -2597,7 +2586,6 @@ static void hub_port_connect_change(struct usb_hub *hub, int port1,
			}
		}

		up (&udev->serialize);
		if (status)
			goto loop_disable;

Loading