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); |
