summaryrefslogtreecommitdiff
path: root/kernel/patch/ppp-generic-smp-2.6.28.patch
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/patch/ppp-generic-smp-2.6.28.patch')
-rw-r--r--kernel/patch/ppp-generic-smp-2.6.28.patch163
1 files changed, 163 insertions, 0 deletions
diff --git a/kernel/patch/ppp-generic-smp-2.6.28.patch b/kernel/patch/ppp-generic-smp-2.6.28.patch
new file mode 100644
index 00000000..65a218a4
--- /dev/null
+++ b/kernel/patch/ppp-generic-smp-2.6.28.patch
@@ -0,0 +1,163 @@
+--- a/drivers/net/ppp_generic.c 2008-12-25 02:26:37.000000000 +0300
++++ b/drivers/net/ppp_generic.c 2009-03-01 14:54:45.000000000 +0300
+@@ -45,6 +45,7 @@
+ #include <linux/stddef.h>
+ #include <linux/device.h>
+ #include <linux/mutex.h>
++#include <linux/workqueue.h>
+ #include <net/slhc_vj.h>
+ #include <asm/atomic.h>
+
+@@ -117,6 +118,7 @@
+ unsigned long last_recv; /* jiffies when last pkt rcvd a0 */
+ struct net_device *dev; /* network interface device a4 */
+ int closing; /* is device closing down? a8 */
++ struct work_struct xmit_work;
+ #ifdef CONFIG_PPP_MULTILINK
+ int nxchan; /* next channel to send something on */
+ u32 nxseq; /* next sequence number to send */
+@@ -156,6 +158,10 @@
+ struct ppp *ppp; /* ppp unit we're connected to */
+ struct list_head clist; /* link in list of channels per unit */
+ rwlock_t upl; /* protects `ppp' */
++
++ struct work_struct recv_work;
++ struct sk_buff_head rq; /* receive queue for pppd */
++
+ #ifdef CONFIG_PPP_MULTILINK
+ u8 avail; /* flag used in multilink stuff */
+ u8 had_frag; /* >= 1 fragments have been sent */
+@@ -272,6 +278,7 @@
+ static void ppp_destroy_channel(struct channel *pch);
+
+ static struct class *ppp_class;
++static struct workqueue_struct *kpppd_workqueue;
+
+ /* Translates a PPP protocol number to a NP index (NP == network protocol) */
+ static inline int proto_to_npindex(int proto)
+@@ -860,6 +867,13 @@
+ int err;
+
+ printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n");
++
++ kpppd_workqueue = create_workqueue("kpppd");
++ if (!kpppd_workqueue){
++ printk(KERN_ERR "failed to create workqueue\n");
++ return -1;
++ }
++
+ err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops);
+ if (!err) {
+ ppp_class = class_create(THIS_MODULE, "ppp");
+@@ -870,10 +884,12 @@
+ device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), NULL,
+ "ppp");
+ }
+-
++
+ out:
+- if (err)
++ if (err) {
++ destroy_workqueue(kpppd_workqueue);
+ printk(KERN_ERR "failed to register PPP device (%d)\n", err);
++ }
+ return err;
+
+ out_chrdev:
+@@ -881,6 +897,12 @@
+ goto out;
+ }
+
++static void ppp_xmit_work(struct work_struct *work)
++{
++ struct ppp *ppp=container_of(work,typeof(*ppp),xmit_work);
++ ppp_xmit_process(ppp);
++}
++
+ /*
+ * Network interface unit routines.
+ */
+@@ -920,7 +942,7 @@
+
+ netif_stop_queue(dev);
+ skb_queue_tail(&ppp->file.xq, skb);
+- ppp_xmit_process(ppp);
++ queue_work(kpppd_workqueue,&ppp->xmit_work);
+ return 0;
+
+ outf:
+@@ -1464,13 +1486,29 @@
+ ppp_do_recv(struct ppp *ppp, struct sk_buff *skb, struct channel *pch)
+ {
+ ppp_recv_lock(ppp);
+- if (!ppp->closing)
+- ppp_receive_frame(ppp, skb, pch);
+- else
++ if (!ppp->closing){
++ skb_queue_tail(&pch->rq, skb);
++ queue_work(kpppd_workqueue,&pch->recv_work);
++ }else
+ kfree_skb(skb);
+ ppp_recv_unlock(ppp);
+ }
+
++static void ppp_recv_work(struct work_struct *work)
++{
++ struct channel *pch=container_of(work,typeof(*pch),recv_work);
++ struct sk_buff *skb;
++
++ ppp_recv_lock(pch->ppp);
++
++ while((skb=skb_dequeue(&pch->rq))){
++ if (pch->ppp->dev)
++ ppp_receive_frame(pch->ppp, skb, pch);
++ }
++
++ ppp_recv_unlock(pch->ppp);
++}
++
+ void
+ ppp_input(struct ppp_channel *chan, struct sk_buff *skb)
+ {
+@@ -2014,6 +2052,8 @@
+ chan->ppp = pch;
+ init_ppp_file(&pch->file, CHANNEL);
+ pch->file.hdrlen = chan->hdrlen;
++ INIT_WORK(&pch->recv_work,ppp_recv_work);
++ skb_queue_head_init(&pch->rq);
+ #ifdef CONFIG_PPP_MULTILINK
+ pch->lastseq = -1;
+ #endif /* CONFIG_PPP_MULTILINK */
+@@ -2429,6 +2469,7 @@
+ INIT_LIST_HEAD(&ppp->channels);
+ spin_lock_init(&ppp->rlock);
+ spin_lock_init(&ppp->wlock);
++ INIT_WORK(&ppp->xmit_work,ppp_xmit_work);
+ #ifdef CONFIG_PPP_MULTILINK
+ ppp->minseq = -1;
+ skb_queue_head_init(&ppp->mrq);
+@@ -2537,6 +2578,7 @@
+ slhc_free(ppp->vj);
+ ppp->vj = NULL;
+ }
++ cancel_work_sync(&ppp->xmit_work);
+ skb_queue_purge(&ppp->file.xq);
+ skb_queue_purge(&ppp->file.rq);
+ #ifdef CONFIG_PPP_MULTILINK
+@@ -2672,6 +2714,8 @@
+ }
+ skb_queue_purge(&pch->file.xq);
+ skb_queue_purge(&pch->file.rq);
++ cancel_work_sync(&pch->recv_work);
++ skb_queue_purge(&pch->rq);
+ kfree(pch);
+ }
+
+@@ -2684,6 +2728,7 @@
+ unregister_chrdev(PPP_MAJOR, "ppp");
+ device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0));
+ class_destroy(ppp_class);
++ destroy_workqueue(kpppd_workqueue);
+ }
+
+ /*