OpenCores
URL https://opencores.org/ocsvn/test_project/test_project/trunk

Subversion Repositories test_project

[/] [test_project/] [trunk/] [linux_sd_driver/] [drivers/] [base/] [class.c] - Blame information for rev 62

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 62 marcus.erl
/*
2
 * class.c - basic device class management
3
 *
4
 * Copyright (c) 2002-3 Patrick Mochel
5
 * Copyright (c) 2002-3 Open Source Development Labs
6
 * Copyright (c) 2003-2004 Greg Kroah-Hartman
7
 * Copyright (c) 2003-2004 IBM Corp.
8
 *
9
 * This file is released under the GPLv2
10
 *
11
 */
12
 
13
#include <linux/device.h>
14
#include <linux/module.h>
15
#include <linux/init.h>
16
#include <linux/string.h>
17
#include <linux/kdev_t.h>
18
#include <linux/err.h>
19
#include <linux/slab.h>
20
#include "base.h"
21
 
22
#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
23
#define to_class(obj) container_of(obj, struct class, subsys.kobj)
24
 
25
static ssize_t
26
class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
27
{
28
        struct class_attribute * class_attr = to_class_attr(attr);
29
        struct class * dc = to_class(kobj);
30
        ssize_t ret = -EIO;
31
 
32
        if (class_attr->show)
33
                ret = class_attr->show(dc, buf);
34
        return ret;
35
}
36
 
37
static ssize_t
38
class_attr_store(struct kobject * kobj, struct attribute * attr,
39
                 const char * buf, size_t count)
40
{
41
        struct class_attribute * class_attr = to_class_attr(attr);
42
        struct class * dc = to_class(kobj);
43
        ssize_t ret = -EIO;
44
 
45
        if (class_attr->store)
46
                ret = class_attr->store(dc, buf, count);
47
        return ret;
48
}
49
 
50
static void class_release(struct kobject * kobj)
51
{
52
        struct class *class = to_class(kobj);
53
 
54
        pr_debug("class '%s': release.\n", class->name);
55
 
56
        if (class->class_release)
57
                class->class_release(class);
58
        else
59
                pr_debug("class '%s' does not have a release() function, "
60
                         "be careful\n", class->name);
61
}
62
 
63
static struct sysfs_ops class_sysfs_ops = {
64
        .show   = class_attr_show,
65
        .store  = class_attr_store,
66
};
67
 
68
static struct kobj_type class_ktype = {
69
        .sysfs_ops      = &class_sysfs_ops,
70
        .release        = class_release,
71
};
72
 
73
/* Hotplug events for classes go to the class_obj subsys */
74
static decl_subsys(class, &class_ktype, NULL);
75
 
76
 
77
int class_create_file(struct class * cls, const struct class_attribute * attr)
78
{
79
        int error;
80
        if (cls) {
81
                error = sysfs_create_file(&cls->subsys.kobj, &attr->attr);
82
        } else
83
                error = -EINVAL;
84
        return error;
85
}
86
 
87
void class_remove_file(struct class * cls, const struct class_attribute * attr)
88
{
89
        if (cls)
90
                sysfs_remove_file(&cls->subsys.kobj, &attr->attr);
91
}
92
 
93
static struct class *class_get(struct class *cls)
94
{
95
        if (cls)
96
                return container_of(kset_get(&cls->subsys), struct class, subsys);
97
        return NULL;
98
}
99
 
100
static void class_put(struct class * cls)
101
{
102
        if (cls)
103
                kset_put(&cls->subsys);
104
}
105
 
106
 
107
static int add_class_attrs(struct class * cls)
108
{
109
        int i;
110
        int error = 0;
111
 
112
        if (cls->class_attrs) {
113
                for (i = 0; attr_name(cls->class_attrs[i]); i++) {
114
                        error = class_create_file(cls,&cls->class_attrs[i]);
115
                        if (error)
116
                                goto Err;
117
                }
118
        }
119
 Done:
120
        return error;
121
 Err:
122
        while (--i >= 0)
123
                class_remove_file(cls,&cls->class_attrs[i]);
124
        goto Done;
125
}
126
 
127
static void remove_class_attrs(struct class * cls)
128
{
129
        int i;
130
 
131
        if (cls->class_attrs) {
132
                for (i = 0; attr_name(cls->class_attrs[i]); i++)
133
                        class_remove_file(cls,&cls->class_attrs[i]);
134
        }
135
}
136
 
