aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-10-22 22:59:04 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2010-10-22 22:59:04 -0400
commit73ecf3a6e3f0206bf56a0fefe3b3eda042fb7034 (patch)
tree866f0ebb2b148479e93b5ac955097b1cc94ceb4e /drivers/char
parentb9da0571050c09863e59f94d0b8594a290d61b88 (diff)
parentcd3ecad19aea8debae9a48b53de2ec7a571f24e9 (diff)
Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6
* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6: (49 commits) serial8250: ratelimit "too much work" error serial: bfin_sport_uart: speed up sport RX sample rate to be 3% faster serial: abstraction for 8250 legacy ports serial/imx: check that the buffer is non-empty before sending it out serial: mfd: add more baud rates support jsm: Remove the uart port on errors Alchemy: Add UART PM methods. 8250: allow platforms to override PM hook. altera_uart: Don't use plain integer as NULL pointer altera_uart: Fix missing prototype for registering an early console altera_uart: Fixup type usage of port flags altera_uart: Make it possible to use Altera UART and 8250 ports together altera_uart: Add support for different address strides altera_uart: Add support for getting mapbase and IRQ from resources altera_uart: Add support for polling mode (IRQ-less) serial: Factor out uart_poll_timeout() from 8250 driver serial: mark the 8250 driver as maintained serial: 8250: Don't delay after transmitter is ready. tty: MAINTAINERS: add drivers/serial/jsm/ as maintained driver vcs: invoke the vt update callback when /dev/vcs* is written to ...
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/Kconfig15
-rw-r--r--drivers/char/Makefile1
-rw-r--r--drivers/char/amiserial.c56
-rw-r--r--drivers/char/cyclades.c49
-rw-r--r--drivers/char/ip2/ip2main.c72
-rw-r--r--drivers/char/mxser.c109
-rw-r--r--drivers/char/nozomi.c37
-rw-r--r--drivers/char/pcmcia/synclink_cs.c60
-rw-r--r--drivers/char/pty.c4
-rw-r--r--drivers/char/synclink.c73
-rw-r--r--drivers/char/synclink_gt.c55
-rw-r--r--drivers/char/synclinkmp.c61
-rw-r--r--drivers/char/tty_io.c77
-rw-r--r--drivers/char/ttyprintk.c225
-rw-r--r--drivers/char/vc_screen.c135
-rw-r--r--drivers/char/vt.c5
16 files changed, 748 insertions, 286 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index 3d44ec724c17..43d3395325c5 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -493,6 +493,21 @@ config LEGACY_PTY_COUNT
493 When not in use, each legacy PTY occupies 12 bytes on 32-bit 493 When not in use, each legacy PTY occupies 12 bytes on 32-bit
494 architectures and 24 bytes on 64-bit architectures. 494 architectures and 24 bytes on 64-bit architectures.
495 495
496config TTY_PRINTK
497 bool "TTY driver to output user messages via printk"
498 depends on EMBEDDED
499 default n
500 ---help---
501 If you say Y here, the support for writing user messages (i.e.
502 console messages) via printk is available.
503
504 The feature is useful to inline user messages with kernel
505 messages.
506 In order to use this feature, you should output user messages
507 to /dev/ttyprintk or redirect console to this TTY.
508
509 If unsure, say N.
510
496config BRIQ_PANEL 511config BRIQ_PANEL
497 tristate 'Total Impact briQ front panel driver' 512 tristate 'Total Impact briQ front panel driver'
498 depends on PPC_CHRP 513 depends on PPC_CHRP
diff --git a/drivers/char/Makefile b/drivers/char/Makefile
index dc9641660605..3a9c01416839 100644
--- a/drivers/char/Makefile
+++ b/drivers/char/Makefile
@@ -12,6 +12,7 @@ obj-y += mem.o random.o tty_io.o n_tty.o tty_ioctl.o tty_ldisc.o tty_buffer.o t
12obj-y += tty_mutex.o 12obj-y += tty_mutex.o
13obj-$(CONFIG_LEGACY_PTYS) += pty.o 13obj-$(CONFIG_LEGACY_PTYS) += pty.o
14obj-$(CONFIG_UNIX98_PTYS) += pty.o 14obj-$(CONFIG_UNIX98_PTYS) += pty.o
15obj-$(CONFIG_TTY_PRINTK) += ttyprintk.o
15obj-y += misc.o 16obj-y += misc.o
16obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o selection.o keyboard.o 17obj-$(CONFIG_VT) += vt_ioctl.o vc_screen.o selection.o keyboard.o
17obj-$(CONFIG_BFIN_JTAG_COMM) += bfin_jtag_comm.o 18obj-$(CONFIG_BFIN_JTAG_COMM) += bfin_jtag_comm.o
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index a11c8c9ca3d4..b0a70461a12c 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -1263,6 +1263,36 @@ static int rs_break(struct tty_struct *tty, int break_state)
1263 return 0; 1263 return 0;
1264} 1264}
1265 1265
1266/*
1267 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
1268 * Return: write counters to the user passed counter struct
1269 * NB: both 1->0 and 0->1 transitions are counted except for
1270 * RI where only 0->1 is counted.
1271 */
1272static int rs_get_icount(struct tty_struct *tty,
1273 struct serial_icounter_struct *icount)
1274{
1275 struct async_struct *info = tty->driver_data;
1276 struct async_icount cnow;
1277 unsigned long flags;
1278
1279 local_irq_save(flags);
1280 cnow = info->state->icount;
1281 local_irq_restore(flags);
1282 icount->cts = cnow.cts;
1283 icount->dsr = cnow.dsr;
1284 icount->rng = cnow.rng;
1285 icount->dcd = cnow.dcd;
1286 icount->rx = cnow.rx;
1287 icount->tx = cnow.tx;
1288 icount->frame = cnow.frame;
1289 icount->overrun = cnow.overrun;
1290 icount->parity = cnow.parity;
1291 icount->brk = cnow.brk;
1292 icount->buf_overrun = cnow.buf_overrun;
1293
1294 return 0;
1295}
1266 1296
1267static int rs_ioctl(struct tty_struct *tty, struct file * file, 1297static int rs_ioctl(struct tty_struct *tty, struct file * file,
1268 unsigned int cmd, unsigned long arg) 1298 unsigned int cmd, unsigned long arg)
@@ -1332,31 +1362,6 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
1332 } 1362 }
1333 /* NOTREACHED */ 1363 /* NOTREACHED */
1334 1364
1335 /*
1336 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
1337 * Return: write counters to the user passed counter struct
1338 * NB: both 1->0 and 0->1 transitions are counted except for
1339 * RI where only 0->1 is counted.
1340 */
1341 case TIOCGICOUNT:
1342 local_irq_save(flags);
1343 cnow = info->state->icount;
1344 local_irq_restore(flags);
1345 icount.cts = cnow.cts;
1346 icount.dsr = cnow.dsr;
1347 icount.rng = cnow.rng;
1348 icount.dcd = cnow.dcd;
1349 icount.rx = cnow.rx;
1350 icount.tx = cnow.tx;
1351 icount.frame = cnow.frame;
1352 icount.overrun = cnow.overrun;
1353 icount.parity = cnow.parity;
1354 icount.brk = cnow.brk;
1355 icount.buf_overrun = cnow.buf_overrun;
1356
1357 if (copy_to_user(argp, &icount, sizeof(icount)))
1358 return -EFAULT;
1359 return 0;
1360 case TIOCSERGWILD: 1365 case TIOCSERGWILD:
1361 case TIOCSERSWILD: 1366 case TIOCSERSWILD:
1362 /* "setserial -W" is called in Debian boot */ 1367 /* "setserial -W" is called in Debian boot */
@@ -1958,6 +1963,7 @@ static const struct tty_operations serial_ops = {
1958 .wait_until_sent = rs_wait_until_sent, 1963 .wait_until_sent = rs_wait_until_sent,
1959 .tiocmget = rs_tiocmget, 1964 .tiocmget = rs_tiocmget,
1960 .tiocmset = rs_tiocmset, 1965 .tiocmset = rs_tiocmset,
1966 .get_icount = rs_get_icount,
1961 .proc_fops = &rs_proc_fops, 1967 .proc_fops = &rs_proc_fops,
1962}; 1968};
1963 1969
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index 27aad9422332..4f152c28f40e 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -2790,29 +2790,6 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
2790 * NB: both 1->0 and 0->1 transitions are counted except for 2790 * NB: both 1->0 and 0->1 transitions are counted except for
2791 * RI where only 0->1 is counted. 2791 * RI where only 0->1 is counted.
2792 */ 2792 */
2793 case TIOCGICOUNT: {
2794 struct serial_icounter_struct sic = { };
2795
2796 spin_lock_irqsave(&info->card->card_lock, flags);
2797 cnow = info->icount;
2798 spin_unlock_irqrestore(&info->card->card_lock, flags);
2799
2800 sic.cts = cnow.cts;
2801 sic.dsr = cnow.dsr;
2802 sic.rng = cnow.rng;
2803 sic.dcd = cnow.dcd;
2804 sic.rx = cnow.rx;
2805 sic.tx = cnow.tx;
2806 sic.frame = cnow.frame;
2807 sic.overrun = cnow.overrun;
2808 sic.parity = cnow.parity;
2809 sic.brk = cnow.brk;
2810 sic.buf_overrun = cnow.buf_overrun;
2811
2812 if (copy_to_user(argp, &sic, sizeof(sic)))
2813 ret_val = -EFAULT;
2814 break;
2815 }
2816 default: 2793 default:
2817 ret_val = -ENOIOCTLCMD; 2794 ret_val = -ENOIOCTLCMD;
2818 } 2795 }
@@ -2823,6 +2800,31 @@ cy_ioctl(struct tty_struct *tty, struct file *file,
2823 return ret_val; 2800 return ret_val;
2824} /* cy_ioctl */ 2801} /* cy_ioctl */
2825 2802
2803static int cy_get_icount(struct tty_struct *tty,
2804 struct serial_icounter_struct *sic)
2805{
2806 struct cyclades_port *info = tty->driver_data;
2807 struct cyclades_icount cnow; /* Used to snapshot */
2808 unsigned long flags;
2809
2810 spin_lock_irqsave(&info->card->card_lock, flags);
2811 cnow = info->icount;
2812 spin_unlock_irqrestore(&info->card->card_lock, flags);
2813
2814 sic->cts = cnow.cts;
2815 sic->dsr = cnow.dsr;
2816 sic->rng = cnow.rng;
2817 sic->dcd = cnow.dcd;
2818 sic->rx = cnow.rx;
2819 sic->tx = cnow.tx;
2820 sic->frame = cnow.frame;
2821 sic->overrun = cnow.overrun;
2822 sic->parity = cnow.parity;
2823 sic->brk = cnow.brk;
2824 sic->buf_overrun = cnow.buf_overrun;
2825 return 0;
2826}
2827
2826/* 2828/*
2827 * This routine allows the tty driver to be notified when 2829 * This routine allows the tty driver to be notified when
2828 * device's termios settings have changed. Note that a 2830 * device's termios settings have changed. Note that a
@@ -4084,6 +4086,7 @@ static const struct tty_operations cy_ops = {
4084 .wait_until_sent = cy_wait_until_sent, 4086 .wait_until_sent = cy_wait_until_sent,
4085 .tiocmget = cy_tiocmget, 4087 .tiocmget = cy_tiocmget,
4086 .tiocmset = cy_tiocmset, 4088 .tiocmset = cy_tiocmset,
4089 .get_icount = cy_get_icount,
4087 .proc_fops = &cyclades_proc_fops, 4090 .proc_fops = &cyclades_proc_fops,
4088}; 4091};
4089 4092
diff --git a/drivers/char/ip2/ip2main.c b/drivers/char/ip2/ip2main.c
index 64a439ce2f89..fcd02baa7d65 100644
--- a/drivers/char/ip2/ip2main.c
+++ b/drivers/char/ip2/ip2main.c
@@ -184,6 +184,8 @@ static void ip2_hangup(PTTY);
184static int ip2_tiocmget(struct tty_struct *tty, struct file *file); 184static int ip2_tiocmget(struct tty_struct *tty, struct file *file);
185static int ip2_tiocmset(struct tty_struct *tty, struct file *file, 185static int ip2_tiocmset(struct tty_struct *tty, struct file *file,
186 unsigned int set, unsigned int clear); 186 unsigned int set, unsigned int clear);
187static int ip2_get_icount(struct tty_struct *tty,
188 struct serial_icounter_struct *icount);
187 189
188static void set_irq(int, int); 190static void set_irq(int, int);
189static void ip2_interrupt_bh(struct work_struct *work); 191static void ip2_interrupt_bh(struct work_struct *work);
@@ -456,6 +458,7 @@ static const struct tty_operations ip2_ops = {
456 .hangup = ip2_hangup, 458 .hangup = ip2_hangup,
457 .tiocmget = ip2_tiocmget, 459 .tiocmget = ip2_tiocmget,
458 .tiocmset = ip2_tiocmset, 460 .tiocmset = ip2_tiocmset,
461 .get_icount = ip2_get_icount,
459 .proc_fops = &ip2_proc_fops, 462 .proc_fops = &ip2_proc_fops,
460}; 463};
461 464
@@ -2130,7 +2133,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
2130 i2ChanStrPtr pCh = DevTable[tty->index]; 2133 i2ChanStrPtr pCh = DevTable[tty->index];
2131 i2eBordStrPtr pB; 2134 i2eBordStrPtr pB;
2132 struct async_icount cprev, cnow; /* kernel counter temps */ 2135 struct async_icount cprev, cnow; /* kernel counter temps */
2133 struct serial_icounter_struct __user *p_cuser;
2134 int rc = 0; 2136 int rc = 0;
2135 unsigned long flags; 2137 unsigned long flags;
2136 void __user *argp = (void __user *)arg; 2138 void __user *argp = (void __user *)arg;
@@ -2299,34 +2301,6 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
2299 break; 2301 break;
2300 2302
2301 /* 2303 /*
2302 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
2303 * Return: write counters to the user passed counter struct
2304 * NB: both 1->0 and 0->1 transitions are counted except for RI where
2305 * only 0->1 is counted. The controller is quite capable of counting
2306 * both, but this done to preserve compatibility with the standard
2307 * serial driver.
2308 */
2309 case TIOCGICOUNT:
2310 ip2trace (CHANN, ITRC_IOCTL, 11, 1, rc );
2311
2312 write_lock_irqsave(&pB->read_fifo_spinlock, flags);
2313 cnow = pCh->icount;
2314 write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
2315 p_cuser = argp;
2316 rc = put_user(cnow.cts, &p_cuser->cts);
2317 rc = put_user(cnow.dsr, &p_cuser->dsr);
2318 rc = put_user(cnow.rng, &p_cuser->rng);
2319 rc = put_user(cnow.dcd, &p_cuser->dcd);
2320 rc = put_user(cnow.rx, &p_cuser->rx);
2321 rc = put_user(cnow.tx, &p_cuser->tx);
2322 rc = put_user(cnow.frame, &p_cuser->frame);
2323 rc = put_user(cnow.overrun, &p_cuser->overrun);
2324 rc = put_user(cnow.parity, &p_cuser->parity);
2325 rc = put_user(cnow.brk, &p_cuser->brk);
2326 rc = put_user(cnow.buf_overrun, &p_cuser->buf_overrun);
2327 break;
2328
2329 /*
2330 * The rest are not supported by this driver. By returning -ENOIOCTLCMD they 2304 * The rest are not supported by this driver. By returning -ENOIOCTLCMD they
2331 * will be passed to the line discipline for it to handle. 2305 * will be passed to the line discipline for it to handle.
2332 */ 2306 */
@@ -2350,6 +2324,46 @@ ip2_ioctl ( PTTY tty, struct file *pFile, UINT cmd, ULONG arg )
2350 return rc; 2324 return rc;
2351} 2325}
2352 2326
2327static int ip2_get_icount(struct tty_struct *tty,
2328 struct serial_icounter_struct *icount)
2329{
2330 i2ChanStrPtr pCh = DevTable[tty->index];
2331 i2eBordStrPtr pB;
2332 struct async_icount cnow; /* kernel counter temp */
2333 unsigned long flags;
2334
2335 if ( pCh == NULL )
2336 return -ENODEV;
2337
2338 pB = pCh->pMyBord;
2339
2340 /*
2341 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
2342 * Return: write counters to the user passed counter struct
2343 * NB: both 1->0 and 0->1 transitions are counted except for RI where
2344 * only 0->1 is counted. The controller is quite capable of counting
2345 * both, but this done to preserve compatibility with the standard
2346 * serial driver.
2347 */
2348
2349 write_lock_irqsave(&pB->read_fifo_spinlock, flags);
2350 cnow = pCh->icount;
2351 write_unlock_irqrestore(&pB->read_fifo_spinlock, flags);
2352
2353 icount->cts = cnow.cts;
2354 icount->dsr = cnow.dsr;
2355 icount->rng = cnow.rng;
2356 icount->dcd = cnow.dcd;
2357 icount->rx = cnow.rx;
2358 icount->tx = cnow.tx;
2359 icount->frame = cnow.frame;
2360 icount->overrun = cnow.overrun;
2361 icount->parity = cnow.parity;
2362 icount->brk = cnow.brk;
2363 icount->buf_overrun = cnow.buf_overrun;
2364 return 0;
2365}
2366
2353/******************************************************************************/ 2367/******************************************************************************/
2354/* Function: GetSerialInfo() */ 2368/* Function: GetSerialInfo() */
2355/* Parameters: Pointer to channel structure */ 2369/* Parameters: Pointer to channel structure */
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 3fc89da856ae..463df27494bd 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -1700,7 +1700,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
1700 return 0; 1700 return 0;
1701 } 1701 }
1702 1702
1703 if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT && cmd != TIOCGICOUNT && 1703 if (cmd != TIOCGSERIAL && cmd != TIOCMIWAIT &&
1704 test_bit(TTY_IO_ERROR, &tty->flags)) 1704 test_bit(TTY_IO_ERROR, &tty->flags))
1705 return -EIO; 1705 return -EIO;
1706 1706
@@ -1730,32 +1730,6 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
1730 1730
1731 return wait_event_interruptible(info->port.delta_msr_wait, 1731 return wait_event_interruptible(info->port.delta_msr_wait,
1732 mxser_cflags_changed(info, arg, &cnow)); 1732 mxser_cflags_changed(info, arg, &cnow));
1733 /*
1734 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
1735 * Return: write counters to the user passed counter struct
1736 * NB: both 1->0 and 0->1 transitions are counted except for
1737 * RI where only 0->1 is counted.
1738 */
1739 case TIOCGICOUNT: {
1740 struct serial_icounter_struct icnt = { 0 };
1741 spin_lock_irqsave(&info->slock, flags);
1742 cnow = info->icount;
1743 spin_unlock_irqrestore(&info->slock, flags);
1744
1745 icnt.frame = cnow.frame;
1746 icnt.brk = cnow.brk;
1747 icnt.overrun = cnow.overrun;
1748 icnt.buf_overrun = cnow.buf_overrun;
1749 icnt.parity = cnow.parity;
1750 icnt.rx = cnow.rx;
1751 icnt.tx = cnow.tx;
1752 icnt.cts = cnow.cts;
1753 icnt.dsr = cnow.dsr;
1754 icnt.rng = cnow.rng;
1755 icnt.dcd = cnow.dcd;
1756
1757 return copy_to_user(argp, &icnt, sizeof(icnt)) ? -EFAULT : 0;
1758 }
1759 case MOXA_HighSpeedOn: 1733 case MOXA_HighSpeedOn:
1760 return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp); 1734 return put_user(info->baud_base != 115200 ? 1 : 0, (int __user *)argp);
1761 case MOXA_SDS_RSTICOUNTER: 1735 case MOXA_SDS_RSTICOUNTER:
@@ -1828,6 +1802,39 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
1828 return 0; 1802 return 0;
1829} 1803}
1830 1804
1805 /*
1806 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
1807 * Return: write counters to the user passed counter struct
1808 * NB: both 1->0 and 0->1 transitions are counted except for
1809 * RI where only 0->1 is counted.
1810 */
1811
1812static int mxser_get_icount(struct tty_struct *tty,
1813 struct serial_icounter_struct *icount)
1814
1815{
1816 struct mxser_port *info = tty->driver_data;
1817 struct async_icount cnow;
1818 unsigned long flags;
1819
1820 spin_lock_irqsave(&info->slock, flags);
1821 cnow = info->icount;
1822 spin_unlock_irqrestore(&info->slock, flags);
1823
1824 icount->frame = cnow.frame;
1825 icount->brk = cnow.brk;
1826 icount->overrun = cnow.overrun;
1827 icount->buf_overrun = cnow.buf_overrun;
1828 icount->parity = cnow.parity;
1829 icount->rx = cnow.rx;
1830 icount->tx = cnow.tx;
1831 icount->cts = cnow.cts;
1832 icount->dsr = cnow.dsr;
1833 icount->rng = cnow.rng;
1834 icount->dcd = cnow.dcd;
1835 return 0;
1836}
1837
1831static void mxser_stoprx(struct tty_struct *tty) 1838static void mxser_stoprx(struct tty_struct *tty)
1832{ 1839{
1833 struct mxser_port *info = tty->driver_data; 1840 struct mxser_port *info = tty->driver_data;
@@ -2326,6 +2333,7 @@ static const struct tty_operations mxser_ops = {
2326 .wait_until_sent = mxser_wait_until_sent, 2333 .wait_until_sent = mxser_wait_until_sent,
2327 .tiocmget = mxser_tiocmget, 2334 .tiocmget = mxser_tiocmget,
2328 .tiocmset = mxser_tiocmset, 2335 .tiocmset = mxser_tiocmset,
2336 .get_icount = mxser_get_icount,
2329}; 2337};
2330 2338
2331struct tty_port_operations mxser_port_ops = { 2339struct tty_port_operations mxser_port_ops = {
@@ -2339,20 +2347,11 @@ struct tty_port_operations mxser_port_ops = {
2339 * The MOXA Smartio/Industio serial driver boot-time initialization code! 2347 * The MOXA Smartio/Industio serial driver boot-time initialization code!
2340 */ 2348 */
2341 2349
2342static void mxser_release_res(struct mxser_board *brd, struct pci_dev *pdev, 2350static void mxser_release_ISA_res(struct mxser_board *brd)
2343 unsigned int irq)
2344{ 2351{
2345 if (irq) 2352 free_irq(brd->irq, brd);
2346 free_irq(brd->irq, brd); 2353 release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
2347 if (pdev != NULL) { /* PCI */ 2354 release_region(brd->vector, 1);
2348#ifdef CONFIG_PCI
2349 pci_release_region(pdev, 2);
2350 pci_release_region(pdev, 3);
2351#endif
2352 } else {
2353 release_region(brd->ports[0].ioaddr, 8 * brd->info->nports);
2354 release_region(brd->vector, 1);
2355 }
2356} 2355}
2357 2356
2358static int __devinit mxser_initbrd(struct mxser_board *brd, 2357static int __devinit mxser_initbrd(struct mxser_board *brd,
@@ -2397,13 +2396,11 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
2397 2396
2398 retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser", 2397 retval = request_irq(brd->irq, mxser_interrupt, IRQF_SHARED, "mxser",
2399 brd); 2398 brd);
2400 if (retval) { 2399 if (retval)
2401 printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may " 2400 printk(KERN_ERR "Board %s: Request irq failed, IRQ (%d) may "
2402 "conflict with another device.\n", 2401 "conflict with another device.\n",
2403 brd->info->name, brd->irq); 2402 brd->info->name, brd->irq);
2404 /* We hold resources, we need to release them. */ 2403
2405 mxser_release_res(brd, pdev, 0);
2406 }
2407 return retval; 2404 return retval;
2408} 2405}
2409 2406
@@ -2555,7 +2552,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
2555 ioaddress = pci_resource_start(pdev, 2); 2552 ioaddress = pci_resource_start(pdev, 2);
2556 retval = pci_request_region(pdev, 2, "mxser(IO)"); 2553 retval = pci_request_region(pdev, 2, "mxser(IO)");
2557 if (retval) 2554 if (retval)
2558 goto err; 2555 goto err_dis;
2559 2556
2560 brd->info = &mxser_cards[ent->driver_data]; 2557 brd->info = &mxser_cards[ent->driver_data];
2561 for (i = 0; i < brd->info->nports; i++) 2558 for (i = 0; i < brd->info->nports; i++)
@@ -2565,7 +2562,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
2565 ioaddress = pci_resource_start(pdev, 3); 2562 ioaddress = pci_resource_start(pdev, 3);
2566 retval = pci_request_region(pdev, 3, "mxser(vector)"); 2563 retval = pci_request_region(pdev, 3, "mxser(vector)");
2567 if (retval) 2564 if (retval)
2568 goto err_relio; 2565 goto err_zero;
2569 brd->vector = ioaddress; 2566 brd->vector = ioaddress;
2570 2567
2571 /* irq */ 2568 /* irq */
@@ -2608,7 +2605,7 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
2608 /* mxser_initbrd will hook ISR. */ 2605 /* mxser_initbrd will hook ISR. */
2609 retval = mxser_initbrd(brd, pdev); 2606 retval = mxser_initbrd(brd, pdev);
2610 if (retval) 2607 if (retval)
2611 goto err_null; 2608 goto err_rel3;
2612 2609
2613 for (i = 0; i < brd->info->nports; i++) 2610 for (i = 0; i < brd->info->nports; i++)
2614 tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev); 2611 tty_register_device(mxvar_sdriver, brd->idx + i, &pdev->dev);
@@ -2616,10 +2613,13 @@ static int __devinit mxser_probe(struct pci_dev *pdev,
2616 pci_set_drvdata(pdev, brd); 2613 pci_set_drvdata(pdev, brd);
2617 2614
2618 return 0; 2615 return 0;
2619err_relio: 2616err_rel3:
2620 pci_release_region(pdev, 2); 2617 pci_release_region(pdev, 3);
2621err_null: 2618err_zero:
2622 brd->info = NULL; 2619 brd->info = NULL;
2620 pci_release_region(pdev, 2);
2621err_dis:
2622 pci_disable_device(pdev);
2623err: 2623err:
2624 return retval; 2624 return retval;
2625#else 2625#else
@@ -2629,14 +2629,19 @@ err:
2629 2629
2630static void __devexit mxser_remove(struct pci_dev *pdev) 2630static void __devexit mxser_remove(struct pci_dev *pdev)
2631{ 2631{
2632#ifdef CONFIG_PCI
2632 struct mxser_board *brd = pci_get_drvdata(pdev); 2633 struct mxser_board *brd = pci_get_drvdata(pdev);
2633 unsigned int i; 2634 unsigned int i;
2634 2635
2635 for (i = 0; i < brd->info->nports; i++) 2636 for (i = 0; i < brd->info->nports; i++)
2636 tty_unregister_device(mxvar_sdriver, brd->idx + i); 2637 tty_unregister_device(mxvar_sdriver, brd->idx + i);
2637 2638
2638 mxser_release_res(brd, pdev, 1); 2639 free_irq(pdev->irq, brd);
2640 pci_release_region(pdev, 2);
2641 pci_release_region(pdev, 3);
2642 pci_disable_device(pdev);
2639 brd->info = NULL; 2643 brd->info = NULL;
2644#endif
2640} 2645}
2641 2646
2642static struct pci_driver mxser_driver = { 2647static struct pci_driver mxser_driver = {
@@ -2741,7 +2746,7 @@ static void __exit mxser_module_exit(void)
2741 2746
2742 for (i = 0; i < MXSER_BOARDS; i++) 2747 for (i = 0; i < MXSER_BOARDS; i++)
2743 if (mxser_boards[i].info != NULL) 2748 if (mxser_boards[i].info != NULL)
2744 mxser_release_res(&mxser_boards[i], NULL, 1); 2749 mxser_release_ISA_res(&mxser_boards[i]);
2745} 2750}
2746 2751
2747module_init(mxser_module_init); 2752module_init(mxser_module_init);
diff --git a/drivers/char/nozomi.c b/drivers/char/nozomi.c
index 817169cbb245..dd3f9b1f11b4 100644
--- a/drivers/char/nozomi.c
+++ b/drivers/char/nozomi.c
@@ -1804,24 +1804,24 @@ static int ntty_cflags_changed(struct port *port, unsigned long flags,
1804 return ret; 1804 return ret;
1805} 1805}
1806 1806
1807static int ntty_ioctl_tiocgicount(struct port *port, void __user *argp) 1807static int ntty_tiocgicount(struct tty_struct *tty,
1808 struct serial_icounter_struct *icount)
1808{ 1809{
1810 struct port *port = tty->driver_data;
1809 const struct async_icount cnow = port->tty_icount; 1811 const struct async_icount cnow = port->tty_icount;
1810 struct serial_icounter_struct icount; 1812
1811 1813 icount->cts = cnow.cts;
1812 icount.cts = cnow.cts; 1814 icount->dsr = cnow.dsr;
1813 icount.dsr = cnow.dsr; 1815 icount->rng = cnow.rng;
1814 icount.rng = cnow.rng; 1816 icount->dcd = cnow.dcd;
1815 icount.dcd = cnow.dcd; 1817 icount->rx = cnow.rx;
1816 icount.rx = cnow.rx; 1818 icount->tx = cnow.tx;
1817 icount.tx = cnow.tx; 1819 icount->frame = cnow.frame;
1818 icount.frame = cnow.frame; 1820 icount->overrun = cnow.overrun;
1819 icount.overrun = cnow.overrun; 1821 icount->parity = cnow.parity;
1820 icount.parity = cnow.parity; 1822 icount->brk = cnow.brk;
1821 icount.brk = cnow.brk; 1823 icount->buf_overrun = cnow.buf_overrun;
1822 icount.buf_overrun = cnow.buf_overrun; 1824 return 0;
1823
1824 return copy_to_user(argp, &icount, sizeof(icount)) ? -EFAULT : 0;
1825} 1825}
1826 1826
1827static int ntty_ioctl(struct tty_struct *tty, struct file *file, 1827static int ntty_ioctl(struct tty_struct *tty, struct file *file,
@@ -1840,9 +1840,7 @@ static int ntty_ioctl(struct tty_struct *tty, struct file *file,
1840 rval = wait_event_interruptible(port->tty_wait, 1840 rval = wait_event_interruptible(port->tty_wait,
1841 ntty_cflags_changed(port, arg, &cprev)); 1841 ntty_cflags_changed(port, arg, &cprev));
1842 break; 1842 break;
1843 } case TIOCGICOUNT: 1843 }
1844 rval = ntty_ioctl_tiocgicount(port, argp);
1845 break;
1846 default: 1844 default:
1847 DBG1("ERR: 0x%08X, %d", cmd, cmd); 1845 DBG1("ERR: 0x%08X, %d", cmd, cmd);
1848 break; 1846 break;
@@ -1922,6 +1920,7 @@ static const struct tty_operations tty_ops = {
1922 .chars_in_buffer = ntty_chars_in_buffer, 1920 .chars_in_buffer = ntty_chars_in_buffer,
1923 .tiocmget = ntty_tiocmget, 1921 .tiocmget = ntty_tiocmget,
1924 .tiocmset = ntty_tiocmset, 1922 .tiocmset = ntty_tiocmset,
1923 .get_icount = ntty_tiocgicount,
1925 .install = ntty_install, 1924 .install = ntty_install,
1926 .cleanup = ntty_cleanup, 1925 .cleanup = ntty_cleanup,
1927}; 1926};
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index be1810057607..bfc10f89d951 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -2191,6 +2191,32 @@ static int mgslpc_break(struct tty_struct *tty, int break_state)
2191 return 0; 2191 return 0;
2192} 2192}
2193 2193
2194static int mgslpc_get_icount(struct tty_struct *tty,
2195 struct serial_icounter_struct *icount)
2196{
2197 MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
2198 struct mgsl_icount cnow; /* kernel counter temps */
2199 unsigned long flags;
2200
2201 spin_lock_irqsave(&info->lock,flags);
2202 cnow = info->icount;
2203 spin_unlock_irqrestore(&info->lock,flags);
2204
2205 icount->cts = cnow.cts;
2206 icount->dsr = cnow.dsr;
2207 icount->rng = cnow.rng;
2208 icount->dcd = cnow.dcd;
2209 icount->rx = cnow.rx;
2210 icount->tx = cnow.tx;
2211 icount->frame = cnow.frame;
2212 icount->overrun = cnow.overrun;
2213 icount->parity = cnow.parity;
2214 icount->brk = cnow.brk;
2215 icount->buf_overrun = cnow.buf_overrun;
2216
2217 return 0;
2218}
2219
2194/* Service an IOCTL request 2220/* Service an IOCTL request
2195 * 2221 *
2196 * Arguments: 2222 * Arguments:
@@ -2206,11 +2232,7 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
2206 unsigned int cmd, unsigned long arg) 2232 unsigned int cmd, unsigned long arg)
2207{ 2233{
2208 MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; 2234 MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
2209 int error;
2210 struct mgsl_icount cnow; /* kernel counter temps */
2211 struct serial_icounter_struct __user *p_cuser; /* user space */
2212 void __user *argp = (void __user *)arg; 2235 void __user *argp = (void __user *)arg;
2213 unsigned long flags;
2214 2236
2215 if (debug_level >= DEBUG_LEVEL_INFO) 2237 if (debug_level >= DEBUG_LEVEL_INFO)
2216 printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__, 2238 printk("%s(%d):mgslpc_ioctl %s cmd=%08X\n", __FILE__,__LINE__,
@@ -2220,7 +2242,7 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
2220 return -ENODEV; 2242 return -ENODEV;
2221 2243
2222 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && 2244 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
2223 (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { 2245 (cmd != TIOCMIWAIT)) {
2224 if (tty->flags & (1 << TTY_IO_ERROR)) 2246 if (tty->flags & (1 << TTY_IO_ERROR))
2225 return -EIO; 2247 return -EIO;
2226 } 2248 }
@@ -2250,34 +2272,6 @@ static int mgslpc_ioctl(struct tty_struct *tty, struct file * file,
2250 return wait_events(info, argp); 2272 return wait_events(info, argp);
2251 case TIOCMIWAIT: 2273 case TIOCMIWAIT:
2252 return modem_input_wait(info,(int)arg); 2274 return modem_input_wait(info,(int)arg);
2253 case TIOCGICOUNT:
2254 spin_lock_irqsave(&info->lock,flags);
2255 cnow = info->icount;
2256 spin_unlock_irqrestore(&info->lock,flags);
2257 p_cuser = argp;
2258 PUT_USER(error,cnow.cts, &p_cuser->cts);
2259 if (error) return error;
2260 PUT_USER(error,cnow.dsr, &p_cuser->dsr);
2261 if (error) return error;
2262 PUT_USER(error,cnow.rng, &p_cuser->rng);
2263 if (error) return error;
2264 PUT_USER(error,cnow.dcd, &p_cuser->dcd);
2265 if (error) return error;
2266 PUT_USER(error,cnow.rx, &p_cuser->rx);
2267 if (error) return error;
2268 PUT_USER(error,cnow.tx, &p_cuser->tx);
2269 if (error) return error;
2270 PUT_USER(error,cnow.frame, &p_cuser->frame);
2271 if (error) return error;
2272 PUT_USER(error,cnow.overrun, &p_cuser->overrun);
2273 if (error) return error;
2274 PUT_USER(error,cnow.parity, &p_cuser->parity);
2275 if (error) return error;
2276 PUT_USER(error,cnow.brk, &p_cuser->brk);
2277 if (error) return error;
2278 PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
2279 if (error) return error;
2280 return 0;
2281 default: 2275 default:
2282 return -ENOIOCTLCMD; 2276 return -ENOIOCTLCMD;
2283 } 2277 }
diff --git a/drivers/char/pty.c b/drivers/char/pty.c
index c350d01716bd..923a48585501 100644
--- a/drivers/char/pty.c
+++ b/drivers/char/pty.c
@@ -676,7 +676,9 @@ static int ptmx_open(struct inode *inode, struct file *filp)
676 676
677 set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */ 677 set_bit(TTY_PTY_LOCK, &tty->flags); /* LOCK THE SLAVE */
678 678
679 tty_add_file(tty, filp); 679 retval = tty_add_file(tty, filp);
680 if (retval)
681 goto out;
680 682
681 retval = devpts_pty_new(inode, tty->link); 683 retval = devpts_pty_new(inode, tty->link);
682 if (retval) 684 if (retval)
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index a2a58004e188..3a6824f12be2 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -2925,6 +2925,38 @@ static int mgsl_break(struct tty_struct *tty, int break_state)
2925 2925
2926} /* end of mgsl_break() */ 2926} /* end of mgsl_break() */
2927 2927
2928/*
2929 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
2930 * Return: write counters to the user passed counter struct
2931 * NB: both 1->0 and 0->1 transitions are counted except for
2932 * RI where only 0->1 is counted.
2933 */
2934static int msgl_get_icount(struct tty_struct *tty,
2935 struct serial_icounter_struct *icount)
2936
2937{
2938 struct mgsl_struct * info = tty->driver_data;
2939 struct mgsl_icount cnow; /* kernel counter temps */
2940 unsigned long flags;
2941
2942 spin_lock_irqsave(&info->irq_spinlock,flags);
2943 cnow = info->icount;
2944 spin_unlock_irqrestore(&info->irq_spinlock,flags);
2945
2946 icount->cts = cnow.cts;
2947 icount->dsr = cnow.dsr;
2948 icount->rng = cnow.rng;
2949 icount->dcd = cnow.dcd;
2950 icount->rx = cnow.rx;
2951 icount->tx = cnow.tx;
2952 icount->frame = cnow.frame;
2953 icount->overrun = cnow.overrun;
2954 icount->parity = cnow.parity;
2955 icount->brk = cnow.brk;
2956 icount->buf_overrun = cnow.buf_overrun;
2957 return 0;
2958}
2959
2928/* mgsl_ioctl() Service an IOCTL request 2960/* mgsl_ioctl() Service an IOCTL request
2929 * 2961 *
2930 * Arguments: 2962 * Arguments:
@@ -2949,7 +2981,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
2949 return -ENODEV; 2981 return -ENODEV;
2950 2982
2951 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && 2983 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
2952 (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { 2984 (cmd != TIOCMIWAIT)) {
2953 if (tty->flags & (1 << TTY_IO_ERROR)) 2985 if (tty->flags & (1 << TTY_IO_ERROR))
2954 return -EIO; 2986 return -EIO;
2955 } 2987 }
@@ -2959,11 +2991,7 @@ static int mgsl_ioctl(struct tty_struct *tty, struct file * file,
2959 2991
2960static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg) 2992static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigned long arg)
2961{ 2993{
2962 int error;
2963 struct mgsl_icount cnow; /* kernel counter temps */
2964 void __user *argp = (void __user *)arg; 2994 void __user *argp = (void __user *)arg;
2965 struct serial_icounter_struct __user *p_cuser; /* user space */
2966 unsigned long flags;
2967 2995
2968 switch (cmd) { 2996 switch (cmd) {
2969 case MGSL_IOCGPARAMS: 2997 case MGSL_IOCGPARAMS:
@@ -2992,40 +3020,6 @@ static int mgsl_ioctl_common(struct mgsl_struct *info, unsigned int cmd, unsigne
2992 case TIOCMIWAIT: 3020 case TIOCMIWAIT:
2993 return modem_input_wait(info,(int)arg); 3021 return modem_input_wait(info,(int)arg);
2994 3022
2995 /*
2996 * Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
2997 * Return: write counters to the user passed counter struct
2998 * NB: both 1->0 and 0->1 transitions are counted except for
2999 * RI where only 0->1 is counted.
3000 */
3001 case TIOCGICOUNT:
3002 spin_lock_irqsave(&info->irq_spinlock,flags);
3003 cnow = info->icount;
3004 spin_unlock_irqrestore(&info->irq_spinlock,flags);
3005 p_cuser = argp;
3006 PUT_USER(error,cnow.cts, &p_cuser->cts);
3007 if (error) return error;
3008 PUT_USER(error,cnow.dsr, &p_cuser->dsr);
3009 if (error) return error;
3010 PUT_USER(error,cnow.rng, &p_cuser->rng);
3011 if (error) return error;
3012 PUT_USER(error,cnow.dcd, &p_cuser->dcd);
3013 if (error) return error;
3014 PUT_USER(error,cnow.rx, &p_cuser->rx);
3015 if (error) return error;
3016 PUT_USER(error,cnow.tx, &p_cuser->tx);
3017 if (error) return error;
3018 PUT_USER(error,cnow.frame, &p_cuser->frame);
3019 if (error) return error;
3020 PUT_USER(error,cnow.overrun, &p_cuser->overrun);
3021 if (error) return error;
3022 PUT_USER(error,cnow.parity, &p_cuser->parity);
3023 if (error) return error;
3024 PUT_USER(error,cnow.brk, &p_cuser->brk);
3025 if (error) return error;
3026 PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
3027 if (error) return error;
3028 return 0;
3029 default: 3023 default:
3030 return -ENOIOCTLCMD; 3024 return -ENOIOCTLCMD;
3031 } 3025 }
@@ -4328,6 +4322,7 @@ static const struct tty_operations mgsl_ops = {
4328 .hangup = mgsl_hangup, 4322 .hangup = mgsl_hangup,
4329 .tiocmget = tiocmget, 4323 .tiocmget = tiocmget,
4330 .tiocmset = tiocmset, 4324 .tiocmset = tiocmset,
4325 .get_icount = msgl_get_icount,
4331 .proc_fops = &mgsl_proc_fops, 4326 .proc_fops = &mgsl_proc_fops,
4332}; 4327};
4333 4328
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index e63b830c86cc..1746d91205f7 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -1032,9 +1032,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
1032 unsigned int cmd, unsigned long arg) 1032 unsigned int cmd, unsigned long arg)
1033{ 1033{
1034 struct slgt_info *info = tty->driver_data; 1034 struct slgt_info *info = tty->driver_data;
1035 struct mgsl_icount cnow; /* kernel counter temps */
1036 struct serial_icounter_struct __user *p_cuser; /* user space */
1037 unsigned long flags;
1038 void __user *argp = (void __user *)arg; 1035 void __user *argp = (void __user *)arg;
1039 int ret; 1036 int ret;
1040 1037
@@ -1043,7 +1040,7 @@ static int ioctl(struct tty_struct *tty, struct file *file,
1043 DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd)); 1040 DBGINFO(("%s ioctl() cmd=%08X\n", info->device_name, cmd));
1044 1041
1045 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && 1042 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
1046 (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { 1043 (cmd != TIOCMIWAIT)) {
1047 if (tty->flags & (1 << TTY_IO_ERROR)) 1044 if (tty->flags & (1 << TTY_IO_ERROR))
1048 return -EIO; 1045 return -EIO;
1049 } 1046 }
@@ -1053,24 +1050,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
1053 return wait_mgsl_event(info, argp); 1050 return wait_mgsl_event(info, argp);
1054 case TIOCMIWAIT: 1051 case TIOCMIWAIT:
1055 return modem_input_wait(info,(int)arg); 1052 return modem_input_wait(info,(int)arg);
1056 case TIOCGICOUNT:
1057 spin_lock_irqsave(&info->lock,flags);
1058 cnow = info->icount;
1059 spin_unlock_irqrestore(&info->lock,flags);
1060 p_cuser = argp;
1061 if (put_user(cnow.cts, &p_cuser->cts) ||
1062 put_user(cnow.dsr, &p_cuser->dsr) ||
1063 put_user(cnow.rng, &p_cuser->rng) ||
1064 put_user(cnow.dcd, &p_cuser->dcd) ||
1065 put_user(cnow.rx, &p_cuser->rx) ||
1066 put_user(cnow.tx, &p_cuser->tx) ||
1067 put_user(cnow.frame, &p_cuser->frame) ||
1068 put_user(cnow.overrun, &p_cuser->overrun) ||
1069 put_user(cnow.parity, &p_cuser->parity) ||
1070 put_user(cnow.brk, &p_cuser->brk) ||
1071 put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
1072 return -EFAULT;
1073 return 0;
1074 case MGSL_IOCSGPIO: 1053 case MGSL_IOCSGPIO:
1075 return set_gpio(info, argp); 1054 return set_gpio(info, argp);
1076 case MGSL_IOCGGPIO: 1055 case MGSL_IOCGGPIO:
@@ -1117,6 +1096,33 @@ static int ioctl(struct tty_struct *tty, struct file *file,
1117 return ret; 1096 return ret;
1118} 1097}
1119 1098
1099static int get_icount(struct tty_struct *tty,
1100 struct serial_icounter_struct *icount)
1101
1102{
1103 struct slgt_info *info = tty->driver_data;
1104 struct mgsl_icount cnow; /* kernel counter temps */
1105 unsigned long flags;
1106
1107 spin_lock_irqsave(&info->lock,flags);
1108 cnow = info->icount;
1109 spin_unlock_irqrestore(&info->lock,flags);
1110
1111 icount->cts = cnow.cts;
1112 icount->dsr = cnow.dsr;
1113 icount->rng = cnow.rng;
1114 icount->dcd = cnow.dcd;
1115 icount->rx = cnow.rx;
1116 icount->tx = cnow.tx;
1117 icount->frame = cnow.frame;
1118 icount->overrun = cnow.overrun;
1119 icount->parity = cnow.parity;
1120 icount->brk = cnow.brk;
1121 icount->buf_overrun = cnow.buf_overrun;
1122
1123 return 0;
1124}
1125
1120/* 1126/*
1121 * support for 32 bit ioctl calls on 64 bit systems 1127 * support for 32 bit ioctl calls on 64 bit systems
1122 */ 1128 */
@@ -1206,10 +1212,6 @@ static long slgt_compat_ioctl(struct tty_struct *tty, struct file *file,
1206 case MGSL_IOCSGPIO: 1212 case MGSL_IOCSGPIO:
1207 case MGSL_IOCGGPIO: 1213 case MGSL_IOCGGPIO:
1208 case MGSL_IOCWAITGPIO: 1214 case MGSL_IOCWAITGPIO:
1209 case TIOCGICOUNT:
1210 rc = ioctl(tty, file, cmd, (unsigned long)(compat_ptr(arg)));
1211 break;
1212
1213 case MGSL_IOCSTXIDLE: 1215 case MGSL_IOCSTXIDLE:
1214 case MGSL_IOCTXENABLE: 1216 case MGSL_IOCTXENABLE:
1215 case MGSL_IOCRXENABLE: 1217 case MGSL_IOCRXENABLE:
@@ -3642,6 +3644,7 @@ static const struct tty_operations ops = {
3642 .hangup = hangup, 3644 .hangup = hangup,
3643 .tiocmget = tiocmget, 3645 .tiocmget = tiocmget,
3644 .tiocmset = tiocmset, 3646 .tiocmset = tiocmset,
3647 .get_icount = get_icount,
3645 .proc_fops = &synclink_gt_proc_fops, 3648 .proc_fops = &synclink_gt_proc_fops,
3646}; 3649};
3647 3650
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index e56caf7d82aa..2f9eb4b0dec1 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -1258,10 +1258,6 @@ static int ioctl(struct tty_struct *tty, struct file *file,
1258 unsigned int cmd, unsigned long arg) 1258 unsigned int cmd, unsigned long arg)
1259{ 1259{
1260 SLMP_INFO *info = tty->driver_data; 1260 SLMP_INFO *info = tty->driver_data;
1261 int error;
1262 struct mgsl_icount cnow; /* kernel counter temps */
1263 struct serial_icounter_struct __user *p_cuser; /* user space */
1264 unsigned long flags;
1265 void __user *argp = (void __user *)arg; 1261 void __user *argp = (void __user *)arg;
1266 1262
1267 if (debug_level >= DEBUG_LEVEL_INFO) 1263 if (debug_level >= DEBUG_LEVEL_INFO)
@@ -1272,7 +1268,7 @@ static int ioctl(struct tty_struct *tty, struct file *file,
1272 return -ENODEV; 1268 return -ENODEV;
1273 1269
1274 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) && 1270 if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
1275 (cmd != TIOCMIWAIT) && (cmd != TIOCGICOUNT)) { 1271 (cmd != TIOCMIWAIT)) {
1276 if (tty->flags & (1 << TTY_IO_ERROR)) 1272 if (tty->flags & (1 << TTY_IO_ERROR))
1277 return -EIO; 1273 return -EIO;
1278 } 1274 }
@@ -1310,40 +1306,38 @@ static int ioctl(struct tty_struct *tty, struct file *file,
1310 * NB: both 1->0 and 0->1 transitions are counted except for 1306 * NB: both 1->0 and 0->1 transitions are counted except for
1311 * RI where only 0->1 is counted. 1307 * RI where only 0->1 is counted.
1312 */ 1308 */
1313 case TIOCGICOUNT:
1314 spin_lock_irqsave(&info->lock,flags);
1315 cnow = info->icount;
1316 spin_unlock_irqrestore(&info->lock,flags);
1317 p_cuser = argp;
1318 PUT_USER(error,cnow.cts, &p_cuser->cts);
1319 if (error) return error;
1320 PUT_USER(error,cnow.dsr, &p_cuser->dsr);
1321 if (error) return error;
1322 PUT_USER(error,cnow.rng, &p_cuser->rng);
1323 if (error) return error;
1324 PUT_USER(error,cnow.dcd, &p_cuser->dcd);
1325 if (error) return error;
1326 PUT_USER(error,cnow.rx, &p_cuser->rx);
1327 if (error) return error;
1328 PUT_USER(error,cnow.tx, &p_cuser->tx);
1329 if (error) return error;
1330 PUT_USER(error,cnow.frame, &p_cuser->frame);
1331 if (error) return error;
1332 PUT_USER(error,cnow.overrun, &p_cuser->overrun);
1333 if (error) return error;
1334 PUT_USER(error,cnow.parity, &p_cuser->parity);
1335 if (error) return error;
1336 PUT_USER(error,cnow.brk, &p_cuser->brk);
1337 if (error) return error;
1338 PUT_USER(error,cnow.buf_overrun, &p_cuser->buf_overrun);
1339 if (error) return error;
1340 return 0;
1341 default: 1309 default:
1342 return -ENOIOCTLCMD; 1310 return -ENOIOCTLCMD;
1343 } 1311 }
1344 return 0; 1312 return 0;
1345} 1313}
1346 1314
1315static int get_icount(struct tty_struct *tty,
1316 struct serial_icounter_struct *icount)
1317{
1318 SLMP_INFO *info = tty->driver_data;
1319 struct mgsl_icount cnow; /* kernel counter temps */
1320 unsigned long flags;
1321
1322 spin_lock_irqsave(&info->lock,flags);
1323 cnow = info->icount;
1324 spin_unlock_irqrestore(&info->lock,flags);
1325
1326 icount->cts = cnow.cts;
1327 icount->dsr = cnow.dsr;
1328 icount->rng = cnow.rng;
1329 icount->dcd = cnow.dcd;
1330 icount->rx = cnow.rx;
1331 icount->tx = cnow.tx;
1332 icount->frame = cnow.frame;
1333 icount->overrun = cnow.overrun;
1334 icount->parity = cnow.parity;
1335 icount->brk = cnow.brk;
1336 icount->buf_overrun = cnow.buf_overrun;
1337
1338 return 0;
1339}
1340
1347/* 1341/*
1348 * /proc fs routines.... 1342 * /proc fs routines....
1349 */ 1343 */
@@ -3909,6 +3903,7 @@ static const struct tty_operations ops = {
3909 .hangup = hangup, 3903 .hangup = hangup,
3910 .tiocmget = tiocmget, 3904 .tiocmget = tiocmget,
3911 .tiocmset = tiocmset, 3905 .tiocmset = tiocmset,
3906 .get_icount = get_icount,
3912 .proc_fops = &synclinkmp_proc_fops, 3907 .proc_fops = &synclinkmp_proc_fops,
3913}; 3908};
3914 3909
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index 613c852ee0fe..c05c5af5aa04 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -96,6 +96,7 @@
96#include <linux/bitops.h> 96#include <linux/bitops.h>
97#include <linux/delay.h> 97#include <linux/delay.h>
98#include <linux/seq_file.h> 98#include <linux/seq_file.h>
99#include <linux/serial.h>
99 100
100#include <linux/uaccess.h> 101#include <linux/uaccess.h>
101#include <asm/system.h> 102#include <asm/system.h>
@@ -183,6 +184,8 @@ struct tty_struct *alloc_tty_struct(void)
183 184
184void free_tty_struct(struct tty_struct *tty) 185void free_tty_struct(struct tty_struct *tty)
185{ 186{
187 if (tty->dev)
188 put_device(tty->dev);
186 kfree(tty->write_buf); 189 kfree(tty->write_buf);
187 tty_buffer_free_all(tty); 190 tty_buffer_free_all(tty);
188 kfree(tty); 191 kfree(tty);
@@ -194,12 +197,13 @@ static inline struct tty_struct *file_tty(struct file *file)
194} 197}
195 198
196/* Associate a new file with the tty structure */ 199/* Associate a new file with the tty structure */
197void tty_add_file(struct tty_struct *tty, struct file *file) 200int tty_add_file(struct tty_struct *tty, struct file *file)
198{ 201{
199 struct tty_file_private *priv; 202 struct tty_file_private *priv;
200 203
201 /* XXX: must implement proper error handling in callers */ 204 priv = kmalloc(sizeof(*priv), GFP_KERNEL);
202 priv = kmalloc(sizeof(*priv), GFP_KERNEL|__GFP_NOFAIL); 205 if (!priv)
206 return -ENOMEM;
203 207
204 priv->tty = tty; 208 priv->tty = tty;
205 priv->file = file; 209 priv->file = file;
@@ -208,6 +212,8 @@ void tty_add_file(struct tty_struct *tty, struct file *file)
208 spin_lock(&tty_files_lock); 212 spin_lock(&tty_files_lock);
209 list_add(&priv->list, &tty->tty_files); 213 list_add(&priv->list, &tty->tty_files);
210 spin_unlock(&tty_files_lock); 214 spin_unlock(&tty_files_lock);
215
216 return 0;
211} 217}
212 218
213/* Delete file from its tty */ 219/* Delete file from its tty */
@@ -1875,7 +1881,11 @@ got_driver:
1875 return PTR_ERR(tty); 1881 return PTR_ERR(tty);
1876 } 1882 }
1877 1883
1878 tty_add_file(tty, filp); 1884 retval = tty_add_file(tty, filp);
1885 if (retval) {
1886 tty_unlock();
1887 return retval;
1888 }
1879 1889
1880 check_tty_count(tty, "tty_open"); 1890 check_tty_count(tty, "tty_open");
1881 if (tty->driver->type == TTY_DRIVER_TYPE_PTY && 1891 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
@@ -2502,6 +2512,20 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int
2502 return tty->ops->tiocmset(tty, file, set, clear); 2512 return tty->ops->tiocmset(tty, file, set, clear);
2503} 2513}
2504 2514
2515static int tty_tiocgicount(struct tty_struct *tty, void __user *arg)
2516{
2517 int retval = -EINVAL;
2518 struct serial_icounter_struct icount;
2519 memset(&icount, 0, sizeof(icount));
2520 if (tty->ops->get_icount)
2521 retval = tty->ops->get_icount(tty, &icount);
2522 if (retval != 0)
2523 return retval;
2524 if (copy_to_user(arg, &icount, sizeof(icount)))
2525 return -EFAULT;
2526 return 0;
2527}
2528
2505struct tty_struct *tty_pair_get_tty(struct tty_struct *tty) 2529struct tty_struct *tty_pair_get_tty(struct tty_struct *tty)
2506{ 2530{
2507 if (tty->driver->type == TTY_DRIVER_TYPE_PTY && 2531 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
@@ -2622,6 +2646,12 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2622 case TIOCMBIC: 2646 case TIOCMBIC:
2623 case TIOCMBIS: 2647 case TIOCMBIS:
2624 return tty_tiocmset(tty, file, cmd, p); 2648 return tty_tiocmset(tty, file, cmd, p);
2649 case TIOCGICOUNT:
2650 retval = tty_tiocgicount(tty, p);
2651 /* For the moment allow fall through to the old method */
2652 if (retval != -EINVAL)
2653 return retval;
2654 break;
2625 case TCFLSH: 2655 case TCFLSH:
2626 switch (arg) { 2656 switch (arg) {
2627 case TCIFLUSH: 2657 case TCIFLUSH:
@@ -2783,6 +2813,20 @@ void do_SAK(struct tty_struct *tty)
2783 2813
2784EXPORT_SYMBOL(do_SAK); 2814EXPORT_SYMBOL(do_SAK);
2785 2815
2816static int dev_match_devt(struct device *dev, void *data)
2817{
2818 dev_t *devt = data;
2819 return dev->devt == *devt;
2820}
2821
2822/* Must put_device() after it's unused! */
2823static struct device *tty_get_device(struct tty_struct *tty)
2824{
2825 dev_t devt = tty_devnum(tty);
2826 return class_find_device(tty_class, NULL, &devt, dev_match_devt);
2827}
2828
2829
2786/** 2830/**
2787 * initialize_tty_struct 2831 * initialize_tty_struct
2788 * @tty: tty to initialize 2832 * @tty: tty to initialize
@@ -2823,6 +2867,7 @@ void initialize_tty_struct(struct tty_struct *tty,
2823 tty->ops = driver->ops; 2867 tty->ops = driver->ops;
2824 tty->index = idx; 2868 tty->index = idx;
2825 tty_line_name(driver, idx, tty->name); 2869 tty_line_name(driver, idx, tty->name);
2870 tty->dev = tty_get_device(tty);
2826} 2871}
2827 2872
2828/** 2873/**
@@ -2980,6 +3025,7 @@ int tty_register_driver(struct tty_driver *driver)
2980 int i; 3025 int i;
2981 dev_t dev; 3026 dev_t dev;
2982 void **p = NULL; 3027 void **p = NULL;
3028 struct device *d;
2983 3029
2984 if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) { 3030 if (!(driver->flags & TTY_DRIVER_DEVPTS_MEM) && driver->num) {
2985 p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL); 3031 p = kzalloc(driver->num * 2 * sizeof(void *), GFP_KERNEL);
@@ -3027,12 +3073,31 @@ int tty_register_driver(struct tty_driver *driver)
3027 mutex_unlock(&tty_mutex); 3073 mutex_unlock(&tty_mutex);
3028 3074
3029 if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) { 3075 if (!(driver->flags & TTY_DRIVER_DYNAMIC_DEV)) {
3030 for (i = 0; i < driver->num; i++) 3076 for (i = 0; i < driver->num; i++) {
3031 tty_register_device(driver, i, NULL); 3077 d = tty_register_device(driver, i, NULL);
3078 if (IS_ERR(d)) {
3079 error = PTR_ERR(d);
3080 goto err;
3081 }
3082 }
3032 } 3083 }
3033 proc_tty_register_driver(driver); 3084 proc_tty_register_driver(driver);
3034 driver->flags |= TTY_DRIVER_INSTALLED; 3085 driver->flags |= TTY_DRIVER_INSTALLED;
3035 return 0; 3086 return 0;
3087
3088err:
3089 for (i--; i >= 0; i--)
3090 tty_unregister_device(driver, i);
3091
3092 mutex_lock(&tty_mutex);
3093 list_del(&driver->tty_drivers);
3094 mutex_unlock(&tty_mutex);
3095
3096 unregister_chrdev_region(dev, driver->num);
3097 driver->ttys = NULL;
3098 driver->termios = NULL;
3099 kfree(p);
3100 return error;
3036} 3101}
3037 3102
3038EXPORT_SYMBOL(tty_register_driver); 3103EXPORT_SYMBOL(tty_register_driver);
diff --git a/drivers/char/ttyprintk.c b/drivers/char/ttyprintk.c
new file mode 100644
index 000000000000..c40c1612c8a7
--- /dev/null
+++ b/drivers/char/ttyprintk.c
@@ -0,0 +1,225 @@
1/*
2 * linux/drivers/char/ttyprintk.c
3 *
4 * Copyright (C) 2010 Samo Pogacnik
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the smems of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.
9 */
10
11/*
12 * This pseudo device allows user to make printk messages. It is possible
13 * to store "console" messages inline with kernel messages for better analyses
14 * of the boot process, for example.
15 */
16
17#include <linux/device.h>
18#include <linux/serial.h>
19#include <linux/tty.h>
20
21struct ttyprintk_port {
22 struct tty_port port;
23 struct mutex port_write_mutex;
24};
25
26static struct ttyprintk_port tpk_port;
27
28/*
29 * Our simple preformatting supports transparent output of (time-stamped)
30 * printk messages (also suitable for logging service):
31 * - any cr is replaced by nl
32 * - adds a ttyprintk source tag in front of each line
33 * - too long message is fragmeted, with '\'nl between fragments
34 * - TPK_STR_SIZE isn't really the write_room limiting factor, bcause
35 * it is emptied on the fly during preformatting.
36 */
37#define TPK_STR_SIZE 508 /* should be bigger then max expected line length */
38#define TPK_MAX_ROOM 4096 /* we could assume 4K for instance */
39static const char *tpk_tag = "[U] "; /* U for User */
40static int tpk_curr;
41
42static int tpk_printk(const unsigned char *buf, int count)
43{
44 static char tmp[TPK_STR_SIZE + 4];
45 int i = tpk_curr;
46
47 if (buf == NULL) {
48 /* flush tmp[] */
49 if (tpk_curr > 0) {
50 /* non nl or cr terminated message - add nl */
51 tmp[tpk_curr + 0] = '\n';
52 tmp[tpk_curr + 1] = '\0';
53 printk(KERN_INFO "%s%s", tpk_tag, tmp);
54 tpk_curr = 0;
55 }
56 return i;
57 }
58
59 for (i = 0; i < count; i++) {
60 tmp[tpk_curr] = buf[i];
61 if (tpk_curr < TPK_STR_SIZE) {
62 switch (buf[i]) {
63 case '\r':
64 /* replace cr with nl */
65 tmp[tpk_curr + 0] = '\n';
66 tmp[tpk_curr + 1] = '\0';
67 printk(KERN_INFO "%s%s", tpk_tag, tmp);
68 tpk_curr = 0;
69 if (buf[i + 1] == '\n')
70 i++;
71 break;
72 case '\n':
73 tmp[tpk_curr + 1] = '\0';
74 printk(KERN_INFO "%s%s", tpk_tag, tmp);
75 tpk_curr = 0;
76 break;
77 default:
78 tpk_curr++;
79 }
80 } else {
81 /* end of tmp buffer reached: cut the message in two */
82 tmp[tpk_curr + 1] = '\\';
83 tmp[tpk_curr + 2] = '\n';
84 tmp[tpk_curr + 3] = '\0';
85 printk(KERN_INFO "%s%s", tpk_tag, tmp);
86 tpk_curr = 0;
87 }
88 }
89
90 return count;
91}
92
93/*
94 * TTY operations open function.
95 */
96static int tpk_open(struct tty_struct *tty, struct file *filp)
97{
98 tty->driver_data = &tpk_port;
99
100 return tty_port_open(&tpk_port.port, tty, filp);
101}
102
103/*
104 * TTY operations close function.
105 */
106static void tpk_close(struct tty_struct *tty, struct file *filp)
107{
108 struct ttyprintk_port *tpkp = tty->driver_data;
109
110 mutex_lock(&tpkp->port_write_mutex);
111 /* flush tpk_printk buffer */
112 tpk_printk(NULL, 0);
113 mutex_unlock(&tpkp->port_write_mutex);
114
115 tty_port_close(&tpkp->port, tty, filp);
116}
117
118/*
119 * TTY operations write function.
120 */
121static int tpk_write(struct tty_struct *tty,
122 const unsigned char *buf, int count)
123{
124 struct ttyprintk_port *tpkp = tty->driver_data;
125 int ret;
126
127
128 /* exclusive use of tpk_printk within this tty */
129 mutex_lock(&tpkp->port_write_mutex);
130 ret = tpk_printk(buf, count);
131 mutex_unlock(&tpkp->port_write_mutex);
132
133 return ret;
134}
135
136/*
137 * TTY operations write_room function.
138 */
139static int tpk_write_room(struct tty_struct *tty)
140{
141 return TPK_MAX_ROOM;
142}
143
144/*
145 * TTY operations ioctl function.
146 */
147static int tpk_ioctl(struct tty_struct *tty, struct file *file,
148 unsigned int cmd, unsigned long arg)
149{
150 struct ttyprintk_port *tpkp = tty->driver_data;
151
152 if (!tpkp)
153 return -EINVAL;
154
155 switch (cmd) {
156 /* Stop TIOCCONS */
157 case TIOCCONS:
158 return -EOPNOTSUPP;
159 default:
160 return -ENOIOCTLCMD;
161 }
162 return 0;
163}
164
165static const struct tty_operations ttyprintk_ops = {
166 .open = tpk_open,
167 .close = tpk_close,
168 .write = tpk_write,
169 .write_room = tpk_write_room,
170 .ioctl = tpk_ioctl,
171};
172
173struct tty_port_operations null_ops = { };
174
175static struct tty_driver *ttyprintk_driver;
176
177static int __init ttyprintk_init(void)
178{
179 int ret = -ENOMEM;
180 void *rp;
181
182 ttyprintk_driver = alloc_tty_driver(1);
183 if (!ttyprintk_driver)
184 return ret;
185
186 ttyprintk_driver->owner = THIS_MODULE;
187 ttyprintk_driver->driver_name = "ttyprintk";
188 ttyprintk_driver->name = "ttyprintk";
189 ttyprintk_driver->major = TTYAUX_MAJOR;
190 ttyprintk_driver->minor_start = 3;
191 ttyprintk_driver->num = 1;
192 ttyprintk_driver->type = TTY_DRIVER_TYPE_CONSOLE;
193 ttyprintk_driver->init_termios = tty_std_termios;
194 ttyprintk_driver->init_termios.c_oflag = OPOST | OCRNL | ONOCR | ONLRET;
195 ttyprintk_driver->flags = TTY_DRIVER_RESET_TERMIOS |
196 TTY_DRIVER_REAL_RAW | TTY_DRIVER_DYNAMIC_DEV;
197 tty_set_operations(ttyprintk_driver, &ttyprintk_ops);
198
199 ret = tty_register_driver(ttyprintk_driver);
200 if (ret < 0) {
201 printk(KERN_ERR "Couldn't register ttyprintk driver\n");
202 goto error;
203 }
204
205 /* create our unnumbered device */
206 rp = device_create(tty_class, NULL, MKDEV(TTYAUX_MAJOR, 3), NULL,
207 ttyprintk_driver->name);
208 if (IS_ERR(rp)) {
209 printk(KERN_ERR "Couldn't create ttyprintk device\n");
210 ret = PTR_ERR(rp);
211 goto error;
212 }
213
214 tty_port_init(&tpk_port.port);
215 tpk_port.port.ops = &null_ops;
216 mutex_init(&tpk_port.port_write_mutex);
217
218 return 0;
219
220error:
221 put_tty_driver(ttyprintk_driver);
222 ttyprintk_driver = NULL;
223 return ret;
224}
225module_init(ttyprintk_init);
diff --git a/drivers/char/vc_screen.c b/drivers/char/vc_screen.c
index bcce46c96b88..273ab44cc91d 100644
--- a/drivers/char/vc_screen.c
+++ b/drivers/char/vc_screen.c
@@ -35,6 +35,12 @@
35#include <linux/console.h> 35#include <linux/console.h>
36#include <linux/device.h> 36#include <linux/device.h>
37#include <linux/smp_lock.h> 37#include <linux/smp_lock.h>
38#include <linux/sched.h>
39#include <linux/fs.h>
40#include <linux/poll.h>
41#include <linux/signal.h>
42#include <linux/slab.h>
43#include <linux/notifier.h>
38 44
39#include <asm/uaccess.h> 45#include <asm/uaccess.h>
40#include <asm/byteorder.h> 46#include <asm/byteorder.h>
@@ -45,6 +51,86 @@
45#undef addr 51#undef addr
46#define HEADER_SIZE 4 52#define HEADER_SIZE 4
47 53
54struct vcs_poll_data {
55 struct notifier_block notifier;
56 unsigned int cons_num;
57 bool seen_last_update;
58 wait_queue_head_t waitq;
59 struct fasync_struct *fasync;
60};
61
62static int
63vcs_notifier(struct notifier_block *nb, unsigned long code, void *_param)
64{
65 struct vt_notifier_param *param = _param;
66 struct vc_data *vc = param->vc;
67 struct vcs_poll_data *poll =
68 container_of(nb, struct vcs_poll_data, notifier);
69 int currcons = poll->cons_num;
70
71 if (code != VT_UPDATE)
72 return NOTIFY_DONE;
73
74 if (currcons == 0)
75 currcons = fg_console;
76 else
77 currcons--;
78 if (currcons != vc->vc_num)
79 return NOTIFY_DONE;
80
81 poll->seen_last_update = false;
82 wake_up_interruptible(&poll->waitq);
83 kill_fasync(&poll->fasync, SIGIO, POLL_IN);
84 return NOTIFY_OK;
85}
86
87static void
88vcs_poll_data_free(struct vcs_poll_data *poll)
89{
90 unregister_vt_notifier(&poll->notifier);
91 kfree(poll);
92}
93
94static struct vcs_poll_data *
95vcs_poll_data_get(struct file *file)
96{
97 struct vcs_poll_data *poll = file->private_data;
98
99 if (poll)
100 return poll;
101
102 poll = kzalloc(sizeof(*poll), GFP_KERNEL);
103 if (!poll)
104 return NULL;
105 poll->cons_num = iminor(file->f_path.dentry->d_inode) & 127;
106 init_waitqueue_head(&poll->waitq);
107 poll->notifier.notifier_call = vcs_notifier;
108 if (register_vt_notifier(&poll->notifier) != 0) {
109 kfree(poll);
110 return NULL;
111 }
112
113 /*
114 * This code may be called either through ->poll() or ->fasync().
115 * If we have two threads using the same file descriptor, they could
116 * both enter this function, both notice that the structure hasn't
117 * been allocated yet and go ahead allocating it in parallel, but
118 * only one of them must survive and be shared otherwise we'd leak
119 * memory with a dangling notifier callback.
120 */
121 spin_lock(&file->f_lock);
122 if (!file->private_data) {
123 file->private_data = poll;
124 } else {
125 /* someone else raced ahead of us */
126 vcs_poll_data_free(poll);
127 poll = file->private_data;
128 }
129 spin_unlock(&file->f_lock);
130
131 return poll;
132}
133
48static int 134static int
49vcs_size(struct inode *inode) 135vcs_size(struct inode *inode)
50{ 136{
@@ -102,6 +188,7 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
102 struct inode *inode = file->f_path.dentry->d_inode; 188 struct inode *inode = file->f_path.dentry->d_inode;
103 unsigned int currcons = iminor(inode); 189 unsigned int currcons = iminor(inode);
104 struct vc_data *vc; 190 struct vc_data *vc;
191 struct vcs_poll_data *poll;
105 long pos; 192 long pos;
106 long viewed, attr, read; 193 long viewed, attr, read;
107 int col, maxcol; 194 int col, maxcol;
@@ -134,6 +221,9 @@ vcs_read(struct file *file, char __user *buf, size_t count, loff_t *ppos)
134 ret = -EINVAL; 221 ret = -EINVAL;
135 if (pos < 0) 222 if (pos < 0)
136 goto unlock_out; 223 goto unlock_out;
224 poll = file->private_data;
225 if (count && poll)
226 poll->seen_last_update = true;
137 read = 0; 227 read = 0;
138 ret = 0; 228 ret = 0;
139 while (count) { 229 while (count) {
@@ -448,6 +538,8 @@ vcs_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos)
448 } 538 }
449 *ppos += written; 539 *ppos += written;
450 ret = written; 540 ret = written;
541 if (written)
542 vcs_scr_updated(vc);
451 543
452unlock_out: 544unlock_out:
453 release_console_sem(); 545 release_console_sem();
@@ -457,6 +549,37 @@ unlock_out:
457 return ret; 549 return ret;
458} 550}
459 551
552static unsigned int
553vcs_poll(struct file *file, poll_table *wait)
554{
555 struct vcs_poll_data *poll = vcs_poll_data_get(file);
556 int ret = 0;
557
558 if (poll) {
559 poll_wait(file, &poll->waitq, wait);
560 if (!poll->seen_last_update)
561 ret = POLLIN | POLLRDNORM;
562 }
563 return ret;
564}
565
566static int
567vcs_fasync(int fd, struct file *file, int on)
568{
569 struct vcs_poll_data *poll = file->private_data;
570
571 if (!poll) {
572 /* don't allocate anything if all we want is disable fasync */
573 if (!on)
574 return 0;
575 poll = vcs_poll_data_get(file);
576 if (!poll)
577 return -ENOMEM;
578 }
579
580 return fasync_helper(fd, file, on, &poll->fasync);
581}
582
460static int 583static int
461vcs_open(struct inode *inode, struct file *filp) 584vcs_open(struct inode *inode, struct file *filp)
462{ 585{
@@ -470,11 +593,23 @@ vcs_open(struct inode *inode, struct file *filp)
470 return ret; 593 return ret;
471} 594}
472 595
596static int vcs_release(struct inode *inode, struct file *file)
597{
598 struct vcs_poll_data *poll = file->private_data;
599
600 if (poll)
601 vcs_poll_data_free(poll);
602 return 0;
603}
604
473static const struct file_operations vcs_fops = { 605static const struct file_operations vcs_fops = {
474 .llseek = vcs_lseek, 606 .llseek = vcs_lseek,
475 .read = vcs_read, 607 .read = vcs_read,
476 .write = vcs_write, 608 .write = vcs_write,
609 .poll = vcs_poll,
610 .fasync = vcs_fasync,
477 .open = vcs_open, 611 .open = vcs_open,
612 .release = vcs_release,
478}; 613};
479 614
480static struct class *vc_class; 615static struct class *vc_class;
diff --git a/drivers/char/vt.c b/drivers/char/vt.c
index 281aada7b4a1..a8ec48ed14d9 100644
--- a/drivers/char/vt.c
+++ b/drivers/char/vt.c
@@ -4182,6 +4182,11 @@ void vcs_scr_writew(struct vc_data *vc, u16 val, u16 *org)
4182 } 4182 }
4183} 4183}
4184 4184
4185void vcs_scr_updated(struct vc_data *vc)
4186{
4187 notify_update(vc);
4188}
4189
4185/* 4190/*
4186 * Visible symbols for modules 4191 * Visible symbols for modules
4187 */ 4192 */