diff options
author | David Woodhouse <David.Woodhouse@intel.com> | 2008-07-25 10:40:14 -0400 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2008-07-25 10:40:14 -0400 |
commit | ff877ea80efa2015b6263766f78ee42c2a1b32f9 (patch) | |
tree | 85205005c611ab774702148558321c6fb92f1ccd /drivers/base | |
parent | 30821fee4f0cb3e6d241d9f7ddc37742212e3eb7 (diff) | |
parent | d37e6bf68fc1eb34a4ad21d9ae8890ed37ea80e7 (diff) |
Merge branch 'linux-next' of git://git.infradead.org/~dedekind/ubi-2.6
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/Kconfig | 67 | ||||
-rw-r--r-- | drivers/base/base.h | 27 | ||||
-rw-r--r-- | drivers/base/class.c | 153 | ||||
-rw-r--r-- | drivers/base/core.c | 196 | ||||
-rw-r--r-- | drivers/base/cpu.c | 14 | ||||
-rw-r--r-- | drivers/base/firmware_class.c | 35 | ||||
-rw-r--r-- | drivers/base/memory.c | 12 | ||||
-rw-r--r-- | drivers/base/node.c | 15 | ||||
-rw-r--r-- | drivers/base/platform.c | 296 | ||||
-rw-r--r-- | drivers/base/power/main.c | 675 | ||||
-rw-r--r-- | drivers/base/power/power.h | 2 | ||||
-rw-r--r-- | drivers/base/power/sysfs.c | 3 | ||||
-rw-r--r-- | drivers/base/power/trace.c | 8 | ||||
-rw-r--r-- | drivers/base/sys.c | 64 | ||||
-rw-r--r-- | drivers/base/topology.c | 66 |
15 files changed, 1276 insertions, 357 deletions
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index d7da109c24fd..6318f6b57360 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig | |||
@@ -27,13 +27,78 @@ config PREVENT_FIRMWARE_BUILD | |||
27 | If unsure say Y here. | 27 | If unsure say Y here. |
28 | 28 | ||
29 | config FW_LOADER | 29 | config FW_LOADER |
30 | tristate "Userspace firmware loading support" | 30 | tristate "Userspace firmware loading support" if EMBEDDED |
31 | depends on HOTPLUG | 31 | depends on HOTPLUG |
32 | default y | ||
32 | ---help--- | 33 | ---help--- |
33 | This option is provided for the case where no in-kernel-tree modules | 34 | This option is provided for the case where no in-kernel-tree modules |
34 | require userspace firmware loading support, but a module built outside | 35 | require userspace firmware loading support, but a module built outside |
35 | the kernel tree does. | 36 | the kernel tree does. |
36 | 37 | ||
38 | config FIRMWARE_IN_KERNEL | ||
39 | bool "Include in-kernel firmware blobs in kernel binary" | ||
40 | depends on FW_LOADER | ||
41 | default y | ||
42 | help | ||
43 | The kernel source tree includes a number of firmware 'blobs' | ||
44 | which are used by various drivers. The recommended way to | ||
45 | use these is to run "make firmware_install" and to copy the | ||
46 | resulting binary files created in usr/lib/firmware directory | ||
47 | of the kernel tree to the /lib/firmware on your system so | ||
48 | that they can be loaded by userspace helpers on request. | ||
49 | |||
50 | Enabling this option will build each required firmware blob | ||
51 | into the kernel directly, where request_firmware() will find | ||
52 | them without having to call out to userspace. This may be | ||
53 | useful if your root file system requires a device which uses | ||
54 | such firmware, and do not wish to use an initrd. | ||
55 | |||
56 | This single option controls the inclusion of firmware for | ||
57 | every driver which usees request_firmare() and ships its | ||
58 | firmware in the kernel source tree, to avoid a proliferation | ||
59 | of 'Include firmware for xxx device' options. | ||
60 | |||
61 | Say 'N' and let firmware be loaded from userspace. | ||
62 | |||
63 | config EXTRA_FIRMWARE | ||
64 | string "External firmware blobs to build into the kernel binary" | ||
65 | depends on FW_LOADER | ||
66 | help | ||
67 | This option allows firmware to be built into the kernel, for the | ||
68 | cases where the user either cannot or doesn't want to provide it from | ||
69 | userspace at runtime (for example, when the firmware in question is | ||
70 | required for accessing the boot device, and the user doesn't want to | ||
71 | use an initrd). | ||
72 | |||
73 | This option is a string, and takes the (space-separated) names of the | ||
74 | firmware files -- the same names which appear in MODULE_FIRMWARE() | ||
75 | and request_firmware() in the source. These files should exist under | ||
76 | the directory specified by the EXTRA_FIRMWARE_DIR option, which is | ||
77 | by default the firmware/ subdirectory of the kernel source tree. | ||
78 | |||
79 | So, for example, you might set CONFIG_EXTRA_FIRMWARE="usb8388.bin", | ||
80 | copy the usb8388.bin file into the firmware/ directory, and build the | ||
81 | kernel. Then any request_firmware("usb8388.bin") will be | ||
82 | satisfied internally without needing to call out to userspace. | ||
83 | |||
84 | WARNING: If you include additional firmware files into your binary | ||
85 | kernel image which are not available under the terms of the GPL, | ||
86 | then it may be a violation of the GPL to distribute the resulting | ||
87 | image -- since it combines both GPL and non-GPL work. You should | ||
88 | consult a lawyer of your own before distributing such an image. | ||
89 | |||
90 | config EXTRA_FIRMWARE_DIR | ||
91 | string "Firmware blobs root directory" | ||
92 | depends on EXTRA_FIRMWARE != "" | ||
93 | default "firmware" | ||
94 | help | ||
95 | This option controls the directory in which the kernel build system | ||
96 | looks for the firmware files listed in the EXTRA_FIRMWARE option. | ||
97 | The default is the firmware/ directory in the kernel source tree, | ||
98 | but by changing this option you can point it elsewhere, such as | ||
99 | the /lib/firmware/ directory or another separate directory | ||
100 | containing firmware files. | ||
101 | |||
37 | config DEBUG_DRIVER | 102 | config DEBUG_DRIVER |
38 | bool "Driver Core verbose debug messages" | 103 | bool "Driver Core verbose debug messages" |
39 | depends on DEBUG_KERNEL | 104 | depends on DEBUG_KERNEL |
diff --git a/drivers/base/base.h b/drivers/base/base.h index 2c9ae43e2219..31dc0cd84afa 100644 --- a/drivers/base/base.h +++ b/drivers/base/base.h | |||
@@ -36,6 +36,33 @@ struct driver_private { | |||
36 | }; | 36 | }; |
37 | #define to_driver(obj) container_of(obj, struct driver_private, kobj) | 37 | #define to_driver(obj) container_of(obj, struct driver_private, kobj) |
38 | 38 | ||
39 | |||
40 | /** | ||
41 | * struct class_private - structure to hold the private to the driver core portions of the class structure. | ||
42 | * | ||
43 | * @class_subsys - the struct kset that defines this class. This is the main kobject | ||
44 | * @class_devices - list of devices associated with this class | ||
45 | * @class_interfaces - list of class_interfaces associated with this class | ||
46 | * @class_dirs - "glue" directory for virtual devices associated with this class | ||
47 | * @class_mutex - mutex to protect the children, devices, and interfaces lists. | ||
48 | * @class - pointer back to the struct class that this structure is associated | ||
49 | * with. | ||
50 | * | ||
51 | * This structure is the one that is the actual kobject allowing struct | ||
52 | * class to be statically allocated safely. Nothing outside of the driver | ||
53 | * core should ever touch these fields. | ||
54 | */ | ||
55 | struct class_private { | ||
56 | struct kset class_subsys; | ||
57 | struct list_head class_devices; | ||
58 | struct list_head class_interfaces; | ||
59 | struct kset class_dirs; | ||
60 | struct mutex class_mutex; | ||
61 | struct class *class; | ||
62 | }; | ||
63 | #define to_class(obj) \ | ||
64 | container_of(obj, struct class_private, class_subsys.kobj) | ||
65 | |||
39 | /* initialisation functions */ | 66 | /* initialisation functions */ |
40 | extern int devices_init(void); | 67 | extern int devices_init(void); |
41 | extern int buses_init(void); | 68 | extern int buses_init(void); |
diff --git a/drivers/base/class.c b/drivers/base/class.c index e085af0ff94f..839d27cecb36 100644 --- a/drivers/base/class.c +++ b/drivers/base/class.c | |||
@@ -18,20 +18,20 @@ | |||
18 | #include <linux/err.h> | 18 | #include <linux/err.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/genhd.h> | 20 | #include <linux/genhd.h> |
21 | #include <linux/mutex.h> | ||
21 | #include "base.h" | 22 | #include "base.h" |
22 | 23 | ||
23 | #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr) | 24 | #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr) |
24 | #define to_class(obj) container_of(obj, struct class, subsys.kobj) | ||
25 | 25 | ||
26 | static ssize_t class_attr_show(struct kobject *kobj, struct attribute *attr, | 26 | static ssize_t class_attr_show(struct kobject *kobj, struct attribute *attr, |
27 | char *buf) | 27 | char *buf) |
28 | { | 28 | { |
29 | struct class_attribute *class_attr = to_class_attr(attr); | 29 | struct class_attribute *class_attr = to_class_attr(attr); |
30 | struct class *dc = to_class(kobj); | 30 | struct class_private *cp = to_class(kobj); |
31 | ssize_t ret = -EIO; | 31 | ssize_t ret = -EIO; |
32 | 32 | ||
33 | if (class_attr->show) | 33 | if (class_attr->show) |
34 | ret = class_attr->show(dc, buf); | 34 | ret = class_attr->show(cp->class, buf); |
35 | return ret; | 35 | return ret; |
36 | } | 36 | } |
37 | 37 | ||
@@ -39,17 +39,18 @@ static ssize_t class_attr_store(struct kobject *kobj, struct attribute *attr, | |||
39 | const char *buf, size_t count) | 39 | const char *buf, size_t count) |
40 | { | 40 | { |
41 | struct class_attribute *class_attr = to_class_attr(attr); | 41 | struct class_attribute *class_attr = to_class_attr(attr); |
42 | struct class *dc = to_class(kobj); | 42 | struct class_private *cp = to_class(kobj); |
43 | ssize_t ret = -EIO; | 43 | ssize_t ret = -EIO; |
44 | 44 | ||
45 | if (class_attr->store) | 45 | if (class_attr->store) |
46 | ret = class_attr->store(dc, buf, count); | 46 | ret = class_attr->store(cp->class, buf, count); |
47 | return ret; | 47 | return ret; |
48 | } | 48 | } |
49 | 49 | ||
50 | static void class_release(struct kobject *kobj) | 50 | static void class_release(struct kobject *kobj) |
51 | { | 51 | { |
52 | struct class *class = to_class(kobj); | 52 | struct class_private *cp = to_class(kobj); |
53 | struct class *class = cp->class; | ||
53 | 54 | ||
54 | pr_debug("class '%s': release.\n", class->name); | 55 | pr_debug("class '%s': release.\n", class->name); |
55 | 56 | ||
@@ -70,7 +71,7 @@ static struct kobj_type class_ktype = { | |||
70 | .release = class_release, | 71 | .release = class_release, |
71 | }; | 72 | }; |
72 | 73 | ||
73 | /* Hotplug events for classes go to the class_obj subsys */ | 74 | /* Hotplug events for classes go to the class class_subsys */ |
74 | static struct kset *class_kset; | 75 | static struct kset *class_kset; |
75 | 76 | ||
76 | 77 | ||
@@ -78,7 +79,8 @@ int class_create_file(struct class *cls, const struct class_attribute *attr) | |||
78 | { | 79 | { |
79 | int error; | 80 | int error; |
80 | if (cls) | 81 | if (cls) |
81 | error = sysfs_create_file(&cls->subsys.kobj, &attr->attr); | 82 | error = sysfs_create_file(&cls->p->class_subsys.kobj, |
83 | &attr->attr); | ||
82 | else | 84 | else |
83 | error = -EINVAL; | 85 | error = -EINVAL; |
84 | return error; | 86 | return error; |
@@ -87,21 +89,20 @@ int class_create_file(struct class *cls, const struct class_attribute *attr) | |||
87 | void class_remove_file(struct class *cls, const struct class_attribute *attr) | 89 | void class_remove_file(struct class *cls, const struct class_attribute *attr) |
88 | { | 90 | { |
89 | if (cls) | 91 | if (cls) |
90 | sysfs_remove_file(&cls->subsys.kobj, &attr->attr); | 92 | sysfs_remove_file(&cls->p->class_subsys.kobj, &attr->attr); |
91 | } | 93 | } |
92 | 94 | ||
93 | static struct class *class_get(struct class *cls) | 95 | static struct class *class_get(struct class *cls) |
94 | { | 96 | { |
95 | if (cls) | 97 | if (cls) |
96 | return container_of(kset_get(&cls->subsys), | 98 | kset_get(&cls->p->class_subsys); |
97 | struct class, subsys); | 99 | return cls; |
98 | return NULL; | ||
99 | } | 100 | } |
100 | 101 | ||
101 | static void class_put(struct class *cls) | 102 | static void class_put(struct class *cls) |
102 | { | 103 | { |
103 | if (cls) | 104 | if (cls) |
104 | kset_put(&cls->subsys); | 105 | kset_put(&cls->p->class_subsys); |
105 | } | 106 | } |
106 | 107 | ||
107 | static int add_class_attrs(struct class *cls) | 108 | static int add_class_attrs(struct class *cls) |
@@ -134,42 +135,57 @@ static void remove_class_attrs(struct class *cls) | |||
134 | } | 135 | } |
135 | } | 136 | } |
136 | 137 | ||
137 | int class_register(struct class *cls) | 138 | int __class_register(struct class *cls, struct lock_class_key *key) |
138 | { | 139 | { |
140 | struct class_private *cp; | ||
139 | int error; | 141 | int error; |
140 | 142 | ||
141 | pr_debug("device class '%s': registering\n", cls->name); | 143 | pr_debug("device class '%s': registering\n", cls->name); |
142 | 144 | ||
143 | INIT_LIST_HEAD(&cls->devices); | 145 | cp = kzalloc(sizeof(*cp), GFP_KERNEL); |
144 | INIT_LIST_HEAD(&cls->interfaces); | 146 | if (!cp) |
145 | kset_init(&cls->class_dirs); | 147 | return -ENOMEM; |
146 | init_MUTEX(&cls->sem); | 148 | INIT_LIST_HEAD(&cp->class_devices); |
147 | error = kobject_set_name(&cls->subsys.kobj, "%s", cls->name); | 149 | INIT_LIST_HEAD(&cp->class_interfaces); |
148 | if (error) | 150 | kset_init(&cp->class_dirs); |
151 | __mutex_init(&cp->class_mutex, "struct class mutex", key); | ||
152 | error = kobject_set_name(&cp->class_subsys.kobj, "%s", cls->name); | ||
153 | if (error) { | ||
154 | kfree(cp); | ||
149 | return error; | 155 | return error; |
156 | } | ||
157 | |||
158 | /* set the default /sys/dev directory for devices of this class */ | ||
159 | if (!cls->dev_kobj) | ||
160 | cls->dev_kobj = sysfs_dev_char_kobj; | ||
150 | 161 | ||
151 | #if defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK) | 162 | #if defined(CONFIG_SYSFS_DEPRECATED) && defined(CONFIG_BLOCK) |
152 | /* let the block class directory show up in the root of sysfs */ | 163 | /* let the block class directory show up in the root of sysfs */ |
153 | if (cls != &block_class) | 164 | if (cls != &block_class) |
154 | cls->subsys.kobj.kset = class_kset; | 165 | cp->class_subsys.kobj.kset = class_kset; |
155 | #else | 166 | #else |
156 | cls->subsys.kobj.kset = class_kset; | 167 | cp->class_subsys.kobj.kset = class_kset; |
157 | #endif | 168 | #endif |
158 | cls->subsys.kobj.ktype = &class_ktype; | 169 | cp->class_subsys.kobj.ktype = &class_ktype; |
170 | cp->class = cls; | ||
171 | cls->p = cp; | ||
159 | 172 | ||
160 | error = kset_register(&cls->subsys); | 173 | error = kset_register(&cp->class_subsys); |
161 | if (!error) { | 174 | if (error) { |
162 | error = add_class_attrs(class_get(cls)); | 175 | kfree(cp); |
163 | class_put(cls); | 176 | return error; |
164 | } | 177 | } |
178 | error = add_class_attrs(class_get(cls)); | ||
179 | class_put(cls); | ||
165 | return error; | 180 | return error; |
166 | } | 181 | } |
182 | EXPORT_SYMBOL_GPL(__class_register); | ||
167 | 183 | ||
168 | void class_unregister(struct class *cls) | 184 | void class_unregister(struct class *cls) |
169 | { | 185 | { |
170 | pr_debug("device class '%s': unregistering\n", cls->name); | 186 | pr_debug("device class '%s': unregistering\n", cls->name); |
171 | remove_class_attrs(cls); | 187 | remove_class_attrs(cls); |
172 | kset_unregister(&cls->subsys); | 188 | kset_unregister(&cls->p->class_subsys); |
173 | } | 189 | } |
174 | 190 | ||
175 | static void class_create_release(struct class *cls) | 191 | static void class_create_release(struct class *cls) |
@@ -189,7 +205,8 @@ static void class_create_release(struct class *cls) | |||
189 | * Note, the pointer created here is to be destroyed when finished by | 205 | * Note, the pointer created here is to be destroyed when finished by |
190 | * making a call to class_destroy(). | 206 | * making a call to class_destroy(). |
191 | */ | 207 | */ |
192 | struct class *class_create(struct module *owner, const char *name) | 208 | struct class *__class_create(struct module *owner, const char *name, |
209 | struct lock_class_key *key) | ||
193 | { | 210 | { |
194 | struct class *cls; | 211 | struct class *cls; |
195 | int retval; | 212 | int retval; |
@@ -204,7 +221,7 @@ struct class *class_create(struct module *owner, const char *name) | |||
204 | cls->owner = owner; | 221 | cls->owner = owner; |
205 | cls->class_release = class_create_release; | 222 | cls->class_release = class_create_release; |
206 | 223 | ||
207 | retval = class_register(cls); | 224 | retval = __class_register(cls, key); |
208 | if (retval) | 225 | if (retval) |
209 | goto error; | 226 | goto error; |
210 | 227 | ||
@@ -214,6 +231,7 @@ error: | |||
214 | kfree(cls); | 231 | kfree(cls); |
215 | return ERR_PTR(retval); | 232 | return ERR_PTR(retval); |
216 | } | 233 | } |
234 | EXPORT_SYMBOL_GPL(__class_create); | ||
217 | 235 | ||
218 | /** | 236 | /** |
219 | * class_destroy - destroys a struct class structure | 237 | * class_destroy - destroys a struct class structure |
@@ -252,39 +270,44 @@ char *make_class_name(const char *name, struct kobject *kobj) | |||
252 | /** | 270 | /** |
253 | * class_for_each_device - device iterator | 271 | * class_for_each_device - device iterator |
254 | * @class: the class we're iterating | 272 | * @class: the class we're iterating |
273 | * @start: the device to start with in the list, if any. | ||
255 | * @data: data for the callback | 274 | * @data: data for the callback |
256 | * @fn: function to be called for each device | 275 | * @fn: function to be called for each device |
257 | * | 276 | * |
258 | * Iterate over @class's list of devices, and call @fn for each, | 277 | * Iterate over @class's list of devices, and call @fn for each, |
259 | * passing it @data. | 278 | * passing it @data. If @start is set, the list iteration will start |
279 | * there, otherwise if it is NULL, the iteration starts at the | ||
280 | * beginning of the list. | ||
260 | * | 281 | * |
261 | * We check the return of @fn each time. If it returns anything | 282 | * We check the return of @fn each time. If it returns anything |
262 | * other than 0, we break out and return that value. | 283 | * other than 0, we break out and return that value. |
263 | * | 284 | * |
264 | * Note, we hold class->sem in this function, so it can not be | 285 | * Note, we hold class->class_mutex in this function, so it can not be |
265 | * re-acquired in @fn, otherwise it will self-deadlocking. For | 286 | * re-acquired in @fn, otherwise it will self-deadlocking. For |
266 | * example, calls to add or remove class members would be verboten. | 287 | * example, calls to add or remove class members would be verboten. |
267 | */ | 288 | */ |
268 | int class_for_each_device(struct class *class, void *data, | 289 | int class_for_each_device(struct class *class, struct device *start, |
269 | int (*fn)(struct device *, void *)) | 290 | void *data, int (*fn)(struct device *, void *)) |
270 | { | 291 | { |
271 | struct device *dev; | 292 | struct device *dev; |
272 | int error = 0; | 293 | int error = 0; |
273 | 294 | ||
274 | if (!class) | 295 | if (!class) |
275 | return -EINVAL; | 296 | return -EINVAL; |
276 | down(&class->sem); | 297 | mutex_lock(&class->p->class_mutex); |
277 | list_for_each_entry(dev, &class->devices, node) { | 298 | list_for_each_entry(dev, &class->p->class_devices, node) { |
299 | if (start) { | ||
300 | if (start == dev) | ||
301 | start = NULL; | ||
302 | continue; | ||
303 | } | ||
278 | dev = get_device(dev); | 304 | dev = get_device(dev); |
279 | if (dev) { | 305 | error = fn(dev, data); |
280 | error = fn(dev, data); | 306 | put_device(dev); |
281 | put_device(dev); | ||
282 | } else | ||
283 | error = -ENODEV; | ||
284 | if (error) | 307 | if (error) |
285 | break; | 308 | break; |
286 | } | 309 | } |
287 | up(&class->sem); | 310 | mutex_unlock(&class->p->class_mutex); |
288 | 311 | ||
289 | return error; | 312 | return error; |
290 | } | 313 | } |
@@ -293,6 +316,7 @@ EXPORT_SYMBOL_GPL(class_for_each_device); | |||
293 | /** | 316 | /** |
294 | * class_find_device - device iterator for locating a particular device | 317 | * class_find_device - device iterator for locating a particular device |
295 | * @class: the class we're iterating | 318 | * @class: the class we're iterating |
319 | * @start: Device to begin with | ||
296 | * @data: data for the match function | 320 | * @data: data for the match function |
297 | * @match: function to check device | 321 | * @match: function to check device |
298 | * | 322 | * |
@@ -306,12 +330,13 @@ EXPORT_SYMBOL_GPL(class_for_each_device); | |||
306 | * | 330 | * |
307 | * Note, you will need to drop the reference with put_device() after use. | 331 | * Note, you will need to drop the reference with put_device() after use. |
308 | * | 332 | * |
309 | * We hold class->sem in this function, so it can not be | 333 | * We hold class->class_mutex in this function, so it can not be |
310 | * re-acquired in @match, otherwise it will self-deadlocking. For | 334 | * re-acquired in @match, otherwise it will self-deadlocking. For |
311 | * example, calls to add or remove class members would be verboten. | 335 | * example, calls to add or remove class members would be verboten. |
312 | */ | 336 | */ |
313 | struct device *class_find_device(struct class *class, void *data, | 337 | struct device *class_find_device(struct class *class, struct device *start, |
314 | int (*match)(struct device *, void *)) | 338 | void *data, |
339 | int (*match)(struct device *, void *)) | ||
315 | { | 340 | { |
316 | struct device *dev; | 341 | struct device *dev; |
317 | int found = 0; | 342 | int found = 0; |
@@ -319,19 +344,21 @@ struct device *class_find_device(struct class *class, void *data, | |||
319 | if (!class) | 344 | if (!class) |
320 | return NULL; | 345 | return NULL; |
321 | 346 | ||
322 | down(&class->sem); | 347 | mutex_lock(&class->p->class_mutex); |
323 | list_for_each_entry(dev, &class->devices, node) { | 348 | list_for_each_entry(dev, &class->p->class_devices, node) { |
349 | if (start) { | ||
350 | if (start == dev) | ||
351 | start = NULL; | ||
352 | continue; | ||
353 | } | ||
324 | dev = get_device(dev); | 354 | dev = get_device(dev); |
325 | if (dev) { | 355 | if (match(dev, data)) { |
326 | if (match(dev, data)) { | 356 | found = 1; |
327 | found = 1; | ||
328 | break; | ||
329 | } else | ||
330 | put_device(dev); | ||
331 | } else | ||
332 | break; | 357 | break; |
358 | } else | ||
359 | put_device(dev); | ||
333 | } | 360 | } |
334 | up(&class->sem); | 361 | mutex_unlock(&class->p->class_mutex); |
335 | 362 | ||
336 | return found ? dev : NULL; | 363 | return found ? dev : NULL; |
337 | } | 364 | } |
@@ -349,13 +376,13 @@ int class_interface_register(struct class_interface *class_intf) | |||
349 | if (!parent) | 376 | if (!parent) |
350 | return -EINVAL; | 377 | return -EINVAL; |
351 | 378 | ||
352 | down(&parent->sem); | 379 | mutex_lock(&parent->p->class_mutex); |
353 | list_add_tail(&class_intf->node, &parent->interfaces); | 380 | list_add_tail(&class_intf->node, &parent->p->class_interfaces); |
354 | if (class_intf->add_dev) { | 381 | if (class_intf->add_dev) { |
355 | list_for_each_entry(dev, &parent->devices, node) | 382 | list_for_each_entry(dev, &parent->p->class_devices, node) |
356 | class_intf->add_dev(dev, class_intf); | 383 | class_intf->add_dev(dev, class_intf); |
357 | } | 384 | } |
358 | up(&parent->sem); | 385 | mutex_unlock(&parent->p->class_mutex); |
359 | 386 | ||
360 | return 0; | 387 | return 0; |
361 | } | 388 | } |
@@ -368,13 +395,13 @@ void class_interface_unregister(struct class_interface *class_intf) | |||
368 | if (!parent) | 395 | if (!parent) |
369 | return; | 396 | return; |
370 | 397 | ||
371 | down(&parent->sem); | 398 | mutex_lock(&parent->p->class_mutex); |
372 | list_del_init(&class_intf->node); | 399 | list_del_init(&class_intf->node); |
373 | if (class_intf->remove_dev) { | 400 | if (class_intf->remove_dev) { |
374 | list_for_each_entry(dev, &parent->devices, node) | 401 | list_for_each_entry(dev, &parent->p->class_devices, node) |
375 | class_intf->remove_dev(dev, class_intf); | 402 | class_intf->remove_dev(dev, class_intf); |
376 | } | 403 | } |
377 | up(&parent->sem); | 404 | mutex_unlock(&parent->p->class_mutex); |
378 | 405 | ||
379 | class_put(parent); | 406 | class_put(parent); |
380 | } | 407 | } |
@@ -389,9 +416,7 @@ int __init classes_init(void) | |||
389 | 416 | ||
390 | EXPORT_SYMBOL_GPL(class_create_file); | 417 | EXPORT_SYMBOL_GPL(class_create_file); |
391 | EXPORT_SYMBOL_GPL(class_remove_file); | 418 | EXPORT_SYMBOL_GPL(class_remove_file); |
392 | EXPORT_SYMBOL_GPL(class_register); | ||
393 | EXPORT_SYMBOL_GPL(class_unregister); | 419 | EXPORT_SYMBOL_GPL(class_unregister); |
394 | EXPORT_SYMBOL_GPL(class_create); | ||
395 | EXPORT_SYMBOL_GPL(class_destroy); | 420 | EXPORT_SYMBOL_GPL(class_destroy); |
396 | 421 | ||
397 | EXPORT_SYMBOL_GPL(class_interface_register); | 422 | EXPORT_SYMBOL_GPL(class_interface_register); |
diff --git a/drivers/base/core.c b/drivers/base/core.c index ee0a51a3a41d..7d5c63c81a59 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c | |||
@@ -21,12 +21,16 @@ | |||
21 | #include <linux/genhd.h> | 21 | #include <linux/genhd.h> |
22 | #include <linux/kallsyms.h> | 22 | #include <linux/kallsyms.h> |
23 | #include <linux/semaphore.h> | 23 | #include <linux/semaphore.h> |
24 | #include <linux/mutex.h> | ||
24 | 25 | ||
25 | #include "base.h" | 26 | #include "base.h" |
26 | #include "power/power.h" | 27 | #include "power/power.h" |
27 | 28 | ||
28 | int (*platform_notify)(struct device *dev) = NULL; | 29 | int (*platform_notify)(struct device *dev) = NULL; |
29 | int (*platform_notify_remove)(struct device *dev) = NULL; | 30 | int (*platform_notify_remove)(struct device *dev) = NULL; |
31 | static struct kobject *dev_kobj; | ||
32 | struct kobject *sysfs_dev_char_kobj; | ||
33 | struct kobject *sysfs_dev_block_kobj; | ||
30 | 34 | ||
31 | #ifdef CONFIG_BLOCK | 35 | #ifdef CONFIG_BLOCK |
32 | static inline int device_is_not_partition(struct device *dev) | 36 | static inline int device_is_not_partition(struct device *dev) |
@@ -548,7 +552,7 @@ static struct kobject *get_device_parent(struct device *dev, | |||
548 | { | 552 | { |
549 | /* class devices without a parent live in /sys/class/<classname>/ */ | 553 | /* class devices without a parent live in /sys/class/<classname>/ */ |
550 | if (dev->class && (!parent || parent->class != dev->class)) | 554 | if (dev->class && (!parent || parent->class != dev->class)) |
551 | return &dev->class->subsys.kobj; | 555 | return &dev->class->p->class_subsys.kobj; |
552 | /* all other devices keep their parent */ | 556 | /* all other devices keep their parent */ |
553 | else if (parent) | 557 | else if (parent) |
554 | return &parent->kobj; | 558 | return &parent->kobj; |
@@ -594,13 +598,13 @@ static struct kobject *get_device_parent(struct device *dev, | |||
594 | parent_kobj = &parent->kobj; | 598 | parent_kobj = &parent->kobj; |
595 | 599 | ||
596 | /* find our class-directory at the parent and reference it */ | 600 | /* find our class-directory at the parent and reference it */ |
597 | spin_lock(&dev->class->class_dirs.list_lock); | 601 | spin_lock(&dev->class->p->class_dirs.list_lock); |
598 | list_for_each_entry(k, &dev->class->class_dirs.list, entry) | 602 | list_for_each_entry(k, &dev->class->p->class_dirs.list, entry) |
599 | if (k->parent == parent_kobj) { | 603 | if (k->parent == parent_kobj) { |
600 | kobj = kobject_get(k); | 604 | kobj = kobject_get(k); |
601 | break; | 605 | break; |
602 | } | 606 | } |
603 | spin_unlock(&dev->class->class_dirs.list_lock); | 607 | spin_unlock(&dev->class->p->class_dirs.list_lock); |
604 | if (kobj) | 608 | if (kobj) |
605 | return kobj; | 609 | return kobj; |
606 | 610 | ||
@@ -608,7 +612,7 @@ static struct kobject *get_device_parent(struct device *dev, | |||
608 | k = kobject_create(); | 612 | k = kobject_create(); |
609 | if (!k) | 613 | if (!k) |
610 | return NULL; | 614 | return NULL; |
611 | k->kset = &dev->class->class_dirs; | 615 | k->kset = &dev->class->p->class_dirs; |
612 | retval = kobject_add(k, parent_kobj, "%s", dev->class->name); | 616 | retval = kobject_add(k, parent_kobj, "%s", dev->class->name); |
613 | if (retval < 0) { | 617 | if (retval < 0) { |
614 | kobject_put(k); | 618 | kobject_put(k); |
@@ -627,7 +631,7 @@ static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir) | |||
627 | { | 631 | { |
628 | /* see if we live in a "glue" directory */ | 632 | /* see if we live in a "glue" directory */ |
629 | if (!glue_dir || !dev->class || | 633 | if (!glue_dir || !dev->class || |
630 | glue_dir->kset != &dev->class->class_dirs) | 634 | glue_dir->kset != &dev->class->p->class_dirs) |
631 | return; | 635 | return; |
632 | 636 | ||
633 | kobject_put(glue_dir); | 637 | kobject_put(glue_dir); |
@@ -654,17 +658,18 @@ static int device_add_class_symlinks(struct device *dev) | |||
654 | if (!dev->class) | 658 | if (!dev->class) |
655 | return 0; | 659 | return 0; |
656 | 660 | ||
657 | error = sysfs_create_link(&dev->kobj, &dev->class->subsys.kobj, | 661 | error = sysfs_create_link(&dev->kobj, |
662 | &dev->class->p->class_subsys.kobj, | ||
658 | "subsystem"); | 663 | "subsystem"); |
659 | if (error) | 664 | if (error) |
660 | goto out; | 665 | goto out; |
661 | 666 | ||
662 | #ifdef CONFIG_SYSFS_DEPRECATED | 667 | #ifdef CONFIG_SYSFS_DEPRECATED |
663 | /* stacked class devices need a symlink in the class directory */ | 668 | /* stacked class devices need a symlink in the class directory */ |
664 | if (dev->kobj.parent != &dev->class->subsys.kobj && | 669 | if (dev->kobj.parent != &dev->class->p->class_subsys.kobj && |
665 | device_is_not_partition(dev)) { | 670 | device_is_not_partition(dev)) { |
666 | error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj, | 671 | error = sysfs_create_link(&dev->class->p->class_subsys.kobj, |
667 | dev->bus_id); | 672 | &dev->kobj, dev->bus_id); |
668 | if (error) | 673 | if (error) |
669 | goto out_subsys; | 674 | goto out_subsys; |
670 | } | 675 | } |
@@ -701,13 +706,14 @@ out_device: | |||
701 | if (dev->parent && device_is_not_partition(dev)) | 706 | if (dev->parent && device_is_not_partition(dev)) |
702 | sysfs_remove_link(&dev->kobj, "device"); | 707 | sysfs_remove_link(&dev->kobj, "device"); |
703 | out_busid: | 708 | out_busid: |
704 | if (dev->kobj.parent != &dev->class->subsys.kobj && | 709 | if (dev->kobj.parent != &dev->class->p->class_subsys.kobj && |
705 | device_is_not_partition(dev)) | 710 | device_is_not_partition(dev)) |
706 | sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); | 711 | sysfs_remove_link(&dev->class->p->class_subsys.kobj, |
712 | dev->bus_id); | ||
707 | #else | 713 | #else |
708 | /* link in the class directory pointing to the device */ | 714 | /* link in the class directory pointing to the device */ |
709 | error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj, | 715 | error = sysfs_create_link(&dev->class->p->class_subsys.kobj, |
710 | dev->bus_id); | 716 | &dev->kobj, dev->bus_id); |
711 | if (error) | 717 | if (error) |
712 | goto out_subsys; | 718 | goto out_subsys; |
713 | 719 | ||
@@ -720,7 +726,7 @@ out_busid: | |||
720 | return 0; | 726 | return 0; |
721 | 727 | ||
722 | out_busid: | 728 | out_busid: |
723 | sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); | 729 | sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev->bus_id); |
724 | #endif | 730 | #endif |
725 | 731 | ||
726 | out_subsys: | 732 | out_subsys: |
@@ -746,14 +752,15 @@ static void device_remove_class_symlinks(struct device *dev) | |||
746 | sysfs_remove_link(&dev->kobj, "device"); | 752 | sysfs_remove_link(&dev->kobj, "device"); |
747 | } | 753 | } |
748 | 754 | ||
749 | if (dev->kobj.parent != &dev->class->subsys.kobj && | 755 | if (dev->kobj.parent != &dev->class->p->class_subsys.kobj && |
750 | device_is_not_partition(dev)) | 756 | device_is_not_partition(dev)) |
751 | sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); | 757 | sysfs_remove_link(&dev->class->p->class_subsys.kobj, |
758 | dev->bus_id); | ||
752 | #else | 759 | #else |
753 | if (dev->parent && device_is_not_partition(dev)) | 760 | if (dev->parent && device_is_not_partition(dev)) |
754 | sysfs_remove_link(&dev->kobj, "device"); | 761 | sysfs_remove_link(&dev->kobj, "device"); |
755 | 762 | ||
756 | sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); | 763 | sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev->bus_id); |
757 | #endif | 764 | #endif |
758 | 765 | ||
759 | sysfs_remove_link(&dev->kobj, "subsystem"); | 766 | sysfs_remove_link(&dev->kobj, "subsystem"); |
@@ -776,6 +783,54 @@ int dev_set_name(struct device *dev, const char *fmt, ...) | |||
776 | EXPORT_SYMBOL_GPL(dev_set_name); | 783 | EXPORT_SYMBOL_GPL(dev_set_name); |
777 | 784 | ||
778 | /** | 785 | /** |
786 | * device_to_dev_kobj - select a /sys/dev/ directory for the device | ||
787 | * @dev: device | ||
788 | * | ||
789 | * By default we select char/ for new entries. Setting class->dev_obj | ||
790 | * to NULL prevents an entry from being created. class->dev_kobj must | ||
791 | * be set (or cleared) before any devices are registered to the class | ||
792 | * otherwise device_create_sys_dev_entry() and | ||
793 | * device_remove_sys_dev_entry() will disagree about the the presence | ||
794 | * of the link. | ||
795 | */ | ||
796 | static struct kobject *device_to_dev_kobj(struct device *dev) | ||
797 | { | ||
798 | struct kobject *kobj; | ||
799 | |||
800 | if (dev->class) | ||
801 | kobj = dev->class->dev_kobj; | ||
802 | else | ||
803 | kobj = sysfs_dev_char_kobj; | ||
804 | |||
805 | return kobj; | ||
806 | } | ||
807 | |||
808 | static int device_create_sys_dev_entry(struct device *dev) | ||
809 | { | ||
810 | struct kobject *kobj = device_to_dev_kobj(dev); | ||
811 | int error = 0; | ||
812 | char devt_str[15]; | ||
813 | |||
814 | if (kobj) { | ||
815 | format_dev_t(devt_str, dev->devt); | ||
816 | error = sysfs_create_link(kobj, &dev->kobj, devt_str); | ||
817 | } | ||
818 | |||
819 | return error; | ||
820 | } | ||
821 | |||
822 | static void device_remove_sys_dev_entry(struct device *dev) | ||
823 | { | ||
824 | struct kobject *kobj = device_to_dev_kobj(dev); | ||
825 | char devt_str[15]; | ||
826 | |||
827 | if (kobj) { | ||
828 | format_dev_t(devt_str, dev->devt); | ||
829 | sysfs_remove_link(kobj, devt_str); | ||
830 | } | ||
831 | } | ||
832 | |||
833 | /** | ||
779 | * device_add - add device to device hierarchy. | 834 | * device_add - add device to device hierarchy. |
780 | * @dev: device. | 835 | * @dev: device. |
781 | * | 836 | * |
@@ -829,6 +884,10 @@ int device_add(struct device *dev) | |||
829 | error = device_create_file(dev, &devt_attr); | 884 | error = device_create_file(dev, &devt_attr); |
830 | if (error) | 885 | if (error) |
831 | goto ueventattrError; | 886 | goto ueventattrError; |
887 | |||
888 | error = device_create_sys_dev_entry(dev); | ||
889 | if (error) | ||
890 | goto devtattrError; | ||
832 | } | 891 | } |
833 | 892 | ||
834 | error = device_add_class_symlinks(dev); | 893 | error = device_add_class_symlinks(dev); |
@@ -849,15 +908,16 @@ int device_add(struct device *dev) | |||
849 | klist_add_tail(&dev->knode_parent, &parent->klist_children); | 908 | klist_add_tail(&dev->knode_parent, &parent->klist_children); |
850 | 909 | ||
851 | if (dev->class) { | 910 | if (dev->class) { |
852 | down(&dev->class->sem); | 911 | mutex_lock(&dev->class->p->class_mutex); |
853 | /* tie the class to the device */ | 912 | /* tie the class to the device */ |
854 | list_add_tail(&dev->node, &dev->class->devices); | 913 | list_add_tail(&dev->node, &dev->class->p->class_devices); |
855 | 914 | ||
856 | /* notify any interfaces that the device is here */ | 915 | /* notify any interfaces that the device is here */ |
857 | list_for_each_entry(class_intf, &dev->class->interfaces, node) | 916 | list_for_each_entry(class_intf, |
917 | &dev->class->p->class_interfaces, node) | ||
858 | if (class_intf->add_dev) | 918 | if (class_intf->add_dev) |
859 | class_intf->add_dev(dev, class_intf); | 919 | class_intf->add_dev(dev, class_intf); |
860 | up(&dev->class->sem); | 920 | mutex_unlock(&dev->class->p->class_mutex); |
861 | } | 921 | } |
862 | Done: | 922 | Done: |
863 | put_device(dev); | 923 | put_device(dev); |
@@ -873,6 +933,9 @@ int device_add(struct device *dev) | |||
873 | device_remove_class_symlinks(dev); | 933 | device_remove_class_symlinks(dev); |
874 | SymlinkError: | 934 | SymlinkError: |
875 | if (MAJOR(dev->devt)) | 935 | if (MAJOR(dev->devt)) |
936 | device_remove_sys_dev_entry(dev); | ||
937 | devtattrError: | ||
938 | if (MAJOR(dev->devt)) | ||
876 | device_remove_file(dev, &devt_attr); | 939 | device_remove_file(dev, &devt_attr); |
877 | ueventattrError: | 940 | ueventattrError: |
878 | device_remove_file(dev, &uevent_attr); | 941 | device_remove_file(dev, &uevent_attr); |
@@ -948,19 +1011,22 @@ void device_del(struct device *dev) | |||
948 | device_pm_remove(dev); | 1011 | device_pm_remove(dev); |
949 | if (parent) | 1012 | if (parent) |
950 | klist_del(&dev->knode_parent); | 1013 | klist_del(&dev->knode_parent); |
951 | if (MAJOR(dev->devt)) | 1014 | if (MAJOR(dev->devt)) { |
1015 | device_remove_sys_dev_entry(dev); | ||
952 | device_remove_file(dev, &devt_attr); | 1016 | device_remove_file(dev, &devt_attr); |
1017 | } | ||
953 | if (dev->class) { | 1018 | if (dev->class) { |
954 | device_remove_class_symlinks(dev); | 1019 | device_remove_class_symlinks(dev); |
955 | 1020 | ||
956 | down(&dev->class->sem); | 1021 | mutex_lock(&dev->class->p->class_mutex); |
957 | /* notify any interfaces that the device is now gone */ | 1022 | /* notify any interfaces that the device is now gone */ |
958 | list_for_each_entry(class_intf, &dev->class->interfaces, node) | 1023 | list_for_each_entry(class_intf, |
1024 | &dev->class->p->class_interfaces, node) | ||
959 | if (class_intf->remove_dev) | 1025 | if (class_intf->remove_dev) |
960 | class_intf->remove_dev(dev, class_intf); | 1026 | class_intf->remove_dev(dev, class_intf); |
961 | /* remove the device from the class list */ | 1027 | /* remove the device from the class list */ |
962 | list_del_init(&dev->node); | 1028 | list_del_init(&dev->node); |
963 | up(&dev->class->sem); | 1029 | mutex_unlock(&dev->class->p->class_mutex); |
964 | } | 1030 | } |
965 | device_remove_file(dev, &uevent_attr); | 1031 | device_remove_file(dev, &uevent_attr); |
966 | device_remove_attrs(dev); | 1032 | device_remove_attrs(dev); |
@@ -1074,7 +1140,25 @@ int __init devices_init(void) | |||
1074 | devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL); | 1140 | devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL); |
1075 | if (!devices_kset) | 1141 | if (!devices_kset) |
1076 | return -ENOMEM; | 1142 | return -ENOMEM; |
1143 | dev_kobj = kobject_create_and_add("dev", NULL); | ||
1144 | if (!dev_kobj) | ||
1145 | goto dev_kobj_err; | ||
1146 | sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj); | ||
1147 | if (!sysfs_dev_block_kobj) | ||
1148 | goto block_kobj_err; | ||
1149 | sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj); | ||
1150 | if (!sysfs_dev_char_kobj) | ||
1151 | goto char_kobj_err; | ||
1152 | |||
1077 | return 0; | 1153 | return 0; |
1154 | |||
1155 | char_kobj_err: | ||
1156 | kobject_put(sysfs_dev_block_kobj); | ||
1157 | block_kobj_err: | ||
1158 | kobject_put(dev_kobj); | ||
1159 | dev_kobj_err: | ||
1160 | kset_unregister(devices_kset); | ||
1161 | return -ENOMEM; | ||
1078 | } | 1162 | } |
1079 | 1163 | ||
1080 | EXPORT_SYMBOL_GPL(device_for_each_child); | 1164 | EXPORT_SYMBOL_GPL(device_for_each_child); |
@@ -1158,48 +1242,11 @@ error: | |||
1158 | EXPORT_SYMBOL_GPL(device_create_vargs); | 1242 | EXPORT_SYMBOL_GPL(device_create_vargs); |
1159 | 1243 | ||
1160 | /** | 1244 | /** |
1161 | * device_create_drvdata - creates a device and registers it with sysfs | ||
1162 | * @class: pointer to the struct class that this device should be registered to | ||
1163 | * @parent: pointer to the parent struct device of this new device, if any | ||
1164 | * @devt: the dev_t for the char device to be added | ||
1165 | * @drvdata: the data to be added to the device for callbacks | ||
1166 | * @fmt: string for the device's name | ||
1167 | * | ||
1168 | * This function can be used by char device classes. A struct device | ||
1169 | * will be created in sysfs, registered to the specified class. | ||
1170 | * | ||
1171 | * A "dev" file will be created, showing the dev_t for the device, if | ||
1172 | * the dev_t is not 0,0. | ||
1173 | * If a pointer to a parent struct device is passed in, the newly created | ||
1174 | * struct device will be a child of that device in sysfs. | ||
1175 | * The pointer to the struct device will be returned from the call. | ||
1176 | * Any further sysfs files that might be required can be created using this | ||
1177 | * pointer. | ||
1178 | * | ||
1179 | * Note: the struct class passed to this function must have previously | ||
1180 | * been created with a call to class_create(). | ||
1181 | */ | ||
1182 | struct device *device_create_drvdata(struct class *class, | ||
1183 | struct device *parent, | ||
1184 | dev_t devt, | ||
1185 | void *drvdata, | ||
1186 | const char *fmt, ...) | ||
1187 | { | ||
1188 | va_list vargs; | ||
1189 | struct device *dev; | ||
1190 | |||
1191 | va_start(vargs, fmt); | ||
1192 | dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs); | ||
1193 | va_end(vargs); | ||
1194 | return dev; | ||
1195 | } | ||
1196 | EXPORT_SYMBOL_GPL(device_create_drvdata); | ||
1197 | |||
1198 | /** | ||
1199 | * device_create - creates a device and registers it with sysfs | 1245 | * device_create - creates a device and registers it with sysfs |
1200 | * @class: pointer to the struct class that this device should be registered to | 1246 | * @class: pointer to the struct class that this device should be registered to |
1201 | * @parent: pointer to the parent struct device of this new device, if any | 1247 | * @parent: pointer to the parent struct device of this new device, if any |
1202 | * @devt: the dev_t for the char device to be added | 1248 | * @devt: the dev_t for the char device to be added |
1249 | * @drvdata: the data to be added to the device for callbacks | ||
1203 | * @fmt: string for the device's name | 1250 | * @fmt: string for the device's name |
1204 | * | 1251 | * |
1205 | * This function can be used by char device classes. A struct device | 1252 | * This function can be used by char device classes. A struct device |
@@ -1217,13 +1264,13 @@ EXPORT_SYMBOL_GPL(device_create_drvdata); | |||
1217 | * been created with a call to class_create(). | 1264 | * been created with a call to class_create(). |
1218 | */ | 1265 | */ |
1219 | struct device *device_create(struct class *class, struct device *parent, | 1266 | struct device *device_create(struct class *class, struct device *parent, |
1220 | dev_t devt, const char *fmt, ...) | 1267 | dev_t devt, void *drvdata, const char *fmt, ...) |
1221 | { | 1268 | { |
1222 | va_list vargs; | 1269 | va_list vargs; |
1223 | struct device *dev; | 1270 | struct device *dev; |
1224 | 1271 | ||
1225 | va_start(vargs, fmt); | 1272 | va_start(vargs, fmt); |
1226 | dev = device_create_vargs(class, parent, devt, NULL, fmt, vargs); | 1273 | dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs); |
1227 | va_end(vargs); | 1274 | va_end(vargs); |
1228 | return dev; | 1275 | return dev; |
1229 | } | 1276 | } |
@@ -1248,7 +1295,7 @@ void device_destroy(struct class *class, dev_t devt) | |||
1248 | { | 1295 | { |
1249 | struct device *dev; | 1296 | struct device *dev; |
1250 | 1297 | ||
1251 | dev = class_find_device(class, &devt, __match_devt); | 1298 | dev = class_find_device(class, NULL, &devt, __match_devt); |
1252 | if (dev) { | 1299 | if (dev) { |
1253 | put_device(dev); | 1300 | put_device(dev); |
1254 | device_unregister(dev); | 1301 | device_unregister(dev); |
@@ -1298,8 +1345,9 @@ int device_rename(struct device *dev, char *new_name) | |||
1298 | if (old_class_name) { | 1345 | if (old_class_name) { |
1299 | new_class_name = make_class_name(dev->class->name, &dev->kobj); | 1346 | new_class_name = make_class_name(dev->class->name, &dev->kobj); |
1300 | if (new_class_name) { | 1347 | if (new_class_name) { |
1301 | error = sysfs_create_link(&dev->parent->kobj, | 1348 | error = sysfs_create_link_nowarn(&dev->parent->kobj, |
1302 | &dev->kobj, new_class_name); | 1349 | &dev->kobj, |
1350 | new_class_name); | ||
1303 | if (error) | 1351 | if (error) |
1304 | goto out; | 1352 | goto out; |
1305 | sysfs_remove_link(&dev->parent->kobj, old_class_name); | 1353 | sysfs_remove_link(&dev->parent->kobj, old_class_name); |
@@ -1307,11 +1355,12 @@ int device_rename(struct device *dev, char *new_name) | |||
1307 | } | 1355 | } |
1308 | #else | 1356 | #else |
1309 | if (dev->class) { | 1357 | if (dev->class) { |
1310 | error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj, | 1358 | error = sysfs_create_link_nowarn(&dev->class->p->class_subsys.kobj, |
1311 | dev->bus_id); | 1359 | &dev->kobj, dev->bus_id); |
1312 | if (error) | 1360 | if (error) |
1313 | goto out; | 1361 | goto out; |
1314 | sysfs_remove_link(&dev->class->subsys.kobj, old_device_name); | 1362 | sysfs_remove_link(&dev->class->p->class_subsys.kobj, |
1363 | old_device_name); | ||
1315 | } | 1364 | } |
1316 | #endif | 1365 | #endif |
1317 | 1366 | ||
@@ -1447,4 +1496,7 @@ void device_shutdown(void) | |||
1447 | dev->driver->shutdown(dev); | 1496 | dev->driver->shutdown(dev); |
1448 | } | 1497 | } |
1449 | } | 1498 | } |
1499 | kobject_put(sysfs_dev_char_kobj); | ||
1500 | kobject_put(sysfs_dev_block_kobj); | ||
1501 | kobject_put(dev_kobj); | ||
1450 | } | 1502 | } |
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c index e38dfed41d80..64f5d54f7edc 100644 --- a/drivers/base/cpu.c +++ b/drivers/base/cpu.c | |||
@@ -21,15 +21,16 @@ EXPORT_SYMBOL(cpu_sysdev_class); | |||
21 | static DEFINE_PER_CPU(struct sys_device *, cpu_sys_devices); | 21 | static DEFINE_PER_CPU(struct sys_device *, cpu_sys_devices); |
22 | 22 | ||
23 | #ifdef CONFIG_HOTPLUG_CPU | 23 | #ifdef CONFIG_HOTPLUG_CPU |
24 | static ssize_t show_online(struct sys_device *dev, char *buf) | 24 | static ssize_t show_online(struct sys_device *dev, struct sysdev_attribute *attr, |
25 | char *buf) | ||
25 | { | 26 | { |
26 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); | 27 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); |
27 | 28 | ||
28 | return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id)); | 29 | return sprintf(buf, "%u\n", !!cpu_online(cpu->sysdev.id)); |
29 | } | 30 | } |
30 | 31 | ||
31 | static ssize_t __ref store_online(struct sys_device *dev, const char *buf, | 32 | static ssize_t __ref store_online(struct sys_device *dev, struct sysdev_attribute *attr, |
32 | size_t count) | 33 | const char *buf, size_t count) |
33 | { | 34 | { |
34 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); | 35 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); |
35 | ssize_t ret; | 36 | ssize_t ret; |
@@ -80,7 +81,8 @@ static inline void register_cpu_control(struct cpu *cpu) | |||
80 | #ifdef CONFIG_KEXEC | 81 | #ifdef CONFIG_KEXEC |
81 | #include <linux/kexec.h> | 82 | #include <linux/kexec.h> |
82 | 83 | ||
83 | static ssize_t show_crash_notes(struct sys_device *dev, char *buf) | 84 | static ssize_t show_crash_notes(struct sys_device *dev, struct sysdev_attribute *attr, |
85 | char *buf) | ||
84 | { | 86 | { |
85 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); | 87 | struct cpu *cpu = container_of(dev, struct cpu, sysdev); |
86 | ssize_t rc; | 88 | ssize_t rc; |
@@ -119,14 +121,14 @@ static ssize_t print_cpus_##type(struct sysdev_class *class, char *buf) \ | |||
119 | { \ | 121 | { \ |
120 | return print_cpus_map(buf, &cpu_##type##_map); \ | 122 | return print_cpus_map(buf, &cpu_##type##_map); \ |
121 | } \ | 123 | } \ |
122 | struct sysdev_class_attribute attr_##type##_map = \ | 124 | static struct sysdev_class_attribute attr_##type##_map = \ |
123 | _SYSDEV_CLASS_ATTR(type, 0444, print_cpus_##type, NULL) | 125 | _SYSDEV_CLASS_ATTR(type, 0444, print_cpus_##type, NULL) |
124 | 126 | ||
125 | print_cpus_func(online); | 127 | print_cpus_func(online); |
126 | print_cpus_func(possible); | 128 | print_cpus_func(possible); |
127 | print_cpus_func(present); | 129 | print_cpus_func(present); |
128 | 130 | ||
129 | struct sysdev_class_attribute *cpu_state_attr[] = { | 131 | static struct sysdev_class_attribute *cpu_state_attr[] = { |
130 | &attr_online_map, | 132 | &attr_online_map, |
131 | &attr_possible_map, | 133 | &attr_possible_map, |
132 | &attr_present_map, | 134 | &attr_present_map, |
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c index 9fd4a8534146..b0be1d18fee2 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -49,6 +49,14 @@ struct firmware_priv { | |||
49 | struct timer_list timeout; | 49 | struct timer_list timeout; |
50 | }; | 50 | }; |
51 | 51 | ||
52 | #ifdef CONFIG_FW_LOADER | ||
53 | extern struct builtin_fw __start_builtin_fw[]; | ||
54 | extern struct builtin_fw __end_builtin_fw[]; | ||
55 | #else /* Module case. Avoid ifdefs later; it'll all optimise out */ | ||
56 | static struct builtin_fw *__start_builtin_fw; | ||
57 | static struct builtin_fw *__end_builtin_fw; | ||
58 | #endif | ||
59 | |||
52 | static void | 60 | static void |
53 | fw_load_abort(struct firmware_priv *fw_priv) | 61 | fw_load_abort(struct firmware_priv *fw_priv) |
54 | { | 62 | { |
@@ -257,7 +265,7 @@ firmware_data_write(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
257 | if (retval) | 265 | if (retval) |
258 | goto out; | 266 | goto out; |
259 | 267 | ||
260 | memcpy(fw->data + offset, buffer, count); | 268 | memcpy((u8 *)fw->data + offset, buffer, count); |
261 | 269 | ||
262 | fw->size = max_t(size_t, offset + count, fw->size); | 270 | fw->size = max_t(size_t, offset + count, fw->size); |
263 | retval = count; | 271 | retval = count; |
@@ -391,13 +399,12 @@ _request_firmware(const struct firmware **firmware_p, const char *name, | |||
391 | struct device *f_dev; | 399 | struct device *f_dev; |
392 | struct firmware_priv *fw_priv; | 400 | struct firmware_priv *fw_priv; |
393 | struct firmware *firmware; | 401 | struct firmware *firmware; |
402 | struct builtin_fw *builtin; | ||
394 | int retval; | 403 | int retval; |
395 | 404 | ||
396 | if (!firmware_p) | 405 | if (!firmware_p) |
397 | return -EINVAL; | 406 | return -EINVAL; |
398 | 407 | ||
399 | printk(KERN_INFO "firmware: requesting %s\n", name); | ||
400 | |||
401 | *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL); | 408 | *firmware_p = firmware = kzalloc(sizeof(*firmware), GFP_KERNEL); |
402 | if (!firmware) { | 409 | if (!firmware) { |
403 | printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n", | 410 | printk(KERN_ERR "%s: kmalloc(struct firmware) failed\n", |
@@ -406,6 +413,20 @@ _request_firmware(const struct firmware **firmware_p, const char *name, | |||
406 | goto out; | 413 | goto out; |
407 | } | 414 | } |
408 | 415 | ||
416 | for (builtin = __start_builtin_fw; builtin != __end_builtin_fw; | ||
417 | builtin++) { | ||
418 | if (strcmp(name, builtin->name)) | ||
419 | continue; | ||
420 | printk(KERN_INFO "firmware: using built-in firmware %s\n", | ||
421 | name); | ||
422 | firmware->size = builtin->size; | ||
423 | firmware->data = builtin->data; | ||
424 | return 0; | ||
425 | } | ||
426 | |||
427 | if (uevent) | ||
428 | printk(KERN_INFO "firmware: requesting %s\n", name); | ||
429 | |||
409 | retval = fw_setup_device(firmware, &f_dev, name, device, uevent); | 430 | retval = fw_setup_device(firmware, &f_dev, name, device, uevent); |
410 | if (retval) | 431 | if (retval) |
411 | goto error_kfree_fw; | 432 | goto error_kfree_fw; |
@@ -473,8 +494,16 @@ request_firmware(const struct firmware **firmware_p, const char *name, | |||
473 | void | 494 | void |
474 | release_firmware(const struct firmware *fw) | 495 | release_firmware(const struct firmware *fw) |
475 | { | 496 | { |
497 | struct builtin_fw *builtin; | ||
498 | |||
476 | if (fw) { | 499 | if (fw) { |
500 | for (builtin = __start_builtin_fw; builtin != __end_builtin_fw; | ||
501 | builtin++) { | ||
502 | if (fw->data == builtin->data) | ||
503 | goto free_fw; | ||
504 | } | ||
477 | vfree(fw->data); | 505 | vfree(fw->data); |
506 | free_fw: | ||
478 | kfree(fw); | 507 | kfree(fw); |
479 | } | 508 | } |
480 | } | 509 | } |
diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 937e8258981d..4d4e0e7b6e92 100644 --- a/drivers/base/memory.c +++ b/drivers/base/memory.c | |||
@@ -92,7 +92,8 @@ unregister_memory(struct memory_block *memory, struct mem_section *section) | |||
92 | * uses. | 92 | * uses. |
93 | */ | 93 | */ |
94 | 94 | ||
95 | static ssize_t show_mem_phys_index(struct sys_device *dev, char *buf) | 95 | static ssize_t show_mem_phys_index(struct sys_device *dev, |
96 | struct sysdev_attribute *attr, char *buf) | ||
96 | { | 97 | { |
97 | struct memory_block *mem = | 98 | struct memory_block *mem = |
98 | container_of(dev, struct memory_block, sysdev); | 99 | container_of(dev, struct memory_block, sysdev); |
@@ -102,7 +103,8 @@ static ssize_t show_mem_phys_index(struct sys_device *dev, char *buf) | |||
102 | /* | 103 | /* |
103 | * online, offline, going offline, etc. | 104 | * online, offline, going offline, etc. |
104 | */ | 105 | */ |
105 | static ssize_t show_mem_state(struct sys_device *dev, char *buf) | 106 | static ssize_t show_mem_state(struct sys_device *dev, |
107 | struct sysdev_attribute *attr, char *buf) | ||
106 | { | 108 | { |
107 | struct memory_block *mem = | 109 | struct memory_block *mem = |
108 | container_of(dev, struct memory_block, sysdev); | 110 | container_of(dev, struct memory_block, sysdev); |
@@ -217,7 +219,8 @@ out: | |||
217 | } | 219 | } |
218 | 220 | ||
219 | static ssize_t | 221 | static ssize_t |
220 | store_mem_state(struct sys_device *dev, const char *buf, size_t count) | 222 | store_mem_state(struct sys_device *dev, |
223 | struct sysdev_attribute *attr, const char *buf, size_t count) | ||
221 | { | 224 | { |
222 | struct memory_block *mem; | 225 | struct memory_block *mem; |
223 | unsigned int phys_section_nr; | 226 | unsigned int phys_section_nr; |
@@ -248,7 +251,8 @@ out: | |||
248 | * s.t. if I offline all of these sections I can then | 251 | * s.t. if I offline all of these sections I can then |
249 | * remove the physical device? | 252 | * remove the physical device? |
250 | */ | 253 | */ |
251 | static ssize_t show_phys_device(struct sys_device *dev, char *buf) | 254 | static ssize_t show_phys_device(struct sys_device *dev, |
255 | struct sysdev_attribute *attr, char *buf) | ||
252 | { | 256 | { |
253 | struct memory_block *mem = | 257 | struct memory_block *mem = |
254 | container_of(dev, struct memory_block, sysdev); | 258 | container_of(dev, struct memory_block, sysdev); |
diff --git a/drivers/base/node.c b/drivers/base/node.c index 0f867a083338..5116b78c6325 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c | |||
@@ -36,11 +36,13 @@ static ssize_t node_read_cpumap(struct sys_device *dev, int type, char *buf) | |||
36 | return len; | 36 | return len; |
37 | } | 37 | } |
38 | 38 | ||
39 | static inline ssize_t node_read_cpumask(struct sys_device *dev, char *buf) | 39 | static inline ssize_t node_read_cpumask(struct sys_device *dev, |
40 | struct sysdev_attribute *attr, char *buf) | ||
40 | { | 41 | { |
41 | return node_read_cpumap(dev, 0, buf); | 42 | return node_read_cpumap(dev, 0, buf); |
42 | } | 43 | } |
43 | static inline ssize_t node_read_cpulist(struct sys_device *dev, char *buf) | 44 | static inline ssize_t node_read_cpulist(struct sys_device *dev, |
45 | struct sysdev_attribute *attr, char *buf) | ||
44 | { | 46 | { |
45 | return node_read_cpumap(dev, 1, buf); | 47 | return node_read_cpumap(dev, 1, buf); |
46 | } | 48 | } |
@@ -49,7 +51,8 @@ static SYSDEV_ATTR(cpumap, S_IRUGO, node_read_cpumask, NULL); | |||
49 | static SYSDEV_ATTR(cpulist, S_IRUGO, node_read_cpulist, NULL); | 51 | static SYSDEV_ATTR(cpulist, S_IRUGO, node_read_cpulist, NULL); |
50 | 52 | ||
51 | #define K(x) ((x) << (PAGE_SHIFT - 10)) | 53 | #define K(x) ((x) << (PAGE_SHIFT - 10)) |
52 | static ssize_t node_read_meminfo(struct sys_device * dev, char * buf) | 54 | static ssize_t node_read_meminfo(struct sys_device * dev, |
55 | struct sysdev_attribute *attr, char * buf) | ||
53 | { | 56 | { |
54 | int n; | 57 | int n; |
55 | int nid = dev->id; | 58 | int nid = dev->id; |
@@ -112,7 +115,8 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf) | |||
112 | #undef K | 115 | #undef K |
113 | static SYSDEV_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL); | 116 | static SYSDEV_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL); |
114 | 117 | ||
115 | static ssize_t node_read_numastat(struct sys_device * dev, char * buf) | 118 | static ssize_t node_read_numastat(struct sys_device * dev, |
119 | struct sysdev_attribute *attr, char * buf) | ||
116 | { | 120 | { |
117 | return sprintf(buf, | 121 | return sprintf(buf, |
118 | "numa_hit %lu\n" | 122 | "numa_hit %lu\n" |
@@ -130,7 +134,8 @@ static ssize_t node_read_numastat(struct sys_device * dev, char * buf) | |||
130 | } | 134 | } |
131 | static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL); | 135 | static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL); |
132 | 136 | ||
133 | static ssize_t node_read_distance(struct sys_device * dev, char * buf) | 137 | static ssize_t node_read_distance(struct sys_device * dev, |
138 | struct sysdev_attribute *attr, char * buf) | ||
134 | { | 139 | { |
135 | int nid = dev->id; | 140 | int nid = dev->id; |
136 | int len = 0; | 141 | int len = 0; |
diff --git a/drivers/base/platform.c b/drivers/base/platform.c index 911ec600fe71..3f940393d6c7 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c | |||
@@ -453,6 +453,8 @@ int platform_driver_register(struct platform_driver *drv) | |||
453 | drv->driver.suspend = platform_drv_suspend; | 453 | drv->driver.suspend = platform_drv_suspend; |
454 | if (drv->resume) | 454 | if (drv->resume) |
455 | drv->driver.resume = platform_drv_resume; | 455 | drv->driver.resume = platform_drv_resume; |
456 | if (drv->pm) | ||
457 | drv->driver.pm = &drv->pm->base; | ||
456 | return driver_register(&drv->driver); | 458 | return driver_register(&drv->driver); |
457 | } | 459 | } |
458 | EXPORT_SYMBOL_GPL(platform_driver_register); | 460 | EXPORT_SYMBOL_GPL(platform_driver_register); |
@@ -560,7 +562,9 @@ static int platform_match(struct device *dev, struct device_driver *drv) | |||
560 | return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0); | 562 | return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0); |
561 | } | 563 | } |
562 | 564 | ||
563 | static int platform_suspend(struct device *dev, pm_message_t mesg) | 565 | #ifdef CONFIG_PM_SLEEP |
566 | |||
567 | static int platform_legacy_suspend(struct device *dev, pm_message_t mesg) | ||
564 | { | 568 | { |
565 | int ret = 0; | 569 | int ret = 0; |
566 | 570 | ||
@@ -570,7 +574,7 @@ static int platform_suspend(struct device *dev, pm_message_t mesg) | |||
570 | return ret; | 574 | return ret; |
571 | } | 575 | } |
572 | 576 | ||
573 | static int platform_suspend_late(struct device *dev, pm_message_t mesg) | 577 | static int platform_legacy_suspend_late(struct device *dev, pm_message_t mesg) |
574 | { | 578 | { |
575 | struct platform_driver *drv = to_platform_driver(dev->driver); | 579 | struct platform_driver *drv = to_platform_driver(dev->driver); |
576 | struct platform_device *pdev; | 580 | struct platform_device *pdev; |
@@ -583,7 +587,7 @@ static int platform_suspend_late(struct device *dev, pm_message_t mesg) | |||
583 | return ret; | 587 | return ret; |
584 | } | 588 | } |
585 | 589 | ||
586 | static int platform_resume_early(struct device *dev) | 590 | static int platform_legacy_resume_early(struct device *dev) |
587 | { | 591 | { |
588 | struct platform_driver *drv = to_platform_driver(dev->driver); | 592 | struct platform_driver *drv = to_platform_driver(dev->driver); |
589 | struct platform_device *pdev; | 593 | struct platform_device *pdev; |
@@ -596,7 +600,7 @@ static int platform_resume_early(struct device *dev) | |||
596 | return ret; | 600 | return ret; |
597 | } | 601 | } |
598 | 602 | ||
599 | static int platform_resume(struct device *dev) | 603 | static int platform_legacy_resume(struct device *dev) |
600 | { | 604 | { |
601 | int ret = 0; | 605 | int ret = 0; |
602 | 606 | ||
@@ -606,15 +610,291 @@ static int platform_resume(struct device *dev) | |||
606 | return ret; | 610 | return ret; |
607 | } | 611 | } |
608 | 612 | ||
613 | static int platform_pm_prepare(struct device *dev) | ||
614 | { | ||
615 | struct device_driver *drv = dev->driver; | ||
616 | int ret = 0; | ||
617 | |||
618 | if (drv && drv->pm && drv->pm->prepare) | ||
619 | ret = drv->pm->prepare(dev); | ||
620 | |||
621 | return ret; | ||
622 | } | ||
623 | |||
624 | static void platform_pm_complete(struct device *dev) | ||
625 | { | ||
626 | struct device_driver *drv = dev->driver; | ||
627 | |||
628 | if (drv && drv->pm && drv->pm->complete) | ||
629 | drv->pm->complete(dev); | ||
630 | } | ||
631 | |||
632 | #ifdef CONFIG_SUSPEND | ||
633 | |||
634 | static int platform_pm_suspend(struct device *dev) | ||
635 | { | ||
636 | struct device_driver *drv = dev->driver; | ||
637 | int ret = 0; | ||
638 | |||
639 | if (drv && drv->pm) { | ||
640 | if (drv->pm->suspend) | ||
641 | ret = drv->pm->suspend(dev); | ||
642 | } else { | ||
643 | ret = platform_legacy_suspend(dev, PMSG_SUSPEND); | ||
644 | } | ||
645 | |||
646 | return ret; | ||
647 | } | ||
648 | |||
649 | static int platform_pm_suspend_noirq(struct device *dev) | ||
650 | { | ||
651 | struct platform_driver *pdrv; | ||
652 | int ret = 0; | ||
653 | |||
654 | if (!dev->driver) | ||
655 | return 0; | ||
656 | |||
657 | pdrv = to_platform_driver(dev->driver); | ||
658 | if (pdrv->pm) { | ||
659 | if (pdrv->pm->suspend_noirq) | ||
660 | ret = pdrv->pm->suspend_noirq(dev); | ||
661 | } else { | ||
662 | ret = platform_legacy_suspend_late(dev, PMSG_SUSPEND); | ||
663 | } | ||
664 | |||
665 | return ret; | ||
666 | } | ||
667 | |||
668 | static int platform_pm_resume(struct device *dev) | ||
669 | { | ||
670 | struct device_driver *drv = dev->driver; | ||
671 | int ret = 0; | ||
672 | |||
673 | if (drv && drv->pm) { | ||
674 | if (drv->pm->resume) | ||
675 | ret = drv->pm->resume(dev); | ||
676 | } else { | ||
677 | ret = platform_legacy_resume(dev); | ||
678 | } | ||
679 | |||
680 | return ret; | ||
681 | } | ||
682 | |||
683 | static int platform_pm_resume_noirq(struct device *dev) | ||
684 | { | ||
685 | struct platform_driver *pdrv; | ||
686 | int ret = 0; | ||
687 | |||
688 | if (!dev->driver) | ||
689 | return 0; | ||
690 | |||
691 | pdrv = to_platform_driver(dev->driver); | ||
692 | if (pdrv->pm) { | ||
693 | if (pdrv->pm->resume_noirq) | ||
694 | ret = pdrv->pm->resume_noirq(dev); | ||
695 | } else { | ||
696 | ret = platform_legacy_resume_early(dev); | ||
697 | } | ||
698 | |||
699 | return ret; | ||
700 | } | ||
701 | |||
702 | #else /* !CONFIG_SUSPEND */ | ||
703 | |||
704 | #define platform_pm_suspend NULL | ||
705 | #define platform_pm_resume NULL | ||
706 | #define platform_pm_suspend_noirq NULL | ||
707 | #define platform_pm_resume_noirq NULL | ||
708 | |||
709 | #endif /* !CONFIG_SUSPEND */ | ||
710 | |||
711 | #ifdef CONFIG_HIBERNATION | ||
712 | |||
713 | static int platform_pm_freeze(struct device *dev) | ||
714 | { | ||
715 | struct device_driver *drv = dev->driver; | ||
716 | int ret = 0; | ||
717 | |||
718 | if (!drv) | ||
719 | return 0; | ||
720 | |||
721 | if (drv->pm) { | ||
722 | if (drv->pm->freeze) | ||
723 | ret = drv->pm->freeze(dev); | ||
724 | } else { | ||
725 | ret = platform_legacy_suspend(dev, PMSG_FREEZE); | ||
726 | } | ||
727 | |||
728 | return ret; | ||
729 | } | ||
730 | |||
731 | static int platform_pm_freeze_noirq(struct device *dev) | ||
732 | { | ||
733 | struct platform_driver *pdrv; | ||
734 | int ret = 0; | ||
735 | |||
736 | if (!dev->driver) | ||
737 | return 0; | ||
738 | |||
739 | pdrv = to_platform_driver(dev->driver); | ||
740 | if (pdrv->pm) { | ||
741 | if (pdrv->pm->freeze_noirq) | ||
742 | ret = pdrv->pm->freeze_noirq(dev); | ||
743 | } else { | ||
744 | ret = platform_legacy_suspend_late(dev, PMSG_FREEZE); | ||
745 | } | ||
746 | |||
747 | return ret; | ||
748 | } | ||
749 | |||
750 | static int platform_pm_thaw(struct device *dev) | ||
751 | { | ||
752 | struct device_driver *drv = dev->driver; | ||
753 | int ret = 0; | ||
754 | |||
755 | if (drv && drv->pm) { | ||
756 | if (drv->pm->thaw) | ||
757 | ret = drv->pm->thaw(dev); | ||
758 | } else { | ||
759 | ret = platform_legacy_resume(dev); | ||
760 | } | ||
761 | |||
762 | return ret; | ||
763 | } | ||
764 | |||
765 | static int platform_pm_thaw_noirq(struct device *dev) | ||
766 | { | ||
767 | struct platform_driver *pdrv; | ||
768 | int ret = 0; | ||
769 | |||
770 | if (!dev->driver) | ||
771 | return 0; | ||
772 | |||
773 | pdrv = to_platform_driver(dev->driver); | ||
774 | if (pdrv->pm) { | ||
775 | if (pdrv->pm->thaw_noirq) | ||
776 | ret = pdrv->pm->thaw_noirq(dev); | ||
777 | } else { | ||
778 | ret = platform_legacy_resume_early(dev); | ||
779 | } | ||
780 | |||
781 | return ret; | ||
782 | } | ||
783 | |||
784 | static int platform_pm_poweroff(struct device *dev) | ||
785 | { | ||
786 | struct device_driver *drv = dev->driver; | ||
787 | int ret = 0; | ||
788 | |||
789 | if (drv && drv->pm) { | ||
790 | if (drv->pm->poweroff) | ||
791 | ret = drv->pm->poweroff(dev); | ||
792 | } else { | ||
793 | ret = platform_legacy_suspend(dev, PMSG_HIBERNATE); | ||
794 | } | ||
795 | |||
796 | return ret; | ||
797 | } | ||
798 | |||
799 | static int platform_pm_poweroff_noirq(struct device *dev) | ||
800 | { | ||
801 | struct platform_driver *pdrv; | ||
802 | int ret = 0; | ||
803 | |||
804 | if (!dev->driver) | ||
805 | return 0; | ||
806 | |||
807 | pdrv = to_platform_driver(dev->driver); | ||
808 | if (pdrv->pm) { | ||
809 | if (pdrv->pm->poweroff_noirq) | ||
810 | ret = pdrv->pm->poweroff_noirq(dev); | ||
811 | } else { | ||
812 | ret = platform_legacy_suspend_late(dev, PMSG_HIBERNATE); | ||
813 | } | ||
814 | |||
815 | return ret; | ||
816 | } | ||
817 | |||
818 | static int platform_pm_restore(struct device *dev) | ||
819 | { | ||
820 | struct device_driver *drv = dev->driver; | ||
821 | int ret = 0; | ||
822 | |||
823 | if (drv && drv->pm) { | ||
824 | if (drv->pm->restore) | ||
825 | ret = drv->pm->restore(dev); | ||
826 | } else { | ||
827 | ret = platform_legacy_resume(dev); | ||
828 | } | ||
829 | |||
830 | return ret; | ||
831 | } | ||
832 | |||
833 | static int platform_pm_restore_noirq(struct device *dev) | ||
834 | { | ||
835 | struct platform_driver *pdrv; | ||
836 | int ret = 0; | ||
837 | |||
838 | if (!dev->driver) | ||
839 | return 0; | ||
840 | |||
841 | pdrv = to_platform_driver(dev->driver); | ||
842 | if (pdrv->pm) { | ||
843 | if (pdrv->pm->restore_noirq) | ||
844 | ret = pdrv->pm->restore_noirq(dev); | ||
845 | } else { | ||
846 | ret = platform_legacy_resume_early(dev); | ||
847 | } | ||
848 | |||
849 | return ret; | ||
850 | } | ||
851 | |||
852 | #else /* !CONFIG_HIBERNATION */ | ||
853 | |||
854 | #define platform_pm_freeze NULL | ||
855 | #define platform_pm_thaw NULL | ||
856 | #define platform_pm_poweroff NULL | ||
857 | #define platform_pm_restore NULL | ||
858 | #define platform_pm_freeze_noirq NULL | ||
859 | #define platform_pm_thaw_noirq NULL | ||
860 | #define platform_pm_poweroff_noirq NULL | ||
861 | #define platform_pm_restore_noirq NULL | ||
862 | |||
863 | #endif /* !CONFIG_HIBERNATION */ | ||
864 | |||
865 | struct pm_ext_ops platform_pm_ops = { | ||
866 | .base = { | ||
867 | .prepare = platform_pm_prepare, | ||
868 | .complete = platform_pm_complete, | ||
869 | .suspend = platform_pm_suspend, | ||
870 | .resume = platform_pm_resume, | ||
871 | .freeze = platform_pm_freeze, | ||
872 | .thaw = platform_pm_thaw, | ||
873 | .poweroff = platform_pm_poweroff, | ||
874 | .restore = platform_pm_restore, | ||
875 | }, | ||
876 | .suspend_noirq = platform_pm_suspend_noirq, | ||
877 | .resume_noirq = platform_pm_resume_noirq, | ||
878 | .freeze_noirq = platform_pm_freeze_noirq, | ||
879 | .thaw_noirq = platform_pm_thaw_noirq, | ||
880 | .poweroff_noirq = platform_pm_poweroff_noirq, | ||
881 | .restore_noirq = platform_pm_restore_noirq, | ||
882 | }; | ||
883 | |||
884 | #define PLATFORM_PM_OPS_PTR &platform_pm_ops | ||
885 | |||
886 | #else /* !CONFIG_PM_SLEEP */ | ||
887 | |||
888 | #define PLATFORM_PM_OPS_PTR NULL | ||
889 | |||
890 | #endif /* !CONFIG_PM_SLEEP */ | ||
891 | |||
609 | struct bus_type platform_bus_type = { | 892 | struct bus_type platform_bus_type = { |
610 | .name = "platform", | 893 | .name = "platform", |
611 | .dev_attrs = platform_dev_attrs, | 894 | .dev_attrs = platform_dev_attrs, |
612 | .match = platform_match, | 895 | .match = platform_match, |
613 | .uevent = platform_uevent, | 896 | .uevent = platform_uevent, |
614 | .suspend = platform_suspend, | 897 | .pm = PLATFORM_PM_OPS_PTR, |
615 | .suspend_late = platform_suspend_late, | ||
616 | .resume_early = platform_resume_early, | ||
617 | .resume = platform_resume, | ||
618 | }; | 898 | }; |
619 | EXPORT_SYMBOL_GPL(platform_bus_type); | 899 | EXPORT_SYMBOL_GPL(platform_bus_type); |
620 | 900 | ||
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 45cc3d9eacb8..3250c5257b74 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -12,11 +12,9 @@ | |||
12 | * and add it to the list of power-controlled devices. sysfs entries for | 12 | * and add it to the list of power-controlled devices. sysfs entries for |
13 | * controlling device power management will also be added. | 13 | * controlling device power management will also be added. |
14 | * | 14 | * |
15 | * A different set of lists than the global subsystem list are used to | 15 | * A separate list is used for keeping track of power info, because the power |
16 | * keep track of power info because we use different lists to hold | 16 | * domain dependencies may differ from the ancestral dependencies that the |
17 | * devices based on what stage of the power management process they | 17 | * subsystem list maintains. |
18 | * are in. The power domain dependencies may also differ from the | ||
19 | * ancestral dependencies that the subsystem list maintains. | ||
20 | */ | 18 | */ |
21 | 19 | ||
22 | #include <linux/device.h> | 20 | #include <linux/device.h> |
@@ -30,31 +28,40 @@ | |||
30 | #include "power.h" | 28 | #include "power.h" |
31 | 29 | ||
32 | /* | 30 | /* |
33 | * The entries in the dpm_active list are in a depth first order, simply | 31 | * The entries in the dpm_list list are in a depth first order, simply |
34 | * because children are guaranteed to be discovered after parents, and | 32 | * because children are guaranteed to be discovered after parents, and |
35 | * are inserted at the back of the list on discovery. | 33 | * are inserted at the back of the list on discovery. |
36 | * | 34 | * |
37 | * All the other lists are kept in the same order, for consistency. | ||
38 | * However the lists aren't always traversed in the same order. | ||
39 | * Semaphores must be acquired from the top (i.e., front) down | ||
40 | * and released in the opposite order. Devices must be suspended | ||
41 | * from the bottom (i.e., end) up and resumed in the opposite order. | ||
42 | * That way no parent will be suspended while it still has an active | ||
43 | * child. | ||
44 | * | ||
45 | * Since device_pm_add() may be called with a device semaphore held, | 35 | * Since device_pm_add() may be called with a device semaphore held, |
46 | * we must never try to acquire a device semaphore while holding | 36 | * we must never try to acquire a device semaphore while holding |
47 | * dpm_list_mutex. | 37 | * dpm_list_mutex. |
48 | */ | 38 | */ |
49 | 39 | ||
50 | LIST_HEAD(dpm_active); | 40 | LIST_HEAD(dpm_list); |
51 | static LIST_HEAD(dpm_off); | ||
52 | static LIST_HEAD(dpm_off_irq); | ||
53 | 41 | ||
54 | static DEFINE_MUTEX(dpm_list_mtx); | 42 | static DEFINE_MUTEX(dpm_list_mtx); |
55 | 43 | ||
56 | /* 'true' if all devices have been suspended, protected by dpm_list_mtx */ | 44 | /* |
57 | static bool all_sleeping; | 45 | * Set once the preparation of devices for a PM transition has started, reset |
46 | * before starting to resume devices. Protected by dpm_list_mtx. | ||
47 | */ | ||
48 | static bool transition_started; | ||
49 | |||
50 | /** | ||
51 | * device_pm_lock - lock the list of active devices used by the PM core | ||
52 | */ | ||
53 | void device_pm_lock(void) | ||
54 | { | ||
55 | mutex_lock(&dpm_list_mtx); | ||
56 | } | ||
57 | |||
58 | /** | ||
59 | * device_pm_unlock - unlock the list of active devices used by the PM core | ||
60 | */ | ||
61 | void device_pm_unlock(void) | ||
62 | { | ||
63 | mutex_unlock(&dpm_list_mtx); | ||
64 | } | ||
58 | 65 | ||
59 | /** | 66 | /** |
60 | * device_pm_add - add a device to the list of active devices | 67 | * device_pm_add - add a device to the list of active devices |
@@ -68,17 +75,25 @@ int device_pm_add(struct device *dev) | |||
68 | dev->bus ? dev->bus->name : "No Bus", | 75 | dev->bus ? dev->bus->name : "No Bus", |
69 | kobject_name(&dev->kobj)); | 76 | kobject_name(&dev->kobj)); |
70 | mutex_lock(&dpm_list_mtx); | 77 | mutex_lock(&dpm_list_mtx); |
71 | if ((dev->parent && dev->parent->power.sleeping) || all_sleeping) { | 78 | if (dev->parent) { |
72 | if (dev->parent->power.sleeping) | 79 | if (dev->parent->power.status >= DPM_SUSPENDING) { |
73 | dev_warn(dev, "parent %s is sleeping\n", | 80 | dev_warn(dev, "parent %s is sleeping, will not add\n", |
74 | dev->parent->bus_id); | 81 | dev->parent->bus_id); |
75 | else | 82 | WARN_ON(true); |
76 | dev_warn(dev, "all devices are sleeping\n"); | 83 | } |
84 | } else if (transition_started) { | ||
85 | /* | ||
86 | * We refuse to register parentless devices while a PM | ||
87 | * transition is in progress in order to avoid leaving them | ||
88 | * unhandled down the road | ||
89 | */ | ||
77 | WARN_ON(true); | 90 | WARN_ON(true); |
78 | } | 91 | } |
79 | error = dpm_sysfs_add(dev); | 92 | error = dpm_sysfs_add(dev); |
80 | if (!error) | 93 | if (!error) { |
81 | list_add_tail(&dev->power.entry, &dpm_active); | 94 | dev->power.status = DPM_ON; |
95 | list_add_tail(&dev->power.entry, &dpm_list); | ||
96 | } | ||
82 | mutex_unlock(&dpm_list_mtx); | 97 | mutex_unlock(&dpm_list_mtx); |
83 | return error; | 98 | return error; |
84 | } | 99 | } |
@@ -100,73 +115,243 @@ void device_pm_remove(struct device *dev) | |||
100 | mutex_unlock(&dpm_list_mtx); | 115 | mutex_unlock(&dpm_list_mtx); |
101 | } | 116 | } |
102 | 117 | ||
118 | /** | ||
119 | * pm_op - execute the PM operation appropiate for given PM event | ||
120 | * @dev: Device. | ||
121 | * @ops: PM operations to choose from. | ||
122 | * @state: PM transition of the system being carried out. | ||
123 | */ | ||
124 | static int pm_op(struct device *dev, struct pm_ops *ops, pm_message_t state) | ||
125 | { | ||
126 | int error = 0; | ||
127 | |||
128 | switch (state.event) { | ||
129 | #ifdef CONFIG_SUSPEND | ||
130 | case PM_EVENT_SUSPEND: | ||
131 | if (ops->suspend) { | ||
132 | error = ops->suspend(dev); | ||
133 | suspend_report_result(ops->suspend, error); | ||
134 | } | ||
135 | break; | ||
136 | case PM_EVENT_RESUME: | ||
137 | if (ops->resume) { | ||
138 | error = ops->resume(dev); | ||
139 | suspend_report_result(ops->resume, error); | ||
140 | } | ||
141 | break; | ||
142 | #endif /* CONFIG_SUSPEND */ | ||
143 | #ifdef CONFIG_HIBERNATION | ||
144 | case PM_EVENT_FREEZE: | ||
145 | case PM_EVENT_QUIESCE: | ||
146 | if (ops->freeze) { | ||
147 | error = ops->freeze(dev); | ||
148 | suspend_report_result(ops->freeze, error); | ||
149 | } | ||
150 | break; | ||
151 | case PM_EVENT_HIBERNATE: | ||
152 | if (ops->poweroff) { | ||
153 | error = ops->poweroff(dev); | ||
154 | suspend_report_result(ops->poweroff, error); | ||
155 | } | ||
156 | break; | ||
157 | case PM_EVENT_THAW: | ||
158 | case PM_EVENT_RECOVER: | ||
159 | if (ops->thaw) { | ||
160 | error = ops->thaw(dev); | ||
161 | suspend_report_result(ops->thaw, error); | ||
162 | } | ||
163 | break; | ||
164 | case PM_EVENT_RESTORE: | ||
165 | if (ops->restore) { | ||
166 | error = ops->restore(dev); | ||
167 | suspend_report_result(ops->restore, error); | ||
168 | } | ||
169 | break; | ||
170 | #endif /* CONFIG_HIBERNATION */ | ||
171 | default: | ||
172 | error = -EINVAL; | ||
173 | } | ||
174 | return error; | ||
175 | } | ||
176 | |||
177 | /** | ||
178 | * pm_noirq_op - execute the PM operation appropiate for given PM event | ||
179 | * @dev: Device. | ||
180 | * @ops: PM operations to choose from. | ||
181 | * @state: PM transition of the system being carried out. | ||
182 | * | ||
183 | * The operation is executed with interrupts disabled by the only remaining | ||
184 | * functional CPU in the system. | ||
185 | */ | ||
186 | static int pm_noirq_op(struct device *dev, struct pm_ext_ops *ops, | ||
187 | pm_message_t state) | ||
188 | { | ||
189 | int error = 0; | ||
190 | |||
191 | switch (state.event) { | ||
192 | #ifdef CONFIG_SUSPEND | ||
193 | case PM_EVENT_SUSPEND: | ||
194 | if (ops->suspend_noirq) { | ||
195 | error = ops->suspend_noirq(dev); | ||
196 | suspend_report_result(ops->suspend_noirq, error); | ||
197 | } | ||
198 | break; | ||
199 | case PM_EVENT_RESUME: | ||
200 | if (ops->resume_noirq) { | ||
201 | error = ops->resume_noirq(dev); | ||
202 | suspend_report_result(ops->resume_noirq, error); | ||
203 | } | ||
204 | break; | ||
205 | #endif /* CONFIG_SUSPEND */ | ||
206 | #ifdef CONFIG_HIBERNATION | ||
207 | case PM_EVENT_FREEZE: | ||
208 | case PM_EVENT_QUIESCE: | ||
209 | if (ops->freeze_noirq) { | ||
210 | error = ops->freeze_noirq(dev); | ||
211 | suspend_report_result(ops->freeze_noirq, error); | ||
212 | } | ||
213 | break; | ||
214 | case PM_EVENT_HIBERNATE: | ||
215 | if (ops->poweroff_noirq) { | ||
216 | error = ops->poweroff_noirq(dev); | ||
217 | suspend_report_result(ops->poweroff_noirq, error); | ||
218 | } | ||
219 | break; | ||
220 | case PM_EVENT_THAW: | ||
221 | case PM_EVENT_RECOVER: | ||
222 | if (ops->thaw_noirq) { | ||
223 | error = ops->thaw_noirq(dev); | ||
224 | suspend_report_result(ops->thaw_noirq, error); | ||
225 | } | ||
226 | break; | ||
227 | case PM_EVENT_RESTORE: | ||
228 | if (ops->restore_noirq) { | ||
229 | error = ops->restore_noirq(dev); | ||
230 | suspend_report_result(ops->restore_noirq, error); | ||
231 | } | ||
232 | break; | ||
233 | #endif /* CONFIG_HIBERNATION */ | ||
234 | default: | ||
235 | error = -EINVAL; | ||
236 | } | ||
237 | return error; | ||
238 | } | ||
239 | |||
240 | static char *pm_verb(int event) | ||
241 | { | ||
242 | switch (event) { | ||
243 | case PM_EVENT_SUSPEND: | ||
244 | return "suspend"; | ||
245 | case PM_EVENT_RESUME: | ||
246 | return "resume"; | ||
247 | case PM_EVENT_FREEZE: | ||
248 | return "freeze"; | ||
249 | case PM_EVENT_QUIESCE: | ||
250 | return "quiesce"; | ||
251 | case PM_EVENT_HIBERNATE: | ||
252 | return "hibernate"; | ||
253 | case PM_EVENT_THAW: | ||
254 | return "thaw"; | ||
255 | case PM_EVENT_RESTORE: | ||
256 | return "restore"; | ||
257 | case PM_EVENT_RECOVER: | ||
258 | return "recover"; | ||
259 | default: | ||
260 | return "(unknown PM event)"; | ||
261 | } | ||
262 | } | ||
263 | |||
264 | static void pm_dev_dbg(struct device *dev, pm_message_t state, char *info) | ||
265 | { | ||
266 | dev_dbg(dev, "%s%s%s\n", info, pm_verb(state.event), | ||
267 | ((state.event & PM_EVENT_SLEEP) && device_may_wakeup(dev)) ? | ||
268 | ", may wakeup" : ""); | ||
269 | } | ||
270 | |||
271 | static void pm_dev_err(struct device *dev, pm_message_t state, char *info, | ||
272 | int error) | ||
273 | { | ||
274 | printk(KERN_ERR "PM: Device %s failed to %s%s: error %d\n", | ||
275 | kobject_name(&dev->kobj), pm_verb(state.event), info, error); | ||
276 | } | ||
277 | |||
103 | /*------------------------- Resume routines -------------------------*/ | 278 | /*------------------------- Resume routines -------------------------*/ |
104 | 279 | ||
105 | /** | 280 | /** |
106 | * resume_device_early - Power on one device (early resume). | 281 | * resume_device_noirq - Power on one device (early resume). |
107 | * @dev: Device. | 282 | * @dev: Device. |
283 | * @state: PM transition of the system being carried out. | ||
108 | * | 284 | * |
109 | * Must be called with interrupts disabled. | 285 | * Must be called with interrupts disabled. |
110 | */ | 286 | */ |
111 | static int resume_device_early(struct device *dev) | 287 | static int resume_device_noirq(struct device *dev, pm_message_t state) |
112 | { | 288 | { |
113 | int error = 0; | 289 | int error = 0; |
114 | 290 | ||
115 | TRACE_DEVICE(dev); | 291 | TRACE_DEVICE(dev); |
116 | TRACE_RESUME(0); | 292 | TRACE_RESUME(0); |
117 | 293 | ||
118 | if (dev->bus && dev->bus->resume_early) { | 294 | if (!dev->bus) |
119 | dev_dbg(dev, "EARLY resume\n"); | 295 | goto End; |
296 | |||
297 | if (dev->bus->pm) { | ||
298 | pm_dev_dbg(dev, state, "EARLY "); | ||
299 | error = pm_noirq_op(dev, dev->bus->pm, state); | ||
300 | } else if (dev->bus->resume_early) { | ||
301 | pm_dev_dbg(dev, state, "legacy EARLY "); | ||
120 | error = dev->bus->resume_early(dev); | 302 | error = dev->bus->resume_early(dev); |
121 | } | 303 | } |
122 | 304 | End: | |
123 | TRACE_RESUME(error); | 305 | TRACE_RESUME(error); |
124 | return error; | 306 | return error; |
125 | } | 307 | } |
126 | 308 | ||
127 | /** | 309 | /** |
128 | * dpm_power_up - Power on all regular (non-sysdev) devices. | 310 | * dpm_power_up - Power on all regular (non-sysdev) devices. |
311 | * @state: PM transition of the system being carried out. | ||
129 | * | 312 | * |
130 | * Walk the dpm_off_irq list and power each device up. This | 313 | * Execute the appropriate "noirq resume" callback for all devices marked |
131 | * is used for devices that required they be powered down with | 314 | * as DPM_OFF_IRQ. |
132 | * interrupts disabled. As devices are powered on, they are moved | ||
133 | * to the dpm_off list. | ||
134 | * | 315 | * |
135 | * Must be called with interrupts disabled and only one CPU running. | 316 | * Must be called with interrupts disabled and only one CPU running. |
136 | */ | 317 | */ |
137 | static void dpm_power_up(void) | 318 | static void dpm_power_up(pm_message_t state) |
138 | { | 319 | { |
320 | struct device *dev; | ||
139 | 321 | ||
140 | while (!list_empty(&dpm_off_irq)) { | 322 | list_for_each_entry(dev, &dpm_list, power.entry) |
141 | struct list_head *entry = dpm_off_irq.next; | 323 | if (dev->power.status > DPM_OFF) { |
142 | struct device *dev = to_device(entry); | 324 | int error; |
143 | 325 | ||
144 | list_move_tail(entry, &dpm_off); | 326 | dev->power.status = DPM_OFF; |
145 | resume_device_early(dev); | 327 | error = resume_device_noirq(dev, state); |
146 | } | 328 | if (error) |
329 | pm_dev_err(dev, state, " early", error); | ||
330 | } | ||
147 | } | 331 | } |
148 | 332 | ||
149 | /** | 333 | /** |
150 | * device_power_up - Turn on all devices that need special attention. | 334 | * device_power_up - Turn on all devices that need special attention. |
335 | * @state: PM transition of the system being carried out. | ||
151 | * | 336 | * |
152 | * Power on system devices, then devices that required we shut them down | 337 | * Power on system devices, then devices that required we shut them down |
153 | * with interrupts disabled. | 338 | * with interrupts disabled. |
154 | * | 339 | * |
155 | * Must be called with interrupts disabled. | 340 | * Must be called with interrupts disabled. |
156 | */ | 341 | */ |
157 | void device_power_up(void) | 342 | void device_power_up(pm_message_t state) |
158 | { | 343 | { |
159 | sysdev_resume(); | 344 | sysdev_resume(); |
160 | dpm_power_up(); | 345 | dpm_power_up(state); |
161 | } | 346 | } |
162 | EXPORT_SYMBOL_GPL(device_power_up); | 347 | EXPORT_SYMBOL_GPL(device_power_up); |
163 | 348 | ||
164 | /** | 349 | /** |
165 | * resume_device - Restore state for one device. | 350 | * resume_device - Restore state for one device. |
166 | * @dev: Device. | 351 | * @dev: Device. |
167 | * | 352 | * @state: PM transition of the system being carried out. |
168 | */ | 353 | */ |
169 | static int resume_device(struct device *dev) | 354 | static int resume_device(struct device *dev, pm_message_t state) |
170 | { | 355 | { |
171 | int error = 0; | 356 | int error = 0; |
172 | 357 | ||
@@ -175,21 +360,40 @@ static int resume_device(struct device *dev) | |||
175 | 360 | ||
176 | down(&dev->sem); | 361 | down(&dev->sem); |
177 | 362 | ||
178 | if (dev->bus && dev->bus->resume) { | 363 | if (dev->bus) { |
179 | dev_dbg(dev,"resuming\n"); | 364 | if (dev->bus->pm) { |
180 | error = dev->bus->resume(dev); | 365 | pm_dev_dbg(dev, state, ""); |
366 | error = pm_op(dev, &dev->bus->pm->base, state); | ||
367 | } else if (dev->bus->resume) { | ||
368 | pm_dev_dbg(dev, state, "legacy "); | ||
369 | error = dev->bus->resume(dev); | ||
370 | } | ||
371 | if (error) | ||
372 | goto End; | ||
181 | } | 373 | } |
182 | 374 | ||
183 | if (!error && dev->type && dev->type->resume) { | 375 | if (dev->type) { |
184 | dev_dbg(dev,"resuming\n"); | 376 | if (dev->type->pm) { |
185 | error = dev->type->resume(dev); | 377 | pm_dev_dbg(dev, state, "type "); |
378 | error = pm_op(dev, dev->type->pm, state); | ||
379 | } else if (dev->type->resume) { | ||
380 | pm_dev_dbg(dev, state, "legacy type "); | ||
381 | error = dev->type->resume(dev); | ||
382 | } | ||
383 | if (error) | ||
384 | goto End; | ||
186 | } | 385 | } |
187 | 386 | ||
188 | if (!error && dev->class && dev->class->resume) { | 387 | if (dev->class) { |
189 | dev_dbg(dev,"class resume\n"); | 388 | if (dev->class->pm) { |
190 | error = dev->class->resume(dev); | 389 | pm_dev_dbg(dev, state, "class "); |
390 | error = pm_op(dev, dev->class->pm, state); | ||
391 | } else if (dev->class->resume) { | ||
392 | pm_dev_dbg(dev, state, "legacy class "); | ||
393 | error = dev->class->resume(dev); | ||
394 | } | ||
191 | } | 395 | } |
192 | 396 | End: | |
193 | up(&dev->sem); | 397 | up(&dev->sem); |
194 | 398 | ||
195 | TRACE_RESUME(error); | 399 | TRACE_RESUME(error); |
@@ -198,78 +402,161 @@ static int resume_device(struct device *dev) | |||
198 | 402 | ||
199 | /** | 403 | /** |
200 | * dpm_resume - Resume every device. | 404 | * dpm_resume - Resume every device. |
405 | * @state: PM transition of the system being carried out. | ||
201 | * | 406 | * |
202 | * Resume the devices that have either not gone through | 407 | * Execute the appropriate "resume" callback for all devices the status of |
203 | * the late suspend, or that did go through it but also | 408 | * which indicates that they are inactive. |
204 | * went through the early resume. | 409 | */ |
410 | static void dpm_resume(pm_message_t state) | ||
411 | { | ||
412 | struct list_head list; | ||
413 | |||
414 | INIT_LIST_HEAD(&list); | ||
415 | mutex_lock(&dpm_list_mtx); | ||
416 | transition_started = false; | ||
417 | while (!list_empty(&dpm_list)) { | ||
418 | struct device *dev = to_device(dpm_list.next); | ||
419 | |||
420 | get_device(dev); | ||
421 | if (dev->power.status >= DPM_OFF) { | ||
422 | int error; | ||
423 | |||
424 | dev->power.status = DPM_RESUMING; | ||
425 | mutex_unlock(&dpm_list_mtx); | ||
426 | |||
427 | error = resume_device(dev, state); | ||
428 | |||
429 | mutex_lock(&dpm_list_mtx); | ||
430 | if (error) | ||
431 | pm_dev_err(dev, state, "", error); | ||
432 | } else if (dev->power.status == DPM_SUSPENDING) { | ||
433 | /* Allow new children of the device to be registered */ | ||
434 | dev->power.status = DPM_RESUMING; | ||
435 | } | ||
436 | if (!list_empty(&dev->power.entry)) | ||
437 | list_move_tail(&dev->power.entry, &list); | ||
438 | put_device(dev); | ||
439 | } | ||
440 | list_splice(&list, &dpm_list); | ||
441 | mutex_unlock(&dpm_list_mtx); | ||
442 | } | ||
443 | |||
444 | /** | ||
445 | * complete_device - Complete a PM transition for given device | ||
446 | * @dev: Device. | ||
447 | * @state: PM transition of the system being carried out. | ||
448 | */ | ||
449 | static void complete_device(struct device *dev, pm_message_t state) | ||
450 | { | ||
451 | down(&dev->sem); | ||
452 | |||
453 | if (dev->class && dev->class->pm && dev->class->pm->complete) { | ||
454 | pm_dev_dbg(dev, state, "completing class "); | ||
455 | dev->class->pm->complete(dev); | ||
456 | } | ||
457 | |||
458 | if (dev->type && dev->type->pm && dev->type->pm->complete) { | ||
459 | pm_dev_dbg(dev, state, "completing type "); | ||
460 | dev->type->pm->complete(dev); | ||
461 | } | ||
462 | |||
463 | if (dev->bus && dev->bus->pm && dev->bus->pm->base.complete) { | ||
464 | pm_dev_dbg(dev, state, "completing "); | ||
465 | dev->bus->pm->base.complete(dev); | ||
466 | } | ||
467 | |||
468 | up(&dev->sem); | ||
469 | } | ||
470 | |||
471 | /** | ||
472 | * dpm_complete - Complete a PM transition for all devices. | ||
473 | * @state: PM transition of the system being carried out. | ||
205 | * | 474 | * |
206 | * Take devices from the dpm_off_list, resume them, | 475 | * Execute the ->complete() callbacks for all devices that are not marked |
207 | * and put them on the dpm_locked list. | 476 | * as DPM_ON. |
208 | */ | 477 | */ |
209 | static void dpm_resume(void) | 478 | static void dpm_complete(pm_message_t state) |
210 | { | 479 | { |
480 | struct list_head list; | ||
481 | |||
482 | INIT_LIST_HEAD(&list); | ||
211 | mutex_lock(&dpm_list_mtx); | 483 | mutex_lock(&dpm_list_mtx); |
212 | all_sleeping = false; | 484 | while (!list_empty(&dpm_list)) { |
213 | while(!list_empty(&dpm_off)) { | 485 | struct device *dev = to_device(dpm_list.prev); |
214 | struct list_head *entry = dpm_off.next; | ||
215 | struct device *dev = to_device(entry); | ||
216 | 486 | ||
217 | list_move_tail(entry, &dpm_active); | 487 | get_device(dev); |
218 | dev->power.sleeping = false; | 488 | if (dev->power.status > DPM_ON) { |
219 | mutex_unlock(&dpm_list_mtx); | 489 | dev->power.status = DPM_ON; |
220 | resume_device(dev); | 490 | mutex_unlock(&dpm_list_mtx); |
221 | mutex_lock(&dpm_list_mtx); | 491 | |
492 | complete_device(dev, state); | ||
493 | |||
494 | mutex_lock(&dpm_list_mtx); | ||
495 | } | ||
496 | if (!list_empty(&dev->power.entry)) | ||
497 | list_move(&dev->power.entry, &list); | ||
498 | put_device(dev); | ||
222 | } | 499 | } |
500 | list_splice(&list, &dpm_list); | ||
223 | mutex_unlock(&dpm_list_mtx); | 501 | mutex_unlock(&dpm_list_mtx); |
224 | } | 502 | } |
225 | 503 | ||
226 | /** | 504 | /** |
227 | * device_resume - Restore state of each device in system. | 505 | * device_resume - Restore state of each device in system. |
506 | * @state: PM transition of the system being carried out. | ||
228 | * | 507 | * |
229 | * Resume all the devices, unlock them all, and allow new | 508 | * Resume all the devices, unlock them all, and allow new |
230 | * devices to be registered once again. | 509 | * devices to be registered once again. |
231 | */ | 510 | */ |
232 | void device_resume(void) | 511 | void device_resume(pm_message_t state) |
233 | { | 512 | { |
234 | might_sleep(); | 513 | might_sleep(); |
235 | dpm_resume(); | 514 | dpm_resume(state); |
515 | dpm_complete(state); | ||
236 | } | 516 | } |
237 | EXPORT_SYMBOL_GPL(device_resume); | 517 | EXPORT_SYMBOL_GPL(device_resume); |
238 | 518 | ||
239 | 519 | ||
240 | /*------------------------- Suspend routines -------------------------*/ | 520 | /*------------------------- Suspend routines -------------------------*/ |
241 | 521 | ||
242 | static inline char *suspend_verb(u32 event) | 522 | /** |
523 | * resume_event - return a PM message representing the resume event | ||
524 | * corresponding to given sleep state. | ||
525 | * @sleep_state: PM message representing a sleep state. | ||
526 | */ | ||
527 | static pm_message_t resume_event(pm_message_t sleep_state) | ||
243 | { | 528 | { |
244 | switch (event) { | 529 | switch (sleep_state.event) { |
245 | case PM_EVENT_SUSPEND: return "suspend"; | 530 | case PM_EVENT_SUSPEND: |
246 | case PM_EVENT_FREEZE: return "freeze"; | 531 | return PMSG_RESUME; |
247 | case PM_EVENT_PRETHAW: return "prethaw"; | 532 | case PM_EVENT_FREEZE: |
248 | default: return "(unknown suspend event)"; | 533 | case PM_EVENT_QUIESCE: |
534 | return PMSG_RECOVER; | ||
535 | case PM_EVENT_HIBERNATE: | ||
536 | return PMSG_RESTORE; | ||
249 | } | 537 | } |
250 | } | 538 | return PMSG_ON; |
251 | |||
252 | static void | ||
253 | suspend_device_dbg(struct device *dev, pm_message_t state, char *info) | ||
254 | { | ||
255 | dev_dbg(dev, "%s%s%s\n", info, suspend_verb(state.event), | ||
256 | ((state.event == PM_EVENT_SUSPEND) && device_may_wakeup(dev)) ? | ||
257 | ", may wakeup" : ""); | ||
258 | } | 539 | } |
259 | 540 | ||
260 | /** | 541 | /** |
261 | * suspend_device_late - Shut down one device (late suspend). | 542 | * suspend_device_noirq - Shut down one device (late suspend). |
262 | * @dev: Device. | 543 | * @dev: Device. |
263 | * @state: Power state device is entering. | 544 | * @state: PM transition of the system being carried out. |
264 | * | 545 | * |
265 | * This is called with interrupts off and only a single CPU running. | 546 | * This is called with interrupts off and only a single CPU running. |
266 | */ | 547 | */ |
267 | static int suspend_device_late(struct device *dev, pm_message_t state) | 548 | static int suspend_device_noirq(struct device *dev, pm_message_t state) |
268 | { | 549 | { |
269 | int error = 0; | 550 | int error = 0; |
270 | 551 | ||
271 | if (dev->bus && dev->bus->suspend_late) { | 552 | if (!dev->bus) |
272 | suspend_device_dbg(dev, state, "LATE "); | 553 | return 0; |
554 | |||
555 | if (dev->bus->pm) { | ||
556 | pm_dev_dbg(dev, state, "LATE "); | ||
557 | error = pm_noirq_op(dev, dev->bus->pm, state); | ||
558 | } else if (dev->bus->suspend_late) { | ||
559 | pm_dev_dbg(dev, state, "legacy LATE "); | ||
273 | error = dev->bus->suspend_late(dev, state); | 560 | error = dev->bus->suspend_late(dev, state); |
274 | suspend_report_result(dev->bus->suspend_late, error); | 561 | suspend_report_result(dev->bus->suspend_late, error); |
275 | } | 562 | } |
@@ -278,37 +565,30 @@ static int suspend_device_late(struct device *dev, pm_message_t state) | |||
278 | 565 | ||
279 | /** | 566 | /** |
280 | * device_power_down - Shut down special devices. | 567 | * device_power_down - Shut down special devices. |
281 | * @state: Power state to enter. | 568 | * @state: PM transition of the system being carried out. |
282 | * | 569 | * |
283 | * Power down devices that require interrupts to be disabled | 570 | * Power down devices that require interrupts to be disabled. |
284 | * and move them from the dpm_off list to the dpm_off_irq list. | ||
285 | * Then power down system devices. | 571 | * Then power down system devices. |
286 | * | 572 | * |
287 | * Must be called with interrupts disabled and only one CPU running. | 573 | * Must be called with interrupts disabled and only one CPU running. |
288 | */ | 574 | */ |
289 | int device_power_down(pm_message_t state) | 575 | int device_power_down(pm_message_t state) |
290 | { | 576 | { |
577 | struct device *dev; | ||
291 | int error = 0; | 578 | int error = 0; |
292 | 579 | ||
293 | while (!list_empty(&dpm_off)) { | 580 | list_for_each_entry_reverse(dev, &dpm_list, power.entry) { |
294 | struct list_head *entry = dpm_off.prev; | 581 | error = suspend_device_noirq(dev, state); |
295 | struct device *dev = to_device(entry); | ||
296 | |||
297 | error = suspend_device_late(dev, state); | ||
298 | if (error) { | 582 | if (error) { |
299 | printk(KERN_ERR "Could not power down device %s: " | 583 | pm_dev_err(dev, state, " late", error); |
300 | "error %d\n", | ||
301 | kobject_name(&dev->kobj), error); | ||
302 | break; | 584 | break; |
303 | } | 585 | } |
304 | if (!list_empty(&dev->power.entry)) | 586 | dev->power.status = DPM_OFF_IRQ; |
305 | list_move(&dev->power.entry, &dpm_off_irq); | ||
306 | } | 587 | } |
307 | |||
308 | if (!error) | 588 | if (!error) |
309 | error = sysdev_suspend(state); | 589 | error = sysdev_suspend(state); |
310 | if (error) | 590 | if (error) |
311 | dpm_power_up(); | 591 | dpm_power_up(resume_event(state)); |
312 | return error; | 592 | return error; |
313 | } | 593 | } |
314 | EXPORT_SYMBOL_GPL(device_power_down); | 594 | EXPORT_SYMBOL_GPL(device_power_down); |
@@ -316,7 +596,7 @@ EXPORT_SYMBOL_GPL(device_power_down); | |||
316 | /** | 596 | /** |
317 | * suspend_device - Save state of one device. | 597 | * suspend_device - Save state of one device. |
318 | * @dev: Device. | 598 | * @dev: Device. |
319 | * @state: Power state device is entering. | 599 | * @state: PM transition of the system being carried out. |
320 | */ | 600 | */ |
321 | static int suspend_device(struct device *dev, pm_message_t state) | 601 | static int suspend_device(struct device *dev, pm_message_t state) |
322 | { | 602 | { |
@@ -324,24 +604,43 @@ static int suspend_device(struct device *dev, pm_message_t state) | |||
324 | 604 | ||
325 | down(&dev->sem); | 605 | down(&dev->sem); |
326 | 606 | ||
327 | if (dev->class && dev->class->suspend) { | 607 | if (dev->class) { |
328 | suspend_device_dbg(dev, state, "class "); | 608 | if (dev->class->pm) { |
329 | error = dev->class->suspend(dev, state); | 609 | pm_dev_dbg(dev, state, "class "); |
330 | suspend_report_result(dev->class->suspend, error); | 610 | error = pm_op(dev, dev->class->pm, state); |
611 | } else if (dev->class->suspend) { | ||
612 | pm_dev_dbg(dev, state, "legacy class "); | ||
613 | error = dev->class->suspend(dev, state); | ||
614 | suspend_report_result(dev->class->suspend, error); | ||
615 | } | ||
616 | if (error) | ||
617 | goto End; | ||
331 | } | 618 | } |
332 | 619 | ||
333 | if (!error && dev->type && dev->type->suspend) { | 620 | if (dev->type) { |
334 | suspend_device_dbg(dev, state, "type "); | 621 | if (dev->type->pm) { |
335 | error = dev->type->suspend(dev, state); | 622 | pm_dev_dbg(dev, state, "type "); |
336 | suspend_report_result(dev->type->suspend, error); | 623 | error = pm_op(dev, dev->type->pm, state); |
624 | } else if (dev->type->suspend) { | ||
625 | pm_dev_dbg(dev, state, "legacy type "); | ||
626 | error = dev->type->suspend(dev, state); | ||
627 | suspend_report_result(dev->type->suspend, error); | ||
628 | } | ||
629 | if (error) | ||
630 | goto End; | ||
337 | } | 631 | } |
338 | 632 | ||
339 | if (!error && dev->bus && dev->bus->suspend) { | 633 | if (dev->bus) { |
340 | suspend_device_dbg(dev, state, ""); | 634 | if (dev->bus->pm) { |
341 | error = dev->bus->suspend(dev, state); | 635 | pm_dev_dbg(dev, state, ""); |
342 | suspend_report_result(dev->bus->suspend, error); | 636 | error = pm_op(dev, &dev->bus->pm->base, state); |
637 | } else if (dev->bus->suspend) { | ||
638 | pm_dev_dbg(dev, state, "legacy "); | ||
639 | error = dev->bus->suspend(dev, state); | ||
640 | suspend_report_result(dev->bus->suspend, error); | ||
641 | } | ||
343 | } | 642 | } |
344 | 643 | End: | |
345 | up(&dev->sem); | 644 | up(&dev->sem); |
346 | 645 | ||
347 | return error; | 646 | return error; |
@@ -349,67 +648,139 @@ static int suspend_device(struct device *dev, pm_message_t state) | |||
349 | 648 | ||
350 | /** | 649 | /** |
351 | * dpm_suspend - Suspend every device. | 650 | * dpm_suspend - Suspend every device. |
352 | * @state: Power state to put each device in. | 651 | * @state: PM transition of the system being carried out. |
353 | * | ||
354 | * Walk the dpm_locked list. Suspend each device and move it | ||
355 | * to the dpm_off list. | ||
356 | * | 652 | * |
357 | * (For historical reasons, if it returns -EAGAIN, that used to mean | 653 | * Execute the appropriate "suspend" callbacks for all devices. |
358 | * that the device would be called again with interrupts disabled. | ||
359 | * These days, we use the "suspend_late()" callback for that, so we | ||
360 | * print a warning and consider it an error). | ||
361 | */ | 654 | */ |
362 | static int dpm_suspend(pm_message_t state) | 655 | static int dpm_suspend(pm_message_t state) |
363 | { | 656 | { |
657 | struct list_head list; | ||
364 | int error = 0; | 658 | int error = 0; |
365 | 659 | ||
660 | INIT_LIST_HEAD(&list); | ||
366 | mutex_lock(&dpm_list_mtx); | 661 | mutex_lock(&dpm_list_mtx); |
367 | while (!list_empty(&dpm_active)) { | 662 | while (!list_empty(&dpm_list)) { |
368 | struct list_head *entry = dpm_active.prev; | 663 | struct device *dev = to_device(dpm_list.prev); |
369 | struct device *dev = to_device(entry); | ||
370 | 664 | ||
371 | WARN_ON(dev->parent && dev->parent->power.sleeping); | 665 | get_device(dev); |
372 | |||
373 | dev->power.sleeping = true; | ||
374 | mutex_unlock(&dpm_list_mtx); | 666 | mutex_unlock(&dpm_list_mtx); |
667 | |||
375 | error = suspend_device(dev, state); | 668 | error = suspend_device(dev, state); |
669 | |||
376 | mutex_lock(&dpm_list_mtx); | 670 | mutex_lock(&dpm_list_mtx); |
377 | if (error) { | 671 | if (error) { |
378 | printk(KERN_ERR "Could not suspend device %s: " | 672 | pm_dev_err(dev, state, "", error); |
379 | "error %d%s\n", | 673 | put_device(dev); |
380 | kobject_name(&dev->kobj), | ||
381 | error, | ||
382 | (error == -EAGAIN ? | ||
383 | " (please convert to suspend_late)" : | ||
384 | "")); | ||
385 | dev->power.sleeping = false; | ||
386 | break; | 674 | break; |
387 | } | 675 | } |
676 | dev->power.status = DPM_OFF; | ||
388 | if (!list_empty(&dev->power.entry)) | 677 | if (!list_empty(&dev->power.entry)) |
389 | list_move(&dev->power.entry, &dpm_off); | 678 | list_move(&dev->power.entry, &list); |
679 | put_device(dev); | ||
390 | } | 680 | } |
391 | if (!error) | 681 | list_splice(&list, dpm_list.prev); |
392 | all_sleeping = true; | ||
393 | mutex_unlock(&dpm_list_mtx); | 682 | mutex_unlock(&dpm_list_mtx); |
683 | return error; | ||
684 | } | ||
685 | |||
686 | /** | ||
687 | * prepare_device - Execute the ->prepare() callback(s) for given device. | ||
688 | * @dev: Device. | ||
689 | * @state: PM transition of the system being carried out. | ||
690 | */ | ||
691 | static int prepare_device(struct device *dev, pm_message_t state) | ||
692 | { | ||
693 | int error = 0; | ||
694 | |||
695 | down(&dev->sem); | ||
696 | |||
697 | if (dev->bus && dev->bus->pm && dev->bus->pm->base.prepare) { | ||
698 | pm_dev_dbg(dev, state, "preparing "); | ||
699 | error = dev->bus->pm->base.prepare(dev); | ||
700 | suspend_report_result(dev->bus->pm->base.prepare, error); | ||
701 | if (error) | ||
702 | goto End; | ||
703 | } | ||
704 | |||
705 | if (dev->type && dev->type->pm && dev->type->pm->prepare) { | ||
706 | pm_dev_dbg(dev, state, "preparing type "); | ||
707 | error = dev->type->pm->prepare(dev); | ||
708 | suspend_report_result(dev->type->pm->prepare, error); | ||
709 | if (error) | ||
710 | goto End; | ||
711 | } | ||
712 | |||
713 | if (dev->class && dev->class->pm && dev->class->pm->prepare) { | ||
714 | pm_dev_dbg(dev, state, "preparing class "); | ||
715 | error = dev->class->pm->prepare(dev); | ||
716 | suspend_report_result(dev->class->pm->prepare, error); | ||
717 | } | ||
718 | End: | ||
719 | up(&dev->sem); | ||
720 | |||
721 | return error; | ||
722 | } | ||
723 | |||
724 | /** | ||
725 | * dpm_prepare - Prepare all devices for a PM transition. | ||
726 | * @state: PM transition of the system being carried out. | ||
727 | * | ||
728 | * Execute the ->prepare() callback for all devices. | ||
729 | */ | ||
730 | static int dpm_prepare(pm_message_t state) | ||
731 | { | ||
732 | struct list_head list; | ||
733 | int error = 0; | ||
734 | |||
735 | INIT_LIST_HEAD(&list); | ||
736 | mutex_lock(&dpm_list_mtx); | ||
737 | transition_started = true; | ||
738 | while (!list_empty(&dpm_list)) { | ||
739 | struct device *dev = to_device(dpm_list.next); | ||
740 | |||
741 | get_device(dev); | ||
742 | dev->power.status = DPM_PREPARING; | ||
743 | mutex_unlock(&dpm_list_mtx); | ||
394 | 744 | ||
745 | error = prepare_device(dev, state); | ||
746 | |||
747 | mutex_lock(&dpm_list_mtx); | ||
748 | if (error) { | ||
749 | dev->power.status = DPM_ON; | ||
750 | if (error == -EAGAIN) { | ||
751 | put_device(dev); | ||
752 | continue; | ||
753 | } | ||
754 | printk(KERN_ERR "PM: Failed to prepare device %s " | ||
755 | "for power transition: error %d\n", | ||
756 | kobject_name(&dev->kobj), error); | ||
757 | put_device(dev); | ||
758 | break; | ||
759 | } | ||
760 | dev->power.status = DPM_SUSPENDING; | ||
761 | if (!list_empty(&dev->power.entry)) | ||
762 | list_move_tail(&dev->power.entry, &list); | ||
763 | put_device(dev); | ||
764 | } | ||
765 | list_splice(&list, &dpm_list); | ||
766 | mutex_unlock(&dpm_list_mtx); | ||
395 | return error; | 767 | return error; |
396 | } | 768 | } |
397 | 769 | ||
398 | /** | 770 | /** |
399 | * device_suspend - Save state and stop all devices in system. | 771 | * device_suspend - Save state and stop all devices in system. |
400 | * @state: new power management state | 772 | * @state: PM transition of the system being carried out. |
401 | * | 773 | * |
402 | * Prevent new devices from being registered, then lock all devices | 774 | * Prepare and suspend all devices. |
403 | * and suspend them. | ||
404 | */ | 775 | */ |
405 | int device_suspend(pm_message_t state) | 776 | int device_suspend(pm_message_t state) |
406 | { | 777 | { |
407 | int error; | 778 | int error; |
408 | 779 | ||
409 | might_sleep(); | 780 | might_sleep(); |
410 | error = dpm_suspend(state); | 781 | error = dpm_prepare(state); |
411 | if (error) | 782 | if (!error) |
412 | device_resume(); | 783 | error = dpm_suspend(state); |
413 | return error; | 784 | return error; |
414 | } | 785 | } |
415 | EXPORT_SYMBOL_GPL(device_suspend); | 786 | EXPORT_SYMBOL_GPL(device_suspend); |
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h index a6894f2a4b99..a3252c0e2887 100644 --- a/drivers/base/power/power.h +++ b/drivers/base/power/power.h | |||
@@ -4,7 +4,7 @@ | |||
4 | * main.c | 4 | * main.c |
5 | */ | 5 | */ |
6 | 6 | ||
7 | extern struct list_head dpm_active; /* The active device list */ | 7 | extern struct list_head dpm_list; /* The active device list */ |
8 | 8 | ||
9 | static inline struct device *to_device(struct list_head *entry) | 9 | static inline struct device *to_device(struct list_head *entry) |
10 | { | 10 | { |
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c index d11f74b038db..596aeecfdffe 100644 --- a/drivers/base/power/sysfs.c +++ b/drivers/base/power/sysfs.c | |||
@@ -6,9 +6,6 @@ | |||
6 | #include <linux/string.h> | 6 | #include <linux/string.h> |
7 | #include "power.h" | 7 | #include "power.h" |
8 | 8 | ||
9 | int (*platform_enable_wakeup)(struct device *dev, int is_on); | ||
10 | |||
11 | |||
12 | /* | 9 | /* |
13 | * wakeup - Report/change current wakeup option for device | 10 | * wakeup - Report/change current wakeup option for device |
14 | * | 11 | * |
diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c index 2b4b392dcbc1..2aa6e8fc4def 100644 --- a/drivers/base/power/trace.c +++ b/drivers/base/power/trace.c | |||
@@ -153,7 +153,7 @@ EXPORT_SYMBOL(set_trace_device); | |||
153 | * it's not any guarantee, but it's a high _likelihood_ that | 153 | * it's not any guarantee, but it's a high _likelihood_ that |
154 | * the match is valid). | 154 | * the match is valid). |
155 | */ | 155 | */ |
156 | void generate_resume_trace(void *tracedata, unsigned int user) | 156 | void generate_resume_trace(const void *tracedata, unsigned int user) |
157 | { | 157 | { |
158 | unsigned short lineno = *(unsigned short *)tracedata; | 158 | unsigned short lineno = *(unsigned short *)tracedata; |
159 | const char *file = *(const char **)(tracedata + 2); | 159 | const char *file = *(const char **)(tracedata + 2); |
@@ -188,13 +188,13 @@ static int show_file_hash(unsigned int value) | |||
188 | static int show_dev_hash(unsigned int value) | 188 | static int show_dev_hash(unsigned int value) |
189 | { | 189 | { |
190 | int match = 0; | 190 | int match = 0; |
191 | struct list_head * entry = dpm_active.prev; | 191 | struct list_head *entry = dpm_list.prev; |
192 | 192 | ||
193 | while (entry != &dpm_active) { | 193 | while (entry != &dpm_list) { |
194 | struct device * dev = to_device(entry); | 194 | struct device * dev = to_device(entry); |
195 | unsigned int hash = hash_string(DEVSEED, dev->bus_id, DEVHASH); | 195 | unsigned int hash = hash_string(DEVSEED, dev->bus_id, DEVHASH); |
196 | if (hash == value) { | 196 | if (hash == value) { |
197 | printk(" hash matches device %s\n", dev->bus_id); | 197 | dev_info(dev, "hash matches\n"); |
198 | match++; | 198 | match++; |
199 | } | 199 | } |
200 | entry = entry->prev; | 200 | entry = entry->prev; |
diff --git a/drivers/base/sys.c b/drivers/base/sys.c index 358bb0be3c08..40fc14f03540 100644 --- a/drivers/base/sys.c +++ b/drivers/base/sys.c | |||
@@ -36,7 +36,7 @@ sysdev_show(struct kobject * kobj, struct attribute * attr, char * buffer) | |||
36 | struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr); | 36 | struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr); |
37 | 37 | ||
38 | if (sysdev_attr->show) | 38 | if (sysdev_attr->show) |
39 | return sysdev_attr->show(sysdev, buffer); | 39 | return sysdev_attr->show(sysdev, sysdev_attr, buffer); |
40 | return -EIO; | 40 | return -EIO; |
41 | } | 41 | } |
42 | 42 | ||
@@ -49,7 +49,7 @@ sysdev_store(struct kobject * kobj, struct attribute * attr, | |||
49 | struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr); | 49 | struct sysdev_attribute * sysdev_attr = to_sysdev_attr(attr); |
50 | 50 | ||
51 | if (sysdev_attr->store) | 51 | if (sysdev_attr->store) |
52 | return sysdev_attr->store(sysdev, buffer, count); | 52 | return sysdev_attr->store(sysdev, sysdev_attr, buffer, count); |
53 | return -EIO; | 53 | return -EIO; |
54 | } | 54 | } |
55 | 55 | ||
@@ -130,8 +130,8 @@ static struct kset *system_kset; | |||
130 | 130 | ||
131 | int sysdev_class_register(struct sysdev_class * cls) | 131 | int sysdev_class_register(struct sysdev_class * cls) |
132 | { | 132 | { |
133 | pr_debug("Registering sysdev class '%s'\n", | 133 | pr_debug("Registering sysdev class '%s'\n", cls->name); |
134 | kobject_name(&cls->kset.kobj)); | 134 | |
135 | INIT_LIST_HEAD(&cls->drivers); | 135 | INIT_LIST_HEAD(&cls->drivers); |
136 | memset(&cls->kset.kobj, 0x00, sizeof(struct kobject)); | 136 | memset(&cls->kset.kobj, 0x00, sizeof(struct kobject)); |
137 | cls->kset.kobj.parent = &system_kset->kobj; | 137 | cls->kset.kobj.parent = &system_kset->kobj; |
@@ -241,7 +241,8 @@ int sysdev_register(struct sys_device * sysdev) | |||
241 | if (!cls) | 241 | if (!cls) |
242 | return -EINVAL; | 242 | return -EINVAL; |
243 | 243 | ||
244 | pr_debug("Registering sys device '%s'\n", kobject_name(&sysdev->kobj)); | 244 | pr_debug("Registering sys device of class '%s'\n", |
245 | kobject_name(&cls->kset.kobj)); | ||
245 | 246 | ||
246 | /* initialize the kobject to 0, in case it had previously been used */ | 247 | /* initialize the kobject to 0, in case it had previously been used */ |
247 | memset(&sysdev->kobj, 0x00, sizeof(struct kobject)); | 248 | memset(&sysdev->kobj, 0x00, sizeof(struct kobject)); |
@@ -257,6 +258,9 @@ int sysdev_register(struct sys_device * sysdev) | |||
257 | if (!error) { | 258 | if (!error) { |
258 | struct sysdev_driver * drv; | 259 | struct sysdev_driver * drv; |
259 | 260 | ||
261 | pr_debug("Registering sys device '%s'\n", | ||
262 | kobject_name(&sysdev->kobj)); | ||
263 | |||
260 | mutex_lock(&sysdev_drivers_lock); | 264 | mutex_lock(&sysdev_drivers_lock); |
261 | /* Generic notification is implicit, because it's that | 265 | /* Generic notification is implicit, because it's that |
262 | * code that should have called us. | 266 | * code that should have called us. |
@@ -269,6 +273,7 @@ int sysdev_register(struct sys_device * sysdev) | |||
269 | } | 273 | } |
270 | mutex_unlock(&sysdev_drivers_lock); | 274 | mutex_unlock(&sysdev_drivers_lock); |
271 | } | 275 | } |
276 | |||
272 | kobject_uevent(&sysdev->kobj, KOBJ_ADD); | 277 | kobject_uevent(&sysdev->kobj, KOBJ_ADD); |
273 | return error; | 278 | return error; |
274 | } | 279 | } |
@@ -474,3 +479,52 @@ int __init system_bus_init(void) | |||
474 | 479 | ||
475 | EXPORT_SYMBOL_GPL(sysdev_register); | 480 | EXPORT_SYMBOL_GPL(sysdev_register); |
476 | EXPORT_SYMBOL_GPL(sysdev_unregister); | 481 | EXPORT_SYMBOL_GPL(sysdev_unregister); |
482 | |||
483 | #define to_ext_attr(x) container_of(x, struct sysdev_ext_attribute, attr) | ||
484 | |||
485 | ssize_t sysdev_store_ulong(struct sys_device *sysdev, | ||
486 | struct sysdev_attribute *attr, | ||
487 | const char *buf, size_t size) | ||
488 | { | ||
489 | struct sysdev_ext_attribute *ea = to_ext_attr(attr); | ||
490 | char *end; | ||
491 | unsigned long new = simple_strtoul(buf, &end, 0); | ||
492 | if (end == buf) | ||
493 | return -EINVAL; | ||
494 | *(unsigned long *)(ea->var) = new; | ||
495 | return end - buf; | ||
496 | } | ||
497 | EXPORT_SYMBOL_GPL(sysdev_store_ulong); | ||
498 | |||
499 | ssize_t sysdev_show_ulong(struct sys_device *sysdev, | ||
500 | struct sysdev_attribute *attr, | ||
501 | char *buf) | ||
502 | { | ||
503 | struct sysdev_ext_attribute *ea = to_ext_attr(attr); | ||
504 | return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var)); | ||
505 | } | ||
506 | EXPORT_SYMBOL_GPL(sysdev_show_ulong); | ||
507 | |||
508 | ssize_t sysdev_store_int(struct sys_device *sysdev, | ||
509 | struct sysdev_attribute *attr, | ||
510 | const char *buf, size_t size) | ||
511 | { | ||
512 | struct sysdev_ext_attribute *ea = to_ext_attr(attr); | ||
513 | char *end; | ||
514 | long new = simple_strtol(buf, &end, 0); | ||
515 | if (end == buf || new > INT_MAX || new < INT_MIN) | ||
516 | return -EINVAL; | ||
517 | *(int *)(ea->var) = new; | ||
518 | return end - buf; | ||
519 | } | ||
520 | EXPORT_SYMBOL_GPL(sysdev_store_int); | ||
521 | |||
522 | ssize_t sysdev_show_int(struct sys_device *sysdev, | ||
523 | struct sysdev_attribute *attr, | ||
524 | char *buf) | ||
525 | { | ||
526 | struct sysdev_ext_attribute *ea = to_ext_attr(attr); | ||
527 | return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var)); | ||
528 | } | ||
529 | EXPORT_SYMBOL_GPL(sysdev_show_int); | ||
530 | |||
diff --git a/drivers/base/topology.c b/drivers/base/topology.c index fdf4044d2e74..199cd97e32e6 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c | |||
@@ -34,12 +34,14 @@ | |||
34 | static SYSDEV_ATTR(_name, 0444, show_##_name, NULL) | 34 | static SYSDEV_ATTR(_name, 0444, show_##_name, NULL) |
35 | 35 | ||
36 | #define define_id_show_func(name) \ | 36 | #define define_id_show_func(name) \ |
37 | static ssize_t show_##name(struct sys_device *dev, char *buf) \ | 37 | static ssize_t show_##name(struct sys_device *dev, \ |
38 | struct sysdev_attribute *attr, char *buf) \ | ||
38 | { \ | 39 | { \ |
39 | unsigned int cpu = dev->id; \ | 40 | unsigned int cpu = dev->id; \ |
40 | return sprintf(buf, "%d\n", topology_##name(cpu)); \ | 41 | return sprintf(buf, "%d\n", topology_##name(cpu)); \ |
41 | } | 42 | } |
42 | 43 | ||
44 | #if defined(topology_thread_siblings) || defined(topology_core_siblings) | ||
43 | static ssize_t show_cpumap(int type, cpumask_t *mask, char *buf) | 45 | static ssize_t show_cpumap(int type, cpumask_t *mask, char *buf) |
44 | { | 46 | { |
45 | ptrdiff_t len = PTR_ALIGN(buf + PAGE_SIZE - 1, PAGE_SIZE) - buf; | 47 | ptrdiff_t len = PTR_ALIGN(buf + PAGE_SIZE - 1, PAGE_SIZE) - buf; |
@@ -54,65 +56,71 @@ static ssize_t show_cpumap(int type, cpumask_t *mask, char *buf) | |||
54 | } | 56 | } |
55 | return n; | 57 | return n; |
56 | } | 58 | } |
59 | #endif | ||
57 | 60 | ||
61 | #ifdef arch_provides_topology_pointers | ||
58 | #define define_siblings_show_map(name) \ | 62 | #define define_siblings_show_map(name) \ |
59 | static inline ssize_t show_##name(struct sys_device *dev, char *buf) \ | 63 | static ssize_t show_##name(struct sys_device *dev, \ |
64 | struct sysdev_attribute *attr, char *buf) \ | ||
60 | { \ | 65 | { \ |
61 | unsigned int cpu = dev->id; \ | 66 | unsigned int cpu = dev->id; \ |
62 | return show_cpumap(0, &(topology_##name(cpu)), buf); \ | 67 | return show_cpumap(0, &(topology_##name(cpu)), buf); \ |
63 | } | 68 | } |
64 | 69 | ||
65 | #define define_siblings_show_list(name) \ | 70 | #define define_siblings_show_list(name) \ |
66 | static inline ssize_t show_##name##_list(struct sys_device *dev, char *buf) \ | 71 | static ssize_t show_##name##_list(struct sys_device *dev, \ |
72 | struct sysdev_attribute *attr, \ | ||
73 | char *buf) \ | ||
67 | { \ | 74 | { \ |
68 | unsigned int cpu = dev->id; \ | 75 | unsigned int cpu = dev->id; \ |
69 | return show_cpumap(1, &(topology_##name(cpu)), buf); \ | 76 | return show_cpumap(1, &(topology_##name(cpu)), buf); \ |
70 | } | 77 | } |
71 | 78 | ||
79 | #else | ||
80 | #define define_siblings_show_map(name) \ | ||
81 | static ssize_t show_##name(struct sys_device *dev, \ | ||
82 | struct sysdev_attribute *attr, char *buf) \ | ||
83 | { \ | ||
84 | unsigned int cpu = dev->id; \ | ||
85 | cpumask_t mask = topology_##name(cpu); \ | ||
86 | return show_cpumap(0, &mask, buf); \ | ||
87 | } | ||
88 | |||
89 | #define define_siblings_show_list(name) \ | ||
90 | static ssize_t show_##name##_list(struct sys_device *dev, \ | ||
91 | struct sysdev_attribute *attr, \ | ||
92 | char *buf) \ | ||
93 | { \ | ||
94 | unsigned int cpu = dev->id; \ | ||
95 | cpumask_t mask = topology_##name(cpu); \ | ||
96 | return show_cpumap(1, &mask, buf); \ | ||
97 | } | ||
98 | #endif | ||
99 | |||
72 | #define define_siblings_show_func(name) \ | 100 | #define define_siblings_show_func(name) \ |
73 | define_siblings_show_map(name); define_siblings_show_list(name) | 101 | define_siblings_show_map(name); define_siblings_show_list(name) |
74 | 102 | ||
75 | #ifdef topology_physical_package_id | ||
76 | define_id_show_func(physical_package_id); | 103 | define_id_show_func(physical_package_id); |
77 | define_one_ro(physical_package_id); | 104 | define_one_ro(physical_package_id); |
78 | #define ref_physical_package_id_attr &attr_physical_package_id.attr, | ||
79 | #else | ||
80 | #define ref_physical_package_id_attr | ||
81 | #endif | ||
82 | 105 | ||
83 | #ifdef topology_core_id | ||
84 | define_id_show_func(core_id); | 106 | define_id_show_func(core_id); |
85 | define_one_ro(core_id); | 107 | define_one_ro(core_id); |
86 | #define ref_core_id_attr &attr_core_id.attr, | ||
87 | #else | ||
88 | #define ref_core_id_attr | ||
89 | #endif | ||
90 | 108 | ||
91 | #ifdef topology_thread_siblings | ||
92 | define_siblings_show_func(thread_siblings); | 109 | define_siblings_show_func(thread_siblings); |
93 | define_one_ro(thread_siblings); | 110 | define_one_ro(thread_siblings); |
94 | define_one_ro(thread_siblings_list); | 111 | define_one_ro(thread_siblings_list); |
95 | #define ref_thread_siblings_attr \ | ||
96 | &attr_thread_siblings.attr, &attr_thread_siblings_list.attr, | ||
97 | #else | ||
98 | #define ref_thread_siblings_attr | ||
99 | #endif | ||
100 | 112 | ||
101 | #ifdef topology_core_siblings | ||
102 | define_siblings_show_func(core_siblings); | 113 | define_siblings_show_func(core_siblings); |
103 | define_one_ro(core_siblings); | 114 | define_one_ro(core_siblings); |
104 | define_one_ro(core_siblings_list); | 115 | define_one_ro(core_siblings_list); |
105 | #define ref_core_siblings_attr \ | ||
106 | &attr_core_siblings.attr, &attr_core_siblings_list.attr, | ||
107 | #else | ||
108 | #define ref_core_siblings_attr | ||
109 | #endif | ||
110 | 116 | ||
111 | static struct attribute *default_attrs[] = { | 117 | static struct attribute *default_attrs[] = { |
112 | ref_physical_package_id_attr | 118 | &attr_physical_package_id.attr, |
113 | ref_core_id_attr | 119 | &attr_core_id.attr, |
114 | ref_thread_siblings_attr | 120 | &attr_thread_siblings.attr, |
115 | ref_core_siblings_attr | 121 | &attr_thread_siblings_list.attr, |
122 | &attr_core_siblings.attr, | ||
123 | &attr_core_siblings_list.attr, | ||
116 | NULL | 124 | NULL |
117 | }; | 125 | }; |
118 | 126 | ||