Skip to content

Commit

Permalink
tty: The big operations rework
Browse files Browse the repository at this point in the history
- Operations are now a shared const function block as with most other Linux
  objects

- Introduce wrappers for some optional functions to get consistent behaviour

- Wrap put_char which used to be patched by the tty layer

- Document which functions are needed/optional

- Make put_char report success/fail

- Cache the driver->ops pointer in the tty as tty->ops

- Remove various surplus lock calls we no longer need

- Remove proc_write method as noted by Alexey Dobriyan

- Introduce some missing sanity checks where certain driver/ldisc
  combinations would oops as they didn't check needed methods were present

[akpm@linux-foundation.org: fix fs/compat_ioctl.c build]
[akpm@linux-foundation.org: fix isicom]
[akpm@linux-foundation.org: fix arch/ia64/hp/sim/simserial.c build]
[akpm@linux-foundation.org: fix kgdb]
Signed-off-by: Alan Cox <alan@redhat.com>
Acked-by: Greg Kroah-Hartman <gregkh@suse.de>
Cc: Jason Wessel <jason.wessel@windriver.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Alan Cox authored and Linus Torvalds committed Apr 30, 2008
1 parent 251b8dd commit f34d7a5
Show file tree
Hide file tree
Showing 30 changed files with 537 additions and 664 deletions.
11 changes: 7 additions & 4 deletions arch/ia64/hp/sim/simserial.c
Original file line number Diff line number Diff line change
Expand Up @@ -210,21 +210,23 @@ static void do_softint(struct work_struct *private_)
printk(KERN_ERR "simserial: do_softint called\n");
}

static void rs_put_char(struct tty_struct *tty, unsigned char ch)
static int rs_put_char(struct tty_struct *tty, unsigned char ch)
{
struct async_struct *info = (struct async_struct *)tty->driver_data;
unsigned long flags;

if (!tty || !info->xmit.buf) return;
if (!tty || !info->xmit.buf)
return 0;

local_irq_save(flags);
if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE) == 0) {
local_irq_restore(flags);
return;
return 0;
}
info->xmit.buf[info->xmit.head] = ch;
info->xmit.head = (info->xmit.head + 1) & (SERIAL_XMIT_SIZE-1);
local_irq_restore(flags);
return 1;
}

static void transmit_chars(struct async_struct *info, int *intr_done)
Expand Down Expand Up @@ -621,7 +623,8 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
* the line discipline to only process XON/XOFF characters.
*/
shutdown(info);
if (tty->driver->flush_buffer) tty->driver->flush_buffer(tty);
if (tty->ops->flush_buffer)
tty->ops->flush_buffer(tty);
if (tty->ldisc.flush_buffer) tty->ldisc.flush_buffer(tty);
info->event = 0;
info->tty = NULL;
Expand Down
13 changes: 5 additions & 8 deletions drivers/bluetooth/hci_ldisc.c
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ int hci_uart_tx_wakeup(struct hci_uart *hu)
int len;

set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
len = tty->driver->write(tty, skb->data, skb->len);
len = tty->ops->write(tty, skb->data, skb->len);
hdev->stat.byte_tx += len;

skb_pull(skb, len);
Expand Down Expand Up @@ -190,8 +190,7 @@ static int hci_uart_flush(struct hci_dev *hdev)

/* Flush any pending characters in the driver and discipline. */
tty_ldisc_flush(tty);
if (tty->driver && tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
tty_driver_flush_buffer(tty);

if (test_bit(HCI_UART_PROTO_SET, &hu->flags))
hu->proto->flush(hu);
Expand Down Expand Up @@ -285,9 +284,7 @@ static int hci_uart_tty_open(struct tty_struct *tty)

if (tty->ldisc.flush_buffer)
tty->ldisc.flush_buffer(tty);

if (tty->driver && tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
tty_driver_flush_buffer(tty);

return 0;
}
Expand Down Expand Up @@ -374,8 +371,8 @@ static void hci_uart_tty_receive(struct tty_struct *tty, const u8 *data, char *f
spin_unlock(&hu->rx_lock);

if (test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
tty->driver->unthrottle)
tty->driver->unthrottle(tty);
tty->ops->unthrottle)
tty->ops->unthrottle(tty);
}

static int hci_uart_register_dev(struct hci_uart *hu)
Expand Down
12 changes: 6 additions & 6 deletions drivers/char/ip2/ip2main.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ static int Fip_firmware_size;
static int ip2_open(PTTY, struct file *);
static void ip2_close(PTTY, struct file *);
static int ip2_write(PTTY, const unsigned char *, int);
static void ip2_putchar(PTTY, unsigned char);
static int ip2_putchar(PTTY, unsigned char);
static void ip2_flush_chars(PTTY);
static int ip2_write_room(PTTY);
static int ip2_chars_in_buf(PTTY);
Expand Down Expand Up @@ -1616,10 +1616,9 @@ ip2_close( PTTY tty, struct file *pFile )

serviceOutgoingFifo ( pCh->pMyBord );

if ( tty->driver->flush_buffer )
tty->driver->flush_buffer(tty);
if ( tty->ldisc.flush_buffer )
tty->ldisc.flush_buffer(tty);
if ( tty->driver->ops->flush_buffer )
tty->driver->ops->flush_buffer(tty);
tty_ldisc_flush(tty);
tty->closing = 0;

