Driver core: create lock/unlock functions for struct device

In the future, we are going to be changing the lock type for struct
device (once we get the lockdep infrastructure properly worked out)  To
make that changeover easier, and to possibly burry the lock in a
different part of struct device, let's create some functions to lock and
unlock a device so that no out-of-core code needs to be changed in the
future.

This patch creates the device_lock/unlock/trylock() functions, and
converts all in-tree users to them.

Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Jean Delvare <khali@linux-fr.org>
Cc: Dave Young <hidave.darkstar@gmail.com>
Cc: Ming Lei <tom.leiming@gmail.com>
Cc: Jiri Kosina <jkosina@suse.cz>
Cc: Phil Carmody <ext-phil.2.carmody@nokia.com>
Cc: Arjan van de Ven <arjan@linux.intel.com>
Cc: Cornelia Huck <cornelia.huck@de.ibm.com>
Cc: Rafael J. Wysocki <rjw@sisk.pl>
Cc: Pavel Machek <pavel@ucw.cz>
Cc: Len Brown <len.brown@intel.com>
Cc: Magnus Damm <damm@igel.co.jp>
Cc: Alan Stern <stern@rowland.harvard.edu>
Cc: Randy Dunlap <randy.dunlap@oracle.com>
Cc: Stefan Richter <stefanr@s5r6.in-berlin.de>
Cc: David Brownell <dbrownell@users.sourceforge.net>
Cc: Vegard Nossum <vegard.nossum@gmail.com>
Cc: Jesse Barnes <jbarnes@virtuousgeek.org>
Cc: Alex Chiang <achiang@hp.com>
Cc: Kenji Kaneshige <kaneshige.kenji@jp.fujitsu.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andrew Patterson <andrew.patterson@hp.com>
Cc: Yu Zhao <yu.zhao@intel.com>
Cc: Dominik Brodowski <linux@dominikbrodowski.net>
Cc: Samuel Ortiz <sameo@linux.intel.com>
Cc: Wolfram Sang <w.sang@pengutronix.de>
Cc: CHENG Renquan <rqcheng@smu.edu.sg>
Cc: Oliver Neukum <oliver@neukum.org>
Cc: Frans Pop <elendil@planet.nl>
Cc: David Vrabel <david.vrabel@csr.com>
Cc: Kay Sievers <kay.sievers@vrfy.org>
Cc: Sarah Sharp <sarah.a.sharp@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
This commit is contained in:
Greg Kroah-Hartman 2010-02-17 10:57:05 -08:00
parent 62e877b893
commit 8e9394ce24
13 changed files with 76 additions and 63 deletions

View File

