Commit 9e98966c authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

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: default avatarAlan Cox <alan@redhat.com>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent abbe629a
...@@ -218,7 +218,7 @@ config MOXA_SMARTIO ...@@ -218,7 +218,7 @@ config MOXA_SMARTIO
config ISI config ISI
tristate "Multi-Tech multiport card support (EXPERIMENTAL)" tristate "Multi-Tech multiport card support (EXPERIMENTAL)"
depends on SERIAL_NONSTANDARD && PCI depends on SERIAL_NONSTANDARD && PCI && BROKEN
select FW_LOADER select FW_LOADER
help help
This is a driver for the Multi-Tech cards which provide several This is a driver for the Multi-Tech cards which provide several
......
...@@ -1248,7 +1248,7 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file, ...@@ -1248,7 +1248,7 @@ static int rs_tiocmset(struct tty_struct *tty, struct file *file,
/* /*
* rs_break() --- routine which turns the break handling on or off * rs_break() --- routine which turns the break handling on or off
*/ */
static void rs_break(struct tty_struct *tty, int break_state) static int rs_break(struct tty_struct *tty, int break_state)
{ {
struct async_struct * info = (struct async_struct *)tty->driver_data; struct async_struct * info = (struct async_struct *)tty->driver_data;
unsigned long flags; unsigned long flags;
...@@ -1263,6 +1263,7 @@ static void rs_break(struct tty_struct *tty, int break_state) ...@@ -1263,6 +1263,7 @@ static void rs_break(struct tty_struct *tty, int break_state)
custom.adkcon = AC_UARTBRK; custom.adkcon = AC_UARTBRK;
mb(); mb();
local_irq_restore(flags); local_irq_restore(flags);
return 0;
} }
......
...@@ -3700,14 +3700,15 @@ cy_tiocmset(struct tty_struct *tty, struct file *file, ...@@ -3700,14 +3700,15 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
/* /*
* cy_break() --- routine which turns the break handling on or off * cy_break() --- routine which turns the break handling on or off
*/ */
static void cy_break(struct tty_struct *tty, int break_state) static int cy_break(struct tty_struct *tty, int break_state)
{ {
struct cyclades_port *info = tty->driver_data; struct cyclades_port *info = tty->driver_data;
struct cyclades_card *card; struct cyclades_card *card;
unsigned long flags; unsigned long flags;
int retval = 0;
if (serial_paranoia_check(info, tty->name, "cy_break")) if (serial_paranoia_check(info, tty->name, "cy_break"))
return; return -EINVAL;
card = info->card; card = info->card;
...@@ -3736,8 +3737,6 @@ static void cy_break(struct tty_struct *tty, int break_state) ...@@ -3736,8 +3737,6 @@ static void cy_break(struct tty_struct *tty, int break_state)
} }
} }
} else { } else {
int retval;
if (break_state == -1) { if (break_state == -1) {
retval = cyz_issue_cmd(card, retval = cyz_issue_cmd(card,
info->line - card->first_line, info->line - card->first_line,
...@@ -3758,6 +3757,7 @@ static void cy_break(struct tty_struct *tty, int break_state) ...@@ -3758,6 +3757,7 @@ static void cy_break(struct tty_struct *tty, int break_state)
} }
} }
spin_unlock_irqrestore(&card->card_lock, flags); spin_unlock_irqrestore(&card->card_lock, flags);
return retval;
} /* cy_break */ } /* cy_break */
static int get_mon_info(struct cyclades_port *info, static int get_mon_info(struct cyclades_port *info,
......
...@@ -1725,13 +1725,13 @@ static int esp_tiocmset(struct tty_struct *tty, struct file *file, ...@@ -1725,13 +1725,13 @@ static int esp_tiocmset(struct tty_struct *tty, struct file *file,
/* /*
* rs_break() --- routine which turns the break handling on or off * rs_break() --- routine which turns the break handling on or off
*/ */
static void esp_break(struct tty_struct *tty, int break_state) static int esp_break(struct tty_struct *tty, int break_state)
{ {
struct esp_struct *info = tty->driver_data; struct esp_struct *info = tty->driver_data;
unsigned long flags; unsigned long flags;
if (serial_paranoia_check(info, tty->name, "esp_break")) if (serial_paranoia_check(info, tty->name, "esp_break"))
return; return -EINVAL;
if (break_state == -1) { if (break_state == -1) {
spin_lock_irqsave(&info->lock, flags); spin_lock_irqsave(&info->lock, flags);
...@@ -1747,6 +1747,7 @@ static void esp_break(struct tty_struct *tty, int break_state) ...@@ -1747,6 +1747,7 @@ static void esp_break(struct tty_struct *tty, int break_state)
serial_out(info, UART_ESI_CMD2, 0x00); serial_out(info, UART_ESI_CMD2, 0x00);
spin_unlock_irqrestore(&info->lock, flags); spin_unlock_irqrestore(&info->lock, flags);
} }
return 0;
} }
static int rs_ioctl(struct tty_struct *tty, struct file *file, static int rs_ioctl(struct tty_struct *tty, struct file *file,
......
...@@ -609,7 +609,7 @@ static void stli_unthrottle(struct tty_struct *tty); ...@@ -609,7 +609,7 @@ static void stli_unthrottle(struct tty_struct *tty);
static void stli_stop(struct tty_struct *tty); static void stli_stop(struct tty_struct *tty);
static void stli_start(struct tty_struct *tty); static void stli_start(struct tty_struct *tty);
static void stli_flushbuffer(struct tty_struct *tty); static void stli_flushbuffer(struct tty_struct *tty);
static void stli_breakctl(struct tty_struct *tty, int state); static int stli_breakctl(struct tty_struct *tty, int state);
static void stli_waituntilsent(struct tty_struct *tty, int timeout); static void stli_waituntilsent(struct tty_struct *tty, int timeout);
static void stli_sendxchar(struct tty_struct *tty, char ch); static void stli_sendxchar(struct tty_struct *tty, char ch);
static void stli_hangup(struct tty_struct *tty); static void stli_hangup(struct tty_struct *tty);
...@@ -1909,7 +1909,7 @@ static void stli_flushbuffer(struct tty_struct *tty) ...@@ -1909,7 +1909,7 @@ static void stli_flushbuffer(struct tty_struct *tty)
/*****************************************************************************/ /*****************************************************************************/
static void stli_breakctl(struct tty_struct *tty, int state) static int stli_breakctl(struct tty_struct *tty, int state)
{ {
struct stlibrd *brdp; struct stlibrd *brdp;
struct stliport *portp; struct stliport *portp;
...@@ -1917,15 +1917,16 @@ static void stli_breakctl(struct tty_struct *tty, int state) ...@@ -1917,15 +1917,16 @@ static void stli_breakctl(struct tty_struct *tty, int state)
portp = tty->driver_data; portp = tty->driver_data;
if (portp == NULL) if (portp == NULL)
return; return -EINVAL;
if (portp->brdnr >= stli_nrbrds) if (portp->brdnr >= stli_nrbrds)
return; return -EINVAL;
brdp = stli_brds[portp->brdnr]; brdp = stli_brds[portp->brdnr];
if (brdp == NULL) if (brdp == NULL)
return; return -EINVAL;
arg = (state == -1) ? BREAKON : BREAKOFF; arg = (state == -1) ? BREAKON : BREAKOFF;
stli_cmdwait(brdp, portp, A_BREAK, &arg, sizeof(long), 0); stli_cmdwait(brdp, portp, A_BREAK, &arg, sizeof(long), 0);
return 0;
} }
/*****************************************************************************/ /*****************************************************************************/
......
...@@ -374,12 +374,13 @@ copy: ...@@ -374,12 +374,13 @@ copy:
return ret; return ret;
} }
static void moxa_break_ctl(struct tty_struct *tty, int state) static int moxa_break_ctl(struct tty_struct *tty, int state)
{ {
struct moxa_port *port = tty->driver_data; struct moxa_port *port = tty->driver_data;
moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak, moxafunc(port->tableAddr, state ? FC_SendBreak : FC_StopBreak,
Magic_code); Magic_code);
return 0;
} }
static const struct tty_operations moxa_ops = { static const struct tty_operations moxa_ops = {
......
...@@ -2183,7 +2183,7 @@ static void mxser_hangup(struct tty_struct *tty) ...@@ -2183,7 +2183,7 @@ static void mxser_hangup(struct tty_struct *tty)
/* /*
* mxser_rs_break() --- routine which turns the break handling on or off * mxser_rs_break() --- routine which turns the break handling on or off
*/ */
static void mxser_rs_break(struct tty_struct *tty, int break_state) static int mxser_rs_break(struct tty_struct *tty, int break_state)
{ {
struct mxser_port *info = tty->driver_data; struct mxser_port *info = tty->driver_data;
unsigned long flags; unsigned long flags;
...@@ -2196,6 +2196,7 @@ static void mxser_rs_break(struct tty_struct *tty, int break_state) ...@@ -2196,6 +2196,7 @@ static void mxser_rs_break(struct tty_struct *tty, int break_state)
outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC, outb(inb(info->ioaddr + UART_LCR) & ~UART_LCR_SBC,
info->ioaddr + UART_LCR); info->ioaddr + UART_LCR);
spin_unlock_irqrestore(&info->slock, flags); spin_unlock_irqrestore(&info->slock, flags);
return 0;
} }
static void mxser_receive_chars(struct mxser_port *port, int *status) static void mxser_receive_chars(struct mxser_port *port, int *status)
......
...@@ -2230,7 +2230,7 @@ static int tiocmset(struct tty_struct *tty, struct file *file, ...@@ -2230,7 +2230,7 @@ static int tiocmset(struct tty_struct *tty, struct file *file,
* Arguments: tty pointer to tty instance data * Arguments: tty pointer to tty instance data
* break_state -1=set break condition, 0=clear * break_state -1=set break condition, 0=clear
*/ */
static void mgslpc_break(struct tty_struct *tty, int break_state) static int mgslpc_break(struct tty_struct *tty, int break_state)
{ {
MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data; MGSLPC_INFO * info = (MGSLPC_INFO *)tty->driver_data;
unsigned long flags; unsigned long flags;
...@@ -2240,7 +2240,7 @@ static void mgslpc_break(struct tty_struct *tty, int break_state) ...@@ -2240,7 +2240,7 @@ static void mgslpc_break(struct tty_struct *tty, int break_state)
__FILE__,__LINE__, info->device_name, break_state); __FILE__,__LINE__, info->device_name, break_state);
if (mgslpc_paranoia_check(info, tty->name, "mgslpc_break")) if (mgslpc_paranoia_check(info, tty->name, "mgslpc_break"))
return; return -EINVAL;
spin_lock_irqsave(&info->lock,flags); spin_lock_irqsave(&info->lock,flags);
if (break_state == -1) if (break_state == -1)
...@@ -2248,6 +2248,7 @@ static void mgslpc_break(struct tty_struct *tty, int break_state) ...@@ -2248,6 +2248,7 @@ static void mgslpc_break(struct tty_struct *tty, int break_state)
else else
clear_reg_bits(info, CHA+DAFO, BIT6); clear_reg_bits(info, CHA+DAFO, BIT6);
spin_unlock_irqrestore(&info->lock,flags); spin_unlock_irqrestore(&info->lock,flags);
return 0;
} }
/* Service an IOCTL request /* Service an IOCTL request
......
...@@ -1236,13 +1236,13 @@ static void rp_set_termios(struct tty_struct *tty, ...@@ -1236,13 +1236,13 @@ static void rp_set_termios(struct tty_struct *tty,
} }
} }
static void rp_break(struct tty_struct *tty, int break_state) static int rp_break(struct tty_struct *tty, int break_state)
{ {
struct r_port *info = (struct r_port *) tty->driver_data; struct r_port *info = (struct r_port *) tty->driver_data;
unsigned long flags; unsigned long flags;
if (rocket_paranoia_check(info, "rp_break")) if (rocket_paranoia_check(info, "rp_break"))
return; return -EINVAL;
spin_lock_irqsave(&info->slock, flags); spin_lock_irqsave(&info->slock, flags);
if (break_state == -1) if (break_state == -1)
...@@ -1250,6 +1250,7 @@ static void rp_break(struct tty_struct *tty, int break_state) ...@@ -1250,6 +1250,7 @@ static void rp_break(struct tty_struct *tty, int break_state)
else else
sClrBreak(&info->channel); sClrBreak(&info->channel);
spin_unlock_irqrestore(&info->slock, flags); spin_unlock_irqrestore(&info->slock, flags);
return 0;
} }
/* /*
......
...@@ -1840,7 +1840,7 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp, ...@@ -1840,7 +1840,7 @@ static int sx_fw_ioctl(struct inode *inode, struct file *filp,
return rc; return rc;
} }
static void sx_break(struct tty_struct *tty, int flag) static int sx_break(struct tty_struct *tty, int flag)
{ {
struct sx_port *port = tty->driver_data; struct sx_port *port = tty->driver_data;
int rv; int rv;
...@@ -1857,6 +1857,7 @@ static void sx_break(struct tty_struct *tty, int flag) ...@@ -1857,6 +1857,7 @@ static void sx_break(struct tty_struct *tty, int flag)
read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat))); read_sx_byte(port->board, CHAN_OFFSET(port, hi_hstat)));
unlock_kernel(); unlock_kernel();
func_exit(); func_exit();
return 0;
} }
static int sx_tiocmget(struct tty_struct *tty, struct file *file) static int sx_tiocmget(struct tty_struct *tty, struct file *file)
......
...@@ -2897,9 +2897,9 @@ static int tiocmset(struct tty_struct *tty, struct file *file, ...@@ -2897,9 +2897,9 @@ static int tiocmset(struct tty_struct *tty, struct file *file,
* *
* Arguments: tty pointer to tty instance data * Arguments: tty pointer to tty instance data
* break_state -1=set break condition, 0=clear * break_state -1=set break condition, 0=clear
* Return Value: None * Return Value: error code
*/ */
static void mgsl_break(struct tty_struct *tty, int break_state) static int mgsl_break(struct tty_struct *tty, int break_state)
{ {
struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data; struct mgsl_struct * info = (struct mgsl_struct *)tty->driver_data;
unsigned long flags; unsigned long flags;
...@@ -2909,7 +2909,7 @@ static void mgsl_break(struct tty_struct *tty, int break_state) ...@@ -2909,7 +2909,7 @@ static void mgsl_break(struct tty_struct *tty, int break_state)
__FILE__,__LINE__, info->device_name, break_state); __FILE__,__LINE__, info->device_name, break_state);
if (mgsl_paranoia_check(info, tty->name, "mgsl_break")) if (mgsl_paranoia_check(info, tty->name, "mgsl_break"))
return; return -EINVAL;
spin_lock_irqsave(&info->irq_spinlock,flags); spin_lock_irqsave(&info->irq_spinlock,flags);
if (break_state == -1) if (break_state == -1)
...@@ -2917,6 +2917,7 @@ static void mgsl_break(struct tty_struct *tty, int break_state) ...@@ -2917,6 +2917,7 @@ static void mgsl_break(struct tty_struct *tty, int break_state)
else else
usc_OutReg(info,IOCR,(u16)(usc_InReg(info,IOCR) & ~BIT7)); usc_OutReg(info,IOCR,(u16)(usc_InReg(info,IOCR) & ~BIT7));
spin_unlock_irqrestore(&info->irq_spinlock,flags); spin_unlock_irqrestore(&info->irq_spinlock,flags);
return 0;
} /* end of mgsl_break() */ } /* end of mgsl_break() */
......
...@@ -165,7 +165,7 @@ static int read_proc(char *page, char **start, off_t off, int count,int *eof, v ...@@ -165,7 +165,7 @@ static int read_proc(char *page, char **start, off_t off, int count,int *eof, v
static int chars_in_buffer(struct tty_struct *tty); static int chars_in_buffer(struct tty_struct *tty);
static void throttle(struct tty_struct * tty); static void throttle(struct tty_struct * tty);
static void unthrottle(struct tty_struct * tty); static void unthrottle(struct tty_struct * tty);
static void set_break(struct tty_struct *tty, int break_state); static int set_break(struct tty_struct *tty, int break_state);
/* /*
* generic HDLC support and callbacks * generic HDLC support and callbacks
...@@ -513,7 +513,7 @@ static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr); ...@@ -513,7 +513,7 @@ static int wait_mgsl_event(struct slgt_info *info, int __user *mask_ptr);
static int tiocmget(struct tty_struct *tty, struct file *file); static int tiocmget(struct tty_struct *tty, struct file *file);
static int tiocmset(struct tty_struct *tty, struct file *file, static int tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear); unsigned int set, unsigned int clear);
static void set_break(struct tty_struct *tty, int break_state); static int set_break(struct tty_struct *tty, int break_state);
static int get_interface(struct slgt_info *info, int __user *if_mode); static int get_interface(struct slgt_info *info, int __user *if_mode);
static int set_interface(struct slgt_info *info, int if_mode); static int set_interface(struct slgt_info *info, int if_mode);
static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio); static int set_gpio(struct slgt_info *info, struct gpio_desc __user *gpio);
...@@ -1452,14 +1452,14 @@ static void unthrottle(struct tty_struct * tty) ...@@ -1452,14 +1452,14 @@ static void unthrottle(struct tty_struct * tty)
* set or clear transmit break condition * set or clear transmit break condition
* break_state -1=set break condition, 0=clear * break_state -1=set break condition, 0=clear
*/ */
static void set_break(struct tty_struct *tty, int break_state) static int set_break(struct tty_struct *tty, int break_state)
{ {
struct slgt_info *info = tty->driver_data; struct slgt_info *info = tty->driver_data;
unsigned short value; unsigned short value;
unsigned long flags; unsigned long flags;
if (sanity_check(info, tty->name, "set_break")) if (sanity_check(info, tty->name, "set_break"))
return; return -EINVAL;
DBGINFO(("%s set_break(%d)\n", info->device_name, break_state)); DBGINFO(("%s set_break(%d)\n", info->device_name, break_state));
spin_lock_irqsave(&info->lock,flags); spin_lock_irqsave(&info->lock,flags);
...@@ -1470,6 +1470,7 @@ static void set_break(struct tty_struct *tty, int break_state) ...@@ -1470,6 +1470,7 @@ static void set_break(struct tty_struct *tty, int break_state)
value &= ~BIT6; value &= ~BIT6;
wr_reg16(info, TCR, value); wr_reg16(info, TCR, value);
spin_unlock_irqrestore(&info->lock,flags); spin_unlock_irqrestore(&info->lock,flags);
return 0;
} }
#if SYNCLINK_GENERIC_HDLC #if SYNCLINK_GENERIC_HDLC
......
...@@ -527,7 +527,7 @@ static int read_proc(char *page, char **start, off_t off, int count,int *eof, v ...@@ -527,7 +527,7 @@ static int read_proc(char *page, char **start, off_t off, int count,int *eof, v
static int chars_in_buffer(struct tty_struct *tty); static int chars_in_buffer(struct tty_struct *tty);
static void throttle(struct tty_struct * tty); static void throttle(struct tty_struct * tty);
static void unthrottle(struct tty_struct * tty); static void unthrottle(struct tty_struct * tty);
static void set_break(struct tty_struct *tty, int break_state); static int set_break(struct tty_struct *tty, int break_state);
#if SYNCLINK_GENERIC_HDLC #if SYNCLINK_GENERIC_HDLC
#define dev_to_port(D) (dev_to_hdlc(D)->priv) #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); ...@@ -552,7 +552,7 @@ static int wait_mgsl_event(SLMP_INFO *info, int __user *mask_ptr);
static int tiocmget(struct tty_struct *tty, struct file *file); static int tiocmget(struct tty_struct *tty, struct file *file);
static int tiocmset(struct tty_struct *tty, struct file *file, static int tiocmset(struct tty_struct *tty, struct file *file,
unsigned int set, unsigned int clear); unsigned int set, unsigned int clear);
static void set_break(struct tty_struct *tty, int break_state); static int set_break(struct tty_struct *tty, int break_state);
static void add_device(SLMP_INFO *info); static void add_device(SLMP_INFO *info);
static void device_init(int adapter_num, struct pci_dev *pdev); static void device_init(int adapter_num, struct pci_dev *pdev);
...@@ -1587,7 +1587,7 @@ static void unthrottle(struct tty_struct * tty) ...@@ -1587,7 +1587,7 @@ static void unthrottle(struct tty_struct * tty)
/* set or clear transmit break condition /* set or clear transmit break condition
* break_state -1=set break condition, 0=clear * break_state -1=set break condition, 0=clear
*/ */
static void set_break(struct tty_struct *tty, int break_state) static int set_break(struct tty_struct *tty, int break_state)
{ {
unsigned char RegValue; unsigned char RegValue;
SLMP_INFO * info = (SLMP_INFO *)tty->driver_data; SLMP_INFO * info = (SLMP_INFO *)tty->driver_data;
...@@ -1598,7 +1598,7 @@ static void set_break(struct tty_struct *tty, int break_state) ...@@ -1598,7 +1598,7 @@ static void set_break(struct tty_struct *tty, int break_state)
__FILE__,__LINE__, info->device_name, break_state); __FILE__,__LINE__, info->device_name, break_state);
if (sanity_check(info, tty->name, "set_break")) if (sanity_check(info, tty->name, "set_break"))
return; return -EINVAL;
spin_lock_irqsave(&info->lock,flags); spin_lock_irqsave(&info->lock,flags);
RegValue = read_reg(info, CTL); RegValue = read_reg(info, CTL);
...@@ -1608,6 +1608,7 @@ static void set_break(struct tty_struct *tty, int break_state) ...@@ -1608,6 +1608,7 @@ static void set_break(struct tty_struct *tty, int break_state)
RegValue &= ~BIT3; RegValue &= ~BIT3;
write_reg(info, CTL, RegValue); write_reg(info, CTL, RegValue);
spin_unlock_irqrestore(&info->lock,flags); spin_unlock_irqrestore(&info->lock,flags);
return 0;
} }
#if SYNCLINK_GENERIC_HDLC #if SYNCLINK_GENERIC_HDLC
......
...@@ -2849,16 +2849,29 @@ static int tiocsetd(struct tty_struct *tty, int __user *p) ...@@ -2849,16 +2849,29 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
static int send_break(struct tty_struct *tty, unsigned int duration) static int send_break(struct tty_struct *tty, unsigned int duration)
{ {
int retval;
if (tty->ops->break_ctl == NULL)
return 0;
if (tty->driver->flags & TTY_DRIVER_HARDWARE_BREAK)
retval = tty->ops->break_ctl(tty, duration);
else {
/* Do the work ourselves */
if (tty_write_lock(tty, 0) < 0) if (tty_write_lock(tty, 0) < 0)
return -EINTR; return -EINTR;
tty->ops->break_ctl(tty, -1); retval = tty->ops->break_ctl(tty, -1);
if (retval)
goto out;
if (!signal_pending(current)) if (!signal_pending(current))
msleep_interruptible(duration); msleep_interruptible(duration);
tty->ops->break_ctl(tty, 0); retval = tty->ops->break_ctl(tty, 0);
out:
tty_write_unlock(tty); tty_write_unlock(tty);
if (signal_pending(current)) if (signal_pending(current))
return -EINTR; retval = -EINTR;
return 0; }
return retval;
} }
/** /**
...@@ -2949,36 +2962,6 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -2949,36 +2962,6 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
tty->driver->subtype == PTY_TYPE_MASTER) tty->driver->subtype == PTY_TYPE_MASTER)
real_tty = tty->link; real_tty = tty->link;
/*
* Break handling by driver
*/
retval = -EINVAL;
if (!tty->ops->break_ctl) {
switch (cmd) {
case TIOCSBRK:
case TIOCCBRK:
if (tty->ops->ioctl)
retval = tty->ops->ioctl(tty, file, cmd, arg);
if (retval != -EINVAL && retval != -ENOIOCTLCMD)
printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name);
return retval;
/* These two ioctl's always return success; even if */
/* the driver doesn't support them. */
case TCSBRK:
case TCSBRKP:
if (!tty->ops->ioctl)
return 0;
retval = tty->ops->ioctl(tty, file, cmd, arg);
if (retval != -EINVAL && retval != -ENOIOCTLCMD)
printk(KERN_WARNING "tty: driver %s needs updating to use break_ctl\n", tty->driver->name);
if (retval == -ENOIOCTLCMD)
retval = 0;
return retval;
}
}
/* /*
* Factor out some common prep work * Factor out some common prep work
...@@ -3000,6 +2983,9 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -3000,6 +2983,9 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
break; break;
} }
/*
* Now do the stuff.
*/
switch (cmd) { switch (cmd) {
case TIOCSTI: case TIOCSTI:
return tiocsti(tty, p); return tiocsti(tty, p);
...@@ -3043,12 +3029,11 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg) ...@@ -3043,12 +3029,11 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
*/ */
case TIOCSBRK: /* Turn break on, unconditionally */ case TIOCSBRK: /* Turn break on, unconditionally */
if (tty->ops->break_ctl) if (tty->ops->break_ctl)
tty->ops->break_ctl(tty, -1); return tty->ops->break_ctl(tty, -1);
return 0; return 0;
case TIOCCBRK: /* Turn break off, unconditionally */ case TIOCCBRK: /* Turn break off, unconditionally */
if (tty->ops->break_ctl) if (tty->ops->break_ctl)
tty->ops->break_ctl(tty, 0); return tty->ops->break_ctl(tty, 0);
return 0; return 0;
case TCSBRK: /* SVID version: non-zero arg --> no break */ case TCSBRK: /* SVID version: non-zero arg --> no break */
/* non-zero arg means wait for all output data /* non-zero arg means wait for all output data
......
...@@ -85,7 +85,7 @@ static irqreturn_t scc_rx_int(int irq, void *data); ...@@ -85,7 +85,7 @@ static irqreturn_t scc_rx_int(int irq, void *data);
static irqreturn_t scc_stat_int(int irq, void *data); static irqreturn_t scc_stat_int(int irq, void *data);
static irqreturn_t scc_spcond_int(int irq, void *data); static irqreturn_t scc_spcond_int(int irq, void *data);
static void scc_setsignals(struct scc_port *port, int dtr, int rts); static void scc_setsignals(struct scc_port *port, int dtr, int rts);
static void scc_break_ctl(struct tty_struct *tty, int break_state); static int scc_break_ctl(struct tty_struct *tty, int break_state);
static struct tty_driver *scc_driver; static struct tty_driver *scc_driver;
...@@ -942,7 +942,7 @@ static int scc_ioctl(struct tty_struct *tty, struct file *file, ...@@ -942,7 +942,7 @@ static int scc_ioctl(struct tty_struct *tty, struct file *file,
} }
static void scc_break_ctl(struct tty_struct *tty, int break_state) static int scc_break_ctl(struct tty_struct *tty, int break_state)
{ {
struct scc_port *port = (struct scc_port *)tty->driver_data; struct scc_port *port = (struct scc_port *)tty->driver_data;
unsigned long flags; unsigned long flags;
...@@ -952,6 +952,7 @@ static void scc_break_ctl(struct tty_struct *tty, int break_state) ...@@ -952,6 +952,7 @@ static void scc_break_ctl(struct tty_struct *tty, int break_state)
SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK, SCCmod(TX_CTRL_REG, ~TCR_SEND_BREAK,
break_state ? TCR_SEND_BREAK : 0); break_state ? TCR_SEND_BREAK : 0);
local_irq_restore(flags); local_irq_restore(flags);
return 0;
} }
......
...@@ -1302,11 +1302,12 @@ static void capinc_tty_hangup(struct tty_struct *tty) ...@@ -1302,11 +1302,12 @@ static void capinc_tty_hangup(struct tty_struct *tty)
#endif #endif
} }
static void capinc_tty_break_ctl(struct tty_struct *tty, int state) static int capinc_tty_break_ctl(struct tty_struct *tty, int state)
{ {
#ifdef _DEBUG_TTYFUNCS #ifdef _DEBUG_TTYFUNCS
printk(KERN_DEBUG "capinc_tty_break_ctl(%d)\n", state); printk(KERN_DEBUG "capinc_tty_break_ctl(%d)\n", state);
#endif #endif
return 0;
} }
static void capinc_tty_flush_buffer(struct tty_struct *tty) static void capinc_tty_flush_buffer(struct tty_struct *tty)
......
...@@ -934,7 +934,7 @@ uart_tiocmset(struct tty_struct *tty, struct file *file, ...@@ -934,7 +934,7 @@ uart_tiocmset(struct tty_struct *tty, struct file *file,
return ret; return ret;
} }
static void uart_break_ctl(struct tty_struct *tty, int break_state) static int uart_break_ctl(struct tty_struct *tty, int break_state)
{ {
struct uart_state *state = tty->driver_data; struct uart_state *state = tty->driver_data;
struct uart_port *port = state->port; struct uart_port *port = state->port;
...@@ -945,6 +945,7 @@ static void uart_break_ctl(struct tty_struct *tty, int break_state) ...@@ -945,6 +945,7 @@ static void uart_break_ctl(struct tty_struct *tty, int break_state)
port->ops->break_ctl(port, break_state); port->ops->break_ctl(port, break_state);
mutex_unlock(&state->mutex); mutex_unlock(&state->mutex);
return 0;
}