1--- a/drivers/net/ppp_generic.c 2008-07-14 01:51:29.000000000 +0400 2+++ b/drivers/net/ppp_generic.c 2009-03-01 00:17:03.000000000 +0300 3@@ -44,6 +44,7 @@ 4 #include <linux/stddef.h> 5 #include <linux/device.h> 6 #include <linux/mutex.h> 7+#include <linux/workqueue.h> 8 #include <net/slhc_vj.h> 9 #include <asm/atomic.h> 10 11@@ -114,7 +115,8 @@ 12 void *rc_state; /* its internal state 98 */ 13 unsigned long last_xmit; /* jiffies when last pkt sent 9c */ 14 unsigned long last_recv; /* jiffies when last pkt rcvd a0 */ 15- struct net_device *dev; /* network interface device a4 */ 16+ struct net_device *dev; /* network interface device a4 */ 17+ struct work_struct xmit_work; 18 #ifdef CONFIG_PPP_MULTILINK 19 int nxchan; /* next channel to send something on */ 20 u32 nxseq; /* next sequence number to send */ 21@@ -154,6 +156,10 @@ 22 struct ppp *ppp; /* ppp unit we're connected to */ 23 struct list_head clist; /* link in list of channels per unit */ 24 rwlock_t upl; /* protects `ppp' */ 25+ 26+ struct work_struct recv_work; 27+ struct sk_buff_head rq; /* receive queue for pppd */ 28+ 29 #ifdef CONFIG_PPP_MULTILINK 30 u8 avail; /* flag used in multilink stuff */ 31 u8 had_frag; /* >= 1 fragments have been sent */ 32@@ -270,6 +276,7 @@ 33 static void ppp_destroy_channel(struct channel *pch); 34 35 static struct class *ppp_class; 36+static struct workqueue_struct *kpppd_workqueue; 37 38 /* Translates a PPP protocol number to a NP index (NP == network protocol) */ 39 static inline int proto_to_npindex(int proto) 40@@ -849,6 +856,13 @@ 41 int err; 42 43 printk(KERN_INFO "PPP generic driver version " PPP_VERSION "\n"); 44+ 45+ kpppd_workqueue = create_workqueue("kpppd"); 46+ if (!kpppd_workqueue){ 47+ printk(KERN_ERR "failed to create workqueue\n"); 48+ return -1; 49+ } 50+ 51 err = register_chrdev(PPP_MAJOR, "ppp", &ppp_device_fops); 52 if (!err) { 53 ppp_class = class_create(THIS_MODULE, "ppp"); 54@@ -858,10 +872,12 @@ 55 } 56 device_create(ppp_class, NULL, MKDEV(PPP_MAJOR, 0), "ppp"); 57 } 58- 59+ 60 out: 61- if (err) 62+ if (err) { 63+ destroy_workqueue(kpppd_workqueue); 64 printk(KERN_ERR "failed to register PPP device (%d)\n", err); 65+ } 66 return err; 67 68 out_chrdev: 69@@ -869,6 +885,12 @@ 70 goto out; 71 } 72 73+static void ppp_xmit_work(struct work_struct *work) 74+{ 75+ struct ppp *ppp=container_of(work,typeof(*ppp),xmit_work); 76+ ppp_xmit_process(ppp); 77+} 78+ 79 /* 80 * Network interface unit routines. 81 */ 82@@ -908,7 +930,7 @@ 83 84 netif_stop_queue(dev); 85 skb_queue_tail(&ppp->file.xq, skb); 86- ppp_xmit_process(ppp); 87+ queue_work(kpppd_workqueue,&ppp->xmit_work); 88 return 0; 89 90 outf: 91@@ -1453,13 +1475,29 @@ 92 { 93 ppp_recv_lock(ppp); 94 /* ppp->dev == 0 means interface is closing down */ 95- if (ppp->dev) 96- ppp_receive_frame(ppp, skb, pch); 97- else 98+ if (ppp->dev) { 99+ skb_queue_tail(&pch->rq, skb); 100+ queue_work(kpppd_workqueue,&pch->recv_work); 101+ } else 102 kfree_skb(skb); 103 ppp_recv_unlock(ppp); 104 } 105 106+static void ppp_recv_work(struct work_struct *work) 107+{ 108+ struct channel *pch=container_of(work,typeof(*pch),recv_work); 109+ struct sk_buff *skb; 110+ 111+ ppp_recv_lock(pch->ppp); 112+ 113+ while((skb=skb_dequeue(&pch->rq))){ 114+ if (pch->ppp->dev) 115+ ppp_receive_frame(pch->ppp, skb, pch); 116+ } 117+ 118+ ppp_recv_unlock(pch->ppp); 119+} 120+ 121 void 122 ppp_input(struct ppp_channel *chan, struct sk_buff *skb) 123 { 124@@ -2000,6 +2038,8 @@ 125 chan->ppp = pch; 126 init_ppp_file(&pch->file, CHANNEL); 127 pch->file.hdrlen = chan->hdrlen; 128+ INIT_WORK(&pch->recv_work,ppp_recv_work); 129+ skb_queue_head_init(&pch->rq); 130 #ifdef CONFIG_PPP_MULTILINK 131 pch->lastseq = -1; 132 #endif /* CONFIG_PPP_MULTILINK */ 133@@ -2419,6 +2459,7 @@ 134 INIT_LIST_HEAD(&ppp->channels); 135 spin_lock_init(&ppp->rlock); 136 spin_lock_init(&ppp->wlock); 137+ INIT_WORK(&ppp->xmit_work,ppp_xmit_work); 138 #ifdef CONFIG_PPP_MULTILINK 139 ppp->minseq = -1; 140 skb_queue_head_init(&ppp->mrq); 141@@ -2529,6 +2570,7 @@ 142 slhc_free(ppp->vj); 143 ppp->vj = NULL; 144 } 145+ cancel_work_sync(&ppp->xmit_work); 146 skb_queue_purge(&ppp->file.xq); 147 skb_queue_purge(&ppp->file.rq); 148 #ifdef CONFIG_PPP_MULTILINK 149@@ -2664,6 +2706,8 @@ 150 } 151 skb_queue_purge(&pch->file.xq); 152 skb_queue_purge(&pch->file.rq); 153+ cancel_work_sync(&pch->recv_work); 154+ skb_queue_purge(&pch->rq); 155 kfree(pch); 156 } 157 158@@ -2676,6 +2720,7 @@ 159 unregister_chrdev(PPP_MAJOR, "ppp"); 160 device_destroy(ppp_class, MKDEV(PPP_MAJOR, 0)); 161 class_destroy(ppp_class); 162+ destroy_workqueue(kpppd_workqueue); 163 } 164 165 /* 166