Commit 2e124b4a authored by Jiri Slaby's avatar Jiri Slaby Committed by Greg Kroah-Hartman

TTY: switch tty_flip_buffer_push

Now, we start converting tty buffer functions to actually use
tty_port. This will allow us to get rid of the need of tty in many
call sites. Only tty_port will needed and hence no more
tty_port_tty_get in those paths.

Now, the one where most of tty_port_tty_get gets removed:
tty_flip_buffer_push.

IOW we also closed all the races in drivers not using tty_port_tty_get
at all yet.

Also we move tty_flip_buffer_push declaration from include/linux/tty.h
to include/linux/tty_flip.h to all others while we are changing it
anyway.
Signed-off-by: 's avatarJiri Slaby <jslaby@suse.cz>
Signed-off-by: 's avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent d6c53c0e
......@@ -53,9 +53,8 @@ struct tty_driver *hp_simserial_driver;
static struct console *console;
static void receive_chars(struct tty_struct *tty)
static void receive_chars(struct tty_port *port)
{
struct tty_port *port = tty->port;
unsigned char ch;
static unsigned char seen_esc = 0;
......@@ -85,7 +84,7 @@ static void receive_chars(struct tty_struct *tty)
if (tty_insert_flip_char(port, ch, TTY_NORMAL) == 0)
break;
}
tty_flip_buffer_push(tty);
tty_flip_buffer_push(port);
}
/*
......@@ -94,18 +93,9 @@ static void receive_chars(struct tty_struct *tty)
static irqreturn_t rs_interrupt_single(int irq, void *dev_id)
{
struct serial_state *info = dev_id;
struct tty_struct *tty = tty_port_tty_get(&info->port);
if (!tty) {
printk(KERN_INFO "%s: tty=0 problem\n", __func__);
return IRQ_NONE;
}
/*
* pretty simple in our case, because we only get interrupts
* on inbound traffic
*/
receive_chars(tty);
tty_kref_put(tty);
receive_chars(&info->port);
return IRQ_HANDLED;
}
......
......@@ -525,7 +525,6 @@ static void mn10300_serial_receive_interrupt(struct mn10300_serial_port *port)
{
struct uart_icount *icount = &port->uart.icount;
struct tty_port *port = &port->uart.state->port;
struct tty_struct *tty = port->tty;
unsigned ix;
int count;
u8 st, ch, push, status, overrun;
......@@ -538,7 +537,7 @@ static void mn10300_serial_receive_interrupt(struct mn10300_serial_port *port)
count = tty_buffer_request_room(port, count);
if (count == 0) {
if (!port->low_latency)
tty_flip_buffer_push(tty);
tty_flip_buffer_push(port);
return;
}
......@@ -547,7 +546,7 @@ try_again:
ix = ACCESS_ONCE(port->rx_outp);
if (CIRC_CNT(port->rx_inp, ix, MNSC_BUFFER_SIZE) == 0) {
if (push && !port->low_latency)
tty_flip_buffer_push(tty);
tty_flip_buffer_push(port);
return;
}
......@@ -679,7 +678,7 @@ insert:
count--;
if (count <= 0) {
if (!port->low_latency)
tty_flip_buffer_push(tty);
tty_flip_buffer_push(port);
return;
}
......
......@@ -138,10 +138,6 @@ static const struct tty_operations pdc_console_tty_ops = {
static void pdc_console_poll(unsigned long unused)
{
int data, count = 0;
struct tty_struct *tty = tty_port_tty_get(&tty_port);
if (!tty)
return;
while (1) {
data = pdc_console_poll_key(NULL);
......@@ -152,9 +148,7 @@ static void pdc_console_poll(unsigned long unused)
}
if (count)
tty_flip_buffer_push(tty);
tty_kref_put(tty);
tty_flip_buffer_push(&tty_port);
if (pdc_cons.flags & CON_ENABLED)
mod_timer(&pdc_console_timer, jiffies + PDC_CONS_POLL_DELAY);
......
......@@ -27,8 +27,7 @@ struct chan {
void *data;
};
extern void chan_interrupt(struct line *line,
struct tty_struct *tty, int irq);
extern void chan_interrupt(struct line *line, int irq);
extern int parse_chan_pair(char *str, struct line *line, int device,
const struct chan_opts *opts, char **error_out);
extern int write_chan(struct chan *chan, const char *buf, int len,
......
......@@ -131,11 +131,9 @@ void chan_enable_winch(struct chan *chan, struct tty_struct *tty)
static void line_timer_cb(struct work_struct *work)
{
struct line *line = container_of(work, struct line, task.work);
struct tty_struct *tty = tty_port_tty_get(&line->port);
if (!line->throttled)
chan_interrupt(line, tty, line->driver->read_irq);
tty_kref_put(tty);
chan_interrupt(line, line->driver->read_irq);
}
int enable_chan(struct line *line)
......@@ -546,7 +544,7 @@ int parse_chan_pair(char *str, struct line *line, int device,
return 0;
}
void chan_interrupt(struct line *line, struct tty_struct *tty, int irq)
void chan_interrupt(struct line *line, int irq)
{
struct tty_port *port = &line->port;
struct chan *chan = line->chan_in;
......@@ -570,8 +568,11 @@ void chan_interrupt(struct line *line, struct tty_struct *tty, int irq)
reactivate_fd(chan->fd, irq);
if (err == -EIO) {
if (chan->primary) {
if (tty != NULL)
struct tty_struct *tty = tty_port_tty_get(&line->port);
if (tty != NULL) {
tty_hangup(tty);
tty_kref_put(tty);
}
if (line->chan_out != chan)
close_one_chan(line->chan_out, 1);
}
......@@ -580,6 +581,5 @@ void chan_interrupt(struct line *line, struct tty_struct *tty, int irq)
return;
}
out:
if (tty)
tty_flip_buffer_push(tty);
tty_flip_buffer_push(port);
}
......@@ -19,11 +19,10 @@ static irqreturn_t line_interrupt(int irq, void *data)
{
struct chan *chan = data;
struct line *line = chan->line;
struct tty_struct *tty = tty_port_tty_get(&line->port);
if (line)
chan_interrupt(line, tty, irq);
tty_kref_put(tty);
chan_interrupt(line, irq);
return IRQ_HANDLED;
}
......@@ -234,7 +233,7 @@ void line_unthrottle(struct tty_struct *tty)
struct line *line = tty->driver_data;
line->throttled = 0;
chan_interrupt(line, tty, line->driver->read_irq);
chan_interrupt(line, line->driver->read_irq);
/*
* Maybe there is enough stuff pending that calling the interrupt
......
......@@ -58,7 +58,8 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
tty->port = &serial_port;
spin_lock(&timer_lock);
if (tty->count == 1) {
setup_timer(&serial_timer, rs_poll, (unsigned long)tty);
setup_timer(&serial_timer, rs_poll,
(unsigned long)&serial_port);
mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
}
spin_unlock(&timer_lock);
......@@ -97,9 +98,7 @@ static int rs_write(struct tty_struct * tty,
static void rs_poll(unsigned long priv)
{
struct tty_struct* tty = (struct tty_struct*) priv;
struct tty_port *port = tty->port;
struct tty_port *port = (struct tty_port *)priv;
struct timeval tv = { .tv_sec = 0, .tv_usec = 0 };
int i = 0;
unsigned char c;
......@@ -113,7 +112,7 @@ static void rs_poll(unsigned long priv)
}
if (i)
tty_flip_buffer_push(tty);
tty_flip_buffer_push(port);
mod_timer(&serial_timer, jiffies + SERIAL_TIMER_VALUE);
......
......@@ -886,7 +886,7 @@ static void rx_ready_hdlc(MGSLPC_INFO *info, int eom)
issue_command(info, CHA, CMD_RXFIFO);
}
static void rx_ready_async(MGSLPC_INFO *info, int tcd, struct tty_struct *tty)
static void rx_ready_async(MGSLPC_INFO *info, int tcd)
{
struct tty_port *port = &info->port;
unsigned char data, status, flag;
......@@ -894,14 +894,6 @@ static void rx_ready_async(MGSLPC_INFO *info, int tcd, struct tty_struct *tty)
int work = 0;
struct mgsl_icount *icount = &info->icount;
if (!tty) {
/* tty is not available anymore */
issue_command(info, CHA, CMD_RXRESET);
if (debug_level >= DEBUG_LEVEL_ISR)
printk("%s(%d):rx_ready_async(tty=NULL)\n",__FILE__,__LINE__);
return;
}
if (tcd) {
/* early termination, get FIFO count from RBCL register */
fifo_count = (unsigned char)(read_reg(info, CHA+RBCL) & 0x1f);
......@@ -958,7 +950,7 @@ static void rx_ready_async(MGSLPC_INFO *info, int tcd, struct tty_struct *tty)
}
if (work)
tty_flip_buffer_push(tty);
tty_flip_buffer_push(port);
}
......@@ -1218,7 +1210,7 @@ static irqreturn_t mgslpc_isr(int dummy, void *dev_id)
if (info->params.mode == MGSL_MODE_HDLC)
rx_ready_hdlc(info, isr & IRQ_RXEOM);
else
rx_ready_async(info, isr & IRQ_RXEOM, tty);
rx_ready_async(info, isr & IRQ_RXEOM);
}
/* transmit IRQs */
......
......@@ -133,8 +133,7 @@ static int ipoctal_get_icount(struct tty_struct *tty,
return 0;
}
static void ipoctal_irq_rx(struct ipoctal_channel *channel,
struct tty_struct *tty, u8 sr)
static void ipoctal_irq_rx(struct ipoctal_channel *channel, u8 sr)
{
struct tty_port *port = &channel->tty_port;
unsigned char value;
......@@ -176,7 +175,7 @@ static void ipoctal_irq_rx(struct ipoctal_channel *channel,
sr = ioread8(&channel->regs->r.sr);
} while (isr & channel->isr_rx_rdy_mask);
tty_flip_buffer_push(tty);
tty_flip_buffer_push(port);
}
static void ipoctal_irq_tx(struct ipoctal_channel *channel)
......@@ -209,15 +208,11 @@ static void ipoctal_irq_tx(struct ipoctal_channel *channel)
static void ipoctal_irq_channel(struct ipoctal_channel *channel)
{
u8 isr, sr;
struct tty_struct *tty;
/* If there is no client, skip the check */
if (!atomic_read(&channel->open))
return;
tty = tty_port_tty_get(&channel->tty_port);
if (!tty)
return;
/* The HW is organized in pair of channels. See which register we need
* to read from */
isr = ioread8(&channel->block_regs->r.isr);
......@@ -236,14 +231,13 @@ static void ipoctal_irq_channel(struct ipoctal_channel *channel)
/* RX data */
if ((isr & channel->isr_rx_rdy_mask) && (sr & SR_RX_READY))
ipoctal_irq_rx(channel, tty, sr);
ipoctal_irq_rx(channel, sr);
/* TX of each character */
if ((isr & channel->isr_tx_rdy_mask) && (sr & SR_TX_READY))
ipoctal_irq_tx(channel);
tty_flip_buffer_push(tty);
tty_kref_put(tty);
tty_flip_buffer_push(&channel->tty_port);
}
static irqreturn_t ipoctal_irq_handler(void *arg)
......
......@@ -562,16 +562,8 @@ void gigaset_if_free(struct cardstate *cs)
void gigaset_if_receive(struct cardstate *cs,
unsigned char *buffer, size_t len)
{
struct tty_struct *tty = tty_port_tty_get(&cs->port);
if (tty == NULL) {
gig_dbg(DEBUG_IF, "receive on closed device");
return;
}
tty_insert_flip_string(&cs->port, buffer, len);
tty_flip_buffer_push(tty);
tty_kref_put(tty);
tty_flip_buffer_push(&cs->port);
}
EXPORT_SYMBOL_GPL(gigaset_if_receive);
......
......@@ -63,16 +63,11 @@ isdn_tty_try_read(modem_info *info, struct sk_buff *skb)
struct tty_port *port = &info->port;
int c;
int len;
struct tty_struct *tty;
char last;
if (!info->online)
return 0;
tty = port->tty;
if (!tty)
return 0;
if (!(info->mcr & UART_MCR_RTS))
return 0;
......@@ -110,7 +105,7 @@ isdn_tty_try_read(modem_info *info, struct sk_buff *skb)
tty_insert_flip_char(port, last, 0xFF);
else
tty_insert_flip_char(port, last, TTY_NORMAL);
tty_flip_buffer_push(tty);
tty_flip_buffer_push(port);
kfree_skb(skb);
return 1;
......@@ -127,7 +122,6 @@ isdn_tty_readmodem(void)
int midx;
int i;
int r;
struct tty_struct *tty;
modem_info *info;
for (i = 0; i < ISDN_MAX_CHANNELS; i++) {
......@@ -145,20 +139,21 @@ isdn_tty_readmodem(void)
if ((info->vonline & 1) && (info->emu.vpar[1]))
isdn_audio_eval_silence(info);
#endif
tty = info->port.tty;
if (tty) {
if (info->mcr & UART_MCR_RTS) {
/* CISCO AsyncPPP Hack */
if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP))
r = isdn_readbchan_tty(info->isdn_driver, info->isdn_channel, &info->port, 0);
else
r = isdn_readbchan_tty(info->isdn_driver, info->isdn_channel, &info->port, 1);
if (r)
tty_flip_buffer_push(tty);
} else
r = 1;
if (info->mcr & UART_MCR_RTS) {
/* CISCO AsyncPPP Hack */
if (!(info->emu.mdmreg[REG_CPPP] & BIT_CPPP))
r = isdn_readbchan_tty(info->isdn_driver,
info->isdn_channel,
&info->port, 0);
else
r = isdn_readbchan_tty(info->isdn_driver,
info->isdn_channel,
&info->port, 1);
if (r)
tty_flip_buffer_push(&info->port);
} else
r = 1;
if (r) {
info->rcvsched = 0;
resched = 1;
......@@ -2230,7 +2225,6 @@ isdn_tty_stat_callback(int i, isdn_ctrl *c)
void
isdn_tty_at_cout(char *msg, modem_info *info)
{
struct tty_struct *tty;
struct tty_port *port = &info->port;
atemu *m = &info->emu;
char *p;
......@@ -2248,8 +2242,7 @@ isdn_tty_at_cout(char *msg, modem_info *info)
l = strlen(msg);
spin_lock_irqsave(&info->readlock, flags);
tty = port->tty;
if ((port->flags & ASYNC_CLOSING) || (!tty)) {
if (port->flags & ASYNC_CLOSING) {
spin_unlock_irqrestore(&info->readlock, flags);
return;
}
......@@ -2301,7 +2294,7 @@ isdn_tty_at_cout(char *msg, modem_info *info)
} else {
spin_unlock_irqrestore(&info->readlock, flags);
tty_flip_buffer_push(tty);
tty_flip_buffer_push(port);
}
}
......
......@@ -381,7 +381,6 @@ static void sdio_uart_stop_rx(struct sdio_uart_port *port)
static void sdio_uart_receive_chars(struct sdio_uart_port *port,
unsigned int *status)
{
struct tty_struct *tty = tty_port_tty_get(&port->port);
unsigned int ch, flag;
int max_count = 256;
......@@ -418,24 +417,19 @@ static void sdio_uart_receive_chars(struct sdio_uart_port *port,
}
if ((*status & port->ignore_status_mask & ~UART_LSR_OE) == 0)
if (tty)
tty_insert_flip_char(&port->port, ch, flag);
tty_insert_flip_char(&port->port, ch, flag);
/*
* Overrun is special. Since it's reported immediately,
* it doesn't affect the current character.
*/
if (*status & ~port->ignore_status_mask & UART_LSR_OE)
if (tty)
tty_insert_flip_char(&port->port, 0,
TTY_OVERRUN);
tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);
*status = sdio_in(port, UART_LSR);
} while ((*status & UART_LSR_DR) && (max_count-- > 0));
if (tty) {
tty_flip_buffer_push(tty);
tty_kref_put(tty);
}
tty_flip_buffer_push(&port->port);
}
static void sdio_uart_transmit_chars(struct sdio_uart_port *port)
......
......@@ -2035,24 +2035,23 @@ static int put_rxbuf_data(struct urb *urb, struct hso_serial *serial)
tty = tty_port_tty_get(&serial->port);
/* Push data to tty */
if (tty) {
write_length_remaining = urb->actual_length -
serial->curr_rx_urb_offset;
D1("data to push to tty");
while (write_length_remaining) {
if (test_bit(TTY_THROTTLED, &tty->flags)) {
tty_kref_put(tty);
return -1;
}
curr_write_len = tty_insert_flip_string(&serial->port,
urb->transfer_buffer + serial->curr_rx_urb_offset,
write_length_remaining);
serial->curr_rx_urb_offset += curr_write_len;
write_length_remaining -= curr_write_len;
tty_flip_buffer_push(tty);
write_length_remaining = urb->actual_length -
serial->curr_rx_urb_offset;
D1("data to push to tty");
while (write_length_remaining) {
if (tty && test_bit(TTY_THROTTLED, &tty->flags)) {
tty_kref_put(tty);
return -1;
}
tty_kref_put(tty);
curr_write_len = tty_insert_flip_string(&serial->port,
urb->transfer_buffer + serial->curr_rx_urb_offset,
write_length_remaining);
serial->curr_rx_urb_offset += curr_write_len;
write_length_remaining -= curr_write_len;
tty_flip_buffer_push(&serial->port);
}
tty_kref_put(tty);
if (write_length_remaining == 0) {
serial->curr_rx_urb_offset = 0;
serial->rx_urb_filled[hso_urb_to_index(serial, urb)] = 0;
......
......@@ -413,7 +413,7 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
case CTRLCHAR_CTRL:
tty_insert_flip_char(&raw->port, cchar,
TTY_NORMAL);
tty_flip_buffer_push(tty);
tty_flip_buffer_push(&raw->port);
break;
case CTRLCHAR_NONE:
......@@ -427,7 +427,7 @@ static void raw3215_irq(struct ccw_device *cdev, unsigned long intparm,
count -= 2;
tty_insert_flip_string(&raw->port, raw->inbuf,
count);
tty_flip_buffer_push(tty);
tty_flip_buffer_push(&raw->port);
break;
}
} else if (req->type == RAW3215_WRITE) {
......
......@@ -343,7 +343,7 @@ sclp_tty_input(unsigned char* buf, unsigned int count)
break;
case CTRLCHAR_CTRL:
tty_insert_flip_char(&sclp_port, cchar, TTY_NORMAL);
tty_flip_buffer_push(tty);
tty_flip_buffer_push(&sclp_port);
break;
case CTRLCHAR_NONE:
/* send (normal) input to line discipline */
......@@ -355,7 +355,7 @@ sclp_tty_input(unsigned char* buf, unsigned int count)
tty_insert_flip_char(&sclp_port, '\n', TTY_NORMAL);
} else
tty_insert_flip_string(&sclp_port, buf, count - 2);
tty_flip_buffer_push(tty);
tty_flip_buffer_push(&sclp_port);
break;
}
tty_kref_put(tty);
......
......@@ -461,14 +461,9 @@ sclp_vt220_write(struct tty_struct *tty, const unsigned char *buf, int count)
static void
sclp_vt220_receiver_fn(struct evbuf_header *evbuf)
{
struct tty_struct *tty = tty_port_tty_get(&sclp_vt220_port);
char *buffer;
unsigned int count;
/* Ignore input if device is not open */
if (tty == NULL)
return;
buffer = (char *) ((addr_t) evbuf + sizeof(struct evbuf_header));
count = evbuf->length - sizeof(struct evbuf_header);
......@@ -481,10 +476,9 @@ sclp_vt220_receiver_fn(struct evbuf_header *evbuf)
buffer++;
count--;
tty_insert_flip_string(&sclp_vt220_port, buffer, count);
tty_flip_buffer_push(tty);
tty_flip_buffer_push(&sclp_vt220_port);
break;
}
tty_kref_put(tty);
}
/*
......
......@@ -491,12 +491,8 @@ static void gs_rx_push(unsigned long _port)
req = list_first_entry(queue, struct usb_request, list);
/* discard data if tty was closed */
if (!tty)
goto recycle;
/* leave data queued if tty was rx throttled */
if (test_bit(TTY_THROTTLED, &tty->flags))
if (tty && test_bit(TTY_THROTTLED, &tty->flags))
break;
switch (req->status) {
......@@ -542,7 +538,6 @@ static void gs_rx_push(unsigned long _port)
}
port->n_read = 0;
}
recycle:
list_move(&req->list, &port->read_pool);
port->read_started--;
}
......@@ -550,8 +545,8 @@ recycle:
/* Push from tty to ldisc; without low_latency set this is handled by
* a workqueue, so we won't get callbacks and can hold port_lock
*/
if (tty && do_push)
tty_flip_buffer_push(tty);
if (do_push)
tty_flip_buffer_push(&port->port);
/* We want our data queue to become empty ASAP, keeping data
......
......@@ -234,7 +234,7 @@ static void dgrp_input(struct ch_struct *ch)
tty_insert_flip_string_flags(&ch->port, myflipbuf,
myflipflagbuf, len);
tty_flip_buffer_push(tty);
tty_flip_buffer_push(&ch->port);
ch->ch_rxcount += len;
}
......@@ -2958,7 +2958,7 @@ check_query:
tty_buffer_request_room(&ch->port, 1);
tty_insert_flip_char(&ch->port, 0, TTY_BREAK);
tty_flip_buffer_push(ch->ch_tun.un_tty);
tty_flip_buffer_push(&ch->port);
}
......
......@@ -489,16 +489,11 @@ static void fwtty_do_hangup(struct work_struct *work)
static void fwtty_emit_breaks(struct work_struct *work)
{
struct fwtty_port *port = to_port(to_delayed_work(work), emit_breaks);
struct tty_struct *tty;
static const char buf[16];
unsigned long now = jiffies;
unsigned long elapsed = now - port->break_last;
int n, t, c, brk = 0;
tty = tty_port_tty_get(&port->port);
if (!tty)
return;
/* generate breaks at the line rate (but at least 1) */
n = (elapsed * port->cps) / HZ + 1;
port->break_last = now;
......@@ -514,9 +509,7 @@ static void fwtty_emit_breaks(struct work_struct *work)
if (c < t)
break;
}
tty_flip_buffer_push(tty);
tty_kref_put(tty);
tty_flip_buffer_push(&port->port);
if (port->mstatus & (UART_LSR_BI << 24))
schedule_delayed_work(&port->emit_breaks, FREQ_BREAKS);
......@@ -530,10 +523,6 @@ static void fwtty_pushrx(struct work_struct *work)
struct buffered_rx *buf, *next;
int n, c = 0;
tty = tty_port_tty_get(&port->port);
if (!tty)
return;
spin_lock_bh(&port->lock);
list_for_each_entry_safe(buf, next, &port->buf_list, list) {
n = tty_insert_flip_string_fixed_flag(&port->port, buf->data,
......@@ -545,7 +534,11 @@ static void fwtty_pushrx(struct work_struct *work)
memmove(buf->data, buf->data + n, buf->n - n);
buf->n -= n;
}
__fwtty_throttle(port, tty);
tty = tty_port_tty_get(&port->port);
if (tty) {
__fwtty_throttle(port, tty);
tty_kref_put(tty);
}
break;
} else {
list_del(&buf->list);
......@@ -553,13 +546,11 @@ static void fwtty_pushrx(struct work_struct *work)
}
}
if (c > 0)
tty_flip_buffer_push(tty);
tty_flip_buffer_push(&port->port);
if (list_empty(&port->buf_list))
clear_bit(BUFFERING_RX, &port->flags);
spin_unlock_bh(&port->lock);
tty_kref_put(tty);
}
static int fwtty_buffer_rx(struct fwtty_port *port, unsigned char *d, size_t n)
......@@ -594,10 +585,6 @@ static int fwtty_rx(struct fwtty_port *port, unsigned char *data, size_t len)
unsigned lsr;