class.c 21.6 KB
Newer Older
L
Linus Torvalds 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * 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
 *
 */

#include <linux/device.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/string.h>
#include <linux/kdev_t.h>
18
#include <linux/err.h>
T
Tim Schmielau 已提交
19
#include <linux/slab.h>
L
Linus Torvalds 已提交
20 21 22
#include "base.h"

#define to_class_attr(_attr) container_of(_attr, struct class_attribute, attr)
23
#define to_class(obj) container_of(obj, struct class, subsys.kobj)
L
Linus Torvalds 已提交
24 25 26 27 28 29

static ssize_t
class_attr_show(struct kobject * kobj, struct attribute * attr, char * buf)
{
	struct class_attribute * class_attr = to_class_attr(attr);
	struct class * dc = to_class(kobj);
30
	ssize_t ret = -EIO;
L
Linus Torvalds 已提交
31 32 33 34 35 36 37 38 39 40 41 42

	if (class_attr->show)
		ret = class_attr->show(dc, buf);
	return ret;
}

static ssize_t
class_attr_store(struct kobject * kobj, struct attribute * attr,
		 const char * buf, size_t count)
{
	struct class_attribute * class_attr = to_class_attr(attr);
	struct class * dc = to_class(kobj);
43
	ssize_t ret = -EIO;
L
Linus Torvalds 已提交
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67

	if (class_attr->store)
		ret = class_attr->store(dc, buf, count);
	return ret;
}

static void class_release(struct kobject * kobj)
{
	struct class *class = to_class(kobj);

	pr_debug("class '%s': release.\n", class->name);

	if (class->class_release)
		class->class_release(class);
	else
		pr_debug("class '%s' does not have a release() function, "
			 "be careful\n", class->name);
}

static struct sysfs_ops class_sysfs_ops = {
	.show	= class_attr_show,
	.store	= class_attr_store,
};

68
static struct kobj_type class_ktype = {
L
Linus Torvalds 已提交
69 70 71 72 73
	.sysfs_ops	= &class_sysfs_ops,
	.release	= class_release,
};

/* Hotplug events for classes go to the class_obj subsys */
74
static struct kset *class_kset;
L
Linus Torvalds 已提交
75 76 77 78 79 80


int class_create_file(struct class * cls, const struct class_attribute * attr)
{
	int error;
	if (cls) {
81
		error = sysfs_create_file(&cls->subsys.kobj, &attr->attr);
L
Linus Torvalds 已提交
82 83 84 85 86 87 88 89
	} else
		error = -EINVAL;
	return error;
}

void class_remove_file(struct class * cls, const struct class_attribute * attr)
{
	if (cls)
90
		sysfs_remove_file(&cls->subsys.kobj, &attr->attr);
L
Linus Torvalds 已提交
91 92
}

93
static struct class *class_get(struct class *cls)
L
Linus Torvalds 已提交
94 95
{
	if (cls)
96
		return container_of(kset_get(&cls->subsys), struct class, subsys);
L
Linus Torvalds 已提交
97 98 99
	return NULL;
}

100
static void class_put(struct class * cls)
L
Linus Torvalds 已提交
101
{
102
	if (cls)
103
		kset_put(&cls->subsys);
L
Linus Torvalds 已提交
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
}


static int add_class_attrs(struct class * cls)
{
	int i;
	int error = 0;

	if (cls->class_attrs) {
		for (i = 0; attr_name(cls->class_attrs[i]); i++) {
			error = class_create_file(cls,&cls->class_attrs[i]);
			if (error)
				goto Err;
		}
	}
 Done:
	return error;
 Err:
	while (--i >= 0)
		class_remove_file(cls,&cls->class_attrs[i]);
	goto Done;
}

static void remove_class_attrs(struct class * cls)
{
	int i;

	if (cls->class_attrs) {
		for (i = 0; attr_name(cls->class_attrs[i]); i++)
			class_remove_file(cls,&cls->class_attrs[i]);
	}
}

