X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fnet%2Fslip.c;h=a0806d262fc6530c1e72c2c75b14a999cc74e529;hb=refs%2Fheads%2Fvserver;hp=6209a35aaf835cec715bc06f3b0b0730108a9f22;hpb=9bf4aaab3e101692164d49b7ca357651eb691cb6;p=linux-2.6.git diff --git a/drivers/net/slip.c b/drivers/net/slip.c index 6209a35aa..a0806d262 100644 --- a/drivers/net/slip.c +++ b/drivers/net/slip.c @@ -55,12 +55,12 @@ */ #define SL_CHECK_TRANSMIT -#include #include +#include #include #include -#include +#include #include #include #include @@ -73,6 +73,7 @@ #include #include #include +#include #include #include "slip.h" #ifdef CONFIG_INET @@ -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); @@ -112,7 +113,7 @@ static int sl_ioctl(struct net_device *dev,struct ifreq *rq,int cmd); * on actively running device. *********************************/ -/* +/* Allocate channel buffers. */ @@ -184,15 +185,12 @@ sl_alloc_bufs(struct slip *sl, int mtu) /* Cleanup */ err_exit: #ifdef SL_INCLUDE_CSLIP - if (cbuff) - kfree(cbuff); + kfree(cbuff); if (slcomp) slhc_free(slcomp); #endif - if (xbuff) - kfree(xbuff); - if (rbuff) - kfree(rbuff); + kfree(xbuff); + kfree(rbuff); return err; } @@ -200,22 +198,16 @@ err_exit: static void sl_free_bufs(struct slip *sl) { - void * tmp; - /* Free all SLIP frame buffers. */ - if ((tmp = xchg(&sl->rbuff, NULL)) != NULL) - kfree(tmp); - if ((tmp = xchg(&sl->xbuff, NULL)) != NULL) - kfree(tmp); + kfree(xchg(&sl->rbuff, NULL)); + kfree(xchg(&sl->xbuff, NULL)); #ifdef SL_INCLUDE_CSLIP - if ((tmp = xchg(&sl->cbuff, NULL)) != NULL) - kfree(tmp); - if ((tmp = xchg(&sl->slcomp, NULL)) != NULL) - slhc_free(tmp); + kfree(xchg(&sl->cbuff, NULL)); + slhc_free(xchg(&sl->slcomp, NULL)); #endif } -/* +/* Reallocate slip channel buffers. */ @@ -237,10 +229,10 @@ static int sl_realloc_bufs(struct slip *sl, int mtu) if (len < 576 * 2) len = 576 * 2; - xbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC); - rbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC); + xbuff = kmalloc(len + 4, GFP_ATOMIC); + rbuff = kmalloc(len + 4, GFP_ATOMIC); #ifdef SL_INCLUDE_CSLIP - cbuff = (unsigned char *) kmalloc (len + 4, GFP_ATOMIC); + cbuff = kmalloc(len + 4, GFP_ATOMIC); #endif @@ -296,13 +288,10 @@ done_on_bh: spin_unlock_bh(&sl->lock); done: - if (xbuff) - kfree(xbuff); - if (rbuff) - kfree(rbuff); + kfree(xbuff); + kfree(rbuff); #ifdef SL_INCLUDE_CSLIP - if (cbuff) - kfree(cbuff); + kfree(cbuff); #endif return err; } @@ -365,7 +354,7 @@ sl_bump(struct slip *sl) #endif /* SL_INCLUDE_CSLIP */ sl->rx_bytes+=count; - + skb = dev_alloc_skb(count); if (skb == NULL) { printk(KERN_WARNING "%s: memory squeeze, dropping packet.\n", sl->dev->name); @@ -417,7 +406,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 +440,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 +481,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 +515,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 +534,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 +548,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 +564,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,10 +599,10 @@ 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. + * Finish setting up the DEVICE info. */ dev->mtu = sl->mtu; @@ -630,7 +617,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); } @@ -663,18 +650,15 @@ static void sl_setup(struct net_device *dev) ******************************************/ -static int slip_receive_room(struct tty_struct *tty) -{ - return 65536; /* We can handle an infinite amount of data. :-) */ -} - /* * 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) { struct slip *sl = (struct slip *) tty->disc_data; @@ -717,7 +701,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) @@ -736,7 +720,7 @@ sl_alloc(dev_t line) struct net_device *dev = NULL; struct slip *sl; - if (slip_devs == NULL) + if (slip_devs == NULL) return NULL; /* Master array missing ! */ for (i = 0; i < slip_maxdev; i++) { @@ -744,7 +728,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 +770,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,14 +781,14 @@ 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; slip_devs[i] = NULL; } } - + if (!dev) { char name[IFNAMSIZ]; sprintf(name, "sl%d", i); @@ -815,7 +799,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; @@ -831,7 +815,7 @@ sl_alloc(dev_t line) sl->outfill_timer.function=sl_outfill; #endif slip_devs[i] = dev; - + return sl; } @@ -841,16 +825,18 @@ 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; if(!capable(CAP_NET_ADMIN)) return -EPERM; - + /* RTnetlink lock is misused here to serialize concurrent opens of slip channels. There are better ways, but it is the simplest one. @@ -876,10 +862,6 @@ slip_open(struct tty_struct *tty) tty->disc_data = sl; sl->line = tty_devnum(tty); sl->pid = current->pid; - 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. */ @@ -905,6 +887,7 @@ slip_open(struct tty_struct *tty) /* Done. We have linked the TTY line to a channel. */ rtnl_unlock(); + tty->receive_room = 65536; /* We don't flow control */ return sl->dev->base_addr; err_free_bufs: @@ -923,6 +906,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! @@ -934,16 +920,15 @@ err_exit: By-product (not desired): sl? does not feel hangups and remains open. It is supposed, that user level program (dip, diald, slattach...) - will catch SIGHUP and make the rest of work. + will catch SIGHUP and make the rest of work. I see no way to make more with current tty code. --ANK */ /* * 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) @@ -1254,7 +1239,7 @@ 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 ?? */ @@ -1306,7 +1291,7 @@ static int sl_ioctl(struct net_device *dev,struct ifreq *rq,int cmd) break; case SIOCSLEASE: - /* Resolve race condition, when ioctl'ing hanged up + /* Resolve race condition, when ioctl'ing hanged up and opened by another process device. */ if (sl->tty != current->signal->tty && sl->pid != current->pid) { @@ -1335,7 +1320,6 @@ static struct tty_ldisc sl_ldisc = { .close = slip_close, .ioctl = slip_ioctl, .receive_buf = slip_receive_buf, - .receive_room = slip_receive_room, .write_wakeup = slip_write_wakeup, }; @@ -1366,7 +1350,7 @@ static int __init slip_init(void) } /* Clear the pointer array, we allocate devices when we need them */ - memset(slip_devs, 0, sizeof(struct net_device *)*slip_maxdev); + memset(slip_devs, 0, sizeof(struct net_device *)*slip_maxdev); /* Fill in our line protocol discipline, and register it */ if ((status = tty_register_ldisc(N_SLIP, &sl_ldisc)) != 0) { @@ -1384,23 +1368,21 @@ static void __exit slip_exit(void) unsigned long timeout = jiffies + HZ; int busy = 0; - if (slip_devs == NULL) + if (slip_devs == NULL) return; /* First of all: check for active disciplines and hangup them. */ do { - if (busy) { - set_current_state(TASK_INTERRUPTIBLE); - schedule_timeout(HZ / 10); - } + if (busy) + msleep_interruptible(100); busy = 0; for (i = 0; i < slip_maxdev; i++) { dev = slip_devs[i]; if (!dev) continue; - sl = dev->priv; + sl = netdev_priv(dev); spin_lock_bh(&sl->lock); if (sl->tty) { busy++; @@ -1417,13 +1399,13 @@ 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); /* Intentionally leak the control block. */ dev->destructor = NULL; - } + } unregister_netdev(dev); } @@ -1431,7 +1413,7 @@ static void __exit slip_exit(void) kfree(slip_devs); slip_devs = NULL; - if ((i = tty_register_ldisc(N_SLIP, NULL))) + if ((i = tty_unregister_ldisc(N_SLIP))) { printk(KERN_ERR "SLIP: can't unregister line discipline (err = %d)\n", i); } @@ -1469,7 +1451,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