diff options
| -rw-r--r-- | drivers/char/tty_io.c | 15 | ||||
| -rw-r--r-- | drivers/usb/serial/usb-serial.c | 14 | ||||
| -rw-r--r-- | include/linux/tty_driver.h | 13 |
3 files changed, 27 insertions, 15 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c index ea18a129b0b5..59499ee0fe6a 100644 --- a/drivers/char/tty_io.c +++ b/drivers/char/tty_io.c | |||
| @@ -1389,7 +1389,7 @@ EXPORT_SYMBOL(tty_shutdown); | |||
| 1389 | * of ttys that the driver keeps. | 1389 | * of ttys that the driver keeps. |
| 1390 | * | 1390 | * |
| 1391 | * This method gets called from a work queue so that the driver private | 1391 | * This method gets called from a work queue so that the driver private |
| 1392 | * shutdown ops can sleep (needed for USB at least) | 1392 | * cleanup ops can sleep (needed for USB at least) |
| 1393 | */ | 1393 | */ |
| 1394 | static void release_one_tty(struct work_struct *work) | 1394 | static void release_one_tty(struct work_struct *work) |
| 1395 | { | 1395 | { |
| @@ -1397,10 +1397,9 @@ static void release_one_tty(struct work_struct *work) | |||
| 1397 | container_of(work, struct tty_struct, hangup_work); | 1397 | container_of(work, struct tty_struct, hangup_work); |
| 1398 | struct tty_driver *driver = tty->driver; | 1398 | struct tty_driver *driver = tty->driver; |
| 1399 | 1399 | ||
| 1400 | if (tty->ops->shutdown) | 1400 | if (tty->ops->cleanup) |
| 1401 | tty->ops->shutdown(tty); | 1401 | tty->ops->cleanup(tty); |
| 1402 | else | 1402 | |
| 1403 | tty_shutdown(tty); | ||
| 1404 | tty->magic = 0; | 1403 | tty->magic = 0; |
| 1405 | tty_driver_kref_put(driver); | 1404 | tty_driver_kref_put(driver); |
| 1406 | module_put(driver->owner); | 1405 | module_put(driver->owner); |
| @@ -1415,6 +1414,12 @@ static void release_one_tty(struct work_struct *work) | |||
| 1415 | static void queue_release_one_tty(struct kref *kref) | 1414 | static void queue_release_one_tty(struct kref *kref) |
| 1416 | { | 1415 | { |
| 1417 | struct tty_struct *tty = container_of(kref, struct tty_struct, kref); | 1416 | struct tty_struct *tty = container_of(kref, struct tty_struct, kref); |
| 1417 | |||
| 1418 | if (tty->ops->shutdown) | ||
| 1419 | tty->ops->shutdown(tty); | ||
| 1420 | else | ||
| 1421 | tty_shutdown(tty); | ||
| 1422 | |||
| 1418 | /* The hangup queue is now free so we can reuse it rather than | 1423 | /* The hangup queue is now free so we can reuse it rather than |
| 1419 | waste a chunk of memory for each port */ | 1424 | waste a chunk of memory for each port */ |
| 1420 | INIT_WORK(&tty->hangup_work, release_one_tty); | 1425 | INIT_WORK(&tty->hangup_work, release_one_tty); |
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c index ff75a3589e7e..aa6b2ae951ae 100644 --- a/drivers/usb/serial/usb-serial.c +++ b/drivers/usb/serial/usb-serial.c | |||
| @@ -192,7 +192,7 @@ void usb_serial_put(struct usb_serial *serial) | |||
| 192 | * This is the first place a new tty gets used. Hence this is where we | 192 | * This is the first place a new tty gets used. Hence this is where we |
| 193 | * acquire references to the usb_serial structure and the driver module, | 193 | * acquire references to the usb_serial structure and the driver module, |
| 194 | * where we store a pointer to the port, and where we do an autoresume. | 194 | * where we store a pointer to the port, and where we do an autoresume. |
| 195 | * All these actions are reversed in serial_release(). | 195 | * All these actions are reversed in serial_cleanup(). |
| 196 | */ | 196 | */ |
| 197 | static int serial_install(struct tty_driver *driver, struct tty_struct *tty) | 197 | static int serial_install(struct tty_driver *driver, struct tty_struct *tty) |
| 198 | { | 198 | { |
| @@ -339,15 +339,16 @@ static void serial_close(struct tty_struct *tty, struct file *filp) | |||
| 339 | } | 339 | } |
| 340 | 340 | ||
| 341 | /** | 341 | /** |
| 342 | * serial_release - free resources post close/hangup | 342 | * serial_cleanup - free resources post close/hangup |
| 343 | * @port: port to free up | 343 | * @port: port to free up |
| 344 | * | 344 | * |
| 345 | * Do the resource freeing and refcount dropping for the port. | 345 | * Do the resource freeing and refcount dropping for the port. |
| 346 | * Avoid freeing the console. | 346 | * Avoid freeing the console. |
| 347 | * | 347 | * |
| 348 | * Called when the last tty kref is dropped. | 348 | * Called asynchronously after the last tty kref is dropped, |
| 349 | * and the tty layer has already done the tty_shutdown(tty); | ||
| 349 | */ | 350 | */ |
| 350 | static void serial_release(struct tty_struct *tty) | 351 | static void serial_cleanup(struct tty_struct *tty) |
| 351 | { | 352 | { |
| 352 | struct usb_serial_port *port = tty->driver_data; | 353 | struct usb_serial_port *port = tty->driver_data; |
| 353 | struct usb_serial *serial; | 354 | struct usb_serial *serial; |
| @@ -361,9 +362,6 @@ static void serial_release(struct tty_struct *tty) | |||
| 361 | 362 | ||
| 362 | dbg("%s - port %d", __func__, port->number); | 363 | dbg("%s - port %d", __func__, port->number); |
| 363 | 364 | ||
| 364 | /* Standard shutdown processing */ | ||
| 365 | tty_shutdown(tty); | ||
| 366 | |||
| 367 | tty->driver_data = NULL; | 365 | tty->driver_data = NULL; |
| 368 | 366 | ||
| 369 | serial = port->serial; | 367 | serial = port->serial; |
| @@ -1210,7 +1208,7 @@ static const struct tty_operations serial_ops = { | |||
| 1210 | .chars_in_buffer = serial_chars_in_buffer, | 1208 | .chars_in_buffer = serial_chars_in_buffer, |
| 1211 | .tiocmget = serial_tiocmget, | 1209 | .tiocmget = serial_tiocmget, |
| 1212 | .tiocmset = serial_tiocmset, | 1210 | .tiocmset = serial_tiocmset, |
| 1213 | .shutdown = serial_release, | 1211 | .cleanup = serial_cleanup, |
| 1214 | .install = serial_install, | 1212 | .install = serial_install, |
| 1215 | .proc_fops = &serial_proc_fops, | 1213 | .proc_fops = &serial_proc_fops, |
| 1216 | }; | 1214 | }; |
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h index 3566129384a4..b08677982525 100644 --- a/include/linux/tty_driver.h +++ b/include/linux/tty_driver.h | |||
| @@ -45,8 +45,16 @@ | |||
| 45 | * | 45 | * |
| 46 | * void (*shutdown)(struct tty_struct * tty); | 46 | * void (*shutdown)(struct tty_struct * tty); |
| 47 | * | 47 | * |
| 48 | * This routine is called when a particular tty device is closed for | 48 | * This routine is called synchronously when a particular tty device |
| 49 | * the last time freeing up the resources. | 49 | * is closed for the last time freeing up the resources. |
| 50 | * | ||
| 51 | * | ||
| 52 | * void (*cleanup)(struct tty_struct * tty); | ||
| 53 | * | ||
| 54 | * This routine is called asynchronously when a particular tty device | ||
| 55 | * is closed for the last time freeing up the resources. This is | ||
| 56 | * actually the second part of shutdown for routines that might sleep. | ||
| 57 | * | ||
| 50 | * | 58 | * |
| 51 | * int (*write)(struct tty_struct * tty, | 59 | * int (*write)(struct tty_struct * tty, |
| 52 | * const unsigned char *buf, int count); | 60 | * const unsigned char *buf, int count); |
| @@ -233,6 +241,7 @@ struct tty_operations { | |||
| 233 | int (*open)(struct tty_struct * tty, struct file * filp); | 241 | int (*open)(struct tty_struct * tty, struct file * filp); |
| 234 | void (*close)(struct tty_struct * tty, struct file * filp); | 242 | void (*close)(struct tty_struct * tty, struct file * filp); |
| 235 | void (*shutdown)(struct tty_struct *tty); | 243 | void (*shutdown)(struct tty_struct *tty); |
| 244 | void (*cleanup)(struct tty_struct *tty); | ||
| 236 | int (*write)(struct tty_struct * tty, | 245 | int (*write)(struct tty_struct * tty, |
| 237 | const unsigned char *buf, int count); | 246 | const unsigned char *buf, int count); |
| 238 | int (*put_char)(struct tty_struct *tty, unsigned char ch); | 247 | int (*put_char)(struct tty_struct *tty, unsigned char ch); |
