aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKarl Hiramoto <karl@hiramoto.org>2009-09-03 02:26:39 -0400
committerDavid S. Miller <davem@davemloft.net>2009-09-03 02:46:10 -0400
commit137742cf9738f1b4784058ff79aec7ca85e769d4 (patch)
tree1b2424c5d0efe674c8a93f09451b281f0ada3ec6
parent81538e74ca12a71ea37ce72f809ebc65a90b9538 (diff)
atm/br2684: netif_stop_queue() when atm device busy and netif_wake_queue() when we can send packets again.
This patch removes the call to dev_kfree_skb() when the atm device is busy. Calling dev_kfree_skb() causes heavy packet loss then the device is under heavy load, the more correct behavior should be to stop the upper layers, then when the lower device can queue packets again wake the upper layers. Signed-off-by: Karl Hiramoto <karl@hiramoto.org> Signed-off-by: Chas Williams <chas@cmf.nrl.navy.mil> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--net/atm/br2684.c37
1 files changed, 27 insertions, 10 deletions
diff --git a/net/atm/br2684.c b/net/atm/br2684.c
index d6be0d1f0b9a..26a646d4eb32 100644
--- a/net/atm/br2684.c
+++ b/net/atm/br2684.c
@@ -69,7 +69,7 @@ struct br2684_vcc {
69 struct net_device *device; 69 struct net_device *device;
70 /* keep old push, pop functions for chaining */ 70 /* keep old push, pop functions for chaining */
71 void (*old_push) (struct atm_vcc * vcc, struct sk_buff * skb); 71 void (*old_push) (struct atm_vcc * vcc, struct sk_buff * skb);
72 /* void (*old_pop)(struct atm_vcc *vcc, struct sk_buff *skb); */ 72 void (*old_pop)(struct atm_vcc *vcc, struct sk_buff *skb);
73 enum br2684_encaps encaps; 73 enum br2684_encaps encaps;
74 struct list_head brvccs; 74 struct list_head brvccs;
75#ifdef CONFIG_ATM_BR2684_IPFILTER 75#ifdef CONFIG_ATM_BR2684_IPFILTER
@@ -142,6 +142,22 @@ static struct net_device *br2684_find_dev(const struct br2684_if_spec *s)
142 return NULL; 142 return NULL;
143} 143}
144 144
145/* chained vcc->pop function. Check if we should wake the netif_queue */
146static void br2684_pop(struct atm_vcc *vcc, struct sk_buff *skb)
147{
148 struct br2684_vcc *brvcc = BR2684_VCC(vcc);
149 struct net_device *net_dev = skb->dev;
150
151 pr_debug("br2684_pop(vcc %p ; net_dev %p )\n", vcc, net_dev);
152 brvcc->old_pop(vcc, skb);
153
154 if (!net_dev)
155 return;
156
157 if (atm_may_send(vcc, 0))
158 netif_wake_queue(net_dev);
159
160}
145/* 161/*
146 * Send a packet out a particular vcc. Not to useful right now, but paves 162 * Send a packet out a particular vcc. Not to useful right now, but paves
147 * the way for multiple vcc's per itf. Returns true if we can send, 163 * the way for multiple vcc's per itf. Returns true if we can send,
@@ -200,20 +216,19 @@ static int br2684_xmit_vcc(struct sk_buff *skb, struct net_device *dev,
200 216
201 ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc; 217 ATM_SKB(skb)->vcc = atmvcc = brvcc->atmvcc;
202 pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev); 218 pr_debug("atm_skb(%p)->vcc(%p)->dev(%p)\n", skb, atmvcc, atmvcc->dev);
203 if (!atm_may_send(atmvcc, skb->truesize)) {
204 /*
205 * We free this here for now, because we cannot know in a higher
206 * layer whether the skb pointer it supplied wasn't freed yet.
207 * Now, it always is.
208 */
209 dev_kfree_skb(skb);
210 return 0;
211 }
212 atomic_add(skb->truesize, &sk_atm(atmvcc)->sk_wmem_alloc); 219 atomic_add(skb->truesize, &sk_atm(atmvcc)->sk_wmem_alloc);
213 ATM_SKB(skb)->atm_options = atmvcc->atm_options; 220 ATM_SKB(skb)->atm_options = atmvcc->atm_options;
214 dev->stats.tx_packets++; 221 dev->stats.tx_packets++;
215 dev->stats.tx_bytes += skb->len; 222 dev->stats.tx_bytes += skb->len;
216 atmvcc->send(atmvcc, skb); 223 atmvcc->send(atmvcc, skb);
224
225 if (!atm_may_send(atmvcc, 0)) {
226 netif_stop_queue(brvcc->device);
227 /*check for race with br2684_pop*/
228 if (atm_may_send(atmvcc, 0))
229 netif_start_queue(brvcc->device);
230 }
231
217 return 1; 232 return 1;
218} 233}
219 234
@@ -504,8 +519,10 @@ static int br2684_regvcc(struct atm_vcc *atmvcc, void __user * arg)
504 atmvcc->user_back = brvcc; 519 atmvcc->user_back = brvcc;
505 brvcc->encaps = (enum br2684_encaps)be.encaps; 520 brvcc->encaps = (enum br2684_encaps)be.encaps;
506 brvcc->old_push = atmvcc->push; 521 brvcc->old_push = atmvcc->push;
522 brvcc->old_pop = atmvcc->pop;
507 barrier(); 523 barrier();
508 atmvcc->push = br2684_push; 524 atmvcc->push = br2684_push;
525 atmvcc->pop = br2684_pop;
509 526
510 __skb_queue_head_init(&queue); 527 __skb_queue_head_init(&queue);
511 rq = &sk_atm(atmvcc)->sk_receive_queue; 528 rq = &sk_atm(atmvcc)->sk_receive_queue;