@ -173,10 +173,10 @@ static ssize_t driver_unbind(struct device_driver *drv,
dev = bus_find_device_by_name(bus, NULL, buf);
if (dev && dev->driver == drv) {
if (dev->parent) /* Needed for USB */
down(&dev->parent->sem);
device_lock(dev->parent);
device_release_driver(dev);
if (dev->parent)
up(&dev->parent->sem);
device_unlock(dev->parent);
err = count;
}
put_device(dev);
@ -200,12 +200,12 @@ static ssize_t driver_bind(struct device_driver *drv,
dev = bus_find_device_by_name(bus, NULL, buf);
if (dev && dev->driver == NULL && driver_match_device(drv, dev)) {
if (dev->parent) /* Needed for USB */
down(&dev->parent->sem);
down(&dev->sem);
device_lock(dev->parent);
device_lock(dev);
err = driver_probe_device(drv, dev);
up(&dev->sem);
device_unlock(dev);
if (dev->parent)
up(&dev->parent->sem);
device_unlock(dev->parent);
if (err > 0) {
/* success */
@ -744,10 +744,10 @@ static int __must_check bus_rescan_devices_helper(struct device *dev,
if (!dev->driver) {
if (dev->parent) /* Needed for USB */
down(&dev->parent->sem);
device_lock(dev->parent);
ret = device_attach(dev);
if (dev->parent)
up(&dev->parent->sem);
device_unlock(dev->parent);
}
return ret < 0 ? ret : 0;
}
@ -779,10 +779,10 @@ int device_reprobe(struct device *dev)
{
if (dev->driver) {
if (dev->parent) /* Needed for USB */
down(&dev->parent->sem);
device_lock(dev->parent);
device_release_driver(dev);
if (dev->parent)
up(&dev->parent->sem);
device_unlock(dev->parent);
}
return bus_rescan_devices_helper(dev, NULL);
}

View File

@ -85,7 +85,7 @@ static void driver_sysfs_remove(struct device *dev)
* for before calling this. (It is ok to call with no other effort
* from a driver's probe() method.)
*
* This function must be called with @dev->sem held.
* This function must be called with the device lock held.
*/
int device_bind_driver(struct device *dev)
{
@ -190,8 +190,8 @@ EXPORT_SYMBOL_GPL(wait_for_device_probe);
* This function returns -ENODEV if the device is not registered,
* 1 if the device is bound successfully and 0 otherwise.
*
* This function must be called with @dev->sem held. When called for a
* USB interface, @dev->parent->sem must be held as well.
* This function must be called with @dev lock held. When called for a
* USB interface, @dev->parent lock must be held as well.
*/
int driver_probe_device(struct device_driver *drv, struct device *dev)
{
@ -233,13 +233,13 @@ static int __device_attach(struct device_driver *drv, void *data)
* 0 if no matching driver was found;
* -ENODEV if the device is not registered.
*
* When called for a USB interface, @dev->parent->sem must be held.
* When called for a USB interface, @dev->parent lock must be held.
*/
int device_attach(struct device *dev)
{
int ret = 0;
down(&dev->sem);
device_lock(dev);
if (dev->driver) {
ret = device_bind_driver(dev);
if (ret == 0)
@ -253,7 +253,7 @@ int device_attach(struct device *dev)
ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
pm_runtime_put_sync(dev);
}
up(&dev->sem);
device_unlock(dev);
return ret;
}
EXPORT_SYMBOL_GPL(device_attach);
@ -276,13 +276,13 @@ static int __driver_attach(struct device *dev, void *data)
return 0;
if (dev->parent) /* Needed for USB */
down(&dev->parent->sem);
down(&dev->sem);
device_lock(dev->parent);
device_lock(dev);
if (!dev->driver)
driver_probe_device(drv, dev);
up(&dev->sem);
device_unlock(dev);
if (dev->parent)
up(&dev->parent->sem);
device_unlock(dev->parent);
return 0;
}
@ -303,8 +303,8 @@ int driver_attach(struct device_driver *drv)
EXPORT_SYMBOL_GPL(driver_attach);
/*
* __device_release_driver() must be called with @dev->sem held.
* When called for a USB interface, @dev->parent->sem must be held as well.
* __device_release_driver() must be called with @dev lock held.
* When called for a USB interface, @dev->parent lock must be held as well.
*/
static void __device_release_driver(struct device *dev)
{
@ -343,7 +343,7 @@ static void __device_release_driver(struct device *dev)
* @dev: device.
*
* Manually detach device from driver.
* When called for a USB interface, @dev->parent->sem must be held.
* When called for a USB interface, @dev->parent lock must be held.
*/
void device_release_driver(struct device *dev)
{
@ -352,9 +352,9 @@ void device_release_driver(struct device *dev)
* within their ->remove callback for the same device, they
* will deadlock right here.
*/
down(&dev->sem);
device_lock(dev);
__device_release_driver(dev);
up(&dev->sem);
device_unlock(dev);
}
EXPORT_SYMBOL_GPL(device_release_driver);
@ -381,13 +381,13 @@ void driver_detach(struct device_driver *drv)
spin_unlock(&drv->p->klist_devices.k_lock);
if (dev->parent) /* Needed for USB */
down(&dev->parent->sem);
down(&dev->sem);
device_lock(dev->parent);
device_lock(dev);
if (dev->driver == drv)
__device_release_driver(dev);
up(&dev->sem);
device_unlock(dev);
if (dev->parent)
up(&dev->parent->sem);
device_unlock(dev->parent);
put_device(dev);
}
}

View File

@ -35,8 +35,8 @@
* because children are guaranteed to be discovered after parents, and
* are inserted at the back of the list on discovery.
*
* Since device_pm_add() may be called with a device semaphore held,
* we must never try to acquire a device semaphore while holding
* Since device_pm_add() may be called with a device lock held,
* we must never try to acquire a device lock while holding
* dpm_list_mutex.
*/
@ -508,7 +508,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
TRACE_RESUME(0);
dpm_wait(dev->parent, async);
down(&dev->sem);
device_lock(dev);
dev->power.status = DPM_RESUMING;
@ -543,7 +543,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
}
}
End:
up(&dev->sem);
device_unlock(dev);
complete_all(&dev->power.completion);
TRACE_RESUME(error);
@ -629,7 +629,7 @@ static void dpm_resume(pm_message_t state)
*/
static void device_complete(struct device *dev, pm_message_t state)
{
down(&dev->sem);
device_lock(dev);
if (dev->class && dev->class->pm && dev->class->pm->complete) {
pm_dev_dbg(dev, state, "completing class ");
@ -646,7 +646,7 @@ static void device_complete(struct device *dev, pm_message_t state)
dev->bus->pm->complete(dev);
}
up(&dev->sem);
device_unlock(dev);
}
/**
@ -809,7 +809,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
int error = 0;
dpm_wait_for_children(dev, async);
down(&dev->sem);
device_lock(dev);
if (async_error)
goto End;
@ -849,7 +849,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
dev->power.status = DPM_OFF;
End:
up(&dev->sem);
device_unlock(dev);
complete_all(&dev->power.completion);
return error;
@ -938,7 +938,7 @@ static int device_prepare(struct device *dev, pm_message_t state)
{
int error = 0;
down(&dev->sem);
device_lock(dev);
if (dev->bus && dev->bus->pm && dev->bus->pm->prepare) {
pm_dev_dbg(dev, state, "preparing ");
@ -962,7 +962,7 @@ static int device_prepare(struct device *dev, pm_message_t state)
suspend_report_result(dev->class->pm->prepare, error);
}
End:
up(&dev->sem);
device_unlock(dev);
return error;
}

View File

@ -33,7 +33,6 @@
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/rwsem.h>
#include <linux/semaphore.h>
#include <linux/spinlock.h>
#include <linux/string.h>
#include <linux/workqueue.h>
@ -828,9 +827,9 @@ static int update_unit(struct device *dev, void *data)
struct fw_driver *driver = (struct fw_driver *)dev->driver;
if (is_fw_unit(dev) && driver != NULL && driver->update != NULL) {
down(&dev->sem);
device_lock(dev);
driver->update(unit);
up(&dev->sem);
device_unlock(dev);
}
return 0;

View File

@ -19,7 +19,6 @@
#include <linux/moduleparam.h>
#include <linux/mutex.h>
#include <linux/freezer.h>
#include <linux/semaphore.h>
#include <asm/atomic.h>
#include "csr.h"
@ -1397,9 +1396,9 @@ static int update_pdrv(struct device *dev, void *data)
pdrv = container_of(drv, struct hpsb_protocol_driver,
driver);
if (pdrv->update) {
down(&ud->device.sem);
device_lock(&ud->device);
error = pdrv->update(ud);
up(&ud->device.sem);
device_unlock(&ud->device);
}
if (error)
device_release_driver(&ud->device);

View File

@ -288,9 +288,9 @@ void pci_walk_bus(struct pci_bus *top, int (*cb)(struct pci_dev *, void *),
next = dev->bus_list.next;
/* Run device routines with the device locked */
down(&dev->dev.sem);
device_lock(&dev->dev);
retval = cb(dev, userdata);
up(&dev->dev.sem);
device_unlock(&dev->dev);
if (retval)
break;
}

View File

@ -2486,7 +2486,7 @@ static int pci_dev_reset(struct pci_dev *dev, int probe)
if (!probe) {
pci_block_user_cfg_access(dev);
/* block PM suspend, driver probe, etc. */
down(&dev->dev.sem);
device_lock(&dev->dev);
}
rc = pci_dev_specific_reset(dev, probe);
@ -2508,7 +2508,7 @@ static int pci_dev_reset(struct pci_dev *dev, int probe)
rc = pci_parent_bus_reset(dev, probe);
done:
if (!probe) {
up(&dev->dev.sem);
device_unlock(&dev->dev);
pci_unblock_user_cfg_access(dev);
}

View File

@ -971,9 +971,9 @@ static int runtime_suspend(struct device *dev)
{
int rc;
down(&dev->sem);
device_lock(dev);
rc = pcmcia_dev_suspend(dev, PMSG_SUSPEND);
up(&dev->sem);
device_unlock(dev);
return rc;
}
@ -981,9 +981,9 @@ static int runtime_resume(struct device *dev)
{
int rc;
down(&dev->sem);
device_lock(dev);
rc = pcmcia_dev_resume(dev);
up(&dev->sem);
device_unlock(dev);
return rc;
}

View File

@ -489,10 +489,10 @@ void usb_driver_release_interface(struct usb_driver *driver,
if (device_is_registered(dev)) {
device_release_driver(dev);
} else {
down(&dev->sem);
device_lock(dev);
usb_unbind_interface(dev);
dev->driver = NULL;
up(&dev->sem);
device_unlock(dev);
}
}
EXPORT_SYMBOL_GPL(usb_driver_release_interface);

View File

@ -62,12 +62,12 @@ int umc_controller_reset(struct umc_dev *umc)
struct device *parent = umc->dev.parent;
int ret = 0;
if(down_trylock(&parent->sem))
if (device_trylock(parent))
return -EAGAIN;
ret = device_for_each_child(parent, parent, umc_bus_pre_reset_helper);
if (ret >= 0)
ret = device_for_each_child(parent, parent, umc_bus_post_reset_helper);
up(&parent->sem);
device_unlock(parent);
return ret;
}

View File

@ -366,12 +366,12 @@ struct dentry *uwb_dbg_create_pal_dir(struct uwb_pal *pal);
static inline void uwb_dev_lock(struct uwb_dev *uwb_dev)
{
down(&uwb_dev->dev.sem);
device_lock(&uwb_dev->dev);
}
static inline void uwb_dev_unlock(struct uwb_dev *uwb_dev)
{
up(&uwb_dev->dev.sem);
device_unlock(&uwb_dev->dev);
}
#endif /* #ifndef __UWB_INTERNAL_H__ */

View File

@ -106,7 +106,7 @@ extern int bus_unregister_notifier(struct bus_type *bus,
/* All 4 notifers below get called with the target struct device *
* as an argument. Note that those functions are likely to be called
* with the device semaphore held in the core, so be careful.
* with the device lock held in the core, so be careful.
*/
#define BUS_NOTIFY_ADD_DEVICE 0x00000001 /* device added */
#define BUS_NOTIFY_DEL_DEVICE 0x00000002 /* device removed */
@ -508,6 +508,21 @@ static inline bool device_async_suspend_enabled(struct device *dev)
return !!dev->power.async_suspend;
}
static inline void device_lock(struct device *dev)
{
down(&dev->sem);
}
static inline int device_trylock(struct device *dev)
{
return down_trylock(&dev->sem);
}
static inline void device_unlock(struct device *dev)
{
up(&dev->sem);
}
void driver_init(void);
/*

View File

@ -512,9 +512,9 @@ extern struct usb_device *usb_get_dev(struct usb_device *dev);
extern void usb_put_dev(struct usb_device *dev);
/* USB device locking */
#define usb_lock_device(udev) down(&(udev)->dev.sem)
#define usb_unlock_device(udev) up(&(udev)->dev.sem)
#define usb_trylock_device(udev) down_trylock(&(udev)->dev.sem)
#define usb_lock_device(udev) device_lock(&(udev)->dev)
#define usb_unlock_device(udev) device_unlock(&(udev)->dev)
#define usb_trylock_device(udev) device_trylock(&(udev)->dev)
extern int usb_lock_device_for_reset(struct usb_device *udev,
const struct usb_interface *iface);