Blame view
drivers/base/class.c
15.1 KB
1da177e4c Linux-2.6.12-rc2 |
1 2 3 4 5 6 7 8 9 10 11 |
/* * class.c - basic device class management * * Copyright (c) 2002-3 Patrick Mochel * Copyright (c) 2002-3 Open Source Development Labs * Copyright (c) 2003-2004 Greg Kroah-Hartman * Copyright (c) 2003-2004 IBM Corp. * * This file is released under the GPLv2 * */ |
1da177e4c Linux-2.6.12-rc2 |
12 13 14 15 16 |
#include <linux/device.h> #include <linux/module.h> #include <linux/init.h> #include <linux/string.h> #include <linux/kdev_t.h> |
e9ba6365f [PATCH] CLASS: mo... |
17 |
#include <linux/err.h> |
4e57b6817 [PATCH] fix missi... |
18 |
#include <linux/slab.h> |
edfaa7c36 Driver core: conv... |
19 |
#include <linux/genhd.h> |
f75b1c60f class: change int... |
20 |
#include <linux/mutex.h> |
1da177e4c Linux-2.6.12-rc2 |
21 22 23 |
#include "base.h" #define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr) |
1da177e4c Linux-2.6.12-rc2 |
24 |
|
4a3ad20cc Driver core: codi... |
25 26 |
static ssize_t class_attr_show(struct kobject *kobj, struct attribute *attr, char *buf) |
1da177e4c Linux-2.6.12-rc2 |
27 |
{ |
4a3ad20cc Driver core: codi... |
28 |
struct class_attribute *class_attr = to_class_attr(attr); |
6b6e39a6a driver-core: merg... |
29 |
struct subsys_private *cp = to_subsys_private(kobj); |
4a0c20bf8 [PATCH] sysfs: (d... |
30 |
ssize_t ret = -EIO; |
1da177e4c Linux-2.6.12-rc2 |
31 32 |
if (class_attr->show) |
28812fe11 driver-core: Add ... |
33 |
ret = class_attr->show(cp->class, class_attr, buf); |
1da177e4c Linux-2.6.12-rc2 |
34 35 |
return ret; } |
4a3ad20cc Driver core: codi... |
36 37 |
static ssize_t class_attr_store(struct kobject *kobj, struct attribute *attr, const char *buf, size_t count) |
1da177e4c Linux-2.6.12-rc2 |
38 |
{ |
4a3ad20cc Driver core: codi... |
39 |
struct class_attribute *class_attr = to_class_attr(attr); |
6b6e39a6a driver-core: merg... |
40 |
struct subsys_private *cp = to_subsys_private(kobj); |
4a0c20bf8 [PATCH] sysfs: (d... |
41 |
ssize_t ret = -EIO; |
1da177e4c Linux-2.6.12-rc2 |
42 43 |
if (class_attr->store) |
28812fe11 driver-core: Add ... |
44 |
ret = class_attr->store(cp->class, class_attr, buf, count); |
1da177e4c Linux-2.6.12-rc2 |
45 46 |
return ret; } |
672d82c18 class: Implement ... |
47 48 49 50 51 52 53 54 55 56 57 |
static const void *class_attr_namespace(struct kobject *kobj, const struct attribute *attr) { struct class_attribute *class_attr = to_class_attr(attr); struct subsys_private *cp = to_subsys_private(kobj); const void *ns = NULL; if (class_attr->namespace) ns = class_attr->namespace(cp->class, class_attr); return ns; } |
4a3ad20cc Driver core: codi... |
58 |
static void class_release(struct kobject *kobj) |
1da177e4c Linux-2.6.12-rc2 |
59 |
{ |
6b6e39a6a driver-core: merg... |
60 |
struct subsys_private *cp = to_subsys_private(kobj); |
7c71448b8 class: move drive... |
61 |
struct class *class = cp->class; |
1da177e4c Linux-2.6.12-rc2 |
62 63 64 65 66 67 68 69 70 71 |
pr_debug("class '%s': release. ", class->name); if (class->class_release) class->class_release(class); else pr_debug("class '%s' does not have a release() function, " "be careful ", class->name); |
18d19c964 class: Free the c... |
72 73 |
kfree(cp); |
1da177e4c Linux-2.6.12-rc2 |
74 |
} |
bc451f205 kobj: Add basic i... |
75 76 |
static const struct kobj_ns_type_operations *class_child_ns_type(struct kobject *kobj) { |
6b6e39a6a driver-core: merg... |
77 |
struct subsys_private *cp = to_subsys_private(kobj); |
bc451f205 kobj: Add basic i... |
78 79 80 81 |
struct class *class = cp->class; return class->ns_type; } |
52cf25d0a Driver core: Cons... |
82 |
static const struct sysfs_ops class_sysfs_ops = { |
672d82c18 class: Implement ... |
83 84 85 |
.show = class_attr_show, .store = class_attr_store, .namespace = class_attr_namespace, |
1da177e4c Linux-2.6.12-rc2 |
86 |
}; |
adc56808f Driver core: rena... |
87 |
static struct kobj_type class_ktype = { |
1da177e4c Linux-2.6.12-rc2 |
88 89 |
.sysfs_ops = &class_sysfs_ops, .release = class_release, |
bc451f205 kobj: Add basic i... |
90 |
.child_ns_type = class_child_ns_type, |
1da177e4c Linux-2.6.12-rc2 |
91 |
}; |
6b6e39a6a driver-core: merg... |
92 |
/* Hotplug events for classes go to the class subsys */ |
443dbf900 kset: convert dri... |
93 |
static struct kset *class_kset; |
1da177e4c Linux-2.6.12-rc2 |
94 |
|
4a3ad20cc Driver core: codi... |
95 |
int class_create_file(struct class *cls, const struct class_attribute *attr) |
1da177e4c Linux-2.6.12-rc2 |
96 97 |
{ int error; |
4a3ad20cc Driver core: codi... |
98 |
if (cls) |
6b6e39a6a driver-core: merg... |
99 |
error = sysfs_create_file(&cls->p->subsys.kobj, |
1fbfee6c6 class: rename "su... |
100 |
&attr->attr); |
4a3ad20cc Driver core: codi... |
101 |
else |
1da177e4c Linux-2.6.12-rc2 |
102 103 104 |
error = -EINVAL; return error; } |
4a3ad20cc Driver core: codi... |
105 |
void class_remove_file(struct class *cls, const struct class_attribute *attr) |
1da177e4c Linux-2.6.12-rc2 |
106 107 |
{ if (cls) |
6b6e39a6a driver-core: merg... |
108 |
sysfs_remove_file(&cls->p->subsys.kobj, &attr->attr); |
1da177e4c Linux-2.6.12-rc2 |
109 |
} |
1740757e8 [PATCH] Driver Co... |
110 |
static struct class *class_get(struct class *cls) |
1da177e4c Linux-2.6.12-rc2 |
111 112 |
{ if (cls) |
6b6e39a6a driver-core: merg... |
113 |
kset_get(&cls->p->subsys); |
7c71448b8 class: move drive... |
114 |
return cls; |
1da177e4c Linux-2.6.12-rc2 |
115 |
} |
4a3ad20cc Driver core: codi... |
116 |
static void class_put(struct class *cls) |
1da177e4c Linux-2.6.12-rc2 |
117 |
{ |
51d172d5f [PATCH] Driver Co... |
118 |
if (cls) |
6b6e39a6a driver-core: merg... |
119 |
kset_put(&cls->p->subsys); |
1da177e4c Linux-2.6.12-rc2 |
120 |
} |
4a3ad20cc Driver core: codi... |
121 |
static int add_class_attrs(struct class *cls) |
1da177e4c Linux-2.6.12-rc2 |
122 123 124 125 126 127 |
{ int i; int error = 0; if (cls->class_attrs) { for (i = 0; attr_name(cls->class_attrs[i]); i++) { |
4a3ad20cc Driver core: codi... |
128 |
error = class_create_file(cls, &cls->class_attrs[i]); |
1da177e4c Linux-2.6.12-rc2 |
129 |
if (error) |
4a3ad20cc Driver core: codi... |
130 |
goto error; |
1da177e4c Linux-2.6.12-rc2 |
131 132 |
} } |
4a3ad20cc Driver core: codi... |
133 |
done: |
1da177e4c Linux-2.6.12-rc2 |
134 |
return error; |
4a3ad20cc Driver core: codi... |
135 |
error: |
1da177e4c Linux-2.6.12-rc2 |
136 |
while (--i >= 0) |
4a3ad20cc Driver core: codi... |
137 138 |
class_remove_file(cls, &cls->class_attrs[i]); goto done; |
1da177e4c Linux-2.6.12-rc2 |
139 |
} |
4a3ad20cc Driver core: codi... |
140 |
static void remove_class_attrs(struct class *cls) |
1da177e4c Linux-2.6.12-rc2 |
141 142 143 144 145 |
{ int i; if (cls->class_attrs) { for (i = 0; attr_name(cls->class_attrs[i]); i++) |
4a3ad20cc Driver core: codi... |
146 |
class_remove_file(cls, &cls->class_attrs[i]); |
1da177e4c Linux-2.6.12-rc2 |
147 148 |
} } |
5a3ceb861 driver-core: use ... |
149 150 151 152 153 154 155 156 157 158 159 160 161 |
static void klist_class_dev_get(struct klist_node *n) { struct device *dev = container_of(n, struct device, knode_class); get_device(dev); } static void klist_class_dev_put(struct klist_node *n) { struct device *dev = container_of(n, struct device, knode_class); put_device(dev); } |
d2a3b9146 class: add lockde... |
162 |
int __class_register(struct class *cls, struct lock_class_key *key) |
1da177e4c Linux-2.6.12-rc2 |
163 |
{ |
6b6e39a6a driver-core: merg... |
164 |
struct subsys_private *cp; |
1da177e4c Linux-2.6.12-rc2 |
165 166 167 168 |
int error; pr_debug("device class '%s': registering ", cls->name); |
7c71448b8 class: move drive... |
169 170 171 |
cp = kzalloc(sizeof(*cp), GFP_KERNEL); if (!cp) return -ENOMEM; |
6b6e39a6a driver-core: merg... |
172 |
klist_init(&cp->klist_devices, klist_class_dev_get, klist_class_dev_put); |
ca22e56de driver-core: impl... |
173 |
INIT_LIST_HEAD(&cp->interfaces); |
6b6e39a6a driver-core: merg... |
174 |
kset_init(&cp->glue_dirs); |
ca22e56de driver-core: impl... |
175 |
__mutex_init(&cp->mutex, "subsys mutex", key); |
6b6e39a6a driver-core: merg... |
176 |
error = kobject_set_name(&cp->subsys.kobj, "%s", cls->name); |
7c71448b8 class: move drive... |
177 178 |
if (error) { kfree(cp); |
1da177e4c Linux-2.6.12-rc2 |
179 |
return error; |
7c71448b8 class: move drive... |
180 |
} |
1da177e4c Linux-2.6.12-rc2 |
181 |
|
e105b8bfc sysfs: add /sys/d... |
182 183 184 |
/* set the default /sys/dev directory for devices of this class */ if (!cls->dev_kobj) cls->dev_kobj = sysfs_dev_char_kobj; |
e52eec13c SYSFS: Allow boot... |
185 |
#if defined(CONFIG_BLOCK) |
edfaa7c36 Driver core: conv... |
186 |
/* let the block class directory show up in the root of sysfs */ |
e52eec13c SYSFS: Allow boot... |
187 |
if (!sysfs_deprecated || cls != &block_class) |
6b6e39a6a driver-core: merg... |
188 |
cp->subsys.kobj.kset = class_kset; |
edfaa7c36 Driver core: conv... |
189 |
#else |
6b6e39a6a driver-core: merg... |
190 |
cp->subsys.kobj.kset = class_kset; |
edfaa7c36 Driver core: conv... |
191 |
#endif |
6b6e39a6a driver-core: merg... |
192 |
cp->subsys.kobj.ktype = &class_ktype; |
7c71448b8 class: move drive... |
193 194 |
cp->class = cls; cls->p = cp; |
1da177e4c Linux-2.6.12-rc2 |
195 |
|
6b6e39a6a driver-core: merg... |
196 |
error = kset_register(&cp->subsys); |
7c71448b8 class: move drive... |
197 198 199 |
if (error) { kfree(cp); return error; |
1da177e4c Linux-2.6.12-rc2 |
200 |
} |
7c71448b8 class: move drive... |
201 202 |
error = add_class_attrs(class_get(cls)); class_put(cls); |
1da177e4c Linux-2.6.12-rc2 |
203 204 |
return error; } |
d2a3b9146 class: add lockde... |
205 |
EXPORT_SYMBOL_GPL(__class_register); |
1da177e4c Linux-2.6.12-rc2 |
206 |
|
4a3ad20cc Driver core: codi... |
207 |
void class_unregister(struct class *cls) |
1da177e4c Linux-2.6.12-rc2 |
208 209 210 211 |
{ pr_debug("device class '%s': unregistering ", cls->name); remove_class_attrs(cls); |
6b6e39a6a driver-core: merg... |
212 |
kset_unregister(&cls->p->subsys); |
1da177e4c Linux-2.6.12-rc2 |
213 |
} |
e9ba6365f [PATCH] CLASS: mo... |
214 215 |
static void class_create_release(struct class *cls) { |
2b3a302a0 driver core: repl... |
216 217 |
pr_debug("%s called for %s ", __func__, cls->name); |
e9ba6365f [PATCH] CLASS: mo... |
218 219 |
kfree(cls); } |
2fc68447d [PATCH] class: ad... |
220 221 222 223 |
/** * class_create - create a struct class structure * @owner: pointer to the module that is to "own" this struct class * @name: pointer to a string for the name of this class. |
0e241ffd3 locking: fix mute... |
224 |
* @key: the lock_class_key for this class; used by mutex lock debugging |
2fc68447d [PATCH] class: ad... |
225 226 |
* * This is used to create a struct class pointer that can then be used |
c3b19ff06 driver core: remo... |
227 |
* in calls to device_create(). |
2fc68447d [PATCH] class: ad... |
228 |
* |
f0eae0ed3 driver-core: docu... |
229 230 |
* Returns &struct class pointer on success, or ERR_PTR() on error. * |
2fc68447d [PATCH] class: ad... |
231 232 233 |
* Note, the pointer created here is to be destroyed when finished by * making a call to class_destroy(). */ |
d2a3b9146 class: add lockde... |
234 235 |
struct class *__class_create(struct module *owner, const char *name, struct lock_class_key *key) |
e9ba6365f [PATCH] CLASS: mo... |
236 237 238 |
{ struct class *cls; int retval; |
4aed0644d [PATCH] drivers/b... |
239 |
cls = kzalloc(sizeof(*cls), GFP_KERNEL); |
e9ba6365f [PATCH] CLASS: mo... |
240 241 242 243 |
if (!cls) { retval = -ENOMEM; goto error; } |
e9ba6365f [PATCH] CLASS: mo... |
244 245 246 247 |
cls->name = name; cls->owner = owner; cls->class_release = class_create_release; |
e9ba6365f [PATCH] CLASS: mo... |
248 |
|
d2a3b9146 class: add lockde... |
249 |
retval = __class_register(cls, key); |
e9ba6365f [PATCH] CLASS: mo... |
250 251 252 253 254 255 256 257 258 |
if (retval) goto error; return cls; error: kfree(cls); return ERR_PTR(retval); } |
d2a3b9146 class: add lockde... |
259 |
EXPORT_SYMBOL_GPL(__class_create); |
e9ba6365f [PATCH] CLASS: mo... |
260 |
|
2fc68447d [PATCH] class: ad... |
261 262 |
/** * class_destroy - destroys a struct class structure |
92a0f861f [PATCH] Fix param... |
263 |
* @cls: pointer to the struct class that is to be destroyed |
2fc68447d [PATCH] class: ad... |
264 265 266 267 |
* * Note, the pointer to be destroyed must have been created with a call * to class_create(). */ |
e9ba6365f [PATCH] CLASS: mo... |
268 269 270 271 272 273 274 |
void class_destroy(struct class *cls) { if ((cls == NULL) || (IS_ERR(cls))) return; class_unregister(cls); } |
1da177e4c Linux-2.6.12-rc2 |
275 |
|
fd04897bb Driver Core: add ... |
276 |
/** |
5a3ceb861 driver-core: use ... |
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 |
* class_dev_iter_init - initialize class device iterator * @iter: class iterator to initialize * @class: the class we wanna iterate over * @start: the device to start iterating from, if any * @type: device_type of the devices to iterate over, NULL for all * * Initialize class iterator @iter such that it iterates over devices * of @class. If @start is set, the list iteration will start there, * otherwise if it is NULL, the iteration starts at the beginning of * the list. */ void class_dev_iter_init(struct class_dev_iter *iter, struct class *class, struct device *start, const struct device_type *type) { struct klist_node *start_knode = NULL; if (start) start_knode = &start->knode_class; |
6b6e39a6a driver-core: merg... |
295 |
klist_iter_init_node(&class->p->klist_devices, &iter->ki, start_knode); |
5a3ceb861 driver-core: use ... |
296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 |
iter->type = type; } EXPORT_SYMBOL_GPL(class_dev_iter_init); /** * class_dev_iter_next - iterate to the next device * @iter: class iterator to proceed * * Proceed @iter to the next device and return it. Returns NULL if * iteration is complete. * * The returned device is referenced and won't be released till * iterator is proceed to the next device or exited. The caller is * free to do whatever it wants to do with the device including * calling back into class code. */ struct device *class_dev_iter_next(struct class_dev_iter *iter) { struct klist_node *knode; struct device *dev; while (1) { knode = klist_next(&iter->ki); if (!knode) return NULL; dev = container_of(knode, struct device, knode_class); if (!iter->type || iter->type == dev->type) return dev; } } EXPORT_SYMBOL_GPL(class_dev_iter_next); /** * class_dev_iter_exit - finish iteration * @iter: class iterator to finish * * Finish an iteration. Always call this function after iteration is * complete whether the iteration ran till the end or not. */ void class_dev_iter_exit(struct class_dev_iter *iter) { klist_iter_exit(&iter->ki); } EXPORT_SYMBOL_GPL(class_dev_iter_exit); /** |
fd04897bb Driver Core: add ... |
342 343 |
* class_for_each_device - device iterator * @class: the class we're iterating |
93562b537 Driver Core: add ... |
344 |
* @start: the device to start with in the list, if any. |
fd04897bb Driver Core: add ... |
345 346 347 348 |
* @data: data for the callback * @fn: function to be called for each device * * Iterate over @class's list of devices, and call @fn for each, |
93562b537 Driver Core: add ... |
349 350 351 |
* passing it @data. If @start is set, the list iteration will start * there, otherwise if it is NULL, the iteration starts at the * beginning of the list. |
fd04897bb Driver Core: add ... |
352 353 354 355 |
* * We check the return of @fn each time. If it returns anything * other than 0, we break out and return that value. * |
5a3ceb861 driver-core: use ... |
356 357 |
* @fn is allowed to do anything including calling back into class * code. There's no locking restriction. |
fd04897bb Driver Core: add ... |
358 |
*/ |
93562b537 Driver Core: add ... |
359 360 |
int class_for_each_device(struct class *class, struct device *start, void *data, int (*fn)(struct device *, void *)) |
fd04897bb Driver Core: add ... |
361 |
{ |
5a3ceb861 driver-core: use ... |
362 |
struct class_dev_iter iter; |
fd04897bb Driver Core: add ... |
363 364 365 366 367 |
struct device *dev; int error = 0; if (!class) return -EINVAL; |
7c2250352 driver model: ant... |
368 369 370 371 372 |
if (!class->p) { WARN(1, "%s called for class '%s' before it was initialized", __func__, class->name); return -EINVAL; } |
5a3ceb861 driver-core: use ... |
373 374 |
class_dev_iter_init(&iter, class, start, NULL); while ((dev = class_dev_iter_next(&iter))) { |
93562b537 Driver Core: add ... |
375 |
error = fn(dev, data); |
fd04897bb Driver Core: add ... |
376 377 378 |
if (error) break; } |
5a3ceb861 driver-core: use ... |
379 |
class_dev_iter_exit(&iter); |
fd04897bb Driver Core: add ... |
380 381 382 383 384 385 386 387 |
return error; } EXPORT_SYMBOL_GPL(class_for_each_device); /** * class_find_device - device iterator for locating a particular device * @class: the class we're iterating |
695794ae0 Driver Core: add ... |
388 |
* @start: Device to begin with |
fd04897bb Driver Core: add ... |
389 390 391 392 393 394 395 396 397 398 |
* @data: data for the match function * @match: function to check device * * This is similar to the class_for_each_dev() function above, but it * returns a reference to a device that is 'found' for later use, as * determined by the @match callback. * * The callback should return 0 if the device doesn't match and non-zero * if it does. If the callback returns non-zero, this function will * return to the caller and not iterate over any more devices. |
a63ca8f65 docbook: fix driv... |
399 |
* |
fd04897bb Driver Core: add ... |
400 401 |
* Note, you will need to drop the reference with put_device() after use. * |
5a3ceb861 driver-core: use ... |
402 403 |
* @fn is allowed to do anything including calling back into class * code. There's no locking restriction. |
fd04897bb Driver Core: add ... |
404 |
*/ |
695794ae0 Driver Core: add ... |
405 406 407 |
struct device *class_find_device(struct class *class, struct device *start, void *data, int (*match)(struct device *, void *)) |
fd04897bb Driver Core: add ... |
408 |
{ |
5a3ceb861 driver-core: use ... |
409 |
struct class_dev_iter iter; |
fd04897bb Driver Core: add ... |
410 |
struct device *dev; |
fd04897bb Driver Core: add ... |
411 412 413 |
if (!class) return NULL; |
7c2250352 driver model: ant... |
414 415 416 417 418 |
if (!class->p) { WARN(1, "%s called for class '%s' before it was initialized", __func__, class->name); return NULL; } |
fd04897bb Driver Core: add ... |
419 |
|
5a3ceb861 driver-core: use ... |
420 421 |
class_dev_iter_init(&iter, class, start, NULL); while ((dev = class_dev_iter_next(&iter))) { |
695794ae0 Driver Core: add ... |
422 |
if (match(dev, data)) { |
5a3ceb861 driver-core: use ... |
423 |
get_device(dev); |
fd04897bb Driver Core: add ... |
424 |
break; |
5a3ceb861 driver-core: use ... |
425 |
} |
fd04897bb Driver Core: add ... |
426 |
} |
5a3ceb861 driver-core: use ... |
427 |
class_dev_iter_exit(&iter); |
fd04897bb Driver Core: add ... |
428 |
|
5a3ceb861 driver-core: use ... |
429 |
return dev; |
fd04897bb Driver Core: add ... |
430 431 |
} EXPORT_SYMBOL_GPL(class_find_device); |
1da177e4c Linux-2.6.12-rc2 |
432 433 434 |
int class_interface_register(struct class_interface *class_intf) { struct class *parent; |
5a3ceb861 driver-core: use ... |
435 |
struct class_dev_iter iter; |
c47ed219b Class: add suppor... |
436 |
struct device *dev; |
1da177e4c Linux-2.6.12-rc2 |
437 438 439 440 441 442 443 |
if (!class_intf || !class_intf->class) return -ENODEV; parent = class_get(class_intf->class); if (!parent) return -EINVAL; |
ca22e56de driver-core: impl... |
444 445 |
mutex_lock(&parent->p->mutex); list_add_tail(&class_intf->node, &parent->p->interfaces); |
c47ed219b Class: add suppor... |
446 |
if (class_intf->add_dev) { |
5a3ceb861 driver-core: use ... |
447 448 |
class_dev_iter_init(&iter, parent, NULL, NULL); while ((dev = class_dev_iter_next(&iter))) |
c47ed219b Class: add suppor... |
449 |
class_intf->add_dev(dev, class_intf); |
5a3ceb861 driver-core: use ... |
450 |
class_dev_iter_exit(&iter); |
c47ed219b Class: add suppor... |
451 |
} |
ca22e56de driver-core: impl... |
452 |
mutex_unlock(&parent->p->mutex); |
1da177e4c Linux-2.6.12-rc2 |
453 454 455 456 457 458 |
return 0; } void class_interface_unregister(struct class_interface *class_intf) { |
4a3ad20cc Driver core: codi... |
459 |
struct class *parent = class_intf->class; |
5a3ceb861 driver-core: use ... |
460 |
struct class_dev_iter iter; |
c47ed219b Class: add suppor... |
461 |
struct device *dev; |
1da177e4c Linux-2.6.12-rc2 |
462 463 464 |
if (!parent) return; |
ca22e56de driver-core: impl... |
465 |
mutex_lock(&parent->p->mutex); |
1da177e4c Linux-2.6.12-rc2 |
466 |
list_del_init(&class_intf->node); |
c47ed219b Class: add suppor... |
467 |
if (class_intf->remove_dev) { |
5a3ceb861 driver-core: use ... |
468 469 |
class_dev_iter_init(&iter, parent, NULL, NULL); while ((dev = class_dev_iter_next(&iter))) |
c47ed219b Class: add suppor... |
470 |
class_intf->remove_dev(dev, class_intf); |
5a3ceb861 driver-core: use ... |
471 |
class_dev_iter_exit(&iter); |
c47ed219b Class: add suppor... |
472 |
} |
ca22e56de driver-core: impl... |
473 |
mutex_unlock(&parent->p->mutex); |
1da177e4c Linux-2.6.12-rc2 |
474 475 476 |
class_put(parent); } |
319684b1c driver core: fix ... |
477 478 |
ssize_t show_class_attr_string(struct class *class, struct class_attribute *attr, char *buf) |
869dfc875 driver core: Add ... |
479 480 481 482 483 484 485 486 |
{ struct class_attribute_string *cs; cs = container_of(attr, struct class_attribute_string, attr); return snprintf(buf, PAGE_SIZE, "%s ", cs->str); } EXPORT_SYMBOL_GPL(show_class_attr_string); |
462270944 Driver core: Add ... |
487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 |
struct class_compat { struct kobject *kobj; }; /** * class_compat_register - register a compatibility class * @name: the name of the class * * Compatibility class are meant as a temporary user-space compatibility * workaround when converting a family of class devices to a bus devices. */ struct class_compat *class_compat_register(const char *name) { struct class_compat *cls; cls = kmalloc(sizeof(struct class_compat), GFP_KERNEL); if (!cls) return NULL; cls->kobj = kobject_create_and_add(name, &class_kset->kobj); if (!cls->kobj) { kfree(cls); return NULL; } return cls; } EXPORT_SYMBOL_GPL(class_compat_register); /** * class_compat_unregister - unregister a compatibility class * @cls: the class to unregister */ void class_compat_unregister(struct class_compat *cls) { kobject_put(cls->kobj); kfree(cls); } EXPORT_SYMBOL_GPL(class_compat_unregister); /** * class_compat_create_link - create a compatibility class device link to * a bus device * @cls: the compatibility class * @dev: the target bus device * @device_link: an optional device to which a "device" link should be created */ int class_compat_create_link(struct class_compat *cls, struct device *dev, struct device *device_link) { int error; error = sysfs_create_link(cls->kobj, &dev->kobj, dev_name(dev)); if (error) return error; /* * Optionally add a "device" link (typically to the parent), as a * class device would have one and we want to provide as much * backwards compatibility as possible. */ if (device_link) { error = sysfs_create_link(&dev->kobj, &device_link->kobj, "device"); if (error) sysfs_remove_link(cls->kobj, dev_name(dev)); } return error; } EXPORT_SYMBOL_GPL(class_compat_create_link); /** * class_compat_remove_link - remove a compatibility class device link to * a bus device * @cls: the compatibility class * @dev: the target bus device * @device_link: an optional device to which a "device" link was previously * created */ void class_compat_remove_link(struct class_compat *cls, struct device *dev, struct device *device_link) { if (device_link) sysfs_remove_link(&dev->kobj, "device"); sysfs_remove_link(cls->kobj, dev_name(dev)); } EXPORT_SYMBOL_GPL(class_compat_remove_link); |
1da177e4c Linux-2.6.12-rc2 |
573 574 |
int __init classes_init(void) { |
443dbf900 kset: convert dri... |
575 576 577 |
class_kset = kset_create_and_add("class", NULL, NULL); if (!class_kset) return -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
578 579 580 581 582 |
return 0; } EXPORT_SYMBOL_GPL(class_create_file); EXPORT_SYMBOL_GPL(class_remove_file); |
1da177e4c Linux-2.6.12-rc2 |
583 |
EXPORT_SYMBOL_GPL(class_unregister); |
e9ba6365f [PATCH] CLASS: mo... |
584 |
EXPORT_SYMBOL_GPL(class_destroy); |
1da177e4c Linux-2.6.12-rc2 |
585 |
|
1da177e4c Linux-2.6.12-rc2 |
586 587 |
EXPORT_SYMBOL_GPL(class_interface_register); EXPORT_SYMBOL_GPL(class_interface_unregister); |