X-Git-Url: http://git.rot13.org/?a=blobdiff_plain;f=fs%2Fchar_dev.c;h=3483d3cf80873432d7696f6f3f68b4adef928b01;hb=e87bfe51b5ca2db99dd680bbb1e8fe3c94b607df;hp=5c36345c9bf78376b6996604d98aba2679d6ed09;hpb=11ed56fb7899f9eb9eaef8e5919db1bf08f1b07e;p=powerpc.git diff --git a/fs/char_dev.c b/fs/char_dev.c index 5c36345c9b..3483d3cf80 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c @@ -4,7 +4,6 @@ * Copyright (C) 1991, 1992 Linus Torvalds */ -#include #include #include #include @@ -14,7 +13,7 @@ #include #include #include -#include +#include #include #include @@ -27,8 +26,6 @@ static struct kobj_map *cdev_map; -#define MAX_PROBE_HASH 255 /* random */ - static DEFINE_MUTEX(chrdevs_lock); static struct char_device_struct { @@ -39,93 +36,29 @@ static struct char_device_struct { char name[64]; struct file_operations *fops; struct cdev *cdev; /* will die */ -} *chrdevs[MAX_PROBE_HASH]; +} *chrdevs[CHRDEV_MAJOR_HASH_SIZE]; /* index in the above */ static inline int major_to_index(int major) { - return major % MAX_PROBE_HASH; + return major % CHRDEV_MAJOR_HASH_SIZE; } -struct chrdev_info { - int index; - struct char_device_struct *cd; -}; +#ifdef CONFIG_PROC_FS -void *get_next_chrdev(void *dev) -{ - struct chrdev_info *info; - - if (dev == NULL) { - info = kmalloc(sizeof(*info), GFP_KERNEL); - if (!info) - goto out; - info->index=0; - info->cd = chrdevs[info->index]; - if (info->cd) - goto out; - } else { - info = dev; - } - - while (info->index < ARRAY_SIZE(chrdevs)) { - if (info->cd) - info->cd = info->cd->next; - if (info->cd) - goto out; - /* - * No devices on this chain, move to the next - */ - info->index++; - info->cd = (info->index < ARRAY_SIZE(chrdevs)) ? - chrdevs[info->index] : NULL; - if (info->cd) - goto out; - } - -out: - return info; -} - -void *acquire_chrdev_list(void) -{ - mutex_lock(&chrdevs_lock); - return get_next_chrdev(NULL); -} - -void release_chrdev_list(void *dev) -{ - mutex_unlock(&chrdevs_lock); - kfree(dev); -} - - -int count_chrdev_list(void) +void chrdev_show(struct seq_file *f, off_t offset) { struct char_device_struct *cd; - int i, count; - - count = 0; - for (i = 0; i < ARRAY_SIZE(chrdevs) ; i++) { - for (cd = chrdevs[i]; cd; cd = cd->next) - count++; + if (offset < CHRDEV_MAJOR_HASH_SIZE) { + mutex_lock(&chrdevs_lock); + for (cd = chrdevs[offset]; cd; cd = cd->next) + seq_printf(f, "%3d %s\n", cd->major, cd->name); + mutex_unlock(&chrdevs_lock); } - - return count; } -int get_chrdev_info(void *dev, int *major, char **name) -{ - struct chrdev_info *info = dev; - - if (info->cd == NULL) - return 1; - - *major = info->cd->major; - *name = info->cd->name; - return 0; -} +#endif /* CONFIG_PROC_FS */ /* * Register a single major with a specified minor range. @@ -146,12 +79,10 @@ __register_chrdev_region(unsigned int major, unsigned int baseminor, int ret = 0; int i; - cd = kmalloc(sizeof(struct char_device_struct), GFP_KERNEL); + cd = kzalloc(sizeof(struct char_device_struct), GFP_KERNEL); if (cd == NULL) return ERR_PTR(-ENOMEM); - memset(cd, 0, sizeof(struct char_device_struct)); - mutex_lock(&chrdevs_lock); /* temporary */ @@ -251,8 +182,30 @@ int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, return 0; } +/** + * register_chrdev() - Register a major number for character devices. + * @major: major device number or 0 for dynamic allocation + * @name: name of this range of devices + * @fops: file operations associated with this devices + * + * If @major == 0 this functions will dynamically allocate a major and return + * its number. + * + * If @major > 0 this function will attempt to reserve a device with the given + * major number and will return zero on success. + * + * Returns a -ve errno on failure. + * + * The name of this device has nothing to do with the name of the device in + * /dev. It only helps to keep track of the different owners of devices. If + * your module name has only one type of devices it's ok to use e.g. the name + * of the module here. + * + * This function registers a range of 256 minor numbers. The first minor number + * is 0. + */ int register_chrdev(unsigned int major, const char *name, - struct file_operations *fops) + const struct file_operations *fops) { struct char_device_struct *cd; struct cdev *cdev; @@ -408,7 +361,7 @@ static void cdev_purge(struct cdev *cdev) * is contain the open that then fills in the correct operations * depending on the special file... */ -struct file_operations def_chr_fops = { +const struct file_operations def_chr_fops = { .open = chrdev_open, }; @@ -466,9 +419,8 @@ static struct kobj_type ktype_cdev_dynamic = { struct cdev *cdev_alloc(void) { - struct cdev *p = kmalloc(sizeof(struct cdev), GFP_KERNEL); + struct cdev *p = kzalloc(sizeof(struct cdev), GFP_KERNEL); if (p) { - memset(p, 0, sizeof(struct cdev)); p->kobj.ktype = &ktype_cdev_dynamic; INIT_LIST_HEAD(&p->list); kobject_init(&p->kobj); @@ -476,7 +428,7 @@ struct cdev *cdev_alloc(void) return p; } -void cdev_init(struct cdev *cdev, struct file_operations *fops) +void cdev_init(struct cdev *cdev, const struct file_operations *fops) { memset(cdev, 0, sizeof *cdev); INIT_LIST_HEAD(&cdev->list);