Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[safe/jmp/linux-2.6] / drivers / net / wan / x25_asy.c
index c48b1cc..80d5c58 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/module.h>
 
 #include <asm/system.h>
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 #include <linux/bitops.h>
 #include <linux/string.h>
 #include <linux/mm.h>
@@ -32,6 +32,9 @@
 #include <linux/x25.h>
 #include <linux/lapb.h>
 #include <linux/init.h>
+#include <linux/rtnetlink.h>
+#include <linux/compat.h>
+#include <linux/slab.h>
 #include "x25_asy.h"
 
 #include <net/x25device.h>
@@ -63,7 +66,7 @@ static struct x25_asy *x25_asy_alloc(void)
                if (dev == NULL)
                        break;
 
-               sl = dev->priv;
+               sl = netdev_priv(dev);
                /* Not in use ? */
                if (!test_and_set_bit(SLF_INUSE, &sl->flags))
                        return sl;
@@ -85,7 +88,7 @@ static struct x25_asy *x25_asy_alloc(void)
                        return NULL;
 
                /* Initialize channel control data */
-               sl = dev->priv;
+               sl = netdev_priv(dev);
                dev->base_addr    = i;
 
                /* register device so that it can be ifconfig'ed       */
@@ -95,7 +98,7 @@ static struct x25_asy *x25_asy_alloc(void)
                        x25_asy_devs[i] = dev;
                        return sl;
                } else {
-                       printk("x25_asy_alloc() - register_netdev() failure.\n");
+                       printk(KERN_WARNING "x25_asy_alloc() - register_netdev() failure.\n");
                        free_netdev(dev);
                }
        }
@@ -112,23 +115,22 @@ static void x25_asy_free(struct x25_asy *sl)
        kfree(sl->xbuff);
        sl->xbuff = NULL;
 
-       if (!test_and_clear_bit(SLF_INUSE, &sl->flags)) {
-               printk("%s: x25_asy_free for already free unit.\n", sl->dev->name);
-       }
+       if (!test_and_clear_bit(SLF_INUSE, &sl->flags))
+               printk(KERN_ERR "%s: x25_asy_free for already free unit.\n",
+                       sl->dev->name);
 }
 
 static int x25_asy_change_mtu(struct net_device *dev, int newmtu)
 {
-       struct x25_asy *sl = dev->priv;
+       struct x25_asy *sl = netdev_priv(dev);
        unsigned char *xbuff, *rbuff;
-       int len = 2* newmtu;
+       int len = 2 * newmtu;
 
        xbuff = kmalloc(len + 4, GFP_ATOMIC);
        rbuff = kmalloc(len + 4, GFP_ATOMIC);
 
-       if (xbuff == NULL || rbuff == NULL)  
-       {
-               printk("%s: unable to grow X.25 buffers, MTU change cancelled.\n",
+       if (xbuff == NULL || rbuff == NULL) {
+               printk(KERN_WARNING "%s: unable to grow X.25 buffers, MTU change cancelled.\n",
                       dev->name);
                kfree(xbuff);
                kfree(rbuff);
@@ -142,7 +144,7 @@ static int x25_asy_change_mtu(struct net_device *dev, int newmtu)
                        memcpy(sl->xbuff, sl->xhead, sl->xleft);
                } else  {
                        sl->xleft = 0;
-                       sl->stats.tx_dropped++;
+                       dev->stats.tx_dropped++;
                }
        }
        sl->xhead = sl->xbuff;
@@ -153,7 +155,7 @@ static int x25_asy_change_mtu(struct net_device *dev, int newmtu)
                        memcpy(sl->rbuff, rbuff, sl->rcount);
                } else  {
                        sl->rcount = 0;
-                       sl->stats.rx_over_errors++;
+                       dev->stats.rx_over_errors++;
                        set_bit(SLF_ERROR, &sl->flags);
                }
        }
