diff options
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/Kconfig | 2 | ||||
-rw-r--r-- | drivers/base/base.h | 2 | ||||
-rw-r--r-- | drivers/base/bus.c | 54 | ||||
-rw-r--r-- | drivers/base/class.c | 147 | ||||
-rw-r--r-- | drivers/base/core.c | 67 | ||||
-rw-r--r-- | drivers/base/dd.c | 3 | ||||
-rw-r--r-- | drivers/base/driver.c | 3 | ||||
-rw-r--r-- | drivers/base/firmware_class.c | 24 | ||||
-rw-r--r-- | drivers/base/platform.c | 80 | ||||
-rw-r--r-- | drivers/base/power/main.c | 28 | ||||
-rw-r--r-- | drivers/base/power/power.h | 9 |
11 files changed, 307 insertions, 112 deletions
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index 6318f6b5736..d8e8c49c0cb 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig @@ -54,7 +54,7 @@ config FIRMWARE_IN_KERNEL such firmware, and do not wish to use an initrd. This single option controls the inclusion of firmware for - every driver which usees request_firmare() and ships its + every driver which uses request_firmare() and ships its firmware in the kernel source tree, to avoid a proliferation of 'Include firmware for xxx device' options. diff --git a/drivers/base/base.h b/drivers/base/base.h index 31dc0cd84af..0a5f055dffb 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h @@ -54,7 +54,7 @@ struct driver_private { */ struct class_private { struct kset class_subsys; - struct list_head class_devices; + struct klist class_devices; struct list_head class_interfaces; struct kset class_dirs; struct mutex class_mutex; diff --git a/drivers/base/bus.c b/drivers/base/bus.c index ef522ae5548..5aee1c0169e 100644 --- a/drivers/base/bus.c +++ b/drivers/base/bus.c @@ -333,9 +333,7 @@ static int match_name(struct device *dev, void *data) { const char *name = data; - if (strcmp(name, dev->bus_id) == 0) - return 1; - return 0; + return sysfs_streq(name, dev->bus_id); } /** @@ -982,6 +980,56 @@ struct klist *bus_get_device_klist(struct bus_type *bus) } EXPORT_SYMBOL_GPL(bus_get_device_klist); +/* + * Yes, this forcably breaks the klist abstraction temporarily. It + * just wants to sort the klist, not change reference counts and + * take/drop locks rapidly in the process. It does all this while + * holding the lock for the list, so objects can't otherwise be + * added/removed while we're swizzling. + */ +static void device_insertion_sort_klist(struct device *a, struct list_head *list, + int (*compare)(const struct device *a, + const struct device *b)) +{ + struct list_head *pos; + struct klist_node *n; + struct device *b; + + list_for_each(pos, list) { + n = container_of(pos, struct klist_node, n_node); + b = container_of(n, struct device, knode_bus); + if (compare(a, b) <= 0) { + list_move_tail(&a->knode_bus.n_node, + &b->knode_bus.n_node); + return; + } + } + list_move_tail(&a->knode_bus.n_node, list); +} + +void bus_sort_breadthfirst(struct bus_type *bus, + int (*compare)(const struct device *a, + const struct device *b)) +{ + LIST_HEAD(sorted_devices); + struct list_head *pos, *tmp; + struct klist_node *n; + struct device *dev; + struct klist *device_klist; + + device_klist = bus_get_device_klist(bus); + + spin_lock(&device_klist->k_lock); + list_for_each_safe(pos, tmp, &device_klist->k_list) { + n = container_of(pos, struct klist_node, n_node); + dev = container_of(n, struct device, knode_bus); + device_insertion_sort_klist(dev, &sorted_devices, compare); + } + list_splice(&sorted_devices, &device_klist->k_list); + spin_unlock(&device_klist->k_lock); +} +EXPORT_SYMBOL_GPL(bus_sort_breadthfirst); + int __init buses_init(void) { bus_kset = kset_create_and_add("bus", &bus_uevent_ops, NULL); diff --git a/drivers/base/class.c b/drivers/base/class.c index 5667c2f02c5..eb85e431230 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c @@ -135,6 +135,20 @@ static void remove_class_attrs(struct class *cls) } } +static void klist_class_dev_get(struct klist_node *n) +{ + struct device *dev = container_of(n, struct device, knode_class); + + get_device(dev); +} + +static void klist_class_dev_put(struct klist_node *n) +{ + struct device *dev = container_of(n, struct device, knode_class); + + put_device(dev); +} + int __class_register(struct class *cls, struct lock_class_key *key) { struct class_private *cp; @@ -145,7 +159,7 @@ int __class_register(struct class *cls, struct lock_class_key *key) cp = kzalloc(sizeof(*cp), GFP_KERNEL); if (!cp) return -ENOMEM; - INIT_LIST_HEAD(&cp->class_devices); + klist_init(&cp->class_devices, klist_class_dev_get, klist_class_dev_put); INIT_LIST_HEAD(&cp->class_interfaces); kset_init(&cp->class_dirs); __mutex_init(&cp->class_mutex, "struct class mutex", key); @@ -269,6 +283,71 @@ char *make_class_name(const char *name, struct kobject *kobj) #endif /** + * class_dev_iter_init - initialize class device iterator + * @iter: class iterator to initialize + * @class: the class we wanna iterate over + * @start: the device to start iterating from, if any + * @type: device_type of the devices to iterate over, NULL for all + * + * Initialize class iterator @iter such that it iterates over devices + * of @class. If @start is set, the list iteration will start there, + * otherwise if it is NULL, the iteration starts at the beginning of + * the list. + */ +void class_dev_iter_init(struct class_dev_iter *iter, struct class *class, + struct device *start, const struct device_type *type) +{ + struct klist_node *start_knode = NULL; + + if (start) + start_knode = &start->knode_class; + klist_iter_init_node(&class->p->class_devices, &iter->ki, start_knode); + iter->type = type; +} +EXPORT_SYMBOL_GPL(class_dev_iter_init); + +/** + * class_dev_iter_next - iterate to the next device + * @iter: class iterator to proceed + * + * Proceed @iter to the next device and return it. Returns NULL if + * iteration is complete. + * + * The returned device is referenced and won't be released till + * iterator is proceed to the next device or exited. The caller is + * free to do whatever it wants to do with the device including + * calling back into class code. + */ +struct device *class_dev_iter_next(struct class_dev_iter *iter) +{ + struct klist_node *knode; + struct device *dev; + + while (1) { + knode = klist_next(&iter->ki); + if (!knode) + return NULL; + dev = container_of(knode, struct device, knode_class); + if (!iter->type || iter->type == dev->type) + return dev; + } +} +EXPORT_SYMBOL_GPL(class_dev_iter_next); + +/** + * class_dev_iter_exit - finish iteration + * @iter: class iterator to finish + * + * Finish an iteration. Always call this function after iteration is + * complete whether the iteration ran till the end or not. + */ +void class_dev_iter_exit(struct class_dev_iter *iter) +{ + klist_iter_exit(&iter->ki); +} +EXPORT_SYMBOL_GPL(class_dev_iter_exit); + +/** * class_for_each_device - device iterator * @class: the class we're iterating * @start: the device to start with in the list, if any. @@ -283,32 +362,31 @@ char *make_class_name(const char *name, struct kobject *kobj) * We check the return of @fn each time. If it returns anything * other than 0, we break out and return that value. * - * Note, we hold class->class_mutex in this function, so it can not be - * re-acquired in @fn, otherwise it will self-deadlocking. For - * example, calls to add or remove class members would be verboten. + * @fn is allowed to do anything including calling back into class + * code. There's no locking restriction. */ int class_for_each_device(struct class *class, struct device *start, void *data, int (*fn)(struct device *, void *)) { + struct class_dev_iter iter; struct device *dev; int error = 0; if (!class) return -EINVAL; - mutex_lock(&class->p->class_mutex); - list_for_each_entry(dev, &class->p->class_devices, node) { - if (start) { - if (start == dev) - start = NULL; - continue; - } - dev = get_device(dev); + if (!class->p) { + WARN(1, "%s called for class '%s' before it was initialized", + __func__, class->name); + return -EINVAL; + } + + class_dev_iter_init(&iter, class, start, NULL); + while ((dev = class_dev_iter_next(&iter))) { error = fn(dev, data); - put_device(dev); if (error) break; } - mutex_unlock(&class->p->class_mutex); + class_dev_iter_exit(&iter); return error; } @@ -331,43 +409,41 @@ EXPORT_SYMBOL_GPL(class_for_each_device); * * Note, you will need to drop the reference with put_device() after use. * - * We hold class->class_mutex in this function, so it can not be - * re-acquired in @match, otherwise it will self-deadlocking. For - * example, calls to add or remove class members would be verboten. + * @fn is allowed to do anything including calling back into class + * code. There's no locking restriction. */ struct device *class_find_device(struct class *class, struct device *start, void *data, int (*match)(struct device *, void *)) { + struct class_dev_iter iter; struct device *dev; - int found = 0; if (!class) return NULL; + if (!class->p) { + WARN(1, "%s called for class '%s' before it was initialized", + __func__, class->name); + return NULL; + } - mutex_lock(&class->p->class_mutex); - list_for_each_entry(dev, &class->p->class_devices, node) { - if (start) { - if (start == dev) - start = NULL; - continue; - } - dev = get_device(dev); + class_dev_iter_init(&iter, class, start, NULL); + while ((dev = class_dev_iter_next(&iter))) { if (match(dev, data)) { - found = 1; + get_device(dev); break; - } else - put_device(dev); + } } - mutex_unlock(&class->p->class_mutex); + class_dev_iter_exit(&iter); - return found ? dev : NULL; + return dev; } EXPORT_SYMBOL_GPL(class_find_device); int class_interface_register(struct class_interface *class_intf) { struct class *parent; + struct class_dev_iter iter; struct device *dev; if (!class_intf || !class_intf->class) @@ -380,8 +456,10 @@ int class_interface_register(struct class_interface *class_intf) mutex_lock(&parent->p->class_mutex); list_add_tail(&class_intf->node, &parent->p->class_interfaces); if (class_intf->add_dev) { - list_for_each_entry(dev, &parent->p->class_devices, node) + class_dev_iter_init(&iter, parent, NULL, NULL); + while ((dev = class_dev_iter_next(&iter))) class_intf->add_dev(dev, class_intf); + class_dev_iter_exit(&iter); } mutex_unlock(&parent->p->class_mutex); @@ -391,6 +469,7 @@ int class_interface_register(struct class_interface *class_intf) void class_interface_unregister(struct class_interface *class_intf) { struct class *parent = class_intf->class; + struct class_dev_iter iter; struct device *dev; if (!parent) @@ -399,8 +478,10 @@ void class_interface_unregister(struct class_interface *class_intf) mutex_lock(&parent->p->class_mutex); list_del_init(&class_intf->node); if (class_intf->remove_dev) { - list_for_each_entry(dev, &parent->p->class_devices, node) + class_dev_iter_init(&iter, parent, NULL, NULL); + while ((dev = class_dev_iter_next(&iter))) class_intf->remove_dev(dev, class_intf); + class_dev_iter_exit(&iter); } mutex_unlock(&parent->p->class_mutex); diff --git a/drivers/base/core.c b/drivers/base/core.c index 068aa1c9538..8c2cc2648f5 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -53,7 +53,7 @@ static inline int device_is_not_partition(struct device *dev) * it is attached to. If it is not attached to a bus either, an empty * string will be returned. */ -const char *dev_driver_string(struct device *dev) +const char *dev_driver_string(const struct device *dev) { return dev->driver ? dev->driver->name : (dev->bus ? dev->bus->name : @@ -523,11 +523,16 @@ static void klist_children_put(struct klist_node *n) * device_initialize - init device structure. * @dev: device. * - * This prepares the device for use by other layers, - * including adding it to the device hierarchy. + * This prepares the device for use by other layers by initializing + * its fields. * It is the first half of device_register(), if called by - * that, though it can also be called separately, so one - * may use @dev's fields (e.g. the refcount). + * that function, though it can also be called separately, so one + * may use @dev's fields. In particular, get_device()/put_device() + * may be used for reference counting of @dev after calling this + * function. + * + * NOTE: Use put_device() to give up your reference instead of freeing + * @dev directly once you have called this function. */ void device_initialize(struct device *dev) { @@ -536,11 +541,11 @@ void device_initialize(struct device *dev) klist_init(&dev->klist_children, klist_children_get, klist_children_put); INIT_LIST_HEAD(&dev->dma_pools); - INIT_LIST_HEAD(&dev->node); init_MUTEX(&dev->sem); spin_lock_init(&dev->devres_lock); INIT_LIST_HEAD(&dev->devres_head); device_init_wakeup(dev, 0); + device_pm_init(dev); set_dev_node(dev, -1); } @@ -835,21 +840,31 @@ static void device_remove_sys_dev_entry(struct device *dev) * This is part 2 of device_register(), though may be called * separately _iff_ device_initialize() has been called separately. * - * This adds it to the kobject hierarchy via kobject_add(), adds it + * This adds @dev to the kobject hierarchy via kobject_add(), adds it * to the global and sibling lists for the device, then * adds it to the other relevant subsystems of the driver model. + * + * NOTE: _Never_ directly free @dev after calling this function, even + * if it returned an error! Always use put_device() to give up your + * reference instead. */ int device_add(struct device *dev) { struct device *parent = NULL; struct class_interface *class_intf; - int error; + int error = -EINVAL; dev = get_device(dev); - if (!dev || !strlen(dev->bus_id)) { - error = -EINVAL; - goto Done; - } + if (!dev) + goto done; + + /* Temporarily support init_name if it is set. + * It will override bus_id for now */ + if (dev->init_name) + dev_set_name(dev, "%s", dev->init_name); + + if (!strlen(dev->bus_id)) + goto done; pr_debug("device: '%s': %s\n", dev->bus_id, __func__); @@ -897,9 +912,10 @@ int device_add(struct device *dev) error = bus_add_device(dev); if (error) goto BusError; - error = device_pm_add(dev); + error = dpm_sysfs_add(dev); if (error) - goto PMError; + goto DPMError; + device_pm_add(dev); kobject_uevent(&dev->kobj, KOBJ_ADD); bus_attach_device(dev); if (parent) @@ -908,7 +924,8 @@ int device_add(struct device *dev) if (dev->class) { mutex_lock(&dev->class->p->class_mutex); /* tie the class to the device */ - list_add_tail(&dev->node, &dev->class->p->class_devices); + klist_add_tail(&dev->knode_class, + &dev->class->p->class_devices); /* notify any interfaces that the device is here */ list_for_each_entry(class_intf, @@ -917,10 +934,10 @@ int device_add(struct device *dev) class_intf->add_dev(dev, class_intf); mutex_unlock(&dev->class->p->class_mutex); } - Done: +done: put_device(dev); return error; - PMError: + DPMError: bus_remove_device(dev); BusError: if (dev->bus) @@ -944,7 +961,7 @@ int device_add(struct device *dev) cleanup_device_parent(dev); if (parent) put_device(parent); - goto Done; + goto done; } /** @@ -957,6 +974,10 @@ int device_add(struct device *dev) * I.e. you should only call the two helpers separately if * have a clearly defined need to use and refcount the device * before it is added to the hierarchy. + * + * NOTE: _Never_ directly free @dev after calling this function, even + * if it returned an error! Always use put_device() to give up the + * reference initialized in this function instead. */ int device_register(struct device *dev) { @@ -1007,6 +1028,7 @@ void device_del(struct device *dev) struct class_interface *class_intf; device_pm_remove(dev); + dpm_sysfs_remove(dev); if (parent) klist_del(&dev->knode_parent); if (MAJOR(dev->devt)) { @@ -1023,7 +1045,7 @@ void device_del(struct device *dev) if (class_intf->remove_dev) class_intf->remove_dev(dev, class_intf); /* remove the device from the class list */ - list_del_init(&dev->node); + klist_del(&dev->knode_class); mutex_unlock(&dev->class->p->class_mutex); } device_remove_file(dev, &uevent_attr); @@ -1234,7 +1256,7 @@ struct device *device_create_vargs(struct class *class, struct device *parent, return dev; error: - kfree(dev); + put_device(dev); return ERR_PTR(retval); } EXPORT_SYMBOL_GPL(device_create_vargs); @@ -1305,6 +1327,11 @@ EXPORT_SYMBOL_GPL(device_destroy); * device_rename - renames a device * @dev: the pointer to the struct device to be renamed * @new_name: the new name of the device + * + * It is the responsibility of the caller to provide mutual + * exclusion between two different calls of device_rename + * on the same device to ensure that new_name is valid and + * won't conflict with other devices. */ int device_rename(struct device *dev, char *new_name) { diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 3ac443b2ac0..20febc00a52 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -257,6 +257,9 @@ static int __driver_attach(struct device *dev, void *data) * is an error. */ + if (drv->bus->match && !drv->bus->match(dev, drv)) + return 0; + if (dev->parent) /* Needed for USB */ down(&dev->parent->sem); down(&dev->sem); diff --git a/drivers/base/driver.c b/drivers/base/driver.c index 2ef5acf4368..1e2bda780e4 100644 --- a/drivers/base/driver.c +++ b/drivers/base/driver.c @@ -16,9 +16,6 @@ #include <linux/string.h> #include "base.h" -#define to_dev(node) container_of(node, struct device, driver_list) - - static struct device *next_device(struct klist_iter *i) { struct klist_node *n = klist_next(i); diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index c9c92b00fd5..b7e571031ec 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c @@ -164,8 +164,7 @@ static ssize_t firmware_loading_store(struct device *dev, } /* fallthrough */ default: - printk(KERN_ERR "%s: unexpected value (%d)\n", __func__, - loading); + dev_err(dev, "%s: unexpected value (%d)\n", __func__, loading); /* fallthrough */ case -1: fw_load_abort(fw_priv); @@ -309,7 +308,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name, *dev_p = NULL; if (!fw_priv || !f_dev) { - printk(KERN_ERR "%s: kmalloc failed\n", __func__); + dev_err(device, "%s: kmalloc failed\n", __func__); retval = -ENOMEM; goto error_kfree; } @@ -329,8 +328,7 @@ static int fw_register_device(struct device **dev_p, const char *fw_name, f_dev->uevent_suppress = 1; retval = device_register(f_dev); if (retval) { - printk(KERN_ERR "%s: device_register failed\n", - __func__); + dev_err(device, "%s: device_register failed\n", __func__); goto error_kfree; } *dev_p = f_dev; @@ -363,15 +361,13 @@ static int fw_setup_device(struct firmware *fw, struct device **dev_p, fw_priv->fw = fw; retval = sysfs_create_bin_file(&f_dev->kobj, &fw_priv->attr_data); if (retval) { - printk(KERN_ERR "%s: sysfs_create_bin_file failed\n", - __func__); + dev_err(device, "%s: sysfs_create_bin_file failed\n", __func__); goto error_unreg; } retval = device_create_file(f_dev, &dev_attr_loading); if (retval) { - printk(KERN_ERR "%s: device_create_file failed\n", - __func__); + dev_err(device, "%s: device_create_file failed\n", __func__); goto error_unreg; } @@ -401,8 +397,8 @@ _request_firmware(const struct firmware **firmware_p, const char *name, *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL); if (!firmware) { - printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n", - __func__); + dev_err(device, "%s: kmalloc(struct firmware) failed\n", + __func__); retval = -ENOMEM; goto out; } @@ -411,15 +407,15 @@ _request_firmware(const struct firmware **firmware_p, const char *name, builtin++) { if (strcmp(name, builtin->name)) continue; - printk(KERN_INFO "firmware: using built-in firmware %s\n", - name); + dev_info(device, "firmware: using built-in firmware %s\n", + name); firmware->size = builtin->size; firmware->data = builtin->data; return 0; } if (uevent) - printk(KERN_INFO "firmware: requesting %s\n", name); + dev_info(device, "firmware: requesting %s\n", name); retval = fw_setup_device(firmware, &f_dev, name, device, uevent); if (retval) diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 3f940393d6c..dfcbfe50486 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -42,10 +42,8 @@ struct resource *platform_get_resource(struct platform_device *dev, for (i = 0; i < dev->num_resources; i++) { struct resource *r = &dev->resource[i]; - if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM| - IORESOURCE_IRQ|IORESOURCE_DMA)) == type) - if (num-- == 0) - return r; + if (type == resource_type(r) && num-- == 0) + return r; } return NULL; } @@ -78,10 +76,8 @@ struct resource *platform_get_resource_byname(struct platform_device *dev, for (i = 0; i < dev->num_resources; i++) { struct resource *r = &dev->resource[i]; - if ((r->flags & (IORESOURCE_IO|IORESOURCE_MEM| - IORESOURCE_IRQ|IORESOURCE_DMA)) == type) - if (!strcmp(r->name, name)) - return r; + if (type == resource_type(r) && !strcmp(r->name, name)) + return r; } return NULL; } @@ -259,9 +255,9 @@ int platform_device_add(struct platform_device *pdev) p = r->parent; if (!p) { - if (r->flags & IORESOURCE_MEM) + if (resource_type(r) == IORESOURCE_MEM) p = &iomem_resource; - else if (r->flags & IORESOURCE_IO) + else if (resource_type(r) == IORESOURCE_IO) p = &ioport_resource; } @@ -282,9 +278,14 @@ int platform_device_add(struct platform_device *pdev) return ret; failed: - while (--i >= 0) - if (pdev->resource[i].flags & (IORESOURCE_MEM|IORESOURCE_IO)) - release_resource(&pdev->resource[i]); + while (--i >= 0) { + struct resource *r = &pdev->resource[i]; + unsigned long type = resource_type(r); + + if (type == IORESOURCE_MEM || type == IORESOURCE_IO) + release_resource(r); + } + return ret; } EXPORT_SYMBOL_GPL(platform_device_add); @@ -306,7 +307,9 @@ void platform_device_del(struct platform_device *pdev) for (i = 0; i < pdev->num_resources; i++) { struct resource *r = &pdev->resource[i]; - if (r->flags & (IORESOURCE_MEM|IORESOURCE_IO)) + unsigned long type = resource_type(r); + + if (type == IORESOURCE_MEM || type == IORESOURCE_IO) release_resource(r); } } @@ -391,6 +394,53 @@ error: } EXPORT_SYMBOL_GPL(platform_device_register_simple); +/** + * platform_device_register_data + * @parent: parent device for the device we're adding + * @name: base name of the device we're adding + * @id: instance id + * @data: platform specific data for this platform device + * @size: size of platform specific data + * + * This function creates a simple platform device that requires minimal + * resource and memory management. Canned release function freeing memory + * allocated for the device allows drivers using such devices to be + * unloaded without waiting for the last reference to the device to be + * dropped. + */ +struct platform_device *platform_device_register_data( + struct device *parent, + const char *name, int id, + const void *data, size_t size) +{ + struct platform_device *pdev; + int retval; + + pdev = platform_device_alloc(name, id); + if (!pdev) { + retval = -ENOMEM; + goto error; + } + + pdev->dev.parent = parent; + + if (size) { + retval = platform_device_add_data(pdev, data, size); + if (retval) + goto error; + } + + retval = platform_device_add(pdev); + if (retval) + goto error; + + return pdev; + +error: + platform_device_put(pdev); + return ERR_PTR(retval); +} + static int platform_drv_probe(struct device *_dev) { struct platform_driver *drv = to_platform_driver(_dev->driver); @@ -862,7 +912,7 @@ static int platform_pm_restore_noirq(struct device *dev) #endif /* !CONFIG_HIBERNATION */ -struct pm_ext_ops platform_pm_ops = { +static struct pm_ext_ops platform_pm_ops = { .base = { .prepare = platform_pm_prepare, .complete = platform_pm_complete, diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 3250c5257b7..692c20ba514 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -67,35 +67,27 @@ void device_pm_unlock(void) * device_pm_add - add a device to the list of active devices * @dev: Device to be added to the list */ -int device_pm_add(struct device *dev) +void device_pm_add(struct device *dev) { - int error; - pr_debug("PM: Adding info for %s:%s\n", dev->bus ? dev->bus->name : "No Bus", kobject_name(&dev->kobj)); mutex_lock(&dpm_list_mtx); if (dev->parent) { - if (dev->parent->power.status >= DPM_SUSPENDING) { - dev_warn(dev, "parent %s is sleeping, will not add\n", + if (dev->parent->power.status >= DPM_SUSPENDING) + dev_warn(dev, "parent %s should not be sleeping\n", dev->parent->bus_id); - WARN_ON(true); - } } else if (transition_started) { /* * We refuse to register parentless devices while a PM * transition is in progress in order to avoid leaving them * unhandled down the road */ - WARN_ON(true); - } - error = dpm_sysfs_add(dev); - if (!error) { - dev->power.status = DPM_ON; - list_add_tail(&dev->power.entry, &dpm_list); + dev_WARN(dev, "Parentless device registered during a PM transaction\n"); } + + list_add_tail(&dev->power.entry, &dpm_list); mutex_unlock(&dpm_list_mtx); - return error; } /** @@ -110,7 +102,6 @@ void device_pm_remove(struct device *dev) dev->bus ? dev->bus->name : "No Bus", kobject_name(&dev->kobj)); mutex_lock(&dpm_list_mtx); - dpm_sysfs_remove(dev); list_del_init(&dev->power.entry); mutex_unlock(&dpm_list_mtx); } @@ -787,10 +778,7 @@ EXPORT_SYMBOL_GPL(device_suspend); void __suspend_report_result(const char *function, void *fn, int ret) { - if (ret) { - printk(KERN_ERR "%s(): ", function); - print_fn_descriptor_symbol("%s returns ", fn); - printk("%d\n", ret); - } + if (ret) + printk(KERN_ERR "%s(): %pF returns %d\n", function, fn, ret); } EXPORT_SYMBOL_GPL(__suspend_report_result); diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index a3252c0e288..41f51fae042 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h @@ -1,3 +1,8 @@ +static inline void device_pm_init(struct device *dev) +{ + dev->power.status = DPM_ON; +} + #ifdef CONFIG_PM_SLEEP /* @@ -11,12 +16,12 @@ static inline struct device *to_device(struct list_head *entry) return container_of(entry, struct device, power.entry); } -extern int device_pm_add(struct device *); +extern void device_pm_add(struct device *); extern void device_pm_remove(struct device *); #else /* CONFIG_PM_SLEEP */ -static inline int device_pm_add(struct device *dev) { return 0; } +static inline void device_pm_add(struct device *dev) {} static inline void device_pm_remove(struct device *dev) {} #endif |