aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Cox <alan@redhat.com>2008-07-22 06:18:03 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-22 16:03:28 -0400
commit9e98966c7bb94355689478bc84cc3e0c190f977e (patch)
tree928aebbfee524a48aa94a3d3def5249c8846a79a
parentabbe629ae4011d2020047f41bea9f9e4b0ec4361 (diff)
tty: rework break handling
Some hardware needs to do break handling itself and may have partial support only. Make break_ctl return an error code. Add a tty driver flag so you can indicate driver hardware side break support. Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/char/Kconfig2
-rw-r--r--drivers/char/amiserial.c3
-rw-r--r--drivers/char/cyclades.c8
-rw-r--r--drivers/char/esp.c5
-rw-r--r--drivers/char/istallion.c11
-rw-r--r--drivers/char/moxa.c3
-rw-r--r--drivers/char/mxser.c3
-rw-r--r--drivers/char/pcmcia/synclink_cs.c5
-rw-r--r--drivers/char/rocket.c5
-rw-r--r--drivers/char/sx.c3
-rw-r--r--drivers/char/synclink.c7
-rw-r--r--drivers/char/synclink_gt.c9
-rw-r--r--drivers/char/synclinkmp.c9
-rw-r--r--drivers/char/tty_io.c71
-rw-r--r--drivers/char/vme_scc.c5
-rw-r--r--drivers/isdn/capi/capi.c3
-rw-r--r--drivers/serial/serial_core.c3
-rw-r--r--drivers/usb/class/cdc-acm.c9
-rw-r--r--drivers/usb/serial/usb-serial.c3
-rw-r--r--include/linux/tty_driver.h14
20 files changed, 97 insertions, 84 deletions
diff --git a/drivers/char/Kconfig b/drivers/char/Kconfig
index ba8782b9c217..a185263b5862 100644
--- a/drivers/char/Kconfig
+++ b/drivers/char/Kconfig
@@ -218,7 +218,7 @@ config MOXA_SMARTIO
218 218
219config ISI 219config ISI
220 tristate "Multi-Tech multiport card support (EXPERIMENTAL)" 220 tristate "Multi-Tech multiport card support (EXPERIMENTAL)"
221 depends on SERIAL_NONSTANDARD && PCI 221 depends on SERIAL_NONSTANDARD && PCI && BROKEN
222 select FW_LOADER 222 select FW_LOADER
223 help 223 help
224 This is a driver for the Multi-Tech cards which provide several 224 This is a driver for the Multi-Tech cards which provide several
diff --git a/drivers/char/amiserial.c b/drivers/char/amiserial.c
index 37457e5a4f2b..3530ff417a51 100644
--- a/drivers/char/amiserial.c
+++ b/drivers/char/amiserial.c
@@ -1248,7 +1248,7 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file,
1248/* 1248/*
1249 * rs_break() --- routine which turns the break handling on or off 1249 * rs_break() --- routine which turns the break handling on or off
1250 */ 1250 */
1251static void rs_break(struct tty_struct *tty, int break_state) 1251static int rs_break(struct tty_struct *tty, int break_state)
1252{ 1252{
1253 struct async_struct * info = (struct async_struct *)tty->driver_data; 1253 struct async_struct * info = (struct async_struct *)tty->driver_data;
1254 unsigned long flags; 1254 unsigned long flags;
@@ -1263,6 +1263,7 @@ static void rs_break(struct tty_struct *tty, int break_state)
1263 custom.adkcon = AC_UARTBRK; 1263 custom.adkcon = AC_UARTBRK;
1264 mb(); 1264 mb();
1265 local_irq_restore(flags); 1265 local_irq_restore(flags);
1266 return 0;
1266} 1267}
1267 1268
1268 1269
diff --git a/drivers/char/cyclades.c b/drivers/char/cyclades.c
index e991dc85f2fb..fe6d774fe2e4 100644
--- a/drivers/char/cyclades.c
+++ b/drivers/char/cyclades.c
@@ -3700,14 +3700,15 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
3700/* 3700/*
3701 * cy_break() --- routine which turns the break handling on or off 3701 * cy_break() --- routine which turns the break handling on or off
3702 */ 3702 */
3703static void cy_break(struct tty_struct *tty, int break_state) 3703static int cy_break(struct tty_struct *tty, int break_state)
3704{ 3704{
3705 struct cyclades_port *info = tty->driver_data; 3705 struct cyclades_port *info = tty->driver_data;
3706 struct cyclades_card *card; 3706 struct cyclades_card *card;
3707 unsigned long flags; 3707 unsigned long flags;
3708 int retval = 0;
3708 3709
3709 if (serial_paranoia_check(info, tty->name, "cy_break")) 3710 if (serial_paranoia_check(info, tty->name, "cy_break"))
3710 return; 3711 return -EINVAL;
3711 3712
3712 card = info->card; 3713 card = info->card;
3713 3714
@@ -3736,8 +3737,6 @@ static void cy_break(struct tty_struct *tty, int break_state)
3736 } 3737 }
3737 } 3738 }
3738 } else { 3739 } else {
3739 int retval;
3740
3741 if (break_state == -1) { 3740 if (break_state == -1) {
3742 retval = cyz_issue_cmd(card, 3741 retval = cyz_issue_cmd(card,
3743 info->line - card->first_line, 3742 info->line - card->first_line,
@@ -3758,6 +3757,7 @@ static void cy_break(struct tty_struct *tty, int break_state)
3758 } 3757 }
3759 } 3758 }
3760 spin_unlock_irqrestore(&card->card_lock, flags); 3759 spin_unlock_irqrestore(&card->card_lock, flags);
3760 return retval;
3761} /* cy_break */ 3761} /* cy_break */
3762 3762
3763static int get_mon_info(struct cyclades_port *info, 3763static int get_mon_info(struct cyclades_port *info,
diff --git a/drivers/char/esp.c b/drivers/char/esp.c
index 2eaf09f93e3d..7f077c0097f6 100644
--- a/drivers/char/esp.c
+++ b/drivers/char/esp.c
@@ -1725,13 +1725,13 @@ static int esp_tiocmset(struct tty_struct *tty, struct file *file,
1725/* 1725/*
1726 * rs_break() --- routine which turns the break handling on or off 1726 * rs_break() --- routine which turns the break handling on or off
1727 */ 1727 */
1728static void esp_break(struct tty_struct *tty, int break_state) 1728static int esp_break(struct tty_struct *tty, int break_state)
1729{ 1729{
1730 struct esp_struct *info = tty->driver_data; 1730 struct esp_struct *info = tty->driver_data;
1731 unsigned long flags; 1731 unsigned long flags;
1732 1732
1733 if (serial_paranoia_check(info, tty->name, "esp_break")) 1733 if (serial_paranoia_check(info, tty->name, "esp_break"))
1734 return; 1734 return -EINVAL;
1735 1735
1736 if (break_state == -1) { 1736 if (break_state == -1) {
1737 spin_lock_irqsave(&info->lock, flags); 1737 spin_lock_irqsave(&info->lock, flags);
@@ -1747,6 +1747,7 @@ static void esp_break(struct tty_struct *tty, int break_state)
1747 serial_out(info, UART_ESI_CMD2, 0x00); 1747 serial_out(info, UART_ESI_CMD2, 0x00);
1748 spin_unlock_irqrestore(&info->lock, flags); 1748 spin_unlock_irqrestore(&info->lock, flags);
1749 } 1749 }
1750 return 0;
1750} 1751}
1751 1752
1752static int rs_ioctl(struct tty_struct *tty, struct file *file, 1753static int rs_ioctl(struct tty_struct *tty, struct file *file,
diff --git a/drivers/char/istallion.c b/drivers/char/istallion.c
index 7930fba4bafc..63d22b5ebc0d 100644
--- a/drivers/char/istallion.c
+++ b/drivers/char/istallion.c
@@ -609,7 +609,7 @@ static void stli_unthrottle(struct tty_struct *tty);
609static void stli_stop(struct tty_struct *tty); 609static void stli_stop(struct tty_struct *tty);
610static void stli_start(struct tty_struct *tty); 610static void stli_start(struct tty_struct *tty);
611static void stli_flushbuffer(struct tty_struct *tty); 611static void stli_flushbuffer(struct tty_struct *tty);
612static void stli_breakctl(struct tty_struct *tty, int state); 612static int stli_breakctl(struct tty_struct *tty, int state);
613static void stli_waituntilsent(struct tty_struct *tty, int timeout); 613static void stli_waituntilsent(struct tty_struct *tty, int timeout);
614static void stli_sendxchar(struct tty_struct *tty, char ch); 614static void stli_sendxchar(struct tty_struct *tty, char ch);
615static void stli_hangup(struct tty_struct *tty); 615static void stli_hangup(struct tty_struct *tty);
@@ -1909,7 +1909,7 @@ static void stli_flushbuffer(struct tty_struct *tty)
1909 1909
1910/*****************************************************************************/ 1910/*****************************************************************************/
1911 1911
1912static void stli_breakctl(struct tty_struct *tty, int state) 1912static int stli_breakctl(struct tty_struct *tty, int state)
1913{ 1913{
1914 struct stlibrd *brdp; 1914 struct stlibrd *brdp;
1915 struct stliport *portp; 1915 struct stliport *portp;
@@ -1917,15 +1917,16 @@ static void stli_breakctl(struct tty_struct *tty, int state)
1917 1917
1918 portp = tty->driver_data; 1918 portp = tty->driver_data;
1919 if (portp == NULL) 1919 if (portp == NULL)
1920 return; 1920 return -EINVAL;
1921 if (portp->brdnr >= stli_nrbrds) 1921 if (portp->brdnr >= stli_nrbrds)
1922 return; 1922 return -EINVAL;
1923 brdp = stli_brds[portp->brdnr]; 1923 brdp = stli_brds[portp->brdnr];
1924 if (brdp == NULL) 1924 if (brdp == NULL)
1925 return; 1925 return -EINVAL;
1926 1926
1927 arg = (state == -1) ? BREAKON : BREAKOFF; 1927 arg = (state == -1) ? BREAKON : BREAKOFF;
1928 stli_cmdwait(brdp, portp, A_BREAK, &arg, sizeof(long), 0); 1928 stli_cmdwait(brdp, portp, A_BREAK, &arg, sizeof(long), 0);
1929 return 0;
1929} 1930}
1930 1931
1931/*****************************************************************************/ 1932/*****************************************************************************/
diff --git a/drivers/char/moxa.c b/drivers/char/moxa.c
index 2bba250ffc8e..d3d7864e0c1e 100644
--- a/drivers/char/moxa.c
+++ b/drivers/char/moxa.c
@@ -374,12 +374,13 @@ copy:
374 return ret; 374 return ret;
375} 375}
376 376
377static void moxa_break_ctl(struct tty_struct *tty, int state) 377static int moxa_break_ctl(struct tty_struct *tty, int state)
378{ 378{
379 struct moxa_port *port = tty->driver_data; 379 struct moxa_port *port = tty->driver_data;
380 380
381 moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak, 381 moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak,
382 Magic_code); 382 Magic_code);
383 return 0;
383} 384}
384 385
385static const struct tty_operations moxa_ops = { 386static const struct tty_operations moxa_ops = {
diff --git a/drivers/char/mxser.c b/drivers/char/mxser.c
index 1fb25571bf85..f04c3c58a05a 100644
--- a/drivers/char/mxser.c
+++ b/drivers/char/mxser.c
@@ -2183,7 +2183,7 @@ static void mxser_hangup(struct tty_struct *tty)
2183/* 2183/*
2184 * mxser_rs_break() --- routine which turns the break handling on or off 2184 * mxser_rs_break() --- routine which turns the break handling on or off
2185 */ 2185 */
2186static void mxser_rs_break(struct tty_struct *tty, int break_state) 2186static int mxser_rs_break(struct tty_struct *tty, int break_state)
2187{ 2187{
2188 struct mxser_port *info = tty->driver_data; 2188 struct mxser_port *info = tty->driver_data;
2189 unsigned long flags; 2189 unsigned long flags;
@@ -2196,6 +2196,7 @@ static void mxser_rs_break(struct tty_struct *tty, int break_state)
2196 outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC, 2196 outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC,
2197 info->ioaddr + UART_LCR); 2197 info->ioaddr + UART_LCR);
2198 spin_unlock_irqrestore(&info->slock, flags); 2198 spin_unlock_irqrestore(&info->slock, flags);
2199 return 0;
2199} 2200}
2200 2201
2201static void mxser_receive_chars(struct mxser_port *port, int *status) 2202static void mxser_receive_chars(struct mxser_port *port, int *status)
diff --git a/drivers/char/pcmcia/synclink_cs.c b/drivers/char/pcmcia/synclink_cs.c
index b694d430f10e..d1fceabe3aef 100644
--- a/drivers/char/pcmcia/synclink_cs.c
+++ b/drivers/char/pcmcia/synclink_cs.c
@@ -2230,7 +2230,7 @@ static int tiocmset(struct tty_struct *tty, struct file *file,
2230 * Arguments: tty pointer to tty instance data 2230 * Arguments: tty pointer to tty instance data
2231 * break_state -1=set break condition, 0=clear 2231 * break_state -1=set break condition, 0=clear
2232 */ 2232 */
2233static void mgslpc_break(struct tty_struct *tty, int break_state) 2233static int mgslpc_break(struct tty_struct *tty, int break_state)
2234{ 2234{
2235 MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; 2235 MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
2236 unsigned long flags; 2236 unsigned long flags;
@@ -2240,7 +2240,7 @@ static void mgslpc_break(struct tty_struct *tty, int break_state)
2240 __FILE__,__LINE__, info->device_name, break_state); 2240 __FILE__,__LINE__, info->device_name, break_state);
2241 2241
2242 if (mgslpc_paranoia_check(info, tty->name, "mgslpc_break")) 2242 if (mgslpc_paranoia_check(info, tty->name, "mgslpc_break"))
2243 return; 2243 return -EINVAL;
2244 2244
2245 spin_lock_irqsave(&info->lock,flags); 2245 spin_lock_irqsave(&info->lock,flags);
2246 if (break_state == -1) 2246 if (break_state == -1)
@@ -2248,6 +2248,7 @@ static void mgslpc_break(struct tty_struct *tty, int break_state)
2248 else 2248 else
2249 clear_reg_bits(info, CHA+DAFO, BIT6); 2249 clear_reg_bits(info, CHA+DAFO, BIT6);
2250 spin_unlock_irqrestore(&info->lock,flags); 2250 spin_unlock_irqrestore(&info->lock,flags);
2251 return 0;
2251} 2252}
2252 2253
2253/* Service an IOCTL request 2254/* Service an IOCTL request
diff --git a/drivers/char/rocket.c b/drivers/char/rocket.c
index e670eae2f510..584d791e84a6 100644
--- a/drivers/char/rocket.c
+++ b/drivers/char/rocket.c
@@ -1236,13 +1236,13 @@ static void rp_set_termios(struct tty_struct *tty,
1236 } 1236 }
1237} 1237}
1238 1238
1239static void rp_break(struct tty_struct *tty, int break_state) 1239static int rp_break(struct tty_struct *tty, int break_state)
1240{ 1240{
1241 struct r_port *info = (struct r_port *) tty->driver_data; 1241 struct r_port *info = (struct r_port *) tty->driver_data;
1242 unsigned long flags; 1242 unsigned long flags;
1243 1243
1244 if (rocket_paranoia_check(info, "rp_break")) 1244 if (rocket_paranoia_check(info, "rp_break"))
1245 return; 1245 return -EINVAL;
1246 1246
1247 spin_lock_irqsave(&info->slock, flags); 1247 spin_lock_irqsave(&info->slock, flags);
1248 if (break_state == -1) 1248 if (break_state == -1)
@@ -1250,6 +1250,7 @@ static void rp_break(struct tty_struct *tty, int break_state)
1250 else 1250 else
1251 sClrBreak(&info->channel); 1251 sClrBreak(&info->channel);
1252 spin_unlock_irqrestore(&info->slock, flags); 1252 spin_unlock_irqrestore(&info->slock, flags);
1253 return 0;
1253} 1254}
1254 1255
1255/* 1256/*
diff --git a/drivers/char/sx.c b/drivers/char/sx.c
index d5cffcd6a572..2162439bbe48 100644
--- a/drivers/char/sx.c
+++ b/drivers/char/sx.c
@@ -1840,7 +1840,7 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
1840 return rc; 1840 return rc;
1841} 1841}
1842 1842
1843static void sx_break(struct tty_struct *tty, int flag) 1843static int sx_break(struct tty_struct *tty, int flag)
1844{ 1844{
1845 struct sx_port *port = tty->driver_data; 1845 struct sx_port *port = tty->driver_data;
1846 int rv; 1846 int rv;
@@ -1857,6 +1857,7 @@ static void sx_break(struct tty_struct *tty, int flag)
1857 read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat))); 1857 read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat)));
1858 unlock_kernel(); 1858 unlock_kernel();
1859 func_exit(); 1859 func_exit();
1860 return 0;
1860} 1861}
1861 1862
1862static int sx_tiocmget(struct tty_struct *tty, struct file *file) 1863static int sx_tiocmget(struct tty_struct *tty, struct file *file)
diff --git a/drivers/char/synclink.c b/drivers/char/synclink.c
index 527d220aa4aa..ef6706f09061 100644
--- a/drivers/char/synclink.c
+++ b/drivers/char/synclink.c
@@ -2897,9 +2897,9 @@ static int tiocmset(struct tty_struct *tty, struct file *file,
2897 * 2897 *
2898 * Arguments: tty pointer to tty instance data 2898 * Arguments: tty pointer to tty instance data
2899 * break_state -1=set break condition, 0=clear 2899 * break_state -1=set break condition, 0=clear
2900 * Return Value: None 2900 * Return Value: error code
2901 */ 2901 */
2902static void mgsl_break(struct tty_struct *tty, int break_state) 2902static int mgsl_break(struct tty_struct *tty, int break_state)
2903{ 2903{
2904 struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data; 2904 struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data;
2905 unsigned long flags; 2905 unsigned long flags;
@@ -2909,7 +2909,7 @@ static void mgsl_break(struct tty_struct *tty, int break_state)
2909 __FILE__,__LINE__, info->device_name, break_state); 2909 __FILE__,__LINE__, info->device_name, break_state);
2910 2910
2911 if (mgsl_paranoia_check(info, tty->name, "mgsl_break")) 2911 if (mgsl_paranoia_check(info, tty->name, "mgsl_break"))
2912 return; 2912 return -EINVAL;
2913 2913
2914 spin_lock_irqsave(&info->irq_spinlock,flags); 2914 spin_lock_irqsave(&info->irq_spinlock,flags);
2915 if (break_state == -1) 2915 if (break_state == -1)
@@ -2917,6 +2917,7 @@ static void mgsl_break(struct tty_struct *tty, int break_state)
2917 else 2917 else
2918 usc_OutReg(info,IOCR,(u16)(usc_InReg(info,IOCR) & ~BIT7)); 2918 usc_OutReg(info,IOCR,(u16)(usc_InReg(info,IOCR) & ~BIT7));
2919 spin_unlock_irqrestore(&info->irq_spinlock,flags); 2919 spin_unlock_irqrestore(&info->irq_spinlock,flags);
2920 return 0;
2920 2921
2921} /* end of mgsl_break() */ 2922} /* end of mgsl_break() */
2922 2923
diff --git a/drivers/char/synclink_gt.c b/drivers/char/synclink_gt.c
index 2c3e43bb2cc9..cf87bb89a77d 100644
--- a/drivers/char/synclink_gt.c
+++ b/drivers/char/synclink_gt.c
@@ -165,7 +165,7 @@ static int read_proc(char *page, char **start, off_t off, int count,int *eof, v
165static int chars_in_buffer(struct tty_struct *tty); 165static int chars_in_buffer(struct tty_struct *tty);
166static void throttle(struct tty_struct * tty); 166static void throttle(struct tty_struct * tty);
167static void unthrottle(struct tty_struct * tty); 167static void unthrottle(struct tty_struct * tty);
168static void set_break(struct tty_struct *tty, int break_state); 168static int set_break(struct tty_struct *tty, int break_state);
169 169
170/* 170/*
171 * generic HDLC support and callbacks 171 * generic HDLC support and callbacks
@@ -513,7 +513,7 @@ static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr);
513static int tiocmget(struct tty_struct *tty, struct file *file); 513static int tiocmget(struct tty_struct *tty, struct file *file);
514static int tiocmset(struct tty_struct *tty, struct file *file, 514static int tiocmset(struct tty_struct *tty, struct file *file,
515 unsigned int set, unsigned int clear); 515 unsigned int set, unsigned int clear);
516static void set_break(struct tty_struct *tty, int break_state); 516static int set_break(struct tty_struct *tty, int break_state);
517static int get_interface(struct slgt_info *info, int __user *if_mode); 517static int get_interface(struct slgt_info *info, int __user *if_mode);
518static int set_interface(struct slgt_info *info, int if_mode); 518static int set_interface(struct slgt_info *info, int if_mode);
519static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); 519static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
@@ -1452,14 +1452,14 @@ static void unthrottle(struct tty_struct * tty)
1452 * set or clear transmit break condition 1452 * set or clear transmit break condition
1453 * break_state -1=set break condition, 0=clear 1453 * break_state -1=set break condition, 0=clear
1454 */ 1454 */
1455static void set_break(struct tty_struct *tty, int break_state) 1455static int set_break(struct tty_struct *tty, int break_state)
1456{ 1456{
1457 struct slgt_info *info = tty->driver_data; 1457 struct slgt_info *info = tty->driver_data;
1458 unsigned short value; 1458 unsigned short value;
1459 unsigned long flags; 1459 unsigned long flags;
1460 1460
1461 if (sanity_check(info, tty->name, "set_break")) 1461 if (sanity_check(info, tty->name, "set_break"))
1462 return; 1462 return -EINVAL;
1463 DBGINFO(("%s set_break(%d)\n", info->device_name, break_state)); 1463 DBGINFO(("%s set_break(%d)\n", info->device_name, break_state));
1464 1464
1465 spin_lock_irqsave(&info->lock,flags); 1465 spin_lock_irqsave(&info->lock,flags);
@@ -1470,6 +1470,7 @@ static void set_break(struct tty_struct *tty, int break_state)
1470 value &= ~BIT6; 1470 value &= ~BIT6;
1471 wr_reg16(info, TCR, value); 1471 wr_reg16(info, TCR, value);
1472 spin_unlock_irqrestore(&info->lock,flags); 1472 spin_unlock_irqrestore(&info->lock,flags);
1473 return 0;
1473} 1474}
1474 1475
1475#if SYNCLINK_GENERIC_HDLC 1476#if SYNCLINK_GENERIC_HDLC
diff --git a/drivers/char/synclinkmp.c b/drivers/char/synclinkmp.c
index 5768c4136342..c0490cbd0db2 100644
--- a/drivers/char/synclinkmp.c
+++ b/drivers/char/synclinkmp.c
@@ -527,7 +527,7 @@ static int read_proc(char *page, char **start, off_t off, int count,int *eof, v
527static int chars_in_buffer(struct tty_struct *tty); 527static int chars_in_buffer(struct tty_struct *tty);
528static void throttle(struct tty_struct * tty); 528static void throttle(struct tty_struct * tty);
529static void unthrottle(struct tty_struct * tty); 529static void unthrottle(struct tty_struct * tty);
530static void set_break(struct tty_struct *tty, int break_state); 530static int set_break(struct tty_struct *tty, int break_state);
531 531
532#if SYNCLINK_GENERIC_HDLC 532#if SYNCLINK_GENERIC_HDLC
533#define dev_to_port(D) (dev_to_hdlc(D)->priv) 533#define dev_to_port(D) (dev_to_hdlc(D)->priv)
@@ -552,7 +552,7 @@ static int wait_mgsl_event(SLMP_INFO *info, int __user *mask_ptr);
552static int tiocmget(struct tty_struct *tty, struct file *file); 552static int tiocmget(struct tty_struct *tty, struct file *file);
553static int tiocmset(struct tty_struct *tty, struct file *file, 553static int tiocmset(struct tty_struct *tty, struct file *file,
554 unsigned int set, unsigned int clear); 554 unsigned int set, unsigned int clear);
555static void set_break(struct tty_struct *tty, int break_state); 555static int set_break(struct tty_struct *tty, int break_state);
556 556
557static void add_device(SLMP_INFO *info); 557static void add_device(SLMP_INFO *info);
558static void device_init(int adapter_num, struct pci_dev *pdev); 558static void device_init(int adapter_num, struct pci_dev *pdev);
@@ -1587,7 +1587,7 @@ static void unthrottle(struct tty_struct * tty)
1587/* set or clear transmit break condition 1587/* set or clear transmit break condition
1588 * break_state -1=set break condition, 0=clear 1588 * break_state -1=set break condition, 0=clear
1589 */ 1589 */
1590static void set_break(struct tty_struct *tty, int break_state) 1590static int set_break(struct tty_struct *tty, int break_state)
1591{ 1591{
1592 unsigned char RegValue; 1592 unsigned char RegValue;
1593 SLMP_INFO * info = (SLMP_INFO *)tty->driver_data; 1593 SLMP_INFO * info = (SLMP_INFO *)tty->driver_data;
@@ -1598,7 +1598,7 @@ static void set_break(struct tty_struct *tty, int break_state)
1598 __FILE__,__LINE__, info->device_name, break_state); 1598 __FILE__,__LINE__, info->device_name, break_state);
1599 1599
1600 if (sanity_check(info, tty->name, "set_break")) 1600 if (sanity_check(info, tty->name, "set_break"))
1601 return; 1601 return -EINVAL;
1602 1602
1603 spin_lock_irqsave(&info->lock,flags); 1603 spin_lock_irqsave(&info->lock,flags);
1604 RegValue = read_reg(info, CTL); 1604 RegValue = read_reg(info, CTL);
@@ -1608,6 +1608,7 @@ static void set_break(struct tty_struct *tty, int break_state)
1608 RegValue &= ~BIT3; 1608 RegValue &= ~BIT3;
1609 write_reg(info, CTL, RegValue); 1609 write_reg(info, CTL, RegValue);
1610 spin_unlock_irqrestore(&info->lock,flags); 1610 spin_unlock_irqrestore(&info->lock,flags);
1611 return 0;
1611} 1612}
1612 1613
1613#if SYNCLINK_GENERIC_HDLC 1614#if SYNCLINK_GENERIC_HDLC
diff --git a/drivers/char/tty_io.c b/drivers/char/tty_io.c
index d27a08b374d0..d94cd8410c53 100644
--- a/drivers/char/tty_io.c
+++ b/drivers/char/tty_io.c
@@ -2849,16 +2849,29 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
2849 2849
2850static int send_break(struct tty_struct *tty, unsigned int duration) 2850static int send_break(struct tty_struct *tty, unsigned int duration)
2851{ 2851{
2852 if (tty_write_lock(tty, 0) < 0) 2852 int retval;
2853 return -EINTR; 2853
2854 tty->ops->break_ctl(tty, -1); 2854 if (tty->ops->break_ctl == NULL)
2855 if (!signal_pending(current)) 2855 return 0;
2856 msleep_interruptible(duration); 2856
2857 tty->ops->break_ctl(tty, 0); 2857 if (tty->driver->flags & TTY_DRIVER_HARDWARE_BREAK)
2858 tty_write_unlock(tty); 2858 retval = tty->ops->break_ctl(tty, duration);
2859 if (signal_pending(current)) 2859 else {
2860 return -EINTR; 2860 /* Do the work ourselves */
2861 return 0; 2861 if (tty_write_lock(tty, 0) < 0)
2862 return -EINTR;
2863 retval = tty->ops->break_ctl(tty, -1);
2864 if (retval)
2865 goto out;
2866 if (!signal_pending(current))
2867 msleep_interruptible(duration);
2868 retval = tty->ops->break_ctl(tty, 0);
2869out:
2870 tty_write_unlock(tty);
2871 if (signal_pending(current))
2872 retval = -EINTR;
2873 }
2874 return retval;
2862} 2875}
2863 2876
2864/** 2877/**
@@ -2949,36 +2962,6 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
2949 tty->driver->subtype == PTY_TYPE_MASTER) 2962 tty->driver->subtype == PTY_TYPE_MASTER)
2950 real_tty = tty->link; 2963 real_tty = tty->link;
2951 2964
2952 /*
2953 * Break handling by driver
2954 */
2955
2956 retval = -EINVAL;
2957
2958 if (!tty->ops->break_ctl) {
2959 switch (cmd) {
2960 case TIOCSBRK:
2961 case TIOCCBRK:
2962 if (tty->ops->ioctl)
2963 retval = tty->ops->ioctl(tty, file, cmd, arg);
2964 if (retval != -EINVAL && retval != -ENOIOCTLCMD)
2965 printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name);
2966 return retval;
2967
2968 /* These two ioctl's always return success; even if */
2969 /* the driver doesn't support them. */
2970 case TCSBRK:
2971 case TCSBRKP:
2972 if (!tty->ops->ioctl)
2973 return 0;
2974 retval = tty->ops->ioctl(tty, file, cmd, arg);
2975 if (retval != -EINVAL && retval != -ENOIOCTLCMD)
2976 printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name);
2977 if (retval == -ENOIOCTLCMD)
2978 retval = 0;
2979 return retval;
2980 }
2981 }
2982 2965
2983 /* 2966 /*
2984 * Factor out some common prep work 2967 * Factor out some common prep work
@@ -3000,6 +2983,9 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
3000 break; 2983 break;
3001 } 2984 }
3002 2985
2986 /*
2987 * Now do the stuff.
2988 */
3003 switch (cmd) { 2989 switch (cmd) {
3004 case TIOCSTI: 2990 case TIOCSTI:
3005 return tiocsti(tty, p); 2991 return tiocsti(tty, p);
@@ -3043,12 +3029,11 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
3043 */ 3029 */
3044 case TIOCSBRK: /* Turn break on, unconditionally */ 3030 case TIOCSBRK: /* Turn break on, unconditionally */
3045 if (tty->ops->break_ctl) 3031 if (tty->ops->break_ctl)
3046 tty->ops->break_ctl(tty, -1); 3032 return tty->ops->break_ctl(tty, -1);
3047 return 0; 3033 return 0;
3048
3049 case TIOCCBRK: /* Turn break off, unconditionally */ 3034 case TIOCCBRK: /* Turn break off, unconditionally */
3050 if (tty->ops->break_ctl) 3035 if (tty->ops->break_ctl)
3051 tty->ops->break_ctl(tty, 0); 3036 return tty->ops->break_ctl(tty, 0);
3052 return 0; 3037 return 0;
3053 case TCSBRK: /* SVID version: non-zero arg --> no break */ 3038 case TCSBRK: /* SVID version: non-zero arg --> no break */
3054 /* non-zero arg means wait for all output data 3039 /* non-zero arg means wait for all output data
diff --git a/drivers/char/vme_scc.c b/drivers/char/vme_scc.c
index f17ac043b551..69c5afe97f19 100644
--- a/drivers/char/vme_scc.c
+++ b/drivers/char/vme_scc.c
@@ -85,7 +85,7 @@ static irqreturn_t scc_rx_int(int irq, void *data);
85static irqreturn_t scc_stat_int(int irq, void *data); 85static irqreturn_t scc_stat_int(int irq, void *data);
86static irqreturn_t scc_spcond_int(int irq, void *data); 86static irqreturn_t scc_spcond_int(int irq, void *data);
87static void scc_setsignals(struct scc_port *port, int dtr, int rts); 87static void scc_setsignals(struct scc_port *port, int dtr, int rts);
88static void scc_break_ctl(struct tty_struct *tty, int break_state); 88static int scc_break_ctl(struct tty_struct *tty, int break_state);
89 89
90static struct tty_driver *scc_driver; 90static struct tty_driver *scc_driver;
91 91
@@ -942,7 +942,7 @@ static int scc_ioctl(struct tty_struct *tty, struct file *file,
942} 942}
943 943
944 944
945static void scc_break_ctl(struct tty_struct *tty, int break_state) 945static int scc_break_ctl(struct tty_struct *tty, int break_state)
946{ 946{
947 struct scc_port *port = (struct scc_port *)tty->driver_data; 947 struct scc_port *port = (struct scc_port *)tty->driver_data;
948 unsigned long flags; 948 unsigned long flags;
@@ -952,6 +952,7 @@ static void scc_break_ctl(struct tty_struct *tty, int break_state)
952 SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK, 952 SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK,
953 break_state ? TCR_SEND_BREAK : 0); 953 break_state ? TCR_SEND_BREAK : 0);
954 local_irq_restore(flags); 954 local_irq_restore(flags);
955 return 0;
955} 956}
956 957
957 958
diff --git a/drivers/isdn/capi/capi.c b/drivers/isdn/capi/capi.c
index 8a35029caca0..19e005e81fef 100644
--- a/drivers/isdn/capi/capi.c
+++ b/drivers/isdn/capi/capi.c
@@ -1302,11 +1302,12 @@ static void capinc_tty_hangup(struct tty_struct *tty)
1302#endif 1302#endif
1303} 1303}
1304 1304
1305static void capinc_tty_break_ctl(struct tty_struct *tty, int state) 1305static int capinc_tty_break_ctl(struct tty_struct *tty, int state)
1306{ 1306{
1307#ifdef _DEBUG_TTYFUNCS 1307#ifdef _DEBUG_TTYFUNCS
1308 printk(KERN_DEBUG "capinc_tty_break_ctl(%d)\n", state); 1308 printk(KERN_DEBUG "capinc_tty_break_ctl(%d)\n", state);
1309#endif 1309#endif
1310 return 0;
1310} 1311}
1311 1312
1312static void capinc_tty_flush_buffer(struct tty_struct *tty) 1313static void capinc_tty_flush_buffer(struct tty_struct *tty)
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 0bce1fe2c62a..f977c98cfa95 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -934,7 +934,7 @@ uart_tiocmset(struct tty_struct *tty, struct file *file,
934 return ret; 934 return ret;
935} 935}
936 936
937static void uart_break_ctl(struct tty_struct *tty, int break_state) 937static int uart_break_ctl(struct tty_struct *tty, int break_state)
938{ 938{
939 struct uart_state *state = tty->driver_data; 939 struct uart_state *state = tty->driver_data;
940 struct uart_port *port = state->port; 940 struct uart_port *port = state->port;
@@ -945,6 +945,7 @@ static void uart_break_ctl(struct tty_struct *tty, int break_state)
945 port->ops->break_ctl(port, break_state); 945 port->ops->break_ctl(port, break_state);
946 946
947 mutex_unlock(&state->mutex); 947 mutex_unlock(&state->mutex);
948 return 0;
948} 949}
949 950
950static int uart_do_autoconfig(struct uart_state *state) 951static int uart_do_autoconfig(struct uart_state *state)
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 95ae6377d7e5..0725b1871f23 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -732,13 +732,16 @@ static void acm_tty_unthrottle(struct tty_struct *tty)
732 tasklet_schedule(&acm->urb_task); 732 tasklet_schedule(&acm->urb_task);
733} 733}
734 734
735static void acm_tty_break_ctl(struct tty_struct *tty, int state) 735static int acm_tty_break_ctl(struct tty_struct *tty, int state)
736{ 736{
737 struct acm *acm = tty->driver_data; 737 struct acm *acm = tty->driver_data;
738 int retval;
738 if (!ACM_READY(acm)) 739 if (!ACM_READY(acm))
739 return; 740 return -EINVAL;
740 if (acm_send_break(acm, state ? 0xffff : 0)) 741 retval = acm_send_break(acm, state ? 0xffff : 0);
742 if (retval < 0)
741 dbg("send break failed"); 743 dbg("send break failed");
744 return retval;
742} 745}
743 746
744static int acm_tty_tiocmget(struct tty_struct *tty, struct file *file) 747static int acm_tty_tiocmget(struct tty_struct *tty, struct file *file)
diff --git a/drivers/usb/serial/usb-serial.c b/drivers/usb/serial/usb-serial.c
index 51917b0f079a..8c2d531eedea 100644
--- a/drivers/usb/serial/usb-serial.c
+++ b/drivers/usb/serial/usb-serial.c
@@ -395,7 +395,7 @@ static void serial_set_termios(struct tty_struct *tty, struct ktermios *old)
395 tty_termios_copy_hw(tty->termios, old); 395 tty_termios_copy_hw(tty->termios, old);
396} 396}
397 397
398static void serial_break(struct tty_struct *tty, int break_state) 398static int serial_break(struct tty_struct *tty, int break_state)
399{ 399{
400 struct usb_serial_port *port = tty->driver_data; 400 struct usb_serial_port *port = tty->driver_data;
401 401
@@ -409,6 +409,7 @@ static void serial_break(struct tty_struct *tty, int break_state)
409 port->serial->type->break_ctl(tty, break_state); 409 port->serial->type->break_ctl(tty, break_state);
410 unlock_kernel(); 410 unlock_kernel();
411 } 411 }
412 return 0;
412} 413}
413 414
414static int serial_read_proc(char *page, char **start, off_t off, int count, 415static int serial_read_proc(char *page, char **start, off_t off, int count,
diff --git a/include/linux/tty_driver.h b/include/linux/tty_driver.h
index d2a003586761..e1065ac0d922 100644
--- a/include/linux/tty_driver.h
+++ b/include/linux/tty_driver.h
@@ -135,7 +135,7 @@
135 * 135 *
136 * Optional: 136 * Optional:
137 * 137 *
138 * void (*break_ctl)(struct tty_stuct *tty, int state); 138 * int (*break_ctl)(struct tty_stuct *tty, int state);
139 * 139 *
140 * This optional routine requests the tty driver to turn on or 140 * This optional routine requests the tty driver to turn on or
141 * off BREAK status on the RS-232 port. If state is -1, 141 * off BREAK status on the RS-232 port. If state is -1,
@@ -146,6 +146,10 @@
146 * handle the following ioctls: TCSBRK, TCSBRKP, TIOCSBRK, 146 * handle the following ioctls: TCSBRK, TCSBRKP, TIOCSBRK,
147 * TIOCCBRK. 147 * TIOCCBRK.
148 * 148 *
149 * If the driver sets TTY_DRIVER_HARDWARE_BREAK then the interface
150 * will also be called with actual times and the hardware is expected
151 * to do the delay work itself. 0 and -1 are still used for on/off.
152 *
149 * Optional: Required for TCSBRK/BRKP/etc handling. 153 * Optional: Required for TCSBRK/BRKP/etc handling.
150 * 154 *
151 * void (*wait_until_sent)(struct tty_struct *tty, int timeout); 155 * void (*wait_until_sent)(struct tty_struct *tty, int timeout);
@@ -192,7 +196,7 @@ struct tty_operations {
192 void (*stop)(struct tty_struct *tty); 196 void (*stop)(struct tty_struct *tty);
193 void (*start)(struct tty_struct *tty); 197 void (*start)(struct tty_struct *tty);
194 void (*hangup)(struct tty_struct *tty); 198 void (*hangup)(struct tty_struct *tty);
195 void (*break_ctl)(struct tty_struct *tty, int state); 199 int (*break_ctl)(struct tty_struct *tty, int state);
196 void (*flush_buffer)(struct tty_struct *tty); 200 void (*flush_buffer)(struct tty_struct *tty);
197 void (*set_ldisc)(struct tty_struct *tty); 201 void (*set_ldisc)(struct tty_struct *tty);
198 void (*wait_until_sent)(struct tty_struct *tty, int timeout); 202 void (*wait_until_sent)(struct tty_struct *tty, int timeout);
@@ -285,12 +289,18 @@ extern struct tty_driver *tty_find_polling_driver(char *name, int *line);
285 * TTY_DRIVER_DEVPTS_MEM -- don't use the standard arrays, instead 289 * TTY_DRIVER_DEVPTS_MEM -- don't use the standard arrays, instead
286 * use dynamic memory keyed through the devpts filesystem. This 290 * use dynamic memory keyed through the devpts filesystem. This
287 * is only applicable to the pty driver. 291 * is only applicable to the pty driver.
292 *
293 * TTY_DRIVER_HARDWARE_BREAK -- hardware handles break signals. Pass
294 * the requested timeout to the caller instead of using a simple
295 * on/off interface.
296 *
288 */ 297 */
289#define TTY_DRIVER_INSTALLED 0x0001 298#define TTY_DRIVER_INSTALLED 0x0001
290#define TTY_DRIVER_RESET_TERMIOS 0x0002 299#define TTY_DRIVER_RESET_TERMIOS 0x0002
291#define TTY_DRIVER_REAL_RAW 0x0004 300#define TTY_DRIVER_REAL_RAW 0x0004
292#define TTY_DRIVER_DYNAMIC_DEV 0x0008 301#define TTY_DRIVER_DYNAMIC_DEV 0x0008
293#define TTY_DRIVER_DEVPTS_MEM 0x0010 302#define TTY_DRIVER_DEVPTS_MEM 0x0010
303#define TTY_DRIVER_HARDWARE_BREAK 0x0020
294 304
295/* tty driver types */ 305/* tty driver types */
296#define TTY_DRIVER_TYPE_SYSTEM 0x0001 306#define TTY_DRIVER_TYPE_SYSTEM 0x0001