class.c 21.7 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>
20
#include <linux/genhd.h>
L
Linus Torvalds 已提交
21 22 23
#include "base.h"

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

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);
31
	ssize_t ret = -EIO;
L
Linus Torvalds 已提交
32 33 34 35 36 37 38 39 40 41 42 43

	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);
44
	ssize_t ret = -EIO;
L
Linus Torvalds 已提交
45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68

	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,
};

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

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


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

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

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

101
static void class_put(struct class * cls)
L
Linus Torvalds 已提交
102
{
103
	if (cls)
104
		kset_put(&cls->subsys);
L
Linus Torvalds 已提交
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 144
}


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

153 154 155 156 157
#ifdef CONFIG_SYSFS_DEPRECATED
	/* let the block class directory show up in the root of sysfs */
	if (cls != &block_class)
		cls->subsys.kobj.kset = class_kset;
#else
158
	cls->subsys.kobj.kset = class_kset;
159
#endif
160
	cls->subsys.kobj.ktype = &class_ktype;
L
Linus Torvalds 已提交
161

162
	error = kset_register(&cls->subsys);
L
Linus Torvalds 已提交
163 164 165 166 167 168 169 170 171 172 173
	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);
174
	kset_unregister(&cls->subsys);
L
Linus Torvalds 已提交
175 176
}

177 178
static void class_create_release(struct class *cls)
{
179
	pr_debug("%s called for %s\n", __FUNCTION__, cls->name);
180 181 182 183 184
	kfree(cls);
}

static void class_device_create_release(struct class_device *class_dev)
{
185
	pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
186 187 188
	kfree(class_dev);
}

189
/* needed to allow these devices to have parent class devices */
190
static int class_device_create_uevent(struct class_device *class_dev,
191
				      struct kobj_uevent_env *env)
192 193 194 195 196
{
	pr_debug("%s called for %s\n", __FUNCTION__, class_dev->class_id);
	return 0;
}

197 198 199 200 201 202 203 204 205 206 207
/**
 * 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().
 */
208
struct class *class_create(struct module *owner, const char *name)
209 210 211 212
{
	struct class *cls;
	int retval;

213
	cls = kzalloc(sizeof(*cls), GFP_KERNEL);
214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234
	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);
}

235 236
/**
 * class_destroy - destroys a struct class structure
237
 * @cls: pointer to the struct class that is to be destroyed
238 239 240 241
 *
 * Note, the pointer to be destroyed must have been created with a call
 * to class_create().
 */
242 243 244 245 246 247 248
void class_destroy(struct class *cls)
{
	if ((cls == NULL) || (IS_ERR(cls)))
		return;

	class_unregister(cls);
}
L
Linus Torvalds 已提交
249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267

/* 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);
}

268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283
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 已提交
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 315 316 317 318 319 320 321
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);

322 323 324
	if (cd->release)
		cd->release(cd);
	else if (cls->release)
L
Linus Torvalds 已提交
325 326
		cls->release(cd);
	else {
327
		printk(KERN_ERR "Class Device '%s' does not have a release() function, "
L
Linus Torvalds 已提交
328 329 330 331 332 333
			"it is broken and must be fixed.\n",
			cd->class_id);
		WARN_ON(1);
	}
}

334
static struct kobj_type class_device_ktype = {
L
Linus Torvalds 已提交
335 336 337 338
	.sysfs_ops	= &class_dev_sysfs_ops,
	.release	= class_dev_release,
};

339
static int class_uevent_filter(struct kset *kset, struct kobject *kobj)
L
Linus Torvalds 已提交
340 341 342
{
	struct kobj_type *ktype = get_ktype(kobj);

343
	if (ktype == &class_device_ktype) {
L
Linus Torvalds 已提交
344 345 346 347 348 349 350
		struct class_device *class_dev = to_class_dev(kobj);
		if (class_dev->class)
			return 1;
	}
	return 0;
}

351
static const char *class_uevent_name(struct kset *kset, struct kobject *kobj)
L
Linus Torvalds 已提交
352 353 354 355 356 357
{
	struct class_device *class_dev = to_class_dev(kobj);

	return class_dev->class->name;
}

358 359 360 361 362 363 364 365 366 367
#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)
368
		return NULL;
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384

	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);
385 386 387 388 389
	if (class_name)
		error = sysfs_create_link(&class_dev->dev->kobj,
					  &class_dev->kobj, class_name);
	else
		error = -ENOMEM;
390 391 392 393 394 395 396 397 398 399 400 401
	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);
402 403
	if (class_name)
		sysfs_remove_link(&class_dev->dev->kobj, class_name);
404 405 406 407 408 409 410 411 412
	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

413 414
static int class_uevent(struct kset *kset, struct kobject *kobj,
			struct kobj_uevent_env *env)
L
Linus Torvalds 已提交
415 416
{
	struct class_device *class_dev = to_class_dev(kobj);
417
	struct device *dev = class_dev->dev;
L
Linus Torvalds 已提交
418 419 420 421 422
	int retval = 0;

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

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

425
		add_uevent_var(env, "MINOR=%u", MINOR(class_dev->devt));
L
Linus Torvalds 已提交
426 427
	}

428 429 430
	if (dev) {
		const char *path = kobject_get_path(&dev->kobj, GFP_KERNEL);
		if (path) {
431
			add_uevent_var(env, "PHYSDEVPATH=%s", path);
432 433 434 435
			kfree(path);
		}

		if (dev->bus)
436
			add_uevent_var(env, "PHYSDEVBUS=%s", dev->bus->name);
437 438

		if (dev->driver)
439
			add_uevent_var(env, "PHYSDEVDRIVER=%s", dev->driver->name);
440 441
	}

442
	if (class_dev->uevent) {
443
		/* have the class device specific function add its stuff */