137
int class_register(struct class * cls)
138
{
139
        int error;
140
 
141
        pr_debug("device class '%s': registering\n", cls->name);
142
 
143
        INIT_LIST_HEAD(&cls->children);
144
        INIT_LIST_HEAD(&cls->devices);
145
        INIT_LIST_HEAD(&cls->interfaces);
146
        kset_init(&cls->class_dirs);
147
        init_MUTEX(&cls->sem);
148
        error = kobject_set_name(&cls->subsys.kobj, "%s", cls->name);
149
        if (error)
150
                return error;
151
 
152
        cls->subsys.kobj.kset = &class_subsys;
153
 
154
        error = subsystem_register(&cls->subsys);
155
        if (!error) {
156
                error = add_class_attrs(class_get(cls));
157
                class_put(cls);
158
        }
159
        return error;
160
}
161
 
162
void class_unregister(struct class * cls)
163
{
164
        pr_debug("device class '%s': unregistering\n", cls->name);
165
        remove_class_attrs(cls);
166
        subsystem_unregister(&cls->subsys);
167
}
168
 
169
static void class_create_release(struct class *cls)
170
{
171
        pr_debug("%s called for %s\n", __FUNCTION__, cls->name);
172
        kfree(cls);
173
}
174
 
175
static void class_device_create_release(struct class_device *class_dev)
176
{
177
        pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
178
        kfree(class_dev);
179
}
180
 
181
/* needed to allow these devices to have parent class devices */
182
static int class_device_create_uevent(struct class_device *class_dev,
183
                                      struct kobj_uevent_env *env)
184
{
185
        pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
186
        return 0;
187
}
188
 
189
/**
190
 * class_create - create a struct class structure
191
 * @owner: pointer to the module that is to "own" this struct class
192
 * @name: pointer to a string for the name of this class.
193
 *
194
 * This is used to create a struct class pointer that can then be used
195
 * in calls to class_device_create().
196
 *
197
 * Note, the pointer created here is to be destroyed when finished by
198
 * making a call to class_destroy().
199
 */
200
struct class *class_create(struct module *owner, const char *name)
201
{
202
        struct class *cls;
203
        int retval;
204
 
205
        cls = kzalloc(sizeof(*cls), GFP_KERNEL);
206
        if (!cls) {
207
                retval = -ENOMEM;
208
                goto error;
209
        }
210
 
211
        cls->name = name;
212
        cls->owner = owner;
213
        cls->class_release = class_create_release;
214
        cls->release = class_device_create_release;
215
 
216
        retval = class_register(cls);
217
        if (retval)
218
                goto error;
219
 
220
        return cls;
221
 
222
error:
223
        kfree(cls);
224
        return ERR_PTR(retval);
225
}
226
 
227
/**
228
 * class_destroy - destroys a struct class structure
229
 * @cls: pointer to the struct class that is to be destroyed
230
 *
231
 * Note, the pointer to be destroyed must have been created with a call
232
 * to class_create().
233
 */
234
void class_destroy(struct class *cls)
235
{
236
        if ((cls == NULL) || (IS_ERR(cls)))
237
                return;
238
 
239
        class_unregister(cls);
240
}
241
 
242
/* Class Device Stuff */
243
 
244
int class_device_create_file(struct class_device * class_dev,
245
                             const struct class_device_attribute * attr)
246
{
247
        int error = -EINVAL;
248
        if (class_dev)
249
                error = sysfs_create_file(&class_dev->kobj, &attr->attr);
250
        return error;
251
}
252
 
253
void class_device_remove_file(struct class_device * class_dev,
254
                              const struct class_device_attribute * attr)
255
{
256
        if (class_dev)
257
                sysfs_remove_file(&class_dev->kobj, &attr->attr);
258
}
259
 
260
int class_device_create_bin_file(struct class_device *class_dev,
261
                                 struct bin_attribute *attr)
262
{
263
        int error = -EINVAL;
264
        if (class_dev)
265
                error = sysfs_create_bin_file(&class_dev->kobj, attr);
266
        return error;
267
}
268
 
269
void class_device_remove_bin_file(struct class_device *class_dev,
270
                                  struct bin_attribute *attr)