int class_register(struct class * cls)
{
	int error;

	pr_debug("device class '%s': registering\n", cls->name);

	INIT_LIST_HEAD(&cls->children);
144
	INIT_LIST_HEAD(&cls->devices);
L
Linus Torvalds 已提交
145
	INIT_LIST_HEAD(&cls->interfaces);
146
	kset_init(&cls->class_dirs);
L
Linus Torvalds 已提交
147
	init_MUTEX(&cls->sem);
148
	error = kobject_set_name(&cls->subsys.kobj, "%s", cls->name);
L
Linus Torvalds 已提交
149 150 151
	if (error)
		return error;

152
	cls->subsys.kobj.kset = class_kset;
153
	cls->subsys.kobj.ktype = &class_ktype;
L
Linus Torvalds 已提交
154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169

	error = subsystem_register(&cls->subsys);
	if (!error) {
		error = add_class_attrs(class_get(cls));
		class_put(cls);
	}
	return error;
}

void class_unregister(struct class * cls)
{
	pr_debug("device class '%s': unregistering\n", cls->name);
	remove_class_attrs(cls);
	subsystem_unregister(&cls->subsys);
}

170 171
static void class_create_release(struct class *cls)
{
172
	pr_debug("%s called for %s\n", __FUNCTION__, cls->name);
173 174 175 176 177
	kfree(cls);
}

static void class_device_create_release(struct class_device *class_dev)
{
178
	pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
179 180 181
	kfree(class_dev);
}

182
/* needed to allow these devices to have parent class devices */
183
static int class_device_create_uevent(struct class_device *class_dev,
184
				      struct kobj_uevent_env *env)
185 186 187 188 189
{
	pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
	return 0;
}

190 191 192 193 194 195 196 197 198 199 200
/**
 * 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.
 *
 * This is used to create a struct class pointer that can then be used
 * in calls to class_device_create().
 *
 * Note, the pointer created here is to be destroyed when finished by
 * making a call to class_destroy().
 */
201
struct class *class_create(struct module *owner, const char *name)
202 203 204 205
{
	struct class *cls;
	int retval;

206
	cls = kzalloc(sizeof(*cls), GFP_KERNEL);
207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227
	if (!cls) {
		retval = -ENOMEM;
		goto error;
	}

	cls->name = name;
	cls->owner = owner;
	cls->class_release = class_create_release;
	cls->release = class_device_create_release;

	retval = class_register(cls);
	if (retval)
		goto error;

	return cls;

error:
	kfree(cls);
	return ERR_PTR(retval);
}

228 229
/**
 * class_destroy - destroys a struct class structure
230
 * @cls: pointer to the struct class that is to be destroyed
231 232 233 234
 *
 * Note, the pointer to be destroyed must have been created with a call
 * to class_create().
 */
235 236 237 238 239 240 241
void class_destroy(struct class *cls)
{
	if ((cls == NULL) || (IS_ERR(cls)))
		return;

	class_unregister(cls);
}
L
Linus Torvalds 已提交
242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260

/* Class Device Stuff */

int class_device_create_file(struct class_device * class_dev,
			     const struct class_device_attribute * attr)
{
	int error = -EINVAL;
	if (class_dev)
		error = sysfs_create_file(&class_dev->kobj, &attr->attr);
	return error;
}

void class_device_remove_file(struct class_device * class_dev,
			      const struct class_device_attribute * attr)
{
	if (class_dev)
		sysfs_remove_file(&class_dev->kobj, &attr->attr);
}

261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276
int class_device_create_bin_file(struct class_device *class_dev,
				 struct bin_attribute *attr)
{
	int error = -EINVAL;
	if (class_dev)
		error = sysfs_create_bin_file(&class_dev->kobj, attr);
	return error;
}

void class_device_remove_bin_file(struct class_device *class_dev,
				  struct bin_attribute *attr)
{
	if (class_dev)
		sysfs_remove_bin_file(&class_dev->kobj, attr);
}

L
Linus Torvalds 已提交
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
static ssize_t
class_device_attr_show(struct kobject * kobj, struct attribute * attr,
		       char * buf)
{
	struct class_device_attribute * class_dev_attr = to_class_dev_attr(attr);
	struct class_device * cd = to_class_dev(kobj);
	ssize_t ret = 0;

	if (class_dev_attr->show)
		ret = class_dev_attr->show(cd, buf);
	return ret;
}

static ssize_t
class_device_attr_store(struct kobject * kobj, struct attribute * attr,
			const char * buf, size_t count)
{
	struct class_device_attribute * class_dev_attr = to_class_dev_attr(attr);
	struct class_device * cd = to_class_dev(kobj);
	ssize_t ret = 0;

	if (class_dev_attr->store)
		ret = class_dev_attr->store(cd, buf, count);
	return ret;
}

