fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / drivers / char / serial167.c
index 1b51eec..af50d32 100644 (file)
  * - don't use the panic function in serial167_init
  * - do resource release on failure on serial167_init
  * - include missing restore_flags in mvme167_serial_console_setup
+ *
+ * Kars de Jong <jongk@linux-m68k.org> - 2004/09/06
+ * - replace bottom half handler with task queue handler
  */
 
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/signal.h>
 #include <linux/sched.h>
 #include <linux/mm.h>
 #include <linux/console.h>
 #include <linux/module.h>
+#include <linux/bitops.h>
+#include <linux/tty_flip.h>
 
 #include <asm/system.h>
 #include <asm/io.h>
-#include <asm/bitops.h>
 #include <asm/mvme16xhw.h>
 #include <asm/bootinfo.h>
 #include <asm/setup.h>
 #undef  CYCLOM_16Y_HACK
 #define  CYCLOM_ENABLE_MONITORING
 
-#ifndef MIN
-#define MIN(a,b)       ((a) < (b) ? (a) : (b))
-#endif
-
 #define WAKEUP_CHARS 256
 
 #define STD_COM_FLAGS (0)
 
 #define SERIAL_TYPE_NORMAL  1
 
-DECLARE_TASK_QUEUE(tq_cyclades);
-
 static struct tty_driver *cy_serial_driver;
 extern int serial_console;
 static struct cyclades_port *serial_console_info = NULL;
@@ -120,19 +117,7 @@ struct cyclades_port cy_port[] = {
         {-1 },      /* ttyS2 */
         {-1 },      /* ttyS3 */
 };
-#define NR_PORTS        (sizeof(cy_port)/sizeof(struct cyclades_port))
-
-/*
- * tmp_buf is used as a temporary buffer by serial_write.  We need to
- * lock it in case the copy_from_user blocks while swapping in a page,
- * and some other program tries to do a serial write at the same time.
- * Since the lock will only come under contention when the system is
- * swapping and available memory is low, it makes sense to share one
- * buffer across all the serial ports, since it significantly saves
- * memory if large numbers of serial ports are open.
- */
-static unsigned char *tmp_buf = 0;
-DECLARE_MUTEX(tmp_buf_sem);
+#define NR_PORTS        ARRAY_SIZE(cy_port)
 
 /*
  * This is used to look up the divisor speeds and the timeouts
@@ -377,8 +362,7 @@ static inline void
 cy_sched_event(struct cyclades_port *info, int event)
 {
     info->event |= 1 << event; /* remember what kind of event and who */
-    queue_task(&info->tqueue, &tq_cyclades); /* it belongs to */
-    mark_bh(CYCLADES_BH);                       /* then trigger event */
+    schedule_work(&info->tqueue);
 } /* cy_sched_event */
 
 
@@ -387,7 +371,7 @@ cy_sched_event(struct cyclades_port *info, int event)
    received, out buffer empty, modem change, etc.
  */
 static irqreturn_t
-cd2401_rxerr_interrupt(int irq, void *dev_id, struct pt_regs *fp)
+cd2401_rxerr_interrupt(int irq, void *dev_id)
 {
     struct tty_struct *tty;
     struct cyclades_port *info;
@@ -426,59 +410,50 @@ cd2401_rxerr_interrupt(int irq, void *dev_id, struct pt_regs *fp)
            base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
            return IRQ_HANDLED;
        }
