diff options
Diffstat (limited to 'net')
-rw-r--r-- | net/atm/br2684.c | 37 |
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 */ | ||
146 | static 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; |