aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorAlan Cox <alan@linux.intel.com>2010-09-16 13:21:24 -0400
committerGreg Kroah-Hartman <gregkh@suse.de>2010-10-22 13:20:04 -0400
commitd281da7ff6f70efca0553c288bb883e8605b3862 (patch)
treeee6a46b33070159af51c07643cf99186f1ef3e03 /drivers
parent68707539df1e9d12435e5d54ffedc7ded50fcd01 (diff)
tty: Make tiocgicount a handler
Dan Rosenberg noted that various drivers return the struct with uncleared fields. Instead of spending forever trying to stomp all the drivers that get it wrong (and every new driver) do the job in one place. This first patch adds the needed operations and hooks them up, including the needed USB midlayer and serial core plumbing. Signed-off-by: Alan Cox <alan@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/char/tty_io.c21
-rw-r--r--drivers/serial/serial_core.c35
-rw-r--r--drivers/usb/serial/usb-serial.c13
3 files changed, 50 insertions, 19 deletions
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index e185db36f8ad..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>
@@ -2511,6 +2512,20 @@ static int tty_tiocmset(struct tty_struct *tty, struct file *file, unsigned int
2511 return tty->ops->tiocmset(tty, file, set, clear); 2512 return tty->ops->tiocmset(tty, file, set, clear);
2512} 2513}
2513 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
2514struct tty_struct *tty_pair_get_tty(struct tty_struct *tty) 2529struct tty_struct *tty_pair_get_tty(struct tty_struct *tty)
2515{ 2530{
2516 if (tty->driver->type == TTY_DRIVER_TYPE_PTY && 2531 if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
@@ -2631,6 +2646,12 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2631 case TIOCMBIC: 2646 case TIOCMBIC:
2632 case TIOCMBIS: 2647 case TIOCMBIS:
2633 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;
2634 case TCFLSH: 2655 case TCFLSH:
2635 switch (arg) { 2656 switch (arg) {
2636 case TCIFLUSH: 2657 case TCIFLUSH:
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index bc6cddd10294..c4ea14670d44 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -1074,10 +1074,10 @@ uart_wait_modem_status(struct uart_state *state, unsigned long arg)
1074 * NB: both 1->0 and 0->1 transitions are counted except for 1074 * NB: both 1->0 and 0->1 transitions are counted except for
1075 * RI where only 0->1 is counted. 1075 * RI where only 0->1 is counted.
1076 */ 1076 */
1077static int uart_get_count(struct uart_state *state, 1077static int uart_get_icount(struct tty_struct *tty,
1078 struct serial_icounter_struct __user *icnt) 1078 struct serial_icounter_struct *icount)
1079{ 1079{
1080 struct serial_icounter_struct icount; 1080 struct uart_state *state = tty->driver_data;
1081 struct uart_icount cnow; 1081 struct uart_icount cnow;
1082 struct uart_port *uport = state->uart_port; 1082 struct uart_port *uport = state->uart_port;
1083 1083
@@ -1085,19 +1085,19 @@ static int uart_get_count(struct uart_state *state,
1085 memcpy(&cnow, &uport->icount, sizeof(struct uart_icount)); 1085 memcpy(&cnow, &uport->icount, sizeof(struct uart_icount));
1086 spin_unlock_irq(&uport->lock); 1086 spin_unlock_irq(&uport->lock);
1087 1087
1088 icount.cts = cnow.cts; 1088 icount->cts = cnow.cts;
1089 icount.dsr = cnow.dsr; 1089 icount->dsr = cnow.dsr;
1090 icount.rng = cnow.rng; 1090 icount->rng = cnow.rng;
1091 icount.dcd = cnow.dcd; 1091 icount->dcd = cnow.dcd;
1092 icount.rx = cnow.rx; 1092 icount->rx = cnow.rx;
1093 icount.tx = cnow.tx; 1093 icount->tx = cnow.tx;
1094 icount.frame = cnow.frame; 1094 icount->frame = cnow.frame;
1095 icount.overrun = cnow.overrun; 1095 icount->overrun = cnow.overrun;
1096 icount.parity = cnow.parity; 1096 icount->parity = cnow.parity;
1097 icount.brk = cnow.brk; 1097 icount->brk = cnow.brk;
1098 icount.buf_overrun = cnow.buf_overrun; 1098 icount->buf_overrun = cnow.buf_overrun;
1099 1099
1100 return copy_to_user(icnt, &icount, sizeof(icount)) ? -EFAULT : 0; 1100 return 0;
1101} 1101}
1102 1102
1103/* 1103/*
@@ -1150,10 +1150,6 @@ uart_ioctl(struct tty_struct *tty, struct file *filp, unsigned int cmd,
1150 case TIOCMIWAIT: 1150 case TIOCMIWAIT:
1151 ret = uart_wait_modem_status(state, arg); 1151 ret = uart_wait_modem_status(state, arg);
1152 break; 1152 break;
1153
1154 case TIOCGICOUNT:
1155 ret = uart_get_count(state, uarg);
1156 break;
1157 } 1153 }
1158 1154
1159 if (ret != -ENOIOCTLCMD) 1155 if (ret != -ENOIOCTLCMD)
@@ -2295,6 +2291,7 @@ static const struct tty_operations uart_ops = {
2295#endif 2291#endif
2296 .tiocmget = uart_tiocmget, 2292 .tiocmget = uart_tiocmget,
2297 .tiocmset = uart_tiocmset, 2293 .tiocmset = uart_tiocmset,
2294 .get_icount = uart_get_icount,
2298#ifdef CONFIG_CONSOLE_POLL 2295#ifdef CONFIG_CONSOLE_POLL
2299 .poll_init = uart_poll_init, 2296 .poll_init = uart_poll_init,
2300 .poll_get_char = uart_poll_get_char, 2297 .poll_get_char = uart_poll_get_char,
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 7a2177c79bde..e64da74bdcc5 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -519,6 +519,18 @@ static int serial_tiocmset(struct tty_struct *tty, struct file *file,
519 return -EINVAL; 519 return -EINVAL;
520} 520}
521 521
522static int serial_get_icount(struct tty_struct *tty,
523 struct serial_icounter_struct *icount)
524{
525 struct usb_serial_port *port = tty->driver_data;
526
527 dbg("%s - port %d", __func__, port->number);
528
529 if (port->serial->type->get_icount)
530 return port->serial->type->get_icount(tty, icount);
531 return -EINVAL;
532}
533
522/* 534/*
523 * We would be calling tty_wakeup here, but unfortunately some line 535 * We would be calling tty_wakeup here, but unfortunately some line
524 * disciplines have an annoying habit of calling tty->write from 536 * disciplines have an annoying habit of calling tty->write from
@@ -1195,6 +1207,7 @@ static const struct tty_operations serial_ops = {
1195 .chars_in_buffer = serial_chars_in_buffer, 1207 .chars_in_buffer = serial_chars_in_buffer,
1196 .tiocmget = serial_tiocmget, 1208 .tiocmget = serial_tiocmget,
1197 .tiocmset = serial_tiocmset, 1209 .tiocmset = serial_tiocmset,
1210 .get_icount = serial_get_icount,
1198 .cleanup = serial_cleanup, 1211 .cleanup = serial_cleanup,
1199 .install = serial_install, 1212 .install = serial_install,
1200 .proc_fops = &serial_proc_fops, 1213 .proc_fops = &serial_proc_fops,