-       if (tty->flip.count < TTY_FLIPBUF_SIZE){
-           tty->flip.count++;
+       if (tty_buffer_request_room(tty, 1) != 0){
            if (err & info->read_status_mask){
                if(err & CyBREAK){
-                   *tty->flip.flag_buf_ptr++ = TTY_BREAK;
-                   *tty->flip.char_buf_ptr++ = data;
+                   tty_insert_flip_char(tty, data, TTY_BREAK);
                    if (info->flags & ASYNC_SAK){
                        do_SAK(tty);
                    }
                }else if(err & CyFRAME){
-                   *tty->flip.flag_buf_ptr++ = TTY_FRAME;
-                   *tty->flip.char_buf_ptr++ = data;
+                   tty_insert_flip_char(tty, data, TTY_FRAME);
                }else if(err & CyPARITY){
-                   *tty->flip.flag_buf_ptr++ = TTY_PARITY;
-                   *tty->flip.char_buf_ptr++ = data;
+                   tty_insert_flip_char(tty, data, TTY_PARITY);
                }else if(err & CyOVERRUN){
-                   *tty->flip.flag_buf_ptr++ = TTY_OVERRUN;
-                   *tty->flip.char_buf_ptr++ = 0;
+                   tty_insert_flip_char(tty, 0, TTY_OVERRUN);
                    /*
                       If the flip buffer itself is
                       overflowing, we still loose
                       the next incoming character.
                     */
-                   if(tty->flip.count < TTY_FLIPBUF_SIZE){
-                       tty->flip.count++;
-                       *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
-                       *tty->flip.char_buf_ptr++ = data;
+                   if (tty_buffer_request_room(tty, 1) != 0){
+                       tty_insert_flip_char(tty, data, TTY_FRAME);
                    }
                /* These two conditions may imply */
                /* a normal read should be done. */
                /* else if(data & CyTIMEOUT) */
                /* else if(data & CySPECHAR) */
                }else{
-                   *tty->flip.flag_buf_ptr++ = 0;
-                   *tty->flip.char_buf_ptr++ = 0;
+                   tty_insert_flip_char(tty, 0, TTY_NORMAL);
                }
            }else{
-               *tty->flip.flag_buf_ptr++ = 0;
-               *tty->flip.char_buf_ptr++ = 0;
+               tty_insert_flip_char(tty, data, TTY_NORMAL);
            }
        }else{
            /* there was a software buffer overrun
               and nothing could be done about it!!! */
        }
     }
-    queue_task(&tty->flip.tqueue, &tq_timer);
+    tty_schedule_flip(tty);
     /* end of service */
     base_addr[CyREOIR] = rfoc ? 0 : CyNOTRANS;
     return IRQ_HANDLED;
 } /* cy_rxerr_interrupt */
 
 static irqreturn_t
-cd2401_modem_interrupt(int irq, void *dev_id, struct pt_regs *fp)
+cd2401_modem_interrupt(int irq, void *dev_id)
 {
     struct cyclades_port *info;
     volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
@@ -533,7 +508,7 @@ cd2401_modem_interrupt(int irq, void *dev_id, struct pt_regs *fp)
 } /* cy_modem_interrupt */
 
 static irqreturn_t
-cd2401_tx_interrupt(int irq, void *dev_id, struct pt_regs *fp)
+cd2401_tx_interrupt(int irq, void *dev_id)
 {
     struct cyclades_port *info;
     volatile unsigned char *base_addr = (unsigned char *)BASE_ADDR;
@@ -653,7 +628,7 @@ cd2401_tx_interrupt(int irq, void *dev_id, struct pt_regs *fp)
 } /* cy_tx_interrupt */
 
 static irqreturn_t
