linux 2.6.16.38 w/ vs2.0.3-rc1
[linux-2.6.git] / drivers / net / ppp_async.c
index e8be5a2..aa6540b 100644 (file)
@@ -31,6 +31,7 @@
 #include <linux/spinlock.h>
 #include <linux/init.h>
 #include <asm/uaccess.h>
+#include <asm/string.h>
 
 #define PPP_VERSION    "2.4.2"
 
@@ -84,7 +85,7 @@ struct asyncppp {
 #define SC_RCV_BITS    (SC_RCV_B7_1|SC_RCV_B7_0|SC_RCV_ODDP|SC_RCV_EVNP)
 
 static int flag_time = HZ;
-MODULE_PARM(flag_time, "i");
+module_param(flag_time, int, 0);
 MODULE_PARM_DESC(flag_time, "ppp_async: interval between flagged packets (in clock ticks)");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_LDISC(N_PPP);
@@ -126,7 +127,7 @@ static struct ppp_channel_ops async_ops = {
  * FIXME: this is no longer true. The _close path for the ldisc is 
  * now guaranteed to be sane. 
  */
-static rwlock_t disc_data_lock = RW_LOCK_UNLOCKED;
+static DEFINE_RWLOCK(disc_data_lock);
 
 static struct asyncppp *ap_get(struct tty_struct *tty)
 {
@@ -188,7 +189,7 @@ ppp_asynctty_open(struct tty_struct *tty)
                goto out_free;
 
        tty->disc_data = ap;
-
+       tty->receive_room = 65536;
        return 0;
 
  out_free:
@@ -342,12 +343,6 @@ ppp_asynctty_poll(struct tty_struct *tty, struct file *file, poll_table *wait)
        return 0;
 }
 
-static int
-ppp_asynctty_room(struct tty_struct *tty)
-{
-       return 65535;
-}
-
 /*
  * This can now be called from hard interrupt level as well
  * as soft interrupt level or mainline.
@@ -364,7 +359,7 @@ ppp_asynctty_receive(struct tty_struct *tty, const unsigned char *buf,
        spin_lock_irqsave(&ap->recv_lock, flags);
        ppp_async_input(ap, buf, cflags, count);
        spin_unlock_irqrestore(&ap->recv_lock, flags);
-       if (skb_queue_len(&ap->rqueue))
+       if (!skb_queue_empty(&ap->rqueue))
                tasklet_schedule(&ap->tsk);
        ap_put(ap);
        if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
@@ -397,7 +392,6 @@ static struct tty_ldisc ppp_ldisc = {
        .write  = ppp_asynctty_write,
        .ioctl  = ppp_asynctty_ioctl,
        .poll   = ppp_asynctty_poll,
-       .receive_room = ppp_asynctty_room,
        .receive_buf = ppp_asynctty_receive,
        .write_wakeup = ppp_asynctty_wakeup,
 };
@@ -835,8 +829,11 @@ process_input_packet(struct asyncppp *ap)
  err:
        /* frame had an error, remember that, reset SC_TOSS & SC_ESCAPE */
        ap->state = SC_PREV_ERROR;
-       if (skb)
+       if (skb) {
+               /* make skb appear as freshly allocated */
                skb_trim(skb, 0);
+               skb_reserve(skb, - skb_headroom(skb));
+       }
 }
 
 /* Called when the tty driver has data for us. Runs parallel with the
@@ -889,10 +886,17 @@ ppp_async_input(struct asyncppp *ap, const unsigned char *buf,
                                skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2);
                                if (skb == 0)
                                        goto nomem;
-                               /* Try to get the payload 4-byte aligned */
+                               ap->rpkt = skb;
+                       }
+                       if (skb->len == 0) {
+                               /* Try to get the payload 4-byte aligned.
+                                * This should match the
+                                * PPP_ALLSTATIONS/PPP_UI/compressed tests in
+                                * process_input_packet, but we do not have
+                                * enough chars here to test buf[1] and buf[2].
+                                */
                                if (buf[0] != PPP_ALLSTATIONS)
                                        skb_reserve(skb, 2 + (buf[0] & 1));
-                               ap->rpkt = skb;
                        }
                        if (n > skb_tailroom(skb)) {
                                /* packet overflowed MRU */
@@ -1000,7 +1004,7 @@ static void async_lcp_peek(struct asyncppp *ap, unsigned char *data,
        data += 4;
        dlen -= 4;
        /* data[0] is code, data[1] is length */
-       while (dlen >= 2 && dlen >= data[1]) {
+       while (dlen >= 2 && dlen >= data[1] && data[1] >= 2) {
                switch (data[0]) {
                case LCP_MRU:
                        val = (data[2] << 8) + data[3];
@@ -1025,7 +1029,7 @@ static void async_lcp_peek(struct asyncppp *ap, unsigned char *data,
 
 static void __exit ppp_async_cleanup(void)
 {
-       if (tty_register_ldisc(N_PPP, NULL) != 0)
+       if (tty_unregister_ldisc(N_PPP) != 0)
                printk(KERN_ERR "failed to unregister PPP line discipline\n");
 }