static struct sysfs_ops class_dev_sysfs_ops = {
	.show	= class_device_attr_show,
	.store	= class_device_attr_store,
};

static void class_dev_release(struct kobject * kobj)
{
	struct class_device *cd = to_class_dev(kobj);
	struct class * cls = cd->class;

	pr_debug("device class '%s': release.\n", cd->class_id);

315 316 317
	if (cd->release)
		cd->release(cd);
	else if (cls->release)
L
Linus Torvalds 已提交
318 319
		cls->release(cd);
	else {
320
		printk(KERN_ERR "Class Device '%s' does not have a release() function, "
L
Linus Torvalds 已提交
321 322 323 324 325 326
			"it is broken and must be fixed.\n",
			cd->class_id);
		WARN_ON(1);
	}
}

327
static struct kobj_type class_device_ktype = {
L
Linus Torvalds 已提交
328 329 330 331
	.sysfs_ops	= &class_dev_sysfs_ops,
	.release	= class_dev_release,
};

332
static int class_uevent_filter(struct kset *kset, struct kobject *kobj)
L
Linus Torvalds 已提交
333 334 335
{
	struct kobj_type *ktype = get_ktype(kobj);

336
	if (ktype == &class_device_ktype) {
L
Linus Torvalds 已提交
337 338 339 340 341 342 343
		struct class_device *class_dev = to_class_dev(kobj);
		if (class_dev->class)
			return 1;
	}
	return 0;
}

344
static const char *class_uevent_name(struct kset *kset, struct kobject *kobj)
L
Linus Torvalds 已提交
345 346 347 348 349 350
{
	struct class_device *class_dev = to_class_dev(kobj);

	return class_dev->class->name;
}

351 352 353 354 355 356 357 358 359 360
#ifdef CONFIG_SYSFS_DEPRECATED
char *make_class_name(const char *name, struct kobject *kobj)
{
	char *class_name;
	int size;

	size = strlen(name) + strlen(kobject_name(kobj)) + 2;

	class_name = kmalloc(size, GFP_KERNEL);
	if (!class_name)
361
		return NULL;
362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377

	strcpy(class_name, name);
	strcat(class_name, ":");
	strcat(class_name, kobject_name(kobj));
	return class_name;
}

static int make_deprecated_class_device_links(struct class_device *class_dev)
{
	char *class_name;
	int error;

	if (!class_dev->dev)
		return 0;

	class_name = make_class_name(class_dev->class->name, &class_dev->kobj);
378 379 380 381 382
	if (class_name)
		error = sysfs_create_link(&class_dev->dev->kobj,
					  &class_dev->kobj, class_name);
	else
		error = -ENOMEM;
383 384 385 386 387 388 389 390 391 392 393 394
	kfree(class_name);
	return error;
}

static void remove_deprecated_class_device_links(struct class_device *class_dev)
{
	char *class_name;

	if (!class_dev->dev)
		return;

	class_name = make_class_name(class_dev->class->name, &class_dev->kobj);
395 396
	if (class_name)
		sysfs_remove_link(&class_dev->dev->kobj, class_name);
397 398 399 400 401 402 403 404 405
	kfree(class_name);
}
#else
static inline int make_deprecated_class_device_links(struct class_device *cd)
{ return 0; }
static void remove_deprecated_class_device_links(struct class_device *cd)
{ }
#endif

406 407
static int class_uevent(struct kset *kset, struct kobject *kobj,
			struct kobj_uevent_env *env)
L
Linus Torvalds 已提交
408 409
{
	struct class_device *class_dev = to_class_dev(kobj);
410
	struct device *dev = class_dev->dev;
L
Linus Torvalds 已提交
411 412 413 414 415
	int retval = 0;

	pr_debug("%s - name = %s\n", __FUNCTION__, class_dev->class_id);

	if (MAJOR(class_dev->devt)) {
416
		add_uevent_var(env, "MAJOR=%u", MAJOR(class_dev->devt));
L
Linus Torvalds 已提交
417

418
		add_uevent_var(env, "MINOR=%u", MINOR(class_dev->devt));
L
Linus Torvalds 已提交
419 420
	}

421 422 423
	if (dev) {
		const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
		if (path) {
424
			add_uevent_var(env, "PHYSDEVPATH=%s", path);
425 426 427 428
			kfree(path);
		}

		if (dev->bus)
429
			add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);
430 431

		if (dev->driver)
432
			add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name);
