diff options
author | Jiri Slaby <jslaby@suse.cz> | 2012-08-08 16:26:42 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2012-08-13 19:45:38 -0400 |
commit | 16a02081baa15becdb7d6460659e7832e6524d93 (patch) | |
tree | 8bd34de93db9a2c225241b1dedf7394baaa6819e /drivers/tty/tty_io.c | |
parent | 21aca2fa00259f781d228496631b61dbb4274e90 (diff) |
TTY: move allocations to tty_alloc_driver
So now, that we have flags and know everything needed, keep a promise
and move all the tables and ports allocation from tty_register_driver
to tty_alloc_driver.
Not only that it makes sense, but we need this for
tty_port_link_device which needs tty_driver->ports but is to be called
before tty_register_driver.
Signed-off-by: Jiri Slaby <jslaby@suse.cz>
Acked-by: Alan Cox <alan@linux.intel.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/tty/tty_io.c')
-rw-r--r-- | drivers/tty/tty_io.c | 73 |
1 files changed, 33 insertions, 40 deletions
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c index 098a7c72b640..a67609b9f21b 100644 --- a/drivers/tty/tty_io.c +++ b/drivers/tty/tty_io.c | |||
@@ -3074,6 +3074,7 @@ struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner, | |||
3074 | unsigned long flags) | 3074 | unsigned long flags) |
3075 | { | 3075 | { |
3076 | struct tty_driver *driver; | 3076 | struct tty_driver *driver; |
3077 | int err; | ||
3077 | 3078 | ||
3078 | if (!lines) | 3079 | if (!lines) |
3079 | return ERR_PTR(-EINVAL); | 3080 | return ERR_PTR(-EINVAL); |
@@ -3087,9 +3088,34 @@ struct tty_driver *__tty_alloc_driver(unsigned int lines, struct module *owner, | |||
3087 | driver->num = lines; | 3088 | driver->num = lines; |
3088 | driver->owner = owner; | 3089 | driver->owner = owner; |
3089 | driver->flags = flags; | 3090 | driver->flags = flags; |
3090 | /* later we'll move allocation of tables here */ | 3091 | |
3092 | if (!(flags & TTY_DRIVER_DEVPTS_MEM)) { | ||
3093 | driver->ttys = kcalloc(lines, sizeof(*driver->ttys), | ||
3094 | GFP_KERNEL); | ||
3095 | driver->termios = kcalloc(lines, sizeof(*driver->termios), | ||
3096 | GFP_KERNEL); | ||
3097 | if (!driver->ttys || !driver->termios) { | ||
3098 | err = -ENOMEM; | ||
3099 | goto err_free_all; | ||
3100 | } | ||
3101 | } | ||
3102 | |||
3103 | if (!(flags & TTY_DRIVER_DYNAMIC_ALLOC)) { | ||
3104 | driver->ports = kcalloc(lines, sizeof(*driver->ports), | ||
3105 | GFP_KERNEL); | ||
3106 | if (!driver->ports) { | ||
3107 | err = -ENOMEM; | ||
3108 | goto err_free_all; | ||
3109 | } | ||
3110 | } | ||
3091 | 3111 | ||
3092 | return driver; | 3112 | return driver; |
3113 | err_free_all: | ||
3114 | kfree(driver->ports); | ||
3115 | kfree(driver->ttys); | ||
3116 | kfree(driver->termios); | ||
3117 | kfree(driver); | ||
3118 | return ERR_PTR(err); | ||
3093 | } | 3119 | } |
3094 | EXPORT_SYMBOL(__tty_alloc_driver); | 3120 | EXPORT_SYMBOL(__tty_alloc_driver); |
3095 | 3121 | ||
@@ -3098,7 +3124,6 @@ static void destruct_tty_driver(struct kref *kref) | |||
3098 | struct tty_driver *driver = container_of(kref, struct tty_driver, kref); | 3124 | struct tty_driver *driver = container_of(kref, struct tty_driver, kref); |
3099 | int i; | 3125 | int i; |
3100 | struct ktermios *tp; | 3126 | struct ktermios *tp; |
3101 | void *p; | ||
3102 | 3127 | ||
3103 | if (driver->flags & TTY_DRIVER_INSTALLED) { | 3128 | if (driver->flags & TTY_DRIVER_INSTALLED) { |
3104 | /* | 3129 | /* |
@@ -3115,14 +3140,12 @@ static void destruct_tty_driver(struct kref *kref) | |||
3115 | if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) | 3140 | if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) |
3116 | tty_unregister_device(driver, i); | 3141 | tty_unregister_device(driver, i); |
3117 | } | 3142 | } |
3118 | p = driver->ttys; | ||
3119 | proc_tty_unregister_driver(driver); | 3143 | proc_tty_unregister_driver(driver); |
3120 | driver->ttys = NULL; | ||
3121 | driver->termios = NULL; | ||
3122 | kfree(p); | ||
3123 | cdev_del(&driver->cdev); | 3144 | cdev_del(&driver->cdev); |
3124 | } | 3145 | } |
3125 | kfree(driver->ports); | 3146 | kfree(driver->ports); |
3147 | kfree(driver->termios); | ||
3148 | kfree(driver->ttys); | ||
3126 | kfree(driver); | 3149 | kfree(driver); |
3127 | } | 3150 | } |
3128 | 3151 | ||
@@ -3153,27 +3176,8 @@ int tty_register_driver(struct tty_driver *driver) | |||
3153 | int error; | 3176 | int error; |
3154 | int i; | 3177 | int i; |
3155 | dev_t dev; | 3178 | dev_t dev; |
3156 | void **p = NULL; | ||
3157 | struct device *d; | 3179 | struct device *d; |
3158 | 3180 | ||
3159 | if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) { | ||
3160 | p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL); | ||
3161 | if (!p) | ||
3162 | return -ENOMEM; | ||
3163 | } | ||
3164 | /* | ||
3165 | * There is too many lines in PTY and we won't need the array there | ||
3166 | * since it has an ->install hook where it assigns ports properly. | ||
3167 | */ | ||
3168 | if (driver->type != TTY_DRIVER_TYPE_PTY) { | ||
3169 | driver->ports = kcalloc(driver->num, sizeof(struct tty_port *), | ||
3170 | GFP_KERNEL); | ||
3171 | if (!driver->ports) { | ||
3172 | error = -ENOMEM; | ||
3173 | goto err_free_p; | ||
3174 | } | ||
3175 | } | ||
3176 | |||
3177 | if (!driver->major) { | 3181 | if (!driver->major) { |
3178 | error = alloc_chrdev_region(&dev, driver->minor_start, | 3182 | error = alloc_chrdev_region(&dev, driver->minor_start, |
3179 | driver->num, driver->name); | 3183 | driver->num, driver->name); |
@@ -3186,15 +3190,7 @@ int tty_register_driver(struct tty_driver *driver) | |||
3186 | error = register_chrdev_region(dev, driver->num, driver->name); | 3190 | error = register_chrdev_region(dev, driver->num, driver->name); |
3187 | } | 3191 | } |
3188 | if (error < 0) | 3192 | if (error < 0) |
3189 | goto err_free_p; | 3193 | goto err; |
3190 | |||
3191 | if (p) { | ||
3192 | driver->ttys = (struct tty_struct **)p; | ||
3193 | driver->termios = (struct ktermios **)(p + driver->num); | ||
3194 | } else { | ||
3195 | driver->ttys = NULL; | ||
3196 | driver->termios = NULL; | ||
3197 | } | ||
3198 | 3194 | ||
3199 | cdev_init(&driver->cdev, &tty_fops); | 3195 | cdev_init(&driver->cdev, &tty_fops); |
3200 | driver->cdev.owner = driver->owner; | 3196 | driver->cdev.owner = driver->owner; |
@@ -3211,7 +3207,7 @@ int tty_register_driver(struct tty_driver *driver) | |||
3211 | d = tty_register_device(driver, i, NULL); | 3207 | d = tty_register_device(driver, i, NULL); |
3212 | if (IS_ERR(d)) { | 3208 | if (IS_ERR(d)) { |
3213 | error = PTR_ERR(d); | 3209 | error = PTR_ERR(d); |
3214 | goto err; | 3210 | goto err_unreg_devs; |
3215 | } | 3211 | } |
3216 | } | 3212 | } |
3217 | } | 3213 | } |
@@ -3219,7 +3215,7 @@ int tty_register_driver(struct tty_driver *driver) | |||
3219 | driver->flags |= TTY_DRIVER_INSTALLED; | 3215 | driver->flags |= TTY_DRIVER_INSTALLED; |
3220 | return 0; | 3216 | return 0; |
3221 | 3217 | ||
3222 | err: | 3218 | err_unreg_devs: |
3223 | for (i--; i >= 0; i--) | 3219 | for (i--; i >= 0; i--) |
3224 | tty_unregister_device(driver, i); | 3220 | tty_unregister_device(driver, i); |
3225 | 3221 | ||
@@ -3229,10 +3225,7 @@ err: | |||
3229 | 3225 | ||
3230 | err_unreg_char: | 3226 | err_unreg_char: |
3231 | unregister_chrdev_region(dev, driver->num); | 3227 | unregister_chrdev_region(dev, driver->num); |
3232 | driver->ttys = NULL; | 3228 | err: |
3233 | driver->termios = NULL; | ||
3234 | err_free_p: /* destruct_tty_driver will free driver->ports */ | ||
3235 | kfree(p); | ||
3236 | return error; | 3229 | return error; |
3237 | } | 3230 | } |
3238 | EXPORT_SYMBOL(tty_register_driver); | 3231 | EXPORT_SYMBOL(tty_register_driver); |