提交 e11c675e 编写于 作者: L Linus Torvalds

Merge git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6

* git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/tty-2.6: (79 commits)
  USB serial: update the console driver
  usb-serial: straighten out serial_open
  usb-serial: add missing tests and debug lines
  usb-serial: rename subroutines
  usb-serial: fix termios initialization logic
  usb-serial: acquire references when a new tty is installed
  usb-serial: change logic of serial lookups
  usb-serial: put subroutines in logical order
  usb-serial: change referencing of port and serial structures
  tty: Char: mxser, use THRE for ASPP_OQUEUE ioctl
  tty: Char: mxser, add support for CP112UL
  uartlite: support shared interrupt lines
  tty: USB: serial/mct_u232, fix tty refcnt
  tty: riscom8, fix tty refcnt
  tty: riscom8, fix shutdown declaration
  TTY: fix typos
  tty: Power: fix suspend vt regression
  tty: vt: use printk_once
  tty: handle VT specific compat ioctls in vt driver
  n_tty: move echoctl check and clean up logic
  ...
......@@ -95,7 +95,7 @@ void foo(void)
OFFSET(__iobase, mn10300_serial_port, _iobase);
DEFINE(__UART_XMIT_SIZE, UART_XMIT_SIZE);
OFFSET(__xmit_buffer, uart_info, xmit.buf);
OFFSET(__xmit_head, uart_info, xmit.head);
OFFSET(__xmit_tail, uart_info, xmit.tail);
OFFSET(__xmit_buffer, uart_state, xmit.buf);
OFFSET(__xmit_head, uart_state, xmit.head);
OFFSET(__xmit_tail, uart_state, xmit.tail);
}
此差异已折叠。
......@@ -572,7 +572,7 @@ static void check_modem_status(struct esp_struct *info)
info->icount.dcd++;
if (status & UART_MSR_DCTS)
info->icount.cts++;
wake_up_interruptible(&info->delta_msr_wait);
wake_up_interruptible(&info->port.delta_msr_wait);
}
if ((info->port.flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
......@@ -927,7 +927,7 @@ static void shutdown(struct esp_struct *info)
* clear delta_msr_wait queue to avoid mem leaks: we may free the irq
* here so the queue might never be waken up
*/
wake_up_interruptible(&info->delta_msr_wait);
wake_up_interruptible(&info->port.delta_msr_wait);
wake_up_interruptible(&info->break_wait);
/* stop a DMA transfer on the port being closed */
......@@ -1800,7 +1800,7 @@ static int rs_ioctl(struct tty_struct *tty, struct file *file,
spin_unlock_irqrestore(&info->lock, flags);
while (1) {
/* FIXME: convert to new style wakeup */
interruptible_sleep_on(&info->delta_msr_wait);
interruptible_sleep_on(&info->port.delta_msr_wait);
/* see if a signal did it */
if (signal_pending(current))
return -ERESTARTSYS;
......@@ -2452,7 +2452,6 @@ static int __init espserial_init(void)
info->config.flow_off = flow_off;
info->config.pio_threshold = pio_threshold;
info->next_port = ports;
init_waitqueue_head(&info->delta_msr_wait);
init_waitqueue_head(&info->break_wait);
ports = info;
printk(KERN_INFO "ttyP%d at 0x%04x (irq = %d) is an ESP ",
......
......@@ -846,37 +846,53 @@ static int isicom_carrier_raised(struct tty_port *port)
return (ip->status & ISI_DCD)?1 : 0;
}
static int isicom_open(struct tty_struct *tty, struct file *filp)
static struct tty_port *isicom_find_port(struct tty_struct *tty)
{
struct isi_port *port;
struct isi_board *card;
unsigned int board;
int error, line;
int line = tty->index;
line = tty->index;
if (line < 0 || line > PORT_COUNT-1)
return -ENODEV;
return NULL;
board = BOARD(line);
card = &isi_card[board];
if (!(card->status & FIRMWARE_LOADED))
return -ENODEV;
return NULL;
/* open on a port greater than the port count for the card !!! */
if (line > ((board * 16) + card->port_count - 1))
return -ENODEV;
return NULL;
port = &isi_ports[line];
if (isicom_paranoia_check(port, tty->name, "isicom_open"))
return -ENODEV;
return NULL;
return &port->port;
}
static int isicom_open(struct tty_struct *tty, struct file *filp)
{
struct isi_port *port;
struct isi_board *card;
struct tty_port *tport;
int error = 0;
tport = isicom_find_port(tty);
if (tport == NULL)
return -ENODEV;
port = container_of(tport, struct isi_port, port);
card = &isi_card[BOARD(tty->index)];
isicom_setup_board(card);
/* FIXME: locking on port.count etc */
port->port.count++;
tty->driver_data = port;
tty_port_tty_set(&port->port, tty);
error = isicom_setup_port(tty);
/* FIXME: Locking on Initialized flag */
if (!test_bit(ASYNCB_INITIALIZED, &tport->flags))
error = isicom_setup_port(tty);
if (error == 0)
error = tty_port_block_til_ready(&port->port, tty, filp);
return error;
......@@ -952,19 +968,12 @@ static void isicom_flush_buffer(struct tty_struct *tty)
tty_wakeup(tty);
}
static void isicom_close(struct tty_struct *tty, struct file *filp)
static void isicom_close_port(struct tty_port *port)
{
struct isi_port *ip = tty->driver_data;
struct tty_port *port = &ip->port;
struct isi_board *card;
struct isi_port *ip = container_of(port, struct isi_port, port);
struct isi_board *card = ip->card;
unsigned long flags;
BUG_ON(!ip);
card = ip->card;
if (isicom_paranoia_check(ip, tty->name, "isicom_close"))
return;
/* indicate to the card that no more data can be received
on this port */
spin_lock_irqsave(&card->card_lock, flags);
......@@ -974,9 +983,19 @@ static void isicom_close(struct tty_struct *tty, struct file *filp)
}
isicom_shutdown_port(ip);
spin_unlock_irqrestore(&card->card_lock, flags);
}
static void isicom_close(struct tty_struct *tty, struct file *filp)
{
struct isi_port *ip = tty->driver_data;
struct tty_port *port = &ip->port;
if (isicom_paranoia_check(ip, tty->name, "isicom_close"))
return;
if (tty_port_close_start(port, tty, filp) == 0)
return;
isicom_close_port(port);
isicom_flush_buffer(tty);
tty_port_close_end(port, tty);
}
......
......@@ -48,7 +48,7 @@
#include "mxser.h"
#define MXSER_VERSION "2.0.4" /* 1.12 */
#define MXSER_VERSION "2.0.5" /* 1.14 */
#define MXSERMAJOR 174
#define MXSER_BOARDS 4 /* Max. boards */
......@@ -69,6 +69,7 @@
#define PCI_DEVICE_ID_POS104UL 0x1044
#define PCI_DEVICE_ID_CB108 0x1080
#define PCI_DEVICE_ID_CP102UF 0x1023
#define PCI_DEVICE_ID_CP112UL 0x1120
#define PCI_DEVICE_ID_CB114 0x1142
#define PCI_DEVICE_ID_CP114UL 0x1143
#define PCI_DEVICE_ID_CB134I 0x1341
......@@ -139,7 +140,8 @@ static const struct mxser_cardinfo mxser_cards[] = {
{ "CP-138U series", 8, },
{ "POS-104UL series", 4, },
{ "CP-114UL series", 4, },
/*30*/ { "CP-102UF series", 2, }
/*30*/ { "CP-102UF series", 2, },
{ "CP-112UL series", 2, },
};
/* driver_data correspond to the lines in the structure above
......@@ -170,6 +172,7 @@ static struct pci_device_id mxser_pcibrds[] = {
{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_POS104UL), .driver_data = 28 },
{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP114UL), .driver_data = 29 },
{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP102UF), .driver_data = 30 },
{ PCI_VDEVICE(MOXA, PCI_DEVICE_ID_CP112UL), .driver_data = 31 },
{ }
};
MODULE_DEVICE_TABLE(pci, mxser_pcibrds);
......@@ -258,7 +261,6 @@ struct mxser_port {
struct mxser_mon mon_data;
spinlock_t slock;
wait_queue_head_t delta_msr_wait;
};
struct mxser_board {
......@@ -818,7 +820,7 @@ static void mxser_check_modem_status(struct tty_struct *tty,
if (status & UART_MSR_DCTS)
port->icount.cts++;
port->mon_data.modem_status = status;
wake_up_interruptible(&port->delta_msr_wait);
wake_up_interruptible(&port->port.delta_msr_wait);
if ((port->port.flags & ASYNC_CHECK_CD) && (status & UART_MSR_DDCD)) {
if (status & UART_MSR_DCD)
......@@ -973,7 +975,7 @@ static void mxser_shutdown(struct tty_struct *tty)
* clear delta_msr_wait queue to avoid mem leaks: we may free the irq
* here so the queue might never be waken up
*/
wake_up_interruptible(&info->delta_msr_wait);
wake_up_interruptible(&info->port.delta_msr_wait);
/*
* Free the IRQ, if necessary
......@@ -1073,34 +1075,17 @@ static void mxser_flush_buffer(struct tty_struct *tty)
}
/*
* This routine is called when the serial port gets closed. First, we
* wait for the last remaining data to be sent. Then, we unlink its
* async structure from the interrupt chain if necessary, and we free
* that IRQ if nothing is left in the chain.
*/
static void mxser_close(struct tty_struct *tty, struct file *filp)
static void mxser_close_port(struct tty_struct *tty, struct tty_port *port)
{
struct mxser_port *info = tty->driver_data;
struct tty_port *port = &info->port;
struct mxser_port *info = container_of(port, struct mxser_port, port);
unsigned long timeout;
if (tty->index == MXSER_PORTS)
return;
if (!info)
return;
if (tty_port_close_start(port, tty, filp) == 0)
return;
/*
* Save the termios structure, since this port may have
* separate termios for callout and dialin.
*
* FIXME: Can this go ?
*/
if (info->port.flags & ASYNC_NORMAL_ACTIVE)
if (port->flags & ASYNC_NORMAL_ACTIVE)
info->normal_termios = *tty->termios;
/*
* At this point we stop accepting input. To do this, we
......@@ -1112,7 +1097,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
if (info->board->chip_flag)
info->IER &= ~MOXA_MUST_RECV_ISR;
if (info->port.flags & ASYNC_INITIALIZED) {
if (port->flags & ASYNC_INITIALIZED) {
outb(info->IER, info->ioaddr + UART_IER);
/*
* Before we drop DTR, make sure the UART transmitter
......@@ -1127,8 +1112,26 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
}
}
mxser_shutdown(tty);
mxser_flush_buffer(tty);
}
/*
* This routine is called when the serial port gets closed. First, we
* wait for the last remaining data to be sent. Then, we unlink its
* async structure from the interrupt chain if necessary, and we free
* that IRQ if nothing is left in the chain.
*/
static void mxser_close(struct tty_struct *tty, struct file *filp)
{
struct mxser_port *info = tty->driver_data;
struct tty_port *port = &info->port;
if (tty->index == MXSER_PORTS)
return;
if (tty_port_close_start(port, tty, filp) == 0)
return;
mxser_close_port(tty, port);
mxser_flush_buffer(tty);
/* Right now the tty_port set is done outside of the close_end helper
as we don't yet have everyone using refcounts */
tty_port_close_end(port, tty);
......@@ -1761,7 +1764,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
cnow = info->icount; /* note the counters on entry */
spin_unlock_irqrestore(&info->slock, flags);
return wait_event_interruptible(info->delta_msr_wait,
return wait_event_interruptible(info->port.delta_msr_wait,
mxser_cflags_changed(info, arg, &cnow));
/*
* Get counter of input serial line interrupts (DCD,RI,DSR,CTS)
......@@ -1803,7 +1806,7 @@ static int mxser_ioctl(struct tty_struct *tty, struct file *file,
lock_kernel();
len = mxser_chars_in_buffer(tty);
lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_TEMT;
lsr = inb(info->ioaddr + UART_LSR) & UART_LSR_THRE;
len += (lsr ? 0 : 1);
unlock_kernel();
......@@ -2413,7 +2416,6 @@ static int __devinit mxser_initbrd(struct mxser_board *brd,
info->port.close_delay = 5 * HZ / 10;
info->port.closing_wait = 30 * HZ;
info->normal_termios = mxvar_sdriver->init_termios;
init_waitqueue_head(&info->delta_msr_wait);
memset(&info->mon_data, 0, sizeof(struct mxser_mon));
info->err_shadow = 0;
spin_lock_init(&info->slock);
......
......@@ -272,7 +272,8 @@ static inline int is_continuation(unsigned char c, struct tty_struct *tty)
*
* This is a helper function that handles one output character
* (including special characters like TAB, CR, LF, etc.),
* putting the results in the tty driver's write buffer.
* doing OPOST processing and putting the results in the
* tty driver's write buffer.
*
* Note that Linux currently ignores TABDLY, CRDLY, VTDLY, FFDLY
* and NLDLY. They simply aren't relevant in the world today.
......@@ -350,8 +351,9 @@ static int do_output_char(unsigned char c, struct tty_struct *tty, int space)
* @c: character (or partial unicode symbol)
* @tty: terminal device
*
* Perform OPOST processing. Returns -1 when the output device is
* full and the character must be retried.
* Output one character with OPOST processing.
* Returns -1 when the output device is full and the character
* must be retried.
*
* Locking: output_lock to protect column state and space left
* (also, this is called from n_tty_write under the
......@@ -377,8 +379,11 @@ static int process_output(unsigned char c, struct tty_struct *tty)
/**
* process_output_block - block post processor
* @tty: terminal device
* @inbuf: user buffer
* @nr: number of bytes
* @buf: character buffer
* @nr: number of bytes to output
*
* Output a block of characters with OPOST processing.
* Returns the number of characters output.
*
* This path is used to speed up block console writes, among other
* things when processing blocks of output data. It handles only
......@@ -571,33 +576,23 @@ static void process_echoes(struct tty_struct *tty)
break;
default:
if (iscntrl(op)) {
if (L_ECHOCTL(tty)) {
/*
* Ensure there is enough space
* for the whole ctrl pair.
*/
if (space < 2) {
no_space_left = 1;
break;
}
tty_put_char(tty, '^');
tty_put_char(tty, op ^ 0100);
tty->column += 2;
space -= 2;
} else {
if (!space) {
no_space_left = 1;
break;
}
tty_put_char(tty, op);
space--;
}
}
/*
* If above falls through, this was an
* undefined op.
* If the op is not a special byte code,
* it is a ctrl char tagged to be echoed
* as "^X" (where X is the letter
* representing the control char).
* Note that we must ensure there is
* enough space for the whole ctrl pair.
*
*/
if (space < 2) {
no_space_left = 1;
break;
}
tty_put_char(tty, '^');
tty_put_char(tty, op ^ 0100);
tty->column += 2;
space -= 2;
cp += 2;
nr -= 2;
}
......@@ -605,12 +600,18 @@ static void process_echoes(struct tty_struct *tty)
if (no_space_left)
break;
} else {
int retval;
retval = do_output_char(c, tty, space);
if (retval < 0)
break;
space -= retval;
if (O_OPOST(tty) &&
!(test_bit(TTY_HW_COOK_OUT, &tty->flags))) {
int retval = do_output_char(c, tty, space);
if (retval < 0)
break;
space -= retval;
} else {
if (!space)
break;
tty_put_char(tty, c);
space -= 1;
}
cp += 1;
nr -= 1;
}
......@@ -798,8 +799,8 @@ static void echo_char_raw(unsigned char c, struct tty_struct *tty)
* Echo user input back onto the screen. This must be called only when
* L_ECHO(tty) is true. Called from the driver receive_buf path.
*
* This variant tags control characters to be possibly echoed as
* as "^X" (where X is the letter representing the control char).
* This variant tags control characters to be echoed as "^X"
* (where X is the letter representing the control char).
*
* Locking: echo_lock to protect the echo buffer
*/
......@@ -812,7 +813,7 @@ static void echo_char(unsigned char c, struct tty_struct *tty)
add_echo_byte(ECHO_OP_START, tty);
add_echo_byte(ECHO_OP_START, tty);
} else {
if (iscntrl(c) && c != '\t')
if (L_ECHOCTL(tty) && iscntrl(c) && c != '\t')
add_echo_byte(ECHO_OP_START, tty);
add_echo_byte(c, tty);
}
......
......@@ -343,7 +343,7 @@ static void rc_receive_exc(struct riscom_board const *bp)
if (port == NULL)
return;
tty = port->port.tty;
tty = tty_port_tty_get(&port->port);
#ifdef RC_REPORT_OVERRUN
status = rc_in(bp, CD180_RCSR);
......@@ -355,18 +355,18 @@ static void rc_receive_exc(struct riscom_board const *bp)
#endif
ch = rc_in(bp, CD180_RDR);
if (!status)
return;
goto out;
if (status & RCSR_TOUT) {
printk(KERN_WARNING "rc%d: port %d: Receiver timeout. "
"Hardware problems ?\n",
board_No(bp), port_No(port));
return;
goto out;
} else if (status & RCSR_BREAK) {
printk(KERN_INFO "rc%d: port %d: Handling break...\n",
board_No(bp), port_No(port));
flag = TTY_BREAK;
if (port->port.flags & ASYNC_SAK)
if (tty && (port->port.flags & ASYNC_SAK))
do_SAK(tty);
} else if (status & RCSR_PE)
......@@ -380,8 +380,12 @@ static void rc_receive_exc(struct riscom_board const *bp)
else
flag = TTY_NORMAL;
tty_insert_flip_char(tty, ch, flag);
tty_flip_buffer_push(tty);
if (tty) {
tty_insert_flip_char(tty, ch, flag);
tty_flip_buffer_push(tty);
}
out:
tty_kref_put(tty);
}
static void rc_receive(struct riscom_board const *bp)
......@@ -394,7 +398,7 @@ static void rc_receive(struct riscom_board const *bp)
if (port == NULL)
return;
tty = port->port.tty;
tty = tty_port_tty_get(&port->port);
count = rc_in(bp, CD180_RDCR);
......@@ -403,15 +407,14 @@ static void rc_receive(struct riscom_board const *bp)
#endif
while (count--) {
if (tty_buffer_request_room(tty, 1) == 0) {
printk(KERN_WARNING "rc%d: port %d: Working around "
"flip buffer overflow.\n",
board_No(bp), port_No(port));
break;
}
tty_insert_flip_char(tty, rc_in(bp, CD180_RDR), TTY_NORMAL);
u8 ch = rc_in(bp, CD180_RDR);
if (tty)
tty_insert_flip_char(tty, ch, TTY_NORMAL);
}
if (tty) {
tty_flip_buffer_push(tty);
tty_kref_put(tty);
}
tty_flip_buffer_push(tty);
}
static void rc_transmit(struct riscom_board const *bp)
......@@ -424,22 +427,22 @@ static void rc_transmit(struct riscom_board const *bp)
if (port == NULL)
return;
tty = port->port.tty;
tty = tty_port_tty_get(&port->port);
if (port->IER & IER_TXEMPTY) {
/* FIFO drained */
rc_out(bp, CD180_CAR, port_No(port));
port->IER &= ~IER_TXEMPTY;
rc_out(bp, CD180_IER, port->IER);
return;
goto out;
}
if ((port->xmit_cnt <= 0 && !port->break_length)
|| tty->stopped || tty->hw_stopped) {
|| (tty && (tty->stopped || tty->hw_stopped))) {
rc_out(bp, CD180_CAR, port_No(port));
port->IER &= ~IER_TXRDY;
rc_out(bp, CD180_IER, port->IER);
return;
goto out;
}
if (port->break_length) {
......@@ -464,7 +467,7 @@ static void rc_transmit(struct riscom_board const *bp)
rc_out(bp, CD180_CCR, CCR_CORCHG2);
port->break_length = 0;
}
return;
goto out;
}
count = CD180_NFIFO;
......@@ -480,8 +483,10 @@ static void rc_transmit(struct riscom_board const *bp)
port->IER &= ~IER_TXRDY;
rc_out(bp, CD180_IER, port->IER);
}
if (port->xmit_cnt <= port->wakeup_chars)
if (tty && port->xmit_cnt <= port->wakeup_chars)
tty_wakeup(tty);
out:
tty_kref_put(tty);
}
static void rc_check_modem(struct riscom_board const *bp)
......@@ -494,37 +499,43 @@ static void rc_check_modem(struct riscom_board const *bp)
if (port == NULL)
return;
tty = port->port.tty;
tty = tty_port_tty_get(&port->port);
mcr = rc_in(bp, CD180_MCR);
if (mcr & MCR_CDCHG) {
if (rc_in(bp, CD180_MSVR) & MSVR_CD)
wake_up_interruptible(&port->port.open_wait);
else
else if (tty)
tty_hangup(tty);
}
#ifdef RISCOM_BRAIN_DAMAGED_CTS
if (mcr & MCR_CTSCHG) {
if (rc_in(bp, CD180_MSVR) & MSVR_CTS) {
tty->hw_stopped = 0;
port->IER |= IER_TXRDY;
if (port->xmit_cnt <= port->wakeup_chars)
tty_wakeup(tty);
if (tty) {
tty->hw_stopped = 0;
if (port->xmit_cnt <= port->wakeup_chars)
tty_wakeup(tty);
}
} else {
tty->hw_stopped = 1;
if (tty)
tty->hw_stopped = 1;
port->IER &= ~IER_TXRDY;
}
rc_out(bp, CD180_IER, port->IER);
}
if (mcr & MCR_DSRCHG) {
if (rc_in(bp, CD180_MSVR) & MSVR_DSR) {
tty->hw_stopped = 0;
port->IER |= IER_TXRDY;
if (port->xmit_cnt <= port->wakeup_chars)
tty_wakeup(tty);
if (tty) {
tty->hw_stopped = 0;
if (port->xmit_cnt <= port->wakeup_chars)
tty_wakeup(tty);
}
} else {
tty->hw_stopped = 1;
if (tty)
tty->hw_stopped = 1;
port->IER &= ~IER_TXRDY;
}
rc_out(bp, CD180_IER, port->IER);
......@@ -533,6 +544,7 @@ static void rc_check_modem(struct riscom_board const *bp)
/* Clear change bits */
rc_out(bp, CD180_MCR, 0);
tty_kref_put(tty);
}
/* The main interrupt processing routine */
......@@ -632,9 +644,9 @@ static void rc_shutdown_board(struct riscom_board *bp)
* Setting up port characteristics.
* Must be called with disabled interrupts
*/
static void rc_change_speed(struct riscom_board *bp, struct riscom_port *port)
static void rc_change_speed(struct tty_struct *tty, struct riscom_board *bp,
struct riscom_port *port)
{
struct tty_struct *tty = port->port.tty;
unsigned long baud;
long tmp;
unsigned char cor1 = 0, cor3 = 0;
......@@ -781,7 +793,8 @@ static void rc_change_speed(struct riscom_board *bp, struct riscom_port *port)
}
/* Must be called with interrupts enabled */
static int rc_setup_port(struct riscom_board *bp, struct riscom_port *port)
static int rc_setup_port(struct tty_struct *tty, struct riscom_board *bp,
struct riscom_port *port)
{
unsigned long flags;
......@@ -793,11 +806,11 @@ static int rc_setup_port(struct riscom_board *bp, struct riscom_port *port)
spin_lock_irqsave(&riscom_lock, flags);
clear_bit(TTY_IO_ERROR, &port->port.tty->flags);
clear_bit(TTY_IO_ERROR, &tty->flags);
if (port->port.count == 1)
bp->count++;
port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
rc_change_speed(bp, port);
rc_change_speed(tty, bp, port);
port->port.flags |= ASYNC_INITIALIZED;
spin_unlock_irqrestore(&riscom_lock, flags);
......@@ -898,9 +911,9 @@ static int rc_open(struct tty_struct *tty, struct file *filp)
port->port.count++;
tty->driver_data = port;
port->port.tty = tty;
tty_port_tty_set(&port->port, tty);
error = rc_setup_port(bp, port);
error = rc_setup_port(tty, bp, port);
if (error == 0)
error = tty_port_block_til_ready(&port->port, tty, filp);
return error;
......@@ -921,20 +934,12 @@ static void rc_flush_buffer(struct tty_struct *tty)
tty_wakeup(tty);
}
static void rc_close(struct tty_struct *tty, struct file *filp)
static void rc_close_port(struct tty_port *port)
{
struct riscom_port *port = tty->driver_data;
struct riscom_board *bp;
unsigned long flags;
struct riscom_port *rp = container_of(port, struct riscom_port, port);
struct riscom_board *bp = port_Board(rp);
unsigned long timeout;
if (!port || rc_paranoia_check(port, tty->name, "close"))
return;
bp = port_Board(port);
if (tty_port_close_start(&port->port, tty, filp) == 0)
return;
/*
* At this point we stop accepting input. To do this, we
......@@ -944,31 +949,37 @@ static void rc_close(struct tty_struct *tty, struct file *filp)
*/
spin_lock_irqsave(&riscom_lock, flags);
port->IER &= ~IER_RXD;
if (port->port.flags & ASYNC_INITIALIZED) {
port->IER &= ~IER_TXRDY;
port->IER |= IER_TXEMPTY;
rc_out(bp, CD180_CAR, port_No(port));
rc_out(bp, CD180_IER, port->IER);
rp->IER &= ~IER_RXD;
if (port->flags & ASYNC_INITIALIZED) {
rp->IER &= ~IER_TXRDY;
rp->IER |= IER_TXEMPTY;
rc_out(bp, CD180_CAR, port_No(rp));
rc_out(bp, CD180_IER, rp->IER);
/*
* Before we drop DTR, make sure the UART transmitter
* has completely drained; this is especially
* important if there is a transmit FIFO!
*/
timeout = jiffies + HZ;
while (port->IER & IER_TXEMPTY) {
while (rp->IER & IER_TXEMPTY) {
spin_unlock_irqrestore(&riscom_lock, flags);
msleep_interruptible(jiffies_to_msecs(port->timeout));
msleep_interruptible(jiffies_to_msecs(rp->timeout));
spin_lock_irqsave(&riscom_lock, flags);
if (time_after(jiffies, timeout))
break;
}
}
rc_shutdown_port(tty, bp, port);
rc_flush_buffer(tty);
rc_shutdown_port(port->tty, bp, rp);
spin_unlock_irqrestore(&riscom_lock, flags);
}
static void rc_close(struct tty_struct *tty, struct file *filp)
{
struct riscom_port *port = tty->driver_data;
tty_port_close_end(&port->port, tty);
if (!port || rc_paranoia_check(port, tty->name, "close"))
return;
tty_port_close(&port->port, tty, filp);
}
static int rc_write(struct tty_struct *tty,
......@@ -1170,7 +1181,7 @@ static int rc_send_break(struct tty_struct *tty, int length)
return 0;
}
static int rc_set_serial_info(struct riscom_port *port,
static int rc_set_serial_info(struct tty_struct *tty, struct riscom_port *port,
struct serial_struct __user *newinfo)
{
struct serial_struct tmp;
......@@ -1180,17 +1191,6 @@ static int rc_set_serial_info(struct riscom_port *port,
if (copy_from_user(&tmp, newinfo, sizeof(tmp)))
return -EFAULT;
#if 0
if ((tmp.irq != bp->irq) ||
(tmp.port != bp->base) ||
(tmp.type != PORT_CIRRUS) ||
(tmp.baud_base != (RC_OSCFREQ + CD180_TPC/2) / CD180_TPC) ||
(tmp.custom_divisor != 0) ||
(tmp.xmit_fifo_size != CD180_NFIFO) ||
(tmp.flags & ~RISCOM_LEGAL_FLAGS))
return -EINVAL;
#endif
change_speed = ((port->port.flags & ASYNC_SPD_MASK) !=
(tmp.flags & ASYNC_SPD_MASK));
......@@ -1212,7 +1212,7 @@ static int rc_set_serial_info(struct riscom_port *port,
unsigned long flags;
spin_lock_irqsave(&riscom_lock, flags);
rc_change_speed(bp, port);
rc_change_speed(tty, bp, port);
spin_unlock_irqrestore(&riscom_lock, flags);
}
return 0;
......@@ -1255,7 +1255,7 @@ static int rc_ioctl(struct tty_struct *tty, struct file *filp,
break;
case TIOCSSERIAL:
lock_kernel();
retval = rc_set_serial_info(port, argp);
retval = rc_set_serial_info(tty, port, argp);
unlock_kernel();
break;
default:
......@@ -1350,21 +1350,12 @@ static void rc_start(struct tty_struct *tty)
static void rc_hangup(struct tty_struct *tty)
{
struct riscom_port *port = tty->driver_data;
struct riscom_board *bp;
unsigned long flags;
if (rc_paranoia_check(port, tty->name, "rc_hangup"))
return;
bp = port_Board(port);
rc_shutdown_port(tty, bp, port);
spin_lock_irqsave(&port->port.lock, flags);
port->port.count = 0;
port->port.flags &= ~ASYNC_NORMAL_ACTIVE;
port->port.tty = NULL;
wake_up_interruptible(&port->port.open_wait);
spin_unlock_irqrestore(&port->port.lock, flags);
rc_shutdown_port(tty, port_Board(port), port);
tty_port_hangup(&port->port);
}
static void rc_set_termios(struct tty_struct *tty,
......@@ -1377,7 +1368,7 @@ static void rc_set_termios(struct tty_struct *tty,
return;
spin_lock_irqsave(&riscom_lock, flags);
rc_change_speed(port_Board(port), port);
rc_change_speed(tty, port_Board(port), port);
spin_unlock_irqrestore(&riscom_lock, flags);
if ((old_termios->c_cflag & CRTSCTS) &&
......@@ -1410,6 +1401,7 @@ static const struct tty_operations riscom_ops = {
static const struct tty_port_operations riscom_port_ops = {
.carrier_raised = carrier_raised,
.shutdown = rc_close_port,
};
......
......@@ -1184,6 +1184,7 @@ int tty_init_termios(struct tty_struct *tty)
tty->termios->c_ospeed = tty_termios_baud_rate(tty->termios);
return 0;
}
EXPORT_SYMBOL_GPL(tty_init_termios);
/**
* tty_driver_install_tty() - install a tty entry in the driver
......@@ -1386,10 +1387,14 @@ EXPORT_SYMBOL(tty_shutdown);
* tty_mutex - sometimes only
* takes the file list lock internally when working on the list
* of ttys that the driver keeps.
*
* This method gets called from a work queue so that the driver private
* shutdown ops can sleep (needed for USB at least)
*/
static void release_one_tty(struct kref *kref)
static void release_one_tty(struct work_struct *work)
{
struct tty_struct *tty = container_of(kref, struct tty_struct, kref);
struct tty_struct *tty =
container_of(work, struct tty_struct, hangup_work);
struct tty_driver *driver = tty->driver;
if (tty->ops->shutdown)
......@@ -1407,6 +1412,15 @@ static void release_one_tty(struct kref *kref)
free_tty_struct(tty);
}
static void queue_release_one_tty(struct kref *kref)
{
struct tty_struct *tty = container_of(kref, struct tty_struct, kref);
/* The hangup queue is now free so we can reuse it rather than
waste a chunk of memory for each port */
INIT_WORK(&tty->hangup_work, release_one_tty);
schedule_work(&tty->hangup_work);
}
/**
* tty_kref_put - release a tty kref
* @tty: tty device
......@@ -1418,7 +1432,7 @@ static void release_one_tty(struct kref *kref)
void tty_kref_put(struct tty_struct *tty)
{
if (tty)
kref_put(&tty->kref, release_one_tty);
kref_put(&tty->kref, queue_release_one_tty);
}
EXPORT_SYMBOL(tty_kref_put);
......@@ -2085,7 +2099,7 @@ static int tioccons(struct file *file)
* the generic functionality existed. This piece of history is preserved
* in the expected tty API of posix OS's.
*
* Locking: none, the open fle handle ensures it won't go away.
* Locking: none, the open file handle ensures it won't go away.
*/
static int fionbio(struct file *file, int __user *p)
......
......@@ -393,9 +393,7 @@ void tty_termios_encode_baud_rate(struct ktermios *termios,
termios->c_cflag |= (BOTHER << IBSHIFT);
#else
if (ifound == -1 || ofound == -1) {
static int warned;
if (!warned++)
printk(KERN_WARNING "tty: Unable to return correct "
printk_once(KERN_WARNING "tty: Unable to return correct "
"speed data as your architecture needs updating.\n");
}
#endif
......
......@@ -145,48 +145,33 @@ int tty_unregister_ldisc(int disc)
}
EXPORT_SYMBOL(tty_unregister_ldisc);
/**
* tty_ldisc_try_get - try and reference an ldisc
* @disc: ldisc number
*
* Attempt to open and lock a line discipline into place. Return
* the line discipline refcounted or an error.
*/
static struct tty_ldisc *tty_ldisc_try_get(int disc)
static struct tty_ldisc_ops *get_ldops(int disc)
{
unsigned long flags;
struct tty_ldisc *ld;
struct tty_ldisc_ops *ldops;
int err = -EINVAL;
ld = kmalloc(sizeof(struct tty_ldisc), GFP_KERNEL);
if (ld == NULL)
return ERR_PTR(-ENOMEM);
struct tty_ldisc_ops *ldops, *ret;
spin_lock_irqsave(&tty_ldisc_lock, flags);
ld->ops = NULL;
ret = ERR_PTR(-EINVAL);
ldops = tty_ldiscs[disc];
/* Check the entry is defined */
if (ldops) {
/* If the module is being unloaded we can't use it */
if (!try_module_get(ldops->owner))
err = -EAGAIN;
else {
/* lock it */
ret = ERR_PTR(-EAGAIN);
if (try_module_get(ldops->owner)) {
ldops->refcount++;
ld->ops = ldops;
atomic_set(&ld->users, 1);
err = 0;
ret = ldops;
}
}
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
if (err) {
kfree(ld);
return ERR_PTR(err);
}
return ld;
return ret;
}
static void put_ldops(struct tty_ldisc_ops *ldops)
{
unsigned long flags;
spin_lock_irqsave(&tty_ldisc_lock, flags);
ldops->refcount--;
module_put(ldops->owner);
spin_unlock_irqrestore(&tty_ldisc_lock, flags);
}
/**
......@@ -205,14 +190,31 @@ static struct tty_ldisc *tty_ldisc_try_get(int disc)
static struct tty_ldisc *tty_ldisc_get(int disc)
{
struct tty_ldisc *ld;
struct tty_ldisc_ops *ldops;
if (disc < N_TTY || disc >= NR_LDISCS)
return ERR_PTR(-EINVAL);
ld = tty_ldisc_try_get(disc);
if (IS_ERR(ld)) {
/*
* Get the ldisc ops - we may need to request them to be loaded
* dynamically and try again.
*/
ldops = get_ldops(disc);
if (IS_ERR(ldops)) {
request_module("tty-ldisc-%d", disc);
ld = tty_ldisc_try_get(disc);
ldops = get_ldops(disc);
if (IS_ERR(ldops))
return ERR_CAST(ldops);
}
ld = kmalloc(sizeof(struct tty_ldisc), GFP_KERNEL);
if (ld == NULL) {
put_ldops(ldops);
return ERR_PTR(-ENOMEM);
}
ld->ops = ldops;
atomic_set(&ld->users, 1);
return ld;
}
......@@ -234,13 +236,13 @@ static void tty_ldiscs_seq_stop(struct seq_file *m, void *v)
static int tty_ldiscs_seq_show(struct seq_file *m, void *v)
{
int i = *(loff_t *)v;
struct tty_ldisc *ld;
struct tty_ldisc_ops *ldops;
ld = tty_ldisc_try_get(i);
if (IS_ERR(ld))
ldops = get_ldops(i);
if (IS_ERR(ldops))
return 0;
seq_printf(m, "%-10s %2d\n", ld->ops->name ? ld->ops->name : "???", i);
put_ldisc(ld);
seq_printf(m, "%-10s %2d\n", ldops->name ? ldops->name : "???", i);
put_ldops(ldops);
return 0;
}
......
......@@ -23,6 +23,7 @@ void tty_port_init(struct tty_port *port)
memset(port, 0, sizeof(*port));
init_waitqueue_head(&port->open_wait);
init_waitqueue_head(&port->close_wait);
init_waitqueue_head(&port->delta_msr_wait);
mutex_init(&port->mutex);
spin_lock_init(&port->lock);
port->close_delay = (50 * HZ) / 100;
......@@ -96,6 +97,14 @@ void tty_port_tty_set(struct tty_port *port, struct tty_struct *tty)
}
EXPORT_SYMBOL(tty_port_tty_set);
static void tty_port_shutdown(struct tty_port *port)
{
if (port->ops->shutdown &&
test_and_clear_bit(ASYNCB_INITIALIZED, &port->flags))
port->ops->shutdown(port);
}
/**
* tty_port_hangup - hangup helper
* @port: tty port
......@@ -116,6 +125,8 @@ void tty_port_hangup(struct tty_port *port)
port->tty = NULL;
spin_unlock_irqrestore(&port->lock, flags);
wake_up_interruptible(&port->open_wait);
wake_up_interruptible(&port->delta_msr_wait);
tty_port_shutdown(port);
}
EXPORT_SYMBOL(tty_port_hangup);
......@@ -296,15 +307,17 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f
if (port->count) {
spin_unlock_irqrestore(&port->lock, flags);
if (port->ops->drop)
port->ops->drop(port);
return 0;
}
port->flags |= ASYNC_CLOSING;
set_bit(ASYNCB_CLOSING, &port->flags);
tty->closing = 1;
spin_unlock_irqrestore(&port->lock, flags);
/* Don't block on a stalled port, just pull the chain */
if (tty->flow_stopped)
tty_driver_flush_buffer(tty);
if (port->flags & ASYNC_INITIALIZED &&
if (test_bit(ASYNCB_INITIALIZED, &port->flags) &&
port->closing_wait != ASYNC_CLOSING_WAIT_NONE)
tty_wait_until_sent(tty, port->closing_wait);
if (port->drain_delay) {
......@@ -318,6 +331,9 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f
timeout = 2 * HZ;
schedule_timeout_interruptible(timeout);
}
/* Don't call port->drop for the last reference. Callers will want
to drop the last active reference in ->shutdown() or the tty
shutdown path */
return 1;
}
EXPORT_SYMBOL(tty_port_close_start);
......@@ -348,3 +364,14 @@ void tty_port_close_end(struct tty_port *port, struct tty_struct *tty)
spin_unlock_irqrestore(&port->lock, flags);
}
EXPORT_SYMBOL(tty_port_close_end);
void tty_port_close(struct tty_port *port, struct tty_struct *tty,
struct file *filp)
{
if (tty_port_close_start(port, tty, filp) == 0)
return;
tty_port_shutdown(port);
tty_port_close_end(port, tty);
tty_port_tty_set(port, NULL);
}
EXPORT_SYMBOL(tty_port_close);
......@@ -252,7 +252,6 @@ static void notify_update(struct vc_data *vc)
struct vt_notifier_param param = { .vc = vc };
atomic_notifier_call_chain(&vt_notifier_list, VT_UPDATE, &param);
}
/*
* Low-Level Functions
*/
......@@ -935,6 +934,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
if (CON_IS_VISIBLE(vc))
update_screen(vc);
vt_event_post(VT_EVENT_RESIZE, vc->vc_num, vc->vc_num);
return err;
}
......@@ -2129,11 +2129,7 @@ static int do_con_write(struct tty_struct *tty, const unsigned char *buf, int co
currcons = vc->vc_num;
if (!vc_cons_allocated(currcons)) {
/* could this happen? */
static int error = 0;
if (!error) {
error = 1;
printk("con_write: tty %d not allocated\n", currcons+1);
}
printk_once("con_write: tty %d not allocated\n", currcons+1);
release_console_sem();
return 0;
}
......@@ -2910,6 +2906,9 @@ static const struct tty_operations con_ops = {
.flush_chars = con_flush_chars,
.chars_in_buffer = con_chars_in_buffer,
.ioctl = vt_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = vt_compat_ioctl,
#endif
.stop = con_stop,
.start = con_start,
.throttle = con_throttle,
......@@ -2955,7 +2954,6 @@ int __init vty_init(const struct file_operations *console_fops)
}
#ifndef VT_SINGLE_DRIVER
#include <linux/device.h>
static struct class *vtconsole_class;
......@@ -3638,6 +3636,7 @@ void do_blank_screen(int entering_gfx)
blank_state = blank_vesa_wait;
mod_timer(&console_timer, jiffies + vesa_off_interval);
}
vt_event_post(VT_EVENT_BLANK, vc->vc_num, vc->vc_num);
}
EXPORT_SYMBOL(do_blank_screen);
......@@ -3682,6 +3681,7 @@ void do_unblank_screen(int leaving_gfx)
console_blank_hook(0);
set_palette(vc);
set_cursor(vc);
vt_event_post(VT_EVENT_UNBLANK, vc->vc_num, vc->vc_num);
}
EXPORT_SYMBOL(do_unblank_screen);
......
此差异已折叠。
......@@ -408,33 +408,28 @@ static int if_write_room(struct tty_struct *tty)
return retval;
}
/* FIXME: This function does not have error returns */
static int if_chars_in_buffer(struct tty_struct *tty)
{
struct cardstate *cs;
int retval = -ENODEV;
int retval = 0;
cs = (struct cardstate *) tty->driver_data;
if (!cs) {
pr_err("%s: no cardstate\n", __func__);
return -ENODEV;
return 0;
}
gig_dbg(DEBUG_IF, "%u: %s()", cs->minor_index, __func__);
if (mutex_lock_interruptible(&cs->mutex))
return -ERESTARTSYS; // FIXME -EINTR?
mutex_lock(&cs->mutex);
if (!cs->connected) {
if (!cs->connected)
gig_dbg(DEBUG_IF, "not connected");
retval = -ENODEV;
} else if (!cs->open_count)
else if (!cs->open_count)
dev_warn(cs->dev, "%s: device not opened\n", __func__);
else if (cs->mstate != MS_LOCKED) {
else if (cs->mstate != MS_LOCKED)
dev_warn(cs->dev, "can't write to unlocked device\n");
retval = -EBUSY;
} else
else
retval = cs->ops->chars_in_buffer(cs);
mutex_unlock(&cs->mutex);
......
......@@ -616,6 +616,14 @@ static void sl_uninit(struct net_device *dev)
sl_free_bufs(sl);
}
/* Hook the destructor so we can free slip devices at the right point in time */
static void sl_free_netdev(struct net_device *dev)
{
int i = dev->base_addr;
free_netdev(dev);
slip_devs[i] = NULL;
}
static const struct net_device_ops sl_netdev_ops = {
.ndo_init = sl_init,
.ndo_uninit = sl_uninit,
......@@ -634,7 +642,7 @@ static const struct net_device_ops sl_netdev_ops = {
static void sl_setup(struct net_device *dev)
{
dev->netdev_ops = &sl_netdev_ops;
dev->destructor = free_netdev;
dev->destructor = sl_free_netdev;
dev->hard_header_len = 0;
dev->addr_len = 0;
......@@ -712,8 +720,6 @@ static void sl_sync(void)
static struct slip *sl_alloc(dev_t line)
{
int i;
int sel = -1;
int score = -1;
struct net_device *dev = NULL;
struct slip *sl;
......@@ -724,55 +730,7 @@ static struct slip *sl_alloc(dev_t line)
dev = slip_devs[i];
if (dev == NULL)
break;
sl = netdev_priv(dev);
if (sl->leased) {
if (sl->line != line)
continue;
if (sl->tty)
return NULL;
/* Clear ESCAPE & ERROR flags */
sl->flags &= (1 << SLF_INUSE);
return sl;
}
if (sl->tty)
continue;
if (current->pid == sl->pid) {
if (sl->line == line && score < 3) {
sel = i;
score = 3;
continue;
}
if (score < 2) {
sel = i;
score = 2;
}
continue;
}
if (sl->line == line && score < 1) {
sel = i;
score = 1;
continue;
}
if (score < 0) {
sel = i;
score = 0;
}
}
if (sel >= 0) {
i = sel;
dev = slip_devs[i];
if (score > 1) {
sl = netdev_priv(dev);
sl->flags &= (1 << SLF_INUSE);
return sl;
}
}
/* Sorry, too many, all slots in use */
if (i >= slip_maxdev)
return NULL;
......@@ -908,31 +866,14 @@ static int slip_open(struct tty_struct *tty)
return err;
}
/*
FIXME: 1,2 are fixed 3 was never true anyway.
Let me to blame a bit.
1. TTY module calls this funstion on soft interrupt.
2. TTY module calls this function WITH MASKED INTERRUPTS!
3. TTY module does not notify us about line discipline
shutdown,
Seems, now it is clean. The solution is to consider netdevice and
line discipline sides as two independent threads.
By-product (not desired): sl? does not feel hangups and remains open.
It is supposed, that user level program (dip, diald, slattach...)
will catch SIGHUP and make the rest of work.
I see no way to make more with current tty code. --ANK
*/
/*
* Close down a SLIP channel.
* This means flushing out any pending queues, and then returning. This
* call is serialized against other ldisc functions.
*
* We also use this method fo a hangup event
*/
static void slip_close(struct tty_struct *tty)
{
struct slip *sl = tty->disc_data;
......@@ -951,10 +892,16 @@ static void slip_close(struct tty_struct *tty)
del_timer_sync(&sl->keepalive_timer);
del_timer_sync(&sl->outfill_timer);
#endif
/* Count references from TTY module */
/* Flush network side */
unregister_netdev(sl->dev);
/* This will complete via sl_free_netdev */
}
static int slip_hangup(struct tty_struct *tty)
{
slip_close(tty);
return 0;
}
/************************************************************************
* STANDARD SLIP ENCAPSULATION *
************************************************************************/
......@@ -1311,6 +1258,7 @@ static struct tty_ldisc_ops sl_ldisc = {
.name = "slip",
.open = slip_open,
.close = slip_close,
.hangup = slip_hangup,
.ioctl = slip_ioctl,
.receive_buf = slip_receive_buf,
.write_wakeup = slip_write_wakeup,
......@@ -1384,6 +1332,8 @@ static void __exit slip_exit(void)
}
} while (busy && time_before(jiffies, timeout));
/* FIXME: hangup is async so we should wait when doing this second
phase */
for (i = 0; i < slip_maxdev; i++) {
dev = slip_devs[i];
......
......@@ -86,7 +86,7 @@ static void serial21285_enable_ms(struct uart_port *port)
static irqreturn_t serial21285_rx_chars(int irq, void *dev_id)
{
struct uart_port *port = dev_id;
struct tty_struct *tty = port->info->port.tty;
struct tty_struct *tty = port->state->port.tty;
unsigned int status, ch, flag, rxs, max_count = 256;
status = *CSR_UARTFLG;
......@@ -124,7 +124,7 @@ static irqreturn_t serial21285_rx_chars(int irq, void *dev_id)
static irqreturn_t serial21285_tx_chars(int irq, void *dev_id)
{
struct uart_port *port = dev_id;
struct circ_buf *xmit = &port->info->xmit;
struct circ_buf *xmit = &port->state->xmit;
int count = 256;
if (port->x_char) {
......@@ -235,8 +235,8 @@ serial21285_set_termios(struct uart_port *port, struct ktermios *termios,
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
quot = uart_get_divisor(port, baud);
if (port->info && port->info->port.tty) {
struct tty_struct *tty = port->info->port.tty;
if (port->state && port->state->port.tty) {
struct tty_struct *tty = port->state->port.tty;
unsigned int b = port->uartclk / (16 * quot);
tty_encode_baud_rate(tty, b, b);
}
......
......@@ -1382,7 +1382,7 @@ static void serial8250_enable_ms(struct uart_port *port)
static void
receive_chars(struct uart_8250_port *up, unsigned int *status)
{
struct tty_struct *tty = up->port.info->port.tty;
struct tty_struct *tty = up->port.state->port.tty;
unsigned char ch, lsr = *status;
int max_count = 256;
char flag;
......@@ -1457,7 +1457,7 @@ receive_chars(struct uart_8250_port *up, unsigned int *status)
static void transmit_chars(struct uart_8250_port *up)
{
struct circ_buf *xmit = &up->port.info->xmit;
struct circ_buf *xmit = &up->port.state->xmit;
int count;
if (up->port.x_char) {
......@@ -1500,7 +1500,7 @@ static unsigned int check_modem_status(struct uart_8250_port *up)
status |= up->msr_saved_flags;
up->msr_saved_flags = 0;
if (status & UART_MSR_ANY_DELTA && up->ier & UART_IER_MSI &&
up->port.info != NULL) {
up->port.state != NULL) {
if (status & UART_MSR_TERI)
up->port.icount.rng++;
if (status & UART_MSR_DDSR)
......@@ -1510,7 +1510,7 @@ static unsigned int check_modem_status(struct uart_8250_port *up)
if (status & UART_MSR_DCTS)
uart_handle_cts_change(&up->port, status & UART_MSR_CTS);
wake_up_interruptible(&up->port.info->delta_msr_wait);
wake_up_interruptible(&up->port.state->port.delta_msr_wait);
}
return status;
......@@ -1677,7 +1677,7 @@ static int serial_link_irq_chain(struct uart_8250_port *up)
INIT_LIST_HEAD(&up->list);
i->head = &up->list;
spin_unlock_irq(&i->lock);
irq_flags |= up->port.irqflags;
ret = request_irq(up->port.irq, serial8250_interrupt,
irq_flags, "serial", i);
if (ret < 0)
......@@ -1764,7 +1764,7 @@ static void serial8250_backup_timeout(unsigned long data)
up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
spin_unlock_irqrestore(&up->port.lock, flags);
if ((iir & UART_IIR_NO_INT) && (up->ier & UART_IER_THRI) &&
(!uart_circ_empty(&up->port.info->xmit) || up->port.x_char) &&
(!uart_circ_empty(&up->port.state->xmit) || up->port.x_char) &&
(lsr & UART_LSR_THRE)) {
iir &= ~(UART_IIR_ID | UART_IIR_NO_INT);
iir |= UART_IIR_THRI;
......@@ -2026,7 +2026,7 @@ static int serial8250_startup(struct uart_port *port)
* allow register changes to become visible.
*/
spin_lock_irqsave(&up->port.lock, flags);
if (up->port.flags & UPF_SHARE_IRQ)
if (up->port.irqflags & IRQF_SHARED)
disable_irq_nosync(up->port.irq);
wait_for_xmitr(up, UART_LSR_THRE);
......@@ -2039,7 +2039,7 @@ static int serial8250_startup(struct uart_port *port)
iir = serial_in(up, UART_IIR);
serial_out(up, UART_IER, 0);
if (up->port.flags & UPF_SHARE_IRQ)
if (up->port.irqflags & IRQF_SHARED)
enable_irq(up->port.irq);
spin_unlock_irqrestore(&up->port.lock, flags);
......@@ -2272,7 +2272,9 @@ serial8250_set_termios(struct uart_port *port, struct ktermios *termios,
/*
* Ask the core to calculate the divisor for us.
*/
baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16);
baud = uart_get_baud_rate(port, termios, old,
port->uartclk / 16 / 0xffff,
port->uartclk / 16);
quot = serial8250_get_divisor(port, baud);
/*
......@@ -2671,6 +2673,7 @@ static void __init serial8250_isa_init_ports(void)
i++, up++) {
up->port.iobase = old_serial_port[i].port;
up->port.irq = irq_canonicalize(old_serial_port[i].irq);
up->port.irqflags = old_serial_port[i].irqflags;
up->port.uartclk = old_serial_port[i].baud_base * 16;
up->port.flags = old_serial_port[i].flags;
up->port.hub6 = old_serial_port[i].hub6;
......@@ -2679,7 +2682,7 @@ static void __init serial8250_isa_init_ports(void)
up->port.regshift = old_serial_port[i].iomem_reg_shift;
set_io_from_upio(&up->port);
if (share_irqs)
up->port.flags |= UPF_SHARE_IRQ;
up->port.irqflags |= IRQF_SHARED;
}
}
......@@ -2869,6 +2872,7 @@ int __init early_serial_setup(struct uart_port *port)
p->iobase = port->iobase;
p->membase = port->membase;
p->irq = port->irq;
p->irqflags = port->irqflags;
p->uartclk = port->uartclk;
p->fifosize = port->fifosize;
p->regshift = port->regshift;
......@@ -2942,6 +2946,7 @@ static int __devinit serial8250_probe(struct platform_device *dev)
port.iobase = p->iobase;
port.membase = p->membase;
port.irq = p->irq;
port.irqflags = p->irqflags;
port.uartclk = p->uartclk;
port.regshift = p->regshift;
port.iotype = p->iotype;
......@@ -2954,7 +2959,7 @@ static int __devinit serial8250_probe(struct platform_device *dev)
port.serial_out = p->serial_out;
port.dev = &dev->dev;
if (share_irqs)
port.flags |= UPF_SHARE_IRQ;
port.irqflags |= IRQF_SHARED;
ret = serial8250_register_port(&port);
if (ret < 0) {
dev_err(&dev->dev, "unable to register port at index %d "
......@@ -3096,6 +3101,7 @@ int serial8250_register_port(struct uart_port *port)
uart->port.iobase = port->iobase;
uart->port.membase = port->membase;
uart->port.irq = port->irq;
uart->port.irqflags = port->irqflags;
uart->port.uartclk = port->uartclk;
uart->port.fifosize = port->fifosize;
uart->port.regshift = port->regshift;
......
......@@ -25,6 +25,7 @@ struct old_serial_port {
unsigned char io_type;
unsigned char *iomem_base;
unsigned short iomem_reg_shift;
unsigned long irqflags;
};
/*
......
......@@ -117,7 +117,7 @@ static void pl010_enable_ms(struct uart_port *port)
static void pl010_rx_chars(struct uart_amba_port *uap)
{
struct tty_struct *tty = uap->port.info->port.tty;
struct tty_struct *tty = uap->port.state->port.tty;
unsigned int status, ch, flag, rsr, max_count = 256;
status = readb(uap->port.membase + UART01x_FR);
......@@ -172,7 +172,7 @@ static void pl010_rx_chars(struct uart_amba_port *uap)
static void pl010_tx_chars(struct uart_amba_port *uap)
{
struct circ_buf *xmit = &uap->port.info->xmit;
struct circ_buf *xmit = &uap->port.state->xmit;
int count;
if (uap->port.x_char) {
......@@ -225,7 +225,7 @@ static void pl010_modem_status(struct uart_amba_port *uap)
if (delta & UART01x_FR_CTS)
uart_handle_cts_change(&uap->port, status & UART01x_FR_CTS);
wake_up_interruptible(&uap->port.info->delta_msr_wait);
wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
}
static irqreturn_t pl010_int(int irq, void *dev_id)
......
......@@ -124,7 +124,7 @@ static void pl011_enable_ms(struct uart_port *port)
static void pl011_rx_chars(struct uart_amba_port *uap)
{
struct tty_struct *tty = uap->port.info->port.tty;
struct tty_struct *tty = uap->port.state->port.tty;
unsigned int status, ch, flag, max_count = 256;
status = readw(uap->port.membase + UART01x_FR);
......@@ -175,7 +175,7 @@ static void pl011_rx_chars(struct uart_amba_port *uap)
static void pl011_tx_chars(struct uart_amba_port *uap)
{
struct circ_buf *xmit = &uap->port.info->xmit;
struct circ_buf *xmit = &uap->port.state->xmit;
int count;
if (uap->port.x_char) {
......@@ -226,7 +226,7 @@ static void pl011_modem_status(struct uart_amba_port *uap)
if (delta & UART01x_FR_CTS)
uart_handle_cts_change(&uap->port, status & UART01x_FR_CTS);
wake_up_interruptible(&uap->port.info->delta_msr_wait);
wake_up_interruptible(&uap->port.state->port.delta_msr_wait);
}
static irqreturn_t pl011_int(int irq, void *dev_id)
......
......@@ -427,7 +427,7 @@ static void atmel_rx_chars(struct uart_port *port)
*/
static void atmel_tx_chars(struct uart_port *port)
{
struct circ_buf *xmit = &port->info->xmit;
struct circ_buf *xmit = &port->state->xmit;
if (port->x_char && UART_GET_CSR(port) & ATMEL_US_TXRDY) {
UART_PUT_CHAR(port, port->x_char);
......@@ -560,7 +560,7 @@ static irqreturn_t atmel_interrupt(int irq, void *dev_id)
static void atmel_tx_dma(struct uart_port *port)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
struct circ_buf *xmit = &port->info->xmit;
struct circ_buf *xmit = &port->state->xmit;
struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
int count;
......@@ -663,14 +663,14 @@ static void atmel_rx_from_ring(struct uart_port *port)
* uart_start(), which takes the lock.
*/
spin_unlock(&port->lock);
tty_flip_buffer_push(port->info->port.tty);
tty_flip_buffer_push(port->state->port.tty);
spin_lock(&port->lock);
}
static void atmel_rx_from_dma(struct uart_port *port)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
struct tty_struct *tty = port->info->port.tty;
struct tty_struct *tty = port->state->port.tty;
struct atmel_dma_buffer *pdc;
int rx_idx = atmel_port->pdc_rx_idx;
unsigned int head;
......@@ -776,7 +776,7 @@ static void atmel_tasklet_func(unsigned long data)
if (status_change & ATMEL_US_CTS)
uart_handle_cts_change(port, !(status & ATMEL_US_CTS));
wake_up_interruptible(&port->info->delta_msr_wait);
wake_up_interruptible(&port->state->port.delta_msr_wait);
atmel_port->irq_status_prev = status;
}
......@@ -795,7 +795,7 @@ static void atmel_tasklet_func(unsigned long data)
static int atmel_startup(struct uart_port *port)
{
struct atmel_uart_port *atmel_port = to_atmel_uart_port(port);
struct tty_struct *tty = port->info->port.tty;
struct tty_struct *tty = port->state->port.tty;
int retval;
/*
......@@ -854,7 +854,7 @@ static int atmel_startup(struct uart_port *port)
}
if (atmel_use_dma_tx(port)) {
struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
struct circ_buf *xmit = &port->info->xmit;
struct circ_buf *xmit = &port->state->xmit;
pdc->buf = xmit->buf;
pdc->dma_addr = dma_map_single(port->dev,
......
......@@ -42,6 +42,10 @@
# undef CONFIG_EARLY_PRINTK
#endif
#ifdef CONFIG_SERIAL_BFIN_MODULE
# undef CONFIG_EARLY_PRINTK
#endif
/* UART name and device definitions */
#define BFIN_SERIAL_NAME "ttyBF"
#define BFIN_SERIAL_MAJOR 204
......@@ -140,7 +144,7 @@ static void bfin_serial_stop_tx(struct uart_port *port)
{
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
#ifdef CONFIG_SERIAL_BFIN_DMA
struct circ_buf *xmit = &uart->port.info->xmit;
struct circ_buf *xmit = &uart->port.state->xmit;
#endif
while (!(UART_GET_LSR(uart) & TEMT))
......@@ -167,7 +171,7 @@ static void bfin_serial_stop_tx(struct uart_port *port)
static void bfin_serial_start_tx(struct uart_port *port)
{
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
struct tty_struct *tty = uart->port.info->port.tty;
struct tty_struct *tty = uart->port.state->port.tty;
#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
if (uart->scts && !(bfin_serial_get_mctrl(&uart->port) & TIOCM_CTS)) {
......@@ -239,10 +243,10 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
return;
}
if (!uart->port.info || !uart->port.info->port.tty)
if (!uart->port.state || !uart->port.state->port.tty)
return;
#endif
tty = uart->port.info->port.tty;
tty = uart->port.state->port.tty;
if (ANOMALY_05000363) {
/* The BF533 (and BF561) family of processors have a nice anomaly
......@@ -327,7 +331,7 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
static void bfin_serial_tx_chars(struct bfin_serial_port *uart)
{
struct circ_buf *xmit = &uart->port.info->xmit;
struct circ_buf *xmit = &uart->port.state->xmit;
if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) {
#ifdef CONFIG_BF54x
......@@ -394,7 +398,7 @@ static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id)
#ifdef CONFIG_SERIAL_BFIN_DMA
static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart)
{
struct circ_buf *xmit = &uart->port.info->xmit;
struct circ_buf *xmit = &uart->port.state->xmit;
uart->tx_done = 0;
......@@ -432,7 +436,7 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart)
static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart)
{
struct tty_struct *tty = uart->port.info->port.tty;
struct tty_struct *tty = uart->port.state->port.tty;
int i, flg, status;
status = UART_GET_LSR(uart);
......@@ -525,7 +529,7 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id)
{
struct bfin_serial_port *uart = dev_id;
struct circ_buf *xmit = &uart->port.info->xmit;
struct circ_buf *xmit = &uart->port.state->xmit;
#ifdef CONFIG_SERIAL_BFIN_HARD_CTSRTS
if (uart->scts && !(bfin_serial_get_mctrl(&uart->port)&TIOCM_CTS)) {
......@@ -961,10 +965,10 @@ static void bfin_serial_set_ldisc(struct uart_port *port)
int line = port->line;
unsigned short val;
if (line >= port->info->port.tty->driver->num)
if (line >= port->state->port.tty->driver->num)
return;
switch (port->info->port.tty->termios->c_line) {
switch (port->state->port.tty->termios->c_line) {
case N_IRDA:
val = UART_GET_GCTL(&bfin_serial_ports[line]);
val |= (IREN | RPOLC);
......
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册