433 434
	}

435
	if (class_dev->uevent) {
436
		/* have the class device specific function add its stuff */
437
		retval = class_dev->uevent(class_dev, env);
438
		if (retval)
439 440
			pr_debug("class_dev->uevent() returned %d\n", retval);
	} else if (class_dev->class->uevent) {
441
		/* have the class specific function add its stuff */
442
		retval = class_dev->class->uevent(class_dev, env);
443
		if (retval)
444
			pr_debug("class->uevent() returned %d\n", retval);
L
Linus Torvalds 已提交
445 446 447 448 449
	}

	return retval;
}

450 451 452 453
static struct kset_uevent_ops class_uevent_ops = {
	.filter =	class_uevent_filter,
	.name =		class_uevent_name,
	.uevent =	class_uevent,
L
Linus Torvalds 已提交
454 455
};

456 457 458 459 460 461 462 463 464
/*
 * DO NOT copy how this is created, kset_create_and_add() should be
 * called, but this is a hold-over from the old-way and will be deleted
 * entirely soon.
 */
static struct kset class_obj_subsys = {
	.kobj = { .k_name = "class_obj", },
	.uevent_ops = &class_uevent_ops,
};
L
Linus Torvalds 已提交
465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498

static int class_device_add_attrs(struct class_device * cd)
{
	int i;
	int error = 0;
	struct class * cls = cd->class;

	if (cls->class_dev_attrs) {
		for (i = 0; attr_name(cls->class_dev_attrs[i]); i++) {
			error = class_device_create_file(cd,
							 &cls->class_dev_attrs[i]);
			if (error)
				goto Err;
		}
	}
 Done:
	return error;
 Err:
	while (--i >= 0)
		class_device_remove_file(cd,&cls->class_dev_attrs[i]);
	goto Done;
}

static void class_device_remove_attrs(struct class_device * cd)
{
	int i;
	struct class * cls = cd->class;

	if (cls->class_dev_attrs) {
		for (i = 0; attr_name(cls->class_dev_attrs[i]); i++)
			class_device_remove_file(cd,&cls->class_dev_attrs[i]);
	}
}

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
static int class_device_add_groups(struct class_device * cd)
{
	int i;
	int error = 0;

	if (cd->groups) {
		for (i = 0; cd->groups[i]; i++) {
			error = sysfs_create_group(&cd->kobj, cd->groups[i]);
			if (error) {
				while (--i >= 0)
					sysfs_remove_group(&cd->kobj, cd->groups[i]);
				goto out;
			}
		}
	}
out:
	return error;
}

static void class_device_remove_groups(struct class_device * cd)
{
	int i;
	if (cd->groups) {
		for (i = 0; cd->groups[i]; i++) {
			sysfs_remove_group(&cd->kobj, cd->groups[i]);
		}
	}
}

L
Linus Torvalds 已提交
528 529 530 531 532
static ssize_t show_dev(struct class_device *class_dev, char *buf)
{
	return print_dev_t(buf, class_dev->devt);
}

533 534 535
static struct class_device_attribute class_devt_attr =
	__ATTR(dev, S_IRUGO, show_dev, NULL);

536 537 538
static ssize_t store_uevent(struct class_device *class_dev,
			    const char *buf, size_t count)
{
539
	kobject_uevent(&class_dev->kobj, KOBJ_ADD);
540 541 542
	return count;
}

543 544 545
static struct class_device_attribute class_uevent_attr =
	__ATTR(uevent, S_IWUSR, NULL, store_uevent);

L
Linus Torvalds 已提交
546 547
void class_device_initialize(struct class_device *class_dev)
{
548 549
	class_dev->kobj.kset = &class_obj_subsys;
	class_dev->kobj.ktype = &class_device_ktype;
L
Linus Torvalds 已提交
550 551 552 553 554 555
	kobject_init(&class_dev->kobj);
	INIT_LIST_HEAD(&class_dev->node);
}

