diff options
-rw-r--r-- | drivers/char/serial167.c | 76 | ||||
-rw-r--r-- | include/linux/serial167.h | 14 |
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 | */ | ||
366 | static 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 | */ | ||
713 | static 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 ****/ |