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

Next file: linux/drivers/net/via-rhine.c
Previous file: linux/drivers/net/ibmtr.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.2.7/linux/drivers/net/ppp.c linux/drivers/net/ppp.c
@@ -4,7 +4,7 @@
  *  Al Longyear <longyear@netcom.com>
  *  Extensively rewritten by Paul Mackerras <paulus@cs.anu.edu.au>
  *
- *  ==FILEVERSION 990331==
+ *  ==FILEVERSION 990510==
  *
  *  NOTE TO MAINTAINERS:
  *     If you modify this file at all, please set the number above to the
@@ -90,9 +90,6 @@
 #include <linux/kmod.h>
 #endif
 
-typedef ssize_t		rw_ret_t;
-typedef size_t		rw_count_t;
-
 /*
  * Local functions
  */
@@ -109,6 +106,7 @@
 static int ppp_async_encode(struct ppp *ppp);
 static int ppp_async_send(struct ppp *, struct sk_buff *);
 static int ppp_sync_send(struct ppp *, struct sk_buff *);
+static void ppp_tty_flush_output(struct ppp *);
 
 static int ppp_ioctl(struct ppp *, unsigned int, unsigned long);
 static int ppp_set_compression (struct ppp *ppp, struct ppp_option_data *odp);
@@ -191,10 +189,10 @@
  * TTY callbacks
  */
 
-static rw_ret_t ppp_tty_read(struct tty_struct *, struct file *, __u8 *,
-			     rw_count_t);
-static rw_ret_t ppp_tty_write(struct tty_struct *, struct file *, const __u8 *,
-			      rw_count_t);
+static ssize_t ppp_tty_read(struct tty_struct *, struct file *, __u8 *,
+			    size_t);
+static ssize_t ppp_tty_write(struct tty_struct *, struct file *, const __u8 *,
+			     size_t);
 static int ppp_tty_ioctl(struct tty_struct *, struct file *, unsigned int,
 			 unsigned long);
 static unsigned int ppp_tty_poll(struct tty_struct *tty, struct file *filp,
@@ -241,6 +239,7 @@
 	0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
 	0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
 };
+EXPORT_SYMBOL(ppp_crc16_table);
 
 #ifdef CHECK_CHARACTERS
 static __u32 paritytab[8] =
@@ -445,6 +444,7 @@
 		ppp->tty = ppp->backup_tty;
 		if (ppp_tty_push(ppp))
 			ppp_output_wakeup(ppp);
+		wake_up_interruptible(&ppp->read_wait);
 	} else {
 		ppp->tty = 0;
 		ppp->sc_xfer = 0;
@@ -462,13 +462,13 @@
  * Read a PPP frame from the rcv_q list,
  * waiting if necessary
  */
-static rw_ret_t
+static ssize_t
 ppp_tty_read(struct tty_struct *tty, struct file *file, __u8 * buf,
-	     rw_count_t nr)
+	     size_t nr)
 {
 	struct ppp *ppp = tty2ppp (tty);
 	struct sk_buff *skb;
-	rw_ret_t len, err;
+	ssize_t len, err;
 
 	/*
 	 * Validate the pointers
@@ -550,9 +550,9 @@
  * Writing to a tty in ppp line discipline sends a PPP frame.
  * Used by pppd to send control packets (LCP, etc.).
  */
-static rw_ret_t
+static ssize_t
 ppp_tty_write(struct tty_struct *tty, struct file *file, const __u8 * data,
-	      rw_count_t count)
+	      size_t count)
 {
 	struct ppp *ppp = tty2ppp (tty);
 	__u8 *new_data;
@@ -604,7 +604,7 @@
 	 */
 	ppp_send_ctrl(ppp, skb);
 
-	return (rw_ret_t) count;
+	return (ssize_t) count;
 }
 
 /*
@@ -723,6 +723,21 @@
 		error = n_tty_ioctl (tty, file, param2, param3);
 		break;
 
+	case TCFLSH:
+		/*
+		 * Flush our buffers, then call the generic code to
+		 * flush the serial port's buffer.
+		 */
+		if (param3 == TCIFLUSH || param3 == TCIOFLUSH) {
+			struct sk_buff *skb;
+			while ((skb = skb_dequeue(&ppp->rcv_q)) != NULL)
+				kfree_skb(skb);
+		}
+		if (param3 == TCIOFLUSH || param3 == TCOFLUSH)
+			ppp_tty_flush_output(ppp);
+		error = n_tty_ioctl (tty, file, param2, param3);
+		break;
+
 	case FIONREAD:
 		/*
 		 * Returns how many bytes are available for a read().
@@ -881,7 +896,7 @@
 	save_flags(flags);
 	cli();
 	if (ppp->tty_pushing) {
-		/* record wakeup attempt so we don't loose */
+		/* record wakeup attempt so we don't lose */
 		/* a wakeup call while doing push processing */
 		ppp->woke_up=1;
 		restore_flags(flags);
@@ -964,16 +979,20 @@
 	int avail, sent, done = 0;
 	struct tty_struct *tty = ppp2tty(ppp);
 	
-	if ( ppp->flags & SC_SYNC ) 
+	if (ppp->flags & SC_SYNC) 
 		return ppp_tty_sync_push(ppp);
 
 	CHECK_PPP(0);
-	if (ppp->tty_pushing)
+	if (ppp->tty_pushing) {
+		ppp->woke_up = 1;
 		return 0;
+	}
 	if (tty == NULL || tty->disc_data != (void *) ppp)
 		goto flush;
 	while (ppp->optr < ppp->olim || ppp->tpkt != 0) {
 		ppp->tty_pushing = 1;
+		mb();
+		ppp->woke_up = 0;
 		avail = ppp->olim - ppp->optr;
 		if (avail > 0) {
 			tty->flags |= (1 << TTY_DO_WRITE_WAKEUP);
@@ -983,18 +1002,24 @@
 			ppp->stats.ppp_obytes += sent;
 			ppp->optr += sent;
 			if (sent < avail) {
+				wmb();
 				ppp->tty_pushing = 0;
+				mb();
+				if (ppp->woke_up)
+					continue;
 				return done;
 			}
 		}
 		if (ppp->tpkt != 0)
 			done = ppp_async_encode(ppp);
+		wmb();
 		ppp->tty_pushing = 0;
 	}
 	return done;
 
 flush:
 	ppp->tty_pushing = 1;
+	mb();
 	ppp->stats.ppp_oerrors++;
 	if (ppp->tpkt != 0) {
 		kfree_skb(ppp->tpkt);
@@ -1002,6 +1027,7 @@
 		done = 1;
 	}
 	ppp->optr = ppp->olim;
+	wmb();
 	ppp->tty_pushing = 0;
 	return done;
 }
@@ -1113,6 +1139,32 @@
 	ppp->tpkt_pos = i;
 	ppp->tfcs = fcs;
 	return 0;
+}
+
+/*
+ * Flush output from our internal buffers.
+ * Called for the TCFLSH ioctl.
+ */
+static void
+ppp_tty_flush_output(struct ppp *ppp)
+{
+	struct sk_buff *skb;
+	int done = 0;
+
+	while ((skb = skb_dequeue(&ppp->xmt_q)) != NULL)
+		kfree_skb(skb);
+	ppp->tty_pushing = 1;
+	mb();
+	ppp->optr = ppp->olim;
+	if (ppp->tpkt != NULL) {
+		kfree_skb(ppp->tpkt);
+		ppp->tpkt = 0;
+		done = 1;
+	}
+	wmb();
+	ppp->tty_pushing = 0;
+	if (done)
+		ppp_output_wakeup(ppp);
 }
 
 /*

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