patch-2.3.43 linux/drivers/net/slip.c
Next file: linux/drivers/net/slip.h
Previous file: linux/drivers/net/skeleton.c
Back to the patch index
Back to the overall index
- Lines: 463
- Date:
Wed Feb 9 20:08:09 2000
- Orig file:
v2.3.42/linux/drivers/net/slip.c
- Orig date:
Thu Nov 11 20:11:42 1999
diff -u --recursive --new-file v2.3.42/linux/drivers/net/slip.c linux/drivers/net/slip.c
@@ -169,9 +169,9 @@
if (slcomp == NULL)
goto err_exit;
#endif
- start_bh_atomic();
+ spin_lock_bh(&sl->lock);
if (sl->tty == NULL) {
- end_bh_atomic();
+ spin_unlock_bh(&sl->lock);
err = -ENODEV;
goto err_exit;
}
@@ -189,7 +189,7 @@
sl->xbits = 0;
#endif
#endif
- end_bh_atomic();
+ spin_unlock_bh(&sl->lock);
err = 0;
/* Cleanup */
@@ -268,7 +268,7 @@
goto done;
}
- start_bh_atomic();
+ spin_lock_bh(&sl->lock);
err = -ENODEV;
if (sl->tty == NULL)
@@ -304,7 +304,7 @@
err = 0;
done_on_bh:
- end_bh_atomic();
+ spin_unlock_bh(&sl->lock);
done:
if (xbuff)
@@ -323,9 +323,7 @@
static inline void
sl_lock(struct slip *sl)
{
- if (test_and_set_bit(0, (void *) &sl->dev->tbusy)) {
- printk("%s: trying to lock already locked device!\n", sl->dev->name);
- }
+ netif_stop_queue(sl->dev);
}
@@ -333,9 +331,7 @@
static inline void
sl_unlock(struct slip *sl)
{
- if (!test_and_clear_bit(0, (void *)&sl->dev->tbusy)) {
- printk("%s: trying to unlock already unlocked device!\n", sl->dev->name);
- }
+ netif_wake_queue(sl->dev);
}
/* Send one completely decapsulated IP datagram to the IP layer. */
@@ -453,7 +449,7 @@
struct slip *sl = (struct slip *) tty->disc_data;
/* First make sure we're connected. */
- if (!sl || sl->magic != SLIP_MAGIC || !sl->dev->start) {
+ if (!sl || sl->magic != SLIP_MAGIC || !test_bit(LINK_STATE_START, &sl->dev->state)) {
return;
}
if (sl->xleft <= 0) {
@@ -462,7 +458,6 @@
sl->tx_packets++;
tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
sl_unlock(sl);
- mark_bh(NET_BH);
return;
}
@@ -471,40 +466,25 @@
sl->xhead += actual;
}
-/* Encapsulate an IP datagram and kick it into a TTY queue. */
-static int
-sl_xmit(struct sk_buff *skb, struct net_device *dev)
+static void sl_tx_timeout(struct net_device *dev)
{
struct slip *sl = (struct slip*)(dev->priv);
- if (!dev->start) {
- printk("%s: xmit call when iface is down\n", dev->name);
- dev_kfree_skb(skb);
- return 0;
- }
- if (sl->tty == NULL) {
- dev_kfree_skb(skb);
- return 0;
- }
+ spin_lock(&sl->lock);
+
+ if (test_bit(LINK_STATE_XOFF, &dev->state)) {
+ struct slip *sl = (struct slip*)(dev->priv);
+
+ if (!test_bit(LINK_STATE_START, &dev->state))
+ goto out;
- /*
- * If we are busy already- too bad. We ought to be able
- * to queue things at this point, to allow for a little
- * frame buffer. Oh well...
- * -----------------------------------------------------
- * I hate queues in SLIP driver. May be it's efficient,
- * but for me latency is more important. ;)
- * So, no queues !
- * 14 Oct 1994 Dmitry Gorodchanin.
- */
- if (dev->tbusy) {
/* May be we must check transmitter timeout here ?
* 14 Oct 1994 Dmitry Gorodchanin.
*/
#ifdef SL_CHECK_TRANSMIT
if (jiffies - dev->trans_start < 20 * HZ) {
/* 20 sec timeout not reached */
- return 1;
+ goto out;
}
printk("%s: transmit timed out, %s?\n", dev->name,
(sl->tty->driver.chars_in_buffer(sl->tty) || sl->xleft) ?
@@ -512,19 +492,39 @@
sl->xleft = 0;
sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
sl_unlock(sl);
-#else
- return 1;
#endif
}
- /* We were not busy, so we are now... :-) */
- if (skb != NULL)
- {
- sl_lock(sl);
- sl->tx_bytes+=skb->len;
- sl_encaps(sl, skb->data, skb->len);
+out:
+ spin_unlock(&sl->lock);
+}
+
+
+/* Encapsulate an IP datagram and kick it into a TTY queue. */
+static int
+sl_xmit(struct sk_buff *skb, struct net_device *dev)
+{
+ struct slip *sl = (struct slip*)(dev->priv);
+
+ spin_lock(&sl->lock);
+ if (!test_bit(LINK_STATE_START, &dev->state)) {
+ spin_unlock(&sl->lock);
+ printk("%s: xmit call when iface is down\n", dev->name);
dev_kfree_skb(skb);
+ return 0;
}
+ if (sl->tty == NULL) {
+ spin_unlock(&sl->lock);
+ dev_kfree_skb(skb);
+ return 0;
+ }
+
+ sl_lock(sl);
+ sl->tx_bytes+=skb->len;
+ sl_encaps(sl, skb->data, skb->len);
+ spin_unlock(&sl->lock);
+
+ dev_kfree_skb(skb);
return 0;
}
@@ -540,16 +540,15 @@
{
struct slip *sl = (struct slip*)(dev->priv);
- start_bh_atomic();
+ spin_lock_bh(&sl->lock);
if (sl->tty) {
/* TTY discipline is running. */
sl->tty->flags &= ~(1 << TTY_DO_WRITE_WAKEUP);
}
- dev->tbusy = 1;
- dev->start = 0;
+ netif_stop_queue(dev);
sl->rcount = 0;
sl->xleft = 0;
- end_bh_atomic();
+ spin_unlock_bh(&sl->lock);
MOD_DEC_USE_COUNT;
return 0;
@@ -565,8 +564,7 @@
return -ENODEV;
sl->flags &= (1 << SLF_INUSE);
- dev->start = 1;
- dev->tbusy = 0;
+ netif_start_queue(dev);
MOD_INC_USE_COUNT;
return 0;
}
@@ -634,6 +632,10 @@
dev->mtu = sl->mtu;
dev->hard_start_xmit = sl_xmit;
+#ifdef SL_CHECK_TRANSMIT
+ dev->tx_timeout = sl_tx_timeout;
+ dev->watchdog_timeo = 20*HZ;
+#endif
dev->open = sl_open;
dev->stop = sl_close;
dev->get_stats = sl_get_stats;
@@ -676,7 +678,8 @@
{
struct slip *sl = (struct slip *) tty->disc_data;
- if (!sl || sl->magic != SLIP_MAGIC || !sl->dev->start)
+ if (!sl || sl->magic != SLIP_MAGIC ||
+ !test_bit(LINK_STATE_START, &sl->dev->state))
return;
/* Read the characters out of the buffer */
@@ -800,6 +803,7 @@
/* Initialize channel control data */
sl->magic = SLIP_MAGIC;
sl->dev = &slp->dev;
+ spin_lock_init(&sl->lock);
sl->mode = SL_MODE_DEFAULT;
sprintf(slp->if_name, "sl%d", i);
slp->dev.name = slp->if_name;
@@ -946,10 +950,8 @@
/* VSV = very important to remove timers */
#ifdef CONFIG_SLIP_SMART
- if (sl->keepalive)
- del_timer (&sl->keepalive_timer);
- if (sl->outfill)
- del_timer (&sl->outfill_timer);
+ del_timer_sync(&sl->keepalive_timer);
+ del_timer_sync(&sl->outfill_timer);
#endif
/* Count references from TTY module */
@@ -1182,20 +1184,18 @@
if (tmp > 255) /* max for unchar */
return -EINVAL;
- start_bh_atomic();
+ spin_lock_bh(&sl->lock);
if (!sl->tty) {
- end_bh_atomic();
+ spin_unlock_bh(&sl->lock);
return -ENODEV;
}
- if (sl->keepalive)
- (void)del_timer (&sl->keepalive_timer);
if ((sl->keepalive = (unchar) tmp) != 0) {
- sl->keepalive_timer.expires=jiffies+sl->keepalive*HZ;
- add_timer(&sl->keepalive_timer);
+ mod_timer(&sl->keepalive_timer, jiffies+sl->keepalive*HZ);
set_bit(SLF_KEEPTEST, &sl->flags);
- }
- end_bh_atomic();
-
+ } else {
+ del_timer (&sl->keepalive_timer);
+ }
+ spin_unlock_bh(&sl->lock);
return 0;
case SIOCGKEEPALIVE:
@@ -1208,19 +1208,18 @@
return -EFAULT;
if (tmp > 255) /* max for unchar */
return -EINVAL;
- start_bh_atomic();
+ spin_lock_bh(&sl->lock);
if (!sl->tty) {
- end_bh_atomic();
+ spin_unlock_bh(&sl->lock);
return -ENODEV;
}
- if (sl->outfill)
- (void)del_timer (&sl->outfill_timer);
if ((sl->outfill = (unchar) tmp) != 0){
- sl->outfill_timer.expires=jiffies+sl->outfill*HZ;
- add_timer(&sl->outfill_timer);
+ mod_timer(&sl->outfill_timer, jiffies+sl->outfill*HZ);
set_bit(SLF_OUTWAIT, &sl->flags);
+ } else {
+ del_timer (&sl->outfill_timer);
}
- end_bh_atomic();
+ spin_unlock_bh(&sl->lock);
return 0;
case SIOCGOUTFILL:
@@ -1253,10 +1252,10 @@
if (sl == NULL) /* Allocation failed ?? */
return -ENODEV;
- start_bh_atomic(); /* Hangup would kill us */
+ spin_lock_bh(&sl->lock);
if (!sl->tty) {
- end_bh_atomic();
+ spin_unlock_bh(&sl->lock);
return -ENODEV;
}
@@ -1265,14 +1264,15 @@
/* max for unchar */
if (((unsigned int)((unsigned long)rq->ifr_data)) > 255)
return -EINVAL;
- if (sl->keepalive)
- (void)del_timer (&sl->keepalive_timer);
sl->keepalive = (unchar) ((unsigned long)rq->ifr_data);
if (sl->keepalive != 0) {
sl->keepalive_timer.expires=jiffies+sl->keepalive*HZ;
- add_timer(&sl->keepalive_timer);
+ mod_timer(&sl->keepalive_timer, jiffies+sl->keepalive*HZ);
set_bit(SLF_KEEPTEST, &sl->flags);
- }
+ } else {
+ del_timer(&sl->keepalive_timer);
+ }
+ spin_unlock_bh(&sl->lock);
break;
case SIOCGKEEPALIVE:
@@ -1282,12 +1282,11 @@
case SIOCSOUTFILL:
if (((unsigned)((unsigned long)rq->ifr_data)) > 255) /* max for unchar */
return -EINVAL;
- if (sl->outfill)
- del_timer (&sl->outfill_timer);
if ((sl->outfill = (unchar)((unsigned long) rq->ifr_data)) != 0){
- sl->outfill_timer.expires=jiffies+sl->outfill*HZ;
- add_timer(&sl->outfill_timer);
+ mod_timer(&sl->outfill_timer, jiffies+sl->outfill*HZ);
set_bit(SLF_OUTWAIT, &sl->flags);
+ } else {
+ del_timer (&sl->outfill_timer);
}
break;
@@ -1300,7 +1299,7 @@
and opened by another process device.
*/
if (sl->tty != current->tty && sl->pid != current->pid) {
- end_bh_atomic();
+ spin_unlock_bh(&sl->lock);
return -EPERM;
}
sl->leased = 0;
@@ -1311,7 +1310,7 @@
case SIOCGLEASE:
rq->ifr_data=(caddr_t)((unsigned long)sl->leased);
};
- end_bh_atomic();
+ spin_unlock_bh(&sl->lock);
return 0;
}
#endif
@@ -1399,15 +1398,19 @@
}
busy = 0;
- start_bh_atomic();
+ local_bh_disable();
for (i = 0; i < slip_maxdev; i++) {
struct slip_ctrl *slc = slip_ctrls[i];
- if (slc && slc->ctrl.tty) {
+ if (!slc)
+ continue;
+ spin_lock(&slc->ctrl.lock);
+ if (slc->ctrl.tty) {
busy++;
tty_hangup(slc->ctrl.tty);
}
+ spin_unlock(&slc->ctrl.lock);
}
- end_bh_atomic();
+ local_bh_enable();
} while (busy && jiffies - start < 1*HZ);
busy = 0;
@@ -1449,8 +1452,10 @@
{
struct slip *sl=(struct slip *)sls;
- if (sl==NULL || sl->tty == NULL)
- return;
+ spin_lock(&sl->lock);
+
+ if (sl->tty == NULL)
+ goto out;
if(sl->outfill)
{
@@ -1463,7 +1468,7 @@
unsigned char s = END;
#endif
/* put END into tty queue. Is it right ??? */
- if (!test_bit(0, (void *) &sl->dev->tbusy))
+ if (!test_bit(LINK_STATE_XOFF, &sl->dev->state))
{
/* if device busy no outfill */
sl->tty->driver.write(sl->tty, 0, &s, 1);
@@ -1471,18 +1476,22 @@
}
else
set_bit(SLF_OUTWAIT, &sl->flags);
- (void)del_timer(&sl->outfill_timer);
- sl->outfill_timer.expires=jiffies+sl->outfill*HZ;
- add_timer(&sl->outfill_timer);
+
+ mod_timer(&sl->outfill_timer, jiffies+sl->outfill*HZ);
}
+out:
+ spin_unlock(&sl->lock);
+ timer_exit(&sl->outfill_timer);
}
static void sl_keepalive(unsigned long sls)
{
struct slip *sl=(struct slip *)sls;
- if (sl == NULL || sl->tty == NULL)
- return;
+ spin_lock(&sl->lock);
+
+ if (sl->tty == NULL)
+ goto out;
if( sl->keepalive)
{
@@ -1494,13 +1503,17 @@
printk("%s: no packets received during keepalive timeout, hangup.\n", sl->dev->name);
tty_hangup(sl->tty); /* this must hangup tty & close slip */
/* I think we need not something else */
- return;
+ goto out;
}
else
set_bit(SLF_KEEPTEST, &sl->flags);
- sl->keepalive_timer.expires=jiffies+sl->keepalive*HZ;
- add_timer(&sl->keepalive_timer);
+
+ mod_timer(&sl->keepalive_timer, jiffies+sl->keepalive*HZ);
}
+
+out:
+ spin_unlock(&sl->lock);
+ timer_exit(&sl->keepalive_timer);
}
#endif
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)