tty/serial: lay the foundations for the next set of reworks
[linux-2.6-block.git] / drivers / char / synclink_gt.c
index 5f6a5da696c755eb49e0232b7140424a268948ca..1a11717b1adc38ff519a7bfcd1ee919082003fe0 100644 (file)
@@ -117,7 +117,7 @@ static struct pci_driver pci_driver = {
        .remove         = __devexit_p(remove_one),
 };
 
-static int pci_registered;
+static bool pci_registered;
 
 /*
  * module configuration and status
@@ -289,12 +289,12 @@ struct slgt_info {
 
        struct work_struct task;
        u32 pending_bh;
-       int bh_requested;
-       int bh_running;
+       bool bh_requested;
+       bool bh_running;
 
        int isr_overflow;
-       int irq_requested;      /* nonzero if IRQ requested */
-       int irq_occurred;       /* for diagnostics use */
+       bool irq_requested;     /* true if IRQ requested */
+       bool irq_occurred;      /* for diagnostics use */
 
        /* device configuration */
 
@@ -304,7 +304,7 @@ struct slgt_info {
 
        unsigned char __iomem * reg_addr;  /* memory mapped registers address */
        u32 phys_reg_addr;
-       int reg_addr_requested;
+       bool reg_addr_requested;
 
        MGSL_PARAMS params;       /* communications parameters */
        u32 idle_mode;
@@ -315,11 +315,11 @@ struct slgt_info {
 
        /* device status */
 
-       int rx_enabled;
-       int rx_restart;
+       bool rx_enabled;
+       bool rx_restart;
 
-       int tx_enabled;
-       int tx_active;
+       bool tx_enabled;
+       bool tx_active;
 
        unsigned char signals;    /* serial signal states */
        int init_error;  /* initialization error */
@@ -329,7 +329,7 @@ struct slgt_info {
 
        char flag_buf[MAX_ASYNC_BUFFER_SIZE];
        char char_buf[MAX_ASYNC_BUFFER_SIZE];
-       BOOLEAN drop_rts_on_tx_done;
+       bool drop_rts_on_tx_done;
        struct  _input_signal_events    input_signal_events;
 
        int dcd_chkcount;       /* check counts to prevent */
@@ -467,8 +467,8 @@ static void rx_start(struct slgt_info *info);
 static void reset_rbufs(struct slgt_info *info);
 static void free_rbufs(struct slgt_info *info, unsigned int first, unsigned int last);
 static void rdma_reset(struct slgt_info *info);
-static int  rx_get_frame(struct slgt_info *info);
-static int  rx_get_buf(struct slgt_info *info);
+static bool rx_get_frame(struct slgt_info *info);
+static bool rx_get_buf(struct slgt_info *info);
 
 static void tx_start(struct slgt_info *info);
 static void tx_stop(struct slgt_info *info);
@@ -491,7 +491,6 @@ static void isr_serial(struct slgt_info *info);
 static void isr_rdma(struct slgt_info *info);
 static void isr_txeom(struct slgt_info *info, unsigned short status);
 static void isr_tdma(struct slgt_info *info);
-static irqreturn_t slgt_interrupt(int irq, void *dev_id);
 
 static int  alloc_dma_bufs(struct slgt_info *info);
 static void free_dma_bufs(struct slgt_info *info);
@@ -772,8 +771,7 @@ static void close(struct tty_struct *tty, struct file *filp)
 
        if (info->flags & ASYNC_INITIALIZED)
                wait_until_sent(tty, info->timeout);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       flush_buffer(tty);
        tty_ldisc_flush(tty);
 
        shutdown(info);
@@ -968,6 +966,8 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
         * Note: use tight timings here to satisfy the NIST-PCTS.
         */
 
+       lock_kernel();
+
        if (info->params.data_rate) {
                char_time = info->timeout/(32 * 5);
                if (!char_time)
@@ -985,6 +985,7 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
                if (timeout && time_after(jiffies, orig_jiffies + timeout))
                        break;
        }
+       unlock_kernel();
 
 exit:
        DBGINFO(("%s wait_until_sent exit\n", info->device_name));
@@ -1098,6 +1099,7 @@ static int ioctl(struct tty_struct *tty, struct file *file,
        struct serial_icounter_struct __user *p_cuser;  /* user space */
        unsigned long flags;
        void __user *argp = (void __user *)arg;
+       int ret;
 
        if (sanity_check(info, tty->name, "ioctl"))
                return -ENODEV;
@@ -1109,37 +1111,54 @@ static int ioctl(struct tty_struct *tty, struct file *file,
                    return -EIO;
        }
 
+       lock_kernel();
+
        switch (cmd) {
        case MGSL_IOCGPARAMS:
-               return get_params(info, argp);
+               ret = get_params(info, argp);
+               break;
        case MGSL_IOCSPARAMS:
-               return set_params(info, argp);
+               ret = set_params(info, argp);
+               break;
        case MGSL_IOCGTXIDLE:
-               return get_txidle(info, argp);
+               ret = get_txidle(info, argp);
+               break;
        case MGSL_IOCSTXIDLE:
-               return set_txidle(info, (int)arg);
+               ret = set_txidle(info, (int)arg);
+               break;
        case MGSL_IOCTXENABLE:
-               return tx_enable(info, (int)arg);
+               ret = tx_enable(info, (int)arg);
+               break;
        case MGSL_IOCRXENABLE:
-               return rx_enable(info, (int)arg);
+               ret = rx_enable(info, (int)arg);
+               break;
        case MGSL_IOCTXABORT:
-               return tx_abort(info);
+               ret = tx_abort(info);
+               break;
        case MGSL_IOCGSTATS:
-               return get_stats(info, argp);
+               ret = get_stats(info, argp);
+               break;
        case MGSL_IOCWAITEVENT:
-               return wait_mgsl_event(info, argp);
+               ret = wait_mgsl_event(info, argp);
+               break;
        case TIOCMIWAIT:
-               return modem_input_wait(info,(int)arg);
+               ret = modem_input_wait(info,(int)arg);
+               break;
        case MGSL_IOCGIF:
-               return get_interface(info, argp);
+               ret = get_interface(info, argp);
+               break;
        case MGSL_IOCSIF:
-               return set_interface(info,(int)arg);
+               ret = set_interface(info,(int)arg);
+               break;
        case MGSL_IOCSGPIO:
-               return set_gpio(info, argp);
+               ret = set_gpio(info, argp);
+               break;
        case MGSL_IOCGGPIO:
-               return get_gpio(info, argp);
+               ret = get_gpio(info, argp);
+               break;
        case MGSL_IOCWAITGPIO:
-               return wait_gpio(info, argp);
+               ret = wait_gpio(info, argp);
+               break;
        case TIOCGICOUNT:
                spin_lock_irqsave(&info->lock,flags);
                cnow = info->icount;
@@ -1156,12 +1175,14 @@ static int ioctl(struct tty_struct *tty, struct file *file,
                    put_user(cnow.parity, &p_cuser->parity) ||
                    put_user(cnow.brk, &p_cuser->brk) ||
                    put_user(cnow.buf_overrun, &p_cuser->buf_overrun))
-                       return -EFAULT;
-               return 0;
+                       ret = -EFAULT;
+               ret = 0;
+               break;
        default:
-               return -ENOIOCTLCMD;
+               ret = -ENOIOCTLCMD;
        }
-       return 0;
+       unlock_kernel();
+       return ret;
 }
 
 /*
@@ -1969,8 +1990,8 @@ static int bh_action(struct slgt_info *info)
                rc = BH_STATUS;
        } else {
                /* Mark BH routine as complete */
-               info->bh_running   = 0;
-               info->bh_requested = 0;
+               info->bh_running = false;
+               info->bh_requested = false;
                rc = 0;
        }
 
@@ -1989,7 +2010,7 @@ static void bh_handler(struct work_struct *work)
 
        if (!info)
                return;
-       info->bh_running = 1;
+       info->bh_running = true;
 
        while((action = bh_action(info))) {
                switch (action) {
@@ -2039,37 +2060,41 @@ static void bh_transmit(struct slgt_info *info)
                tty_wakeup(tty);
 }
 
-static void dsr_change(struct slgt_info *info)
+static void dsr_change(struct slgt_info *info, unsigned short status)
 {
-       get_signals(info);
+       if (status & BIT3) {
+               info->signals |= SerialSignal_DSR;
+               info->input_signal_events.dsr_up++;
+       } else {
+               info->signals &= ~SerialSignal_DSR;
+               info->input_signal_events.dsr_down++;
+       }
        DBGISR(("dsr_change %s signals=%04X\n", info->device_name, info->signals));
        if ((info->dsr_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
                slgt_irq_off(info, IRQ_DSR);
                return;
        }
        info->icount.dsr++;
-       if (info->signals & SerialSignal_DSR)
-               info->input_signal_events.dsr_up++;
-       else
-               info->input_signal_events.dsr_down++;
        wake_up_interruptible(&info->status_event_wait_q);
        wake_up_interruptible(&info->event_wait_q);
        info->pending_bh |= BH_STATUS;
 }
 
-static void cts_change(struct slgt_info *info)
+static void cts_change(struct slgt_info *info, unsigned short status)
 {
-       get_signals(info);
+       if (status & BIT2) {
+               info->signals |= SerialSignal_CTS;
+               info->input_signal_events.cts_up++;
+       } else {
+               info->signals &= ~SerialSignal_CTS;
+               info->input_signal_events.cts_down++;
+       }
        DBGISR(("cts_change %s signals=%04X\n", info->device_name, info->signals));
        if ((info->cts_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
                slgt_irq_off(info, IRQ_CTS);
                return;
        }
        info->icount.cts++;
-       if (info->signals & SerialSignal_CTS)
-               info->input_signal_events.cts_up++;
-       else
-               info->input_signal_events.cts_down++;
        wake_up_interruptible(&info->status_event_wait_q);
        wake_up_interruptible(&info->event_wait_q);
        info->pending_bh |= BH_STATUS;
@@ -2090,20 +2115,21 @@ static void cts_change(struct slgt_info *info)
        }
 }
 
-static void dcd_change(struct slgt_info *info)
+static void dcd_change(struct slgt_info *info, unsigned short status)
 {
-       get_signals(info);
+       if (status & BIT1) {
+               info->signals |= SerialSignal_DCD;
+               info->input_signal_events.dcd_up++;
+       } else {
+               info->signals &= ~SerialSignal_DCD;
+               info->input_signal_events.dcd_down++;
+       }
        DBGISR(("dcd_change %s signals=%04X\n", info->device_name, info->signals));
        if ((info->dcd_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
                slgt_irq_off(info, IRQ_DCD);
                return;
        }
        info->icount.dcd++;
-       if (info->signals & SerialSignal_DCD) {
-               info->input_signal_events.dcd_up++;
-       } else {
-               info->input_signal_events.dcd_down++;
-       }
 #if SYNCLINK_GENERIC_HDLC
        if (info->netcount) {
                if (info->signals & SerialSignal_DCD)
@@ -2126,20 +2152,21 @@ static void dcd_change(struct slgt_info *info)
        }
 }
 
-static void ri_change(struct slgt_info *info)
+static void ri_change(struct slgt_info *info, unsigned short status)
 {
-       get_signals(info);
+       if (status & BIT0) {
+               info->signals |= SerialSignal_RI;
+               info->input_signal_events.ri_up++;
+       } else {
+               info->signals &= ~SerialSignal_RI;
+               info->input_signal_events.ri_down++;
+       }
        DBGISR(("ri_change %s signals=%04X\n", info->device_name, info->signals));
        if ((info->ri_chkcount)++ == IO_PIN_SHUTDOWN_LIMIT) {
                slgt_irq_off(info, IRQ_RI);
                return;
        }
-       info->icount.dcd++;
-       if (info->signals & SerialSignal_RI) {
-               info->input_signal_events.ri_up++;
-       } else {
-               info->input_signal_events.ri_down++;
-       }
+       info->icount.rng++;
        wake_up_interruptible(&info->status_event_wait_q);
        wake_up_interruptible(&info->event_wait_q);
        info->pending_bh |= BH_STATUS;
@@ -2153,7 +2180,7 @@ static void isr_serial(struct slgt_info *info)
 
        wr_reg16(info, SSR, status); /* clear pending */
 
-       info->irq_occurred = 1;
+       info->irq_occurred = true;
 
        if (info->params.mode == MGSL_MODE_ASYNC) {
                if (status & IRQ_TXIDLE) {
@@ -2190,13 +2217,13 @@ static void isr_serial(struct slgt_info *info)
        }
 
        if (status & IRQ_DSR)
-               dsr_change(info);
+               dsr_change(info, status);
        if (status & IRQ_CTS)
-               cts_change(info);
+               cts_change(info, status);
        if (status & IRQ_DCD)
-               dcd_change(info);
+               dcd_change(info, status);
        if (status & IRQ_RI)
-               ri_change(info);
+               ri_change(info, status);
 }
 
 static void isr_rdma(struct slgt_info *info)
@@ -2220,7 +2247,7 @@ static void isr_rdma(struct slgt_info *info)
 
        if (status & (BIT5 + BIT4)) {
                DBGISR(("%s isr_rdma rx_restart=1\n", info->device_name));
-               info->rx_restart = 1;
+               info->rx_restart = true;
        }
        info->pending_bh |= BH_RECEIVE;
 }
@@ -2271,14 +2298,14 @@ static void isr_txeom(struct slgt_info *info, unsigned short status)
                                info->icount.txok++;
                }
 
-               info->tx_active = 0;
+               info->tx_active = false;
                info->tx_count = 0;
 
                del_timer(&info->tx_timer);
 
                if (info->params.mode != MGSL_MODE_ASYNC && info->drop_rts_on_tx_done) {
                        info->signals &= ~SerialSignal_RTS;
-                       info->drop_rts_on_tx_done = 0;
+                       info->drop_rts_on_tx_done = false;
                        set_signals(info);
                }
 
@@ -2320,23 +2347,19 @@ static void isr_gpio(struct slgt_info *info, unsigned int changed, unsigned int
  *     irq     interrupt number
  *     dev_id  device ID supplied during interrupt registration
  */
-static irqreturn_t slgt_interrupt(int irq, void *dev_id)
+static irqreturn_t slgt_interrupt(int dummy, void *dev_id)
 {
-       struct slgt_info *info;
+       struct slgt_info *info = dev_id;
        unsigned int gsr;
        unsigned int i;
 
-       DBGISR(("slgt_interrupt irq=%d entry\n", irq));
-
-       info = dev_id;
-       if (!info)
-               return IRQ_NONE;
+       DBGISR(("slgt_interrupt irq=%d entry\n", info->irq_level));
 
        spin_lock(&info->lock);
 
        while((gsr = rd_reg32(info, GSR) & 0xffffff00)) {
                DBGISR(("%s gsr=%08x\n", info->device_name, gsr));
-               info->irq_occurred = 1;
+               info->irq_occurred = true;
                for(i=0; i < info->port_count ; i++) {
                        if (info->port_array[i] == NULL)
                                continue;
@@ -2373,13 +2396,13 @@ static irqreturn_t slgt_interrupt(int irq, void *dev_id)
                    !port->bh_requested) {
                        DBGISR(("%s bh queued\n", port->device_name));
                        schedule_work(&port->task);
-                       port->bh_requested = 1;
+                       port->bh_requested = true;
                }
        }
 
        spin_unlock(&info->lock);
 
-       DBGISR(("slgt_interrupt irq=%d exit\n", irq));
+       DBGISR(("slgt_interrupt irq=%d exit\n", info->irq_level));
        return IRQ_HANDLED;
 }
 
@@ -3109,7 +3132,8 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
 {
        DECLARE_WAITQUEUE(wait, current);
        int             retval;
-       int             do_clocal = 0, extra_count = 0;
+       bool            do_clocal = false;
+       bool            extra_count = false;
        unsigned long   flags;
 
        DBGINFO(("%s block_til_ready\n", tty->driver->name));
@@ -3121,7 +3145,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
        }
 
        if (tty->termios->c_cflag & CLOCAL)
-               do_clocal = 1;
+               do_clocal = true;
 
        /* Wait for carrier detect and the line to become
         * free (i.e., not in use by the callout).  While we are in
@@ -3135,7 +3159,7 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
 
        spin_lock_irqsave(&info->lock, flags);
        if (!tty_hung_up_p(filp)) {
-               extra_count = 1;
+               extra_count = true;
                info->count--;
        }
        spin_unlock_irqrestore(&info->lock, flags);
@@ -3320,7 +3344,7 @@ static int claim_resources(struct slgt_info *info)
                goto errout;
        }
        else
-               info->reg_addr_requested = 1;
+               info->reg_addr_requested = true;
 
        info->reg_addr = ioremap(info->phys_reg_addr, SLGT_REG_SIZE);
        if (!info->reg_addr) {
@@ -3340,12 +3364,12 @@ static void release_resources(struct slgt_info *info)
 {
        if (info->irq_requested) {
                free_irq(info->irq_level, info);
-               info->irq_requested = 0;
+               info->irq_requested = false;
        }
 
        if (info->reg_addr_requested) {
                release_mem_region(info->phys_reg_addr, SLGT_REG_SIZE);
-               info->reg_addr_requested = 0;
+               info->reg_addr_requested = false;
        }
 
        if (info->reg_addr) {
@@ -3510,7 +3534,7 @@ static void device_init(int adapter_num, struct pci_dev *pdev)
                                port_array[0]->device_name,
                                port_array[0]->irq_level));
                } else {
-                       port_array[0]->irq_requested = 1;
+                       port_array[0]->irq_requested = true;
                        adapter_test(port_array[0]);
                        for (i=1 ; i < port_count ; i++) {
                                port_array[i]->init_error = port_array[0]->init_error;
@@ -3653,7 +3677,7 @@ static int __init slgt_init(void)
                printk("%s pci_register_driver error=%d\n", driver_name, rc);
                goto error;
        }
-       pci_registered = 1;
+       pci_registered = true;
 
        if (!slgt_device_list)
                printk("%s no devices found\n",driver_name);
@@ -3811,8 +3835,8 @@ static void rx_stop(struct slgt_info *info)
 
        rdma_reset(info);
 
-       info->rx_enabled = 0;
-       info->rx_restart = 0;
+       info->rx_enabled = false;
+       info->rx_restart = false;
 }
 
 static void rx_start(struct slgt_info *info)
@@ -3848,8 +3872,8 @@ static void rx_start(struct slgt_info *info)
        /* enable receiver */
        wr_reg16(info, RCR, (unsigned short)(rd_reg16(info, RCR) | BIT1));
 
-       info->rx_restart = 0;
-       info->rx_enabled = 1;
+       info->rx_restart = false;
+       info->rx_enabled = true;
 }
 
 static void tx_start(struct slgt_info *info)
@@ -3857,11 +3881,11 @@ static void tx_start(struct slgt_info *info)
        if (!info->tx_enabled) {
                wr_reg16(info, TCR,
                         (unsigned short)((rd_reg16(info, TCR) | BIT1) & ~BIT2));
-               info->tx_enabled = TRUE;
+               info->tx_enabled = true;
        }
 
        if (info->tx_count) {
-               info->drop_rts_on_tx_done = 0;
+               info->drop_rts_on_tx_done = false;
 
                if (info->params.mode != MGSL_MODE_ASYNC) {
                        if (info->params.flags & HDLC_FLAG_AUTO_RTS) {
@@ -3869,7 +3893,7 @@ static void tx_start(struct slgt_info *info)
                                if (!(info->signals & SerialSignal_RTS)) {
                                        info->signals |= SerialSignal_RTS;
                                        set_signals(info);
-                                       info->drop_rts_on_tx_done = 1;
+                                       info->drop_rts_on_tx_done = true;
                                }
                        }
 
@@ -3887,7 +3911,7 @@ static void tx_start(struct slgt_info *info)
                        wr_reg16(info, SSR, IRQ_TXIDLE);
                }
                tdma_start(info);
-               info->tx_active = 1;
+               info->tx_active = true;
        }
 }
 
@@ -3948,8 +3972,8 @@ static void tx_stop(struct slgt_info *info)
 
        reset_tbufs(info);
 
-       info->tx_enabled = 0;
-       info->tx_active  = 0;
+       info->tx_enabled = false;
+       info->tx_active = false;
 }
 
 static void reset_port(struct slgt_info *info)
@@ -4469,14 +4493,13 @@ static void reset_rbufs(struct slgt_info *info)
 /*
  * pass receive HDLC frame to upper layer
  *
- * return 1 if frame available, otherwise 0
+ * return true if frame available, otherwise false
  */
-static int rx_get_frame(struct slgt_info *info)
+static bool rx_get_frame(struct slgt_info *info)
 {
        unsigned int start, end;
        unsigned short status;
        unsigned int framesize = 0;
-       int rc = 0;
        unsigned long flags;
        struct tty_struct *tty = info->tty;
        unsigned char addr_field = 0xff;
@@ -4600,23 +4623,23 @@ check_again:
                }
        }
        free_rbufs(info, start, end);
-       rc = 1;
+       return true;
 
 cleanup:
-       return rc;
+       return false;
 }
 
 /*
  * pass receive buffer (RAW synchronous mode) to tty layer
- * return 1 if buffer available, otherwise 0
+ * return true if buffer available, otherwise false
  */
