patch-2.3.99-pre6 linux/drivers/net/ppp_generic.c

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

diff -u --recursive --new-file v2.3.99-pre5/linux/drivers/net/ppp_generic.c linux/drivers/net/ppp_generic.c
@@ -19,7 +19,7 @@
  * PPP driver, written by Michael Callahan and Al Longyear, and
  * subsequently hacked by Paul Mackerras.
  *
- * ==FILEVERSION 20000406==
+ * ==FILEVERSION 20000417==
  */
 
 #include <linux/config.h>
@@ -206,7 +206,7 @@
 			      size_t count);
 static int ppp_unattached_ioctl(struct ppp_file *pf, struct file *file,
 				unsigned int cmd, unsigned long arg);
-static void ppp_xmit_process(struct ppp *ppp, int wakeup);
+static void ppp_xmit_process(struct ppp *ppp);
 static void ppp_send_frame(struct ppp *ppp, struct sk_buff *skb);
 static void ppp_push(struct ppp *ppp);
 static void ppp_channel_push(struct channel *pch);
@@ -427,7 +427,7 @@
 
 	switch (pf->kind) {
 	case INTERFACE:
-		ppp_xmit_process(PF_TO_PPP(pf), 0);
+		ppp_xmit_process(PF_TO_PPP(pf));
 		break;
 	case CHANNEL:
 		ppp_channel_push(PF_TO_CHANNEL(pf));
@@ -440,6 +440,7 @@
 	return ret;
 }
 
+/* No kernel lock - fine */
 static unsigned int ppp_poll(struct file *file, poll_table *wait)
 {
 	struct ppp_file *pf = (struct ppp_file *) file->private_data;
@@ -774,7 +775,7 @@
 
 	netif_stop_queue(dev);
 	skb_queue_tail(&ppp->file.xq, skb);
-	ppp_xmit_process(ppp, 0);
+	ppp_xmit_process(ppp);
 	return 0;
 
  outf:
@@ -860,13 +861,12 @@
  * that can now be done.
  */
 static void
-ppp_xmit_process(struct ppp *ppp, int wakeup)
+ppp_xmit_process(struct ppp *ppp)
 {
 	struct sk_buff *skb;
 
 	ppp_xmit_lock(ppp);
-	if (wakeup)
-		ppp_push(ppp);
+	ppp_push(ppp);
 	while (ppp->xmit_pending == 0
 	       && (skb = skb_dequeue(&ppp->file.xq)) != 0)
 		ppp_send_frame(ppp, skb);
@@ -1018,14 +1018,12 @@
 		spin_lock_bh(&pch->downl);
 		if (pch->chan) {
 			if (pch->chan->ops->start_xmit(pch->chan, skb))
-				skb = 0;
+				ppp->xmit_pending = 0;
 		} else {
 			/* channel got unregistered */
 			kfree_skb(skb);
-			skb = 0;
-		}
-		if (skb_queue_len(&pch->file.xq) == 0 && skb == 0)
 			ppp->xmit_pending = 0;
+		}
 		spin_unlock_bh(&pch->downl);
 		return;
 	}
@@ -1196,6 +1194,7 @@
 ppp_channel_push(struct channel *pch)
 {
 	struct sk_buff *skb;
+	struct ppp *ppp;
 
 	spin_lock_bh(&pch->downl);
 	if (pch->chan != 0) {
@@ -1212,6 +1211,14 @@
 		skb_queue_purge(&pch->file.xq);
 	}
 	spin_unlock_bh(&pch->downl);
+	/* see if there is anything from the attached unit to be sent */
+	if (skb_queue_len(&pch->file.xq) == 0) {
+		read_lock_bh(&pch->upl);
+		ppp = pch->ppp;
+		if (ppp != 0)
+			ppp_xmit_process(ppp);
+		read_unlock_bh(&pch->upl);
+	}
 }
 
 /*
@@ -1792,18 +1799,10 @@
 ppp_output_wakeup(struct ppp_channel *chan)
 {
 	struct channel *pch = chan->ppp;
-	struct ppp *ppp;
 
 	if (pch == 0)
 		return;
 	ppp_channel_push(pch);
-	if (skb_queue_len(&pch->file.xq) == 0) {
-		read_lock_bh(&pch->upl);
-		ppp = pch->ppp;
-		if (ppp != 0)
-			ppp_xmit_process(ppp, 1);
-		read_unlock_bh(&pch->upl);
-	}
 }
 
 /*
@@ -1830,6 +1829,7 @@
 	return ppp_file_write(&pch->file, buf, count);
 }
 
+/* No kernel lock - fine */
 unsigned int
 ppp_channel_poll(struct ppp_channel *chan, struct file *file, poll_table *wait)
 {
@@ -2376,6 +2376,7 @@
 {
 	struct ppp *ppp;
 	int err = -EINVAL;
+	int dead;
 
 	write_lock_bh(&pch->upl);
 	ppp = pch->ppp;
@@ -2385,12 +2386,12 @@
 		ppp_lock(ppp);
 		list_del(&pch->clist);
 		--ppp->n_channels;
-		if (ppp->dev == 0 && ppp->n_channels == 0)
+		dead = ppp->dev == 0 && ppp->n_channels == 0;
+		ppp_unlock(ppp);
+		if (dead)
 			/* Last disconnect from a ppp unit
 			   that is already dead: free it. */
 			kfree(ppp);
-		else
-			ppp_unlock(ppp);
 		err = 0;
 	}
 	write_unlock_bh(&pch->upl);

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)