diff options
-rw-r--r-- | drivers/char/epca.c | 172 | ||||
-rw-r--r-- | drivers/char/tty_port.c | 3 |
2 files changed, 26 insertions, 149 deletions
diff --git a/drivers/char/epca.c b/drivers/char/epca.c index 7a697055e4f..71225d1af9e 100644 --- a/drivers/char/epca.c +++ b/drivers/char/epca.c @@ -432,58 +432,15 @@ static void pc_close(struct tty_struct *tty, struct file *filp) return; port = &ch->port; - spin_lock_irqsave(&port->lock, flags); - if (tty_hung_up_p(filp)) { - spin_unlock_irqrestore(&port->lock, flags); - return; - } - if (port->count-- > 1) { - /* Begin channel is open more than once */ - /* - * Return without doing anything. Someone might still - * be using the channel. - */ - spin_unlock_irqrestore(&port->lock, flags); + if (tty_port_close_start(port, tty, filp) == 0) return; - } - /* Port open only once go ahead with shutdown & reset */ - WARN_ON(port->count < 0); - /* - * Let the rest of the driver know the channel is being closed. - * This becomes important if an open is attempted before close - * is finished. - */ - port->flags |= ASYNC_CLOSING; - tty->closing = 1; - - spin_unlock_irqrestore(&port->lock, flags); - - if (port->flags & ASYNC_INITIALIZED) { - /* Setup an event to indicate when the - transmit buffer empties */ - setup_empty_event(tty, ch); - /* 30 seconds timeout */ - tty_wait_until_sent(tty, 3000); - } pc_flush_buffer(tty); - tty_ldisc_flush(tty); shutdown(ch, tty); - spin_lock_irqsave(&port->lock, flags); - tty->closing = 0; - ch->event = 0; + tty_port_close_end(port, tty); + ch->event = 0; /* FIXME: review ch->event locking */ tty_port_tty_set(port, NULL); - spin_unlock_irqrestore(&port->lock, flags); - - if (port->blocked_open) { - if (ch->close_delay) - msleep_interruptible(jiffies_to_msecs(ch->close_delay)); - wake_up_interruptible(&port->open_wait); - } - port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED | - ASYNC_CLOSING); - wake_up_interruptible(&port->close_wait); } static void shutdown(struct channel *ch, struct tty_struct *tty) @@ -527,7 +484,6 @@ static void shutdown(struct channel *ch, struct tty_struct *tty) static void pc_hangup(struct tty_struct *tty) { struct channel *ch; - struct tty_port *port; /* * verifyChannel returns the channel from the tty struct if it is @@ -536,19 +492,13 @@ static void pc_hangup(struct tty_struct *tty) ch = verifyChannel(tty); if (ch != NULL) { unsigned long flags; - port = &ch->port; pc_flush_buffer(tty); tty_ldisc_flush(tty); shutdown(ch, tty); - spin_lock_irqsave(&port->lock, flags); - port->tty = NULL; ch->event = 0; /* FIXME: review locking of ch->event */ - port->count = 0; - port->flags &= ~(ASYNC_NORMAL_ACTIVE | ASYNC_INITIALIZED); - spin_unlock_irqrestore(&port->lock, flags); - wake_up_interruptible(&port->open_wait); + tty_port_hangup(&ch->port); } } @@ -792,98 +742,18 @@ static void pc_flush_chars(struct tty_struct *tty) } } -static int block_til_ready(struct tty_struct *tty, - struct file *filp, struct channel *ch) +static int epca_carrier_raised(struct tty_port *port) { - DECLARE_WAITQUEUE(wait, current); - int retval, do_clocal = 0; - unsigned long flags; - struct tty_port *port = &ch->port; - - if (tty_hung_up_p(filp)) { - if (port->flags & ASYNC_HUP_NOTIFY) - retval = -EAGAIN; - else - retval = -ERESTARTSYS; - return retval; - } - - /* - * If the device is in the middle of being closed, then block until - * it's done, and then try again. - */ - if (port->flags & ASYNC_CLOSING) { - interruptible_sleep_on(&port->close_wait); - - if (port->flags & ASYNC_HUP_NOTIFY) - return -EAGAIN; - else - return -ERESTARTSYS; - } - - if (filp->f_flags & O_NONBLOCK) { - /* - * If non-blocking mode is set, then make the check up front - * and then exit. - */ - port->flags |= ASYNC_NORMAL_ACTIVE; - return 0; - } - if (tty->termios->c_cflag & CLOCAL) - do_clocal = 1; - /* Block waiting for the carrier detect and the line to become free */ - - retval = 0; - add_wait_queue(&port->open_wait, &wait); - - spin_lock_irqsave(&port->lock, flags); - /* We dec count so that pc_close will know when to free things */ - if (!tty_hung_up_p(filp)) - port->count--; - port->blocked_open++; - while (1) { - set_current_state(TASK_INTERRUPTIBLE); - if (tty_hung_up_p(filp) || - !(port->flags & ASYNC_INITIALIZED)) { - if (port->flags & ASYNC_HUP_NOTIFY) - retval = -EAGAIN; - else - retval = -ERESTARTSYS; - break; - } - if (!(port->flags & ASYNC_CLOSING) && - (do_clocal || (ch->imodem & ch->dcd))) - break; - if (signal_pending(current)) { - retval = -ERESTARTSYS; - break; - } - spin_unlock_irqrestore(&port->lock, flags); - /* - * Allow someone else to be scheduled. We will occasionally go - * through this loop until one of the above conditions change. - * The below schedule call will allow other processes to enter - * and prevent this loop from hogging the cpu. - */ - schedule(); - spin_lock_irqsave(&port->lock, flags); - } - - __set_current_state(TASK_RUNNING); - remove_wait_queue(&port->open_wait, &wait); - if (!tty_hung_up_p(filp)) - port->count++; - port->blocked_open--; - - spin_unlock_irqrestore(&port->lock, flags); - - if (retval) - return retval; - - port->flags |= ASYNC_NORMAL_ACTIVE; + struct channel *ch = container_of(port, struct channel, port); + if (ch->imodem & ch->dcd) + return 1; return 0; } +static void epca_raise_dtr_rts(struct tty_port *port0 +{ +} + static int pc_open(struct tty_struct *tty, struct file *filp) { struct channel *ch; @@ -978,7 +848,7 @@ static int pc_open(struct tty_struct *tty, struct file *filp) port->flags |= ASYNC_INITIALIZED; spin_unlock_irqrestore(&port->lock, flags); - retval = block_til_ready(tty, filp, ch); + retval = tty_port_block_til_ready(port, tty, filp); if (retval) return retval; /* @@ -1058,6 +928,11 @@ static const struct tty_operations pc_ops = { .break_ctl = pc_send_break }; +static const struct tty_port_operations epca_port_ops = { + .carrier_raised = epca_carrier_raised, + .raise_dtr_rts = epca_raise_dtr_rts, +}; + static int info_open(struct tty_struct *tty, struct file *filp) { return 0; @@ -1393,6 +1268,7 @@ static void post_fep_init(unsigned int crd) u16 tseg, rseg; tty_port_init(&ch->port); + ch->port.ops - &epca_port_ops; ch->brdchan = bc; ch->mailbox = gd; INIT_WORK(&ch->tqueue, do_softint); @@ -1526,7 +1402,7 @@ static void post_fep_init(unsigned int crd) ch->fepstartca = 0; ch->fepstopca = 0; - ch->close_delay = 50; + ch->port.close_delay = 50; spin_unlock_irqrestore(&epca_lock, flags); } @@ -1647,7 +1523,7 @@ static void doevent(int crd) if (event & MODEMCHG_IND) { /* A modem signal change has been indicated */ ch->imodem = mstat; - if (ch->port.flags & ASYNC_CHECK_CD) { + if (test_bit(ASYNC_CHECK_CD, &ch->port.flags)) { /* We are now receiving dcd */ if (mstat & ch->dcd) wake_up_interruptible(&ch->port.open_wait); @@ -1894,9 +1770,9 @@ static void epcaparam(struct tty_struct *tty, struct channel *ch) * that the driver will wait on carrier detect. */ if (ts->c_cflag & CLOCAL) - ch->port.flags &= ~ASYNC_CHECK_CD; + clear_bit(ASYNC_CHECK_CD, &ch->port.flags); else - ch->port.flags |= ASYNC_CHECK_CD; + set_bit(ASYNC_CHECK_CD, &ch->port.flags); mval = ch->m_dtr | ch->m_rts; } /* End CBAUD not detected */ iflag = termios2digi_i(ch, ts->c_iflag); @@ -2373,7 +2249,7 @@ static void do_softint(struct work_struct *work) if (test_and_clear_bit(EPCA_EVENT_HANGUP, &ch->event)) { tty_hangup(tty); wake_up_interruptible(&ch->port.open_wait); - ch->port.flags &= ~ASYNC_NORMAL_ACTIVE; + clear_bit(ASYNC_NORMAL_ACTIVE, &ch->port.flags); } } tty_kref_put(tty); diff --git a/drivers/char/tty_port.c b/drivers/char/tty_port.c index b3175f54fe0..b580fcf629f 100644 --- a/drivers/char/tty_port.c +++ b/drivers/char/tty_port.c @@ -286,7 +286,8 @@ int tty_port_close_start(struct tty_port *port, struct tty_struct *tty, struct f port->flags |= ASYNC_CLOSING; tty->closing = 1; spin_unlock_irqrestore(&port->lock, flags); - if (port->closing_wait != ASYNC_CLOSING_WAIT_NONE) + if (port->flags & ASYNC_INITIALIZED && + port->closing_wait != ASYNC_CLOSING_WAIT_NONE) tty_wait_until_sent(tty, port->closing_wait); return 1; } |