271
{
272
        if (class_dev)
273
                sysfs_remove_bin_file(&class_dev->kobj, attr);
274
}
275
 
276
static ssize_t
277
class_device_attr_show(struct kobject * kobj, struct attribute * attr,
278
                       char * buf)
279
{
280
        struct class_device_attribute * class_dev_attr = to_class_dev_attr(attr);
281
        struct class_device * cd = to_class_dev(kobj);
282
        ssize_t ret = 0;
283
 
284
        if (class_dev_attr->show)
285
                ret = class_dev_attr->show(cd, buf);
286
        return ret;
287
}
288
 
289
static ssize_t
290
class_device_attr_store(struct kobject * kobj, struct attribute * attr,
291
                        const char * buf, size_t count)
292
{
293
        struct class_device_attribute * class_dev_attr = to_class_dev_attr(attr);
294
        struct class_device * cd = to_class_dev(kobj);
295
        ssize_t ret = 0;
296
 
297
        if (class_dev_attr->store)
298
                ret = class_dev_attr->store(cd, buf, count);
299
        return ret;
300
}
301
 
302
static struct sysfs_ops class_dev_sysfs_ops = {
303
        .show   = class_device_attr_show,
304
        .store  = class_device_attr_store,
305
};
306
 
307
static void class_dev_release(struct kobject * kobj)
308
{
309
        struct class_device *cd = to_class_dev(kobj);
310
        struct class * cls = cd->class;
311
 
312
        pr_debug("device class '%s': release.\n", cd->class_id);
313
 
314
        if (cd->release)
315
                cd->release(cd);
316
        else if (cls->release)
317
                cls->release(cd);
318
        else {
319
                printk(KERN_ERR "Class Device '%s' does not have a release() function, "
320
                        "it is broken and must be fixed.\n",
321
                        cd->class_id);
322
                WARN_ON(1);
323
        }
324
}
325
 
326
static struct kobj_type class_device_ktype = {
327
        .sysfs_ops      = &class_dev_sysfs_ops,
328
        .release        = class_dev_release,
329
};
330
 
331
static int class_uevent_filter(struct kset *kset, struct kobject *kobj)
332
{
333
        struct kobj_type *ktype = get_ktype(kobj);
334
 
335
        if (ktype == &class_device_ktype) {
336
                struct class_device *class_dev = to_class_dev(kobj);
337
                if (class_dev->class)
338
                        return 1;
339
        }
340
        return 0;
341
}
342
 
343
static const char *class_uevent_name(struct kset *kset, struct kobject *kobj)
344
{
345
        struct class_device *class_dev = to_class_dev(kobj);
346
 
347
        return class_dev->class->name;
348
}
349
 
350
#ifdef CONFIG_SYSFS_DEPRECATED
351
char *make_class_name(const char *name, struct kobject *kobj)
352
{
353
        char *class_name;
354
        int size;
355
 
356
        size = strlen(name) + strlen(kobject_name(kobj)) + 2;
357
 
358
        class_name = kmalloc(size, GFP_KERNEL);
359
        if (!class_name)
360
                return NULL;
361
 
362
        strcpy(class_name, name);
363
        strcat(class_name, ":");
364
        strcat(class_name, kobject_name(kobj));
365
        return class_name;
366
}
367
 
368
static int make_deprecated_class_device_links(struct class_device *class_dev)
369
{
370
        char *class_name;
371
        int error;
372
 
373
        if (!class_dev->dev)
374
                return 0;
375
 
376
        class_name = make_class_name(class_dev->class->name, &class_dev->kobj);
377
        if (class_name)
378
                error = sysfs_create_link(&class_dev->dev->kobj,
379
                                          &class_dev->kobj, class_name);
380
        else
381
                error = -ENOMEM;
382
        kfree(class_name);
383
        return error;
384
}
385
 
386
static void remove_deprecated_class_device_links(struct class_device *class_dev)
387
{
388
        char *class_name;
389
 
390
        if (!class_dev->dev)
391
                return;
392
 
393
        class_name = make_class_name(class_dev->class->name, &class_dev->kobj);
394
        if (class_name)
395
                sysfs_remove_link(&class_dev->dev->kobj, class_name);
396
        kfree(class_name);
397
}
398
#else
399
static inline int make_deprecated_class_device_links(struct class_device *cd)
400
{ return 0; }
401
static void remove_deprecated_class_device_links(struct class_device *cd)
402
{ }
403
#endif
404
 