int class_device_add(struct class_device *class_dev)
{
556 557 558 559
	struct class *parent_class = NULL;
	struct class_device *parent_class_dev = NULL;
	struct class_interface *class_intf;
	int error = -EINVAL;
L
Linus Torvalds 已提交
560 561 562 563 564

	class_dev = class_device_get(class_dev);
	if (!class_dev)
		return -EINVAL;

565
	if (!strlen(class_dev->class_id))
566
		goto out1;
L
Linus Torvalds 已提交
567

568 569
	parent_class = class_get(class_dev->class);
	if (!parent_class)
570 571
		goto out1;

572
	parent_class_dev = class_device_get(class_dev->parent);
L
Linus Torvalds 已提交
573 574 575 576 577

	pr_debug("CLASS: registering class device: ID = '%s'\n",
		 class_dev->class_id);

	/* first, register with generic layer. */
578 579 580 581
	error = kobject_set_name(&class_dev->kobj, "%s", class_dev->class_id);
	if (error)
		goto out2;

582 583 584
	if (parent_class_dev)
		class_dev->kobj.parent = &parent_class_dev->kobj;
	else
585
		class_dev->kobj.parent = &parent_class->subsys.kobj;
L
Linus Torvalds 已提交
586

587 588
	error = kobject_add(&class_dev->kobj);
	if (error)
589
		goto out2;
L
Linus Torvalds 已提交
590

591
	/* add the needed attributes to this device */
592
	error = sysfs_create_link(&class_dev->kobj,
593
				  &parent_class->subsys.kobj, "subsystem");
594 595
	if (error)
		goto out3;
596 597

	error = class_device_create_file(class_dev, &class_uevent_attr);
598 599
	if (error)
		goto out3;
600

601
	if (MAJOR(class_dev->devt)) {
602 603
		error = class_device_create_file(class_dev, &class_devt_attr);
		if (error)
604
			goto out4;
605 606
	}

607 608 609 610
	error = class_device_add_attrs(class_dev);
	if (error)
		goto out5;

611
	if (class_dev->dev) {
612 613 614 615
		error = sysfs_create_link(&class_dev->kobj,
					  &class_dev->dev->kobj, "device");
		if (error)
			goto out6;
616
	}
617

618
	error = class_device_add_groups(class_dev);
619 620 621 622
	if (error)
		goto out7;

	error = make_deprecated_class_device_links(class_dev);
623 624
	if (error)
		goto out8;
625

626
	kobject_uevent(&class_dev->kobj, KOBJ_ADD);
627

628
	/* notify any interfaces this device is now here */
629 630 631 632 633
	down(&parent_class->sem);
	list_add_tail(&class_dev->node, &parent_class->children);
	list_for_each_entry(class_intf, &parent_class->interfaces, node) {
		if (class_intf->add)
			class_intf->add(class_dev, class_intf);
L
Linus Torvalds 已提交
634
	}
635
	up(&parent_class->sem);
636

637 638 639
	goto out1;

 out8:
640
	class_device_remove_groups(class_dev);
641 642 643 644 645 646
 out7:
	if (class_dev->dev)
		sysfs_remove_link(&class_dev->kobj, "device");
 out6:
	class_device_remove_attrs(class_dev);
 out5:
647 648
	if (MAJOR(class_dev->devt))
		class_device_remove_file(class_dev, &class_devt_attr);
649
 out4:
650
	class_device_remove_file(class_dev, &class_uevent_attr);
651 652 653 654
 out3:
	kobject_del(&class_dev->kobj);
 out2:
	if(parent_class_dev)
655
		class_device_put(parent_class_dev);
656 657
	class_put(parent_class);
 out1:
L
Linus Torvalds 已提交
658 659 660 661 662 663 664 665 666 667
	class_device_put(class_dev);
	return error;
}

int class_device_register(struct class_device *class_dev)
{
	class_device_initialize(class_dev);
	return class_device_add(class_dev);
}

668 669
/**
 * class_device_create - creates a class device and registers it with sysfs
670
 * @cls: pointer to the struct class that this device should be registered to.
671
 * @parent: pointer to the parent struct class_device of this new device, if any.
672
 * @devt: the dev_t for the char device to be added.
673 674 675 676 677
 * @device: a pointer to a struct device that is assiociated with this class device.
 * @fmt: string for the class device's name
 *
 * This function can be used by char device classes.  A struct
 * class_device will be created in sysfs, registered to the specified
678 679 680 681 682 683 684 685
 * class.
 * A "dev" file will be created, showing the dev_t for the device, if
 * the dev_t is not 0,0.
 * If a pointer to a parent struct class_device is passed in, the newly
 * created struct class_device will be a child of that device in sysfs.
 * The pointer to the struct class_device will be returned from the
 * call.  Any further sysfs files that might be required can be created
 * using this pointer.
686 687 688 689
 *
 * Note: the struct class passed to this function must have previously
 * been created with a call to class_create().
 */