pCh->pTTY = NULL;
Expand Down Expand Up @@ -1738,7 +1737,7 @@ ip2_write( PTTY tty, const unsigned char *pData, int count)
/* */
/* */
/******************************************************************************/
static void
static int
ip2_putchar( PTTY tty, unsigned char ch )
{
i2ChanStrPtr pCh = tty->driver_data;
Expand All @@ -1753,6 +1752,7 @@ ip2_putchar( PTTY tty, unsigned char ch )
ip2_flush_chars( tty );
} else
write_unlock_irqrestore(&pCh->Pbuf_spinlock, flags);
return 1;

// ip2trace (CHANN, ITRC_PUTC, ITRC_RETURN, 1, ch );
}
Expand Down
15 changes: 8 additions & 7 deletions drivers/char/isicom.c
Original file line number Diff line number Diff line change
Expand Up @@ -1140,28 +1140,29 @@ static int isicom_write(struct tty_struct *tty, const unsigned char *buf,
}

/* put_char et all */
static void isicom_put_char(struct tty_struct *tty, unsigned char ch)
static int isicom_put_char(struct tty_struct *tty, unsigned char ch)
{
struct isi_port *port = tty->driver_data;
struct isi_board *card = port->card;
unsigned long flags;

if (isicom_paranoia_check(port, tty->name, "isicom_put_char"))
return;
return 0;

if (!port->xmit_buf)
return;
return 0;

spin_lock_irqsave(&card->card_lock, flags);
if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1)
goto out;
if (port->xmit_cnt >= SERIAL_XMIT_SIZE - 1) {
spin_unlock_irqrestore(&card->card_lock, flags);
return 0;
}

port->xmit_buf[port->xmit_head++] = ch;
port->xmit_head &= (SERIAL_XMIT_SIZE - 1);
port->xmit_cnt++;
spin_unlock_irqrestore(&card->card_lock, flags);
out:
return;
return 1;
}

/* flush_chars et all */
Expand Down
2 changes: 1 addition & 1 deletion drivers/char/keyboard.c
Original file line number Diff line number Diff line change
Expand Up @@ -1230,7 +1230,7 @@ static void kbd_keycode(unsigned int keycode, int down, int hw_raw)

if (rep &&
(!vc_kbd_mode(kbd, VC_REPEAT) ||
(tty && !L_ECHO(tty) && tty->driver->chars_in_buffer(tty)))) {
(tty && !L_ECHO(tty) && tty_chars_in_buffer(tty)))) {
/*
* Don't repeat a key if the input buffers are not empty and the
* characters get aren't echoed locally. This makes key repeat
Expand Down
11 changes: 4 additions & 7 deletions drivers/char/n_hdlc.c
Original file line number Diff line number Diff line change
Expand Up @@ -342,12 +342,10 @@ static int n_hdlc_tty_open (struct tty_struct *tty)
#endif

/* Flush any pending characters in the driver and discipline. */

if (tty->ldisc.flush_buffer)
tty->ldisc.flush_buffer (tty);
tty->ldisc.flush_buffer(tty);

if (tty->driver->flush_buffer)
tty->driver->flush_buffer (tty);
tty_driver_flush_buffer(tty);

if (debuglevel >= DEBUG_LEVEL_INFO)
printk("%s(%d)n_hdlc_tty_open() success\n",__FILE__,__LINE__);
Expand Down Expand Up @@ -399,7 +397,7 @@ static void n_hdlc_send_frames(struct n_hdlc *n_hdlc, struct tty_struct *tty)

/* Send the next block of data to device */
tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
actual = tty->driver->write(tty, tbuf->buf, tbuf->count);
actual = tty->ops->write(tty, tbuf->buf, tbuf->count);

/* rollback was possible and has been done */
if (actual == -ERESTARTSYS) {
Expand Down Expand Up @@ -752,8 +750,7 @@ static int n_hdlc_tty_ioctl(struct tty_struct *tty, struct file *file,

case TIOCOUTQ:
/* get the pending tx byte count in the driver */
count = tty->driver->chars_in_buffer ?
tty->driver->chars_in_buffer(tty) : 0;
count = tty_chars_in_buffer(tty);
/* add size of next output frame in queue */
spin_lock_irqsave(&n_hdlc->tx_buf_list.spinlock,flags);
if (n_hdlc->tx_buf_list.head)
Expand Down
17 changes: 7 additions & 10 deletions drivers/char/n_r3964.c
Original file line number Diff line number Diff line change
Expand Up @@ -376,8 +376,9 @@ static void put_char(struct r3964_info *pInfo, unsigned char ch)
if (tty == NULL)
return;

if (tty->driver->put_char) {
tty->driver->put_char(tty, ch);
/* FIXME: put_char should not be called from an IRQ */
if (tty->ops->put_char) {
tty->ops->put_char(tty, ch);
}
pInfo->bcc ^= ch;
}
Expand All @@ -386,12 +387,9 @@ static void flush(struct r3964_info *pInfo)
{
struct tty_struct *tty = pInfo->tty;

if (tty == NULL)
if (tty == NULL || tty->ops->flush_chars == NULL)
return;

if (tty->driver->flush_chars) {
tty->driver->flush_chars(tty);
}
tty->ops->flush_chars(tty);
}

static void trigger_transmit(struct r3964_info *pInfo)
Expand Down Expand Up @@ -449,12 +447,11 @@ static void transmit_block(struct r3964_info *pInfo)
struct r3964_block_header *pBlock = pInfo->tx_first;
int room = 0;

if ((tty == NULL) || (pBlock == NULL)) {
if (tty == NULL || pBlock == NULL) {
return;
}

if (tty->driver->write_room)
room = tty->driver->write_room(tty);
room = tty_write_room(tty);

TRACE_PS("transmit_block %p, room %d, length %d",
pBlock, room, pBlock->length);
Expand Down
Loading

0 comments on commit f34d7a5

Please sign in to comment.