405
static int class_uevent(struct kset *kset, struct kobject *kobj,
406
                        struct kobj_uevent_env *env)
407
{
408
        struct class_device *class_dev = to_class_dev(kobj);
409
        struct device *dev = class_dev->dev;
410
        int retval = 0;
411
 
412
        pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);
413
 
414
        if (MAJOR(class_dev->devt)) {
415
                add_uevent_var(env, "MAJOR=%u", MAJOR(class_dev->devt));
416
 
417
                add_uevent_var(env, "MINOR=%u", MINOR(class_dev->devt));
418
        }
419
 
420
        if (dev) {
421
                const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
422
                if (path) {
423
                        add_uevent_var(env, "PHYSDEVPATH=%s", path);
424
                        kfree(path);
425
                }
426
 
427
                if (dev->bus)
428
                        add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);
429
 
430
                if (dev->driver)
431
                        add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name);
432
        }
433
 
434
        if (class_dev->uevent) {
435
                /* have the class device specific function add its stuff */
436
                retval = class_dev->uevent(class_dev, env);
437
                if (retval)
438
                        pr_debug("class_dev->uevent() returned %d\n", retval);
439
        } else if (class_dev->class->uevent) {
440
                /* have the class specific function add its stuff */
441
                retval = class_dev->class->uevent(class_dev, env);
442
                if (retval)
443
                        pr_debug("class->uevent() returned %d\n", retval);
444
        }
445
 
446
        return retval;
447
}
448
 
449
static struct kset_uevent_ops class_uevent_ops = {
450
        .filter =       class_uevent_filter,
451
        .name =         class_uevent_name,
452
        .uevent =       class_uevent,
453
};
454
 
455
static decl_subsys(class_obj, &class_device_ktype, &class_uevent_ops);
456
 
457
 
458
static int class_device_add_attrs(struct class_device * cd)
459
{
460
        int i;
461
        int error = 0;
462
        struct class * cls = cd->class;
463
 
464
        if (cls->class_dev_attrs) {
465
                for (i = 0; attr_name(cls->class_dev_attrs[i]); i++) {
466
                        error = class_device_create_file(cd,
467
                                                         &cls->class_dev_attrs[i]);
468
                        if (error)
469
                                goto Err;
470
                }
471
        }
472
 Done:
473
        return error;
474
 Err:
475
        while (--i >= 0)
476
                class_device_remove_file(cd,&cls->class_dev_attrs[i]);
477
        goto Done;
478
}
479
 
480
static void class_device_remove_attrs(struct class_device * cd)
481
{
482
        int i;
483
        struct class * cls = cd->class;
484
 
485
        if (cls->class_dev_attrs) {
486
                for (i = 0; attr_name(cls->class_dev_attrs[i]); i++)
487
                        class_device_remove_file(cd,&cls->class_dev_attrs[i]);
488
        }
489
}
490
 
491
static int class_device_add_groups(struct class_device * cd)
492
{
493
        int i;
494
        int error = 0;
495
 
496
        if (cd->groups) {
497
                for (i = 0; cd->groups[i]; i++) {
498
                        error = sysfs_create_group(&cd->kobj, cd->groups[i]);
499
                        if (error) {
500
                                while (--i >= 0)
501
                                        sysfs_remove_group(&cd->kobj, cd->groups[i]);
502
                                goto out;
503
                        }
504
                }
505
        }
506
out:
507
        return error;
508
}
509
 
510
static void class_device_remove_groups(struct class_device * cd)
511
{
512
        int i;
513
        if (cd->groups) {
514
                for (i = 0; cd->groups[i]; i++) {
515
                        sysfs_remove_group(&cd->kobj, cd->groups[i]);
516
                }
517
        }
518
}
519
 
520
static ssize_t show_dev(struct class_device *class_dev, char *buf)
521
{
522
        return print_dev_t(buf, class_dev->devt);
523
}
524
 
525
static struct class_device_attribute class_devt_attr =
526
        __ATTR(dev, S_IRUGO, show_dev, NULL);
527
 
528
static ssize_t store_uevent(struct class_device *class_dev,
529
                            const char *buf, size_t count)
530
{
531
        kobject_uevent(&class_dev->kobj, KOBJ_ADD);
532
        return count;
533
}
534
 
