Char: cyclades, remove bottom half processing
authorJiri Slaby <jirislaby@gmail.com>
Thu, 18 Oct 2007 10:06:20 +0000 (03:06 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Thu, 18 Oct 2007 21:37:26 +0000 (14:37 -0700)
The work done in bottom half doesn't cost much cpu time (e.g.  tty_hangup
itself schedules its own bottom half), it's possible to do the work in isr
directly and save hence some .text.

Signed-off-by: Jiri Slaby <jirislaby@gmail.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Paul Fulghum <paulkf@microgate.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
drivers/char/cyclades.c
include/linux/cyclades.h

index 9e0adfe..817fef3 100644 (file)
@@ -897,71 +897,6 @@ static inline int serial_paranoia_check(struct cyclades_port *info,
        return 0;
 }                              /* serial_paranoia_check */
 
-/*
- * 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 */
-
-/*
- * 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 *work)
-{
-       struct cyclades_port *info =
-               container_of(work, 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);
-#ifdef CONFIG_CYZ_INTR
-       if (test_and_clear_bit(Cy_EVENT_Z_RX_FULL, &info->event) &&
-                       !timer_pending(&cyz_rx_full_timer[info->line]))
-               mod_timer(&cyz_rx_full_timer[info->line], jiffies + 1);
-#endif
-       if (test_and_clear_bit(Cy_EVENT_DELTA_WAKEUP, &info->event))
-               wake_up_interruptible(&info->delta_msr_wait);
-       tty_wakeup(tty);
-#ifdef Z_WAKE
-       if (test_and_clear_bit(Cy_EVENT_SHUTDOWN_WAKEUP, &info->event))
-               complete(&info->shutdown_wait);
-#endif
-} /* do_softint */
-
-
 /***********************************************************/
 /********* Start of block of Cyclom-Y specific code ********/
 
@@ -1243,7 +1178,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,
                        cy_writeb(base_addr + (CySRER << index),
                                  readb(base_addr + (CySRER << index)) &
                                  ~CyTxRdy);
-                       goto txdone;
+                       goto txend;
                }
 
                /* load the on-chip space for outbound data */
@@ -1334,9 +1269,7 @@ static void cyy_intr_chip(struct cyclades_card *cinfo, int chip,
                }
 
 txdone:
-               if (info->xmit_cnt < WAKEUP_CHARS) {
-                       cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
-               }
+               tty_wakeup(info->tty);
 txend:
                /* end of service */
                cy_writeb(base_addr + (CyTIR << index), (save_xir & 0x3f));
@@ -1369,17 +1302,16 @@ txend:
                                if (mdm_change & CyRI)
                                        info->icount.rng++;
 
-                               cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP);
+                               wake_up_interruptible(&info->delta_msr_wait);
                        }
 
                        if ((mdm_change & CyDCD) &&
                                        (info->flags & ASYNC_CHECK_CD)) {
-                               if (mdm_status & CyDCD) {
-                                       cy_sched_event(info,
-                                                       Cy_EVENT_OPEN_WAKEUP);
-                               } else {
-                                       cy_sched_event(info, Cy_EVENT_HANGUP);
+                               if (!(mdm_status & CyDCD)) {
+                                       tty_hangup(info->tty);
+                                       info->flags &= ~ASYNC_NORMAL_ACTIVE;
                                }
+                               wake_up_interruptible(&info->open_wait);
                        }
                        if ((mdm_change & CyCTS) &&
                                        (info->flags & ASYNC_CTS_FLOW)) {
@@ -1394,8 +1326,7 @@ txend:
                                                                (CySRER <<
                                                                        index))|
                                                        CyTxRdy);
