vserver 1.9.5.x5
[linux-2.6.git] / drivers / net / slip.c
index e783ac0..4ce52f5 100644 (file)
 #define SL_CHECK_TRANSMIT
 #include <linux/config.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 
 #include <asm/system.h>
 #include <asm/uaccess.h>
-#include <asm/bitops.h>
+#include <linux/bitops.h>
 #include <linux/string.h>
 #include <linux/mm.h>
 #include <linux/interrupt.h>
@@ -85,8 +86,8 @@
 
 static struct net_device **slip_devs;
 
-int slip_maxdev = SL_NRUNIT;           /* Can be overridden with insmod! */
-MODULE_PARM(slip_maxdev, "i");
+static int slip_maxdev = SL_NRUNIT;
+module_param(slip_maxdev, int, 0);
 MODULE_PARM_DESC(slip_maxdev, "Maximum number of slip devices");
 
 static int slip_esc(unsigned char *p, unsigned char *d, int len);
@@ -417,7 +418,7 @@ sl_encaps(struct slip *sl, unsigned char *icp, int len)
         *       14 Oct 1994  Dmitry Gorodchanin.
         */
        sl->tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
-       actual = sl->tty->driver->write(sl->tty, 0, sl->xbuff, count);
+       actual = sl->tty->driver->write(sl->tty, sl->xbuff, count);
 #ifdef SL_CHECK_TRANSMIT
        sl->dev->trans_start = jiffies;
 #endif
@@ -451,20 +452,18 @@ static void slip_write_wakeup(struct tty_struct *tty)
                return;
        }
 
