aboutsummaryrefslogtreecommitdiffstats
path: root/net/phonet/pep-gprs.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/phonet/pep-gprs.c')
-rw-r--r--net/phonet/pep-gprs.c91
1 files changed, 28 insertions, 63 deletions
diff --git a/net/phonet/pep-gprs.c b/net/phonet/pep-gprs.c
index a2873203dff2..b0ceac2d6cd1 100644
--- a/net/phonet/pep-gprs.c
+++ b/net/phonet/pep-gprs.c
@@ -41,11 +41,6 @@ struct gprs_dev {
41 void (*old_write_space)(struct sock *); 41 void (*old_write_space)(struct sock *);
42 42
43 struct net_device *dev; 43 struct net_device *dev;
44
45 struct sk_buff_head tx_queue;
46 struct work_struct tx_work;
47 spinlock_t tx_lock;
48 unsigned tx_max;
49}; 44};
50 45
51static __be16 gprs_type_trans(struct sk_buff *skb) 46static __be16 gprs_type_trans(struct sk_buff *skb)
@@ -66,6 +61,14 @@ static __be16 gprs_type_trans(struct sk_buff *skb)
66 return htons(0); 61 return htons(0);
67} 62}
68 63
64static void gprs_writeable(struct gprs_dev *gp)
65{
66 struct net_device *dev = gp->dev;
67
68 if (pep_writeable(gp->sk))
69 netif_wake_queue(dev);
70}
71
69/* 72/*
70 * Socket callbacks 73 * Socket callbacks
71 */ 74 */
@@ -157,14 +160,9 @@ static void gprs_data_ready(struct sock *sk, int len)
157static void gprs_write_space(struct sock *sk) 160static void gprs_write_space(struct sock *sk)
158{ 161{
159 struct gprs_dev *gp = sk->sk_user_data; 162 struct gprs_dev *gp = sk->sk_user_data;
160 struct net_device *dev = gp->dev;
161 unsigned credits = pep_writeable(sk);
162 163
163 spin_lock_bh(&gp->tx_lock); 164 if (netif_running(gp->dev))
164 gp->tx_max = credits; 165 gprs_writeable(gp);
165 if (credits > skb_queue_len(&gp->tx_queue) && netif_running(dev))
166 netif_wake_queue(dev);
167 spin_unlock_bh(&gp->tx_lock);
168} 166}
169 167
170/* 168/*
@@ -175,22 +173,21 @@ static int gprs_open(struct net_device *dev)
175{ 173{
176 struct gprs_dev *gp = netdev_priv(dev); 174 struct gprs_dev *gp = netdev_priv(dev);
177 175
178 gprs_write_space(gp->sk); 176 gprs_writeable(gp);
179 return 0; 177 return 0;
180} 178}
181 179
182static int gprs_close(struct net_device *dev) 180static int gprs_close(struct net_device *dev)
183{ 181{
184 struct gprs_dev *gp = netdev_priv(dev);
185
186 netif_stop_queue(dev); 182 netif_stop_queue(dev);
187 flush_work(&gp->tx_work);
188 return 0; 183 return 0;
189} 184}
190 185
191static int gprs_xmit(struct sk_buff *skb, struct net_device *dev) 186static int gprs_xmit(struct sk_buff *skb, struct net_device *dev)
192{ 187{
193 struct gprs_dev *gp = netdev_priv(dev); 188 struct gprs_dev *gp = netdev_priv(dev);
189 struct sock *sk = gp->sk;
190 int len, err;
194 191
195 switch (skb->protocol) { 192 switch (skb->protocol) {
196 case htons(ETH_P_IP): 193 case htons(ETH_P_IP):
@@ -201,51 +198,24 @@ static int gprs_xmit(struct sk_buff *skb, struct net_device *dev)
201 return 0; 198 return 0;
202 } 199 }
203 200
204 spin_lock(&gp->tx_lock); 201 skb_orphan(skb);
205 if (likely(skb_queue_len(&gp->tx_queue) < gp->tx_max)) { 202 skb_set_owner_w(skb, sk);
206 skb_queue_tail(&gp->tx_queue, skb); 203 len = skb->len;
207 skb = NULL; 204 err = pep_write(sk, skb);
208 } 205 if (err) {
209 if (skb_queue_len(&gp->tx_queue) >= gp->tx_max) 206 LIMIT_NETDEBUG(KERN_WARNING"%s: TX error (%d)\n",
210 netif_stop_queue(dev); 207 dev->name, err);
211 spin_unlock(&gp->tx_lock); 208 dev->stats.tx_aborted_errors++;
212 209 dev->stats.tx_errors++;
213 schedule_work(&gp->tx_work);
214 if (unlikely(skb))
215 dev_kfree_skb(skb); 210 dev_kfree_skb(skb);
216 return 0; 211 } else {
217}
218
219static void gprs_tx(struct work_struct *work)
220{
221 struct gprs_dev *gp = container_of(work, struct gprs_dev, tx_work);
222 struct net_device *dev = gp->dev;
223 struct sock *sk = gp->sk;
224 struct sk_buff *skb;
225
226 while ((skb = skb_dequeue(&gp->tx_queue)) != NULL) {
227 int err;
228
229 dev->stats.tx_bytes += skb->len;
230 dev->stats.tx_packets++; 212 dev->stats.tx_packets++;
231 213 dev->stats.tx_bytes += len;
232 skb_orphan(skb);
233 skb_set_owner_w(skb, sk);
234
235 lock_sock(sk);
236 err = pep_write(sk, skb);
237 if (err) {
238 LIMIT_NETDEBUG(KERN_WARNING"%s: TX error (%d)\n",
239 dev->name, err);
240 dev->stats.tx_aborted_errors++;
241 dev->stats.tx_errors++;
242 }
243 release_sock(sk);
244 } 214 }
245 215
246 lock_sock(sk); 216 if (!pep_writeable(sk))
247 gprs_write_space(sk); 217 netif_stop_queue(dev);
248 release_sock(sk); 218 return 0;
249} 219}
250 220
251static int gprs_set_mtu(struct net_device *dev, int new_mtu) 221static int gprs_set_mtu(struct net_device *dev, int new_mtu)
@@ -297,11 +267,8 @@ int gprs_attach(struct sock *sk)
297 if (!dev) 267 if (!dev)
298 return -ENOMEM; 268 return -ENOMEM;
299 gp = netdev_priv(dev); 269 gp = netdev_priv(dev);
270 gp->sk = sk;
300 gp->dev = dev; 271 gp->dev = dev;
301 gp->tx_max = 0;
302 spin_lock_init(&gp->tx_lock);
303 skb_queue_head_init(&gp->tx_queue);
304 INIT_WORK(&gp->tx_work, gprs_tx);
305 272
306 netif_stop_queue(dev); 273 netif_stop_queue(dev);
307 err = register_netdev(dev); 274 err = register_netdev(dev);
@@ -328,9 +295,7 @@ int gprs_attach(struct sock *sk)
328 sk->sk_data_ready = gprs_data_ready; 295 sk->sk_data_ready = gprs_data_ready;
329 sk->sk_write_space = gprs_write_space; 296 sk->sk_write_space = gprs_write_space;
330 release_sock(sk); 297 release_sock(sk);
331
332 sock_hold(sk); 298 sock_hold(sk);
333 gp->sk = sk;
334 299
335 printk(KERN_DEBUG"%s: attached\n", dev->name); 300 printk(KERN_DEBUG"%s: attached\n", dev->name);
336 return dev->ifindex; 301 return dev->ifindex;