VServer 1.9.2 (patch-2.6.8.1-vs1.9.2.diff)
[linux-2.6.git] / drivers / s390 / net / ctctty.c
index 3755f99..6290b5c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $Id: ctctty.c,v 1.17 2004/03/31 17:06:34 ptiedem Exp $
+ * $Id: ctctty.c,v 1.26 2004/08/04 11:06:55 mschwide Exp $
  *
  * CTC / ESCON network driver, tty interface.
  *
 #include <linux/tty.h>
 #include <linux/serial_reg.h>
 #include <linux/interrupt.h>
+#include <linux/delay.h>
 #include <asm/uaccess.h>
 #include <linux/devfs_fs_kernel.h>
 #include "ctctty.h"
+#include "ctcdbug.h"
 
 #define CTC_TTY_MAJOR       43
 #define CTC_TTY_MAX_DEVICES 64
@@ -103,6 +105,7 @@ ctc_tty_try_read(ctc_tty_info * info, struct sk_buff *skb)
        int len;
        struct tty_struct *tty;
 
+       DBF_TEXT(trace, 5, __FUNCTION__);
        if ((tty = info->tty)) {
                if (info->mcr & UART_MCR_RTS) {
                        c = TTY_FLIPBUF_SIZE - tty->flip.count;
@@ -132,6 +135,7 @@ ctc_tty_readmodem(ctc_tty_info *info)
        int ret = 1;
        struct tty_struct *tty;
 
+       DBF_TEXT(trace, 5, __FUNCTION__);
        if ((tty = info->tty)) {
                if (info->mcr & UART_MCR_RTS) {
                        int c = TTY_FLIPBUF_SIZE - tty->flip.count;
@@ -165,6 +169,7 @@ ctc_tty_setcarrier(struct net_device *netdev, int on)
 {
        int i;
 
+       DBF_TEXT(trace, 4, __FUNCTION__);
        if ((!driver) || ctc_tty_shuttingdown)
                return;
        for (i = 0; i < CTC_TTY_MAX_DEVICES; i++)
@@ -185,6 +190,7 @@ ctc_tty_netif_rx(struct sk_buff *skb)
        int i;
        ctc_tty_info *info = NULL;
 
+       DBF_TEXT(trace, 5, __FUNCTION__);
        if (!skb)
                return;
        if ((!skb->dev) || (!driver) || ctc_tty_shuttingdown) {
@@ -249,6 +255,7 @@ ctc_tty_tint(ctc_tty_info * info)
        int wake = 1;
        int rc;
 
+       DBF_TEXT(trace, 4, __FUNCTION__);
        if (!info->netdev) {
                if (skb)
                        kfree_skb(skb);
@@ -341,6 +348,7 @@ ctc_tty_inject(ctc_tty_info *info, char c)
        int skb_res;
        struct sk_buff *skb;
        
+       DBF_TEXT(trace, 4, __FUNCTION__);
        if (ctc_tty_shuttingdown)
                return;
        skb_res = info->netdev->hard_header_len + sizeof(info->mcr) +
@@ -361,6 +369,7 @@ ctc_tty_inject(ctc_tty_info *info, char c)
 static void
 ctc_tty_transmit_status(ctc_tty_info *info)
 {
+       DBF_TEXT(trace, 5, __FUNCTION__);
        if (ctc_tty_shuttingdown)
                return;
        info->flags |= CTC_ASYNC_TX_LINESTAT;
@@ -374,6 +383,7 @@ ctc_tty_change_speed(ctc_tty_info * info)
        unsigned int quot;
        int i;
 
+       DBF_TEXT(trace, 3, __FUNCTION__);
        if (!info->tty || !info->tty->termios)
                return;
        cflag = info->tty->termios->c_cflag;
@@ -412,6 +422,7 @@ ctc_tty_change_speed(ctc_tty_info * info)
 static int
 ctc_tty_startup(ctc_tty_info * info)
 {
+       DBF_TEXT(trace, 3, __FUNCTION__);
        if (info->flags & CTC_ASYNC_INITIALIZED)
                return 0;
 #ifdef CTC_DEBUG_MODEM_OPEN
@@ -454,6 +465,7 @@ ctc_tty_stopdev(unsigned long data)
 static void
 ctc_tty_shutdown(ctc_tty_info * info)
 {
+       DBF_TEXT(trace, 3, __FUNCTION__);
        if (!(info->flags & CTC_ASYNC_INITIALIZED))
                return;
 #ifdef CTC_DEBUG_MODEM_OPEN
@@ -486,14 +498,17 @@ ctc_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int cou
        int total = 0;
        ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
 
+       DBF_TEXT(trace, 5, __FUNCTION__);
        if (ctc_tty_shuttingdown)
-               return 0;
+               goto ex;
        if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_write"))
-               return 0;
+               goto ex;
        if (!tty)
-               return 0;
-       if (!info->netdev)
-               return -ENODEV;
+               goto ex;
+       if (!info->netdev) {
+               total = -ENODEV;
+               goto ex;
+       }
        if (from_user)
                down(&info->write_sem);
        while (1) {
@@ -530,6 +545,8 @@ ctc_tty_write(struct tty_struct *tty, int from_user, const u_char * buf, int cou
        }
        if (from_user)
                up(&info->write_sem);
+ex:
+       DBF_TEXT(trace, 6, __FUNCTION__);
        return total;
 }
 
@@ -559,13 +576,14 @@ ctc_tty_flush_buffer(struct tty_struct *tty)
        ctc_tty_info *info;
        unsigned long flags;
 
+       DBF_TEXT(trace, 4, __FUNCTION__);
        if (!tty)
-               return;
+               goto ex;
        spin_lock_irqsave(&ctc_tty_lock, flags);
        info = (ctc_tty_info *) tty->driver_data;
        if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_flush_buffer")) {
                spin_unlock_irqrestore(&ctc_tty_lock, flags);
-               return;
+               goto ex;
        }
        skb_queue_purge(&info->tx_queue);
        info->lsr |= UART_LSR_TEMT;
@@ -574,6 +592,9 @@ ctc_tty_flush_buffer(struct tty_struct *tty)
        if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
            tty->ldisc.write_wakeup)
                (tty->ldisc.write_wakeup) (tty);
+ex:
+       DBF_TEXT_(trace, 2, "ex: %s ", __FUNCTION__);
+       return;
 }
 
 static void
@@ -581,6 +602,7 @@ ctc_tty_flush_chars(struct tty_struct *tty)
 {
        ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
 
+       DBF_TEXT(trace, 4, __FUNCTION__);
        if (ctc_tty_shuttingdown)
                return;
        if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_flush_chars"))
@@ -603,6 +625,7 @@ ctc_tty_throttle(struct tty_struct *tty)
 {
        ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
 
+       DBF_TEXT(trace, 4, __FUNCTION__);
        if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_throttle"))
                return;
        info->mcr &= ~UART_MCR_RTS;
@@ -616,6 +639,7 @@ ctc_tty_unthrottle(struct tty_struct *tty)
 {
        ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
 
+       DBF_TEXT(trace, 4, __FUNCTION__);
        if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_unthrottle"))
                return;
        info->mcr |= UART_MCR_RTS;
@@ -647,6 +671,7 @@ ctc_tty_get_lsr_info(ctc_tty_info * info, uint __user *value)
        uint result;
        ulong flags;
 
+       DBF_TEXT(trace, 4, __FUNCTION__);
        spin_lock_irqsave(&ctc_tty_lock, flags);
        status = info->lsr;
        spin_unlock_irqrestore(&ctc_tty_lock, flags);
@@ -664,6 +689,7 @@ static int ctc_tty_tiocmget(struct tty_struct *tty, struct file *file)
        uint result;
        ulong flags;
 
+       DBF_TEXT(trace, 4, __FUNCTION__);
        if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
                return -ENODEV;
        if (tty->flags & (1 << TTY_IO_ERROR))
@@ -688,6 +714,7 @@ ctc_tty_tiocmset(struct tty_struct *tty, struct file *file,
 {
        ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
 
+       DBF_TEXT(trace, 4, __FUNCTION__);
        if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
                return -ENODEV;
        if (tty->flags & (1 << TTY_IO_ERROR))
@@ -716,6 +743,7 @@ ctc_tty_ioctl(struct tty_struct *tty, struct file *file,
        int error;
        int retval;
 
+       DBF_TEXT(trace, 4, __FUNCTION__);
        if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_ioctl"))
                return -ENODEV;
        if (tty->flags & (1 << TTY_IO_ERROR))
@@ -784,6 +812,7 @@ ctc_tty_set_termios(struct tty_struct *tty, struct termios *old_termios)
        ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
        unsigned int cflag = tty->termios->c_cflag;
 
+       DBF_TEXT(trace, 4, __FUNCTION__);
        ctc_tty_change_speed(info);
 
        /* Handle transition to B0 */
@@ -821,6 +850,7 @@ ctc_tty_block_til_ready(struct tty_struct *tty, struct file *filp, ctc_tty_info
        unsigned long flags;
        int retval;
 
+       DBF_TEXT(trace, 4, __FUNCTION__);
        /*
         * If the device is in the middle of being closed, then block
         * until it's done, and then try again.
@@ -925,6 +955,7 @@ ctc_tty_open(struct tty_struct *tty, struct file *filp)
        int retval,
         line;
 
+       DBF_TEXT(trace, 3, __FUNCTION__);
        line = tty->index;
        if (line < 0 || line > CTC_TTY_MAX_DEVICES)
                return -ENODEV;
@@ -971,7 +1002,7 @@ ctc_tty_close(struct tty_struct *tty, struct file *filp)
        ctc_tty_info *info = (ctc_tty_info *) tty->driver_data;
        ulong flags;
        ulong timeout;
-
+       DBF_TEXT(trace, 3, __FUNCTION__);
        if (!info || ctc_tty_paranoia_check(info, tty->name, "ctc_tty_close"))
                return;
        spin_lock_irqsave(&ctc_tty_lock, flags);
@@ -1023,17 +1054,18 @@ ctc_tty_close(struct tty_struct *tty, struct file *filp)
                 */
                timeout = jiffies + HZ;
                while (!(info->lsr & UART_LSR_TEMT)) {
-                       set_current_state(TASK_INTERRUPTIBLE);
                        spin_unlock_irqrestore(&ctc_tty_lock, flags);
-                       schedule_timeout(HZ/2);
+                       msleep(500);
                        spin_lock_irqsave(&ctc_tty_lock, flags);
                        if (time_after(jiffies,timeout))
                                break;
                }
        }
        ctc_tty_shutdown(info);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       if (tty->driver->flush_buffer) {
+               skb_queue_purge(&info->tx_queue);
+               info->lsr |= UART_LSR_TEMT;
+       }
        if (tty->ldisc.flush_buffer)
                tty->ldisc.flush_buffer(tty);
        info->tty = 0;
@@ -1059,7 +1091,7 @@ ctc_tty_hangup(struct tty_struct *tty)
 {
        ctc_tty_info *info = (ctc_tty_info *)tty->driver_data;
        unsigned long saveflags;
-
+       DBF_TEXT(trace, 3, __FUNCTION__);
        if (ctc_tty_paranoia_check(info, tty->name, "ctc_tty_hangup"))
                return;
        ctc_tty_shutdown(info);
@@ -1083,6 +1115,7 @@ ctc_tty_task(unsigned long arg)
        unsigned long saveflags;
        int again;
 
+       DBF_TEXT(trace, 3, __FUNCTION__);
        spin_lock_irqsave(&ctc_tty_lock, saveflags);
        if ((!ctc_tty_shuttingdown) && info) {
                again = ctc_tty_tint(info);
@@ -1120,6 +1153,7 @@ ctc_tty_init(void)
        ctc_tty_info *info;
        struct tty_driver *device;
 
+       DBF_TEXT(trace, 2, __FUNCTION__);
        driver = kmalloc(sizeof(ctc_tty_driver), GFP_KERNEL);
        if (driver == NULL) {
                printk(KERN_WARNING "Out of memory in ctc_tty_modem_init\n");
@@ -1179,12 +1213,28 @@ ctc_tty_register_netdev(struct net_device *dev) {
        char *err;
        char *p;
 
+       DBF_TEXT(trace, 2, __FUNCTION__);
        if ((!dev) || (!dev->name)) {
                printk(KERN_WARNING
                       "ctc_tty_register_netdev called "
                       "with NULL dev or NULL dev-name\n");
                return -1;
        }
+
+       /*
+        *      If the name is a format string the caller wants us to
+        *      do a name allocation : format string must end with %d
+        */
+       if (strchr(dev->name, '%'))
+       {
+               int err = dev_alloc_name(dev, dev->name);       // dev->name is changed by this
+               if (err < 0) {
+                       printk(KERN_DEBUG "dev_alloc returned error %d\n", err);
+                       return err;
+               }
+
+       }
+
        for (p = dev->name; p && ((*p < '0') || (*p > '9')); p++);
        ttynum = simple_strtoul(p, &err, 0);
        if ((ttynum < 0) || (ttynum >= CTC_TTY_MAX_DEVICES) ||
@@ -1211,6 +1261,7 @@ ctc_tty_unregister_netdev(struct net_device *dev) {
        unsigned long saveflags;
        ctc_tty_info *info = NULL;
 
+       DBF_TEXT(trace, 2, __FUNCTION__);
        spin_lock_irqsave(&ctc_tty_lock, saveflags);
        for (i = 0; i < CTC_TTY_MAX_DEVICES; i++)
                if (driver->info[i].netdev == dev) {
@@ -1229,6 +1280,7 @@ void
 ctc_tty_cleanup(void) {
        unsigned long saveflags;
        
+       DBF_TEXT(trace, 2, __FUNCTION__);
        spin_lock_irqsave(&ctc_tty_lock, saveflags);
        ctc_tty_shuttingdown = 1;
        spin_unlock_irqrestore(&ctc_tty_lock, saveflags);