444
		retval = class_dev->uevent(class_dev, env);
445
		if (retval)
446 447
			pr_debug("class_dev->uevent() returned %d\n", retval);
	} else if (class_dev->class->uevent) {
448
		/* have the class specific function add its stuff */
449
		retval = class_dev->class->uevent(class_dev, env);
450
		if (retval)
451
			pr_debug("class->uevent() returned %d\n", retval);
L
Linus Torvalds 已提交
452 453 454 455 456
	}

	return retval;
}

457 458 459 460
static struct kset_uevent_ops class_uevent_ops = {
	.filter =	class_uevent_filter,
	.name =		class_uevent_name,
	.uevent =	class_uevent,
L
Linus Torvalds 已提交
461 462
};

463 464 465 466 467 468 469 470
/*
 * 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 = {
	.uevent_ops = &class_uevent_ops,
};
L
Linus Torvalds 已提交
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 499 500 501 502 503 504

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]);
	}
}

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
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 已提交
534 535 536 537 538
static ssize_t show_dev(struct class_device *class_dev, char *buf)
{
	return print_dev_t(buf, class_dev->devt);
}

539 540 541
static struct class_device_attribute class_devt_attr =
	__ATTR(dev, S_IRUGO, show_dev, NULL);

542 543 544
static ssize_t store_uevent(struct class_device *class_dev,
			    const char *buf, size_t count)
{
545
	kobject_uevent(&class_dev->kobj, KOBJ_ADD);
546 547 548
	return count;
}

549 550 551
static struct class_device_attribute class_uevent_attr =
	__ATTR(uevent, S_IWUSR, NULL, store_uevent);

L
Linus Torvalds 已提交
552 553
void class_device_initialize(struct class_device *class_dev)
{
554
	class_dev->kobj.kset = &class_obj_subsys;
555
	kobject_init(&class_dev->kobj, &class_device_ktype);
L
Linus Torvalds 已提交
556 557 558 559 560
	INIT_LIST_HEAD(&class_dev->node);
}

int class_device_add(struct class_device *class_dev)
{
561 562 563 564
	struct class *parent_class = NULL;
	struct class_device *parent_class_dev = NULL;
	struct class_interface *class_intf;
	int error = -EINVAL;
L
Linus Torvalds 已提交
565 566 567 568 569

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

570
	if (!strlen(class_dev->class_id))
571
		goto out1;
L
Linus Torvalds 已提交
572

573 574
	parent_class = class_get(class_dev->class);
	if (!parent_class)
575 576
		goto out1;

577
	parent_class_dev = class_device_get(class_dev->parent);
L
Linus Torvalds 已提交
578 579 580 581 582

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

	/* first, register with generic layer. */
583 584 585
	if (parent_class_dev)
		class_dev->kobj.parent = &parent_class_dev->kobj;
	else
586
		class_dev->kobj.parent = &parent_class->subsys.kobj;
L
Linus Torvalds 已提交
587

588 589
	error = kobject_add(&class_dev->kobj, class_dev->kobj.parent,
			    "%s", class_dev->class_id);
590
	if (error)
591
		goto out2;
L
Linus Torvalds 已提交
592

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

	error = class_device_create_file(class_dev, &class_uevent_attr);
600 601
	if (error)
		goto out3;
602

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

609 610 611 612
	error = class_device_add_attrs(class_dev);
	if (error)
		goto out5;

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