535
static struct class_device_attribute class_uevent_attr =
536
        __ATTR(uevent, S_IWUSR, NULL, store_uevent);
537
 
538
void class_device_initialize(struct class_device *class_dev)
539
{
540
        kobj_set_kset_s(class_dev, class_obj_subsys);
541
        kobject_init(&class_dev->kobj);
542
        INIT_LIST_HEAD(&class_dev->node);
543
}
544
 
545
int class_device_add(struct class_device *class_dev)
546
{
547
        struct class *parent_class = NULL;
548
        struct class_device *parent_class_dev = NULL;
549
        struct class_interface *class_intf;
550
        int error = -EINVAL;
551
 
552
        class_dev = class_device_get(class_dev);
553
        if (!class_dev)
554
                return -EINVAL;
555
 
556
        if (!strlen(class_dev->class_id))
557
                goto out1;
558
 
559
        parent_class = class_get(class_dev->class);
560
        if (!parent_class)
561
                goto out1;
562
 
563
        parent_class_dev = class_device_get(class_dev->parent);
564
 
565
        pr_debug("CLASS: registering class device: ID = '%s'\n",
566
                 class_dev->class_id);
567
 
568
        /* first, register with generic layer. */
569
        error = kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
570
        if (error)
571
                goto out2;
572
 
573
        if (parent_class_dev)
574
                class_dev->kobj.parent = &parent_class_dev->kobj;
575
        else
576
                class_dev->kobj.parent = &parent_class->subsys.kobj;
577
 
578
        error = kobject_add(&class_dev->kobj);
579
        if (error)
580
                goto out2;
581
 
582
        /* add the needed attributes to this device */
583
        error = sysfs_create_link(&class_dev->kobj,
584
                                  &parent_class->subsys.kobj, "subsystem");
585
        if (error)
586
                goto out3;
587
 
588
        error = class_device_create_file(class_dev, &class_uevent_attr);
589
        if (error)
590
                goto out3;
591
 
592
        if (MAJOR(class_dev->devt)) {
593
                error = class_device_create_file(class_dev, &class_devt_attr);
594
                if (error)
595
                        goto out4;
596
        }
597
 
598
        error = class_device_add_attrs(class_dev);
599
        if (error)
600
                goto out5;
601
 
602
        if (class_dev->dev) {
603
                error = sysfs_create_link(&class_dev->kobj,
604
                                          &class_dev->dev->kobj, "device");
605
                if (error)
606
                        goto out6;
607
        }
608
 
609
        error = class_device_add_groups(class_dev);
610
        if (error)
611
                goto out7;
612
 
613
        error = make_deprecated_class_device_links(class_dev);
614
        if (error)
615
                goto out8;
616
 
617
        kobject_uevent(&class_dev->kobj, KOBJ_ADD);
618
 
619
        /* notify any interfaces this device is now here */
620
        down(&parent_class->sem);
621
        list_add_tail(&class_dev->node, &parent_class->children);
622
        list_for_each_entry(class_intf, &parent_class->interfaces, node) {
623
                if (class_intf->add)
624
                        class_intf->add(class_dev, class_intf);
625
        }
626
        up(&parent_class->sem);
627
 
628
        goto out1;
629
 
630
 out8:
631
        class_device_remove_groups(class_dev);
632
 out7:
633
        if (class_dev->dev)
634
                sysfs_remove_link(&class_dev->kobj, "device");
635
 out6:
636
        class_device_remove_attrs(class_dev);
637
 out5:
638
        if (MAJOR(class_dev->devt))
639
                class_device_remove_file(class_dev, &class_devt_attr);
640
 out4:
641
        class_device_remove_file(class_dev, &class_uevent_attr);
642
 out3:
643
        kobject_del(&class_dev->kobj);
644
 out2:
645
        if(parent_class_dev)
646
                class_device_put(parent_class_dev);
647
        class_put(parent_class);
648
 out1:
649
        class_device_put(class_dev);
650
        return error;
651
}
652
 
653
int class_device_register(struct class_device *class_dev)
654
{
655
        class_device_initialize(class_dev);
656
        return class_device_add(class_dev);
657
}
658
 
