提交 916b7656 编写于 作者: J Jiri Slaby 提交者: Greg Kroah-Hartman

TTY: serialP, merge serial_state and async_struct

This is the final step to get rid of the one of the structures.  A
further cleanup will follow. And I struct serial_state deserves cease
to exist after a switch to tty_port too.

While changing the lines, it removes also pointless tty->driver_data
casts.
Signed-off-by: NJiri Slaby <jslaby@suse.cz>
Cc: Geert Uytterhoeven <geert@linux-m68k.org>
Cc: Tony Luck <tony.luck@intel.com>
Cc: Fenghua Yu <fenghua.yu@intel.com>
Signed-off-by: NGreg Kroah-Hartman <gregkh@linuxfoundation.org>
上级 13c90621
...@@ -163,7 +163,7 @@ static void receive_chars(struct tty_struct *tty) ...@@ -163,7 +163,7 @@ static void receive_chars(struct tty_struct *tty)
*/ */
static irqreturn_t rs_interrupt_single(int irq, void *dev_id) static irqreturn_t rs_interrupt_single(int irq, void *dev_id)
{ {
struct async_struct *info = dev_id; struct serial_state *info = dev_id;
if (!info->tty) { if (!info->tty) {
printk(KERN_INFO "simrs_interrupt_single: info|tty=0 info=%p problem\n", info); printk(KERN_INFO "simrs_interrupt_single: info|tty=0 info=%p problem\n", info);
...@@ -185,7 +185,7 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id) ...@@ -185,7 +185,7 @@ static irqreturn_t rs_interrupt_single(int irq, void *dev_id)
static int 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; struct serial_state *info = tty->driver_data;
unsigned long flags; unsigned long flags;
if (!tty || !info->xmit.buf) if (!tty || !info->xmit.buf)
...@@ -202,12 +202,11 @@ static int rs_put_char(struct tty_struct *tty, unsigned char ch) ...@@ -202,12 +202,11 @@ static int rs_put_char(struct tty_struct *tty, unsigned char ch)
return 1; return 1;
} }
static void transmit_chars(struct async_struct *info, int *intr_done) static void transmit_chars(struct serial_state *info, int *intr_done)
{ {
int count; int count;
unsigned long flags; unsigned long flags;
local_irq_save(flags); local_irq_save(flags);
if (info->x_char) { if (info->x_char) {
...@@ -215,7 +214,7 @@ static void transmit_chars(struct async_struct *info, int *intr_done) ...@@ -215,7 +214,7 @@ static void transmit_chars(struct async_struct *info, int *intr_done)
console->write(console, &c, 1); console->write(console, &c, 1);
info->state->icount.tx++; info->icount.tx++;
info->x_char = 0; info->x_char = 0;
goto out; goto out;
...@@ -256,7 +255,7 @@ static void transmit_chars(struct async_struct *info, int *intr_done) ...@@ -256,7 +255,7 @@ static void transmit_chars(struct async_struct *info, int *intr_done)
static void rs_flush_chars(struct tty_struct *tty) static void rs_flush_chars(struct tty_struct *tty)
{ {
struct async_struct *info = (struct async_struct *)tty->driver_data; struct serial_state *info = tty->driver_data;
if (info->xmit.head == info->xmit.tail || tty->stopped || tty->hw_stopped || if (info->xmit.head == info->xmit.tail || tty->stopped || tty->hw_stopped ||
!info->xmit.buf) !info->xmit.buf)
...@@ -269,8 +268,8 @@ static void rs_flush_chars(struct tty_struct *tty) ...@@ -269,8 +268,8 @@ static void rs_flush_chars(struct tty_struct *tty)
static int rs_write(struct tty_struct * tty, static int rs_write(struct tty_struct * tty,
const unsigned char *buf, int count) const unsigned char *buf, int count)
{ {
struct serial_state *info = tty->driver_data;
int c, ret = 0; int c, ret = 0;
struct async_struct *info = (struct async_struct *)tty->driver_data;
unsigned long flags; unsigned long flags;
if (!tty || !info->xmit.buf || !tmp_buf) return 0; if (!tty || !info->xmit.buf || !tmp_buf) return 0;
...@@ -303,21 +302,21 @@ static int rs_write(struct tty_struct * tty, ...@@ -303,21 +302,21 @@ static int rs_write(struct tty_struct * tty,
static int rs_write_room(struct tty_struct *tty) static int rs_write_room(struct tty_struct *tty)
{ {
struct async_struct *info = (struct async_struct *)tty->driver_data; struct serial_state *info = tty->driver_data;
return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); return CIRC_SPACE(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
} }
static int rs_chars_in_buffer(struct tty_struct *tty) static int rs_chars_in_buffer(struct tty_struct *tty)
{ {
struct async_struct *info = (struct async_struct *)tty->driver_data; struct serial_state *info = tty->driver_data;
return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE); return CIRC_CNT(info->xmit.head, info->xmit.tail, SERIAL_XMIT_SIZE);
} }
static void rs_flush_buffer(struct tty_struct *tty) static void rs_flush_buffer(struct tty_struct *tty)
{ {
struct async_struct *info = (struct async_struct *)tty->driver_data; struct serial_state *info = tty->driver_data;
unsigned long flags; unsigned long flags;
local_irq_save(flags); local_irq_save(flags);
...@@ -333,7 +332,7 @@ static void rs_flush_buffer(struct tty_struct *tty) ...@@ -333,7 +332,7 @@ static void rs_flush_buffer(struct tty_struct *tty)
*/ */
static void rs_send_xchar(struct tty_struct *tty, char ch) static void rs_send_xchar(struct tty_struct *tty, char ch)
{ {
struct async_struct *info = (struct async_struct *)tty->driver_data; struct serial_state *info = tty->driver_data;
info->x_char = ch; info->x_char = ch;
if (ch) { if (ch) {
...@@ -362,7 +361,7 @@ static void rs_throttle(struct tty_struct * tty) ...@@ -362,7 +361,7 @@ static void rs_throttle(struct tty_struct * tty)
static void rs_unthrottle(struct tty_struct * tty) static void rs_unthrottle(struct tty_struct * tty)
{ {
struct async_struct *info = (struct async_struct *)tty->driver_data; struct serial_state *info = tty->driver_data;
if (I_IXOFF(tty)) { if (I_IXOFF(tty)) {
if (info->x_char) if (info->x_char)
...@@ -443,23 +442,22 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios) ...@@ -443,23 +442,22 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
* This routine will shutdown a serial port; interrupts are disabled, and * This routine will shutdown a serial port; interrupts are disabled, and
* DTR is dropped if the hangup on close termio flag is on. * DTR is dropped if the hangup on close termio flag is on.
*/ */
static void shutdown(struct async_struct * info) static void shutdown(struct serial_state *info)
{ {
unsigned long flags; unsigned long flags;
struct serial_state *state = info->state;
if (!(state->flags & ASYNC_INITIALIZED)) if (!(info->flags & ASYNC_INITIALIZED))
return; return;
#ifdef SIMSERIAL_DEBUG #ifdef SIMSERIAL_DEBUG
printk("Shutting down serial port %d (irq %d)....", info->line, printk("Shutting down serial port %d (irq %d)...\n", info->line,
state->irq); info->irq);
#endif #endif
local_irq_save(flags); local_irq_save(flags);
{ {
if (state->irq) if (info->irq)
free_irq(state->irq, info); free_irq(info->irq, info);
if (info->xmit.buf) { if (info->xmit.buf) {
free_page((unsigned long) info->xmit.buf); free_page((unsigned long) info->xmit.buf);
...@@ -468,7 +466,7 @@ static void shutdown(struct async_struct * info) ...@@ -468,7 +466,7 @@ static void shutdown(struct async_struct * info)
if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags);
state->flags &= ~ASYNC_INITIALIZED; info->flags &= ~ASYNC_INITIALIZED;
} }
local_irq_restore(flags); local_irq_restore(flags);
} }
...@@ -485,13 +483,11 @@ static void shutdown(struct async_struct * info) ...@@ -485,13 +483,11 @@ static void shutdown(struct async_struct * info)
*/ */
static void rs_close(struct tty_struct *tty, struct file * filp) static void rs_close(struct tty_struct *tty, struct file * filp)
{ {
struct async_struct * info = (struct async_struct *)tty->driver_data; struct serial_state *info = tty->driver_data;
struct serial_state *state;
unsigned long flags; unsigned long flags;
if (!info ) return; if (!info)
return;
state = info->state;
local_irq_save(flags); local_irq_save(flags);
if (tty_hung_up_p(filp)) { if (tty_hung_up_p(filp)) {
...@@ -502,30 +498,30 @@ static void rs_close(struct tty_struct *tty, struct file * filp) ...@@ -502,30 +498,30 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
return; return;
} }
#ifdef SIMSERIAL_DEBUG #ifdef SIMSERIAL_DEBUG
printk("rs_close ttys%d, count = %d\n", info->line, state->count); printk("rs_close ttys%d, count = %d\n", info->line, info->count);
#endif #endif
if ((tty->count == 1) && (state->count != 1)) { if ((tty->count == 1) && (info->count != 1)) {
/* /*
* Uh, oh. tty->count is 1, which means that the tty * Uh, oh. tty->count is 1, which means that the tty
* structure will be freed. state->count should always * structure will be freed. info->count should always
* be one in these conditions. If it's greater than * be one in these conditions. If it's greater than
* one, we've got real problems, since it means the * one, we've got real problems, since it means the
* serial port won't be shutdown. * serial port won't be shutdown.
*/ */
printk(KERN_ERR "rs_close: bad serial port count; tty->count is 1, " printk(KERN_ERR "rs_close: bad serial port count; tty->count is 1, "
"state->count is %d\n", state->count); "info->count is %d\n", info->count);
state->count = 1; info->count = 1;
} }
if (--state->count < 0) { if (--info->count < 0) {
printk(KERN_ERR "rs_close: bad serial port count for ttys%d: %d\n", printk(KERN_ERR "rs_close: bad serial port count for ttys%d: %d\n",
state->line, state->count); info->line, info->count);
state->count = 0; info->count = 0;
} }
if (state->count) { if (info->count) {
local_irq_restore(flags); local_irq_restore(flags);
return; return;
} }
state->flags |= ASYNC_CLOSING; info->flags |= ASYNC_CLOSING;
local_irq_restore(flags); local_irq_restore(flags);
/* /*
...@@ -537,11 +533,11 @@ static void rs_close(struct tty_struct *tty, struct file * filp) ...@@ -537,11 +533,11 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
tty_ldisc_flush(tty); tty_ldisc_flush(tty);
info->tty = NULL; info->tty = NULL;
if (info->blocked_open) { if (info->blocked_open) {
if (state->close_delay) if (info->close_delay)
schedule_timeout_interruptible(state->close_delay); schedule_timeout_interruptible(info->close_delay);
wake_up_interruptible(&info->open_wait); wake_up_interruptible(&info->open_wait);
} }
state->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
wake_up_interruptible(&info->close_wait); wake_up_interruptible(&info->close_wait);
} }
...@@ -558,59 +554,28 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout) ...@@ -558,59 +554,28 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
*/ */
static void rs_hangup(struct tty_struct *tty) static void rs_hangup(struct tty_struct *tty)
{ {
struct async_struct * info = (struct async_struct *)tty->driver_data; struct serial_state *info = tty->driver_data;
struct serial_state *state = info->state;
#ifdef SIMSERIAL_DEBUG #ifdef SIMSERIAL_DEBUG
printk("rs_hangup: called\n"); printk("rs_hangup: called\n");
#endif #endif
rs_flush_buffer(tty); rs_flush_buffer(tty);
if (state->flags & ASYNC_CLOSING) if (info->flags & ASYNC_CLOSING)
return; return;
shutdown(info); shutdown(info);
state->count = 0; info->count = 0;
state->flags &= ~ASYNC_NORMAL_ACTIVE; info->flags &= ~ASYNC_NORMAL_ACTIVE;
info->tty = NULL; info->tty = NULL;
wake_up_interruptible(&info->open_wait); wake_up_interruptible(&info->open_wait);
} }
static int get_async_struct(int line, struct async_struct **ret_info) static int startup(struct serial_state *state)
{
struct async_struct *info;
struct serial_state *sstate;
sstate = rs_table + line;
sstate->count++;
if (sstate->info) {
*ret_info = sstate->info;
return 0;
}
info = kzalloc(sizeof(struct async_struct), GFP_KERNEL);
if (!info) {
sstate->count--;
return -ENOMEM;
}
init_waitqueue_head(&info->open_wait);
init_waitqueue_head(&info->close_wait);
info->state = sstate;
if (sstate->info) {
kfree(info);
*ret_info = sstate->info;
return 0;
}
*ret_info = sstate->info = info;
return 0;
}
static int
startup(struct async_struct *info)
{ {
unsigned long flags; unsigned long flags;
int retval=0; int retval=0;
struct serial_state *state= info->state;
unsigned long page; unsigned long page;
page = get_zeroed_page(GFP_KERNEL); page = get_zeroed_page(GFP_KERNEL);
...@@ -625,17 +590,18 @@ startup(struct async_struct *info) ...@@ -625,17 +590,18 @@ startup(struct async_struct *info)
} }
if (!state->port || !state->type) { if (!state->port || !state->type) {
if (info->tty) set_bit(TTY_IO_ERROR, &info->tty->flags); if (state->tty)
set_bit(TTY_IO_ERROR, &state->tty->flags);
free_page(page); free_page(page);
goto errout; goto errout;
} }
if (info->xmit.buf) if (state->xmit.buf)
free_page(page); free_page(page);
else else
info->xmit.buf = (unsigned char *) page; state->xmit.buf = (unsigned char *) page;
#ifdef SIMSERIAL_DEBUG #ifdef SIMSERIAL_DEBUG
printk("startup: ttys%d (irq %d)...", info->line, state->irq); printk("startup: ttys%d (irq %d)...", state->line, state->irq);
#endif #endif
/* /*
...@@ -643,14 +609,15 @@ startup(struct async_struct *info) ...@@ -643,14 +609,15 @@ startup(struct async_struct *info)
*/ */
if (state->irq) { if (state->irq) {
retval = request_irq(state->irq, rs_interrupt_single, 0, retval = request_irq(state->irq, rs_interrupt_single, 0,
"simserial", info); "simserial", state);
if (retval) if (retval)
goto errout; goto errout;
} }
if (info->tty) clear_bit(TTY_IO_ERROR, &info->tty->flags); if (state->tty)
clear_bit(TTY_IO_ERROR, &state->tty->flags);
info->xmit.head = info->xmit.tail = 0; state->xmit.head = state->xmit.tail = 0;
#if 0 #if 0
/* /*
...@@ -663,15 +630,15 @@ startup(struct async_struct *info) ...@@ -663,15 +630,15 @@ startup(struct async_struct *info)
/* /*
* Set up the tty->alt_speed kludge * Set up the tty->alt_speed kludge
*/ */
if (info->tty) { if (state->tty) {
if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI) if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_HI)
info->tty->alt_speed = 57600; state->tty->alt_speed = 57600;
if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI) if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_VHI)
info->tty->alt_speed = 115200; state->tty->alt_speed = 115200;
if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI) if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_SHI)
info->tty->alt_speed = 230400; state->tty->alt_speed = 230400;
if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP) if ((state->flags & ASYNC_SPD_MASK) == ASYNC_SPD_WARP)
info->tty->alt_speed = 460800; state->tty->alt_speed = 460800;
} }
state->flags |= ASYNC_INITIALIZED; state->flags |= ASYNC_INITIALIZED;
...@@ -692,20 +659,18 @@ startup(struct async_struct *info) ...@@ -692,20 +659,18 @@ startup(struct async_struct *info)
*/ */
static int rs_open(struct tty_struct *tty, struct file * filp) static int rs_open(struct tty_struct *tty, struct file * filp)
{ {
struct async_struct *info; struct serial_state *info = rs_table + tty->index;
int retval; int retval;
unsigned long page; unsigned long page;
retval = get_async_struct(tty->index, &info); info->count++;
if (retval)
return retval;
tty->driver_data = info;
info->tty = tty; info->tty = tty;
tty->driver_data = info;
#ifdef SIMSERIAL_DEBUG #ifdef SIMSERIAL_DEBUG
printk("rs_open %s, count = %d\n", tty->name, info->state->count); printk("rs_open %s, count = %d\n", tty->name, info->count);
#endif #endif
info->tty->low_latency = (info->state->flags & ASYNC_LOW_LATENCY) ? 1 : 0; tty->low_latency = (info->flags & ASYNC_LOW_LATENCY) ? 1 : 0;
if (!tmp_buf) { if (!tmp_buf) {
page = get_zeroed_page(GFP_KERNEL); page = get_zeroed_page(GFP_KERNEL);
...@@ -720,12 +685,11 @@ static int rs_open(struct tty_struct *tty, struct file * filp) ...@@ -720,12 +685,11 @@ static int rs_open(struct tty_struct *tty, struct file * filp)
/* /*
* If the port is the middle of closing, bail out now * If the port is the middle of closing, bail out now
*/ */
if (tty_hung_up_p(filp) || if (tty_hung_up_p(filp) || (info->flags & ASYNC_CLOSING)) {
(info->state->flags & ASYNC_CLOSING)) { if (info->flags & ASYNC_CLOSING)
if (info->state->flags & ASYNC_CLOSING)
interruptible_sleep_on(&info->close_wait); interruptible_sleep_on(&info->close_wait);
#ifdef SERIAL_DO_RESTART #ifdef SERIAL_DO_RESTART
return ((info->state->flags & ASYNC_HUP_NOTIFY) ? return ((info->flags & ASYNC_HUP_NOTIFY) ?
-EAGAIN : -ERESTARTSYS); -EAGAIN : -ERESTARTSYS);
#else #else
return -EAGAIN; return -EAGAIN;
...@@ -865,6 +829,8 @@ simrs_init (void) ...@@ -865,6 +829,8 @@ simrs_init (void)
* Let's have a little bit of fun ! * Let's have a little bit of fun !
*/ */
for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) { for (i = 0, state = rs_table; i < NR_PORTS; i++,state++) {
init_waitqueue_head(&state->open_wait);
init_waitqueue_head(&state->close_wait);
if (state->type == PORT_UNKNOWN) continue; if (state->type == PORT_UNKNOWN) continue;
......
此差异已折叠。
...@@ -38,24 +38,24 @@ struct serial_state { ...@@ -38,24 +38,24 @@ struct serial_state {
unsigned short close_delay; unsigned short close_delay;
unsigned short closing_wait; /* time to wait before closing */ unsigned short closing_wait; /* time to wait before closing */
struct async_icount icount; struct async_icount icount;
struct async_struct *info;
};
struct async_struct { /* amiserial */
struct serial_state *state;
struct tty_struct *tty;
int read_status_mask; int read_status_mask;
int ignore_status_mask; int ignore_status_mask;
int timeout; int timeout;
int quot; int quot;
int x_char; /* xon/xoff character */
int IER; /* Interrupt Enable Register */ int IER; /* Interrupt Enable Register */
int MCR; /* Modem control register */ int MCR; /* Modem control register */
wait_queue_head_t delta_msr_wait;
/* simserial */
int x_char; /* xon/xoff character */
int blocked_open; /* # of blocked opens */ int blocked_open; /* # of blocked opens */
struct circ_buf xmit; struct circ_buf xmit;
wait_queue_head_t open_wait; wait_queue_head_t open_wait;
wait_queue_head_t close_wait; wait_queue_head_t close_wait;
wait_queue_head_t delta_msr_wait; struct tty_struct *tty;
/* /simserial */
/* /amiserial */
}; };
#endif /* _LINUX_SERIAL_H */ #endif /* _LINUX_SERIAL_H */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册