aboutsummaryrefslogtreecommitdiffstats
path: root/fs/char_dev.c
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2011-01-13 01:06:28 -0500
committerPaul Mundt <lethal@linux-sh.org>2011-01-13 01:06:28 -0500
commitf43dc23d5ea91fca257be02138a255f02d98e806 (patch)
treeb29722f6e965316e90ac97abf79923ced250dc21 /fs/char_dev.c
parentf8e53553f452dcbf67cb89c8cba63a1cd6eb4cc0 (diff)
parent4162cf64973df51fc885825bc9ca4d055891c49f (diff)
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6 into common/serial-rework
Conflicts: arch/sh/kernel/cpu/sh2/setup-sh7619.c arch/sh/kernel/cpu/sh2a/setup-mxg.c arch/sh/kernel/cpu/sh2a/setup-sh7201.c arch/sh/kernel/cpu/sh2a/setup-sh7203.c arch/sh/kernel/cpu/sh2a/setup-sh7206.c arch/sh/kernel/cpu/sh3/setup-sh7705.c arch/sh/kernel/cpu/sh3/setup-sh770x.c arch/sh/kernel/cpu/sh3/setup-sh7710.c arch/sh/kernel/cpu/sh3/setup-sh7720.c arch/sh/kernel/cpu/sh4/setup-sh4-202.c arch/sh/kernel/cpu/sh4/setup-sh7750.c arch/sh/kernel/cpu/sh4/setup-sh7760.c arch/sh/kernel/cpu/sh4a/setup-sh7343.c arch/sh/kernel/cpu/sh4a/setup-sh7366.c arch/sh/kernel/cpu/sh4a/setup-sh7722.c arch/sh/kernel/cpu/sh4a/setup-sh7723.c arch/sh/kernel/cpu/sh4a/setup-sh7724.c arch/sh/kernel/cpu/sh4a/setup-sh7763.c arch/sh/kernel/cpu/sh4a/setup-sh7770.c arch/sh/kernel/cpu/sh4a/setup-sh7780.c arch/sh/kernel/cpu/sh4a/setup-sh7785.c arch/sh/kernel/cpu/sh4a/setup-sh7786.c arch/sh/kernel/cpu/sh4a/setup-shx3.c arch/sh/kernel/cpu/sh5/setup-sh5.c drivers/serial/sh-sci.c drivers/serial/sh-sci.h include/linux/serial_sci.h
Diffstat (limited to 'fs/char_dev.c')
-rw-r--r--fs/char_dev.c50
1 files changed, 32 insertions, 18 deletions
diff --git a/fs/char_dev.c b/fs/char_dev.c
index b7c9d5187a75..e5b9df993b93 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -13,7 +13,6 @@
13#include <linux/major.h> 13#include <linux/major.h>
14#include <linux/errno.h> 14#include <linux/errno.h>
15#include <linux/module.h> 15#include <linux/module.h>
16#include <linux/smp_lock.h>
17#include <linux/seq_file.h> 16#include <linux/seq_file.h>
18 17
19#include <linux/kobject.h> 18#include <linux/kobject.h>
@@ -21,6 +20,7 @@
21#include <linux/cdev.h> 20#include <linux/cdev.h>
22#include <linux/mutex.h> 21#include <linux/mutex.h>
23#include <linux/backing-dev.h> 22#include <linux/backing-dev.h>
23#include <linux/tty.h>
24 24
25#include "internal.h" 25#include "internal.h"
26 26
@@ -32,6 +32,7 @@
32 * - no readahead or I/O queue unplugging required 32 * - no readahead or I/O queue unplugging required
33 */ 33 */
34struct backing_dev_info directly_mappable_cdev_bdi = { 34struct backing_dev_info directly_mappable_cdev_bdi = {
35 .name = "char",
35 .capabilities = ( 36 .capabilities = (
36#ifdef CONFIG_MMU 37#ifdef CONFIG_MMU
37 /* permit private copies of the data to be taken */ 38 /* permit private copies of the data to be taken */
@@ -39,7 +40,9 @@ struct backing_dev_info directly_mappable_cdev_bdi = {
39#endif 40#endif
40 /* permit direct mmap, for read, write or exec */ 41 /* permit direct mmap, for read, write or exec */
41 BDI_CAP_MAP_DIRECT | 42 BDI_CAP_MAP_DIRECT |
42 BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP), 43 BDI_CAP_READ_MAP | BDI_CAP_WRITE_MAP | BDI_CAP_EXEC_MAP |
44 /* no writeback happens */
45 BDI_CAP_NO_ACCT_AND_WRITEBACK),
43}; 46};
44 47
45static struct kobj_map *cdev_map; 48static struct kobj_map *cdev_map;
@@ -238,8 +241,10 @@ int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
238} 241}
239 242
240/** 243/**
241 * register_chrdev() - Register a major number for character devices. 244 * __register_chrdev() - create and register a cdev occupying a range of minors
242 * @major: major device number or 0 for dynamic allocation 245 * @major: major device number or 0 for dynamic allocation
246 * @baseminor: first of the requested range of minor numbers
247 * @count: the number of minor numbers required
243 * @name: name of this range of devices 248 * @name: name of this range of devices
244 * @fops: file operations associated with this devices 249 * @fops: file operations associated with this devices
245 * 250 *
@@ -255,19 +260,16 @@ int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count,
255 * /dev. It only helps to keep track of the different owners of devices. If 260 * /dev. It only helps to keep track of the different owners of devices. If
256 * your module name has only one type of devices it's ok to use e.g. the name 261 * your module name has only one type of devices it's ok to use e.g. the name
257 * of the module here. 262 * of the module here.
258 *
259 * This function registers a range of 256 minor numbers. The first minor number
260 * is 0.
261 */ 263 */
262int register_chrdev(unsigned int major, const char *name, 264int __register_chrdev(unsigned int major, unsigned int baseminor,
263 const struct file_operations *fops) 265 unsigned int count, const char *name,
266 const struct file_operations *fops)
264{ 267{
265 struct char_device_struct *cd; 268 struct char_device_struct *cd;
266 struct cdev *cdev; 269 struct cdev *cdev;
267 char *s;
268 int err = -ENOMEM; 270 int err = -ENOMEM;
269 271
270 cd = __register_chrdev_region(major, 0, 256, name); 272 cd = __register_chrdev_region(major, baseminor, count, name);
271 if (IS_ERR(cd)) 273 if (IS_ERR(cd))
272 return PTR_ERR(cd); 274 return PTR_ERR(cd);
273 275
@@ -278,10 +280,8 @@ int register_chrdev(unsigned int major, const char *name,
278 cdev->owner = fops->owner; 280 cdev->owner = fops->owner;
279 cdev->ops = fops; 281 cdev->ops = fops;
280 kobject_set_name(&cdev->kobj, "%s", name); 282 kobject_set_name(&cdev->kobj, "%s", name);
281 for (s = strchr(kobject_name(&cdev->kobj),'/'); s; s = strchr(s, '/'))
282 *s = '!';
283 283
284 err = cdev_add(cdev, MKDEV(cd->major, 0), 256); 284 err = cdev_add(cdev, MKDEV(cd->major, baseminor), count);
285 if (err) 285 if (err)
286 goto out; 286 goto out;
287 287
@@ -291,7 +291,7 @@ int register_chrdev(unsigned int major, const char *name,
291out: 291out:
292 kobject_put(&cdev->kobj); 292 kobject_put(&cdev->kobj);
293out2: 293out2:
294 kfree(__unregister_chrdev_region(cd->major, 0, 256)); 294 kfree(__unregister_chrdev_region(cd->major, baseminor, count));
295 return err; 295 return err;
296} 296}
297 297
@@ -317,10 +317,23 @@ void unregister_chrdev_region(dev_t from, unsigned count)
317 } 317 }
318} 318}
319 319
320void unregister_chrdev(unsigned int major, const char *name) 320/**
321 * __unregister_chrdev - unregister and destroy a cdev
322 * @major: major device number
323 * @baseminor: first of the range of minor numbers
324 * @count: the number of minor numbers this cdev is occupying
325 * @name: name of this range of devices
326 *
327 * Unregister and destroy the cdev occupying the region described by
328 * @major, @baseminor and @count. This function undoes what
329 * __register_chrdev() did.
330 */
331void __unregister_chrdev(unsigned int major, unsigned int baseminor,
332 unsigned int count, const char *name)
321{ 333{
322 struct char_device_struct *cd; 334 struct char_device_struct *cd;
323 cd = __unregister_chrdev_region(major, 0, 256); 335
336 cd = __unregister_chrdev_region(major, baseminor, count);
324 if (cd && cd->cdev) 337 if (cd && cd->cdev)
325 cdev_del(cd->cdev); 338 cdev_del(cd->cdev);
326 kfree(cd); 339 kfree(cd);
@@ -443,6 +456,7 @@ static void cdev_purge(struct cdev *cdev)
443 */ 456 */
444const struct file_operations def_chr_fops = { 457const struct file_operations def_chr_fops = {
445 .open = chrdev_open, 458 .open = chrdev_open,
459 .llseek = noop_llseek,
446}; 460};
447 461
448static struct kobject *exact_match(dev_t dev, int *part, void *data) 462static struct kobject *exact_match(dev_t dev, int *part, void *data)
@@ -569,6 +583,6 @@ EXPORT_SYMBOL(cdev_alloc);
569EXPORT_SYMBOL(cdev_del); 583EXPORT_SYMBOL(cdev_del);
570EXPORT_SYMBOL(cdev_add); 584EXPORT_SYMBOL(cdev_add);
571EXPORT_SYMBOL(cdev_index); 585EXPORT_SYMBOL(cdev_index);
572EXPORT_SYMBOL(register_chrdev); 586EXPORT_SYMBOL(__register_chrdev);
573EXPORT_SYMBOL(unregister_chrdev); 587EXPORT_SYMBOL(__unregister_chrdev);
574EXPORT_SYMBOL(directly_mappable_cdev_bdi); 588EXPORT_SYMBOL(directly_mappable_cdev_bdi);