-cd2401_rx_interrupt(int irq, void *dev_id, struct pt_regs *fp)
+cd2401_rx_interrupt(int irq, void *dev_id)
 {
     struct tty_struct *tty;
     struct cyclades_port *info;
@@ -662,6 +637,7 @@ cd2401_rx_interrupt(int irq, void *dev_id, struct pt_regs *fp)
     char data;
     int char_count;
     int save_cnt;
+    int len;
 
     /* determine the channel and change to that context */
     channel = (u_short ) (base_addr[CyLICR] >> 2);
@@ -694,19 +670,15 @@ cd2401_rx_interrupt(int irq, void *dev_id, struct pt_regs *fp)
            info->mon.char_max = char_count;
        info->mon.char_last = char_count;
 #endif
-       while(char_count--){
+       len = tty_buffer_request_room(tty, char_count);
+       while(len--){
            data = base_addr[CyRDR];
-           if (tty->flip.count >= TTY_FLIPBUF_SIZE){
-               continue;
-           }
-           tty->flip.count++;
-           *tty->flip.flag_buf_ptr++ = TTY_NORMAL;
-           *tty->flip.char_buf_ptr++ = data;
+           tty_insert_flip_char(tty, data, TTY_NORMAL);
 #ifdef CYCLOM_16Y_HACK
            udelay(10L);
 #endif
         }
-       queue_task(&tty->flip.tqueue, &tq_timer);
+       tty_schedule_flip(tty);
     }
     /* end of service */
     base_addr[CyREOIR] = save_cnt ? 0 : CyNOTRANS;
@@ -717,7 +689,7 @@ cd2401_rx_interrupt(int irq, void *dev_id, struct pt_regs *fp)
  * 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
+ * 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.
@@ -725,9 +697,7 @@ cd2401_rx_interrupt(int irq, void *dev_id, struct pt_regs *fp)
  * 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 tq_cyclades work queue and sets a request flag
- * via mark_bh for processing that queue.  When the time is right,
- * do_cyclades_bh is called (because of the mark_bh) and it requests
+ * 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
@@ -736,15 +706,9 @@ cd2401_rx_interrupt(int irq, void *dev_id, struct pt_regs *fp)
  * had to poll every port to see if that port needed servicing.
  */
 static void
-do_cyclades_bh(void)
+do_softint(struct work_struct *ugly_api)
 {
-    run_task_queue(&tq_cyclades);
-} /* do_cyclades_bh */
-
-static void
-do_softint(void *private_)
-{
-  struct cyclades_port *info = (struct cyclades_port *) private_;
+  struct cyclades_port *info = container_of(ugly_api, struct cyclades_port, tqueue);
   struct tty_struct    *tty;
 
     tty = info->tty;
@@ -760,11 +724,7 @@ do_softint(void *private_)
        wake_up_interruptible(&info->open_wait);
     }
     if (test_and_clear_bit(Cy_EVENT_WRITE_WAKEUP, &info->event)) {
-       if((tty->flags & (1<< TTY_DO_WRITE_WAKEUP))
-       && tty->ldisc.write_wakeup){
-           (tty->ldisc.write_wakeup)(tty);
-       }
-       wake_up_interruptible(&tty->write_wait);
+       tty_wakeup(tty);
     }
 } /* do_softint */
 
@@ -879,7 +839,7 @@ shutdown(struct cyclades_port * info)
     local_irq_save(flags);
        if (info->xmit_buf){
            free_page((unsigned long) info->xmit_buf);
-           info->xmit_buf = 0;
+           info->xmit_buf = NULL;
        }
 
        base_addr[CyCAR] = (u_char)channel;
@@ -1165,7 +1125,7 @@ cy_put_char(struct tty_struct *tty, unsigned char ch)
     if (serial_paranoia_check(info, tty->name, "cy_put_char"))
        return;
 
-    if (!tty || !info->xmit_buf)
+    if (!info->xmit_buf)
        return;
 
     local_irq_save(flags);
@@ -1216,7 +1176,7 @@ cy_flush_chars(struct tty_struct *tty)
     port is already active, there is no need to kick it.
  */
 static int
