Commit 387f6b76 authored by Linus Torvalds's avatar Linus Torvalds

Merge bk://kernel.bkbits.net/gregkh/linux/driver-2.6

into ppc970.osdl.org:/home/torvalds/v2.5/linux
parents acf3fabb 9069f148
......@@ -6,3 +6,8 @@ obj-y := core.o sys.o interface.o bus.o \
obj-y += power/
obj-$(CONFIG_FW_LOADER) += firmware_class.o
obj-$(CONFIG_NUMA) += node.o
ifeq ($(CONFIG_DEBUG_DRIVER),y)
EXTRA_CFLAGS += -DDEBUG
endif
......@@ -9,10 +9,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_DEBUG_DRIVER
#define DEBUG 1
#endif
#include <linux/device.h>
#include <linux/module.h>
#include <linux/errno.h>
......
......@@ -11,10 +11,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_DEBUG_DRIVER
#define DEBUG 1
#endif
#include <linux/device.h>
#include <linux/module.h>
#include <linux/init.h>
......@@ -106,13 +102,21 @@ void class_put(struct class * cls)
int class_register(struct class * cls)
{
int error;
pr_debug("device class '%s': registering\n",cls->name);
INIT_LIST_HEAD(&cls->children);
INIT_LIST_HEAD(&cls->interfaces);
kobject_set_name(&cls->subsys.kset.kobj,cls->name);
error = kobject_set_name(&cls->subsys.kset.kobj,cls->name);
if (error)
return error;
subsys_set_kset(cls,class_subsys);
subsystem_register(&cls->subsys);
error = subsystem_register(&cls->subsys);
if (error)
return error;
return 0;
}
......
......@@ -9,10 +9,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_DEBUG_DRIVER
#define DEBUG 1
#endif
#include <linux/device.h>
#include <linux/kdev_t.h>
#include <linux/err.h>
......
......@@ -9,10 +9,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_DEBUG_DRIVER
#define DEBUG 1
#endif
#include <linux/device.h>
#include <linux/err.h>
#include <linux/init.h>
......
......@@ -9,10 +9,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_DEBUG_DRIVER
#define DEBUG 1
#endif
#include <linux/device.h>
#include <linux/module.h>
#include <linux/errno.h>
......
obj-y := shutdown.o
obj-$(CONFIG_PM) += main.o suspend.o resume.o runtime.o sysfs.o
ifeq ($(CONFIG_DEBUG_DRIVER),y)
EXTRA_CFLAGS += -DDEBUG
endif
......@@ -20,10 +20,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_DEBUG_DRIVER
#define DEBUG 1
#endif
#include <linux/device.h>
#include "power.h"
......
......@@ -9,10 +9,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_DEBUG_DRIVER
#define DEBUG 1
#endif
#include <linux/device.h>
#include <asm/semaphore.h>
......
......@@ -13,10 +13,6 @@
*/
#include <linux/config.h>
#ifdef CONFIG_DEBUG_DRIVER
#define DEBUG 1
#endif
#include <linux/sysdev.h>
#include <linux/err.h>
#include <linux/module.h>
......
......@@ -35,6 +35,8 @@
#define DRM_STUB_MAXCARDS 16 /* Enough for one machine */
static struct class_simple *drm_class;
/** Stub list. One for each minor. */
static struct drm_stub_list {
const char *name;
......@@ -117,6 +119,7 @@ static int DRM(stub_getminor)(const char *name, struct file_operations *fops,
DRM(stub_root) = DRM(proc_init)(dev, i, DRM(stub_root),
&DRM(stub_list)[i]
.dev_root);
class_simple_device_add(drm_class, MKDEV(DRM_MAJOR, i), NULL, name);
return i;
}
}
......@@ -141,6 +144,7 @@ static int DRM(stub_putminor)(int minor)
DRM(proc_cleanup)(minor, DRM(stub_root),
DRM(stub_list)[minor].dev_root);
if (minor) {
class_simple_device_remove(MKDEV(DRM_MAJOR, minor));
inter_module_put("drm");
} else {
inter_module_unregister("drm");
......@@ -148,6 +152,8 @@ static int DRM(stub_putminor)(int minor)
sizeof(*DRM(stub_list)) * DRM_STUB_MAXCARDS,
DRM_MEM_STUB);
unregister_chrdev(DRM_MAJOR, "drm");
class_simple_device_remove(MKDEV(DRM_MAJOR, minor));
class_simple_destroy(drm_class);
}
return 0;
}
......@@ -170,10 +176,23 @@ int DRM(stub_register)(const char *name, struct file_operations *fops,
drm_device_t *dev)
{
struct drm_stub_info *i = NULL;
int ret1;
int ret2;
DRM_DEBUG("\n");
if (register_chrdev(DRM_MAJOR, "drm", &DRM(stub_fops)))
ret1 = register_chrdev(DRM_MAJOR, "drm", &DRM(stub_fops));
if (!ret1) {
drm_class = class_simple_create(THIS_MODULE, "drm");
if (IS_ERR(drm_class)) {
printk (KERN_ERR "Error creating drm class.\n");
unregister_chrdev(DRM_MAJOR, "drm");
return PTR_ERR(drm_class);
}
}
else if (ret1 == -EBUSY)
i = (struct drm_stub_info *)inter_module_get("drm");
else
return -1;
if (i) {
/* Already registered */
......@@ -186,8 +205,18 @@ int DRM(stub_register)(const char *name, struct file_operations *fops,
DRM_DEBUG("calling inter_module_register\n");
inter_module_register("drm", THIS_MODULE, &DRM(stub_info));
}
if (DRM(stub_info).info_register)
return DRM(stub_info).info_register(name, fops, dev);
if (DRM(stub_info).info_register) {
ret2 = DRM(stub_info).info_register(name, fops, dev);
if (ret2) {
if (!ret1) {
unregister_chrdev(DRM_MAJOR, "drm");
class_simple_destroy(drm_class);
}
if (!i)
inter_module_unregister("drm");
}
return ret2;
}
return -1;
}
......
......@@ -869,7 +869,7 @@ static struct parport_driver lp_driver = {
int __init lp_init (void)
{
int i;
int i, err = 0;
if (parport_nr[0] == LP_PARPORT_OFF)
return 0;
......@@ -900,10 +900,15 @@ int __init lp_init (void)
devfs_mk_dir("printers");
lp_class = class_simple_create(THIS_MODULE, "printer");
if (IS_ERR(lp_class)) {
err = PTR_ERR(lp_class);
goto out_devfs;
}
if (parport_register_driver (&lp_driver)) {
printk (KERN_ERR "lp: unable to register with parport\n");
return -EIO;
err = -EIO;
goto out_class;
}
if (!lp_count) {
......@@ -915,6 +920,13 @@ int __init lp_init (void)
}
return 0;
out_class:
class_simple_destroy(lp_class);
out_devfs:
devfs_remove("printers");
unregister_chrdev(LP_MAJOR, "lp");
return err;
}
static int __init lp_init_module (void)
......
......@@ -342,6 +342,7 @@ static int __init misc_init(void)
if (register_chrdev(MISC_MAJOR,"misc",&misc_fops)) {
printk("unable to get major %d for misc devices\n",
MISC_MAJOR);
class_simple_destroy(misc_class);
return -EIO;
}
return 0;
......
......@@ -2195,8 +2195,6 @@ void tty_unregister_device(struct tty_driver *driver, unsigned index)
EXPORT_SYMBOL(tty_register_device);
EXPORT_SYMBOL(tty_unregister_device);
static struct kobject tty_kobj = {.name = "tty"};
struct tty_driver *alloc_tty_driver(int lines)
{
struct tty_driver *driver;
......@@ -2256,7 +2254,6 @@ int tty_register_driver(struct tty_driver *driver)
int error;
int i;
dev_t dev;
char *s;
void **p = NULL;
if (driver->flags & TTY_DRIVER_INSTALLED)
......@@ -2296,15 +2293,11 @@ int tty_register_driver(struct tty_driver *driver)
driver->termios_locked = NULL;
}
driver->cdev.kobj.parent = &tty_kobj;
strcpy(driver->cdev.kobj.name, driver->name);
for (s = strchr(driver->cdev.kobj.name, '/'); s; s = strchr(s, '/'))
*s = '!';
cdev_init(&driver->cdev, &tty_fops);
driver->cdev.owner = driver->owner;
error = cdev_add(&driver->cdev, dev, driver->num);
if (error) {
kobject_del(&driver->cdev.kobj);
cdev_del(&driver->cdev);
unregister_chrdev_region(dev, driver->num);
driver->ttys = NULL;
driver->termios = driver->termios_locked = NULL;
......@@ -2420,7 +2413,9 @@ static int __init tty_class_init(void)
}
postcore_initcall(tty_class_init);
/* 3/2004 jmc: why do these devices exist? */
static struct cdev tty_cdev, console_cdev;
#ifdef CONFIG_UNIX98_PTYS
static struct cdev ptmx_cdev;
......@@ -2435,7 +2430,6 @@ static struct cdev vc0_cdev;
*/
static int __init tty_init(void)
{
strcpy(tty_cdev.kobj.name, "dev.tty");
cdev_init(&tty_cdev, &tty_fops);
if (cdev_add(&tty_cdev, MKDEV(TTYAUX_MAJOR, 0), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1, "/dev/tty") < 0)
......@@ -2443,7 +2437,6 @@ static int __init tty_init(void)
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty");
class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 0), NULL, "tty");
strcpy(console_cdev.kobj.name, "dev.console");
cdev_init(&console_cdev, &console_fops);
if (cdev_add(&console_cdev, MKDEV(TTYAUX_MAJOR, 1), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1, "/dev/console") < 0)
......@@ -2451,11 +2444,7 @@ static int __init tty_init(void)
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console");
class_simple_device_add(tty_class, MKDEV(TTYAUX_MAJOR, 1), NULL, "console");
tty_kobj.kset = tty_cdev.kobj.kset;
kobject_register(&tty_kobj);
#ifdef CONFIG_UNIX98_PTYS
strcpy(ptmx_cdev.kobj.name, "dev.ptmx");
cdev_init(&ptmx_cdev, &tty_fops);
if (cdev_add(&ptmx_cdev, MKDEV(TTYAUX_MAJOR, 2), 1) ||
register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1, "/dev/ptmx") < 0)
......@@ -2465,7 +2454,6 @@ static int __init tty_init(void)
#endif
#ifdef CONFIG_VT
strcpy(vc0_cdev.kobj.name, "dev.vc0");
cdev_init(&vc0_cdev, &console_fops);
if (cdev_add(&vc0_cdev, MKDEV(TTY_MAJOR, 0), 1) ||
register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1, "/dev/vc/0") < 0)
......
......@@ -1266,7 +1266,6 @@ static int __init amdtp_init_module (void)
{
cdev_init(&amdtp_cdev, &amdtp_fops);
amdtp_cdev.owner = THIS_MODULE;
kobject_set_name(&amdtp_cdev.kobj, "amdtp");
if (cdev_add(&amdtp_cdev, IEEE1394_AMDTP_DEV, 16)) {
HPSB_ERR("amdtp: unable to add char device");
return -EIO;
......
......@@ -2616,7 +2616,6 @@ static int __init dv1394_init_module(void)
cdev_init(&dv1394_cdev, &dv1394_fops);
dv1394_cdev.owner = THIS_MODULE;
kobject_set_name(&dv1394_cdev.kobj, "dv1394");
ret = cdev_add(&dv1394_cdev, IEEE1394_DV1394_DEV, 16);
if (ret) {
printk(KERN_ERR "dv1394: unable to register character device\n");
......
......@@ -2746,9 +2746,9 @@ static int __init init_raw1394(void)
cdev_init(&raw1394_cdev, &raw1394_fops);
raw1394_cdev.owner = THIS_MODULE;
kobject_set_name(&raw1394_cdev.kobj, RAW1394_DEVICE_NAME);
ret = cdev_add(&raw1394_cdev, IEEE1394_RAW1394_DEV, 1);
if (ret) {
/* jmc: leaves reference to (static) raw1394_cdev */
HPSB_ERR("raw1394 failed to register minor device block");
devfs_remove(RAW1394_DEVICE_NAME);
hpsb_unregister_highlevel(&raw1394_highlevel);
......
......@@ -1457,7 +1457,6 @@ static int __init video1394_init_module (void)
cdev_init(&video1394_cdev, &video1394_fops);
video1394_cdev.owner = THIS_MODULE;
kobject_set_name(&video1394_cdev.kobj, VIDEO1394_DRIVER_NAME);
ret = cdev_add(&video1394_cdev, IEEE1394_VIDEO1394_DEV, 16);
if (ret) {
PRINT_G(KERN_ERR, "video1394: unable to get minor device block");
......
......@@ -727,6 +727,8 @@ static int __init input_init(void)
int retval = -ENOMEM;
input_class = class_simple_create(THIS_MODULE, "input");
if (IS_ERR(input_class))
return PTR_ERR(input_class);
input_proc_init();
retval = register_chrdev(INPUT_MAJOR, "input", &input_fops);
if (retval) {
......@@ -734,6 +736,7 @@ static int __init input_init(void)
remove_proc_entry("devices", proc_bus_input_dir);
remove_proc_entry("handlers", proc_bus_input_dir);
remove_proc_entry("input", proc_bus);
class_simple_destroy(input_class);
return retval;
}
......@@ -743,6 +746,7 @@ static int __init input_init(void)
remove_proc_entry("handlers", proc_bus_input_dir);
remove_proc_entry("input", proc_bus);
unregister_chrdev(INPUT_MAJOR, "input");
class_simple_destroy(input_class);
}
return retval;
}
......
......@@ -45,6 +45,7 @@
#include <linux/smp_lock.h>
#include <linux/rwsem.h>
#include <linux/stddef.h>
#include <linux/device.h>
#include <net/slhc_vj.h>
#include <asm/atomic.h>
......@@ -271,6 +272,8 @@ static int ppp_connect_channel(struct channel *pch, int unit);
static int ppp_disconnect_channel(struct channel *pch);
static void ppp_destroy_channel(struct channel *pch);
static struct class_simple *ppp_class;
/* Translates a PPP protocol number to a NP index (NP == network protocol) */
static inline int proto_to_npindex(int proto)
{
......@@ -804,15 +807,29 @@ static int __init ppp_init(void)
printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n");
err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops);
if (!err) {
ppp_class = class_simple_create(THIS_MODULE, "ppp");
if (IS_ERR(ppp_class)) {
err = PTR_ERR(ppp_class);
goto out_chrdev;
}
class_simple_device_add(ppp_class, MKDEV(PPP_MAJOR, 0), NULL, "ppp");
err = devfs_mk_cdev(MKDEV(PPP_MAJOR, 0),
S_IFCHR|S_IRUSR|S_IWUSR, "ppp");
if (err)
unregister_chrdev(PPP_MAJOR, "ppp");
goto out_class;
}
out:
if (err)
printk(KERN_ERR "failed to register PPP device (%d)\n", err);
return err;
out_class:
class_simple_device_remove(MKDEV(PPP_MAJOR,0));
class_simple_destroy(ppp_class);
out_chrdev:
unregister_chrdev(PPP_MAJOR, "ppp");
goto out;
}
/*
......@@ -2545,6 +2562,8 @@ static void __exit ppp_cleanup(void)
if (unregister_chrdev(PPP_MAJOR, "ppp") != 0)
printk(KERN_ERR "PPP: failed to unregister PPP device\n");
devfs_remove("ppp");
class_simple_device_remove(MKDEV(PPP_MAJOR, 0));
class_simple_destroy(ppp_class);
}
/*
......
......@@ -104,19 +104,7 @@ static struct kobj_type hotplug_slot_ktype = {
.release = &hotplug_slot_release,
};
/*
* We create a struct subsystem on our own and not use decl_subsys so
* we can have a sane name "slots" in sysfs, yet still keep a good
* global variable name "pci_hotplug_slots_subsys.
* If the decl_subsys() #define ever changes, this declaration will
* need to be update to make sure everything is initialized properly.
*/
struct subsystem pci_hotplug_slots_subsys = {
.kset = {
.kobj = { .name = "slots" },
.ktype = &hotplug_slot_ktype,
}
};
decl_subsys_name(pci_hotplug_slots, slots, &hotplug_slot_ktype, NULL);
/* these strings match up with the values in pci_bus_speed */
static char *pci_bus_speed_strings[] = {
......
......@@ -46,13 +46,10 @@ struct cdev *register_tape_dev(
cdev->owner = fops->owner;
cdev->ops = fops;
cdev->dev = dev;
strcpy(cdev->kobj.name, devname);
for (s = strchr(cdev->kobj.name, '/'); s; s = strchr(s, '/'))
*s = '!';
rc = cdev_add(cdev, cdev->dev, 1);
if (rc) {
kobject_put(&cdev->kobj);
cdev_del(cdev);
return ERR_PTR(rc);
}
class_simple_device_add(tape_class, cdev->dev, device, "%s", devname);
......
......@@ -1409,7 +1409,6 @@ sg_add(struct class_device *cl_dev)
SCSI_LOG_TIMEOUT(3, printk("sg_add: dev=%d \n", k));
memset(sdp, 0, sizeof(*sdp));
sprintf(disk->disk_name, "sg%d", k);
strncpy(cdev->kobj.name, disk->disk_name, KOBJ_NAME_LEN);
cdev->owner = THIS_MODULE;
cdev->ops = &sg_fops;
disk->major = SCSI_GENERIC_MAJOR;
......@@ -1439,7 +1438,7 @@ sg_add(struct class_device *cl_dev)
MKDEV(SCSI_GENERIC_MAJOR, k),
cl_dev->dev, "%s",
disk->disk_name);
if (NULL == sg_class_member)
if (IS_ERR(sg_class_member))
printk(KERN_WARNING "sg_add: "
"class_simple_device_add failed\n");
class_set_devdata(sg_class_member, sdp);
......@@ -1462,7 +1461,7 @@ sg_add(struct class_device *cl_dev)
out:
put_disk(disk);
if (cdev)
kobject_put(&cdev->kobj);
cdev_del(cdev);
return error;
}
......
......@@ -3896,11 +3896,6 @@ static int st_probe(struct device *dev)
dev_num);
goto out_free_tape;
}
/* Make sure that the minor numbers corresponding to the four
first modes always get the same names */
i = mode << (4 - ST_NBR_MODE_BITS);
snprintf(cdev->kobj.name, KOBJ_NAME_LEN, "%s%s%s", j ? "n" : "",
disk->disk_name, st_formats[i]);
cdev->owner = THIS_MODULE;
cdev->ops = &st_fops;
......@@ -3959,7 +3954,7 @@ static int st_probe(struct device *dev)
}
}
if (cdev)
kobject_put(&cdev->kobj);
cdev_del(cdev);
write_lock(&st_dev_arr_lock);
scsi_tapes[dev_num] = NULL;
st_nr_dev--;
......
......@@ -340,15 +340,9 @@ static int exact_lock(dev_t dev, void *data)
int cdev_add(struct cdev *p, dev_t dev, unsigned count)
{
int err = kobject_add(&p->kobj);
if (err)
return err;
err = kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);
if (err)
kobject_del(&p->kobj);
p->dev = dev;
p->count = count;
return err;
return kobj_map(cdev_map, dev, count, NULL, exact_match, exact_lock, p);
}
static void cdev_unmap(dev_t dev, unsigned count)
......@@ -359,7 +353,6 @@ static void cdev_unmap(dev_t dev, unsigned count)
void cdev_del(struct cdev *p)
{
cdev_unmap(p->dev, p->count);
kobject_del(&p->kobj);
kobject_put(&p->kobj);
}
......@@ -407,18 +400,12 @@ static struct kobj_type ktype_cdev_dynamic = {
.release = cdev_dynamic_release,
};
static struct kset kset_dynamic = {
.subsys = &cdev_subsys,
.kobj = {.name = "major",},
.ktype = &ktype_cdev_dynamic,
};
struct cdev *cdev_alloc(void)
{
struct cdev *p = kmalloc(sizeof(struct cdev), GFP_KERNEL);
if (p) {
memset(p, 0, sizeof(struct cdev));
p->kobj.kset = &kset_dynamic;
p->kobj.ktype = &ktype_cdev_dynamic;
INIT_LIST_HEAD(&p->list);
kobject_init(&p->kobj);
}
......@@ -428,7 +415,6 @@ struct cdev *cdev_alloc(void)
void cdev_init(struct cdev *cdev, struct file_operations *fops)
{
INIT_LIST_HEAD(&cdev->list);
kobj_set_kset_s(cdev, cdev_subsys);
cdev->kobj.ktype = &ktype_cdev_default;
kobject_init(&cdev->kobj);
cdev->ops = fops;
......@@ -444,8 +430,12 @@ static struct kobject *base_probe(dev_t dev, int *part, void *data)
void __init chrdev_init(void)
{
subsystem_register(&cdev_subsys);
kset_register(&kset_dynamic);
/*
* Keep cdev_subsys around because (and only because) the kobj_map code
* depends on the rwsem it contains. We don't make it public in sysfs,
* however.
*/
subsystem_init(&cdev_subsys);
cdev_map = kobj_map_init(base_probe, &cdev_subsys);
}
......
......@@ -151,6 +151,14 @@ struct subsystem _name##_subsys = { \
.hotplug_ops =_hotplug_ops, \
} \
}
#define decl_subsys_name(_varname,_name,_type,_hotplug_ops) \
struct subsystem _varname##_subsys = { \
.kset = { \
.kobj = { .name = __stringify(_name) }, \
.ktype = _type, \
.hotplug_ops =_hotplug_ops, \
} \
}
/**
......
/*
* kref.c - library routines for handling generic reference counted objects
*
* Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
* Copyright (C) 2004 IBM Corp.
*
* based on kobject.h which was:
* Copyright (C) 2002-2003 Patrick Mochel <mochel@osdl.org>
* Copyright (C) 2002-2003 Open Source Development Labs
*
* This file is released under the GPLv2.
*
*/
#if defined(__KERNEL__) && !defined(_KREF_H_)
#define _KREF_H_
#include <linux/types.h>
#include <asm/atomic.h>
struct kref {
atomic_t refcount;
void (*release)(struct kref *kref);
};
void kref_init(struct kref *kref, void (*release)(struct kref *));
struct kref *kref_get(struct kref *kref);
void kref_put(struct kref *kref);
#endif /* _KREF_H_ */
......@@ -8,6 +8,9 @@ lib-y := errno.o ctype.o string.o vsprintf.o cmdline.o \
kobject.o idr.o div64.o parser.o int_sqrt.o \
bitmap.o extable.o
# hack for now till some static code uses krefs, then it can move up above...
obj-y += kref.o
lib-$(CONFIG_RWSEM_GENERIC_SPINLOCK) += rwsem-spinlock.o
lib-$(CONFIG_RWSEM_XCHGADD_ALGORITHM) += rwsem.o
......
/*
* kref.c - library routines for handling generic reference counted objects
*
* Copyright (C) 2004 Greg Kroah-Hartman <greg@kroah.com>
* Copyright (C) 2004 IBM Corp.
*
* based on lib/kobject.c which was:
* Copyright (C) 2002-2003 Patrick Mochel <mochel@osdl.org>
*
* This file is released under the GPLv2.
*
*/
/* #define DEBUG */
#include <linux/kref.h>
#include <linux/module.h>
/**
* kref_init - initialize object.
* @kref: object in question.
* @release: pointer to a function that will clean up the object
* when the last reference to the object is released.
* This pointer is required.
*/
void kref_init(struct kref *kref, void (*release)(struct kref *kref))
{
WARN_ON(release == NULL);
atomic_set(&kref->refcount,1);
kref->release = release;
}
/**
* kref_get - increment refcount for object.
* @kref: object.
*/
struct kref *kref_get(struct kref *kref)
{
WARN_ON(!atomic_read(&kref->refcount));
atomic_inc(&kref->refcount);
return kref;
}
/**
* kref_put - decrement refcount for object.
* @kref: object.
*
* Decrement the refcount, and if 0, call kref->release().
*/
void kref_put(struct kref *kref)
{
if (atomic_dec_and_test(&kref->refcount)) {
pr_debug("kref cleaning up\n");
kref->release(kref);
}
}
EXPORT_SYMBOL(kref_init);
EXPORT_SYMBOL(kref_get);
EXPORT_SYMBOL(kref_put);
......@@ -27,6 +27,7 @@
#include <linux/init.h>
#include <linux/devfs_fs_kernel.h>
#include <linux/smp_lock.h>
#include <linux/device.h>
#include <asm/bitops.h>
#include <asm/system.h>
......@@ -34,6 +35,7 @@
static long open_map;
static struct socket *netlink_user[MAX_LINKS];
static struct class_simple *netlink_class;
/*
* Device operations
......@@ -229,17 +231,26 @@ static int __init init_netlink(void)
return -EIO;
}
netlink_class = class_simple_create(THIS_MODULE, "netlink");
if (IS_ERR(netlink_class)) {
printk (KERN_ERR "Error creating netlink class.\n");
unregister_chrdev(NETLINK_MAJOR, "netlink");
return PTR_ERR(netlink_class);
}
devfs_mk_dir("netlink");
/* Someone tell me the official names for the uppercase ones */
for (i = 0; i < ARRAY_SIZE(entries); i++) {
devfs_mk_cdev(MKDEV(NETLINK_MAJOR, entries[i].minor),
S_IFCHR|S_IRUSR|S_IWUSR, "netlink/%s", entries[i].name);
class_simple_device_add(netlink_class, MKDEV(NETLINK_MAJOR, entries[i].minor), NULL, "%s", entries[i].name);
}
for (i = 0; i < 16; i++) {
devfs_mk_cdev(MKDEV(NETLINK_MAJOR, i + 16),
S_IFCHR|S_IRUSR|S_IWUSR, "netlink/tap%d", i);
class_simple_device_add(netlink_class, MKDEV(NETLINK_MAJOR, i + 16), NULL, "tap%d", i);
}
return 0;
......@@ -249,11 +260,16 @@ static void __exit cleanup_netlink(void)
{
int i;
for (i = 0; i < ARRAY_SIZE(entries); i++)
for (i = 0; i < ARRAY_SIZE(entries); i++) {
devfs_remove("netlink/%s", entries[i].name);
for (i = 0; i < 16; i++)
class_simple_device_remove(MKDEV(NETLINK_MAJOR, entries[i].minor));
}
for (i = 0; i < 16; i++) {
devfs_remove("netlink/tap%d", i);
class_simple_device_remove(MKDEV(NETLINK_MAJOR, i + 16));
}
devfs_remove("netlink");
class_simple_destroy(netlink_class);
unregister_chrdev(NETLINK_MAJOR, "netlink");
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment