summaryrefslogtreecommitdiffstats
path: root/drivers/tty/tty_io.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-10-26 15:11:09 +0200
committerLinus Torvalds <torvalds@linux-foundation.org>2011-10-26 15:11:09 +0200
commitefb8d21b2c6db3497655cc6a033ae8a9883e4063 (patch)
treea14a0dbb9fec3a6db5e542ba7ed4a49681706420 /drivers/tty/tty_io.c
parent3cb603284b3d256ae9ae9e65887cee8416bfef15 (diff)
parentd208a3bf77f902283894f546b6b5383202cf7882 (diff)
downloadlinux-efb8d21b2c6db3497655cc6a033ae8a9883e4063.tar.gz
linux-efb8d21b2c6db3497655cc6a033ae8a9883e4063.tar.xz
linux-efb8d21b2c6db3497655cc6a033ae8a9883e4063.zip
Merge branch 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty
* 'tty-next' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty: (79 commits) TTY: serial_core: Fix crash if DCD drop during suspend tty/serial: atmel_serial: bootconsole removed from auto-enumerates Revert "TTY: call tty_driver_lookup_tty unconditionally" tty/serial: atmel_serial: add device tree support tty/serial: atmel_serial: auto-enumerate ports tty/serial: atmel_serial: whitespace and braces modifications tty/serial: atmel_serial: change platform_data variable name tty/serial: RS485 bindings for device tree TTY: call tty_driver_lookup_tty unconditionally TTY: pty, release tty in all ptmx_open fail paths TTY: make tty_add_file non-failing TTY: drop driver reference in tty_open fail path 8250_pci: Fix kernel panic when pch_uart is disabled h8300: drivers/serial/Kconfig was moved parport_pc: release IO region properly if unsupported ITE887x card is found tty: Support compat_ioctl get/set termios_locked hvc_console: display printk messages on console. TTY: snyclinkmp: forever loop in tx_load_dma_buffer() tty/n_gsm: avoid fifo overflow in gsm_dlci_data_output tty/n_gsm: fix a bug in gsm_dlci_data_output (adaption = 2 case) ... Fix up Conflicts in: - drivers/tty/serial/8250_pci.c Trivial conflict with removed duplicate device ID - drivers/tty/serial/atmel_serial.c Annoying silly conflict between "specify the port num via platform_data" and other changes to atmel_console_init
Diffstat (limited to 'drivers/tty/tty_io.c')
-rw-r--r--drivers/tty/tty_io.c50
1 files changed, 38 insertions, 12 deletions
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 4f1fc81112e6..05085beb83db 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -194,8 +194,7 @@ static inline struct tty_struct *file_tty(struct file *file)
return ((struct tty_file_private *)file->private_data)->tty;
}
-/* Associate a new file with the tty structure */
-int tty_add_file(struct tty_struct *tty, struct file *file)
+int tty_alloc_file(struct file *file)
{
struct tty_file_private *priv;
@@ -203,15 +202,36 @@ int tty_add_file(struct tty_struct *tty, struct file *file)
if (!priv)
return -ENOMEM;
+ file->private_data = priv;
+
+ return 0;
+}
+
+/* Associate a new file with the tty structure */
+void tty_add_file(struct tty_struct *tty, struct file *file)
+{
+ struct tty_file_private *priv = file->private_data;
+
priv->tty = tty;
priv->file = file;
- file->private_data = priv;
spin_lock(&tty_files_lock);
list_add(&priv->list, &tty->tty_files);
spin_unlock(&tty_files_lock);
+}
- return 0;
+/**
+ * tty_free_file - free file->private_data
+ *
+ * This shall be used only for fail path handling when tty_add_file was not
+ * called yet.
+ */
+void tty_free_file(struct file *file)
+{
+ struct tty_file_private *priv = file->private_data;
+
+ file->private_data = NULL;
+ kfree(priv);
}
/* Delete file from its tty */
@@ -222,8 +242,7 @@ void tty_del_file(struct file *file)
spin_lock(&tty_files_lock);
list_del(&priv->list);
spin_unlock(&tty_files_lock);
- file->private_data = NULL;
- kfree(priv);
+ tty_free_file(file);
}
@@ -1811,6 +1830,10 @@ static int tty_open(struct inode *inode, struct file *filp)
nonseekable_open(inode, filp);
retry_open:
+ retval = tty_alloc_file(filp);
+ if (retval)
+ return -ENOMEM;
+
noctty = filp->f_flags & O_NOCTTY;
index = -1;
retval = 0;
@@ -1823,6 +1846,7 @@ retry_open:
if (!tty) {
tty_unlock();
mutex_unlock(&tty_mutex);
+ tty_free_file(filp);
return -ENXIO;
}
driver = tty_driver_kref_get(tty->driver);
@@ -1855,6 +1879,7 @@ retry_open:
}
tty_unlock();
mutex_unlock(&tty_mutex);
+ tty_free_file(filp);
return -ENODEV;
}
@@ -1862,6 +1887,7 @@ retry_open:
if (!driver) {
tty_unlock();
mutex_unlock(&tty_mutex);
+ tty_free_file(filp);
return -ENODEV;
}
got_driver:
@@ -1872,6 +1898,8 @@ got_driver:
if (IS_ERR(tty)) {
tty_unlock();
mutex_unlock(&tty_mutex);
+ tty_driver_kref_put(driver);
+ tty_free_file(filp);
return PTR_ERR(tty);
}
}
@@ -1887,15 +1915,11 @@ got_driver:
tty_driver_kref_put(driver);
if (IS_ERR(tty)) {
tty_unlock();
+ tty_free_file(filp);
return PTR_ERR(tty);
}
- retval = tty_add_file(tty, filp);
- if (retval) {
- tty_unlock();
- tty_release(inode, filp);
- return retval;
- }
+ tty_add_file(tty, filp);
check_tty_count(tty, "tty_open");
if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
@@ -2716,6 +2740,8 @@ static long tty_compat_ioctl(struct file *file, unsigned int cmd,
ld = tty_ldisc_ref_wait(tty);
if (ld->ops->compat_ioctl)
retval = ld->ops->compat_ioctl(tty, file, cmd, arg);
+ else
+ retval = n_tty_compat_ioctl_helper(tty, file, cmd, arg);
tty_ldisc_deref(ld);
return retval;