patch-2.1.89 linux/drivers/net/ppp.c

Next file: linux/drivers/net/shaper.c
Previous file: linux/drivers/net/ethertap.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.88/linux/drivers/net/ppp.c linux/drivers/net/ppp.c
@@ -684,13 +684,6 @@
 	if (tty != NULL && tty->disc_data == ppp)
 		tty->disc_data = NULL;	/* Break the tty->ppp link */
 
-	rtnl_lock();
-	/* Strong layering violation. */
-	if (dev && dev->flags & IFF_UP) {
-		dev_close (dev); /* close the device properly */
-	}
-	rtnl_unlock();
-
 	ppp_free_buf (ppp->rbuf);
 	ppp_free_buf (ppp->wbuf);
 	ppp_free_buf (ppp->cbuf);
@@ -2564,8 +2557,8 @@
 	if (ppp && ppp->magic == PPP_MAGIC && tty == ppp->tty) {
 		CHECK_PPP (0);
 
-		poll_wait(&ppp->read_wait, wait);
-		poll_wait(&ppp->write_wait, wait);
+		poll_wait(filp, &ppp->read_wait, wait);
+		poll_wait(filp, &ppp->write_wait, wait);
 
 		/* Must lock the user buffer area while checking. */
 		CHECK_BUF_MAGIC(ppp->ubuf);
@@ -3021,6 +3014,25 @@
 	return ppp;
 }
 
+/* Collect hanged up channels */
+
+static void ppp_sync(void)
+{
+	struct device	*dev;
+	struct ppp	*ppp;
+
+	rtnl_lock();
+	for (ppp = ppp_list; ppp != 0; ppp = ppp->next) {
+		if (!ppp->inuse) {
+			dev = ppp2dev(ppp);
+			if (dev->flags&IFF_UP)
+				dev_close(dev);
+		}
+	}
+	rtnl_unlock();
+}
+
+
 /* allocate or create a PPP channel */
 static struct ppp *
 ppp_alloc (void)
@@ -3030,11 +3042,24 @@
 	struct device	*dev;
 	struct ppp	*ppp;
 
+	ppp_sync();
+
 	/* try to find an free device */
 	if_num = 0;
 	for (ppp = ppp_list; ppp != 0; ppp = ppp->next) {
-		if (!test_and_set_bit(0, &ppp->inuse))
+		if (!test_and_set_bit(0, &ppp->inuse)) {
+
+			/* Reregister device */
+
+			dev = ppp2dev(ppp);
+			unregister_netdev (dev);
+
+			if (register_netdev (dev)) {
+				printk(KERN_DEBUG "cannot reregister ppp device\n");
+				return NULL;
+			}
 			return ppp;
+		}
 		++if_num;
 	}
 /*

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov