#include <linux/miscdevice.h>
#include <linux/kernel.h>
#include <linux/major.h>
-#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/proc_fs.h>
#include <linux/seq_file.h>
#include <linux/device.h>
#include <linux/tty.h>
#include <linux/kmod.h>
-#include <linux/smp_lock.h>
+#include <linux/gfp.h>
/*
* Head entry for the doubly linked miscdevice list
* Assigned numbers, used for dynamic minors
*/
#define DYNAMIC_MINORS 64 /* like dynamic majors */
-static unsigned char misc_minors[DYNAMIC_MINORS / 8];
-
-extern int pmu_device_init(void);
+static DECLARE_BITMAP(misc_minors, DYNAMIC_MINORS);
#ifdef CONFIG_PROC_FS
static void *misc_seq_start(struct seq_file *seq, loff_t *pos)
}
-static struct seq_operations misc_seq_ops = {
+static const struct seq_operations misc_seq_ops = {
.start = misc_seq_start,
.next = misc_seq_next,
.stop = misc_seq_stop,
struct miscdevice *c;
int err = -ENODEV;
const struct file_operations *old_fops, *new_fops = NULL;
-
- lock_kernel();
+
mutex_lock(&misc_mtx);
list_for_each_entry(c, &misc_list, list) {
old_fops = file->f_op;
file->f_op = new_fops;
if (file->f_op->open) {
+ file->private_data = c;
err=file->f_op->open(inode,file);
if (err) {
fops_put(file->f_op);
fops_put(old_fops);
fail:
mutex_unlock(&misc_mtx);
- unlock_kernel();
return err;
}
.open = misc_open,
};
-
/**
* misc_register - register a miscellaneous device
* @misc: device structure
}
if (misc->minor == MISC_DYNAMIC_MINOR) {
- int i = DYNAMIC_MINORS;
- while (--i >= 0)
- if ( (misc_minors[i>>3] & (1 << (i&7))) == 0)
- break;
- if (i<0) {
+ int i = find_first_zero_bit(misc_minors, DYNAMIC_MINORS);
+ if (i >= DYNAMIC_MINORS) {
mutex_unlock(&misc_mtx);
return -EBUSY;
}
- misc->minor = i;
+ misc->minor = DYNAMIC_MINORS - i - 1;
+ set_bit(i, misc_minors);
}
- if (misc->minor < DYNAMIC_MINORS)
- misc_minors[misc->minor >> 3] |= 1 << (misc->minor & 7);
dev = MKDEV(MISC_MAJOR, misc->minor);
- misc->this_device = device_create(misc_class, misc->parent, dev, NULL,
- "%s", misc->name);
+ misc->this_device = device_create(misc_class, misc->parent, dev,
+ misc, "%s", misc->name);
if (IS_ERR(misc->this_device)) {
+ int i = DYNAMIC_MINORS - misc->minor - 1;
+ if (i < DYNAMIC_MINORS && i >= 0)
+ clear_bit(i, misc_minors);
err = PTR_ERR(misc->this_device);
goto out;
}
int misc_deregister(struct miscdevice *misc)
{
- int i = misc->minor;
+ int i = DYNAMIC_MINORS - misc->minor - 1;
if (list_empty(&misc->list))
return -EINVAL;
mutex_lock(&misc_mtx);
list_del(&misc->list);
device_destroy(misc_class, MKDEV(MISC_MAJOR, misc->minor));
- if (i < DYNAMIC_MINORS && i>0) {
- misc_minors[i>>3] &= ~(1 << (misc->minor & 7));
- }
+ if (i < DYNAMIC_MINORS && i >= 0)
+ clear_bit(i, misc_minors);
mutex_unlock(&misc_mtx);
return 0;
}
EXPORT_SYMBOL(misc_register);
EXPORT_SYMBOL(misc_deregister);
+static char *misc_devnode(struct device *dev, mode_t *mode)
+{
+ struct miscdevice *c = dev_get_drvdata(dev);
+
+ if (mode && c->mode)
+ *mode = c->mode;
+ if (c->nodename)
+ return kstrdup(c->nodename, GFP_KERNEL);
+ return NULL;
+}
+
static int __init misc_init(void)
{
int err;
err = -EIO;
if (register_chrdev(MISC_MAJOR,"misc",&misc_fops))
goto fail_printk;
+ misc_class->devnode = misc_devnode;
return 0;
fail_printk: