diff options
Diffstat (limited to 'kernel/patch/ppp-generic-smp-2.6.28.patch')
-rw-r--r-- | kernel/patch/ppp-generic-smp-2.6.28.patch | 163 |
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); + } + + /* |