690 691 692
struct class_device *class_device_create(struct class *cls,
					 struct class_device *parent,
					 dev_t devt,
693 694
					 struct device *device,
					 const char *fmt, ...)
695 696 697 698 699 700 701 702
{
	va_list args;
	struct class_device *class_dev = NULL;
	int retval = -ENODEV;

	if (cls == NULL || IS_ERR(cls))
		goto error;

703
	class_dev = kzalloc(sizeof(*class_dev), GFP_KERNEL);
704 705 706 707 708 709 710 711
	if (!class_dev) {
		retval = -ENOMEM;
		goto error;
	}

	class_dev->devt = devt;
	class_dev->dev = device;
	class_dev->class = cls;
712 713
	class_dev->parent = parent;
	class_dev->release = class_device_create_release;
714
	class_dev->uevent = class_device_create_uevent;
715 716 717 718 719 720 721 722 723 724 725 726 727 728 729

	va_start(args, fmt);
	vsnprintf(class_dev->class_id, BUS_ID_SIZE, fmt, args);
	va_end(args);
	retval = class_device_register(class_dev);
	if (retval)
		goto error;

	return class_dev;

error:
	kfree(class_dev);
	return ERR_PTR(retval);
}

L
Linus Torvalds 已提交
730 731
void class_device_del(struct class_device *class_dev)
{
732 733 734
	struct class *parent_class = class_dev->class;
	struct class_device *parent_device = class_dev->parent;
	struct class_interface *class_intf;
L
Linus Torvalds 已提交
735

736 737
	if (parent_class) {
		down(&parent_class->sem);
L
Linus Torvalds 已提交
738
		list_del_init(&class_dev->node);
739
		list_for_each_entry(class_intf, &parent_class->interfaces, node)
L
Linus Torvalds 已提交
740
			if (class_intf->remove)
741
				class_intf->remove(class_dev, class_intf);
742
		up(&parent_class->sem);
L
Linus Torvalds 已提交
743 744
	}

745
	if (class_dev->dev) {
746
		remove_deprecated_class_device_links(class_dev);
L
Linus Torvalds 已提交
747
		sysfs_remove_link(&class_dev->kobj, "device");
748
	}
749
	sysfs_remove_link(&class_dev->kobj, "subsystem");
750 751 752
	class_device_remove_file(class_dev, &class_uevent_attr);
	if (MAJOR(class_dev->devt))
		class_device_remove_file(class_dev, &class_devt_attr);
L
Linus Torvalds 已提交
753
	class_device_remove_attrs(class_dev);
754
	class_device_remove_groups(class_dev);
L
Linus Torvalds 已提交
755

756
	kobject_uevent(&class_dev->kobj, KOBJ_REMOVE);
L
Linus Torvalds 已提交
757 758
	kobject_del(&class_dev->kobj);

759 760
	class_device_put(parent_device);
	class_put(parent_class);
L
Linus Torvalds 已提交
761 762 763 764 765 766 767 768 769 770
}

void class_device_unregister(struct class_device *class_dev)
{
	pr_debug("CLASS: Unregistering class device. ID = '%s'\n",
		 class_dev->class_id);
	class_device_del(class_dev);
	class_device_put(class_dev);
}

771 772 773
/**
 * class_device_destroy - removes a class device that was created with class_device_create()
 * @cls: the pointer to the struct class that this device was registered * with.
774
 * @devt: the dev_t of the device that was previously registered.
775 776 777 778
 *
 * This call unregisters and cleans up a class device that was created with a
 * call to class_device_create()
 */
779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796
void class_device_destroy(struct class *cls, dev_t devt)
{
	struct class_device *class_dev = NULL;
	struct class_device *class_dev_tmp;

	down(&cls->sem);
	list_for_each_entry(class_dev_tmp, &cls->children, node) {
		if (class_dev_tmp->devt == devt) {
			class_dev = class_dev_tmp;
			break;
		}
	}
	up(&cls->sem);

	if (class_dev)
		class_device_unregister(class_dev);
}