659
/**
660
 * class_device_create - creates a class device and registers it with sysfs
661
 * @cls: pointer to the struct class that this device should be registered to.
662
 * @parent: pointer to the parent struct class_device of this new device, if any.
663
 * @devt: the dev_t for the char device to be added.
664
 * @device: a pointer to a struct device that is assiociated with this class device.
665
 * @fmt: string for the class device's name
666
 *
667
 * This function can be used by char device classes.  A struct
668
 * class_device will be created in sysfs, registered to the specified
669
 * class.
670
 * A "dev" file will be created, showing the dev_t for the device, if
671
 * the dev_t is not 0,0.
672
 * If a pointer to a parent struct class_device is passed in, the newly
673
 * created struct class_device will be a child of that device in sysfs.
674
 * The pointer to the struct class_device will be returned from the
675
 * call.  Any further sysfs files that might be required can be created
676
 * using this pointer.
677
 *
678
 * Note: the struct class passed to this function must have previously
679
 * been created with a call to class_create().
680
 */
681
struct class_device *class_device_create(struct class *cls,
682
                                         struct class_device *parent,
683
                                         dev_t devt,
684
                                         struct device *device,
685
                                         const char *fmt, ...)
686
{
687
        va_list args;
688
        struct class_device *class_dev = NULL;
689
        int retval = -ENODEV;
690
 
691
        if (cls == NULL || IS_ERR(cls))
692
                goto error;
693
 
694
        class_dev = kzalloc(sizeof(*class_dev), GFP_KERNEL);
695
        if (!class_dev) {
696
                retval = -ENOMEM;
697
                goto error;
698
        }
699
 
700
        class_dev->devt = devt;
701
        class_dev->dev = device;
702
        class_dev->class = cls;
703
        class_dev->parent = parent;
704
        class_dev->release = class_device_create_release;
705
        class_dev->uevent = class_device_create_uevent;
706
 
707
        va_start(args, fmt);
708
        vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
709
        va_end(args);
710
        retval = class_device_register(class_dev);
711
        if (retval)
712
                goto error;
713
 
714
        return class_dev;
715
 
716
error:
717
        kfree(class_dev);
718
        return ERR_PTR(retval);
719
}
720
 
721
void class_device_del(struct class_device *class_dev)
722
{
723
        struct class *parent_class = class_dev->class;
724
        struct class_device *parent_device = class_dev->parent;
725
        struct class_interface *class_intf;
726
 
727
        if (parent_class) {
728
                down(&parent_class->sem);
729
                list_del_init(&class_dev->node);
730
                list_for_each_entry(class_intf, &parent_class->interfaces, node)
731
                        if (class_intf->remove)
732
                                class_intf->remove(class_dev, class_intf);
733
                up(&parent_class->sem);
734
        }
735
 
736
        if (class_dev->dev) {
737
                remove_deprecated_class_device_links(class_dev);
738
                sysfs_remove_link(&class_dev->kobj, "device");
739
        }
740
        sysfs_remove_link(&class_dev->kobj, "subsystem");
741
        class_device_remove_file(class_dev, &class_uevent_attr);
742
        if (MAJOR(class_dev->devt))
743
                class_device_remove_file(class_dev, &class_devt_attr);
744
        class_device_remove_attrs(class_dev);
745
        class_device_remove_groups(class_dev);
746
 
747
        kobject_uevent(&class_dev->kobj, KOBJ_REMOVE);
748
        kobject_del(&class_dev->kobj);
749
 
750
        class_device_put(parent_device);
751
        class_put(parent_class);
752
}
753
 
754
void class_device_unregister(struct class_device *class_dev)
755
{
756
        pr_debug("CLASS: Unregistering class device. ID = '%s'\n",
757
                 class_dev->class_id);
758
        class_device_del(class_dev);
759
        class_device_put(class_dev);
760
}
761
 
762
/**
763
 * class_device_destroy - removes a class device that was created with class_device_create()
764
 * @cls: the pointer to the struct class that this device was registered * with.
765
 * @devt: the dev_t of the device that was previously registered.
766
 *
767
 * This call unregisters and cleans up a class device that was created with a
768
 * call to class_device_create()
769
 */
770
void class_device_destroy(struct class *cls, dev_t devt)
771
{
772
        struct class_device *class_dev = NULL;
773
        struct class_device *class_dev_tmp;
774
 
775
        down(&cls->sem);
776
        list_for_each_entry(class_dev_tmp, &cls->children, node) {
777
                if (class_dev_tmp->devt == devt) {
778
                        class_dev = class_dev_tmp;
779
                        break;
780
                }
781
        }
782
        up(&cls->sem);
783
 
784
        if (class_dev)
785
                class_device_unregister(class_dev);
786
}
787
 