620
	error = class_device_add_groups(class_dev);
621 622 623 624
	if (error)
		goto out7;

	error = make_deprecated_class_device_links(class_dev);
625 626
	if (error)
		goto out8;
627

628
	kobject_uevent(&class_dev->kobj, KOBJ_ADD);
629

630
	/* notify any interfaces this device is now here */
631 632 633 634 635
	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 已提交
636
	}
637
	up(&parent_class->sem);
638

639 640 641
	goto out1;

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

670 671
/**
 * class_device_create - creates a class device and registers it with sysfs
672
 * @cls: pointer to the struct class that this device should be registered to.
673
 * @parent: pointer to the parent struct class_device of this new device, if any.
674
 * @devt: the dev_t for the char device to be added.
675 676 677 678 679
 * @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
680 681 682 683 684 685 686 687
 * 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.
688 689 690 691
 *
 * Note: the struct class passed to this function must have previously
 * been created with a call to class_create().
 */
692 693 694
struct class_device *class_device_create(struct class *cls,
					 struct class_device *parent,
					 dev_t devt,
695 696
					 struct device *device,
					 const char *fmt, ...)
697 698 699 700 701 702 703 704
{
	va_list args;
	struct class_device *class_dev = NULL;
	int retval = -ENODEV;

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

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

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

	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 已提交
732 733
void class_device_del(struct class_device *class_dev)
{
734 735 736
	struct class *parent_class = class_dev->class;
	struct class_device *parent_device = class_dev->parent;
	struct class_interface *class_intf;
L
Linus Torvalds 已提交
737

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

747
	if (class_dev->dev) {
748
		remove_deprecated_class_device_links(class_dev);
L
Linus Torvalds 已提交
749
		sysfs_remove_link(&class_dev->kobj, "device");
750
	}
751
	sysfs_remove_link(&class_dev->kobj, "subsystem");
752 753 754
	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 已提交
755
	class_device_remove_attrs(class_dev);
756
	class_device_remove_groups(class_dev);
L
Linus Torvalds 已提交
757

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

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

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);
}

773 774 775
/**
 * 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.
776
 * @devt: the dev_t of the device that was previously registered.
777 778 779 780
 *
 * This call unregisters and cleans up a class device that was created with a
 * call to class_device_create()
 */
781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798
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 已提交
799 800 801 802 803 804 805 806 807
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)
{
808 809
	if (class_dev)
		kobject_put(&class_dev->kobj);
L
Linus Torvalds 已提交
810 811 812 813 814 815 816
}


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

	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)
830
			class_intf->add(class_dev, class_intf);
L
Linus Torvalds 已提交
831
	}
832 833 834 835
	if (class_intf->add_dev) {
		list_for_each_entry(dev, &parent->devices, node)
			class_intf->add_dev(dev, class_intf);
	}
L
Linus Torvalds 已提交
836 837 838 839 840 841 842 843 844
	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;
845
	struct device *dev;
L
Linus Torvalds 已提交
846 847 848 849 850 851 852 853

	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)
854
			class_intf->remove(class_dev, class_intf);
L
Linus Torvalds 已提交
855
	}
856 857 858 859
	if (class_intf->remove_dev) {
		list_for_each_entry(dev, &parent->devices, node)
			class_intf->remove_dev(dev, class_intf);
	}
L
Linus Torvalds 已提交
860 861 862 863 864 865 866
	up(&parent->sem);

	class_put(parent);
}

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

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

EXPORT_SYMBOL_GPL(class_create_file);
EXPORT_SYMBOL_GPL(class_remove_file);
EXPORT_SYMBOL_GPL(class_register);
EXPORT_SYMBOL_GPL(class_unregister);
884 885
EXPORT_SYMBOL_GPL(class_create);
EXPORT_SYMBOL_GPL(class_destroy);
L
Linus Torvalds 已提交
886 887 888 889 890 891 892 893

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);
894 895
EXPORT_SYMBOL_GPL(class_device_create);
EXPORT_SYMBOL_GPL(class_device_destroy);
L
Linus Torvalds 已提交
896 897
EXPORT_SYMBOL_GPL(class_device_create_file);
EXPORT_SYMBOL_GPL(class_device_remove_file);
898 899
EXPORT_SYMBOL_GPL(class_device_create_bin_file);
EXPORT_SYMBOL_GPL(class_device_remove_bin_file);
L
Linus Torvalds 已提交
900 901 902

EXPORT_SYMBOL_GPL(class_interface_register);
EXPORT_SYMBOL_GPL(class_interface_unregister);