@@ -188,33 +190,31 @@ static inline void x25_asy_unlock(struct x25_asy *sl)
 
 static void x25_asy_bump(struct x25_asy *sl)
 {
+       struct net_device *dev = sl->dev;
        struct sk_buff *skb;
        int count;
        int err;
 
        count = sl->rcount;
-       sl->stats.rx_bytes+=count;
-       
+       dev->stats.rx_bytes += count;
+
        skb = dev_alloc_skb(count+1);
-       if (skb == NULL)  
-       {
-               printk("%s: memory squeeze, dropping packet.\n", sl->dev->name);
-               sl->stats.rx_dropped++;
+       if (skb == NULL) {
+               printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n",
+                       sl->dev->name);
+               dev->stats.rx_dropped++;
                return;
        }
-       skb_push(skb,1);        /* LAPB internal control */
-       memcpy(skb_put(skb,count), sl->rbuff, count);
+       skb_push(skb, 1);       /* LAPB internal control */
+       memcpy(skb_put(skb, count), sl->rbuff, count);
        skb->protocol = x25_type_trans(skb, sl->dev);
-       if((err=lapb_data_received(skb->dev, skb))!=LAPB_OK)
-       {
+       err = lapb_data_received(skb->dev, skb);
+       if (err != LAPB_OK) {
                kfree_skb(skb);
-               printk(KERN_DEBUG "x25_asy: data received err - %d\n",err);
-       }
-       else
-       {
+               printk(KERN_DEBUG "x25_asy: data received err - %d\n", err);
+       } else {
                netif_rx(skb);
-               sl->dev->last_rx = jiffies;
-               sl->stats.rx_packets++;
+               dev->stats.rx_packets++;
        }
 }
 
@@ -224,11 +224,12 @@ static void x25_asy_encaps(struct x25_asy *sl, unsigned char *icp, int len)
        unsigned char *p;
        int actual, count, mtu = sl->dev->mtu;
 
-       if (len > mtu) 
-       {               /* Sigh, shouldn't occur BUT ... */
+       if (len > mtu) {
+               /* Sigh, shouldn't occur BUT ... */
                len = mtu;
-               printk ("%s: truncating oversized transmit packet!\n", sl->dev->name);
-               sl->stats.tx_dropped++;
+               printk(KERN_DEBUG "%s: truncating oversized transmit packet!\n",
+                                       sl->dev->name);
+               sl->dev->stats.tx_dropped++;
                x25_asy_unlock(sl);
                return;
        }
@@ -244,8 +245,8 @@ static void x25_asy_encaps(struct x25_asy *sl, unsigned char *icp, int len)
         * if we did not request it before write operation.
         *       14 Oct 1994  Dmitry Gorodchanin.
         */
-       sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
-       actual = sl->tty->driver->write(sl->tty, sl->xbuff, count);
+       set_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
+       actual = sl->tty->ops->write(sl->tty, sl->xbuff, count);
        sl->xleft = count - actual;
        sl->xhead = sl->xbuff + actual;
        /* VSV */
@@ -259,30 +260,29 @@ static void x25_asy_encaps(struct x25_asy *sl, unsigned char *icp, int len)
 static void x25_asy_write_wakeup(struct tty_struct *tty)
 {
        int actual;
-       struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
+       struct x25_asy *sl = tty->disc_data;
 
        /* First make sure we're connected. */
        if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev))
                return;
 
-       if (sl->xleft <= 0)  
-       {
+       if (sl->xleft <= 0) {
                /* Now serial buffer is almost free & we can start
                 * transmission of another packet */
-               sl->stats.tx_packets++;
-               tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+               sl->dev->stats.tx_packets++;
+               clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
                x25_asy_unlock(sl);
                return;
        }
 
-       actual = tty->driver->write(tty, sl->xhead, sl->xleft);
+       actual = tty->ops->write(tty, sl->xhead, sl->xleft);
        sl->xleft -= actual;
        sl->xhead += actual;
 }
 
 static void x25_asy_timeout(struct net_device *dev)
 {
-       struct x25_asy *sl = (struct x25_asy*)(dev->priv);
+       struct x25_asy *sl = netdev_priv(dev);
 
        spin_lock(&sl->lock);
        if (netif_queue_stopped(dev)) {
@@ -290,10 +290,10 @@ static void x25_asy_timeout(struct net_device *dev)
                 *      14 Oct 1994 Dmitry Gorodchanin.
                 */
                printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,
-                      (sl->tty->driver->chars_in_buffer(sl->tty) || sl->xleft) ?
+                      (tty_chars_in_buffer(sl->tty) || sl->xleft) ?
                       "bad line quality" : "driver error");
                sl->xleft = 0;
-               sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+               clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
                x25_asy_unlock(sl);
        }
        spin_unlock(&sl->lock);
@@ -301,33 +301,37 @@ static void x25_asy_timeout(struct net_device *dev)
 
 /* Encapsulate an IP datagram and kick it into a TTY queue. */
 
-static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
+static netdev_tx_t x25_asy_xmit(struct sk_buff *skb,
+                                     struct net_device *dev)
 {
-       struct x25_asy *sl = (struct x25_asy*)(dev->priv);
+       struct x25_asy *sl = netdev_priv(dev);
        int err;
 
        if (!netif_running(sl->dev)) {
-               printk("%s: xmit call when iface is down\n", dev->name);
+               printk(KERN_ERR "%s: xmit call when iface is down\n",
+                       dev->name);
                kfree_skb(skb);
-               return 0;
+               return NETDEV_TX_OK;
        }
-       
-       switch(skb->data[0])
-       {
-               case 0x00:break;
-               case 0x01: /* Connection request .. do nothing */
-                       if((err=lapb_connect_request(dev))!=LAPB_OK)
-                               printk(KERN_ERR "x25_asy: lapb_connect_request error - %d\n", err);
-                       kfree_skb(skb);
-                       return 0;
-               case 0x02: /* Disconnect request .. do nothing - hang up ?? */
-                       if((err=lapb_disconnect_request(dev))!=LAPB_OK)
-                               printk(KERN_ERR "x25_asy: lapb_disconnect_request error - %d\n", err);
-               default:
-                       kfree_skb(skb);
-                       return  0;
+
+       switch (skb->data[0]) {
+       case 0x00:
+               break;
+       case 0x01: /* Connection request .. do nothing */
+               err = lapb_connect_request(dev);
+               if (err != LAPB_OK)
+                       printk(KERN_ERR "x25_asy: lapb_connect_request error - %d\n", err);
+               kfree_skb(skb);
+               return NETDEV_TX_OK;
+       case 0x02: /* Disconnect request .. do nothing - hang up ?? */
+               err = lapb_disconnect_request(dev);
+               if (err != LAPB_OK)
+                       printk(KERN_ERR "x25_asy: lapb_disconnect_request error - %d\n", err);
+       default:
+               kfree_skb(skb);
+               return NETDEV_TX_OK;
        }
-       skb_pull(skb,1);        /* Remove control byte */
+       skb_pull(skb, 1);       /* Remove control byte */
        /*
         * If we are busy already- too bad.  We ought to be able
         * to queue things at this point, to allow for a little
@@ -338,14 +342,14 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
         * So, no queues !
         *        14 Oct 1994  Dmitry Gorodchanin.
         */
-       
-       if((err=lapb_data_request(dev,skb))!=LAPB_OK)
-       {
-               printk(KERN_ERR "lapbeth: lapb_data_request error - %d\n", err);
+
+       err = lapb_data_request(dev, skb);
+       if (err != LAPB_OK) {
+               printk(KERN_ERR "x25_asy: lapb_data_request error - %d\n", err);
                kfree_skb(skb);
-               return 0;
+               return NETDEV_TX_OK;
        }
-       return 0;
+       return NETDEV_TX_OK;
 }
 
 
@@ -357,10 +361,9 @@ static int x25_asy_xmit(struct sk_buff *skb, struct net_device *dev)
  *     Called when I frame data arrives. We did the work above - throw it
  *     at the net layer.
  */
-  
+
 static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb)
 {
-       skb->dev->last_rx = jiffies;
        return netif_rx(skb);
 }
 
@@ -369,24 +372,22 @@ static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb)
  *     busy cases too well. Its tricky to see how to do this nicely -
  *     perhaps lapb should allow us to bounce this ?
  */
+
 static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb)
 {
-       struct x25_asy *sl=dev->priv;
-       
+       struct x25_asy *sl = netdev_priv(dev);
+
        spin_lock(&sl->lock);
-       if (netif_queue_stopped(sl->dev) || sl->tty == NULL)
-       {
+       if (netif_queue_stopped(sl->dev) || sl->tty == NULL) {
                spin_unlock(&sl->lock);
                printk(KERN_ERR "x25_asy: tbusy drop\n");
                kfree_skb(skb);
                return;
        }
        /* We were not busy, so we are now... :-) */
-       if (skb != NULL) 
-       {
+       if (skb != NULL) {
                x25_asy_lock(sl);
-               sl->stats.tx_bytes+=skb->len;
+               dev->stats.tx_bytes += skb->len;
                x25_asy_encaps(sl, skb->data, skb->len);
                dev_kfree_skb(skb);
        }
@@ -396,15 +397,16 @@ static void x25_asy_data_transmit(struct net_device *dev, struct sk_buff *skb)
 /*
  *     LAPB connection establish/down information.
  */
+
 static void x25_asy_connected(struct net_device *dev, int reason)
 {
-       struct x25_asy *sl = dev->priv;
+       struct x25_asy *sl = netdev_priv(dev);
        struct sk_buff *skb;
        unsigned char *ptr;
 
-       if ((skb = dev_alloc_skb(1)) == NULL) {
-               printk(KERN_ERR "lapbeth: out of memory\n");
+       skb = dev_alloc_skb(1);
+       if (skb == NULL) {
+               printk(KERN_ERR "x25_asy: out of memory\n");
                return;
        }
 
@@ -413,16 +415,16 @@ static void x25_asy_connected(struct net_device *dev, int reason)
 
        skb->protocol = x25_type_trans(skb, sl->dev);
        netif_rx(skb);
-       sl->dev->last_rx = jiffies;
 }
 
 static void x25_asy_disconnected(struct net_device *dev, int reason)
 {
-       struct x25_asy *sl = dev->priv;
+       struct x25_asy *sl = netdev_priv(dev);
        struct sk_buff *skb;
        unsigned char *ptr;
 
-       if ((skb = dev_alloc_skb(1)) == NULL) {
+       skb = dev_alloc_skb(1);
+       if (skb == NULL) {
                printk(KERN_ERR "x25_asy: out of memory\n");
                return;
        }
@@ -432,7 +434,6 @@ static void x25_asy_disconnected(struct net_device *dev, int reason)
 
        skb->protocol = x25_type_trans(skb, sl->dev);
        netif_rx(skb);
-       sl->dev->last_rx = jiffies;
 }
 
 static struct lapb_register_struct x25_asy_callbacks = {
@@ -449,7 +450,7 @@ static struct lapb_register_struct x25_asy_callbacks = {
 /* Open the low-level part of the X.25 channel. Easy! */
 static int x25_asy_open(struct net_device *dev)
 {
-       struct x25_asy *sl = (struct x25_asy*)(dev->priv);
+       struct x25_asy *sl = netdev_priv(dev);
        unsigned long len;
        int err;
 
@@ -466,13 +467,11 @@ static int x25_asy_open(struct net_device *dev)
        len = dev->mtu * 2;
 
        sl->rbuff = kmalloc(len + 4, GFP_KERNEL);
-       if (sl->rbuff == NULL)   {
+       if (sl->rbuff == NULL)
                goto norbuff;
-       }
        sl->xbuff = kmalloc(len + 4, GFP_KERNEL);
-       if (sl->xbuff == NULL)   {
+       if (sl->xbuff == NULL)
                goto noxbuff;
-       }
 
        sl->buffsize = len;
        sl->rcount   = 0;
@@ -480,11 +479,12 @@ static int x25_asy_open(struct net_device *dev)
        sl->flags   &= (1 << SLF_INUSE);      /* Clear ESCAPE & ERROR flags */
 
        netif_start_queue(dev);
-                       
+
        /*
         *      Now attach LAPB
         */
-       if((err=lapb_register(dev, &x25_asy_callbacks))==LAPB_OK)
+       err = lapb_register(dev, &x25_asy_callbacks);
+       if (err == LAPB_OK)
                return 0;
 
        /* Cleanup */
@@ -499,18 +499,20 @@ norbuff:
 /* Close the low-level part of the X.25 channel. Easy! */
 static int x25_asy_close(struct net_device *dev)
 {
-       struct x25_asy *sl = (struct x25_asy*)(dev->priv);
+       struct x25_asy *sl = netdev_priv(dev);
        int err;
 
        spin_lock(&sl->lock);
-       if (sl->tty) 
-               sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
+       if (sl->tty)
+               clear_bit(TTY_DO_WRITE_WAKEUP, &sl->tty->flags);
 
        netif_stop_queue(dev);
        sl->rcount = 0;
        sl->xleft  = 0;
-       if((err=lapb_unregister(dev))!=LAPB_OK)
-               printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",err);
+       err = lapb_unregister(dev);
+       if (err != LAPB_OK)
+               printk(KERN_ERR "x25_asy_close: lapb_unregister error -%d\n",
+                       err);
        spin_unlock(&sl->lock);
        return 0;
 }
@@ -521,10 +523,11 @@ static int x25_asy_close(struct net_device *dev)
  * a block of X.25 data has been received, which can now be decapsulated
  * and sent on to some IP layer for further processing.
  */
-static void x25_asy_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
+
+static void x25_asy_receive_buf(struct tty_struct *tty,
+                               const unsigned char *cp, char *fp, int count)
 {
-       struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
+       struct x25_asy *sl = tty->disc_data;
 
        if (!sl || sl->magic != X25_ASY_MAGIC || !netif_running(sl->dev))
                return;
@@ -533,9 +536,8 @@ static void x25_asy_receive_buf(struct tty_struct *tty, const unsigned char *cp,
        /* Read the characters out of the buffer */
        while (count--) {
                if (fp && *fp++) {
-                       if (!test_and_set_bit(SLF_ERROR, &sl->flags))  {
-                               sl->stats.rx_errors++;
-                       }
+                       if (!test_and_set_bit(SLF_ERROR, &sl->flags))
+                               sl->dev->stats.rx_errors++;
                        cp++;
                        continue;
                }
@@ -553,36 +555,34 @@ static void x25_asy_receive_buf(struct tty_struct *tty, const unsigned char *cp,
 
 static int x25_asy_open_tty(struct tty_struct *tty)
 {
-       struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
+       struct x25_asy *sl = tty->disc_data;
        int err;
 
+       if (tty->ops->write == NULL)
+               return -EOPNOTSUPP;
+
        /* First make sure we're not already connected. */
-       if (sl && sl->magic == X25_ASY_MAGIC) {
+       if (sl && sl->magic == X25_ASY_MAGIC)
                return -EEXIST;
-       }
 
        /* OK.  Find a free X.25 channel to use. */
-       if ((sl = x25_asy_alloc()) == NULL) {
+       sl = x25_asy_alloc();
+       if (sl == NULL)
                return -ENFILE;
-       }
 
        sl->tty = tty;
        tty->disc_data = sl;
        tty->receive_room = 65536;
-       if (tty->driver->flush_buffer)  {
-               tty->driver->flush_buffer(tty);
-       }
-       if (tty->ldisc.flush_buffer)  {
-               tty->ldisc.flush_buffer(tty);
-       }
+       tty_driver_flush_buffer(tty);
+       tty_ldisc_flush(tty);
 
        /* Restore default settings */
        sl->dev->type = ARPHRD_X25;
-       
+
        /* Perform the low-level X.25 async init */
-       if ((err = x25_asy_open(sl->dev)))
+       err = x25_asy_open(sl->dev);
+       if (err)
                return err;
-
        /* Done.  We have linked the TTY line to a channel. */
        return sl->dev->base_addr;
 }
@@ -596,36 +596,27 @@ static int x25_asy_open_tty(struct tty_struct *tty)
  */
 static void x25_asy_close_tty(struct tty_struct *tty)
 {
-       struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
+       struct x25_asy *sl = tty->disc_data;
 
        /* First make sure we're connected. */
        if (!sl || sl->magic != X25_ASY_MAGIC)
                return;
 
+       rtnl_lock();
        if (sl->dev->flags & IFF_UP)
-       {
-               (void) dev_close(sl->dev);
-       }
+               dev_close(sl->dev);
+       rtnl_unlock();
 
        tty->disc_data = NULL;
        sl->tty = NULL;
        x25_asy_free(sl);
 }
 
-
-static struct net_device_stats *x25_asy_get_stats(struct net_device *dev)
-{
-       struct x25_asy *sl = (struct x25_asy*)(dev->priv);
-
-       return &sl->stats;
-}
-
-
  /************************************************************************
   *                    STANDARD X.25 ENCAPSULATION                      *
   ************************************************************************/
 
-int x25_asy_esc(unsigned char *s, unsigned char *d, int len)
+static int x25_asy_esc(unsigned char *s, unsigned char *d, int len)
 {
        unsigned char *ptr = d;
        unsigned char c;
@@ -643,21 +634,19 @@ int x25_asy_esc(unsigned char *s, unsigned char *d, int len)
         * character sequence, according to the X.25 protocol.
         */
 
-       while (len-- > 0) 
-       {
-               switch(c = *s++) 
-               {
-                       case X25_END:
-                               *ptr++ = X25_ESC;
-                               *ptr++ = X25_ESCAPE(X25_END);
-                               break;
-                       case X25_ESC:
-                               *ptr++ = X25_ESC;
-                               *ptr++ = X25_ESCAPE(X25_ESC);
-                               break;
-                        default:
-                               *ptr++ = c;
-                               break;
+       while (len-- > 0) {
+               switch (c = *s++) {
+               case X25_END:
+                       *ptr++ = X25_ESC;
+                       *ptr++ = X25_ESCAPE(X25_END);
+                       break;
+               case X25_ESC:
+                       *ptr++ = X25_ESC;
+                       *ptr++ = X25_ESCAPE(X25_ESC);
+                       break;
+               default:
+                       *ptr++ = c;
+                       break;
                }
        }
        *ptr++ = X25_END;
@@ -667,35 +656,29 @@ int x25_asy_esc(unsigned char *s, unsigned char *d, int len)
 static void x25_asy_unesc(struct x25_asy *sl, unsigned char s)
 {
 
-       switch(s) 
-       {
-               case X25_END:
-                       if (!test_and_clear_bit(SLF_ERROR, &sl->flags) && (sl->rcount > 2))  
-                       {
-                               x25_asy_bump(sl);
-                       }
-                       clear_bit(SLF_ESCAPE, &sl->flags);
-                       sl->rcount = 0;
-                       return;
-
-               case X25_ESC:
-                       set_bit(SLF_ESCAPE, &sl->flags);
-                       return;
-                       
-               case X25_ESCAPE(X25_ESC):
-               case X25_ESCAPE(X25_END):
-                       if (test_and_clear_bit(SLF_ESCAPE, &sl->flags))
-                               s = X25_UNESCAPE(s);
-                       break;
-       }
-       if (!test_bit(SLF_ERROR, &sl->flags))  
-       {
-               if (sl->rcount < sl->buffsize)  
-               {
+       switch (s) {
+       case X25_END:
+               if (!test_and_clear_bit(SLF_ERROR, &sl->flags) &&
+                   sl->rcount > 2)
+                       x25_asy_bump(sl);
+               clear_bit(SLF_ESCAPE, &sl->flags);
+               sl->rcount = 0;
+               return;
+       case X25_ESC:
+               set_bit(SLF_ESCAPE, &sl->flags);
+               return;
+       case X25_ESCAPE(X25_ESC):
+       case X25_ESCAPE(X25_END):
+               if (test_and_clear_bit(SLF_ESCAPE, &sl->flags))
+                       s = X25_UNESCAPE(s);
+               break;
+       }
+       if (!test_bit(SLF_ERROR, &sl->flags)) {
+               if (sl->rcount < sl->buffsize) {
                        sl->rbuff[sl->rcount++] = s;
                        return;
                }
-               sl->stats.rx_over_errors++;
+               sl->dev->stats.rx_over_errors++;
                set_bit(SLF_ERROR, &sl->flags);
        }
 }
@@ -705,13 +688,13 @@ static void x25_asy_unesc(struct x25_asy *sl, unsigned char s)
 static int x25_asy_ioctl(struct tty_struct *tty, struct file *file,
                         unsigned int cmd,  unsigned long arg)
 {
-       struct x25_asy *sl = (struct x25_asy *) tty->disc_data;
+       struct x25_asy *sl = tty->disc_data;
 
        /* First make sure we're connected. */
        if (!sl || sl->magic != X25_ASY_MAGIC)
                return -EINVAL;
 
-       switch(cmd) {
+       switch (cmd) {
        case SIOCGIFNAME:
                if (copy_to_user((void __user *)arg, sl->dev->name,
                                        strlen(sl->dev->name) + 1))
@@ -719,27 +702,46 @@ static int x25_asy_ioctl(struct tty_struct *tty, struct file *file,
                return 0;
        case SIOCSIFHWADDR:
                return -EINVAL;
-       /* Allow stty to read, but not set, the serial port */
-       case TCGETS:
-       case TCGETA:
-               return n_tty_ioctl(tty, file, cmd, arg);
        default:
-               return -ENOIOCTLCMD;
+               return tty_mode_ioctl(tty, file, cmd, arg);
        }
 }
 
+#ifdef CONFIG_COMPAT
+static long x25_asy_compat_ioctl(struct tty_struct *tty, struct file *file,
+                        unsigned int cmd,  unsigned long arg)
+{
+       switch (cmd) {
+       case SIOCGIFNAME:
+       case SIOCSIFHWADDR:
+               return x25_asy_ioctl(tty, file, cmd,
+                                    (unsigned long)compat_ptr(arg));
+       }
+
+       return -ENOIOCTLCMD;
+}
+#endif
+
 static int x25_asy_open_dev(struct net_device *dev)
 {
-       struct x25_asy *sl = (struct x25_asy*)(dev->priv);
-       if(sl->tty==NULL)
+       struct x25_asy *sl = netdev_priv(dev);
+       if (sl->tty == NULL)
                return -ENODEV;
        return 0;
 }
 
+static const struct net_device_ops x25_asy_netdev_ops = {
+       .ndo_open       = x25_asy_open_dev,
+       .ndo_stop       = x25_asy_close,
+       .ndo_start_xmit = x25_asy_xmit,
+       .ndo_tx_timeout = x25_asy_timeout,
+       .ndo_change_mtu = x25_asy_change_mtu,
+};
+
 /* Initialise the X.25 driver.  Called by the device init code */
 static void x25_asy_setup(struct net_device *dev)
 {
-       struct x25_asy *sl = dev->priv;
+       struct x25_asy *sl = netdev_priv(dev);
 
        sl->magic  = X25_ASY_MAGIC;
        sl->dev    = dev;
@@ -747,17 +749,12 @@ static void x25_asy_setup(struct net_device *dev)
        set_bit(SLF_INUSE, &sl->flags);
 
        /*
-        *      Finish setting up the DEVICE info. 
+        *      Finish setting up the DEVICE info.
         */
-        
+
        dev->mtu                = SL_MTU;
-       dev->hard_start_xmit    = x25_asy_xmit;
-       dev->tx_timeout         = x25_asy_timeout;
+       dev->netdev_ops         = &x25_asy_netdev_ops;
        dev->watchdog_timeo     = HZ*20;
-       dev->open               = x25_asy_open_dev;
-       dev->stop               = x25_asy_close;
-       dev->get_stats          = x25_asy_get_stats;
-       dev->change_mtu         = x25_asy_change_mtu;
        dev->hard_header_len    = 0;
        dev->addr_len           = 0;
        dev->type               = ARPHRD_X25;
@@ -767,13 +764,16 @@ static void x25_asy_setup(struct net_device *dev)
        dev->flags              = IFF_NOARP;
 }
 
-static struct tty_ldisc x25_ldisc = {
+static struct tty_ldisc_ops x25_ldisc = {
        .owner          = THIS_MODULE,
        .magic          = TTY_LDISC_MAGIC,
        .name           = "X.25",
        .open           = x25_asy_open_tty,
        .close          = x25_asy_close_tty,
        .ioctl          = x25_asy_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl   = x25_asy_compat_ioctl,
+#endif
        .receive_buf    = x25_asy_receive_buf,
        .write_wakeup   = x25_asy_write_wakeup,
 };
@@ -784,9 +784,10 @@ static int __init init_x25_asy(void)
                x25_asy_maxdev = 4; /* Sanity */
 
        printk(KERN_INFO "X.25 async: version 0.00 ALPHA "
-                       "(dynamic channels, max=%d).\n", x25_asy_maxdev );
+                       "(dynamic channels, max=%d).\n", x25_asy_maxdev);
 
-       x25_asy_devs = kcalloc(x25_asy_maxdev, sizeof(struct net_device*), GFP_KERNEL);
+       x25_asy_devs = kcalloc(x25_asy_maxdev, sizeof(struct net_device *),
+                               GFP_KERNEL);
        if (!x25_asy_devs) {
                printk(KERN_WARNING "X25 async: Can't allocate x25_asy_ctrls[] "
                                "array! Uaargh! (-> No X.25 available)\n");
@@ -805,10 +806,10 @@ static void __exit exit_x25_asy(void)
        for (i = 0; i < x25_asy_maxdev; i++) {
                dev = x25_asy_devs[i];
                if (dev) {
-                       struct x25_asy *sl = dev->priv;
+                       struct x25_asy *sl = netdev_priv(dev);
 
                        spin_lock_bh(&sl->lock);
-                       if (sl->tty) 
+                       if (sl->tty)
                                tty_hangup(sl->tty);
 
                        spin_unlock_bh(&sl->lock);