788
struct class_device * class_device_get(struct class_device *class_dev)
789
{
790
        if (class_dev)
791
                return to_class_dev(kobject_get(&class_dev->kobj));
792
        return NULL;
793
}
794
 
795
void class_device_put(struct class_device *class_dev)
796
{
797
        if (class_dev)
798
                kobject_put(&class_dev->kobj);
799
}
800
 
801
 
802
int class_interface_register(struct class_interface *class_intf)
803
{
804
        struct class *parent;
805
        struct class_device *class_dev;
806
        struct device *dev;
807
 
808
        if (!class_intf || !class_intf->class)
809
                return -ENODEV;
810
 
811
        parent = class_get(class_intf->class);
812
        if (!parent)
813
                return -EINVAL;
814
 
815
        down(&parent->sem);
816
        list_add_tail(&class_intf->node, &parent->interfaces);
817
        if (class_intf->add) {
818
                list_for_each_entry(class_dev, &parent->children, node)
819
                        class_intf->add(class_dev, class_intf);
820
        }
821
        if (class_intf->add_dev) {
822
                list_for_each_entry(dev, &parent->devices, node)
823
                        class_intf->add_dev(dev, class_intf);
824
        }
825
        up(&parent->sem);
826
 
827
        return 0;
828
}
829
 
830
void class_interface_unregister(struct class_interface *class_intf)
831
{
832
        struct class * parent = class_intf->class;
833
        struct class_device *class_dev;
834
        struct device *dev;
835
 
836
        if (!parent)
837
                return;
838
 
839
        down(&parent->sem);
840
        list_del_init(&class_intf->node);
841
        if (class_intf->remove) {
842
                list_for_each_entry(class_dev, &parent->children, node)
843
                        class_intf->remove(class_dev, class_intf);
844
        }
845
        if (class_intf->remove_dev) {
846
                list_for_each_entry(dev, &parent->devices, node)
847
                        class_intf->remove_dev(dev, class_intf);
848
        }
849
        up(&parent->sem);
850
 
851
        class_put(parent);
852
}
853
 
854
int __init classes_init(void)
855
{
856
        int retval;
857
 
858
        retval = subsystem_register(&class_subsys);
859
        if (retval)
860
                return retval;
861
 
862
        /* ick, this is ugly, the things we go through to keep from showing up
863
         * in sysfs... */
864
        kset_init(&class_obj_subsys);
865
        if (!class_obj_subsys.kobj.parent)
866
                class_obj_subsys.kobj.parent = &class_obj_subsys.kobj;
867
        return 0;
868
}
869
 
870
EXPORT_SYMBOL_GPL(class_create_file);
871
EXPORT_SYMBOL_GPL(class_remove_file);
872
EXPORT_SYMBOL_GPL(class_register);
873
EXPORT_SYMBOL_GPL(class_unregister);
874
EXPORT_SYMBOL_GPL(class_create);
875
EXPORT_SYMBOL_GPL(class_destroy);
876
 
877
EXPORT_SYMBOL_GPL(class_device_register);
878
EXPORT_SYMBOL_GPL(class_device_unregister);
879
EXPORT_SYMBOL_GPL(class_device_initialize);
880
EXPORT_SYMBOL_GPL(class_device_add);
881
EXPORT_SYMBOL_GPL(class_device_del);
882
EXPORT_SYMBOL_GPL(class_device_get);
883
EXPORT_SYMBOL_GPL(class_device_put);
884
EXPORT_SYMBOL_GPL(class_device_create);
885
EXPORT_SYMBOL_GPL(class_device_destroy);
886
EXPORT_SYMBOL_GPL(class_device_create_file);
887
EXPORT_SYMBOL_GPL(class_device_remove_file);
888
EXPORT_SYMBOL_GPL(class_device_create_bin_file);
889
EXPORT_SYMBOL_GPL(class_device_remove_bin_file);
890
 
891
EXPORT_SYMBOL_GPL(class_interface_register);
892
EXPORT_SYMBOL_GPL(class_interface_unregister);

powered by: WebSVN 2.1.0

© copyright 1999-2025 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.