diff options
author | Haavard Skinnemoen <haavard.skinnemoen@atmel.com> | 2008-07-27 07:54:08 -0400 |
---|---|---|
committer | Haavard Skinnemoen <haavard.skinnemoen@atmel.com> | 2008-07-27 07:54:08 -0400 |
commit | eda3d8f5604860aae1bb9996bb5efc4213778369 (patch) | |
tree | 9d3887d2665bcc5f5abf200758794545c7b2c69b /drivers/base | |
parent | 87a9f704658a40940e740b1d73d861667e9164d3 (diff) | |
parent | 8be1a6d6c77ab4532e4476fdb8177030ef48b52c (diff) |
Merge commit 'upstream/master'
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/Kconfig | 3 | ||||
-rw-r--r-- | drivers/base/base.h | 27 | ||||
-rw-r--r-- | drivers/base/class.c | 153 | ||||
-rw-r--r-- | drivers/base/core.c | 202 | ||||
-rw-r--r-- | drivers/base/cpu.c | 14 | ||||
-rw-r--r-- | drivers/base/firmware_class.c | 12 | ||||
-rw-r--r-- | drivers/base/isa.c | 4 | ||||
-rw-r--r-- | drivers/base/memory.c | 34 | ||||
-rw-r--r-- | drivers/base/node.c | 15 | ||||
-rw-r--r-- | drivers/base/power/trace.c | 2 | ||||
-rw-r--r-- | drivers/base/sys.c | 76 | ||||
-rw-r--r-- | drivers/base/topology.c | 17 |
12 files changed, 373 insertions, 186 deletions
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig index d47482fa1d21..6318f6b57360 100644 --- a/drivers/base/Kconfig +++ b/drivers/base/Kconfig | |||
@@ -27,8 +27,9 @@ 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 |
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..068aa1c9538c 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) |
@@ -112,12 +116,10 @@ static void device_release(struct kobject *kobj) | |||
112 | dev->type->release(dev); | 116 | dev->type->release(dev); |
113 | else if (dev->class && dev->class->dev_release) | 117 | else if (dev->class && dev->class->dev_release) |
114 | dev->class->dev_release(dev); | 118 | dev->class->dev_release(dev); |
115 | else { | 119 | else |
116 | printk(KERN_ERR "Device '%s' does not have a release() " | 120 | WARN(1, KERN_ERR "Device '%s' does not have a release() " |
117 | "function, it is broken and must be fixed.\n", | 121 | "function, it is broken and must be fixed.\n", |
118 | dev->bus_id); | 122 | dev->bus_id); |
119 | WARN_ON(1); | ||
120 | } | ||
121 | } | 123 | } |
122 | 124 | ||
123 | static struct kobj_type device_ktype = { | 125 | static struct kobj_type device_ktype = { |
@@ -548,7 +550,7 @@ static struct kobject *get_device_parent(struct device *dev, | |||
548 | { | 550 | { |
549 | /* class devices without a parent live in /sys/class/<classname>/ */ | 551 | /* class devices without a parent live in /sys/class/<classname>/ */ |
550 | if (dev->class && (!parent || parent->class != dev->class)) | 552 | if (dev->class && (!parent || parent->class != dev->class)) |
551 | return &dev->class->subsys.kobj; | 553 | return &dev->class->p->class_subsys.kobj; |
552 | /* all other devices keep their parent */ | 554 | /* all other devices keep their parent */ |
553 | else if (parent) | 555 | else if (parent) |
554 | return &parent->kobj; | 556 | return &parent->kobj; |
@@ -594,13 +596,13 @@ static struct kobject *get_device_parent(struct device *dev, | |||
594 | parent_kobj = &parent->kobj; | 596 | parent_kobj = &parent->kobj; |
595 | 597 | ||
596 | /* find our class-directory at the parent and reference it */ | 598 | /* find our class-directory at the parent and reference it */ |
597 | spin_lock(&dev->class->class_dirs.list_lock); | 599 | spin_lock(&dev->class->p->class_dirs.list_lock); |
598 | list_for_each_entry(k, &dev->class->class_dirs.list, entry) | 600 | list_for_each_entry(k, &dev->class->p->class_dirs.list, entry) |
599 | if (k->parent == parent_kobj) { | 601 | if (k->parent == parent_kobj) { |
600 | kobj = kobject_get(k); | 602 | kobj = kobject_get(k); |
601 | break; | 603 | break; |
602 | } | 604 | } |
603 | spin_unlock(&dev->class->class_dirs.list_lock); | 605 | spin_unlock(&dev->class->p->class_dirs.list_lock); |
604 | if (kobj) | 606 | if (kobj) |
605 | return kobj; | 607 | return kobj; |
606 | 608 | ||
@@ -608,7 +610,7 @@ static struct kobject *get_device_parent(struct device *dev, | |||
608 | k = kobject_create(); | 610 | k = kobject_create(); |
609 | if (!k) | 611 | if (!k) |
610 | return NULL; | 612 | return NULL; |
611 | k->kset = &dev->class->class_dirs; | 613 | k->kset = &dev->class->p->class_dirs; |
612 | retval = kobject_add(k, parent_kobj, "%s", dev->class->name); | 614 | retval = kobject_add(k, parent_kobj, "%s", dev->class->name); |
613 | if (retval < 0) { | 615 | if (retval < 0) { |
614 | kobject_put(k); | 616 | kobject_put(k); |
@@ -627,7 +629,7 @@ static void cleanup_glue_dir(struct device *dev, struct kobject *glue_dir) | |||
627 | { | 629 | { |
628 | /* see if we live in a "glue" directory */ | 630 | /* see if we live in a "glue" directory */ |
629 | if (!glue_dir || !dev->class || | 631 | if (!glue_dir || !dev->class || |
630 | glue_dir->kset != &dev->class->class_dirs) | 632 | glue_dir->kset != &dev->class->p->class_dirs) |
631 | return; | 633 | return; |
632 | 634 | ||
633 | kobject_put(glue_dir); | 635 | kobject_put(glue_dir); |
@@ -654,17 +656,18 @@ static int device_add_class_symlinks(struct device *dev) | |||
654 | if (!dev->class) | 656 | if (!dev->class) |
655 | return 0; | 657 | return 0; |
656 | 658 | ||
657 | error = sysfs_create_link(&dev->kobj, &dev->class->subsys.kobj, | 659 | error = sysfs_create_link(&dev->kobj, |
660 | &dev->class->p->class_subsys.kobj, | ||
658 | "subsystem"); | 661 | "subsystem"); |
659 | if (error) | 662 | if (error) |
660 | goto out; | 663 | goto out; |
661 | 664 | ||
662 | #ifdef CONFIG_SYSFS_DEPRECATED | 665 | #ifdef CONFIG_SYSFS_DEPRECATED |
663 | /* stacked class devices need a symlink in the class directory */ | 666 | /* stacked class devices need a symlink in the class directory */ |
664 | if (dev->kobj.parent != &dev->class->subsys.kobj && | 667 | if (dev->kobj.parent != &dev->class->p->class_subsys.kobj && |
665 | device_is_not_partition(dev)) { | 668 | device_is_not_partition(dev)) { |
666 | error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj, | 669 | error = sysfs_create_link(&dev->class->p->class_subsys.kobj, |
667 | dev->bus_id); | 670 | &dev->kobj, dev->bus_id); |
668 | if (error) | 671 | if (error) |
669 | goto out_subsys; | 672 | goto out_subsys; |
670 | } | 673 | } |
@@ -701,13 +704,14 @@ out_device: | |||
701 | if (dev->parent && device_is_not_partition(dev)) | 704 | if (dev->parent && device_is_not_partition(dev)) |
702 | sysfs_remove_link(&dev->kobj, "device"); | 705 | sysfs_remove_link(&dev->kobj, "device"); |
703 | out_busid: | 706 | out_busid: |
704 | if (dev->kobj.parent != &dev->class->subsys.kobj && | 707 | if (dev->kobj.parent != &dev->class->p->class_subsys.kobj && |
705 | device_is_not_partition(dev)) | 708 | device_is_not_partition(dev)) |
706 | sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); | 709 | sysfs_remove_link(&dev->class->p->class_subsys.kobj, |
710 | dev->bus_id); | ||
707 | #else | 711 | #else |
708 | /* link in the class directory pointing to the device */ | 712 | /* link in the class directory pointing to the device */ |
709 | error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj, | 713 | error = sysfs_create_link(&dev->class->p->class_subsys.kobj, |
710 | dev->bus_id); | 714 | &dev->kobj, dev->bus_id); |
711 | if (error) | 715 | if (error) |
712 | goto out_subsys; | 716 | goto out_subsys; |
713 | 717 | ||
@@ -720,7 +724,7 @@ out_busid: | |||
720 | return 0; | 724 | return 0; |
721 | 725 | ||
722 | out_busid: | 726 | out_busid: |
723 | sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); | 727 | sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev->bus_id); |
724 | #endif | 728 | #endif |
725 | 729 | ||
726 | out_subsys: | 730 | out_subsys: |
@@ -746,14 +750,15 @@ static void device_remove_class_symlinks(struct device *dev) | |||
746 | sysfs_remove_link(&dev->kobj, "device"); | 750 | sysfs_remove_link(&dev->kobj, "device"); |
747 | } | 751 | } |
748 | 752 | ||
749 | if (dev->kobj.parent != &dev->class->subsys.kobj && | 753 | if (dev->kobj.parent != &dev->class->p->class_subsys.kobj && |
750 | device_is_not_partition(dev)) | 754 | device_is_not_partition(dev)) |
751 | sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); | 755 | sysfs_remove_link(&dev->class->p->class_subsys.kobj, |
756 | dev->bus_id); | ||
752 | #else | 757 | #else |
753 | if (dev->parent && device_is_not_partition(dev)) | 758 | if (dev->parent && device_is_not_partition(dev)) |
754 | sysfs_remove_link(&dev->kobj, "device"); | 759 | sysfs_remove_link(&dev->kobj, "device"); |
755 | 760 | ||
756 | sysfs_remove_link(&dev->class->subsys.kobj, dev->bus_id); | 761 | sysfs_remove_link(&dev->class->p->class_subsys.kobj, dev->bus_id); |
757 | #endif | 762 | #endif |
758 | 763 | ||
759 | sysfs_remove_link(&dev->kobj, "subsystem"); | 764 | sysfs_remove_link(&dev->kobj, "subsystem"); |
@@ -776,6 +781,54 @@ int dev_set_name(struct device *dev, const char *fmt, ...) | |||
776 | EXPORT_SYMBOL_GPL(dev_set_name); | 781 | EXPORT_SYMBOL_GPL(dev_set_name); |
777 | 782 | ||
778 | /** | 783 | /** |
784 | * device_to_dev_kobj - select a /sys/dev/ directory for the device | ||
785 | * @dev: device | ||
786 | * | ||
787 | * By default we select char/ for new entries. Setting class->dev_obj | ||
788 | * to NULL prevents an entry from being created. class->dev_kobj must | ||
789 | * be set (or cleared) before any devices are registered to the class | ||
790 | * otherwise device_create_sys_dev_entry() and | ||
791 | * device_remove_sys_dev_entry() will disagree about the the presence | ||
792 | * of the link. | ||
793 | */ | ||
794 | static struct kobject *device_to_dev_kobj(struct device *dev) | ||
795 | { | ||
796 | struct kobject *kobj; | ||
797 | |||
798 | if (dev->class) | ||
799 | kobj = dev->class->dev_kobj; | ||
800 | else | ||
801 | kobj = sysfs_dev_char_kobj; | ||
802 | |||
803 | return kobj; | ||
804 | } | ||
805 | |||
806 | static int device_create_sys_dev_entry(struct device *dev) | ||
807 | { | ||
808 | struct kobject *kobj = device_to_dev_kobj(dev); | ||
809 | int error = 0; | ||
810 | char devt_str[15]; | ||
811 | |||
812 | if (kobj) { | ||
813 | format_dev_t(devt_str, dev->devt); | ||
814 | error = sysfs_create_link(kobj, &dev->kobj, devt_str); | ||
815 | } | ||
816 | |||
817 | return error; | ||
818 | } | ||
819 | |||
820 | static void device_remove_sys_dev_entry(struct device *dev) | ||
821 | { | ||
822 | struct kobject *kobj = device_to_dev_kobj(dev); | ||
823 | char devt_str[15]; | ||
824 | |||
825 | if (kobj) { | ||
826 | format_dev_t(devt_str, dev->devt); | ||
827 | sysfs_remove_link(kobj, devt_str); | ||
828 | } | ||
829 | } | ||
830 | |||
831 | /** | ||
779 | * device_add - add device to device hierarchy. | 832 | * device_add - add device to device hierarchy. |
780 | * @dev: device. | 833 | * @dev: device. |
781 | * | 834 | * |
@@ -829,6 +882,10 @@ int device_add(struct device *dev) | |||
829 | error = device_create_file(dev, &devt_attr); | 882 | error = device_create_file(dev, &devt_attr); |
830 | if (error) | 883 | if (error) |
831 | goto ueventattrError; | 884 | goto ueventattrError; |
885 | |||
886 | error = device_create_sys_dev_entry(dev); | ||
887 | if (error) | ||
888 | goto devtattrError; | ||
832 | } | 889 | } |
833 | 890 | ||
834 | error = device_add_class_symlinks(dev); | 891 | error = device_add_class_symlinks(dev); |
@@ -849,15 +906,16 @@ int device_add(struct device *dev) | |||
849 | klist_add_tail(&dev->knode_parent, &parent->klist_children); | 906 | klist_add_tail(&dev->knode_parent, &parent->klist_children); |
850 | 907 | ||
851 | if (dev->class) { | 908 | if (dev->class) { |
852 | down(&dev->class->sem); | 909 | mutex_lock(&dev->class->p->class_mutex); |
853 | /* tie the class to the device */ | 910 | /* tie the class to the device */ |
854 | list_add_tail(&dev->node, &dev->class->devices); | 911 | list_add_tail(&dev->node, &dev->class->p->class_devices); |
855 | 912 | ||
856 | /* notify any interfaces that the device is here */ | 913 | /* notify any interfaces that the device is here */ |
857 | list_for_each_entry(class_intf, &dev->class->interfaces, node) | 914 | list_for_each_entry(class_intf, |
915 | &dev->class->p->class_interfaces, node) | ||
858 | if (class_intf->add_dev) | 916 | if (class_intf->add_dev) |
859 | class_intf->add_dev(dev, class_intf); | 917 | class_intf->add_dev(dev, class_intf); |
860 | up(&dev->class->sem); | 918 | mutex_unlock(&dev->class->p->class_mutex); |
861 | } | 919 | } |
862 | Done: | 920 | Done: |
863 | put_device(dev); | 921 | put_device(dev); |
@@ -873,6 +931,9 @@ int device_add(struct device *dev) | |||
873 | device_remove_class_symlinks(dev); | 931 | device_remove_class_symlinks(dev); |
874 | SymlinkError: | 932 | SymlinkError: |
875 | if (MAJOR(dev->devt)) | 933 | if (MAJOR(dev->devt)) |
934 | device_remove_sys_dev_entry(dev); | ||
935 | devtattrError: | ||
936 | if (MAJOR(dev->devt)) | ||
876 | device_remove_file(dev, &devt_attr); | 937 | device_remove_file(dev, &devt_attr); |
877 | ueventattrError: | 938 | ueventattrError: |
878 | device_remove_file(dev, &uevent_attr); | 939 | device_remove_file(dev, &uevent_attr); |
@@ -948,19 +1009,22 @@ void device_del(struct device *dev) | |||
948 | device_pm_remove(dev); | 1009 | device_pm_remove(dev); |
949 | if (parent) | 1010 | if (parent) |
950 | klist_del(&dev->knode_parent); | 1011 | klist_del(&dev->knode_parent); |
951 | if (MAJOR(dev->devt)) | 1012 | if (MAJOR(dev->devt)) { |
1013 | device_remove_sys_dev_entry(dev); | ||
952 | device_remove_file(dev, &devt_attr); | 1014 | device_remove_file(dev, &devt_attr); |
1015 | } | ||
953 | if (dev->class) { | 1016 | if (dev->class) { |
954 | device_remove_class_symlinks(dev); | 1017 | device_remove_class_symlinks(dev); |
955 | 1018 | ||
956 | down(&dev->class->sem); | 1019 | mutex_lock(&dev->class->p->class_mutex); |
957 | /* notify any interfaces that the device is now gone */ | 1020 | /* notify any interfaces that the device is now gone */ |
958 | list_for_each_entry(class_intf, &dev->class->interfaces, node) | 1021 | list_for_each_entry(class_intf, |
1022 | &dev->class->p->class_interfaces, node) | ||
959 | if (class_intf->remove_dev) | 1023 | if (class_intf->remove_dev) |
960 | class_intf->remove_dev(dev, class_intf); | 1024 | class_intf->remove_dev(dev, class_intf); |
961 | /* remove the device from the class list */ | 1025 | /* remove the device from the class list */ |
962 | list_del_init(&dev->node); | 1026 | list_del_init(&dev->node); |
963 | up(&dev->class->sem); | 1027 | mutex_unlock(&dev->class->p->class_mutex); |
964 | } | 1028 | } |
965 | device_remove_file(dev, &uevent_attr); | 1029 | device_remove_file(dev, &uevent_attr); |
966 | device_remove_attrs(dev); | 1030 | device_remove_attrs(dev); |
@@ -1074,7 +1138,25 @@ int __init devices_init(void) | |||
1074 | devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL); | 1138 | devices_kset = kset_create_and_add("devices", &device_uevent_ops, NULL); |
1075 | if (!devices_kset) | 1139 | if (!devices_kset) |
1076 | return -ENOMEM; | 1140 | return -ENOMEM; |
1141 | dev_kobj = kobject_create_and_add("dev", NULL); | ||
1142 | if (!dev_kobj) | ||
1143 | goto dev_kobj_err; | ||
1144 | sysfs_dev_block_kobj = kobject_create_and_add("block", dev_kobj); | ||
1145 | if (!sysfs_dev_block_kobj) | ||
1146 | goto block_kobj_err; | ||
1147 | sysfs_dev_char_kobj = kobject_create_and_add("char", dev_kobj); | ||
1148 | if (!sysfs_dev_char_kobj) | ||
1149 | goto char_kobj_err; | ||
1150 | |||
1077 | return 0; | 1151 | return 0; |
1152 | |||
1153 | char_kobj_err: | ||
1154 | kobject_put(sysfs_dev_block_kobj); | ||
1155 | block_kobj_err: | ||
1156 | kobject_put(dev_kobj); | ||
1157 | dev_kobj_err: | ||
1158 | kset_unregister(devices_kset); | ||
1159 | return -ENOMEM; | ||
1078 | } | 1160 | } |
1079 | 1161 | ||
1080 | EXPORT_SYMBOL_GPL(device_for_each_child); | 1162 | EXPORT_SYMBOL_GPL(device_for_each_child); |
@@ -1158,48 +1240,11 @@ error: | |||
1158 | EXPORT_SYMBOL_GPL(device_create_vargs); | 1240 | EXPORT_SYMBOL_GPL(device_create_vargs); |
1159 | 1241 | ||
1160 | /** | 1242 | /** |
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 | 1243 | * device_create - creates a device and registers it with sysfs |
1200 | * @class: pointer to the struct class that this device should be registered to | 1244 | * @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 | 1245 | * @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 | 1246 | * @devt: the dev_t for the char device to be added |
1247 | * @drvdata: the data to be added to the device for callbacks | ||
1203 | * @fmt: string for the device's name | 1248 | * @fmt: string for the device's name |
1204 | * | 1249 | * |
1205 | * This function can be used by char device classes. A struct device | 1250 | * This function can be used by char device classes. A struct device |
@@ -1217,13 +1262,13 @@ EXPORT_SYMBOL_GPL(device_create_drvdata); | |||
1217 | * been created with a call to class_create(). | 1262 | * been created with a call to class_create(). |
1218 | */ | 1263 | */ |
1219 | struct device *device_create(struct class *class, struct device *parent, | 1264 | struct device *device_create(struct class *class, struct device *parent, |
1220 | dev_t devt, const char *fmt, ...) | 1265 | dev_t devt, void *drvdata, const char *fmt, ...) |
1221 | { | 1266 | { |
1222 | va_list vargs; | 1267 | va_list vargs; |
1223 | struct device *dev; | 1268 | struct device *dev; |
1224 | 1269 | ||
1225 | va_start(vargs, fmt); | 1270 | va_start(vargs, fmt); |
1226 | dev = device_create_vargs(class, parent, devt, NULL, fmt, vargs); | 1271 | dev = device_create_vargs(class, parent, devt, drvdata, fmt, vargs); |
1227 | va_end(vargs); | 1272 | va_end(vargs); |
1228 | return dev; | 1273 | return dev; |
1229 | } | 1274 | } |
@@ -1248,7 +1293,7 @@ void device_destroy(struct class *class, dev_t devt) | |||
1248 | { | 1293 | { |
1249 | struct device *dev; | 1294 | struct device *dev; |
1250 | 1295 | ||
1251 | dev = class_find_device(class, &devt, __match_devt); | 1296 | dev = class_find_device(class, NULL, &devt, __match_devt); |
1252 | if (dev) { | 1297 | if (dev) { |
1253 | put_device(dev); | 1298 | put_device(dev); |
1254 | device_unregister(dev); | 1299 | device_unregister(dev); |
@@ -1298,8 +1343,9 @@ int device_rename(struct device *dev, char *new_name) | |||
1298 | if (old_class_name) { | 1343 | if (old_class_name) { |
1299 | new_class_name = make_class_name(dev->class->name, &dev->kobj); | 1344 | new_class_name = make_class_name(dev->class->name, &dev->kobj); |
1300 | if (new_class_name) { | 1345 | if (new_class_name) { |
1301 | error = sysfs_create_link(&dev->parent->kobj, | 1346 | error = sysfs_create_link_nowarn(&dev->parent->kobj, |
1302 | &dev->kobj, new_class_name); | 1347 | &dev->kobj, |
1348 | new_class_name); | ||
1303 | if (error) | 1349 | if (error) |
1304 | goto out; | 1350 | goto out; |
1305 | sysfs_remove_link(&dev->parent->kobj, old_class_name); | 1351 | sysfs_remove_link(&dev->parent->kobj, old_class_name); |
@@ -1307,11 +1353,12 @@ int device_rename(struct device *dev, char *new_name) | |||
1307 | } | 1353 | } |
1308 | #else | 1354 | #else |
1309 | if (dev->class) { | 1355 | if (dev->class) { |
1310 | error = sysfs_create_link(&dev->class->subsys.kobj, &dev->kobj, | 1356 | error = sysfs_create_link_nowarn(&dev->class->p->class_subsys.kobj, |
1311 | dev->bus_id); | 1357 | &dev->kobj, dev->bus_id); |
1312 | if (error) | 1358 | if (error) |
1313 | goto out; | 1359 | goto out; |
1314 | sysfs_remove_link(&dev->class->subsys.kobj, old_device_name); | 1360 | sysfs_remove_link(&dev->class->p->class_subsys.kobj, |
1361 | old_device_name); | ||
1315 | } | 1362 | } |
1316 | #endif | 1363 | #endif |
1317 | 1364 | ||
@@ -1447,4 +1494,7 @@ void device_shutdown(void) | |||
1447 | dev->driver->shutdown(dev); | 1494 | dev->driver->shutdown(dev); |
1448 | } | 1495 | } |
1449 | } | 1496 | } |
1497 | kobject_put(sysfs_dev_char_kobj); | ||
1498 | kobject_put(sysfs_dev_block_kobj); | ||
1499 | kobject_put(dev_kobj); | ||
1450 | } | 1500 | } |
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 b0be1d18fee2..c9c92b00fd55 100644 --- a/drivers/base/firmware_class.c +++ b/drivers/base/firmware_class.c | |||
@@ -184,7 +184,7 @@ firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
184 | struct device *dev = to_dev(kobj); | 184 | struct device *dev = to_dev(kobj); |
185 | struct firmware_priv *fw_priv = dev_get_drvdata(dev); | 185 | struct firmware_priv *fw_priv = dev_get_drvdata(dev); |
186 | struct firmware *fw; | 186 | struct firmware *fw; |
187 | ssize_t ret_count = count; | 187 | ssize_t ret_count; |
188 | 188 | ||
189 | mutex_lock(&fw_lock); | 189 | mutex_lock(&fw_lock); |
190 | fw = fw_priv->fw; | 190 | fw = fw_priv->fw; |
@@ -192,14 +192,8 @@ firmware_data_read(struct kobject *kobj, struct bin_attribute *bin_attr, | |||
192 | ret_count = -ENODEV; | 192 | ret_count = -ENODEV; |
193 | goto out; | 193 | goto out; |
194 | } | 194 | } |
195 | if (offset > fw->size) { | 195 | ret_count = memory_read_from_buffer(buffer, count, &offset, |
196 | ret_count = 0; | 196 | fw->data, fw->size); |
197 | goto out; | ||
198 | } | ||
199 | if (offset + ret_count > fw->size) | ||
200 | ret_count = fw->size - offset; | ||
201 | |||
202 | memcpy(buffer, fw->data + offset, ret_count); | ||
203 | out: | 197 | out: |
204 | mutex_unlock(&fw_lock); | 198 | mutex_unlock(&fw_lock); |
205 | return ret_count; | 199 | return ret_count; |
diff --git a/drivers/base/isa.c b/drivers/base/isa.c index d2222397a401..efd577574948 100644 --- a/drivers/base/isa.c +++ b/drivers/base/isa.c | |||
@@ -7,6 +7,7 @@ | |||
7 | #include <linux/slab.h> | 7 | #include <linux/slab.h> |
8 | #include <linux/module.h> | 8 | #include <linux/module.h> |
9 | #include <linux/init.h> | 9 | #include <linux/init.h> |
10 | #include <linux/dma-mapping.h> | ||
10 | #include <linux/isa.h> | 11 | #include <linux/isa.h> |
11 | 12 | ||
12 | static struct device isa_bus = { | 13 | static struct device isa_bus = { |
@@ -141,6 +142,9 @@ int isa_register_driver(struct isa_driver *isa_driver, unsigned int ndev) | |||
141 | isa_dev->dev.release = isa_dev_release; | 142 | isa_dev->dev.release = isa_dev_release; |
142 | isa_dev->id = id; | 143 | isa_dev->id = id; |
143 | 144 | ||
145 | isa_dev->dev.coherent_dma_mask = DMA_24BIT_MASK; | ||
146 | isa_dev->dev.dma_mask = &isa_dev->dev.coherent_dma_mask; | ||
147 | |||
144 | error = device_register(&isa_dev->dev); | 148 | error = device_register(&isa_dev->dev); |
145 | if (error) { | 149 | if (error) { |
146 | put_device(&isa_dev->dev); | 150 | put_device(&isa_dev->dev); |
diff --git a/drivers/base/memory.c b/drivers/base/memory.c index 937e8258981d..3ad49a00029f 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); |
@@ -100,9 +101,25 @@ static ssize_t show_mem_phys_index(struct sys_device *dev, char *buf) | |||
100 | } | 101 | } |
101 | 102 | ||
102 | /* | 103 | /* |
104 | * Show whether the section of memory is likely to be hot-removable | ||
105 | */ | ||
106 | static ssize_t show_mem_removable(struct sys_device *dev, char *buf) | ||
107 | { | ||
108 | unsigned long start_pfn; | ||
109 | int ret; | ||
110 | struct memory_block *mem = | ||
111 | container_of(dev, struct memory_block, sysdev); | ||
112 | |||
113 | start_pfn = section_nr_to_pfn(mem->phys_index); | ||
114 | ret = is_mem_section_removable(start_pfn, PAGES_PER_SECTION); | ||
115 | return sprintf(buf, "%d\n", ret); | ||
116 | } | ||
117 | |||
118 | /* | ||
103 | * online, offline, going offline, etc. | 119 | * online, offline, going offline, etc. |
104 | */ | 120 | */ |
105 | static ssize_t show_mem_state(struct sys_device *dev, char *buf) | 121 | static ssize_t show_mem_state(struct sys_device *dev, |
122 | struct sysdev_attribute *attr, char *buf) | ||
106 | { | 123 | { |
107 | struct memory_block *mem = | 124 | struct memory_block *mem = |
108 | container_of(dev, struct memory_block, sysdev); | 125 | container_of(dev, struct memory_block, sysdev); |
@@ -187,9 +204,8 @@ memory_block_action(struct memory_block *mem, unsigned long action) | |||
187 | } | 204 | } |
188 | break; | 205 | break; |
189 | default: | 206 | default: |
190 | printk(KERN_WARNING "%s(%p, %ld) unknown action: %ld\n", | 207 | WARN(1, KERN_WARNING "%s(%p, %ld) unknown action: %ld\n", |
191 | __func__, mem, action, action); | 208 | __func__, mem, action, action); |
192 | WARN_ON(1); | ||
193 | ret = -EINVAL; | 209 | ret = -EINVAL; |
194 | } | 210 | } |
195 | 211 | ||
@@ -217,7 +233,8 @@ out: | |||
217 | } | 233 | } |
218 | 234 | ||
219 | static ssize_t | 235 | static ssize_t |
220 | store_mem_state(struct sys_device *dev, const char *buf, size_t count) | 236 | store_mem_state(struct sys_device *dev, |
237 | struct sysdev_attribute *attr, const char *buf, size_t count) | ||
221 | { | 238 | { |
222 | struct memory_block *mem; | 239 | struct memory_block *mem; |
223 | unsigned int phys_section_nr; | 240 | unsigned int phys_section_nr; |
@@ -248,7 +265,8 @@ out: | |||
248 | * s.t. if I offline all of these sections I can then | 265 | * s.t. if I offline all of these sections I can then |
249 | * remove the physical device? | 266 | * remove the physical device? |
250 | */ | 267 | */ |
251 | static ssize_t show_phys_device(struct sys_device *dev, char *buf) | 268 | static ssize_t show_phys_device(struct sys_device *dev, |
269 | struct sysdev_attribute *attr, char *buf) | ||
252 | { | 270 | { |
253 | struct memory_block *mem = | 271 | struct memory_block *mem = |
254 | container_of(dev, struct memory_block, sysdev); | 272 | container_of(dev, struct memory_block, sysdev); |
@@ -258,6 +276,7 @@ static ssize_t show_phys_device(struct sys_device *dev, char *buf) | |||
258 | static SYSDEV_ATTR(phys_index, 0444, show_mem_phys_index, NULL); | 276 | static SYSDEV_ATTR(phys_index, 0444, show_mem_phys_index, NULL); |
259 | static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state); | 277 | static SYSDEV_ATTR(state, 0644, show_mem_state, store_mem_state); |
260 | static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL); | 278 | static SYSDEV_ATTR(phys_device, 0444, show_phys_device, NULL); |
279 | static SYSDEV_ATTR(removable, 0444, show_mem_removable, NULL); | ||
261 | 280 | ||
262 | #define mem_create_simple_file(mem, attr_name) \ | 281 | #define mem_create_simple_file(mem, attr_name) \ |
263 | sysdev_create_file(&mem->sysdev, &attr_##attr_name) | 282 | sysdev_create_file(&mem->sysdev, &attr_##attr_name) |
@@ -346,6 +365,8 @@ static int add_memory_block(unsigned long node_id, struct mem_section *section, | |||
346 | ret = mem_create_simple_file(mem, state); | 365 | ret = mem_create_simple_file(mem, state); |
347 | if (!ret) | 366 | if (!ret) |
348 | ret = mem_create_simple_file(mem, phys_device); | 367 | ret = mem_create_simple_file(mem, phys_device); |
368 | if (!ret) | ||
369 | ret = mem_create_simple_file(mem, removable); | ||
349 | 370 | ||
350 | return ret; | 371 | return ret; |
351 | } | 372 | } |
@@ -390,6 +411,7 @@ int remove_memory_block(unsigned long node_id, struct mem_section *section, | |||
390 | mem_remove_simple_file(mem, phys_index); | 411 | mem_remove_simple_file(mem, phys_index); |
391 | mem_remove_simple_file(mem, state); | 412 | mem_remove_simple_file(mem, state); |
392 | mem_remove_simple_file(mem, phys_device); | 413 | mem_remove_simple_file(mem, phys_device); |
414 | mem_remove_simple_file(mem, removable); | ||
393 | unregister_memory(mem, section); | 415 | unregister_memory(mem, section); |
394 | 416 | ||
395 | return 0; | 417 | return 0; |
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/power/trace.c b/drivers/base/power/trace.c index 9b1b20b59e0a..2aa6e8fc4def 100644 --- a/drivers/base/power/trace.c +++ b/drivers/base/power/trace.c | |||
@@ -194,7 +194,7 @@ static int show_dev_hash(unsigned int value) | |||
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..75dd6e22faff 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; |
@@ -168,19 +168,16 @@ int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv) | |||
168 | int err = 0; | 168 | int err = 0; |
169 | 169 | ||
170 | if (!cls) { | 170 | if (!cls) { |
171 | printk(KERN_WARNING "sysdev: invalid class passed to " | 171 | WARN(1, KERN_WARNING "sysdev: invalid class passed to " |
172 | "sysdev_driver_register!\n"); | 172 | "sysdev_driver_register!\n"); |
173 | WARN_ON(1); | ||
174 | return -EINVAL; | 173 | return -EINVAL; |
175 | } | 174 | } |
176 | 175 | ||
177 | /* Check whether this driver has already been added to a class. */ | 176 | /* Check whether this driver has already been added to a class. */ |
178 | if (drv->entry.next && !list_empty(&drv->entry)) { | 177 | if (drv->entry.next && !list_empty(&drv->entry)) |
179 | printk(KERN_WARNING "sysdev: class %s: driver (%p) has already" | 178 | WARN(1, KERN_WARNING "sysdev: class %s: driver (%p) has already" |
180 | " been registered to a class, something is wrong, but " | 179 | " been registered to a class, something is wrong, but " |
181 | "will forge on!\n", cls->name, drv); | 180 | "will forge on!\n", cls->name, drv); |
182 | WARN_ON(1); | ||
183 | } | ||
184 | 181 | ||
185 | mutex_lock(&sysdev_drivers_lock); | 182 | mutex_lock(&sysdev_drivers_lock); |
186 | if (cls && kset_get(&cls->kset)) { | 183 | if (cls && kset_get(&cls->kset)) { |
@@ -194,8 +191,7 @@ int sysdev_driver_register(struct sysdev_class *cls, struct sysdev_driver *drv) | |||
194 | } | 191 | } |
195 | } else { | 192 | } else { |
196 | err = -EINVAL; | 193 | err = -EINVAL; |
197 | printk(KERN_ERR "%s: invalid device class\n", __func__); | 194 | WARN(1, KERN_ERR "%s: invalid device class\n", __func__); |
198 | WARN_ON(1); | ||
199 | } | 195 | } |
200 | mutex_unlock(&sysdev_drivers_lock); | 196 | mutex_unlock(&sysdev_drivers_lock); |
201 | return err; | 197 | return err; |
@@ -241,7 +237,8 @@ int sysdev_register(struct sys_device * sysdev) | |||
241 | if (!cls) | 237 | if (!cls) |
242 | return -EINVAL; | 238 | return -EINVAL; |
243 | 239 | ||
244 | pr_debug("Registering sys device '%s'\n", kobject_name(&sysdev->kobj)); | 240 | pr_debug("Registering sys device of class '%s'\n", |
241 | kobject_name(&cls->kset.kobj)); | ||
245 | 242 | ||
246 | /* initialize the kobject to 0, in case it had previously been used */ | 243 | /* initialize the kobject to 0, in case it had previously been used */ |
247 | memset(&sysdev->kobj, 0x00, sizeof(struct kobject)); | 244 | memset(&sysdev->kobj, 0x00, sizeof(struct kobject)); |
@@ -257,6 +254,9 @@ int sysdev_register(struct sys_device * sysdev) | |||
257 | if (!error) { | 254 | if (!error) { |
258 | struct sysdev_driver * drv; | 255 | struct sysdev_driver * drv; |
259 | 256 | ||
257 | pr_debug("Registering sys device '%s'\n", | ||
258 | kobject_name(&sysdev->kobj)); | ||
259 | |||
260 | mutex_lock(&sysdev_drivers_lock); | 260 | mutex_lock(&sysdev_drivers_lock); |
261 | /* Generic notification is implicit, because it's that | 261 | /* Generic notification is implicit, because it's that |
262 | * code that should have called us. | 262 | * code that should have called us. |
@@ -269,6 +269,7 @@ int sysdev_register(struct sys_device * sysdev) | |||
269 | } | 269 | } |
270 | mutex_unlock(&sysdev_drivers_lock); | 270 | mutex_unlock(&sysdev_drivers_lock); |
271 | } | 271 | } |
272 | |||
272 | kobject_uevent(&sysdev->kobj, KOBJ_ADD); | 273 | kobject_uevent(&sysdev->kobj, KOBJ_ADD); |
273 | return error; | 274 | return error; |
274 | } | 275 | } |
@@ -474,3 +475,52 @@ int __init system_bus_init(void) | |||
474 | 475 | ||
475 | EXPORT_SYMBOL_GPL(sysdev_register); | 476 | EXPORT_SYMBOL_GPL(sysdev_register); |
476 | EXPORT_SYMBOL_GPL(sysdev_unregister); | 477 | EXPORT_SYMBOL_GPL(sysdev_unregister); |
478 | |||
479 | #define to_ext_attr(x) container_of(x, struct sysdev_ext_attribute, attr) | ||
480 | |||
481 | ssize_t sysdev_store_ulong(struct sys_device *sysdev, | ||
482 | struct sysdev_attribute *attr, | ||
483 | const char *buf, size_t size) | ||
484 | { | ||
485 | struct sysdev_ext_attribute *ea = to_ext_attr(attr); | ||
486 | char *end; | ||
487 | unsigned long new = simple_strtoul(buf, &end, 0); | ||
488 | if (end == buf) | ||
489 | return -EINVAL; | ||
490 | *(unsigned long *)(ea->var) = new; | ||
491 | return end - buf; | ||
492 | } | ||
493 | EXPORT_SYMBOL_GPL(sysdev_store_ulong); | ||
494 | |||
495 | ssize_t sysdev_show_ulong(struct sys_device *sysdev, | ||
496 | struct sysdev_attribute *attr, | ||
497 | char *buf) | ||
498 | { | ||
499 | struct sysdev_ext_attribute *ea = to_ext_attr(attr); | ||
500 | return snprintf(buf, PAGE_SIZE, "%lx\n", *(unsigned long *)(ea->var)); | ||
501 | } | ||
502 | EXPORT_SYMBOL_GPL(sysdev_show_ulong); | ||
503 | |||
504 | ssize_t sysdev_store_int(struct sys_device *sysdev, | ||
505 | struct sysdev_attribute *attr, | ||
506 | const char *buf, size_t size) | ||
507 | { | ||
508 | struct sysdev_ext_attribute *ea = to_ext_attr(attr); | ||
509 | char *end; | ||
510 | long new = simple_strtol(buf, &end, 0); | ||
511 | if (end == buf || new > INT_MAX || new < INT_MIN) | ||
512 | return -EINVAL; | ||
513 | *(int *)(ea->var) = new; | ||
514 | return end - buf; | ||
515 | } | ||
516 | EXPORT_SYMBOL_GPL(sysdev_store_int); | ||
517 | |||
518 | ssize_t sysdev_show_int(struct sys_device *sysdev, | ||
519 | struct sysdev_attribute *attr, | ||
520 | char *buf) | ||
521 | { | ||
522 | struct sysdev_ext_attribute *ea = to_ext_attr(attr); | ||
523 | return snprintf(buf, PAGE_SIZE, "%d\n", *(int *)(ea->var)); | ||
524 | } | ||
525 | EXPORT_SYMBOL_GPL(sysdev_show_int); | ||
526 | |||
diff --git a/drivers/base/topology.c b/drivers/base/topology.c index 3f6d9b0a6abe..199cd97e32e6 100644 --- a/drivers/base/topology.c +++ b/drivers/base/topology.c | |||
@@ -34,7 +34,8 @@ | |||
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)); \ |
@@ -59,14 +60,17 @@ static ssize_t show_cpumap(int type, cpumask_t *mask, char *buf) | |||
59 | 60 | ||
60 | #ifdef arch_provides_topology_pointers | 61 | #ifdef arch_provides_topology_pointers |
61 | #define define_siblings_show_map(name) \ | 62 | #define define_siblings_show_map(name) \ |
62 | static 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) \ | ||
63 | { \ | 65 | { \ |
64 | unsigned int cpu = dev->id; \ | 66 | unsigned int cpu = dev->id; \ |
65 | return show_cpumap(0, &(topology_##name(cpu)), buf); \ | 67 | return show_cpumap(0, &(topology_##name(cpu)), buf); \ |
66 | } | 68 | } |
67 | 69 | ||
68 | #define define_siblings_show_list(name) \ | 70 | #define define_siblings_show_list(name) \ |
69 | static 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) \ | ||
70 | { \ | 74 | { \ |
71 | unsigned int cpu = dev->id; \ | 75 | unsigned int cpu = dev->id; \ |
72 | return show_cpumap(1, &(topology_##name(cpu)), buf); \ | 76 | return show_cpumap(1, &(topology_##name(cpu)), buf); \ |
@@ -74,7 +78,8 @@ static ssize_t show_##name##_list(struct sys_device *dev, char *buf) \ | |||
74 | 78 | ||
75 | #else | 79 | #else |
76 | #define define_siblings_show_map(name) \ | 80 | #define define_siblings_show_map(name) \ |
77 | static ssize_t show_##name(struct sys_device *dev, char *buf) \ | 81 | static ssize_t show_##name(struct sys_device *dev, \ |
82 | struct sysdev_attribute *attr, char *buf) \ | ||
78 | { \ | 83 | { \ |
79 | unsigned int cpu = dev->id; \ | 84 | unsigned int cpu = dev->id; \ |
80 | cpumask_t mask = topology_##name(cpu); \ | 85 | cpumask_t mask = topology_##name(cpu); \ |
@@ -82,7 +87,9 @@ static ssize_t show_##name(struct sys_device *dev, char *buf) \ | |||
82 | } | 87 | } |
83 | 88 | ||
84 | #define define_siblings_show_list(name) \ | 89 | #define define_siblings_show_list(name) \ |
85 | static ssize_t show_##name##_list(struct sys_device *dev, char *buf) \ | 90 | static ssize_t show_##name##_list(struct sys_device *dev, \ |
91 | struct sysdev_attribute *attr, \ | ||
92 | char *buf) \ | ||
86 | { \ | 93 | { \ |
87 | unsigned int cpu = dev->id; \ | 94 | unsigned int cpu = dev->id; \ |
88 | cpumask_t mask = topology_##name(cpu); \ | 95 | cpumask_t mask = topology_##name(cpu); \ |