Commit f34d7a5b authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

tty: The big operations rework

- 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: 's avatarAlan Cox <alan@redhat.com>
Acked-by: 's avatarGreg Kroah-Hartman <gregkh@suse.de>
Cc: Jason Wessel <jason.wessel@windriver.com>
Signed-off-by: 's avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: 's avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 251b8dd7
......@@ -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)
......@@ -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;
......
......@@ -143,7 +143,7 @@ restart:
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);
......@@ -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);
......@@ -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;
}
......@@ -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)
......
......@@ -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);
......@@ -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;
......@@ -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;
......@@ -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 );
}
......
......@@ -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 */
......
......@@ -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
......
......@@ -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__);
......@@ -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) {
......@@ -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)
......
......@@ -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;
}
......@@ -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)
......@@ -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);
......
......@@ -149,8 +149,8 @@ static void check_unthrottle(struct tty_struct *tty)
{
if (tty->count &&
test_and_clear_bit(TTY_THROTTLED, &tty->flags) &&
tty->driver->unthrottle)
tty->driver->unthrottle(tty);
tty->ops->unthrottle)
tty->ops->unthrottle(tty);
}
/**
......@@ -273,7 +273,7 @@ static int opost(unsigned char c, struct tty_struct *tty)
{
int space, spaces;
space = tty->driver->write_room(tty);
space = tty_write_room(tty);
if (!space)
return -1;
......@@ -286,7 +286,7 @@ static int opost(unsigned char c, struct tty_struct *tty)
if (O_ONLCR(tty)) {
if (space < 2)
return -1;
tty->driver->put_char(tty, '\r');
tty_put_char(tty, '\r');
tty->column = 0;
}
tty->canon_column = tty->column;
......@@ -308,7 +308,7 @@ static int opost(unsigned char c, struct tty_struct *tty)
if (space < spaces)
return -1;
tty->column += spaces;
tty->driver->write(tty, " ", spaces);
tty->ops->write(tty, " ", spaces);
return 0;
}
tty->column += spaces;
......@@ -325,7 +325,7 @@ static int opost(unsigned char c, struct tty_struct *tty)
break;
}
}
tty->driver->put_char(tty, c);
tty_put_char(tty, c);
unlock_kernel();
return 0;
}
......@@ -352,7 +352,7 @@ static ssize_t opost_block(struct tty_struct *tty,
int i;
const unsigned char *cp;
space = tty->driver->write_room(tty);
space = tty_write_room(tty);
if (!space)
return 0;
if (nr > space)
......@@ -390,27 +390,14 @@ static ssize_t opost_block(struct tty_struct *tty,
}
}
break_out:
if (tty->driver->flush_chars)
tty->driver->flush_chars(tty);
i = tty->driver->write(tty, buf, i);
if (tty->ops->flush_chars)
tty->ops->flush_chars(tty);
i = tty->ops->write(tty, buf, i);
unlock_kernel();
return i;
}
/**
* put_char - write character to driver
* @c: character (or part of unicode symbol)
* @tty: terminal device
*
* Queue a byte to the driver layer for output
*/
static inline void put_char(unsigned char c, struct tty_struct *tty)
{
tty->driver->put_char(tty, c);
}
/**
* echo_char - echo characters
* @c: unicode byte to echo
......@@ -423,8 +410,8 @@ static inline void put_char(unsigned char c, struct tty_struct *tty)
static void echo_char(unsigned char c, struct tty_struct *tty)
{
if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t') {
put_char('^', tty);
put_char(c ^ 0100, tty);
tty_put_char(tty, '^');
tty_put_char(tty, c ^ 0100);
tty->column += 2;
} else
opost(c, tty);
......@@ -433,7 +420,7 @@ static void echo_char(unsigned char c, struct tty_struct *tty)
static inline void finish_erasing(struct tty_struct *tty)
{
if (tty->erasing) {
put_char('/', tty);
tty_put_char(tty, '/');
tty->column++;
tty->erasing = 0;
}
......@@ -517,7 +504,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
if (L_ECHO(tty)) {
if (L_ECHOPRT(tty)) {
if (!tty->erasing) {
put_char('\\', tty);
tty_put_char(tty, '\\');
tty->column++;
tty->erasing = 1;
}
......@@ -525,7 +512,7 @@ static void eraser(unsigned char c, struct tty_struct *tty)
echo_char(c, tty);
while (--cnt > 0) {
head = (head+1) & (N_TTY_BUF_SIZE-1);
put_char(tty->read_buf[head], tty);
tty_put_char(tty, tty->read_buf[head]);
}
} else if (kill_type == ERASE && !L_ECHOE(tty)) {
echo_char(ERASE_CHAR(tty), tty);
......@@ -553,22 +540,22 @@ static void eraser(unsigned char c, struct tty_struct *tty)
/* Now backup to that column. */
while (tty->column > col) {
/* Can't use opost here. */
put_char('\b', tty);
tty_put_char(tty, '\b');
if (tty->column > 0)
tty->column--;
}
} else {
if (iscntrl(c) && L_ECHOCTL(tty)) {
put_char('\b', tty);
put_char(' ', tty);
put_char('\b', tty);
tty_put_char(tty, '\b');
tty_put_char(tty, ' ');
tty_put_char(tty, '\b');
if (tty->column > 0)
tty->column--;
}
if (!iscntrl(c) || L_ECHOCTL(tty)) {
put_char('\b', tty);
put_char(' ', tty);
put_char('\b', tty);
tty_put_char(tty, '\b');
tty_put_char(tty, ' ');
tty_put_char(tty, '\b');
if (tty->column > 0)
tty->column--;
}
......@@ -599,8 +586,7 @@ static inline void isig(int sig, struct tty_struct *tty, int flush)
kill_pgrp(tty->pgrp, sig, 1);
if (flush || !L_NOFLSH(tty)) {
n_tty_flush_buffer(tty);
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
tty_driver_flush_buffer(tty);
}
}
......@@ -732,7 +718,7 @@ static inline void n_tty_receive_char(struct tty_struct *tty, unsigned char c)
tty->lnext = 0;
if (L_ECHO(tty)) {
if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
put_char('\a', tty); /* beep if no space */
tty_put_char(tty, '\a'); /* beep if no space */
return;
}
/* Record the column of first canon char. */
......@@ -776,8 +762,7 @@ send_signal:
*/
if (!L_NOFLSH(tty)) {
n_tty_flush_buffer(tty);
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
tty_driver_flush_buffer(tty);
}
if (L_ECHO(tty))
echo_char(c, tty);
......@@ -806,8 +791,8 @@ send_signal:
if (L_ECHO(tty)) {
finish_erasing(tty);
if (L_ECHOCTL(tty)) {
put_char('^', tty);
put_char('\b', tty);
tty_put_char(tty, '^');
tty_put_char(tty, '\b');
}
}
return;
......@@ -828,7 +813,7 @@ send_signal:
if (c == '\n') {
if (L_ECHO(tty) || L_ECHONL(tty)) {
if (tty->read_cnt >= N_TTY_BUF_SIZE-1)
put_char('\a', tty);
tty_put_char(tty, '\a');
opost('\n', tty);
}
goto handle_newline;
......@@ -846,7 +831,7 @@ send_signal:
*/
if (L_ECHO(tty)) {
if (tty->read_cnt >= N_TTY_BUF_SIZE-1)
put_char('\a', tty);
tty_put_char(tty, '\a');
/* Record the column of first canon char. */
if (tty->canon_head == tty->read_head)
tty->canon_column = tty->column;
......@@ -876,7 +861,7 @@ handle_newline:
finish_erasing(tty);
if (L_ECHO(tty)) {
if (tty->read_cnt >= N_TTY_BUF_SIZE-1) {
put_char('\a', tty); /* beep if no space */
tty_put_char(tty, '\a'); /* beep if no space */
return;
}
if (c == '\n')
......@@ -980,8 +965,8 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
break;
}
}
if (tty->driver->flush_chars)
tty->driver->flush_chars(tty);
if (tty->ops->flush_chars)
tty->ops->flush_chars(tty);
}
n_tty_set_room(tty);
......@@ -1000,8 +985,8 @@ static void n_tty_receive_buf(struct tty_struct *tty, const unsigned char *cp,
if (tty->receive_room < TTY_THRESHOLD_THROTTLE) {
/* check TTY_THROTTLED first so it indicates our state */
if (!test_and_set_bit(TTY_THROTTLED, &tty->flags) &&
tty->driver->throttle)
tty->driver->throttle(tty);
tty->ops->throttle)
tty->ops->throttle(tty);
}
}
......@@ -1086,6 +1071,9 @@ static void n_tty_set_termios(struct tty_struct *tty, struct ktermios *old)
tty->real_raw = 0;
}
n_tty_set_room(tty);
/* The termios change make the tty ready for I/O */
wake_up_interruptible(&tty->write_wait);
wake_up_interruptible(&tty->read_wait);
}
/**
......@@ -1513,11 +1501,11 @@ static ssize_t write_chan(struct tty_struct *tty, struct file *file,
break;
b++; nr--;
}
if (tty->driver->flush_chars)
tty->driver->flush_chars(tty);
if (tty->ops->flush_chars)
tty->ops->flush_chars(tty);
} else {
while (nr > 0) {
c = tty->driver->write(tty, b, nr);
c = tty->ops->write(tty, b, nr);
if (c < 0) {
retval = c;
goto break_out;
......@@ -1554,11 +1542,6 @@ break_out:
*
* This code must be sure never to sleep through a hangup.
* Called without the kernel lock held - fine
*
* FIXME: if someone changes the VMIN or discipline settings for the
* terminal while another process is in poll() the poll does not
* recompute the new limits. Possibly set_termios should issue
* a read wakeup to fix this bug.
*/
static unsigned int normal_poll(struct tty_struct *tty, struct file *file,
......@@ -1582,9 +1565,9 @@ static unsigned int normal_poll(struct tty_struct *tty, struct file *file,
else
tty->minimum_to_wake = 1;
}
if (!tty_is_writelocked(tty) &&
tty->driver->chars_in_buffer(tty) < WAKEUP_CHARS &&
tty->driver->write_room(tty) > 0)
if (tty->ops->write && !tty_is_writelocked(tty) &&
tty_chars_in_buffer(tty) < WAKEUP_CHARS &&
tty_write_room(tty) > 0)
mask |= POLLOUT | POLLWRNORM;
return mask;
}
......
This diff is collapsed.
......@@ -40,6 +40,34 @@
#define TERMIOS_OLD 8
int tty_chars_in_buffer(struct tty_struct *tty)
{
if (tty->ops->chars_in_buffer)
return tty->ops->chars_in_buffer(tty);
else
return 0;
}
EXPORT_SYMBOL(tty_chars_in_buffer);
int tty_write_room(struct tty_struct *tty)
{
if (tty->ops->write_room)
return tty->ops->write_room(tty);
return 2048;
}
EXPORT_SYMBOL(tty_write_room);
void tty_driver_flush_buffer(struct tty_struct *tty)
{
if (tty->ops->flush_buffer)
tty->ops->flush_buffer(tty);
}
EXPORT_SYMBOL(tty_driver_flush_buffer);
/**
* tty_wait_until_sent - wait for I/O to finish
* @tty: tty we are waiting for
......@@ -58,17 +86,13 @@ void tty_wait_until_sent(struct tty_struct *tty, long timeout)
printk(KERN_DEBUG "%s wait until sent...\n", tty_name(tty, buf));
#endif
if (!tty->driver->chars_in_buffer)
return;
if (!timeout)
timeout = MAX_SCHEDULE_TIMEOUT;
lock_kernel();
if (wait_event_interruptible_timeout(tty->write_wait,
!tty->driver->chars_in_buffer(tty), timeout) >= 0) {
if (tty->driver->wait_until_sent)
tty->driver->wait_until_sent(tty, timeout);
!tty_chars_in_buffer(tty), timeout) >= 0) {
if (tty->ops->wait_until_sent)
tty->ops->wait_until_sent(tty, timeout);
}
unlock_kernel();
}
EXPORT_SYMBOL(tty_wait_until_sent);
......@@ -444,8 +468,8 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
}
}
if (tty->driver->set_termios)
(*tty->driver->set_termios)(tty, &old_termios);
if (tty->ops->set_termios)
(*tty->ops->set_termios)(tty, &old_termios);
else
tty_termios_copy_hw(tty->termios, &old_termios);
......@@ -748,8 +772,8 @@ static int send_prio_char(struct tty_struct *tty, char ch)
{
int was_stopped = tty->stopped;
if (tty->driver->send_xchar) {
tty->driver->send_xchar(tty, ch);
if (tty->ops->send_xchar) {
tty->ops->send_xchar(tty, ch);
return 0;
}
......@@ -758,7 +782,7 @@ static int send_prio_char(struct tty_struct *tty, char ch)
if (was_stopped)
start_tty(tty);
tty->driver->write(tty, &ch, 1);
tty->ops->write(tty, &ch, 1);
if (was_stopped)
stop_tty(tty);
tty_write_unlock(tty);
......@@ -778,13 +802,14 @@ static int tty_change_softcar(struct tty_struct *tty, int arg)
{
int ret = 0;
int bit = arg ? CLOCAL : 0;
struct ktermios old = *tty->termios;
struct ktermios old;
mutex_lock(&tty->termios_mutex);
old = *tty->termios;
tty->termios->c_cflag &= ~CLOCAL;
tty->termios->c_cflag |= bit;
if (tty->driver->set_termios)
tty->driver->set_termios(tty, &old);
if (tty->ops->set_termios)
tty->ops->set_termios(tty, &old);
if ((tty->termios->c_cflag & CLOCAL) != bit)
ret = -EINVAL;
mutex_unlock(&tty->termios_mutex);
......@@ -926,8 +951,7 @@ int tty_perform_flush(struct tty_struct *tty, unsigned long arg)
ld->flush_buffer(tty);
/* fall through */
case TCOFLUSH:
if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty);
tty_driver_flush_buffer(tty);
break;
default:
tty_ldisc_deref(ld);
......@@ -984,9 +1008,7 @@ int n_tty_ioctl(struct tty_struct *tty, struct file *file,
case TCFLSH:
return tty_perform_flush(tty, arg);
case TIOCOUTQ:
return put_user(tty->driver->chars_in_buffer ?
tty->driver->chars_in_buffer(tty) : 0,
(int __user *) arg);
return put_user(tty_chars_in_buffer(tty), (int __user *) arg);
case TIOCINQ:
retval = tty->read_cnt;
if (L_ICANON(tty))
......
......@@ -46,7 +46,7 @@ struct serport {
static int serport_serio_write(struct serio *serio, unsigned char data)
{
struct serport *serport = serio->port_data;
return -(serport->tty->driver->write(serport->tty, &data, 1) != 1);
return -(serport->tty->ops->write(serport->tty, &data, 1) != 1);
}
static int serport_serio_open(struct serio *serio)
......
......@@ -68,10 +68,10 @@ static int write_modem(struct cardstate *cs)
struct tty_struct *tty = cs->hw.ser->tty;
struct bc_state *bcs = &cs->bcs[0]; /* only one channel */
struct sk_buff *skb = bcs->tx_skb;
int sent;
int sent = -EOPNOTSUPP;
if (!tty || !tty->driver || !skb)
return -EFAULT;
return -EINVAL;
if (!skb->len) {
dev_kfree_skb_any(skb);
......@@ -80,7 +80,8 @@ static int write_modem(struct cardstate *cs)
}
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
sent = tty->driver->write(tty, skb->data, skb->len);
if (tty->ops->write)
sent = tty->ops->write(tty, skb->data, skb->len);
gig_dbg(DEBUG_OUTPUT, "write_modem: sent %d", sent);
if (sent < 0) {
/* error */
......@@ -120,7 +121,7 @@ static int send_cb(struct cardstate *cs)
if (cb->len) {
set_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
sent = tty->driver->write(tty, cb->buf + cb->offset, cb->len);
sent = tty->ops->write(tty, cb->buf + cb->offset, cb->len);
if (sent < 0) {
/* error */
gig_dbg(DEBUG_OUTPUT, "send_cb: write error %d", sent);
......@@ -440,14 +441,14 @@ static int gigaset_set_modem_ctrl(struct cardstate *cs, unsigned old_state, unsi
struct tty_struct *tty = cs->hw.ser->tty;
unsigned int set, clear;
if (!tty || !tty->driver || !tty->driver->tiocmset)
return -EFAULT;
if (!tty || !tty->driver || !tty->ops->tiocmset)
return -EINVAL;
set = new_state & ~old_state;
clear = old_state & ~new_state;
if (!set && !clear)
return 0;
gig_dbg(DEBUG_IF, "tiocmset set %x clear %x", set, clear);
return tty->driver->tiocmset(tty, NULL, set, clear);
return tty->ops->tiocmset(tty, NULL, set, clear);
}
static int gigaset_baud_rate(struct cardstate *cs, unsigned cflag)
......
......@@ -148,13 +148,13 @@ static void sp_xmit_on_air(unsigned long channel)
if (((sp->status1 & SIXP_DCD_MASK) == 0) && (random < sp->persistence)) {
sp->led_state = 0x70;
sp->tty->driver->write(sp->tty, &sp->led_state, 1);
sp->tty->ops->write(sp->tty, &sp->led_state, 1);
sp->tx_enable = 1;
actual = sp->tty->driver->write(sp->tty, sp->xbuff, sp->status2);
actual = sp->tty->ops->write(sp->tty, sp->xbuff, sp->status2);
sp->xleft -= actual;