diff options
author | Ingo Molnar <mingo@elte.hu> | 2008-07-24 02:09:26 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-07-24 02:09:26 -0400 |
commit | 28afe961a18f77b2249062499bdbf70fd2ec6bba (patch) | |
tree | 71a5cb32924b8c8256bbc0f2f81c6b8c2ac79108 /drivers/base/class.c | |
parent | 1e01cb0c6ff7e9ddb6547551794c6aa82785a7cb (diff) | |
parent | 338b9bb3adac0d2c5a1e180491d9b001d624c402 (diff) |
Merge branch 'linus' into tracing/urgent
Diffstat (limited to 'drivers/base/class.c')
-rw-r--r-- | drivers/base/class.c | 153 |
1 files changed, 89 insertions, 64 deletions
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); |