-       actual = tty->driver->write(tty, 0, sl->xhead, sl->xleft);
+       actual = tty->driver->write(tty, sl->xhead, sl->xleft);
        sl->xleft -= actual;
        sl->xhead += actual;
 }
 
 static void sl_tx_timeout(struct net_device *dev)
 {
-       struct slip *sl = (struct slip*)(dev->priv);
+       struct slip *sl = netdev_priv(dev);
 
        spin_lock(&sl->lock);
 
        if (netif_queue_stopped(dev)) {
-               struct slip *sl = (struct slip*)(dev->priv);
-
                if (!netif_running(dev))
                        goto out;
 
@@ -494,7 +493,7 @@ out:
 static int
 sl_xmit(struct sk_buff *skb, struct net_device *dev)
 {
-       struct slip *sl = (struct slip*)(dev->priv);
+       struct slip *sl = netdev_priv(dev);
 
        spin_lock(&sl->lock);
        if (!netif_running(dev))  {
@@ -528,7 +527,7 @@ sl_xmit(struct sk_buff *skb, struct net_device *dev)
 static int
 sl_close(struct net_device *dev)
 {
-       struct slip *sl = (struct slip*)(dev->priv);
+       struct slip *sl = netdev_priv(dev);
 
        spin_lock_bh(&sl->lock);
        if (sl->tty) {
@@ -547,7 +546,7 @@ sl_close(struct net_device *dev)
 
 static int sl_open(struct net_device *dev)
 {
-       struct slip *sl = (struct slip*)(dev->priv);
+       struct slip *sl = netdev_priv(dev);
 
        if (sl->tty==NULL)
                return -ENODEV;
@@ -561,7 +560,7 @@ static int sl_open(struct net_device *dev)
 
 static int sl_change_mtu(struct net_device *dev, int new_mtu)
 {
-       struct slip *sl = (struct slip*)(dev->priv);
+       struct slip *sl = netdev_priv(dev);
 
        if (new_mtu < 68 || new_mtu > 65534)
                return -EINVAL;
@@ -577,7 +576,7 @@ static struct net_device_stats *
 sl_get_stats(struct net_device *dev)
 {
        static struct net_device_stats stats;
-       struct slip *sl = (struct slip*)(dev->priv);
+       struct slip *sl = netdev_priv(dev);
 #ifdef SL_INCLUDE_CSLIP
        struct slcompress *comp;
 #endif
@@ -612,7 +611,7 @@ sl_get_stats(struct net_device *dev)
 
 static int sl_init(struct net_device *dev)
 {
-       struct slip *sl = (struct slip*)(dev->priv);
+       struct slip *sl = netdev_priv(dev);
 
        /*
         *      Finish setting up the DEVICE info. 
@@ -630,7 +629,7 @@ static int sl_init(struct net_device *dev)
 
 static void sl_uninit(struct net_device *dev)
 {
-       struct slip *sl = (struct slip*)(dev->priv);
+       struct slip *sl = netdev_priv(dev);
 
        sl_free_bufs(sl);
 }
@@ -672,7 +671,9 @@ static int slip_receive_room(struct tty_struct *tty)
  * Handle the 'receiver data ready' interrupt.
  * This function is called by the 'tty_io' module in the kernel when
  * a block of SLIP data has been received, which can now be decapsulated
- * and sent on to some IP layer for further processing.
+ * and sent on to some IP layer for further processing. This will not
+ * be re-entered while running but other ldisc functions may be called
+ * in parallel
  */
  
 static void slip_receive_buf(struct tty_struct *tty, const unsigned char *cp, char *fp, int count)
@@ -717,7 +718,7 @@ static void sl_sync(void)
                if ((dev = slip_devs[i]) == NULL)
                        break;
 
-               sl = dev->priv;
+               sl = netdev_priv(dev);
                if (sl->tty || sl->leased)
                        continue;
                if (dev->flags&IFF_UP)
@@ -744,7 +745,7 @@ sl_alloc(dev_t line)
                if (dev == NULL)
                        break;
 
-               sl = dev->priv;
+               sl = netdev_priv(dev);
                if (sl->leased) {
                        if (sl->line != line)
                                continue;
@@ -786,7 +787,7 @@ sl_alloc(dev_t line)
                i = sel;
                dev = slip_devs[i];
                if (score > 1) {
-                       sl = dev->priv;
+                       sl = netdev_priv(dev);
                        sl->flags &= (1 << SLF_INUSE);
                        return sl;
                }
@@ -797,7 +798,7 @@ sl_alloc(dev_t line)
                return NULL;
 
        if (dev) {
-               sl = dev->priv;
+               sl = netdev_priv(dev);
                if (test_bit(SLF_INUSE, &sl->flags)) {
                        unregister_netdevice(dev);
                        dev = NULL;
@@ -815,7 +816,7 @@ sl_alloc(dev_t line)
                dev->base_addr  = i;
        }
 
-       sl = dev->priv;
+       sl = netdev_priv(dev);
 
        /* Initialize channel control data */
        sl->magic       = SLIP_MAGIC;
@@ -841,9 +842,11 @@ sl_alloc(dev_t line)
  * SLIP line discipline is called for.  Because we are
  * sure the tty line exists, we only have to link it to
  * a free SLIP channel...
+ *
+ * Called in process context serialized from other ldisc calls.
  */
-static int
-slip_open(struct tty_struct *tty)
+
+static int slip_open(struct tty_struct *tty)
 {
        struct slip *sl;
        int err;
@@ -876,11 +879,11 @@ slip_open(struct tty_struct *tty)
        tty->disc_data = sl;
        sl->line = tty_devnum(tty);
        sl->pid = current->pid;
+       
+       /* FIXME: already done before we were called - seems this can go */
        if (tty->driver->flush_buffer)
                tty->driver->flush_buffer(tty);
-       if (tty->ldisc.flush_buffer)
-               tty->ldisc.flush_buffer(tty);
-
+               
        if (!test_bit(SLF_INUSE, &sl->flags)) {
                /* Perform the low-level SLIP initialization. */
                if ((err = sl_alloc_bufs(sl, SL_MTU)) != 0)
@@ -923,6 +926,9 @@ err_exit:
 }
 
 /*
+
+  FIXME: 1,2 are fixed 3 was never true anyway.
+  
    Let me to blame a bit.
    1. TTY module calls this funstion on soft interrupt.
    2. TTY module calls this function WITH MASKED INTERRUPTS!
@@ -941,9 +947,8 @@ err_exit:
 
 /*
  * Close down a SLIP channel.
- * This means flushing out any pending queues, and then restoring the
- * TTY line discipline to what it was before it got hooked to SLIP
- * (which usually is TTY again).
+ * This means flushing out any pending queues, and then returning. This
+ * call is serialized against other ldisc functions.
  */
 static void
 slip_close(struct tty_struct *tty)
@@ -954,7 +959,7 @@ slip_close(struct tty_struct *tty)
        if (!sl || sl->magic != SLIP_MAGIC || sl->tty != tty)
                return;
 
-       tty->disc_data = 0;
+       tty->disc_data = NULL;
        sl->tty = NULL;
        if (!sl->leased)
                sl->line = 0;
@@ -1138,6 +1143,7 @@ static int slip_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm
 {
        struct slip *sl = (struct slip *) tty->disc_data;
        unsigned int tmp;
+       int __user *p = (int __user *)arg;
 
        /* First make sure we're connected. */
        if (!sl || sl->magic != SLIP_MAGIC) {
@@ -1147,17 +1153,17 @@ static int slip_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm
        switch(cmd) {
         case SIOCGIFNAME:
                tmp = strlen(sl->dev->name) + 1;
-               if (copy_to_user((void *)arg, sl->dev->name, tmp))
+               if (copy_to_user((void __user *)arg, sl->dev->name, tmp))
                        return -EFAULT;
                return 0;
 
        case SIOCGIFENCAP:
-               if (put_user(sl->mode, (int *)arg))
+               if (put_user(sl->mode, p))
                        return -EFAULT;
                return 0;
 
        case SIOCSIFENCAP:
-               if (get_user(tmp,(int *)arg))
+               if (get_user(tmp, p))
                        return -EFAULT;
 #ifndef SL_INCLUDE_CSLIP
                if (tmp & (SL_MODE_CSLIP|SL_MODE_ADAPTIVE))  {
@@ -1185,7 +1191,7 @@ static int slip_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm
 #ifdef CONFIG_SLIP_SMART
        /* VSV changes start here */
         case SIOCSKEEPALIVE:
-               if (get_user(tmp,(int *)arg))
+               if (get_user(tmp, p))
                        return -EFAULT;
                 if (tmp > 255) /* max for unchar */
                        return -EINVAL;
@@ -1205,12 +1211,12 @@ static int slip_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm
                return 0;
 
         case SIOCGKEEPALIVE:
-               if (put_user(sl->keepalive, (int *)arg))
+               if (put_user(sl->keepalive, p))
                        return -EFAULT;
                return 0;
 
         case SIOCSOUTFILL:
-               if (get_user(tmp,(int *)arg))
+               if (get_user(tmp, p))
                        return -EFAULT;
                 if (tmp > 255) /* max for unchar */
                        return -EINVAL;
@@ -1229,7 +1235,7 @@ static int slip_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm
                 return 0;
 
         case SIOCGOUTFILL:
-               if (put_user(sl->outfill, (int *)arg))
+               if (put_user(sl->outfill, p))
                        return -EFAULT;
                return 0;
        /* VSV changes end */
@@ -1253,7 +1259,8 @@ static int slip_ioctl(struct tty_struct *tty, struct file *file, unsigned int cm
 
 static int sl_ioctl(struct net_device *dev,struct ifreq *rq,int cmd)
 {
-       struct slip *sl = (struct slip*)(dev->priv);
+       struct slip *sl = netdev_priv(dev);
+       unsigned long *p = (unsigned long *)&rq->ifr_ifru;
 
        if (sl == NULL)         /* Allocation failed ?? */
                return -ENODEV;
@@ -1268,11 +1275,11 @@ static int sl_ioctl(struct net_device *dev,struct ifreq *rq,int cmd)
        switch(cmd){
         case SIOCSKEEPALIVE:
                /* max for unchar */
-                if (((unsigned int)((unsigned long)rq->ifr_data)) > 255) {
+                if ((unsigned)*p > 255) {
                        spin_unlock_bh(&sl->lock);
                        return -EINVAL;
                }
-               sl->keepalive = (unchar) ((unsigned long)rq->ifr_data);
+               sl->keepalive = (unchar) *p;
                if (sl->keepalive != 0) {
                        sl->keepalive_timer.expires=jiffies+sl->keepalive*HZ;
                        mod_timer(&sl->keepalive_timer, jiffies+sl->keepalive*HZ);
@@ -1283,15 +1290,15 @@ static int sl_ioctl(struct net_device *dev,struct ifreq *rq,int cmd)
                break;
 
         case SIOCGKEEPALIVE:
-               rq->ifr_data=(caddr_t)((unsigned long)sl->keepalive);
+               *p = sl->keepalive;
                break;
 
         case SIOCSOUTFILL:
-                if (((unsigned)((unsigned long)rq->ifr_data)) > 255) { /* max for unchar */
+                if ((unsigned)*p > 255) { /* max for unchar */
                        spin_unlock_bh(&sl->lock);
                        return -EINVAL;
                }
-                if ((sl->outfill = (unchar)((unsigned long) rq->ifr_data)) != 0){
+                if ((sl->outfill = (unchar)*p) != 0){
                        mod_timer(&sl->outfill_timer, jiffies+sl->outfill*HZ);
                        set_bit(SLF_OUTWAIT, &sl->flags);
                } else {
@@ -1300,7 +1307,7 @@ static int sl_ioctl(struct net_device *dev,struct ifreq *rq,int cmd)
                 break;
 
         case SIOCGOUTFILL:
-               rq->ifr_data=(caddr_t)((unsigned long)sl->outfill);
+               *p = sl->outfill;
                break;
 
         case SIOCSLEASE:
@@ -1312,12 +1319,12 @@ static int sl_ioctl(struct net_device *dev,struct ifreq *rq,int cmd)
                        return -EPERM;
                }
                sl->leased = 0;
-                if ((unsigned long)rq->ifr_data)
+                if (*p)
                        sl->leased = 1;
                 break;
 
         case SIOCGLEASE:
-               rq->ifr_data=(caddr_t)((unsigned long)sl->leased);
+               *p = sl->leased;
        };
        spin_unlock_bh(&sl->lock);
        return 0;
@@ -1398,7 +1405,7 @@ static void __exit slip_exit(void)
                        dev = slip_devs[i];
                        if (!dev)
                                continue;
-                       sl = dev->priv;
+                       sl = netdev_priv(dev);
                        spin_lock_bh(&sl->lock);
                        if (sl->tty) {
                                busy++;
@@ -1415,7 +1422,7 @@ static void __exit slip_exit(void)
                        continue;
                slip_devs[i] = NULL;
 
-               sl = dev->priv;
+               sl = netdev_priv(dev);
                if (sl->tty) {
                        printk(KERN_ERR "%s: tty discipline still running\n",
                               dev->name);
@@ -1467,7 +1474,7 @@ static void sl_outfill(unsigned long sls)
                        if (!netif_queue_stopped(sl->dev))
                        {
                                /* if device busy no outfill */
-                               sl->tty->driver->write(sl->tty, 0, &s, 1);
+                               sl->tty->driver->write(sl->tty, &s, 1);
                        }
                }
                else