-cy_write(struct tty_struct * tty, int from_user,
+cy_write(struct tty_struct * tty,
            const unsigned char *buf, int count)
 {
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
@@ -1231,57 +1191,27 @@ cy_write(struct tty_struct * tty, int from_user,
        return 0;
     }
        
-    if (!tty || !info->xmit_buf || !tmp_buf){
+    if (!info->xmit_buf){
         return 0;
     }
 
-    if (from_user) {
-           down(&tmp_buf_sem);
-           while (1) {
-                   c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-                                      SERIAL_XMIT_SIZE - info->xmit_head));
-                   if (c <= 0)
-                           break;
-
-                   c -= copy_from_user(tmp_buf, buf, c);
-                   if (!c) {
-                           if (!total)
-                                   total = -EFAULT;
-                           break;
-                   }
-
-                   local_irq_save(flags);
-                   c = MIN(c, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-                                  SERIAL_XMIT_SIZE - info->xmit_head));
-                   memcpy(info->xmit_buf + info->xmit_head, tmp_buf, c);
-                   info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-                   info->xmit_cnt += c;
+    while (1) {
+           local_irq_save(flags);
+           c = min_t(int, count, min(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
+                                     SERIAL_XMIT_SIZE - info->xmit_head));
+           if (c <= 0) {
                    local_irq_restore(flags);
-
-                   buf += c;
-                   count -= c;
-                   total += c;
+                   break;
            }
-           up(&tmp_buf_sem);
-    } else {
-           while (1) {
-                   local_irq_save(flags);
-                   c = MIN(count, MIN(SERIAL_XMIT_SIZE - info->xmit_cnt - 1,
-                                      SERIAL_XMIT_SIZE - info->xmit_head));
-                   if (c <= 0) {
-                           local_irq_restore(flags);
-                           break;
-                   }
 
-                   memcpy(info->xmit_buf + info->xmit_head, buf, c);
-                   info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
-                   info->xmit_cnt += c;
-                   local_irq_restore(flags);
+           memcpy(info->xmit_buf + info->xmit_head, buf, c);
+           info->xmit_head = (info->xmit_head + c) & (SERIAL_XMIT_SIZE-1);
+           info->xmit_cnt += c;
+           local_irq_restore(flags);
 
-                   buf += c;
-                   count -= c;
-                   total += c;
-           }
+           buf += c;
+           count -= c;
+           total += c;
     }
 
     if (info->xmit_cnt
@@ -1343,10 +1273,7 @@ cy_flush_buffer(struct tty_struct *tty)
     local_irq_save(flags);
        info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
     local_irq_restore(flags);
-    wake_up_interruptible(&tty->write_wait);
-    if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP))
-    && tty->ldisc.write_wakeup)
-       (tty->ldisc.write_wakeup)(tty);
+    tty_wakeup(tty);
 } /* cy_flush_buffer */
 
 
