summaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/amba/bus.c13
-rw-r--r--drivers/base/attribute_container.c26
-rw-r--r--drivers/base/base.h2
-rw-r--r--drivers/base/bus.c112
-rw-r--r--drivers/base/class.c2
-rw-r--r--drivers/base/core.c293
-rw-r--r--drivers/base/dd.c66
-rw-r--r--drivers/base/dmapool.c14
-rw-r--r--drivers/base/driver.c20
-rw-r--r--drivers/base/firmware_class.c10
-rw-r--r--drivers/base/power/main.c3
-rw-r--r--drivers/base/power/resume.c13
-rw-r--r--drivers/base/power/shutdown.c2
-rw-r--r--drivers/base/power/suspend.c12
-rw-r--r--drivers/ide/ide-proc.c4
-rw-r--r--drivers/ieee1394/nodemgr.c22
-rw-r--r--drivers/input/gameport/gameport.c39
-rw-r--r--drivers/input/serio/serio.c41
-rw-r--r--drivers/mmc/mmc_sysfs.c27
-rw-r--r--drivers/net/phy/fixed.c6
-rw-r--r--drivers/net/phy/phy_device.c9
-rw-r--r--drivers/pci/pci-driver.c6
-rw-r--r--drivers/pci/pci.c58
-rw-r--r--drivers/pnp/card.c6
-rw-r--r--drivers/s390/cio/device.c6
-rw-r--r--drivers/s390/crypto/ap_bus.c28
-rw-r--r--drivers/s390/net/qeth_proc.c2
-rw-r--r--drivers/scsi/hosts.c4
-rw-r--r--drivers/usb/core/devices.c2
-rw-r--r--drivers/usb/core/devio.c13
-rw-r--r--drivers/usb/core/driver.c12
-rw-r--r--drivers/usb/core/hub.c4
-rw-r--r--drivers/usb/core/message.c2
-rw-r--r--drivers/usb/host/ohci-hcd.c6
34 files changed, 512 insertions, 373 deletions
diff --git a/drivers/amba/bus.c b/drivers/amba/bus.c
index fd54750..268e301 100644
--- a/drivers/amba/bus.c
+++ b/drivers/amba/bus.c
@@ -47,14 +47,13 @@ static int amba_match(struct device *dev, struct device_driver *drv)
static int amba_uevent(struct device *dev, char **envp, int nr_env, char *buf, int bufsz)
{
struct amba_device *pcdev = to_amba_device(dev);
+ int retval = 0, i = 0, len = 0;
- if (nr_env < 2)
- return -ENOMEM;
-
- snprintf(buf, bufsz, "AMBA_ID=%08x", pcdev->periphid);
- *envp++ = buf;
- *envp++ = NULL;
- return 0;
+ retval = add_uevent_var(envp, nr_env, &i,
+ buf, bufsz, &len,
+ "AMBA_ID=%08x", pcdev->periphid);
+ envp[i] = NULL;
+ return retval;
}
#else
#define amba_uevent NULL
diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c
index 2222073..1ec0654 100644
--- a/drivers/base/attribute_container.c
+++ b/drivers/base/attribute_container.c
@@ -62,7 +62,7 @@ EXPORT_SYMBOL_GPL(attribute_container_classdev_to_container);
static struct list_head attribute_container_list;
-static DECLARE_MUTEX(attribute_container_mutex);
+static DEFINE_MUTEX(attribute_container_mutex);
/**
* attribute_container_register - register an attribute container
@@ -77,9 +77,9 @@ attribute_container_register(struct attribute_container *cont)
klist_init(&cont->containers,internal_container_klist_get,
internal_container_klist_put);
- down(&attribute_container_mutex);
+ mutex_lock(&attribute_container_mutex);
list_add_tail(&cont->node, &attribute_container_list);
- up(&attribute_container_mutex);
+ mutex_unlock(&attribute_container_mutex);
return 0;
}
@@ -94,7 +94,7 @@ int
attribute_container_unregister(struct attribute_container *cont)
{
int retval = -EBUSY;
- down(&attribute_container_mutex);
+ mutex_lock(&attribute_container_mutex);
spin_lock(&cont->containers.k_lock);
if (!list_empty(&cont->containers.k_list))
goto out;
@@ -102,7 +102,7 @@ attribute_container_unregister(struct attribute_container *cont)
list_del(&cont->node);
out:
spin_unlock(&cont->containers.k_lock);
- up(&attribute_container_mutex);
+ mutex_unlock(&attribute_container_mutex);
return retval;
}
@@ -145,7 +145,7 @@ attribute_container_add_device(struct device *dev,
{
struct attribute_container *cont;
- down(&attribute_container_mutex);
+ mutex_lock(&attribute_container_mutex);
list_for_each_entry(cont, &attribute_container_list, node) {
struct internal_container *ic;
@@ -173,7 +173,7 @@ attribute_container_add_device(struct device *dev,
attribute_container_add_class_device(&ic->classdev);
klist_add_tail(&ic->node, &cont->containers);
}
- up(&attribute_container_mutex);
+ mutex_unlock(&attribute_container_mutex);
}
/* FIXME: can't break out of this unless klist_iter_exit is also
@@ -211,7 +211,7 @@ attribute_container_remove_device(struct device *dev,
{
struct attribute_container *cont;
- down(&attribute_container_mutex);
+ mutex_lock(&attribute_container_mutex);
list_for_each_entry(cont, &attribute_container_list, node) {
struct internal_container *ic;
struct klist_iter iter;
@@ -234,7 +234,7 @@ attribute_container_remove_device(struct device *dev,
}
}
}
- up(&attribute_container_mutex);
+ mutex_unlock(&attribute_container_mutex);
}
/**
@@ -255,7 +255,7 @@ attribute_container_device_trigger(struct device *dev,
{
struct attribute_container *cont;
- down(&attribute_container_mutex);
+ mutex_lock(&attribute_container_mutex);
list_for_each_entry(cont, &attribute_container_list, node) {
struct internal_container *ic;
struct klist_iter iter;
@@ -273,7 +273,7 @@ attribute_container_device_trigger(struct device *dev,
fn(cont, dev, &ic->classdev);
}
}
- up(&attribute_container_mutex);
+ mutex_unlock(&attribute_container_mutex);
}
/**
@@ -295,12 +295,12 @@ attribute_container_trigger(struct device *dev,
{
struct attribute_container *cont;
- down(&attribute_container_mutex);
+ mutex_lock(&attribute_container_mutex);
list_for_each_entry(cont, &attribute_container_list, node) {
if (cont->match(cont, dev))
fn(cont, dev);
}
- up(&attribute_container_mutex);
+ mutex_unlock(&attribute_container_mutex);
}
/**
diff --git a/drivers/base/base.h b/drivers/base/base.h
index de7e144..d597f26 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -16,7 +16,7 @@ extern int cpu_dev_init(void);
extern int attribute_container_init(void);
extern int bus_add_device(struct device * dev);
-extern int bus_attach_device(struct device * dev);
+extern void bus_attach_device(struct device * dev);
extern void bus_remove_device(struct device * dev);
extern struct bus_type *get_bus(struct bus_type * bus);
extern void put_bus(struct bus_type * bus);
diff --git a/drivers/base/bus.c b/drivers/base/bus.c
index 253868e..1d76e23 100644
--- a/drivers/base/bus.c
+++ b/drivers/base/bus.c
@@ -27,6 +27,9 @@
#define to_driver(obj) container_of(obj, struct device_driver, kobj)
+static int __must_check bus_rescan_devices_helper(struct device *dev,
+ void *data);
+
static ssize_t
drv_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
{
@@ -60,8 +63,19 @@ static struct sysfs_ops driver_sysfs_ops = {
static void driver_release(struct kobject * kobj)
{
- struct device_driver * drv = to_driver(kobj);
- complete(&drv->unloaded);
+ /*
+ * Yes this is an empty release function, it is this way because struct
+ * device is always a static object, not a dynamic one. Yes, this is
+ * not nice and bad, but remember, drivers are code, reference counted
+ * by the module count, not a device, which is really data. And yes,
+ * in the future I do want to have all drivers be created dynamically,
+ * and am working toward that goal, but it will take a bit longer...
+ *
+ * But do not let this example give _anyone_ the idea that they can
+ * create a release function without any code in it at all, to do that
+ * is almost always wrong. If you have any questions about this,
+ * please send an email to <greg@kroah.com>
+ */
}
static struct kobj_type ktype_driver = {
@@ -133,7 +147,6 @@ static decl_subsys(bus, &ktype_bus, NULL);
#ifdef CONFIG_HOTPLUG
-
/* Manually detach a device from its associated driver. */
static int driver_helper(struct device *dev, void *data)
{
@@ -199,6 +212,33 @@ static ssize_t driver_bind(struct device_driver *drv,
}
static DRIVER_ATTR(bind, S_IWUSR, NULL, driver_bind);
+static ssize_t show_drivers_autoprobe(struct bus_type *bus, char *buf)
+{
+ return sprintf(buf, "%d\n", bus->drivers_autoprobe);
+}
+
+static ssize_t store_drivers_autoprobe(struct bus_type *bus,
+ const char *buf, size_t count)
+{
+ if (buf[0] == '0')
+ bus->drivers_autoprobe = 0;
+ else
+ bus->drivers_autoprobe = 1;
+ return count;
+}
+
+static ssize_t store_drivers_probe(struct bus_type *bus,
+ const char *buf, size_t count)
+{
+ struct device *dev;
+
+ dev = bus_find_device(bus, NULL, (void *)buf, driver_helper);
+ if (!dev)
+ return -ENODEV;
+ if (bus_rescan_devices_helper(dev, NULL) != 0)
+ return -EINVAL;
+ return count;
+}
#endif
static struct device * next_device(struct klist_iter * i)
@@ -418,21 +458,21 @@ out_put:
* - Add device to bus's list of devices.
* - Try to attach to driver.
*/
-int bus_attach_device(struct device * dev)
+void bus_attach_device(struct device * dev)
{
struct bus_type *bus = dev->bus;
int ret = 0;
if (bus) {
dev->is_registered = 1;
- ret = device_attach(dev);
- if (ret >= 0) {
+ if (bus->drivers_autoprobe)
+ ret = device_attach(dev);
+ WARN_ON(ret < 0);
+ if (ret >= 0)
klist_add_tail(&dev->knode_bus, &bus->klist_devices);
- ret = 0;
- } else
+ else
dev->is_registered = 0;
}
- return ret;
}
/**
@@ -515,9 +555,41 @@ static void remove_bind_files(struct device_driver *drv)
driver_remove_file(drv, &driver_attr_bind);
driver_remove_file(drv, &driver_attr_unbind);
}
+
+static int add_probe_files(struct bus_type *bus)
+{
+ int retval;
+
+ bus->drivers_probe_attr.attr.name = "drivers_probe";
+ bus->drivers_probe_attr.attr.mode = S_IWUSR;
+ bus->drivers_probe_attr.attr.owner = bus->owner;
+ bus->drivers_probe_attr.store = store_drivers_probe;
+ retval = bus_create_file(bus, &bus->drivers_probe_attr);
+ if (retval)
+ goto out;
+
+ bus->drivers_autoprobe_attr.attr.name = "drivers_autoprobe";
+ bus->drivers_autoprobe_attr.attr.mode = S_IWUSR | S_IRUGO;
+ bus->drivers_autoprobe_attr.attr.owner = bus->owner;
+ bus->drivers_autoprobe_attr.show = show_drivers_autoprobe;
+ bus->drivers_autoprobe_attr.store = store_drivers_autoprobe;
+ retval = bus_create_file(bus, &bus->drivers_autoprobe_attr);
+ if (retval)
+ bus_remove_file(bus, &bus->drivers_probe_attr);
+out:
+ return retval;
+}
+
+static void remove_probe_files(struct bus_type *bus)
+{
+ bus_remove_file(bus, &bus->drivers_autoprobe_attr);
+ bus_remove_file(bus, &bus->drivers_probe_attr);
+}
#else
static inline int add_bind_files(struct device_driver *drv) { return 0; }
static inline void remove_bind_files(struct device_driver *drv) {}
+static inline int add_probe_files(struct bus_type *bus) { return 0; }
+static inline void remove_probe_files(struct bus_type *bus) {}
#endif
/**
@@ -531,7 +603,7 @@ int bus_add_driver(struct device_driver *drv)
int error = 0;
if (!bus)
- return 0;
+ return -EINVAL;
pr_debug("bus %s: add driver %s\n", bus->name, drv->name);
error = kobject_set_name(&drv->kobj, "%s", drv->name);
@@ -541,9 +613,11 @@ int bus_add_driver(struct device_driver *drv)
if ((error = kobject_register(&drv->kobj)))
goto out_put_bus;
- error = driver_attach(drv);
- if (error)
- goto out_unregister;
+ if (drv->bus->drivers_autoprobe) {
+ error = driver_attach(drv);
+ if (error)
+ goto out_unregister;
+ }
klist_add_tail(&drv->knode_bus, &bus->klist_drivers);
module_add_driver(drv->owner, drv);
@@ -605,8 +679,6 @@ static int __must_check bus_rescan_devices_helper(struct device *dev,
ret = device_attach(dev);
if (dev->parent)
up(&dev->parent->sem);
- if (ret > 0)
- ret = 0;
}
return ret < 0 ? ret : 0;
}
@@ -762,6 +834,12 @@ int bus_register(struct bus_type * bus)
klist_init(&bus->klist_devices, klist_devices_get, klist_devices_put);
klist_init(&bus->klist_drivers, NULL, NULL);
+
+ bus->drivers_autoprobe = 1;
+ retval = add_probe_files(bus);
+ if (retval)
+ goto bus_probe_files_fail;
+
retval = bus_add_attrs(bus);
if (retval)
goto bus_attrs_fail;
@@ -770,6 +848,8 @@ int bus_register(struct bus_type * bus)
return 0;
bus_attrs_fail:
+ remove_probe_files(bus);
+bus_probe_files_fail:
kset_unregister(&bus->drivers);
bus_drivers_fail:
kset_unregister(&bus->devices);
@@ -779,7 +859,6 @@ out:
return retval;
}
-
/**
* bus_unregister - remove a bus from the system
* @bus: bus.
@@ -791,6 +870,7 @@ void bus_unregister(struct bus_type * bus)
{
pr_debug("bus %s: unregistering\n", bus->name);
bus_remove_attrs(bus);
+ remove_probe_files(bus);
kset_unregister(&bus->drivers);
kset_unregister(&bus->devices);
subsystem_unregister(&bus->subsys);
diff --git a/drivers/base/class.c b/drivers/base/class.c
index d596812..80bbb20 100644
--- a/drivers/base/class.c
+++ b/drivers/base/class.c
@@ -145,6 +145,7 @@ int class_register(struct class * cls)
INIT_LIST_HEAD(&cls->children);
INIT_LIST_HEAD(&cls->devices);
INIT_LIST_HEAD(&cls->interfaces);
+ kset_init(&cls->class_dirs);
init_MUTEX(&cls->sem);
error = kobject_set_name(&cls->subsys.kset.kobj, "%s", cls->name);
if (error)
@@ -163,7 +164,6 @@ int class_register(struct class * cls)
void class_unregister(struct class * cls)
{
pr_debug("device class '%s': unregistering\n", cls->name);
- kobject_unregister(cls->virtual_dir);
remove_class_attrs(cls);
subsystem_unregister(&cls->subsys);
}
diff --git a/drivers/base/core.c b/drivers/base/core.c
index d7fcf82..8aa090d 100644
--- a/drivers/base/core.c
+++ b/drivers/base/core.c
@@ -43,7 +43,8 @@ int (*platform_notify_remove)(struct device * dev) = NULL;
const char *dev_driver_string(struct device *dev)
{
return dev->driver ? dev->driver->name :
- (dev->bus ? dev->bus->name : "");
+ (dev->bus ? dev->bus->name :
+ (dev->class ? dev->class->name : ""));
}
EXPORT_SYMBOL(dev_driver_string);
@@ -119,6 +120,8 @@ static int dev_uevent_filter(struct kset *kset, struct kobject *kobj)
if (ktype == &ktype_device) {
struct device *dev = to_dev(kobj);
+ if (dev->uevent_suppress)
+ return 0;
if (dev->bus)
return 1;
if (dev->class)
@@ -156,6 +159,11 @@ static int dev_uevent(struct kset *kset, struct kobject *kobj, char **envp,
"MINOR=%u", MINOR(dev->devt));
}
+ if (dev->type && dev->type->name)
+ add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "DEVTYPE=%s", dev->type->name);
+
if (dev->driver)
add_uevent_var(envp, num_envp, &i,
buffer, buffer_size, &length,
@@ -238,71 +246,152 @@ static struct kset_uevent_ops device_uevent_ops = {
.uevent = dev_uevent,
};
+static ssize_t show_uevent(struct device *dev, struct device_attribute *attr,
+ char *buf)
+{
+ struct kobject *top_kobj;
+ struct kset *kset;
+ char *envp[32];
+ char data[PAGE_SIZE];
+ char *pos;
+ int i;
+ size_t count = 0;
+ int retval;
+
+ /* search the kset, the device belongs to */
+ top_kobj = &dev->kobj;
+ if (!top_kobj->kset && top_kobj->parent) {
+ do {
+ top_kobj = top_kobj->parent;
+ } while (!top_kobj->kset && top_kobj->parent);
+ }
+ if (!top_kobj->kset)
+ goto out;
+ kset = top_kobj->kset;
+ if (!kset->uevent_ops || !kset->uevent_ops->uevent)
+ goto out;
+
+ /* respect filter */
+ if (kset->uevent_ops && kset->uevent_ops->filter)
+ if (!kset->uevent_ops->filter(kset, &dev->kobj))
+ goto out;
+
+ /* let the kset specific function add its keys */
+ pos = data;
+ retval = kset->uevent_ops->uevent(kset, &dev->kobj,
+ envp, ARRAY_SIZE(envp),
+ pos, PAGE_SIZE);
+ if (retval)
+ goto out;
+
+ /* copy keys to file */
+ for (i = 0; envp[i]; i++) {
+ pos = &buf[count];
+ count += sprintf(pos, "%s\n", envp[i]);
+ }
+out:
+ return count;
+}
+
static ssize_t store_uevent(struct device *dev, struct device_attribute *attr,
const char *buf, size_t count)
{
+ if (memcmp(buf, "add", 3) != 0)
+ dev_err(dev, "uevent: unsupported action-string; this will "
+ "be ignored in a future kernel version");
kobject_uevent(&dev->kobj, KOBJ_ADD);
return count;
}
-static int device_add_groups(struct device *dev)
+static int device_add_attributes(struct device *dev,
+ struct device_attribute *attrs)
+{
+ int error = 0;
+ int i;
+
+ if (attrs) {
+ for (i = 0; attr_name(attrs[i]); i++) {
+ error = device_create_file(dev, &attrs[i]);
+ if (error)
+ break;
+ }
+ if (error)
+ while (--i >= 0)
+ device_remove_file(dev, &attrs[i]);
+ }
+ return error;
+}
+
+static void device_remove_attributes(struct device *dev,
+ struct device_attribute *attrs)
{
int i;
+
+ if (attrs)
+ for (i = 0; attr_name(attrs[i]); i++)
+ device_remove_file(dev, &attrs[i]);
+}
+
+static int device_add_groups(struct device *dev,
+ struct attribute_group **groups)
+{
int error = 0;
+ int i;
- if (dev->groups) {
- for (i = 0; dev->groups[i]; i++) {
- error = sysfs_create_group(&dev->kobj, dev->groups[i]);
+ if (groups) {
+ for (i = 0; groups[i]; i++) {
+ error = sysfs_create_group(&dev->kobj, groups[i]);
if (error) {
while (--i >= 0)
- sysfs_remove_group(&dev->kobj, dev->groups[i]);
- goto out;
+ sysfs_remove_group(&dev->kobj, groups[i]);
+ break;
}
}
}
-out:
return error;
}
-static void device_remove_groups(struct device *dev)
+static void device_remove_groups(struct device *dev,
+ struct attribute_group **groups)
{
int i;
- if (dev->groups) {
- for (i = 0; dev->groups[i]; i++) {
- sysfs_remove_group(&dev->kobj, dev->groups[i]);
- }
- }
+
+ if (groups)
+ for (i = 0; groups[i]; i++)
+ sysfs_remove_group(&dev->kobj, groups[i]);
}
static int device_add_attrs(struct device *dev)
{
struct class *class = dev->class;
struct device_type *type = dev->type;
- int error = 0;
- int i;
+ int error;
- if (class && class->dev_attrs) {
- for (i = 0; attr_name(class->dev_attrs[i]); i++) {
- error = device_create_file(dev, &class->dev_attrs[i]);
- if (error)
- break;
- }
+ if (class) {
+ error = device_add_attributes(dev, class->dev_attrs);
if (error)
- while (--i >= 0)
- device_remove_file(dev, &class->dev_attrs[i]);
+ return error;
}
- if (type && type->attrs) {
- for (i = 0; attr_name(type->attrs[i]); i++) {
- error = device_create_file(dev, &type->attrs[i]);
- if (error)
- break;
- }
+ if (type) {
+ error = device_add_groups(dev, type->groups);
if (error)
- while (--i >= 0)
- device_remove_file(dev, &type->attrs[i]);
+ goto err_remove_class_attrs;
}
+ error = device_add_groups(dev, dev->groups);
+ if (error)
+ goto err_remove_type_groups;
+
+ return 0;
+
+ err_remove_type_groups:
+ if (type)
+ device_remove_groups(dev, type->groups);
+ err_remove_class_attrs:
+ if (class)
+ device_remove_attributes(dev, class->dev_attrs);
+
return error;
}
@@ -310,17 +399,14 @@ static void device_remove_attrs(struct device *dev)
{
struct class *class = dev->class;
struct device_type *type = dev->type;
- int i;
- if (class && class->dev_attrs) {
- for (i = 0; attr_name(class->dev_attrs[i]); i++)
- device_remove_file(dev, &class->dev_attrs[i]);
- }
+ device_remove_groups(dev, dev->groups);
- if (type && type->attrs) {
- for (i = 0; attr_name(type->attrs[i]); i++)
- device_remove_file(dev, &type->attrs[i]);
- }
+ if (type)
+ device_remove_groups(dev, type->groups);
+
+ if (class)
+ device_remove_attributes(dev, class->dev_attrs);
}
@@ -394,9 +480,10 @@ void device_remove_bin_file(struct device *dev, struct bin_attribute *attr)
EXPORT_SYMBOL_GPL(device_remove_bin_file);
/**
- * device_schedule_callback - helper to schedule a callback for a device
+ * device_schedule_callback_owner - helper to schedule a callback for a device
* @dev: device.
* @func: callback function to invoke later.
+ * @owner: module owning the callback routine
*
* Attribute methods must not unregister themselves or their parent device
* (which would amount to the same thing). Attempts to do so will deadlock,
@@ -407,20 +494,23 @@ EXPORT_SYMBOL_GPL(device_remove_bin_file);
* argument in the workqueue's process context. @dev will be pinned until
* @func returns.
*
+ * This routine is usually called via the inline device_schedule_callback(),
+ * which automatically sets @owner to THIS_MODULE.
+ *
* Returns 0 if the request was submitted, -ENOMEM if storage could not
- * be allocated.
+ * be allocated, -ENODEV if a reference to @owner isn't available.
*
* NOTE: This routine won't work if CONFIG_SYSFS isn't set! It uses an
* underlying sysfs routine (since it is intended for use by attribute
* methods), and if sysfs isn't available you'll get nothing but -ENOSYS.
*/
-int device_schedule_callback(struct device *dev,
- void (*func)(struct device *))
+int device_schedule_callback_owner(struct device *dev,
+ void (*func)(struct device *), struct module *owner)
{
return sysfs_schedule_callback(&dev->kobj,
- (void (*)(void *)) func, dev);
+ (void (*)(void *)) func, dev, owner);
}
-EXPORT_SYMBOL_GPL(device_schedule_callback);
+EXPORT_SYMBOL_GPL(device_schedule_callback_owner);
static void klist_children_get(struct klist_node *n)
{
@@ -477,34 +567,58 @@ static struct kobject * get_device_parent(struct device *dev,
return NULL;
}
#else
-static struct kobject * virtual_device_parent(struct device *dev)
+static struct kobject *virtual_device_parent(struct device *dev)
{
- if (!dev->class)
- return ERR_PTR(-ENODEV);
+ static struct kobject *virtual_dir = NULL;
- if (!dev->class->virtual_dir) {
- static struct kobject *virtual_dir = NULL;
+ if (!virtual_dir)
+ virtual_dir = kobject_add_dir(&devices_subsys.kset.kobj, "virtual");
- if (!virtual_dir)
- virtual_dir = kobject_add_dir(&devices_subsys.kset.kobj, "virtual");
- dev->class->virtual_dir = kobject_add_dir(virtual_dir, dev->class->name);
- }
-
- return dev->class->virtual_dir;
+ return virtual_dir;
}
static struct kobject * get_device_parent(struct device *dev,
struct device *parent)
{
- /* if this is a class device, and has no parent, create one */
- if ((dev->class) && (parent == NULL)) {
- return virtual_device_parent(dev);
- } else if (parent)
+ if (dev->class) {
+ struct kobject *kobj = NULL;
+ struct kobject *parent_kobj;
+ struct kobject *k;
+
+ /*
+ * If we have no parent, we live in "virtual".
+ * Class-devices with a bus-device as parent, live
+ * in a class-directory to prevent namespace collisions.
+ */
+ if (parent == NULL)
+ parent_kobj = virtual_device_parent(dev);
+ else if (parent->class)
+ return &parent->kobj;
+ else
+ parent_kobj = &parent->kobj;
+
+ /* find our class-directory at the parent and reference it */
+ spin_lock(&dev->class->class_dirs.list_lock);
+ list_for_each_entry(k, &dev->class->class_dirs.list, entry)
+ if (k->parent == parent_kobj) {
+ kobj = kobject_get(k);
+ break;
+ }
+ spin_unlock(&dev->class->class_dirs.list_lock);
+ if (kobj)
+ return kobj;
+
+ /* or create a new class-directory at the parent device */
+ return kobject_kset_add_dir(&dev->class->class_dirs,
+ parent_kobj, dev->class->name);
+ }
+
+ if (parent)
return &parent->kobj;
return NULL;
}
-
#endif
+
static int setup_parent(struct device *dev, struct device *parent)
{
struct kobject *kobj;
@@ -541,7 +655,6 @@ int device_add(struct device *dev)
pr_debug("DEV: registering device: ID = '%s'\n", dev->bus_id);
parent = get_device(dev->parent);
-
error = setup_parent(dev, parent);
if (error)
goto Error;
@@ -562,10 +675,11 @@ int device_add(struct device *dev)
BUS_NOTIFY_ADD_DEVICE, dev);
dev->uevent_attr.attr.name = "uevent";
- dev->uevent_attr.attr.mode = S_IWUSR;
+ dev->uevent_attr.attr.mode = S_IRUGO | S_IWUSR;
if (dev->driver)
dev->uevent_attr.attr.owner = dev->driver->owner;
dev->uevent_attr.store = store_uevent;
+ dev->uevent_attr.show = show_uevent;
error = device_create_file(dev, &dev->uevent_attr);
if (error)
goto attrError;
@@ -614,16 +728,12 @@ int device_add(struct device *dev)
if ((error = device_add_attrs(dev)))
goto AttrsError;
- if ((error = device_add_groups(dev)))
- goto GroupError;
if ((error = device_pm_add(dev)))
goto PMError;
if ((error = bus_add_device(dev)))
goto BusError;
- if (!dev->uevent_suppress)
- kobject_uevent(&dev->kobj, KOBJ_ADD);
- if ((error = bus_attach_device(dev)))
- goto AttachError;
+ kobject_uevent(&dev->kobj, KOBJ_ADD);
+ bus_attach_device(dev);
if (parent)
klist_add_tail(&dev->knode_parent, &parent->klist_children);
@@ -639,19 +749,15 @@ int device_add(struct device *dev)
up(&dev->class->sem);
}
Done:
- kfree(class_name);
+ kfree(class_name);
put_device(dev);
return error;
- AttachError:
- bus_remove_device(dev);
BusError:
device_pm_remove(dev);
PMError:
if (dev->bus)
blocking_notifier_call_chain(&dev->bus->bus_notifier,
BUS_NOTIFY_DEL_DEVICE, dev);
- device_remove_groups(dev);
- GroupError:
device_remove_attrs(dev);
AttrsError:
if (dev->devt_attr) {
@@ -677,15 +783,6 @@ int device_add(struct device *dev)
#endif
sysfs_remove_link(&dev->kobj, "device");
}
-
- down(&dev->class->sem);
- /* notify any interfaces that the device is now gone */
- list_for_each_entry(class_intf, &dev->class->interfaces, node)
- if (class_intf->remove_dev)
- class_intf->remove_dev(dev, class_intf);
- /* remove the device from the class list */
- list_del_init(&dev->node);
- up(&dev->class->sem);
}
ueventattrError:
device_remove_file(dev, &dev->uevent_attr);
@@ -796,9 +893,33 @@ void device_del(struct device * dev)
/* remove the device from the class list */
list_del_init(&dev->node);
up(&dev->class->sem);
+
+ /* If we live in a parent class-directory, unreference it */
+ if (dev->kobj.parent->kset == &dev->class->class_dirs) {
+ struct device *d;
+ int other = 0;
+
+ /*
+ * if we are the last child of our class, delete
+ * our class-directory at this parent
+ */
+ down(&dev->class->sem);
+ list_for_each_entry(d, &dev->class->devices, node) {
+ if (d == dev)
+ continue;
+ if (d->kobj.parent == dev->kobj.parent) {
+ other = 1;
+ break;
+ }
+ }
+ if (!other)
+ kobject_del(dev->kobj.parent);
+
+ kobject_put(dev->kobj.parent);
+ up(&dev->class->sem);
+ }
}
device_remove_file(dev, &dev->uevent_attr);
- device_remove_groups(dev);
device_remove_attrs(dev);
bus_remove_device(dev);
diff --git a/drivers/base/dd.c b/drivers/base/dd.c
index 6a48824..18dba8e 100644
--- a/drivers/base/dd.c
+++ b/drivers/base/dd.c
@@ -94,19 +94,11 @@ int device_bind_driver(struct device *dev)
return ret;
}
-struct stupid_thread_structure {
- struct device_driver *drv;
- struct device *dev;
-};
-
static atomic_t probe_count = ATOMIC_INIT(0);
static DECLARE_WAIT_QUEUE_HEAD(probe_waitqueue);
-static int really_probe(void *void_data)
+static int really_probe(struct device *dev, struct device_driver *drv)
{
- struct stupid_thread_structure *data = void_data;
- struct device_driver *drv = data->drv;
- struct device *dev = data->dev;
int ret = 0;
atomic_inc(&probe_count);
@@ -154,7 +146,6 @@ probe_failed:
*/
ret = 0;
done:
- kfree(data);
atomic_dec(&probe_count);
wake_up(&probe_waitqueue);
return ret;
@@ -186,16 +177,14 @@ int driver_probe_done(void)
* format of the ID structures, nor what is to be considered a match and
* what is not.
*
- * This function returns 1 if a match is found, an error if one occurs
- * (that is not -ENODEV or -ENXIO), and 0 otherwise.
+ * This function returns 1 if a match is found, -ENODEV if the device is
+ * not registered, 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.
*/
int driver_probe_device(struct device_driver * drv, struct device * dev)
{
- struct stupid_thread_structure *data;
- struct task_struct *probe_task;
int ret = 0;
if (!device_is_registered(dev))
@@ -206,19 +195,7 @@ int driver_probe_device(struct device_driver * drv, struct device * dev)
pr_debug("%s: Matched Device %s with Driver %s\n",
drv->bus->name, dev->bus_id, drv->name);
- data = kmalloc(sizeof(*data), GFP_KERNEL);
- if (!data)
- return -ENOMEM;
- data->drv = drv;
- data->dev = dev;
-
- if (drv->multithread_probe) {
- probe_task = kthread_run(really_probe, data,
- "probe-%s", dev->bus_id);
- if (IS_ERR(probe_task))
- ret = really_probe(data);
- } else
- ret = really_probe(data);
+ ret = really_probe(dev, drv);
done:
return ret;
@@ -230,30 +207,57 @@ static int __device_attach(struct device_driver * drv, void * data)
return driver_probe_device(drv, dev);
}
+static int device_probe_drivers(void *data)
+{
+ struct device *dev = data;
+ int ret = 0;
+
+ if (dev->bus) {
+ down(&dev->sem);
+ ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
+ up(&dev->sem);
+ }
+ return ret;
+}
+
/**
* device_attach - try to attach device to a driver.
* @dev: device.
*
* Walk the list of drivers that the bus has and call
* driver_probe_device() for each pair. If a compatible
- * pair is found, break out and return.
+ * pair is found, break out and return. If the bus specifies
+ * multithreaded probing, walking the list of drivers is done
+ * on a probing thread.
*
* Returns 1 if the device was bound to a driver;
- * 0 if no matching device was found; error code otherwise.
+ * 0 if no matching device was found or multithreaded probing is done;
+ * -ENODEV if the device is not registered.
*
* When called for a USB interface, @dev->parent->sem must be held.
*/
int device_attach(struct device * dev)
{
int ret = 0;
+ struct task_struct *probe_task = ERR_PTR(-ENOMEM);
down(&dev->sem);
if (dev->driver) {
ret = device_bind_driver(dev);
if (ret == 0)
ret = 1;
- } else
- ret = bus_for_each_drv(dev->bus, NULL, dev, __device_attach);
+ else {
+ dev->driver = NULL;
+ ret = 0;
+ }
+ } else {
+ if (dev->bus->multithread_probe)
+ probe_task = kthread_run(device_probe_drivers, dev,
+ "probe-%s", dev->bus_id);
+ if(IS_ERR(probe_task))
+ ret = bus_for_each_drv(dev->bus, NULL, dev,
+ __device_attach);
+ }
up(&dev->sem);
return ret;
}
diff --git a/drivers/base/dmapool.c b/drivers/base/dmapool.c
index cd467c9..9406259 100644
--- a/drivers/base/dmapool.c
+++ b/drivers/base/dmapool.c
@@ -37,7 +37,7 @@ struct dma_page { /* cacheable header for 'allocation' bytes */
#define POOL_TIMEOUT_JIFFIES ((100 /* msec */ * HZ) / 1000)
-static DECLARE_MUTEX (pools_lock);
+static DEFINE_MUTEX (pools_lock);
static ssize_t
show_pools (struct device *dev, struct device_attribute *attr, char *buf)
@@ -55,7 +55,7 @@ show_pools (struct device *dev, struct device_attribute *attr, char *buf)
size -= temp;
next += temp;
- down (&pools_lock);
+ mutex_lock(&pools_lock);
list_for_each_entry(pool, &dev->dma_pools, pools) {
unsigned pages = 0;
unsigned blocks = 0;
@@ -73,7 +73,7 @@ show_pools (struct device *dev, struct device_attribute *attr, char *buf)
size -= temp;
next += temp;
}
- up (&pools_lock);
+ mutex_unlock(&pools_lock);
return PAGE_SIZE - size;
}
@@ -143,7 +143,7 @@ dma_pool_create (const char *name, struct device *dev,
if (dev) {
int ret;
- down (&pools_lock);
+ mutex_lock(&pools_lock);
if (list_empty (&dev->dma_pools))
ret = device_create_file (dev, &dev_attr_pools);
else
@@ -155,7 +155,7 @@ dma_pool_create (const char *name, struct device *dev,
kfree(retval);
retval = NULL;
}
- up (&pools_lock);
+ mutex_unlock(&pools_lock);
} else
INIT_LIST_HEAD (&retval->pools);
@@ -231,11 +231,11 @@ pool_free_page (struct dma_pool *pool, struct dma_page *page)
void
dma_pool_destroy (struct dma_pool *pool)
{
- down (&pools_lock);
+ mutex_lock(&pools_lock);
list_del (&pool->pools);
if (pool->dev && list_empty (&pool->dev->dma_pools))
device_remove_file (pool->dev, &dev_attr_pools);
- up (&pools_lock);
+ mutex_unlock(&pools_lock);
while (!list_empty (&pool->page_list)) {
struct dma_page *page;
diff --git a/drivers/base/driver.c b/drivers/base/driver.c
index 082bfde..eb11475 100644
--- a/drivers/base/driver.c
+++ b/drivers/base/driver.c
@@ -149,10 +149,6 @@ void put_driver(struct device_driver * drv)
* We pass off most of the work to the bus_add_driver() call,
* since most of the things we have to do deal with the bus
* structures.
- *
- * The one interesting aspect is that we setup @drv->unloaded
- * as a completion that gets complete when the driver reference
- * count reaches 0.
*/
int driver_register(struct device_driver * drv)
{
@@ -162,35 +158,19 @@ int driver_register(struct device_driver * drv)
printk(KERN_WARNING "Driver '%s' needs updating - please use bus_type methods\n", drv->name);
}
klist_init(&drv->klist_devices, NULL, NULL);
- init_completion(&drv->unloaded);
return bus_add_driver(drv);
}
-
/**
* driver_unregister - remove driver from system.
* @drv: driver.
*
* Again, we pass off most of the work to the bus-level call.
- *
- * Though, once that is done, we wait until @drv->unloaded is completed.
- * This will block until the driver refcount reaches 0, and it is
- * released. Only modular drivers will call this function, and we
- * have to guarantee that it won't complete, letting the driver
- * unload until all references are gone.
*/
void driver_unregister(struct device_driver * drv)
{
bus_remove_driver(drv);
- /*
- * If the driver is a module, we are probably in
- * the module unload path, and we want to wait
- * for everything to unload before we can actually
- * finish the unload.
- */
- if (drv->owner)
- wait_for_completion(&drv->unloaded);
}
/**
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index c0a979a5..97ab5bd 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -31,8 +31,6 @@ enum {
FW_STATUS_LOADING,
FW_STATUS_DONE,
FW_STATUS_ABORT,
- FW_STATUS_READY,
- FW_STATUS_READY_NOHOTPLUG,
};
static int loading_timeout = 60; /* In seconds */
@@ -96,9 +94,6 @@ static int firmware_uevent(struct device *dev, char **envp, int num_envp,
struct firmware_priv *fw_priv = dev_get_drvdata(dev);
int i = 0, len = 0;
- if (!test_bit(FW_STATUS_READY, &fw_priv->status))
- return -ENODEV;
-
if (add_uevent_var(envp, num_envp, &i, buffer, buffer_size, &len,
"FIRMWARE=%s", fw_priv->fw_id))
return -ENOMEM;
@@ -333,6 +328,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name,
f_dev->parent = device;
f_dev->class = &firmware_class;
dev_set_drvdata(f_dev, fw_priv);
+ f_dev->uevent_suppress = 1;
retval = device_register(f_dev);
if (retval) {
printk(KERN_ERR "%s: device_register failed\n",
@@ -382,9 +378,7 @@ static int fw_setup_device(struct firmware *fw, struct device **dev_p,
}
if (uevent)
- set_bit(FW_STATUS_READY, &fw_priv->status);
- else
- set_bit(FW_STATUS_READY_NOHOTPLUG, &fw_priv->status);
+ f_dev->uevent_suppress = 0;
*dev_p = f_dev;
goto out;
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index bbbb973..05dc876 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -29,6 +29,9 @@ LIST_HEAD(dpm_off_irq);
DECLARE_MUTEX(dpm_sem);
DECLARE_MUTEX(dpm_list_sem);
+int (*platform_enable_wakeup)(struct device *dev, int is_on);
+
+
/**
* device_pm_set_parent - Specify power dependency.
* @dev: Device who needs power.
diff --git a/drivers/base/power/resume.c b/drivers/base/power/resume.c
index 020be36..a2c6418 100644
--- a/drivers/base/power/resume.c
+++ b/drivers/base/power/resume.c
@@ -26,7 +26,9 @@ int resume_device(struct device * dev)
TRACE_DEVICE(dev);
TRACE_RESUME(0);
+
down(&dev->sem);
+
if (dev->power.pm_parent
&& dev->power.pm_parent->power.power_state.event) {
dev_err(dev, "PM: resume from %d, parent %s still %d\n",
@@ -34,15 +36,24 @@ int resume_device(struct device * dev)
dev->power.pm_parent->bus_id,
dev->power.pm_parent->power.power_state.event);
}
+
if (dev->bus && dev->bus->resume) {
dev_dbg(dev,"resuming\n");
error = dev->bus->resume(dev);
}
- if (dev->class && dev->class->resume) {
+
+ if (!error && dev->type && dev->type->resume) {
+ dev_dbg(dev,"resuming\n");
+ error = dev->type->resume(dev);
+ }
+
+ if (!error && dev->class && dev->class->resume) {
dev_dbg(dev,"class resume\n");
error = dev->class->resume(dev);
}
+
up(&dev->sem);
+
TRACE_RESUME(error);
return error;
}
diff --git a/drivers/base/power/shutdown.c b/drivers/base/power/shutdown.c
index 3483ae4..58b6f77 100644
--- a/drivers/base/power/shutdown.c
+++ b/drivers/base/power/shutdown.c
@@ -36,7 +36,6 @@ void device_shutdown(void)
{
struct device * dev, *devn;
- down_write(&devices_subsys.rwsem);
list_for_each_entry_safe_reverse(dev, devn, &devices_subsys.kset.list,
kobj.entry) {
if (dev->bus && dev->bus->shutdown) {
@@ -47,7 +46,6 @@ void device_shutdown(void)
dev->driver->shutdown(dev);
}
}
- up_write(&devices_subsys.rwsem);
sysdev_shutdown();
}
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c
index ece136b..42d2b86 100644
--- a/drivers/base/power/suspend.c
+++ b/drivers/base/power/suspend.c
@@ -78,6 +78,18 @@ int suspend_device(struct device * dev, pm_message_t state)
suspend_report_result(dev->class->suspend, error);
}
+ if (!error && dev->type && dev->type->suspend && !dev->power.power_state.event) {
+ dev_dbg(dev, "%s%s\n",
+ suspend_verb(state.event),
+ ((state.event == PM_EVENT_SUSPEND)
+ && device_may_wakeup(dev))
+ ? ", may wakeup"
+ : ""
+ );
+ error = dev->type->suspend(dev, state);
+ suspend_report_result(dev->type->suspend, error);
+ }
+
if (!error && dev->bus && dev->bus->suspend && !dev->power.power_state.event) {
dev_dbg(dev, "%s%s\n",
suspend_verb(state.event),
diff --git a/drivers/ide/ide-proc.c b/drivers/ide/ide-proc.c
index afb71c6..a9e0b30 100644
--- a/drivers/ide/ide-proc.c
+++ b/drivers/ide/ide-proc.c
@@ -310,14 +310,12 @@ static int proc_ide_read_driver
ide_driver_t *ide_drv;
int len;
- down_read(&dev->bus->subsys.rwsem);
if (dev->driver) {
ide_drv = container_of(dev->driver, ide_driver_t, gen_driver);
len = sprintf(page, "%s version %s\n",
dev->driver->name, ide_drv->version);
} else
len = sprintf(page, "ide-default version 0.9.newide\n");
- up_read(&dev->bus->subsys.rwsem);
PROC_IDE_READ_RETURN(page,start,off,count,eof,len);
}
@@ -327,7 +325,6 @@ static int ide_replace_subdriver(ide_drive_t *drive, const char *driver)
int ret = 1;
int err;
- down_write(&dev->bus->subsys.rwsem);
device_release_driver(dev);
/* FIXME: device can still be in use by previous driver */
strlcpy(drive->driver_req, driver, sizeof(drive->driver_req));
@@ -345,7 +342,6 @@ static int ide_replace_subdriver(ide_drive_t *drive, const char *driver)
}
if (dev->driver && !strcmp(dev->driver->name, driver))
ret = 0;
- up_write(&dev->bus->subsys.rwsem);
return ret;
}
diff --git a/drivers/ieee1394/nodemgr.c b/drivers/ieee1394/nodemgr.c
index c5ace19..dbeba45 100644
--- a/drivers/ieee1394/nodemgr.c
+++ b/drivers/ieee1394/nodemgr.c
@@ -370,9 +370,7 @@ static ssize_t fw_set_ignore_driver(struct device *dev, struct device_attribute
if (state == 1) {
ud->ignore_driver = 1;
- down_write(&ieee1394_bus_type.subsys.rwsem);
device_release_driver(dev);
- up_write(&ieee1394_bus_type.subsys.rwsem);
} else if (state == 0)
ud->ignore_driver = 0;
@@ -1163,6 +1161,7 @@ static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
struct unit_directory *ud;
int i = 0;
int length = 0;
+ int retval = 0;
/* ieee1394:venNmoNspNverN */
char buf[8 + 1 + 3 + 8 + 2 + 8 + 2 + 8 + 3 + 8 + 1];
@@ -1176,14 +1175,11 @@ static int nodemgr_uevent(struct class_device *cdev, char **envp, int num_envp,
#define PUT_ENVP(fmt,val) \
do { \
- int printed; \
- envp[i++] = buffer; \
- printed = snprintf(buffer, buffer_size - length, \
- fmt, val); \
- if ((buffer_size - (length+printed) <= 0) || (i >= num_envp)) \
- return -ENOMEM; \
- length += printed+1; \
- buffer += printed+1; \
+ retval = add_uevent_var(envp, num_envp, &i, \
+ buffer, buffer_size, &length, \
+ fmt, val); \
+ if (retval) \
+ return retval; \
} while (0)
PUT_ENVP("VENDOR_ID=%06x", ud->vendor_id);
@@ -1393,12 +1389,10 @@ static void nodemgr_suspend_ne(struct node_entry *ne)
if (ud->ne != ne)
continue;
- down_write(&ieee1394_bus_type.subsys.rwsem);
if (ud->device.driver &&
(!ud->device.driver->suspend ||
ud->device.driver->suspend(&ud->device, PMSG_SUSPEND)))
device_release_driver(&ud->device);
- up_write(&ieee1394_bus_type.subsys.rwsem);
}
up(&nodemgr_ud_class.sem);
}
@@ -1418,10 +1412,8 @@ static void nodemgr_resume_ne(struct node_entry *ne)
if (ud->ne != ne)
continue;
- down_read(&ieee1394_bus_type.subsys.rwsem);
if (ud->device.driver && ud->device.driver->resume)
ud->device.driver->resume(&ud->device);
- up_read(&ieee1394_bus_type.subsys.rwsem);
}
up(&nodemgr_ud_class.sem);
@@ -1442,7 +1434,6 @@ static void nodemgr_update_pdrv(struct node_entry *ne)
if (ud->ne != ne)
continue;
- down_write(&ieee1394_bus_type.subsys.rwsem);
if (ud->device.driver) {
pdrv = container_of(ud->device.driver,
struct hpsb_protocol_driver,
@@ -1450,7 +1441,6 @@ static void nodemgr_update_pdrv(struct node_entry *ne)
if (pdrv->update && pdrv->update(ud))
device_release_driver(&ud->device);
}
- up_write(&ieee1394_bus_type.subsys.rwsem);
}
up(&nodemgr_ud_class.sem);
}
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index a00fe47..bd686a2 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -190,16 +190,14 @@ static void gameport_run_poll_handler(unsigned long d)
* Basic gameport -> driver core mappings
*/
-static void gameport_bind_driver(struct gameport *gameport, struct gameport_driver *drv)
+static int gameport_bind_driver(struct gameport *gameport, struct gameport_driver *drv)
{
int error;
- down_write(&gameport_bus.subsys.rwsem);
-
gameport->dev.driver = &drv->driver;
if (drv->connect(gameport, drv)) {
gameport->dev.driver = NULL;
- goto out;
+ return -ENODEV;
}
error = device_bind_driver(&gameport->dev);
@@ -211,31 +209,21 @@ static void gameport_bind_driver(struct gameport *gameport, struct gameport_driv
drv->description, error);
drv->disconnect(gameport);
gameport->dev.driver = NULL;
- goto out;
+ return error;
}
- out:
- up_write(&gameport_bus.subsys.rwsem);
-}
-
-static void gameport_release_driver(struct gameport *gameport)
-{
- down_write(&gameport_bus.subsys.rwsem);
- device_release_driver(&gameport->dev);
- up_write(&gameport_bus.subsys.rwsem);
+ return 0;
}
static void gameport_find_driver(struct gameport *gameport)
{
int error;
- down_write(&gameport_bus.subsys.rwsem);
error = device_attach(&gameport->dev);
if (error < 0)
printk(KERN_WARNING
"gameport: device_attach() failed for %s (%s), error: %d\n",
gameport->phys, gameport->name, error);
- up_write(&gameport_bus.subsys.rwsem);
}
@@ -483,13 +471,12 @@ static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribut
{
struct gameport *gameport = to_gameport_port(dev);
struct device_driver *drv;
- int retval;
+ int error;
- retval = mutex_lock_interruptible(&gameport_mutex);
- if (retval)
- return retval;
+ error = mutex_lock_interruptible(&gameport_mutex);
+ if (error)
+ return error;
- retval = count;
if (!strncmp(buf, "none", count)) {
gameport_disconnect_port(gameport);
} else if (!strncmp(buf, "reconnect", count)) {
@@ -499,15 +486,15 @@ static ssize_t gameport_rebind_driver(struct device *dev, struct device_attribut
gameport_find_driver(gameport);
} else if ((drv = driver_find(buf, &gameport_bus)) != NULL) {
gameport_disconnect_port(gameport);
- gameport_bind_driver(gameport, to_gameport_driver(drv));
+ error = gameport_bind_driver(gameport, to_gameport_driver(drv));
put_driver(drv);
} else {
- retval = -EINVAL;
+ error = -EINVAL;
}
mutex_unlock(&gameport_mutex);
- return retval;
+ return error ? error : count;
}
static struct device_attribute gameport_device_attrs[] = {
@@ -655,7 +642,7 @@ static void gameport_disconnect_port(struct gameport *gameport)
do {
parent = s->parent;
- gameport_release_driver(s);
+ device_release_driver(&s->dev);
gameport_destroy_port(s);
} while ((s = parent) != gameport);
}
@@ -663,7 +650,7 @@ static void gameport_disconnect_port(struct gameport *gameport)
/*
* Ok, no children left, now disconnect this port
*/
- gameport_release_driver(gameport);
+ device_release_driver(&gameport->dev);
}
void gameport_rescan(struct gameport *gameport)
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index a15e531..5895202 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -115,18 +115,18 @@ static int serio_match_port(const struct serio_device_id *ids, struct serio *ser
* Basic serio -> driver core mappings
*/
-static void serio_bind_driver(struct serio *serio, struct serio_driver *drv)
+static int serio_bind_driver(struct serio *serio, struct serio_driver *drv)
{
int error;
- down_write(&serio_bus.subsys.rwsem);
-
if (serio_match_port(drv->id_table, serio)) {
+
serio->dev.driver = &drv->driver;
if (serio_connect_driver(serio, drv)) {
serio->dev.driver = NULL;
- goto out;
+ return -ENODEV;
}
+
error = device_bind_driver(&serio->dev);
if (error) {
printk(KERN_WARNING
@@ -136,31 +136,21 @@ static void serio_bind_driver(struct serio *serio, struct serio_driver *drv)
drv->description, error);
serio_disconnect_driver(serio);
serio->dev.driver = NULL;
- goto out;
+ return error;
}
}
- out:
- up_write(&serio_bus.subsys.rwsem);
-}
-
-static void serio_release_driver(struct serio *serio)
-{
- down_write(&serio_bus.subsys.rwsem);
- device_release_driver(&serio->dev);
- up_write(&serio_bus.subsys.rwsem);
+ return 0;
}
static void serio_find_driver(struct serio *serio)
{
int error;
- down_write(&serio_bus.subsys.rwsem);
error = device_attach(&serio->dev);
if (error < 0)
printk(KERN_WARNING
"serio: device_attach() failed for %s (%s), error: %d\n",
serio->phys, serio->name, error);
- up_write(&serio_bus.subsys.rwsem);
}
@@ -470,13 +460,12 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *
{
struct serio *serio = to_serio_port(dev);
struct device_driver *drv;
- int retval;
+ int error;
- retval = mutex_lock_interruptible(&serio_mutex);
- if (retval)
- return retval;
+ error = mutex_lock_interruptible(&serio_mutex);
+ if (error)
+ return error;
- retval = count;
if (!strncmp(buf, "none", count)) {
serio_disconnect_port(serio);
} else if (!strncmp(buf, "reconnect", count)) {
@@ -486,15 +475,15 @@ static ssize_t serio_rebind_driver(struct device *dev, struct device_attribute *
serio_find_driver(serio);
} else if ((drv = driver_find(buf, &serio_bus)) != NULL) {
serio_disconnect_port(serio);
- serio_bind_driver(serio, to_serio_driver(drv));
+ error = serio_bind_driver(serio, to_serio_driver(drv));
put_driver(drv);
} else {
- retval = -EINVAL;
+ error = -EINVAL;
}
mutex_unlock(&serio_mutex);
- return retval;
+ return error ? error : count;
}
static ssize_t serio_show_bind_mode(struct device *dev, struct device_attribute *attr, char *buf)
@@ -665,7 +654,7 @@ static void serio_disconnect_port(struct serio *serio)
do {
parent = s->parent;
- serio_release_driver(s);
+ device_release_driver(&s->dev);
serio_destroy_port(s);
} while ((s = parent) != serio);
}
@@ -673,7 +662,7 @@ static void serio_disconnect_port(struct serio *serio)
/*
* Ok, no children left, now disconnect this port
*/
- serio_release_driver(serio);
+ device_release_driver(&serio->dev);
}
void serio_rescan(struct serio *serio)
diff --git a/drivers/mmc/mmc_sysfs.c b/drivers/mmc/mmc_sysfs.c
index d32698b..e0e82d8 100644
--- a/drivers/mmc/mmc_sysfs.c
+++ b/drivers/mmc/mmc_sysfs.c
@@ -86,31 +86,26 @@ mmc_bus_uevent(struct device *dev, char **envp, int num_envp, char *buf,
{
struct mmc_card *card = dev_to_mmc_card(dev);
char ccc[13];
- int i = 0;
-
-#define add_env(fmt,val) \
- ({ \
- int len, ret = -ENOMEM; \
- if (i < num_envp) { \
- envp[i++] = buf; \
- len = snprintf(buf, buf_size, fmt, val) + 1; \
- buf_size -= len; \
- buf += len; \
- if (buf_size >= 0) \
- ret = 0; \
- } \
- ret; \
- })
+ int retval = 0, i = 0, length = 0;
+
+#define add_env(fmt,val) do { \
+ retval = add_uevent_var(envp, num_envp, &i, \
+ buf, buf_size, &length, \
+ fmt, val); \
+ if (retval) \
+ return retval; \
+} while (0);
for (i = 0; i < 12; i++)
ccc[i] = card->csd.cmdclass & (1 << i) ? '1' : '0';
ccc[12] = '\0';
- i = 0;
add_env("MMC_CCC=%s", ccc);
add_env("MMC_MANFID=%06x", card->cid.manfid);
add_env("MMC_NAME=%s", mmc_card_name(card));
add_env("MMC_OEMID=%04x", card->cid.oemid);
+#undef add_env
+ envp[i] = NULL;
return 0;
}
diff --git a/drivers/net/phy/fixed.c b/drivers/net/phy/fixed.c
index 66da91b..68c99b4c 100644
--- a/drivers/net/phy/fixed.c
+++ b/drivers/net/phy/fixed.c
@@ -276,21 +276,15 @@ static int fixed_mdio_register_device(int number, int speed, int duplex)
artificially, we are binding the driver here by hand;
it will be the same for all the fixed phys anyway.
*/
- down_write(&phydev->dev.bus->subsys.rwsem);
-
phydev->dev.driver = &fixed_mdio_driver.driver;
err = phydev->dev.driver->probe(&phydev->dev);
if(err < 0) {
printk(KERN_ERR "Phy %s: problems with fixed driver\n",phydev->dev.bus_id);
- up_write(&phydev->dev.bus->subsys.rwsem);
goto probe_fail;
}
err = device_bind_driver(&phydev->dev);
-
- up_write(&phydev->dev.bus->subsys.rwsem);
-
if (err)
goto probe_fail;
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 7d5b6d1..8f01952 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -208,16 +208,12 @@ struct phy_device *phy_attach(struct net_device *dev,
* exist, and we should use the genphy driver. */
if (NULL == d->driver) {
int err;
- down_write(&d->bus->subsys.rwsem);
d->driver = &genphy_driver.driver;
err = d->driver->probe(d);
-
if (err >= 0)
err = device_bind_driver(d);
- up_write(&d->bus->subsys.rwsem);
-
if (err)
return ERR_PTR(err);
}
@@ -258,11 +254,8 @@ void phy_detach(struct phy_device *phydev)
* was using the generic driver), we unbind the device
* from the generic driver so that there's a chance a
* real driver could be loaded */
- if (phydev->dev.driver == &genphy_driver.driver) {
- down_write(&phydev->dev.bus->subsys.rwsem);
+ if (phydev->dev.driver == &genphy_driver.driver)
device_release_driver(&phydev->dev);
- up_write(&phydev->dev.bus->subsys.rwsem);
- }
}
EXPORT_SYMBOL(phy_detach);
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index a3c1755..39e80fc 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -434,11 +434,6 @@ int __pci_register_driver(struct pci_driver *drv, struct module *owner,
drv->driver.mod_name = mod_name;
drv->driver.kobj.ktype = &pci_driver_kobj_type;
- if (pci_multithread_probe)
- drv->driver.multithread_probe = pci_multithread_probe;
- else
- drv->driver.multithread_probe = drv->multithread_probe;
-
spin_lock_init(&drv->dynids.lock);
INIT_LIST_HEAD(&drv->dynids.list);
@@ -574,6 +569,7 @@ struct bus_type pci_bus_type = {
static int __init pci_driver_init(void)
{
+ pci_bus_type.multithread_probe = pci_multithread_probe;
return bus_register(&pci_bus_type);
}
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index d3eab05..2a45827 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -13,6 +13,7 @@
#include <linux/delay.h>
#include <linux/init.h>
#include <linux/pci.h>
+#include <linux/pm.h>
#include <linux/module.h>
#include <linux/spinlock.h>
#include <linux/string.h>
@@ -891,31 +892,48 @@ pci_disable_device(struct pci_dev *dev)
}
/**
- * pci_enable_wake - enable device to generate PME# when suspended
- * @dev: - PCI device to operate on
- * @state: - Current state of device.
- * @enable: - Flag to enable or disable generation
- *
- * Set the bits in the device's PM Capabilities to generate PME# when
- * the system is suspended.
+ * pci_enable_wake - enable PCI device as wakeup event source
+ * @dev: PCI device affected
+ * @state: PCI state from which device will issue wakeup events
+ * @enable: True to enable event generation; false to disable
*
- * -EIO is returned if device doesn't have PM Capabilities.
- * -EINVAL is returned if device supports it, but can't generate wake events.
- * 0 if operation is successful.
- *
+ * This enables the device as a wakeup event source, or disables it.
+ * When such events involves platform-specific hooks, those hooks are
+ * called automatically by this routine.
+ *
+ * Devices with legacy power management (no standard PCI PM capabilities)
+ * always require such platform hooks. Depending on the platform, devices
+ * supporting the standard PCI PME# signal may require such platform hooks;
+ * they always update bits in config space to allow PME# generation.
+ *
+ * -EIO is returned if the device can't ever be a wakeup event source.
+ * -EINVAL is returned if the device can't generate wakeup events from
+ * the specified PCI state. Returns zero if the operation is successful.
*/
int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable)
{
int pm;
+ int status;
u16 value;
+ /* Note that drivers should verify device_may_wakeup(&dev->dev)
+ * before calling this function. Platform code should report
+ * errors when drivers try to enable wakeup on devices that
+ * can't issue wakeups, or on which wakeups were disabled by
+ * userspace updating the /sys/devices.../power/wakeup file.
+ */
+
+ status = call_platform_enable_wakeup(&dev->dev, enable);
+
/* find PCI PM capability in list */
pm = pci_find_capability(dev, PCI_CAP_ID_PM);
- /* If device doesn't support PM Capabilities, but request is to disable
- * wake events, it's a nop; otherwise fail */
- if (!pm)
- return enable ? -EIO : 0;
+ /* If device doesn't support PM Capabilities, but caller wants to
+ * disable wake events, it's a NOP. Otherwise fail unless the
+ * platform hooks handled this legacy device already.
+ */
+ if (!pm)
+ return enable ? status : 0;
/* Check device's ability to generate PME# */
pci_read_config_word(dev,pm+PCI_PM_PMC,&value);
@@ -924,8 +942,14 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable)
value >>= ffs(PCI_PM_CAP_PME_MASK) - 1; /* First bit of mask */
/* Check if it can generate PME# from requested state. */
- if (!value || !(value & (1 << state)))
+ if (!value || !(value & (1 << state))) {
+ /* if it can't, revert what the platform hook changed,
+ * always reporting the base "EINVAL, can't PME#" error
+ */
+ if (enable)
+ call_platform_enable_wakeup(&dev->dev, 0);
return enable ? -EINVAL : 0;
+ }
pci_read_config_word(dev, pm + PCI_PM_CTRL, &value);
@@ -936,7 +960,7 @@ int pci_enable_wake(struct pci_dev *dev, pci_power_t state, int enable)
value &= ~PCI_PM_CTRL_PME_ENABLE;
pci_write_config_word(dev, pm + PCI_PM_CTRL, value);
-
+
return 0;
}
diff --git a/drivers/pnp/card.c b/drivers/pnp/card.c
index 91c047a..dd6384b 100644
--- a/drivers/pnp/card.c
+++ b/drivers/pnp/card.c
@@ -311,7 +311,6 @@ done:
return NULL;
found:
- down_write(&dev->dev.bus->subsys.rwsem);
dev->card_link = clink;
dev->dev.driver = &drv->link.driver;
if (pnp_bus_type.probe(&dev->dev))
@@ -319,14 +318,11 @@ found:
if (device_bind_driver(&dev->dev))
goto err_out;
- up_write(&dev->dev.bus->subsys.rwsem);
-
return dev;
err_out:
dev->dev.driver = NULL;
dev->card_link = NULL;
- up_write(&dev->dev.bus->subsys.rwsem);
return NULL;
}
@@ -340,11 +336,9 @@ void pnp_release_card_device(struct pnp_dev * dev)
struct pnp_card_driver * drv = dev->card_link->driver;
if (!drv)
return;
- down_write(&dev->dev.bus->subsys.rwsem);
drv->link.remove = &card_remove;
device_release_driver(&dev->dev);
drv->link.remove = &card_remove_first;
- up_write(&dev->dev.bus->subsys.rwsem);
}
/*
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 0335590..a23ff58 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -871,6 +871,12 @@ io_subchannel_register(struct work_struct *work)
}
goto out;
}
+ /*
+ * Now we know this subchannel will stay, we can throw
+ * our delayed uevent.
+ */
+ sch->dev.uevent_suppress = 0;
+ kobject_uevent(&sch->dev.kobj, KOBJ_ADD);
/* make it known to the system */
ret = ccw_device_register(cdev);
if (ret) {
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index bf37cdf..5aac0ec 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -423,27 +423,25 @@ static int ap_uevent (struct device *dev, char **envp, int num_envp,
char *buffer, int buffer_size)
{
struct ap_device *ap_dev = to_ap_dev(dev);
- int length;
+ int retval = 0, length = 0, i = 0;
if (!ap_dev)
return -ENODEV;
/* Set up DEV_TYPE environment variable. */
- envp[0] = buffer;
- length = scnprintf(buffer, buffer_size, "DEV_TYPE=%04X",
- ap_dev->device_type);
- if (buffer_size - length <= 0)
- return -ENOMEM;
- buffer += length;
- buffer_size -= length;
+ retval = add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "DEV_TYPE=%04X", ap_dev->device_type);
+ if (retval)
+ return retval;
+
/* Add MODALIAS= */
- envp[1] = buffer;
- length = scnprintf(buffer, buffer_size, "MODALIAS=ap:t%02X",
- ap_dev->device_type);
- if (buffer_size - length <= 0)
- return -ENOMEM;
- envp[2] = NULL;
- return 0;
+ retval = add_uevent_var(envp, num_envp, &i,
+ buffer, buffer_size, &length,
+ "MODALIAS=ap:t%02X", ap_dev->device_type);
+
+ envp[i] = NULL;
+ return retval;
}
static struct bus_type ap_bus_type = {
diff --git a/drivers/s390/net/qeth_proc.c b/drivers/s390/net/qeth_proc.c
index 81f805c..89d56c8 100644
--- a/drivers/s390/net/qeth_proc.c
+++ b/drivers/s390/net/qeth_proc.c
@@ -37,7 +37,6 @@ qeth_procfile_seq_start(struct seq_file *s, loff_t *offset)
struct device *dev = NULL;
loff_t nr = 0;
- down_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
if (*offset == 0)
return SEQ_START_TOKEN;
while (1) {
@@ -53,7 +52,6 @@ qeth_procfile_seq_start(struct seq_file *s, loff_t *offset)
static void
qeth_procfile_seq_stop(struct seq_file *s, void* it)
{
- up_read(&qeth_ccwgroup_driver.driver.bus->subsys.rwsem);
}
static void *
diff --git a/drivers/scsi/hosts.c b/drivers/scsi/hosts.c
index 38c3a29..bd8e7f3 100644
--- a/drivers/scsi/hosts.c
+++ b/drivers/scsi/hosts.c
@@ -435,7 +435,7 @@ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum)
struct class_device *cdev;
struct Scsi_Host *shost = ERR_PTR(-ENXIO), *p;
- down_read(&class->subsys.rwsem);
+ down(&class->sem);
list_for_each_entry(cdev, &class->children, node) {
p = class_to_shost(cdev);
if (p->host_no == hostnum) {
@@ -443,7 +443,7 @@ struct Scsi_Host *scsi_host_lookup(unsigned short hostnum)
break;
}
}
- up_read(&class->subsys.rwsem);
+ up(&class->sem);
return shost;
}
diff --git a/drivers/usb/core/devices.c b/drivers/usb/core/devices.c
index aefc798..6753ca0 100644
--- a/drivers/usb/core/devices.c
+++ b/drivers/usb/core/devices.c
@@ -246,7 +246,6 @@ static char *usb_dump_interface_descriptor(char *start, char *end,
if (start > end)
return start;
- down_read(&usb_bus_type.subsys.rwsem);
if (iface) {
driver_name = (iface->dev.driver
? iface->dev.driver->name
@@ -263,7 +262,6 @@ static char *usb_dump_interface_descriptor(char *start, char *end,
desc->bInterfaceSubClass,
desc->bInterfaceProtocol,
driver_name);
- up_read(&usb_bus_type.subsys.rwsem);
return start;
}
diff --git a/drivers/usb/core/devio.c b/drivers/usb/core/devio.c
index 36e7a84..fc3545d 100644
--- a/drivers/usb/core/devio.c
+++ b/drivers/usb/core/devio.c
@@ -421,14 +421,11 @@ static int claimintf(struct dev_state *ps, unsigned int ifnum)
if (test_bit(ifnum, &ps->ifclaimed))
return 0;
- /* lock against other changes to driver bindings */
- down_write(&usb_bus_type.subsys.rwsem);
intf = usb_ifnum_to_if(dev, ifnum);
if (!intf)
err = -ENOENT;
else
err = usb_driver_claim_interface(&usbfs_driver, intf, ps);
- up_write(&usb_bus_type.subsys.rwsem);
if (err == 0)
set_bit(ifnum, &ps->ifclaimed);
return err;
@@ -444,8 +441,6 @@ static int releaseintf(struct dev_state *ps, unsigned int ifnum)
if (ifnum >= 8*sizeof(ps->ifclaimed))
return err;
dev = ps->dev;
- /* lock against other changes to driver bindings */
- down_write(&usb_bus_type.subsys.rwsem);
intf = usb_ifnum_to_if(dev, ifnum);
if (!intf)
err = -ENOENT;
@@ -453,7 +448,6 @@ static int releaseintf(struct dev_state *ps, unsigned int ifnum)
usb_driver_release_interface(&usbfs_driver, intf);
err = 0;
}
- up_write(&usb_bus_type.subsys.rwsem);
return err;
}
@@ -813,7 +807,6 @@ static int proc_getdriver(struct dev_state *ps, void __user *arg)
if (copy_from_user(&gd, arg, sizeof(gd)))
return -EFAULT;
- down_read(&usb_bus_type.subsys.rwsem);
intf = usb_ifnum_to_if(ps->dev, gd.interface);
if (!intf || !intf->dev.driver)
ret = -ENODATA;
@@ -822,7 +815,6 @@ static int proc_getdriver(struct dev_state *ps, void __user *arg)
sizeof(gd.driver));
ret = (copy_to_user(arg, &gd, sizeof(gd)) ? -EFAULT : 0);
}
- up_read(&usb_bus_type.subsys.rwsem);
return ret;
}
@@ -1351,15 +1343,12 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
/* disconnect kernel driver from interface */
case USBDEVFS_DISCONNECT:
-
- down_write(&usb_bus_type.subsys.rwsem);
if (intf->dev.driver) {
driver = to_usb_driver(intf->dev.driver);
dev_dbg (&intf->dev, "disconnect by usbfs\n");
usb_driver_release_interface(driver, intf);
} else
retval = -ENODATA;
- up_write(&usb_bus_type.subsys.rwsem);
break;
/* let kernel drivers try to (re)bind to the interface */
@@ -1371,7 +1360,6 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
/* talk directly to the interface's driver */
default:
- down_read(&usb_bus_type.subsys.rwsem);
if (intf->dev.driver)
driver = to_usb_driver(intf->dev.driver);
if (driver == NULL || driver->ioctl == NULL) {
@@ -1381,7 +1369,6 @@ static int proc_ioctl(struct dev_state *ps, struct usbdevfs_ioctl *ctl)
if (retval == -ENOIOCTLCMD)
retval = -ENOTTY;
}
- up_read(&usb_bus_type.subsys.rwsem);
}
/* cleanup and return */
diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c
index 9e3e943..e6dd2b9 100644
--- a/drivers/usb/core/driver.c
+++ b/drivers/usb/core/driver.c
@@ -287,9 +287,9 @@ static int usb_unbind_interface(struct device *dev)
* way to bind to an interface is to return the private data from
* the driver's probe() method.
*
- * Callers must own the device lock and the driver model's usb_bus_type.subsys
- * writelock. So driver probe() entries don't need extra locking,
- * but other call contexts may need to explicitly claim those locks.
+ * Callers must own the device lock, so driver probe() entries don't need
+ * extra locking, but other call contexts may need to explicitly claim that
+ * lock.
*/
int usb_driver_claim_interface(struct usb_driver *driver,
struct usb_interface *iface, void* priv)
@@ -330,9 +330,9 @@ EXPORT_SYMBOL(usb_driver_claim_interface);
* also causes the driver disconnect() method to be called.
*
* This call is synchronous, and may not be used in an interrupt context.
- * Callers must own the device lock and the driver model's usb_bus_type.subsys
- * writelock. So driver disconnect() entries don't need extra locking,
- * but other call contexts may need to explicitly claim those locks.
+ * Callers must own the device lock, so driver disconnect() entries don't
+ * need extra locking, but other call contexts may need to explicitly claim
+ * that lock.
*/
void usb_driver_release_interface(struct usb_driver *driver,
struct usb_interface *iface)
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index b89a98e..7a60285 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -119,8 +119,7 @@ MODULE_PARM_DESC(use_both_schemes,
"first one fails");
-#ifdef DEBUG
-static inline char *portspeed (int portstatus)
+static inline char *portspeed(int portstatus)
{
if (portstatus & (1 << USB_PORT_FEAT_HIGHSPEED))
return "480 Mb/s";
@@ -129,7 +128,6 @@ static inline char *portspeed (int portstatus)
else
return "12 Mb/s";
}
-#endif
/* Note that hdev or one of its children must be locked! */
static inline struct usb_hub *hdev_to_hub(struct usb_device *hdev)
diff --git a/drivers/usb/core/message.c b/drivers/usb/core/message.c
index 217a3d6..c359ccb 100644
--- a/drivers/usb/core/message.c
+++ b/drivers/usb/core/message.c
@@ -1349,7 +1349,7 @@ static void release_interface(struct device *dev)
*
* This call is synchronous. The calling context must be able to sleep,
* must own the device lock, and must not hold the driver model's USB
- * bus rwsem; usb device driver probe() methods cannot use this routine.
+ * bus mutex; usb device driver probe() methods cannot use this routine.
*
* Returns zero on success, or else the status code returned by the
* underlying call that failed. On successful completion, each interface
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index f0d29ed..e8bbe8b 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -486,9 +486,6 @@ static int ohci_run (struct ohci_hcd *ohci)
* or if bus glue did the same (e.g. for PCI add-in cards with
* PCI PM support).
*/
- ohci_dbg (ohci, "resetting from state '%s', control = 0x%x\n",
- hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
- ohci_readl (ohci, &ohci->regs->control));
if ((ohci->hc_control & OHCI_CTRL_RWC) != 0
&& !device_may_wakeup(hcd->self.controller))
device_init_wakeup(hcd->self.controller, 1);
@@ -744,9 +741,6 @@ static void ohci_stop (struct usb_hcd *hcd)
{
struct ohci_hcd *ohci = hcd_to_ohci (hcd);
- ohci_dbg (ohci, "stop %s controller (state 0x%02x)\n",
- hcfs2string (ohci->hc_control & OHCI_CTRL_HCFS),
- hcd->state);
ohci_dump (ohci, 1);
flush_scheduled_work();
OpenPOWER on IntegriCloud