diff options
Diffstat (limited to 'fs/char_dev.c')
-rw-r--r-- | fs/char_dev.c | 43 |
1 files changed, 27 insertions, 16 deletions
diff --git a/fs/char_dev.c b/fs/char_dev.c index a173551e19d7..d6db933df2b2 100644 --- a/fs/char_dev.c +++ b/fs/char_dev.c | |||
@@ -31,6 +31,7 @@ | |||
31 | * - no readahead or I/O queue unplugging required | 31 | * - no readahead or I/O queue unplugging required |
32 | */ | 32 | */ |
33 | struct backing_dev_info directly_mappable_cdev_bdi = { | 33 | struct backing_dev_info directly_mappable_cdev_bdi = { |
34 | .name = "char", | ||
34 | .capabilities = ( | 35 | .capabilities = ( |
35 | #ifdef CONFIG_MMU | 36 | #ifdef CONFIG_MMU |
36 | /* permit private copies of the data to be taken */ | 37 | /* permit private copies of the data to be taken */ |
@@ -237,8 +238,10 @@ int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, | |||
237 | } | 238 | } |
238 | 239 | ||
239 | /** | 240 | /** |
240 | * register_chrdev() - Register a major number for character devices. | 241 | * __register_chrdev() - create and register a cdev occupying a range of minors |
241 | * @major: major device number or 0 for dynamic allocation | 242 | * @major: major device number or 0 for dynamic allocation |
243 | * @baseminor: first of the requested range of minor numbers | ||
244 | * @count: the number of minor numbers required | ||
242 | * @name: name of this range of devices | 245 | * @name: name of this range of devices |
243 | * @fops: file operations associated with this devices | 246 | * @fops: file operations associated with this devices |
244 | * | 247 | * |
@@ -254,19 +257,16 @@ 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 | 257 | * /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 | 258 | * your module name has only one type of devices it's ok to use e.g. the name |
256 | * of the module here. | 259 | * of the module here. |
257 | * | ||
258 | * This function registers a range of 256 minor numbers. The first minor number | ||
259 | * is 0. | ||
260 | */ | 260 | */ |
261 | int register_chrdev(unsigned int major, const char *name, | 261 | int __register_chrdev(unsigned int major, unsigned int baseminor, |
262 | const struct file_operations *fops) | 262 | unsigned int count, const char *name, |
263 | const struct file_operations *fops) | ||
263 | { | 264 | { |
264 | struct char_device_struct *cd; | 265 | struct char_device_struct *cd; |
265 | struct cdev *cdev; | 266 | struct cdev *cdev; |
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 | ||
@@ -277,10 +277,8 @@ int register_chrdev(unsigned int major, const char *name, | |||
277 | cdev->owner = fops->owner; | 277 | cdev->owner = fops->owner; |
278 | cdev->ops = fops; | 278 | cdev->ops = fops; |
279 | kobject_set_name(&cdev->kobj, "%s", name); | 279 | kobject_set_name(&cdev->kobj, "%s", name); |
280 | for (s = strchr(kobject_name(&cdev->kobj),'/'); s; s = strchr(s, '/')) | ||
281 | *s = '!'; | ||
282 | 280 | ||
283 | err = cdev_add(cdev, MKDEV(cd->major, 0), 256); | 281 | err = cdev_add(cdev, MKDEV(cd->major, baseminor), count); |
284 | if (err) | 282 | if (err) |
285 | goto out; | 283 | goto out; |
286 | 284 | ||
@@ -290,7 +288,7 @@ int register_chrdev(unsigned int major, const char *name, | |||
290 | out: | 288 | out: |
291 | kobject_put(&cdev->kobj); | 289 | kobject_put(&cdev->kobj); |
292 | out2: | 290 | out2: |
293 | kfree(__unregister_chrdev_region(cd->major, 0, 256)); | 291 | kfree(__unregister_chrdev_region(cd->major, baseminor, count)); |
294 | return err; | 292 | return err; |
295 | } | 293 | } |
296 | 294 | ||
@@ -316,10 +314,23 @@ void unregister_chrdev_region(dev_t from, unsigned count) | |||
316 | } | 314 | } |
317 | } | 315 | } |
318 | 316 | ||
319 | void unregister_chrdev(unsigned int major, const char *name) | 317 | /** |
318 | * __unregister_chrdev - unregister and destroy a cdev | ||
319 | * @major: major device number | ||
320 | * @baseminor: first of the range of minor numbers | ||
321 | * @count: the number of minor numbers this cdev is occupying | ||
322 | * @name: name of this range of devices | ||
323 | * | ||
324 | * Unregister and destroy the cdev occupying the region described by | ||
325 | * @major, @baseminor and @count. This function undoes what | ||
326 | * __register_chrdev() did. | ||
327 | */ | ||
328 | void __unregister_chrdev(unsigned int major, unsigned int baseminor, | ||
329 | unsigned int count, const char *name) | ||
320 | { | 330 | { |
321 | struct char_device_struct *cd; | 331 | struct char_device_struct *cd; |
322 | cd = __unregister_chrdev_region(major, 0, 256); | 332 | |
333 | cd = __unregister_chrdev_region(major, baseminor, count); | ||
323 | if (cd && cd->cdev) | 334 | if (cd && cd->cdev) |
324 | cdev_del(cd->cdev); | 335 | cdev_del(cd->cdev); |
325 | kfree(cd); | 336 | kfree(cd); |
@@ -568,6 +579,6 @@ EXPORT_SYMBOL(cdev_alloc); | |||
568 | EXPORT_SYMBOL(cdev_del); | 579 | EXPORT_SYMBOL(cdev_del); |
569 | EXPORT_SYMBOL(cdev_add); | 580 | EXPORT_SYMBOL(cdev_add); |
570 | EXPORT_SYMBOL(cdev_index); | 581 | EXPORT_SYMBOL(cdev_index); |
571 | EXPORT_SYMBOL(register_chrdev); | 582 | EXPORT_SYMBOL(__register_chrdev); |
572 | EXPORT_SYMBOL(unregister_chrdev); | 583 | EXPORT_SYMBOL(__unregister_chrdev); |
573 | EXPORT_SYMBOL(directly_mappable_cdev_bdi); | 584 | EXPORT_SYMBOL(directly_mappable_cdev_bdi); |