#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>
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);
* 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
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;
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)) {
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) {
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;
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;
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
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.
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);
}
* 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)
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)
if (dev == NULL)
break;
- sl = dev->priv;
+ sl = netdev_priv(dev);
if (sl->leased) {
if (sl->line != line)
continue;
i = sel;
dev = slip_devs[i];
if (score > 1) {
- sl = dev->priv;
+ sl = netdev_priv(dev);
sl->flags &= (1 << SLF_INUSE);
return sl;
}
return NULL;
if (dev) {
- sl = dev->priv;
+ sl = netdev_priv(dev);
if (test_bit(SLF_INUSE, &sl->flags)) {
unregister_netdevice(dev);
dev = NULL;
dev->base_addr = i;
}
- sl = dev->priv;
+ sl = netdev_priv(dev);
/* Initialize channel control data */
sl->magic = SLIP_MAGIC;
* 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;
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)
}
/*
+
+ 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!
/*
* 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)
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;
{
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) {
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)) {
#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;
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;
return 0;
case SIOCGOUTFILL:
- if (put_user(sl->outfill, (int *)arg))
+ if (put_user(sl->outfill, p))
return -EFAULT;
return 0;
/* VSV changes end */
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;
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);
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 {
break;
case SIOCGOUTFILL:
- rq->ifr_data=(caddr_t)((unsigned long)sl->outfill);
+ *p = sl->outfill;
break;
case SIOCSLEASE:
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;
dev = slip_devs[i];
if (!dev)
continue;
- sl = dev->priv;
+ sl = netdev_priv(dev);
spin_lock_bh(&sl->lock);
if (sl->tty) {
busy++;
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);
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