Commit 3099bbc5 authored by Jiri Slaby's avatar Jiri Slaby Committed by Linus Torvalds

Char: serial167, remove bottomhalf

- Cy_EVENT_OPEN_WAKEUP is simple wake_up
- Cy_EVENT_HANGUP is wake_up + tty_hangup, which schedules its own work
- Cy_EVENT_WRITE_WAKEUP is tty_wakeup which may be called directly too
Signed-off-by: default avatarJiri Slaby <jirislaby@gmail.com>
Acked-by: default avatarAlan Cox <alan@redhat.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent ccfea3c9
...@@ -357,18 +357,6 @@ static void cy_start(struct tty_struct *tty) ...@@ -357,18 +357,6 @@ static void cy_start(struct tty_struct *tty)
local_irq_restore(flags); local_irq_restore(flags);
} /* cy_start */ } /* 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 /* The real interrupt service routines are called
whenever the card wants its hand held--chars whenever the card wants its hand held--chars
received, out buffer empty, modem change, etc. received, out buffer empty, modem change, etc.
...@@ -483,10 +471,12 @@ static irqreturn_t cd2401_modem_interrupt(int irq, void *dev_id) ...@@ -483,10 +471,12 @@ static irqreturn_t cd2401_modem_interrupt(int irq, void *dev_id)
&& (info->flags & ASYNC_CHECK_CD)) { && (info->flags & ASYNC_CHECK_CD)) {
if (mdm_status & CyDCD) { if (mdm_status & CyDCD) {
/* CP('!'); */ /* CP('!'); */
cy_sched_event(info, Cy_EVENT_OPEN_WAKEUP); wake_up_interruptible(&info->open_wait);
} else { } else {
/* CP('@'); */ /* 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) if ((mdm_change & CyCTS)
...@@ -496,8 +486,7 @@ static irqreturn_t cd2401_modem_interrupt(int irq, void *dev_id) ...@@ -496,8 +486,7 @@ static irqreturn_t cd2401_modem_interrupt(int irq, void *dev_id)
/* !!! cy_start isn't used because... */ /* !!! cy_start isn't used because... */
info->tty->stopped = 0; info->tty->stopped = 0;
base_addr[CyIER] |= CyTxMpty; base_addr[CyIER] |= CyTxMpty;
cy_sched_event(info, tty_wakeup(info->tty);
Cy_EVENT_WRITE_WAKEUP);
} }
} else { } else {
if (!(mdm_status & CyCTS)) { if (!(mdm_status & CyCTS)) {
...@@ -543,9 +532,6 @@ static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id) ...@@ -543,9 +532,6 @@ static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id)
info->last_active = jiffies; info->last_active = jiffies;
if (info->tty == 0) { if (info->tty == 0) {
base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
if (info->xmit_cnt < WAKEUP_CHARS) {
cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
}
base_addr[CyTEOIR] = CyNOTRANS; base_addr[CyTEOIR] = CyNOTRANS;
return IRQ_HANDLED; return IRQ_HANDLED;
} }
...@@ -627,9 +613,9 @@ static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id) ...@@ -627,9 +613,9 @@ static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id)
} }
} }
if (info->xmit_cnt < WAKEUP_CHARS) { if (info->xmit_cnt < WAKEUP_CHARS)
cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); tty_wakeup(info->tty);
}
base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS; base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS;
return IRQ_HANDLED; return IRQ_HANDLED;
} /* cy_tx_interrupt */ } /* cy_tx_interrupt */
...@@ -690,49 +676,6 @@ static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id) ...@@ -690,49 +676,6 @@ static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id)
return IRQ_HANDLED; return IRQ_HANDLED;
} /* cy_rx_interrupt */ } /* 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; /* This is called whenever a port becomes active;
interrupts are enabled and DTR & RTS are turned on. interrupts are enabled and DTR & RTS are turned on.
*/ */
...@@ -1743,7 +1686,6 @@ static void cy_close(struct tty_struct *tty, struct file *filp) ...@@ -1743,7 +1686,6 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
if (tty->driver->flush_buffer) if (tty->driver->flush_buffer)
tty->driver->flush_buffer(tty); tty->driver->flush_buffer(tty);
tty_ldisc_flush(tty); tty_ldisc_flush(tty);
info->event = 0;
info->tty = NULL; info->tty = NULL;
if (info->blocked_open) { if (info->blocked_open) {
if (info->close_delay) { if (info->close_delay) {
...@@ -2234,7 +2176,6 @@ static int __init serial167_init(void) ...@@ -2234,7 +2176,6 @@ static int __init serial167_init(void)
info->rco = baud_co[DefSpeed] >> 5; /* Rx CO */ info->rco = baud_co[DefSpeed] >> 5; /* Rx CO */
info->close_delay = 0; info->close_delay = 0;
info->x_char = 0; info->x_char = 0;
info->event = 0;
info->count = 0; info->count = 0;
#ifdef SERIAL_DEBUG_COUNT #ifdef SERIAL_DEBUG_COUNT
printk("cyc: %d: setting count to 0\n", printk("cyc: %d: setting count to 0\n",
...@@ -2243,7 +2184,6 @@ static int __init serial167_init(void) ...@@ -2243,7 +2184,6 @@ static int __init serial167_init(void)
info->blocked_open = 0; info->blocked_open = 0;
info->default_threshold = 0; info->default_threshold = 0;
info->default_timeout = 0; info->default_timeout = 0;
INIT_WORK(&info->tqueue, do_softint);
init_waitqueue_head(&info->open_wait); init_waitqueue_head(&info->open_wait);
init_waitqueue_head(&info->close_wait); init_waitqueue_head(&info->close_wait);
/* info->session */ /* info->session */
......
...@@ -37,7 +37,6 @@ struct cyclades_port { ...@@ -37,7 +37,6 @@ struct cyclades_port {
int ignore_status_mask; int ignore_status_mask;
int close_delay; int close_delay;
int IER; /* Interrupt Enable Register */ int IER; /* Interrupt Enable Register */
unsigned long event;
unsigned long last_active; unsigned long last_active;
int count; /* # of fd on device */ int count; /* # of fd on device */
int x_char; /* to be pushed out ASAP */ int x_char; /* to be pushed out ASAP */
...@@ -49,7 +48,6 @@ struct cyclades_port { ...@@ -49,7 +48,6 @@ struct cyclades_port {
int xmit_cnt; int xmit_cnt;
int default_threshold; int default_threshold;
int default_timeout; int default_timeout;
struct work_struct tqueue;
wait_queue_head_t open_wait; wait_queue_head_t open_wait;
wait_queue_head_t close_wait; wait_queue_head_t close_wait;
struct cyclades_monitor mon; struct cyclades_monitor mon;
...@@ -67,18 +65,6 @@ struct cyclades_port { ...@@ -67,18 +65,6 @@ struct cyclades_port {
#define CYGETDEFTIMEOUT 0x435908 #define CYGETDEFTIMEOUT 0x435908
#define CYSETDEFTIMEOUT 0x435909 #define CYSETDEFTIMEOUT 0x435909
/*
* Events are used to schedule things to happen at timer-interrupt
* time, instead of at cy interrupt time.
*/
#define Cy_EVENT_READ_PROCESS 0
#define Cy_EVENT_WRITE_WAKEUP 1
#define Cy_EVENT_HANGUP 2
#define Cy_EVENT_BREAK 3
#define Cy_EVENT_OPEN_WAKEUP 4
#define CyMaxChipsPerCard 1 #define CyMaxChipsPerCard 1
/**** cd2401 registers ****/ /**** cd2401 registers ****/
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment