aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to '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;