|
@@ -357,18 +357,6 @@ static void cy_start(struct tty_struct *tty)
|
|
|
local_irq_restore(flags);
|
|
|
} /* cy_start */
|
|
|
|
|
|
-/*
|
|
|
- * This routine is used by the interrupt handler to schedule
|
|
|
- * processing in the software interrupt portion of the driver
|
|
|
- * (also known as the "bottom half"). This can be called any
|
|
|
- * number of times for any channel without harm.
|
|
|
- */
|
|
|
-static inline void cy_sched_event(struct cyclades_port *info, int event)
|
|
|
-{
|
|
|
- info->event |= 1 << event; /* remember what kind of event and who */
|
|
|
- schedule_work(&info->tqueue);
|
|
|
-} /* cy_sched_event */
|
|
|
-
|
|
|
/* The real interrupt service routines are called
|
|
|
whenever the card wants its hand held--chars
|
|
|
received, out buffer empty, modem change, etc.
|
|
@@ -483,10 +471,12 @@ static irqreturn_t cd2401_modem_interrupt(int irq, void *dev_id)
|
|
|
&& (info->flags & ASYNC_CHECK_CD)) {
|
|
|
if (mdm_status & CyDCD) {
|
|
|
/* CP('!'); */
|
|
|
- cy_sched_event(info, Cy_EVENT_OPEN_WAKEUP);
|
|
|
+ wake_up_interruptible(&info->open_wait);
|
|
|
} else {
|
|
|
/* CP('@'); */
|
|
|
- cy_sched_event(info, Cy_EVENT_HANGUP);
|
|
|
+ tty_hangup(info->tty);
|
|
|
+ wake_up_interruptible(&info->open_wait);
|
|
|
+ info->flags &= ~ASYNC_NORMAL_ACTIVE;
|
|
|
}
|
|
|
}
|
|
|
if ((mdm_change & CyCTS)
|
|
@@ -496,8 +486,7 @@ static irqreturn_t cd2401_modem_interrupt(int irq, void *dev_id)
|
|
|
/* !!! cy_start isn't used because... */
|
|
|
info->tty->stopped = 0;
|
|
|
base_addr[CyIER] |= CyTxMpty;
|
|
|
- cy_sched_event(info,
|
|
|
- Cy_EVENT_WRITE_WAKEUP);
|
|
|
+ tty_wakeup(info->tty);
|
|
|
}
|
|
|
} else {
|
|
|
if (!(mdm_status & CyCTS)) {
|
|
@@ -543,9 +532,6 @@ static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id)
|
|
|
info->last_active = jiffies;
|
|
|
if (info->tty == 0) {
|
|
|
base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
|
|
|
- if (info->xmit_cnt < WAKEUP_CHARS) {
|
|
|
- cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
|
|
|
- }
|
|
|
base_addr[CyTEOIR] = CyNOTRANS;
|
|
|
return IRQ_HANDLED;
|
|
|
}
|
|
@@ -627,9 +613,9 @@ static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- if (info->xmit_cnt < WAKEUP_CHARS) {
|
|
|
- cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
|
|
|
- }
|
|
|
+ if (info->xmit_cnt < WAKEUP_CHARS)
|
|
|
+ tty_wakeup(info->tty);
|
|
|
+
|
|
|
base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS;
|
|
|
return IRQ_HANDLED;
|
|
|
} /* cy_tx_interrupt */
|
|
@@ -690,49 +676,6 @@ static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id)
|
|
|
return IRQ_HANDLED;
|
|
|
} /* cy_rx_interrupt */
|
|
|
|
|
|
-/*
|
|
|
- * This routine is used to handle the "bottom half" processing for the
|
|
|
- * serial driver, known also the "software interrupt" processing.
|
|
|
- * This processing is done at the kernel interrupt level, after the
|
|
|
- * cy#/_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This
|
|
|
- * is where time-consuming activities which can not be done in the
|
|
|
- * interrupt driver proper are done; the interrupt driver schedules
|
|
|
- * them using cy_sched_event(), and they get done here.
|
|
|
- *
|
|
|
- * This is done through one level of indirection--the task queue.
|
|
|
- * When a hardware interrupt service routine wants service by the
|
|
|
- * driver's bottom half, it enqueues the appropriate tq_struct (one
|
|
|
- * per port) to the keventd work queue and sets a request flag
|
|
|
- * that the work queue be processed.
|
|
|
- *
|
|
|
- * Although this may seem unwieldy, it gives the system a way to
|
|
|
- * pass an argument (in this case the pointer to the cyclades_port
|
|
|
- * structure) to the bottom half of the driver. Previous kernels
|
|
|
- * had to poll every port to see if that port needed servicing.
|
|
|
- */
|
|
|
-static void do_softint(struct work_struct *ugly_api)
|
|
|
-{
|
|
|
- struct cyclades_port *info =
|
|
|
- container_of(ugly_api, struct cyclades_port, tqueue);
|
|
|
- struct tty_struct *tty;
|
|
|
-
|
|
|
- tty = info->tty;
|
|
|
- if (!tty)
|
|
|
- return;
|
|
|
-
|
|
|
- if (test_and_clear_bit(Cy_EVENT_HANGUP, &info->event)) {
|
|
|
- tty_hangup(info->tty);
|
|
|
- wake_up_interruptible(&info->open_wait);
|
|
|
- info->flags &= ~ASYNC_NORMAL_ACTIVE;
|
|
|
- }
|
|
|
- if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) {
|
|
|
- wake_up_interruptible(&info->open_wait);
|
|
|
- }
|
|
|
- if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) {
|
|
|
- tty_wakeup(tty);
|
|
|
- }
|
|
|
-} /* do_softint */
|
|
|
-
|
|
|
/* This is called whenever a port becomes active;
|
|
|
interrupts are enabled and DTR & RTS are turned on.
|
|
|
*/
|
|
@@ -1743,7 +1686,6 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
|
|
|
if (tty->driver->flush_buffer)
|
|
|
tty->driver->flush_buffer(tty);
|
|
|
tty_ldisc_flush(tty);
|
|
|
- info->event = 0;
|
|
|
info->tty = NULL;
|
|
|
if (info->blocked_open) {
|
|
|
if (info->close_delay) {
|
|
@@ -2234,7 +2176,6 @@ static int __init serial167_init(void)
|
|
|
info->rco = baud_co[DefSpeed] >> 5; /* Rx CO */
|
|
|
info->close_delay = 0;
|
|
|
info->x_char = 0;
|
|
|
- info->event = 0;
|
|
|
info->count = 0;
|
|
|
#ifdef SERIAL_DEBUG_COUNT
|
|
|
printk("cyc: %d: setting count to 0\n",
|
|
@@ -2243,7 +2184,6 @@ static int __init serial167_init(void)
|
|
|
info->blocked_open = 0;
|
|
|
info->default_threshold = 0;
|
|
|
info->default_timeout = 0;
|
|
|
- INIT_WORK(&info->tqueue, do_softint);
|
|
|
init_waitqueue_head(&info->open_wait);
|
|
|
init_waitqueue_head(&info->close_wait);
|
|
|
/* info->session */
|