aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/char/serial167.c76
-rw-r--r--include/linux/serial167.h14
2 files changed, 8 insertions, 82 deletions
diff --git a/drivers/char/serial167.c b/drivers/char/serial167.c
index cbf21cc7b56d..df8cd0ca97eb 100644
--- a/drivers/char/serial167.c
+++ b/drivers/char/serial167.c
@@ -357,18 +357,6 @@ static void cy_start(struct tty_struct *tty)
357 local_irq_restore(flags); 357 local_irq_restore(flags);
358} /* cy_start */ 358} /* cy_start */
359 359
360/*
361 * This routine is used by the interrupt handler to schedule
362 * processing in the software interrupt portion of the driver
363 * (also known as the "bottom half"). This can be called any
364 * number of times for any channel without harm.
365 */
366static inline void cy_sched_event(struct cyclades_port *info, int event)
367{
368 info->event |= 1 << event; /* remember what kind of event and who */
369 schedule_work(&info->tqueue);
370} /* cy_sched_event */
371
372/* The real interrupt service routines are called 360/* The real interrupt service routines are called
373 whenever the card wants its hand held--chars 361 whenever the card wants its hand held--chars
374 received, out buffer empty, modem change, etc. 362 received, out buffer empty, modem change, etc.
@@ -483,10 +471,12 @@ static irqreturn_t cd2401_modem_interrupt(int irq, void *dev_id)
483 && (info->flags & ASYNC_CHECK_CD)) { 471 && (info->flags & ASYNC_CHECK_CD)) {
484 if (mdm_status & CyDCD) { 472 if (mdm_status & CyDCD) {
485/* CP('!'); */ 473/* CP('!'); */
486 cy_sched_event(info, Cy_EVENT_OPEN_WAKEUP); 474 wake_up_interruptible(&info->open_wait);
487 } else { 475 } else {
488/* CP('@'); */ 476/* CP('@'); */
489 cy_sched_event(info, Cy_EVENT_HANGUP); 477 tty_hangup(info->tty);
478 wake_up_interruptible(&info->open_wait);
479 info->flags &= ~ASYNC_NORMAL_ACTIVE;
490 } 480 }
491 } 481 }
492 if ((mdm_change & CyCTS) 482 if ((mdm_change & CyCTS)
@@ -496,8 +486,7 @@ static irqreturn_t cd2401_modem_interrupt(int irq, void *dev_id)
496 /* !!! cy_start isn't used because... */ 486 /* !!! cy_start isn't used because... */
497 info->tty->stopped = 0; 487 info->tty->stopped = 0;
498 base_addr[CyIER] |= CyTxMpty; 488 base_addr[CyIER] |= CyTxMpty;
499 cy_sched_event(info, 489 tty_wakeup(info->tty);
500 Cy_EVENT_WRITE_WAKEUP);
501 } 490 }
502 } else { 491 } else {
503 if (!(mdm_status & CyCTS)) { 492 if (!(mdm_status & CyCTS)) {
@@ -543,9 +532,6 @@ static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id)
543 info->last_active = jiffies; 532 info->last_active = jiffies;
544 if (info->tty == 0) { 533 if (info->tty == 0) {
545 base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy); 534 base_addr[CyIER] &= ~(CyTxMpty | CyTxRdy);
546 if (info->xmit_cnt < WAKEUP_CHARS) {
547 cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
548 }
549 base_addr[CyTEOIR] = CyNOTRANS; 535 base_addr[CyTEOIR] = CyNOTRANS;
550 return IRQ_HANDLED; 536 return IRQ_HANDLED;
551 } 537 }
@@ -627,9 +613,9 @@ static irqreturn_t cd2401_tx_interrupt(int irq, void *dev_id)
627 } 613 }
628 } 614 }
629 615
630 if (info->xmit_cnt < WAKEUP_CHARS) { 616 if (info->xmit_cnt < WAKEUP_CHARS)
631 cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP); 617 tty_wakeup(info->tty);
632 } 618
633 base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS; 619 base_addr[CyTEOIR] = (char_count != saved_cnt) ? 0 : CyNOTRANS;
634 return IRQ_HANDLED; 620 return IRQ_HANDLED;
635} /* cy_tx_interrupt */ 621} /* cy_tx_interrupt */
@@ -690,49 +676,6 @@ static irqreturn_t cd2401_rx_interrupt(int irq, void *dev_id)
690 return IRQ_HANDLED; 676 return IRQ_HANDLED;
691} /* cy_rx_interrupt */ 677} /* cy_rx_interrupt */
692 678
693/*
694 * This routine is used to handle the "bottom half" processing for the
695 * serial driver, known also the "software interrupt" processing.
696 * This processing is done at the kernel interrupt level, after the
697 * cy#/_interrupt() has returned, BUT WITH INTERRUPTS TURNED ON. This
698 * is where time-consuming activities which can not be done in the
699 * interrupt driver proper are done; the interrupt driver schedules
700 * them using cy_sched_event(), and they get done here.
701 *
702 * This is done through one level of indirection--the task queue.
703 * When a hardware interrupt service routine wants service by the
704 * driver's bottom half, it enqueues the appropriate tq_struct (one
705 * per port) to the keventd work queue and sets a request flag
706 * that the work queue be processed.
707 *
708 * Although this may seem unwieldy, it gives the system a way to
709 * pass an argument (in this case the pointer to the cyclades_port
710 * structure) to the bottom half of the driver. Previous kernels
711 * had to poll every port to see if that port needed servicing.
712 */
713static void do_softint(struct work_struct *ugly_api)
714{
715 struct cyclades_port *info =
716 container_of(ugly_api, struct cyclades_port, tqueue);
717 struct tty_struct *tty;
718
719 tty = info->tty;
720 if (!tty)
721 return;
722
723 if (test_and_clear_bit(Cy_EVENT_HANGUP, &info->event)) {
724 tty_hangup(info->tty);
725 wake_up_interruptible(&info->open_wait);
726 info->flags &= ~ASYNC_NORMAL_ACTIVE;
727 }
728 if (test_and_clear_bit(Cy_EVENT_OPEN_WAKEUP, &info->event)) {
729 wake_up_interruptible(&info->open_wait);
730 }
731 if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) {
732 tty_wakeup(tty);
733 }
734} /* do_softint */
735
736/* This is called whenever a port becomes active; 679/* This is called whenever a port becomes active;
737 interrupts are enabled and DTR & RTS are turned on. 680 interrupts are enabled and DTR & RTS are turned on.
738 */ 681 */
@@ -1743,7 +1686,6 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
1743 if (tty->driver->flush_buffer) 1686 if (tty->driver->flush_buffer)
1744 tty->driver->flush_buffer(tty); 1687 tty->driver->flush_buffer(tty);
1745 tty_ldisc_flush(tty); 1688 tty_ldisc_flush(tty);
1746 info->event = 0;
1747 info->tty = NULL; 1689 info->tty = NULL;
1748 if (info->blocked_open) { 1690 if (info->blocked_open) {
1749 if (info->close_delay) { 1691 if (info->close_delay) {
@@ -2234,7 +2176,6 @@ static int __init serial167_init(void)
2234 info->rco = baud_co[DefSpeed] >> 5; /* Rx CO */ 2176 info->rco = baud_co[DefSpeed] >> 5; /* Rx CO */
2235 info->close_delay = 0; 2177 info->close_delay = 0;
2236 info->x_char = 0; 2178 info->x_char = 0;
2237 info->event = 0;
2238 info->count = 0; 2179 info->count = 0;
2239#ifdef SERIAL_DEBUG_COUNT 2180#ifdef SERIAL_DEBUG_COUNT
2240 printk("cyc: %d: setting count to 0\n", 2181 printk("cyc: %d: setting count to 0\n",
@@ -2243,7 +2184,6 @@ static int __init serial167_init(void)
2243 info->blocked_open = 0; 2184 info->blocked_open = 0;
2244 info->default_threshold = 0; 2185 info->default_threshold = 0;
2245 info->default_timeout = 0; 2186 info->default_timeout = 0;
2246 INIT_WORK(&info->tqueue, do_softint);
2247 init_waitqueue_head(&info->open_wait); 2187 init_waitqueue_head(&info->open_wait);
2248 init_waitqueue_head(&info->close_wait); 2188 init_waitqueue_head(&info->close_wait);
2249 /* info->session */ 2189 /* info->session */
diff --git a/include/linux/serial167.h b/include/linux/serial167.h
index 71b6df2516a6..59c81b708562 100644
--- a/include/linux/serial167.h
+++ b/include/linux/serial167.h
@@ -37,7 +37,6 @@ struct cyclades_port {
37 int ignore_status_mask; 37 int ignore_status_mask;
38 int close_delay; 38 int close_delay;
39 int IER; /* Interrupt Enable Register */ 39 int IER; /* Interrupt Enable Register */
40 unsigned long event;
41 unsigned long last_active; 40 unsigned long last_active;
42 int count; /* # of fd on device */ 41 int count; /* # of fd on device */
43 int x_char; /* to be pushed out ASAP */ 42 int x_char; /* to be pushed out ASAP */
@@ -49,7 +48,6 @@ struct cyclades_port {
49 int xmit_cnt; 48 int xmit_cnt;
50 int default_threshold; 49 int default_threshold;
51 int default_timeout; 50 int default_timeout;
52 struct work_struct tqueue;
53 wait_queue_head_t open_wait; 51 wait_queue_head_t open_wait;
54 wait_queue_head_t close_wait; 52 wait_queue_head_t close_wait;
55 struct cyclades_monitor mon; 53 struct cyclades_monitor mon;
@@ -67,18 +65,6 @@ struct cyclades_port {
67#define CYGETDEFTIMEOUT 0x435908 65#define CYGETDEFTIMEOUT 0x435908
68#define CYSETDEFTIMEOUT 0x435909 66#define CYSETDEFTIMEOUT 0x435909
69 67
70/*
71 * Events are used to schedule things to happen at timer-interrupt
72 * time, instead of at cy interrupt time.
73 */
74#define Cy_EVENT_READ_PROCESS 0
75#define Cy_EVENT_WRITE_WAKEUP 1
76#define Cy_EVENT_HANGUP 2
77#define Cy_EVENT_BREAK 3
78#define Cy_EVENT_OPEN_WAKEUP 4
79
80
81
82#define CyMaxChipsPerCard 1 68#define CyMaxChipsPerCard 1
83 69
84/**** cd2401 registers ****/ 70/**** cd2401 registers ****/