summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Viro <viro@www.linux.org.uk>2003-05-24 21:42:02 -0700
committerLinus Torvalds <torvalds@home.transmeta.com>2003-05-24 21:42:02 -0700
commit4460bbfdaec0d570c1e50cfa9b4d57ada50bb9db (patch)
treeca15d9e00d9eba44999c577eea8aeae9885f9325
parent106a92d12dc1fbe260b89d3783bcdf96a74656d3 (diff)
[PATCH] register_chrdev_region() cleanup
register_chrdev_region() sanitized, code in tty_io.c that dealt with it cleaned up.
-rw-r--r--drivers/char/tty_io.c73
-rw-r--r--fs/char_dev.c106
-rw-r--r--include/linux/fs.h9
3 files changed, 99 insertions, 89 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 4deacb6d95ed..ec5bd80e34ff 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -2242,53 +2242,6 @@ void tty_unregister_device(struct tty_driver *driver, unsigned index)
EXPORT_SYMBOL(tty_register_device);
EXPORT_SYMBOL(tty_unregister_device);
-/* that should be handled by register_chrdev_region() */
-static int get_range(struct tty_driver *driver)
-{
- dev_t from = MKDEV(driver->major, driver->minor_start);
- dev_t to = from + driver->num;
- dev_t n, next;
- int error = 0;
-
- for (n = from; MAJOR(n) < MAJOR(to); n = next) {
- next = MKDEV(MAJOR(n)+1, 0);
- error = register_chrdev_region(MAJOR(n), MINOR(n),
- next - n, driver->name, &tty_fops);
- if (error)
- goto fail;
- }
- if (n != to)
- error = register_chrdev_region(MAJOR(n), MINOR(n),
- to - n, driver->name, &tty_fops);
- if (!error)
- return 0;
-fail:
- to = n;
- for (n = from; MAJOR(n) < MAJOR(to); n = next) {
- next = MKDEV(MAJOR(n)+1, 0);
- unregister_chrdev_region(MAJOR(n), MINOR(n),
- next - n, driver->name);
- }
- return error;
-}
-
-/* that should be handled by unregister_chrdev_region() */
-static void put_range(struct tty_driver *driver)
-{
- dev_t from = MKDEV(driver->major, driver->minor_start);
- dev_t to = from + driver->num;
- dev_t n, next;
-
- for (n = from; MAJOR(n) < MAJOR(to); n = next) {
- next = MKDEV(MAJOR(n)+1, 0);
- unregister_chrdev_region(MAJOR(n), MINOR(n),
- next - n, driver->name);
- }
- if (n != to)
- unregister_chrdev_region(MAJOR(n), MINOR(n),
- to - n, driver->name);
-}
-
/*
* Called by a tty driver to register itself.
*/
@@ -2296,17 +2249,22 @@ int tty_register_driver(struct tty_driver *driver)
{
int error;
int i;
+ dev_t dev;
if (driver->flags & TTY_DRIVER_INSTALLED)
return 0;
if (!driver->major) {
- error = register_chrdev_region(0, driver->minor_start,
- driver->num, driver->name, &tty_fops);
- if (error > 0)
- driver->major = error;
+ error = alloc_chrdev_region(&dev, driver->num,
+ (char*)driver->name, &tty_fops);
+ if (!error) {
+ driver->major = MAJOR(dev);
+ driver->minor_start = MINOR(dev);
+ }
} else {
- error = get_range(driver);
+ dev = MKDEV(driver->major, driver->minor_start);
+ error = register_chrdev_region(dev, driver->num,
+ (char*)driver->name, &tty_fops);
}
if (error < 0)
return error;
@@ -2335,7 +2293,8 @@ int tty_unregister_driver(struct tty_driver *driver)
if (*driver->refcount)
return -EBUSY;
- put_range(driver);
+ unregister_chrdev_region(MKDEV(driver->major, driver->minor_start),
+ driver->num);
list_del(&driver->tty_drivers);
@@ -2412,20 +2371,20 @@ postcore_initcall(tty_class_init);
*/
void __init tty_init(void)
{
- if (register_chrdev_region(TTYAUX_MAJOR, 0, 1,
+ if (register_chrdev_region(MKDEV(TTYAUX_MAJOR, 0), 1,
"/dev/tty", &tty_fops) < 0)
panic("Couldn't register /dev/tty driver\n");
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 0), S_IFCHR|S_IRUGO|S_IWUGO, "tty");
tty_add_class_device ("tty", MKDEV(TTYAUX_MAJOR, 0), NULL);
- if (register_chrdev_region(TTYAUX_MAJOR, 1, 1,
+ if (register_chrdev_region(MKDEV(TTYAUX_MAJOR, 1), 1,
"/dev/console", &tty_fops) < 0)
panic("Couldn't register /dev/console driver\n");
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 1), S_IFCHR|S_IRUSR|S_IWUSR, "console");
tty_add_class_device ("console", MKDEV(TTYAUX_MAJOR, 1), NULL);
#ifdef CONFIG_UNIX98_PTYS
- if (register_chrdev_region(TTYAUX_MAJOR, 2, 1,
+ if (register_chrdev_region(MKDEV(TTYAUX_MAJOR, 2), 1,
"/dev/ptmx", &tty_fops) < 0)
panic("Couldn't register /dev/ptmx driver\n");
devfs_mk_cdev(MKDEV(TTYAUX_MAJOR, 2), S_IFCHR|S_IRUGO|S_IWUGO, "ptmx");
@@ -2433,7 +2392,7 @@ void __init tty_init(void)
#endif
#ifdef CONFIG_VT
- if (register_chrdev_region(TTY_MAJOR, 0, 1,
+ if (register_chrdev_region(MKDEV(TTY_MAJOR, 0), 1,
"/dev/vc/0", &tty_fops) < 0)
panic("Couldn't register /dev/tty0 driver\n");
devfs_mk_cdev(MKDEV(TTY_MAJOR, 0), S_IFCHR|S_IRUSR|S_IWUSR, "vc/0");
diff --git a/fs/char_dev.c b/fs/char_dev.c
index 2621ba46bf9d..f20b95221a02 100644
--- a/fs/char_dev.c
+++ b/fs/char_dev.c
@@ -123,7 +123,8 @@ get_chrfops(unsigned int major, unsigned int minor)
*
* Returns a -ve errno on failure.
*/
-int register_chrdev_region(unsigned int major, unsigned int baseminor,
+static struct char_device_struct *
+__register_chrdev_region(unsigned int major, unsigned int baseminor,
int minorct, const char *name,
struct file_operations *fops)
{
@@ -133,7 +134,7 @@ int register_chrdev_region(unsigned int major, unsigned int baseminor,
cd = kmalloc(sizeof(struct char_device_struct), GFP_KERNEL);
if (cd == NULL)
- return -ENOMEM;
+ return ERR_PTR(-ENOMEM);
write_lock_irq(&chrdevs_lock);
@@ -167,32 +168,23 @@ int register_chrdev_region(unsigned int major, unsigned int baseminor,
if (*cp && (*cp)->major == major &&
(*cp)->baseminor < baseminor + minorct) {
ret = -EBUSY;
- } else {
- cd->next = *cp;
- *cp = cd;
+ goto out;
}
+ cd->next = *cp;
+ *cp = cd;
+ write_unlock_irq(&chrdevs_lock);
+ return cd;
out:
write_unlock_irq(&chrdevs_lock);
- if (ret < 0)
- kfree(cd);
- return ret;
+ kfree(cd);
+ return ERR_PTR(ret);
}
-int register_chrdev(unsigned int major, const char *name,
- struct file_operations *fops)
+static struct char_device_struct *
+__unregister_chrdev_region(unsigned major, unsigned baseminor, int minorct)
{
- return register_chrdev_region(major, 0, 256, name, fops);
-}
-
-/* todo: make void - error printk here */
-int unregister_chrdev_region(unsigned int major, unsigned int baseminor,
- int minorct, const char *name)
-{
- struct char_device_struct *cd, **cp;
- int ret = 0;
- int i;
-
- i = major_to_index(major);
+ struct char_device_struct *cd = NULL, **cp;
+ int i = major_to_index(major);
write_lock_irq(&chrdevs_lock);
for (cp = &chrdevs[i]; *cp; cp = &(*cp)->next)
@@ -200,21 +192,79 @@ int unregister_chrdev_region(unsigned int major, unsigned int baseminor,
(*cp)->baseminor == baseminor &&
(*cp)->minorct == minorct)
break;
- if (!*cp || strcmp((*cp)->name, name))
- ret = -EINVAL;
- else {
+ if (*cp) {
cd = *cp;
*cp = cd->next;
- kfree(cd);
}
write_unlock_irq(&chrdevs_lock);
+ return cd;
+}
- return ret;
+int register_chrdev_region(dev_t from, unsigned count, char *name,
+ struct file_operations *fops)
+{
+ struct char_device_struct *cd;
+ dev_t to = from + count;
+ dev_t n, next;
+
+ for (n = from; n < to; n = next) {
+ next = MKDEV(MAJOR(n)+1, 0);
+ if (next > to)
+ next = to;
+ cd = __register_chrdev_region(MAJOR(n), MINOR(n),
+ next - n, name, fops);
+ if (IS_ERR(cd))
+ goto fail;
+ }
+ return 0;
+fail:
+ to = n;
+ for (n = from; n < to; n = next) {
+ next = MKDEV(MAJOR(n)+1, 0);
+ kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
+ }
+ return PTR_ERR(cd);
+}
+
+int alloc_chrdev_region(dev_t *dev, unsigned count, char *name,
+ struct file_operations *fops)
+{
+ struct char_device_struct *cd;
+ cd = __register_chrdev_region(0, 0, count, name, fops);
+ if (IS_ERR(cd))
+ return PTR_ERR(cd);
+ *dev = MKDEV(cd->major, cd->baseminor);
+ return 0;
+}
+
+int register_chrdev(unsigned int major, const char *name,
+ struct file_operations *fops)
+{
+ struct char_device_struct *cd;
+
+ cd = __register_chrdev_region(major, 0, 256, name, fops);
+ if (IS_ERR(cd))
+ return PTR_ERR(cd);
+ return cd->major;
+}
+
+void unregister_chrdev_region(dev_t from, unsigned count)
+{
+ dev_t to = from + count;
+ dev_t n, next;
+
+ for (n = from; n < to; n = next) {
+ next = MKDEV(MAJOR(n)+1, 0);
+ if (next > to)
+ next = to;
+ kfree(__unregister_chrdev_region(MAJOR(n), MINOR(n), next - n));
+ }
}
int unregister_chrdev(unsigned int major, const char *name)
{
- return unregister_chrdev_region(major, 0, 256, name);
+ kfree(__unregister_chrdev_region(major, 0, 256));
+ return 0;
}
/*
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 7365aef817b5..1b7fac010f1f 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -1056,13 +1056,14 @@ extern void bd_release(struct block_device *);
extern void blk_run_queues(void);
/* fs/char_dev.c */
-extern int register_chrdev_region(unsigned int, unsigned int, int,
- const char *, struct file_operations *);
+extern int alloc_chrdev_region(dev_t *, unsigned, char *,
+ struct file_operations *);
+extern int register_chrdev_region(dev_t, unsigned, char *,
+ struct file_operations *);
extern int register_chrdev(unsigned int, const char *,
struct file_operations *);
extern int unregister_chrdev(unsigned int, const char *);
-extern int unregister_chrdev_region(unsigned int, unsigned int, int,
- const char *);
+extern void unregister_chrdev_region(dev_t, unsigned);
extern int chrdev_open(struct inode *, struct file *);
/* fs/block_dev.c */