* Al Longyear <longyear@netcom.com>
* Extensively rewritten by Paul Mackerras <paulus@cs.anu.edu.au>
*
- * ==FILEVERSION 990331==
+ * ==FILEVERSION 990910==
*
* NOTE TO MAINTAINERS:
* If you modify this file at all, please set the number above to the
#define PPP_MAX_RCV_QLEN 32 /* max # frames we queue up for pppd */
-/* $Id: ppp.c,v 1.23 1999/03/31 05:29:08 paulus Exp $ */
+/* $Id: ppp.c,v 1.32 1999/09/11 12:09:31 paulus Exp $ */
#include <linux/version.h>
#include <linux/config.h>
#endif
#undef PPP_VERSION
-#define PPP_VERSION "2.3.6"
+#define PPP_VERSION "2.3.10"
#if LINUX_VERSION_CODE >= VERSION(2,1,4)
#define SUSER() capable(CAP_NET_ADMIN)
#endif
+#if LINUX_VERSION_CODE < VERSION(2,2,0)
+#define wmb() mb()
+#endif
+
/*
* Local functions
*/
-#ifdef CONFIG_MODULES
static int ppp_register_compressor (struct compressor *cp);
static void ppp_unregister_compressor (struct compressor *cp);
-#endif
static void ppp_async_init(struct ppp *ppp);
static void ppp_async_release(struct ppp *ppp);
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);
0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
};
+#if LINUX_VERSION_CODE >= VERSION(2,1,18)
+EXPORT_SYMBOL(ppp_crc16_table);
+#endif
#ifdef CHECK_CHARACTERS
static __u32 paritytab[8] =
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;
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().
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);
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);
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);
done = 1;
}
ppp->optr = ppp->olim;
+ wmb();
ppp->tty_pushing = 0;
return done;
}
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);
+}
+
/*
* Callback function from tty driver. Return the amount of space left
* in the receiver's buffer to decide if remote transmitter is to be
break;
switch (npi.protocol) {
+ case PPP_IPV6:
+ npi.protocol = NP_IPV6;
+ break;
case PPP_IP:
npi.protocol = NP_IP;
break;
return (struct compressor *) 0;
}
-#ifdef CONFIG_MODULES
static int ppp_register_compressor (struct compressor *cp)
{
struct compressor_link *new;
}
restore_flags(flags);
}
-#endif
/*************************************************************
* Module support routines