From: Paul Fulghum <paulkf@microgate.com>
To: linux-kernel <linux-kernel@vger.kernel.org>
Cc: Paul Mackerras <paulus@samba.org>, Andrew Morton <akpm@osdl.org>
Subject: [PATCH] 2.6.7 ppp_synctty.c receive/write_wakeup fix
Date: 16 Jun 2004 10:05:59 -0500 [thread overview]
Message-ID: <1087398358.2830.7.camel@deimos.microgate.com> (raw)
Changes:
Allow receive and write_wakeup callbacks to be
called at hard interrupt context and/or with
interrupts disabled (removes softirq warning).
This mirrors changes by Paul Mackerras to ppp_async.c
for the same purpose. Patch has been previously posted
for comments and has been tested with success by
multiple persons.
Please apply.
--
Paul Fulghum
paulkf@microgate.com
--- linux-2.6.7/drivers/net/ppp_synctty.c 2004-06-16 08:27:46.000000000 -0500
+++ linux-2.6.7-mg1/drivers/net/ppp_synctty.c 2004-06-16 08:33:16.000000000 -0500
@@ -29,7 +29,7 @@
* PPP driver, written by Michael Callahan and Al Longyear, and
* subsequently hacked by Paul Mackerras.
*
- * ==FILEVERSION 20020125==
+ * ==FILEVERSION 20040616==
*/
#include <linux/module.h>
@@ -65,7 +65,9 @@
struct sk_buff *tpkt;
unsigned long last_xmit;
- struct sk_buff *rpkt;
+ struct sk_buff_head rqueue;
+
+ struct tasklet_struct tsk;
atomic_t refcnt;
struct semaphore dead_sem;
@@ -88,6 +90,7 @@
static int ppp_sync_send(struct ppp_channel *chan, struct sk_buff *skb);
static int ppp_sync_ioctl(struct ppp_channel *chan, unsigned int cmd,
unsigned long arg);
+static void ppp_sync_process(unsigned long arg);
static int ppp_sync_push(struct syncppp *ap);
static void ppp_sync_flush_output(struct syncppp *ap);
static void ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
@@ -217,6 +220,9 @@
ap->xaccm[3] = 0x60000000U;
ap->raccm = ~0U;
+ skb_queue_head_init(&ap->rqueue);
+ tasklet_init(&ap->tsk, ppp_sync_process, (unsigned long) ap);
+
atomic_set(&ap->refcnt, 1);
init_MUTEX_LOCKED(&ap->dead_sem);
@@ -267,10 +273,10 @@
*/
if (!atomic_dec_and_test(&ap->refcnt))
down(&ap->dead_sem);
+ tasklet_kill(&ap->tsk);
ppp_unregister_channel(&ap->chan);
- if (ap->rpkt != 0)
- kfree_skb(ap->rpkt);
+ skb_queue_purge(&ap->rqueue);
if (ap->tpkt != 0)
kfree_skb(ap->tpkt);
kfree(ap);
@@ -369,17 +375,24 @@
return 65535;
}
+/*
+ * This can now be called from hard interrupt level as well
+ * as soft interrupt level or mainline.
+ */
static void
ppp_sync_receive(struct tty_struct *tty, const unsigned char *buf,
- char *flags, int count)
+ char *cflags, int count)
{
struct syncppp *ap = sp_get(tty);
+ unsigned long flags;
if (ap == 0)
return;
- spin_lock_bh(&ap->recv_lock);
- ppp_sync_input(ap, buf, flags, count);
- spin_unlock_bh(&ap->recv_lock);
+ spin_lock_irqsave(&ap->recv_lock, flags);
+ ppp_sync_input(ap, buf, cflags, count);
+ spin_unlock_irqrestore(&ap->recv_lock, flags);
+ if (skb_queue_len(&ap->rqueue))
+ tasklet_schedule(&ap->tsk);
sp_put(ap);
if (test_and_clear_bit(TTY_THROTTLED, &tty->flags)
&& tty->driver->unthrottle)
@@ -394,8 +407,8 @@
clear_bit(TTY_DO_WRITE_WAKEUP, &tty->flags);
if (ap == 0)
return;
- if (ppp_sync_push(ap))
- ppp_output_wakeup(&ap->chan);
+ set_bit(XMIT_WAKEUP, &ap->xmit_flags);
+ tasklet_schedule(&ap->tsk);
sp_put(ap);
}
@@ -449,9 +462,9 @@
if (get_user(val, (int *) arg))
break;
ap->flags = val & ~SC_RCV_BITS;
- spin_lock_bh(&ap->recv_lock);
+ spin_lock_irq(&ap->recv_lock);
ap->rbits = val & SC_RCV_BITS;
- spin_unlock_bh(&ap->recv_lock);
+ spin_unlock_irq(&ap->recv_lock);
err = 0;
break;
@@ -512,6 +525,32 @@
}
/*
+ * This is called at softirq level to deliver received packets
+ * to the ppp_generic code, and to tell the ppp_generic code
+ * if we can accept more output now.
+ */
+static void ppp_sync_process(unsigned long arg)
+{
+ struct syncppp *ap = (struct syncppp *) arg;
+ struct sk_buff *skb;
+
+ /* process received packets */
+ while ((skb = skb_dequeue(&ap->rqueue)) != NULL) {
+ if (skb->len == 0) {
+ /* zero length buffers indicate error */
+ ppp_input_error(&ap->chan, 0);
+ kfree_skb(skb);
+ }
+ else
+ ppp_input(&ap->chan, skb);
+ }
+
+ /* try to push more stuff out */
+ if (test_bit(XMIT_WAKEUP, &ap->xmit_flags) && ppp_sync_push(ap))
+ ppp_output_wakeup(&ap->chan);
+}
+
+/*
* Procedures for encapsulation and framing.
*/
@@ -600,7 +639,6 @@
struct tty_struct *tty = ap->tty;
int tty_stuffed = 0;
- set_bit(XMIT_WAKEUP, &ap->xmit_flags);
if (!spin_trylock_bh(&ap->xmit_lock))
return 0;
for (;;) {
@@ -667,15 +705,44 @@
* Receive-side routines.
*/
-static inline void
-process_input_packet(struct syncppp *ap)
+/* called when the tty driver has data for us.
+ *
+ * Data is frame oriented: each call to ppp_sync_input is considered
+ * a whole frame. If the 1st flag byte is non-zero then the whole
+ * frame is considered to be in error and is tossed.
+ */
+static void
+ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
+ char *flags, int count)
{
struct sk_buff *skb;
unsigned char *p;
- int code = 0;
- skb = ap->rpkt;
- ap->rpkt = 0;
+ if (count == 0)
+ return;
+
+ if (ap->flags & SC_LOG_INPKT)
+ ppp_print_buffer ("receive buffer", buf, count);
+
+ /* stuff the chars in the skb */
+ if ((skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2)) == 0) {
+ printk(KERN_ERR "PPPsync: no memory (input pkt)\n");
+ goto err;
+ }
+ /* Try to get the payload 4-byte aligned */
+ if (buf[0] != PPP_ALLSTATIONS)
+ skb_reserve(skb, 2 + (buf[0] & 1));
+
+ if (flags != 0 && *flags) {
+ /* error flag set, ignore frame */
+ goto err;
+ } else if (count > skb_tailroom(skb)) {
+ /* packet overflowed MRU */
+ goto err;
+ }
+
+ p = skb_put(skb, count);
+ memcpy(p, buf, count);
/* strip address/control field if present */
p = skb->data;
@@ -693,59 +760,15 @@
} else if (skb->len < 2)
goto err;
- /* pass to generic layer */
- ppp_input(&ap->chan, skb);
+ /* queue the frame to be processed */
+ skb_queue_tail(&ap->rqueue, skb);
return;
- err:
- kfree_skb(skb);
- ppp_input_error(&ap->chan, code);
-}
-
-/* called when the tty driver has data for us.
- *
- * Data is frame oriented: each call to ppp_sync_input is considered
- * a whole frame. If the 1st flag byte is non-zero then the whole
- * frame is considered to be in error and is tossed.
- */
-static void
-ppp_sync_input(struct syncppp *ap, const unsigned char *buf,
- char *flags, int count)
-{
- struct sk_buff *skb;
- unsigned char *sp;
-
- if (count == 0)
- return;
-
- /* if flag set, then error, ignore frame */
- if (flags != 0 && *flags) {
- ppp_input_error(&ap->chan, *flags);
- return;
- }
-
- if (ap->flags & SC_LOG_INPKT)
- ppp_print_buffer ("receive buffer", buf, count);
-
- /* stuff the chars in the skb */
- if ((skb = ap->rpkt) == 0) {
- if ((skb = dev_alloc_skb(ap->mru + PPP_HDRLEN + 2)) == 0) {
- printk(KERN_ERR "PPPsync: no memory (input pkt)\n");
- ppp_input_error(&ap->chan, 0);
- return;
- }
- /* Try to get the payload 4-byte aligned */
- if (buf[0] != PPP_ALLSTATIONS)
- skb_reserve(skb, 2 + (buf[0] & 1));
- ap->rpkt = skb;
- }
- if (count > skb_tailroom(skb)) {
- /* packet overflowed MRU */
- ppp_input_error(&ap->chan, 1);
- } else {
- sp = skb_put(skb, count);
- memcpy(sp, buf, count);
- process_input_packet(ap);
+err:
+ /* queue zero length packet as error indication */
+ if (skb || (skb = dev_alloc_skb(0))) {
+ skb_trim(skb, 0);
+ skb_queue_tail(&ap->rqueue, skb);
}
}
reply other threads:[~2004-06-16 15:06 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1087398358.2830.7.camel@deimos.microgate.com \
--to=paulkf@microgate.com \
--cc=akpm@osdl.org \
--cc=linux-kernel@vger.kernel.org \
--cc=paulus@samba.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.