diff options
| -rw-r--r-- | fs/char_dev.c | 39 | ||||
| -rw-r--r-- | include/linux/fs.h | 19 |
2 files changed, 42 insertions, 16 deletions
diff --git a/fs/char_dev.c b/fs/char_dev.c index a173551e19d7..2f18c1e4e301 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c | |||
| @@ -237,8 +237,10 @@ int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, | |||
| 237 | } | 237 | } |
| 238 | 238 | ||
| 239 | /** | 239 | /** |
| 240 | * register_chrdev() - Register a major number for character devices. | 240 | * __register_chrdev() - create and register a cdev occupying a range of minors |
| 241 | * @major: major device number or 0 for dynamic allocation | 241 | * @major: major device number or 0 for dynamic allocation |
| 242 | * @baseminor: first of the requested range of minor numbers | ||
| 243 | * @count: the number of minor numbers required | ||
| 242 | * @name: name of this range of devices | 244 | * @name: name of this range of devices |
| 243 | * @fops: file operations associated with this devices | 245 | * @fops: file operations associated with this devices |
| 244 | * | 246 | * |
| @@ -254,19 +256,17 @@ int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, | |||
| 254 | * /dev. It only helps to keep track of the different owners of devices. If | 256 | * /dev. It only helps to keep track of the different owners of devices. If |
| 255 | * your module name has only one type of devices it's ok to use e.g. the name | 257 | * your module name has only one type of devices it's ok to use e.g. the name |
| 256 | * of the module here. | 258 | * of the module here. |
| 257 | * | ||
| 258 | * This function registers a range of 256 minor numbers. The first minor number | ||
| 259 | * is 0. | ||
| 260 | */ | 259 | */ |
| 261 | int register_chrdev(unsigned int major, const char *name, | 260 | int __register_chrdev(unsigned int major, unsigned int baseminor, |
| 262 | const struct file_operations *fops) | 261 | unsigned int count, const char *name, |
| 262 | const struct file_operations *fops) | ||
| 263 | { | 263 | { |
| 264 | struct char_device_struct *cd; | 264 | struct char_device_struct *cd; |
| 265 | struct cdev *cdev; | 265 | struct cdev *cdev; |
| 266 | char *s; | 266 | char *s; |
| 267 | int err = -ENOMEM; | 267 | int err = -ENOMEM; |
| 268 | 268 | ||
| 269 | cd = __register_chrdev_region(major, 0, 256, name); | 269 | cd = __register_chrdev_region(major, baseminor, count, name); |
| 270 | if (IS_ERR(cd)) | 270 | if (IS_ERR(cd)) |
| 271 | return PTR_ERR(cd); | 271 | return PTR_ERR(cd); |
| 272 | 272 | ||
| @@ -280,7 +280,7 @@ int register_chrdev(unsigned int major, const char *name, | |||
| 280 | for (s = strchr(kobject_name(&cdev->kobj),'/'); s; s = strchr(s, '/')) | 280 | for (s = strchr(kobject_name(&cdev->kobj),'/'); s; s = strchr(s, '/')) |
| 281 | *s = '!'; | 281 | *s = '!'; |
| 282 | 282 | ||
| 283 | err = cdev_add(cdev, MKDEV(cd->major, 0), 256); | 283 | err = cdev_add(cdev, MKDEV(cd->major, baseminor), count); |
| 284 | if (err) | 284 | if (err) |
| 285 | goto out; | 285 | goto out; |
| 286 | 286 | ||
| @@ -290,7 +290,7 @@ int register_chrdev(unsigned int major, const char *name, | |||
| 290 | out: | 290 | out: |
| 291 | kobject_put(&cdev->kobj); | 291 | kobject_put(&cdev->kobj); |
| 292 | out2: | 292 | out2: |
| 293 | kfree(__unregister_chrdev_region(cd->major, 0, 256)); | 293 | kfree(__unregister_chrdev_region(cd->major, baseminor, count)); |
| 294 | return err; | 294 | return err; |
| 295 | } | 295 | } |
| 296 | 296 | ||
| @@ -316,10 +316,23 @@ void unregister_chrdev_region(dev_t from, unsigned count) | |||
| 316 | } | 316 | } |
| 317 | } | 317 | } |
| 318 | 318 | ||
| 319 | void unregister_chrdev(unsigned int major, const char *name) | 319 | /** |
| 320 | * __unregister_chrdev - unregister and destroy a cdev | ||
| 321 | * @major: major device number | ||
| 322 | * @baseminor: first of the range of minor numbers | ||
| 323 | * @count: the number of minor numbers this cdev is occupying | ||
| 324 | * @name: name of this range of devices | ||
| 325 | * | ||
| 326 | * Unregister and destroy the cdev occupying the region described by | ||
| 327 | * @major, @baseminor and @count. This function undoes what | ||
| 328 | * __register_chrdev() did. | ||
| 329 | */ | ||
| 330 | void __unregister_chrdev(unsigned int major, unsigned int baseminor, | ||
| 331 | unsigned int count, const char *name) | ||
| 320 | { | 332 | { |
| 321 | struct char_device_struct *cd; | 333 | struct char_device_struct *cd; |
| 322 | cd = __unregister_chrdev_region(major, 0, 256); | 334 | |
| 335 | cd = __unregister_chrdev_region(major, baseminor, count); | ||
| 323 | if (cd && cd->cdev) | 336 | if (cd && cd->cdev) |
| 324 | cdev_del(cd->cdev); | 337 | cdev_del(cd->cdev); |
| 325 | kfree(cd); | 338 | kfree(cd); |
| @@ -568,6 +581,6 @@ EXPORT_SYMBOL(cdev_alloc); | |||
| 568 | EXPORT_SYMBOL(cdev_del); | 581 | EXPORT_SYMBOL(cdev_del); |
| 569 | EXPORT_SYMBOL(cdev_add); | 582 | EXPORT_SYMBOL(cdev_add); |
| 570 | EXPORT_SYMBOL(cdev_index); | 583 | EXPORT_SYMBOL(cdev_index); |
| 571 | EXPORT_SYMBOL(register_chrdev); | 584 | EXPORT_SYMBOL(__register_chrdev); |
| 572 | EXPORT_SYMBOL(unregister_chrdev); | 585 | EXPORT_SYMBOL(__unregister_chrdev); |
| 573 | EXPORT_SYMBOL(directly_mappable_cdev_bdi); | 586 | EXPORT_SYMBOL(directly_mappable_cdev_bdi); |
diff --git a/include/linux/fs.h b/include/linux/fs.h index a36ffa5a77a4..6c36ab788854 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h | |||
| @@ -1998,12 +1998,25 @@ extern void bd_release_from_disk(struct block_device *, struct gendisk *); | |||
| 1998 | #define CHRDEV_MAJOR_HASH_SIZE 255 | 1998 | #define CHRDEV_MAJOR_HASH_SIZE 255 |
| 1999 | extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *); | 1999 | extern int alloc_chrdev_region(dev_t *, unsigned, unsigned, const char *); |
| 2000 | extern int register_chrdev_region(dev_t, unsigned, const char *); | 2000 | extern int register_chrdev_region(dev_t, unsigned, const char *); |
| 2001 | extern int register_chrdev(unsigned int, const char *, | 2001 | extern int __register_chrdev(unsigned int major, unsigned int baseminor, |
| 2002 | const struct file_operations *); | 2002 | unsigned int count, const char *name, |
| 2003 | extern void unregister_chrdev(unsigned int, const char *); | 2003 | const struct file_operations *fops); |
| 2004 | extern void __unregister_chrdev(unsigned int major, unsigned int baseminor, | ||
| 2005 | unsigned int count, const char *name); | ||
| 2004 | extern void unregister_chrdev_region(dev_t, unsigned); | 2006 | extern void unregister_chrdev_region(dev_t, unsigned); |
| 2005 | extern void chrdev_show(struct seq_file *,off_t); | 2007 | extern void chrdev_show(struct seq_file *,off_t); |
| 2006 | 2008 | ||
| 2009 | static inline int register_chrdev(unsigned int major, const char *name, | ||
| 2010 | const struct file_operations *fops) | ||
| 2011 | { | ||
| 2012 | return __register_chrdev(major, 0, 256, name, fops); | ||
| 2013 | } | ||
| 2014 | |||
| 2015 | static inline void unregister_chrdev(unsigned int major, const char *name) | ||
| 2016 | { | ||
| 2017 | __unregister_chrdev(major, 0, 256, name); | ||
| 2018 | } | ||
| 2019 | |||
| 2007 | /* fs/block_dev.c */ | 2020 | /* fs/block_dev.c */ |
| 2008 | #define BDEVNAME_SIZE 32 /* Largest string for a blockdev identifier */ | 2021 | #define BDEVNAME_SIZE 32 /* Largest string for a blockdev identifier */ |
| 2009 | #define BDEVT_SIZE 10 /* Largest string for MAJ:MIN for blkdev */ | 2022 | #define BDEVT_SIZE 10 /* Largest string for MAJ:MIN for blkdev */ |