L
Linus Torvalds 已提交
797 798 799 800 801 802 803 804 805
struct class_device * class_device_get(struct class_device *class_dev)
{
	if (class_dev)
		return to_class_dev(kobject_get(&class_dev->kobj));
	return NULL;
}

void class_device_put(struct class_device *class_dev)
{
806 807
	if (class_dev)
		kobject_put(&class_dev->kobj);
L
Linus Torvalds 已提交
808 809 810 811 812 813 814
}


int class_interface_register(struct class_interface *class_intf)
{
	struct class *parent;
	struct class_device *class_dev;
815
	struct device *dev;
L
Linus Torvalds 已提交
816 817 818 819 820 821 822 823 824 825 826 827

	if (!class_intf || !class_intf->class)
		return -ENODEV;

	parent = class_get(class_intf->class);
	if (!parent)
		return -EINVAL;

	down(&parent->sem);
	list_add_tail(&class_intf->node, &parent->interfaces);
	if (class_intf->add) {
		list_for_each_entry(class_dev, &parent->children, node)
828
			class_intf->add(class_dev, class_intf);
L
Linus Torvalds 已提交
829
	}
830 831 832 833
	if (class_intf->add_dev) {
		list_for_each_entry(dev, &parent->devices, node)
			class_intf->add_dev(dev, class_intf);
	}
L
Linus Torvalds 已提交
834 835 836 837 838 839 840 841 842
	up(&parent->sem);

	return 0;
}

void class_interface_unregister(struct class_interface *class_intf)
{
	struct class * parent = class_intf->class;
	struct class_device *class_dev;
843
	struct device *dev;
L
Linus Torvalds 已提交
844 845 846 847 848 849 850 851

	if (!parent)
		return;

	down(&parent->sem);
	list_del_init(&class_intf->node);
	if (class_intf->remove) {
		list_for_each_entry(class_dev, &parent->children, node)
852
			class_intf->remove(class_dev, class_intf);
L
Linus Torvalds 已提交
853
	}
854 855 856 857
	if (class_intf->remove_dev) {
		list_for_each_entry(dev, &parent->devices, node)
			class_intf->remove_dev(dev, class_intf);
	}
L
Linus Torvalds 已提交
858 859 860 861 862 863 864
	up(&parent->sem);

	class_put(parent);
}

int __init classes_init(void)
{
865 866 867
	class_kset = kset_create_and_add("class", NULL, NULL);
	if (!class_kset)
		return -ENOMEM;
L
Linus Torvalds 已提交
868 869 870

	/* ick, this is ugly, the things we go through to keep from showing up
	 * in sysfs... */
871
	kset_init(&class_obj_subsys);
872 873
	if (!class_obj_subsys.kobj.parent)
		class_obj_subsys.kobj.parent = &class_obj_subsys.kobj;
L
Linus Torvalds 已提交
874 875 876 877 878 879 880
	return 0;
}

EXPORT_SYMBOL_GPL(class_create_file);
EXPORT_SYMBOL_GPL(class_remove_file);
EXPORT_SYMBOL_GPL(class_register);
EXPORT_SYMBOL_GPL(class_unregister);
881 882
EXPORT_SYMBOL_GPL(class_create);
EXPORT_SYMBOL_GPL(class_destroy);
L
Linus Torvalds 已提交
883 884 885 886 887 888 889 890

EXPORT_SYMBOL_GPL(class_device_register);
EXPORT_SYMBOL_GPL(class_device_unregister);
EXPORT_SYMBOL_GPL(class_device_initialize);
EXPORT_SYMBOL_GPL(class_device_add);
EXPORT_SYMBOL_GPL(class_device_del);
EXPORT_SYMBOL_GPL(class_device_get);
EXPORT_SYMBOL_GPL(class_device_put);
891 892
EXPORT_SYMBOL_GPL(class_device_create);
EXPORT_SYMBOL_GPL(class_device_destroy);
L
Linus Torvalds 已提交
893 894
EXPORT_SYMBOL_GPL(class_device_create_file);
EXPORT_SYMBOL_GPL(class_device_remove_file);
895 896
EXPORT_SYMBOL_GPL(class_device_create_bin_file);
EXPORT_SYMBOL_GPL(class_device_remove_bin_file);
L
Linus Torvalds 已提交
897 898 899

EXPORT_SYMBOL_GPL(class_interface_register);
EXPORT_SYMBOL_GPL(class_interface_unregister);