-static int rx_get_buf(struct slgt_info *info)
+static bool rx_get_buf(struct slgt_info *info)
 {
        unsigned int i = info->rbuf_current;
        unsigned int count;
 
        if (!desc_complete(info->rbufs[i]))
-               return 0;
+               return false;
        count = desc_count(info->rbufs[i]);
        switch(info->params.mode) {
        case MGSL_MODE_MONOSYNC:
@@ -4632,7 +4655,7 @@ static int rx_get_buf(struct slgt_info *info)
                ldisc_receive_buf(info->tty, info->rbufs[i].buf,
                                  info->flag_buf, count);
        free_rbufs(info, i, i);
-       return 1;
+       return true;
 }
 
 static void reset_tbufs(struct slgt_info *info)
@@ -4757,7 +4780,7 @@ static int irq_test(struct slgt_info *info)
 
        /* assume failure */
        info->init_error = DiagStatus_IrqFailure;
-       info->irq_occurred = FALSE;
+       info->irq_occurred = false;
 
        spin_unlock_irqrestore(&info->lock, flags);
 
@@ -4890,7 +4913,7 @@ static void tx_timeout(unsigned long context)
                info->icount.txtimeout++;
        }
        spin_lock_irqsave(&info->lock,flags);
-       info->tx_active = 0;
+       info->tx_active = false;
        info->tx_count = 0;
        spin_unlock_irqrestore(&info->lock,flags);