@@ -1427,7 +1354,7 @@ cy_unthrottle(struct tty_struct * tty)
 
 static int
 get_serial_info(struct cyclades_port * info,
-                           struct serial_struct * retinfo)
+                           struct serial_struct __user * retinfo)
 {
   struct serial_struct tmp;
 
@@ -1449,7 +1376,7 @@ get_serial_info(struct cyclades_port * info,
 
 static int
 set_serial_info(struct cyclades_port * info,
-                           struct serial_struct * new_info)
+                           struct serial_struct __user * new_info)
 {
   struct serial_struct new_serial;
   struct cyclades_port old_info;
@@ -1499,7 +1426,6 @@ cy_tiocmget(struct tty_struct *tty, struct file *file)
   volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
   unsigned long flags;
   unsigned char status;
-  unsigned int result;
 
     channel = info->line;
 
@@ -1523,7 +1449,6 @@ cy_tiocmset(struct tty_struct *tty, struct file *file,
   int channel;
   volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
   unsigned long flags;
-  unsigned int arg;
          
     channel = info->line;
 
@@ -1578,7 +1503,7 @@ send_break( struct cyclades_port * info, int duration)
 } /* send_break */
 
 static int
-get_mon_info(struct cyclades_port * info, struct cyclades_monitor * mon)
+get_mon_info(struct cyclades_port * info, struct cyclades_monitor __user * mon)
 {
 
    if (copy_to_user(mon, &info->mon, sizeof(struct cyclades_monitor)))
@@ -1591,7 +1516,7 @@ get_mon_info(struct cyclades_port * info, struct cyclades_monitor * mon)
 }
 
 static int
-set_threshold(struct cyclades_port * info, unsigned long *arg)
+set_threshold(struct cyclades_port * info, unsigned long __user *arg)
 {
    volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
    unsigned long value;
@@ -1608,7 +1533,7 @@ set_threshold(struct cyclades_port * info, unsigned long *arg)
 }
 
 static int
-get_threshold(struct cyclades_port * info, unsigned long *value)
+get_threshold(struct cyclades_port * info, unsigned long __user *value)
 {
    volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
    int channel;
@@ -1621,7 +1546,7 @@ get_threshold(struct cyclades_port * info, unsigned long *value)
 }
 
 static int
-set_default_threshold(struct cyclades_port * info, unsigned long *arg)
+set_default_threshold(struct cyclades_port * info, unsigned long __user *arg)
 {
    unsigned long value;
 
@@ -1633,13 +1558,13 @@ set_default_threshold(struct cyclades_port * info, unsigned long *arg)
 }
 
 static int
-get_default_threshold(struct cyclades_port * info, unsigned long *value)
+get_default_threshold(struct cyclades_port * info, unsigned long __user *value)
 {
    return put_user(info->default_threshold,value);
 }
 
 static int
-set_timeout(struct cyclades_port * info, unsigned long *arg)
+set_timeout(struct cyclades_port * info, unsigned long __user *arg)
 {
    volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
    int channel;
@@ -1656,7 +1581,7 @@ set_timeout(struct cyclades_port * info, unsigned long *arg)
 }
 
 static int
-get_timeout(struct cyclades_port * info, unsigned long *value)
+get_timeout(struct cyclades_port * info, unsigned long __user *value)
 {
    volatile unsigned char *base_addr = (u_char *)BASE_ADDR;
    int channel;
@@ -1676,7 +1601,7 @@ set_default_timeout(struct cyclades_port * info, unsigned long value)
 }
 
 static int
-get_default_timeout(struct cyclades_port * info, unsigned long *value)
+get_default_timeout(struct cyclades_port * info, unsigned long __user *value)
 {
    return put_user(info->default_timeout,value);
 }
@@ -1688,6 +1613,7 @@ cy_ioctl(struct tty_struct *tty, struct file * file,
   unsigned long val;
   struct cyclades_port * info = (struct cyclades_port *)tty->driver_data;
   int ret_val = 0;
+  void __user *argp = (void __user *)arg;
 
 #ifdef SERIAL_DEBUG_OTHER
     printk("cy_ioctl %s, cmd = %x arg = %lx\n", tty->name, cmd, arg); /* */
@@ -1695,28 +1621,28 @@ cy_ioctl(struct tty_struct *tty, struct file * file,
 
     switch (cmd) {
         case CYGETMON:
-            ret_val = get_mon_info(info, (struct cyclades_monitor *)arg);
+            ret_val = get_mon_info(info, argp);
            break;
         case CYGETTHRESH:
-           ret_val = get_threshold(info, (unsigned long *)arg);
+           ret_val = get_threshold(info, argp);
            break;
         case CYSETTHRESH:
-            ret_val = set_threshold(info, (unsigned long *)arg);
+            ret_val = set_threshold(info, argp);
            break;
         case CYGETDEFTHRESH:
-           ret_val = get_default_threshold(info, (unsigned long *)arg);
+           ret_val = get_default_threshold(info, argp);
            break;
         case CYSETDEFTHRESH:
-            ret_val = set_default_threshold(info, (unsigned long *)arg);
+            ret_val = set_default_threshold(info, argp);
            break;
         case CYGETTIMEOUT:
-           ret_val = get_timeout(info, (unsigned long *)arg);
+           ret_val = get_timeout(info, argp);
            break;
         case CYSETTIMEOUT:
-            ret_val = set_timeout(info, (unsigned long *)arg);
+            ret_val = set_timeout(info, argp);
            break;
         case CYGETDEFTIMEOUT:
-           ret_val = get_default_timeout(info, (unsigned long *)arg);
+           ret_val = get_default_timeout(info, argp);
            break;
         case CYSETDEFTIMEOUT:
             ret_val = set_default_timeout(info, (unsigned long)arg);
@@ -1739,21 +1665,20 @@ cy_ioctl(struct tty_struct *tty, struct file * file,
 
 /* The following commands are incompletely implemented!!! */
         case TIOCGSOFTCAR:
-            ret_val = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long *) arg);
+            ret_val = put_user(C_CLOCAL(tty) ? 1 : 0, (unsigned long __user *) argp);
             break;
         case TIOCSSOFTCAR:
-            ret_val = get_user(val, (unsigned long *) arg);
+            ret_val = get_user(val, (unsigned long __user *) argp);
            if (ret_val)
                    break;
             tty->termios->c_cflag =
                     ((tty->termios->c_cflag & ~CLOCAL) | (val ? CLOCAL : 0));
             break;
         case TIOCGSERIAL:
-            ret_val = get_serial_info(info, (struct serial_struct *) arg);
+            ret_val = get_serial_info(info, argp);
             break;
         case TIOCSSERIAL:
-            ret_val = set_serial_info(info,
-                                   (struct serial_struct *) arg);
+            ret_val = set_serial_info(info, argp);
             break;
         default:
            ret_val = -ENOIOCTLCMD;
@@ -1770,7 +1695,7 @@ cy_ioctl(struct tty_struct *tty, struct file * file,
 
 
 static void
-cy_set_termios(struct tty_struct *tty, struct termios * old_termios)
+cy_set_termios(struct tty_struct *tty, struct ktermios * old_termios)
 {
   struct cyclades_port *info = (struct cyclades_port *)tty->driver_data;
 
@@ -1846,22 +1771,12 @@ cy_close(struct tty_struct * tty, struct file * filp)
     shutdown(info);
     if (tty->driver->flush_buffer)
        tty->driver->flush_buffer(tty);
-    if (tty->ldisc.flush_buffer)
-       tty->ldisc.flush_buffer(tty);
+    tty_ldisc_flush(tty);
     info->event = 0;
-    info->tty = 0;
-    if (tty->ldisc.num != ldiscs[N_TTY].num) {
-       if (tty->ldisc.close)
-           (tty->ldisc.close)(tty);
-       tty->ldisc = ldiscs[N_TTY];
-       tty->termios->c_line = N_TTY;
-       if (tty->ldisc.open)
-           (tty->ldisc.open)(tty);
-    }
+    info->tty = NULL;
     if (info->blocked_open) {
        if (info->close_delay) {
-           current->state = TASK_INTERRUPTIBLE;
-           schedule_timeout(info->close_delay);
+           msleep_interruptible(jiffies_to_msecs(info->close_delay));
        }
        wake_up_interruptible(&info->open_wait);
     }
@@ -2059,13 +1974,6 @@ cy_open(struct tty_struct *tty, struct file * filp)
     tty->driver_data = info;
     info->tty = tty;
 
-    if (!tmp_buf) {
-       tmp_buf = (unsigned char *) get_zeroed_page(GFP_KERNEL);
-       if (!tmp_buf){
-           return -ENOMEM;
-        }
-    }
-
     /*
      * Start up serial port
      */
@@ -2234,7 +2142,7 @@ mvme167_serial_console_setup(int cflag)
                                        rcor >> 5, rbpr);
 } /* serial_console_init */
 
-static struct tty_operations cy_ops = {
+static const struct tty_operations cy_ops = {
        .open = cy_open,
        .close = cy_close,
        .write = cy_write,
@@ -2310,7 +2218,6 @@ scrn[1] = '\0';
     /* Initialize the tty_driver structure */
     
     cy_serial_driver->owner = THIS_MODULE;
-    cy_serial_driver->devfs_name = "tts/";
     cy_serial_driver->name = "ttyS";
     cy_serial_driver->major = TTY_MAJOR;
     cy_serial_driver->minor_start = 64;
@@ -2329,8 +2236,6 @@ scrn[1] = '\0';
            return ret;
     }
 
-    init_bh(CYCLADES_BH, do_cyclades_bh);
-
     port_num = 0;
     info = cy_port;
     for (index = 0; index < 1; index++) {
@@ -2345,7 +2250,7 @@ scrn[1] = '\0';
                info->card = index;
                info->line = port_num;
                info->flags = STD_COM_FLAGS;
-               info->tty = 0;
+               info->tty = NULL;
                info->xmit_fifo_size = 12;
                info->cor1 = CyPARITY_NONE|Cy_8_BITS;
                info->cor2 = CyETC;
@@ -2368,8 +2273,7 @@ scrn[1] = '\0';
                info->blocked_open = 0;
                info->default_threshold = 0;
                info->default_timeout = 0;
-               info->tqueue.routine = do_softint;
-               info->tqueue.data = info;
+               INIT_WORK(&info->tqueue, do_softint);
                init_waitqueue_head(&info->open_wait);
                init_waitqueue_head(&info->close_wait);
                /* info->session */
@@ -2379,7 +2283,7 @@ scrn[1] = '\0';
                                        | CyPARITY| CyFRAME| CyOVERRUN;
                /* info->timeout */
 
-               printk("ttyS%1d ", info->line);
+               printk("ttyS%d ", info->line);
                port_num++;info++;
                if(!(port_num & 7)){
                    printk("\n               ");