diff options
Diffstat (limited to 'net/ieee80211/ieee80211_tx.c')
-rw-r--r-- | net/ieee80211/ieee80211_tx.c | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/net/ieee80211/ieee80211_tx.c b/net/ieee80211/ieee80211_tx.c index cdee41cefb26..f505aa127e21 100644 --- a/net/ieee80211/ieee80211_tx.c +++ b/net/ieee80211/ieee80211_tx.c | |||
@@ -459,7 +459,71 @@ int ieee80211_xmit(struct sk_buff *skb, struct net_device *dev) | |||
459 | netif_stop_queue(dev); | 459 | netif_stop_queue(dev); |
460 | stats->tx_errors++; | 460 | stats->tx_errors++; |
461 | return 1; | 461 | return 1; |
462 | } | ||
463 | |||
464 | /* Incoming 802.11 strucure is converted to a TXB | ||
465 | * a block of 802.11 fragment packets (stored as skbs) */ | ||
466 | int ieee80211_tx_frame(struct ieee80211_device *ieee, | ||
467 | struct ieee80211_hdr *frame, int len) | ||
468 | { | ||
469 | struct ieee80211_txb *txb = NULL; | ||
470 | unsigned long flags; | ||
471 | struct net_device_stats *stats = &ieee->stats; | ||
472 | struct sk_buff *skb_frag; | ||
473 | |||
474 | spin_lock_irqsave(&ieee->lock, flags); | ||
475 | |||
476 | /* If there is no driver handler to take the TXB, dont' bother | ||
477 | * creating it... */ | ||
478 | if (!ieee->hard_start_xmit) { | ||
479 | printk(KERN_WARNING "%s: No xmit handler.\n", ieee->dev->name); | ||
480 | goto success; | ||
481 | } | ||
462 | 482 | ||
483 | if (unlikely(len < 24)) { | ||
484 | printk(KERN_WARNING "%s: skb too small (%d).\n", | ||
485 | ieee->dev->name, len); | ||
486 | goto success; | ||
487 | } | ||
488 | |||
489 | /* When we allocate the TXB we allocate enough space for the reserve | ||
490 | * and full fragment bytes (bytes_per_frag doesn't include prefix, | ||
491 | * postfix, header, FCS, etc.) */ | ||
492 | txb = ieee80211_alloc_txb(1, len, GFP_ATOMIC); | ||
493 | if (unlikely(!txb)) { | ||
494 | printk(KERN_WARNING "%s: Could not allocate TXB\n", | ||
495 | ieee->dev->name); | ||
496 | goto failed; | ||
497 | } | ||
498 | txb->encrypted = 0; | ||
499 | txb->payload_size = len; | ||
500 | |||
501 | skb_frag = txb->fragments[0]; | ||
502 | |||
503 | memcpy(skb_put(skb_frag, len), frame, len); | ||
504 | |||
505 | if (ieee->config & | ||
506 | (CFG_IEEE80211_COMPUTE_FCS | CFG_IEEE80211_RESERVE_FCS)) | ||
507 | skb_put(skb_frag, 4); | ||
508 | |||
509 | success: | ||
510 | spin_unlock_irqrestore(&ieee->lock, flags); | ||
511 | |||
512 | if (txb) { | ||
513 | if ((*ieee->hard_start_xmit) (txb, ieee->dev) == 0) { | ||
514 | stats->tx_packets++; | ||
515 | stats->tx_bytes += txb->payload_size; | ||
516 | return 0; | ||
517 | } | ||
518 | ieee80211_txb_free(txb); | ||
519 | } | ||
520 | return 0; | ||
521 | |||
522 | failed: | ||
523 | spin_unlock_irqrestore(&ieee->lock, flags); | ||
524 | stats->tx_errors++; | ||
525 | return 1; | ||
463 | } | 526 | } |
464 | 527 | ||
528 | EXPORT_SYMBOL(ieee80211_tx_frame); | ||
465 | EXPORT_SYMBOL(ieee80211_txb_free); | 529 | EXPORT_SYMBOL(ieee80211_txb_free); |