-                                               cy_sched_event(info,
-                                                       Cy_EVENT_WRITE_WAKEUP);
+                                               tty_wakeup(info->tty);
                                        }
                                } else {
                                        if (!(mdm_status & CyCTS)) {
@@ -1633,9 +1564,11 @@ cyz_handle_rx(struct cyclades_port *info, struct CH_CTRL __iomem *ch_ctrl,
                                char_count = rx_put - rx_get;
                        else
                                char_count = rx_put - rx_get + rx_bufsize;
-                       if (char_count >= (int)readl(&buf_ctrl->rx_threshold)) {
-                               cy_sched_event(info, Cy_EVENT_Z_RX_FULL);
-                       }
+                       if (char_count >= (int)readl(&buf_ctrl->rx_threshold) &&
+                                       !timer_pending(&cyz_rx_full_timer[
+                                                       info->line]))
+                               mod_timer(&cyz_rx_full_timer[info->line],
+                                               jiffies + 1);
 #endif
                        info->idle_stats.recv_idle = jiffies;
                        tty_schedule_flip(tty);
@@ -1717,9 +1650,7 @@ cyz_handle_tx(struct cyclades_port *info, struct CH_CTRL __iomem *ch_ctrl,
                }
 #endif
 ztxdone:
-               if (info->xmit_cnt < WAKEUP_CHARS) {
-                       cy_sched_event(info, Cy_EVENT_WRITE_WAKEUP);
-               }
+               tty_wakeup(tty);
                /* Update tx_put */
                cy_writel(&buf_ctrl->tx_put, tx_put);
        }
@@ -1781,10 +1712,11 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
                                if ((fw_ver > 241 ? ((u_long) param) :
                                                readl(&ch_ctrl->rs_status)) &
                                                C_RS_DCD) {
-                                       cy_sched_event(info,
-                                                       Cy_EVENT_OPEN_WAKEUP);
+                                       wake_up_interruptible(&info->open_wait);
                                } else {
-                                       cy_sched_event(info, Cy_EVENT_HANGUP);
+                                       tty_hangup(info->tty);
+                                       wake_up_interruptible(&info->open_wait);
+                                       info->flags &= ~ASYNC_NORMAL_ACTIVE;
                                }
                        }
                        break;
@@ -1802,7 +1734,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
                        break;
 #ifdef Z_WAKE
                case C_CM_IOCTLW:
-                       cy_sched_event(info, Cy_EVENT_SHUTDOWN_WAKEUP);
+                       complete(&info->shutdown_wait);
                        break;
 #endif
 #ifdef CONFIG_CYZ_INTR
@@ -1834,7 +1766,7 @@ static void cyz_handle_cmd(struct cyclades_card *cinfo)
                        break;
                }
                if (delta_count)
-                       cy_sched_event(info, Cy_EVENT_DELTA_WAKEUP);
+                       wake_up_interruptible(&info->delta_msr_wait);
                if (special_count)
                        tty_schedule_flip(tty);
        }
@@ -2812,7 +2744,6 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
        spin_lock_irqsave(&card->card_lock, flags);
 
        tty->closing = 0;
-       info->event = 0;
        info->tty = NULL;
        if (info->blocked_open) {
                spin_unlock_irqrestore(&card->card_lock, flags);
@@ -4444,7 +4375,6 @@ static void cy_hangup(struct tty_struct *tty)
 
        cy_flush_buffer(tty);
        shutdown(info);
-       info->event = 0;
        info->count = 0;
 #ifdef CY_DEBUG_COUNT
        printk(KERN_DEBUG "cyc:cy_hangup (%d): setting count to 0\n",
@@ -4502,7 +4432,6 @@ static int __devinit cy_init_card(struct cyclades_card *cinfo)
                info->closing_wait = CLOSING_WAIT_DELAY;
                info->close_delay = 5 * HZ / 10;
 
-               INIT_WORK(&info->tqueue, do_softint);
                init_waitqueue_head(&info->open_wait);
                init_waitqueue_head(&info->close_wait);
                init_completion(&info->shutdown_wait);
index 72aa00c..06b2725 100644 (file)
@@ -569,7 +569,6 @@ struct cyclades_port {
        int                     x_char; /* to be pushed out ASAP */
        int                     close_delay;
        unsigned short          closing_wait;
-       unsigned long           event;
        int                     count;  /* # of fd on device */
        int                     breakon;
        int                     breakoff;
@@ -584,7 +583,6 @@ struct cyclades_port {
        struct cyclades_monitor mon;
        struct cyclades_idle_stats      idle_stats;
        struct cyclades_icount  icount;
-       struct work_struct      tqueue;
        wait_queue_head_t       open_wait;
        wait_queue_head_t       close_wait;
        struct completion       shutdown_wait;
@@ -592,19 +590,6 @@ struct cyclades_port {
        int throttle;
 };
 
-/*
- * 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 Cy_EVENT_SHUTDOWN_WAKEUP       5
-#define        Cy_EVENT_DELTA_WAKEUP           6
-#define        Cy_EVENT_Z_RX_FULL              7
-
 #define        CLOSING_WAIT_DELAY      30*HZ
 #define CY_CLOSING_WAIT_NONE   65535
 #define CY_CLOSING_WAIT_INF    0