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