diff options
Diffstat (limited to 'net/mac80211/agg-tx.c')
-rw-r--r-- | net/mac80211/agg-tx.c | 65 |
1 files changed, 23 insertions, 42 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index c8be8eff70da..b3f65520e7a7 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -15,6 +15,7 @@ | |||
15 | 15 | ||
16 | #include <linux/ieee80211.h> | 16 | #include <linux/ieee80211.h> |
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/export.h> | ||
18 | #include <net/mac80211.h> | 19 | #include <net/mac80211.h> |
19 | #include "ieee80211_i.h" | 20 | #include "ieee80211_i.h" |
20 | #include "driver-ops.h" | 21 | #include "driver-ops.h" |
@@ -68,11 +69,9 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, | |||
68 | 69 | ||
69 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); | 70 | skb = dev_alloc_skb(sizeof(*mgmt) + local->hw.extra_tx_headroom); |
70 | 71 | ||
71 | if (!skb) { | 72 | if (!skb) |
72 | printk(KERN_ERR "%s: failed to allocate buffer " | ||
73 | "for addba request frame\n", sdata->name); | ||
74 | return; | 73 | return; |
75 | } | 74 | |
76 | skb_reserve(skb, local->hw.extra_tx_headroom); | 75 | skb_reserve(skb, local->hw.extra_tx_headroom); |
77 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); | 76 | mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); |
78 | memset(mgmt, 0, 24); | 77 | memset(mgmt, 0, 24); |
@@ -106,19 +105,18 @@ static void ieee80211_send_addba_request(struct ieee80211_sub_if_data *sdata, | |||
106 | ieee80211_tx_skb(sdata, skb); | 105 | ieee80211_tx_skb(sdata, skb); |
107 | } | 106 | } |
108 | 107 | ||
109 | void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u16 ssn) | 108 | void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn) |
110 | { | 109 | { |
110 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
111 | struct ieee80211_local *local = sdata->local; | 111 | struct ieee80211_local *local = sdata->local; |
112 | struct sk_buff *skb; | 112 | struct sk_buff *skb; |
113 | struct ieee80211_bar *bar; | 113 | struct ieee80211_bar *bar; |
114 | u16 bar_control = 0; | 114 | u16 bar_control = 0; |
115 | 115 | ||
116 | skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); | 116 | skb = dev_alloc_skb(sizeof(*bar) + local->hw.extra_tx_headroom); |
117 | if (!skb) { | 117 | if (!skb) |
118 | printk(KERN_ERR "%s: failed to allocate buffer for " | ||
119 | "bar frame\n", sdata->name); | ||
120 | return; | 118 | return; |
121 | } | 119 | |
122 | skb_reserve(skb, local->hw.extra_tx_headroom); | 120 | skb_reserve(skb, local->hw.extra_tx_headroom); |
123 | bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar)); | 121 | bar = (struct ieee80211_bar *)skb_put(skb, sizeof(*bar)); |
124 | memset(bar, 0, sizeof(*bar)); | 122 | memset(bar, 0, sizeof(*bar)); |
@@ -128,13 +126,14 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1 | |||
128 | memcpy(bar->ta, sdata->vif.addr, ETH_ALEN); | 126 | memcpy(bar->ta, sdata->vif.addr, ETH_ALEN); |
129 | bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; | 127 | bar_control |= (u16)IEEE80211_BAR_CTRL_ACK_POLICY_NORMAL; |
130 | bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; | 128 | bar_control |= (u16)IEEE80211_BAR_CTRL_CBMTID_COMPRESSED_BA; |
131 | bar_control |= (u16)(tid << 12); | 129 | bar_control |= (u16)(tid << IEEE80211_BAR_CTRL_TID_INFO_SHIFT); |
132 | bar->control = cpu_to_le16(bar_control); | 130 | bar->control = cpu_to_le16(bar_control); |
133 | bar->start_seq_num = cpu_to_le16(ssn); | 131 | bar->start_seq_num = cpu_to_le16(ssn); |
134 | 132 | ||
135 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; | 133 | IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT; |
136 | ieee80211_tx_skb(sdata, skb); | 134 | ieee80211_tx_skb(sdata, skb); |
137 | } | 135 | } |
136 | EXPORT_SYMBOL(ieee80211_send_bar); | ||
138 | 137 | ||
139 | void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, | 138 | void ieee80211_assign_tid_tx(struct sta_info *sta, int tid, |
140 | struct tid_ampdu_tx *tid_tx) | 139 | struct tid_ampdu_tx *tid_tx) |
@@ -364,7 +363,8 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
364 | return -EINVAL; | 363 | return -EINVAL; |
365 | 364 | ||
366 | if ((tid >= STA_TID_NUM) || | 365 | if ((tid >= STA_TID_NUM) || |
367 | !(local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION)) | 366 | !(local->hw.flags & IEEE80211_HW_AMPDU_AGGREGATION) || |
367 | (local->hw.flags & IEEE80211_HW_TX_AMPDU_SETUP_IN_HW)) | ||
368 | return -EINVAL; | 368 | return -EINVAL; |
369 | 369 | ||
370 | #ifdef CONFIG_MAC80211_HT_DEBUG | 370 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -383,7 +383,7 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
383 | sdata->vif.type != NL80211_IFTYPE_AP) | 383 | sdata->vif.type != NL80211_IFTYPE_AP) |
384 | return -EINVAL; | 384 | return -EINVAL; |
385 | 385 | ||
386 | if (test_sta_flags(sta, WLAN_STA_BLOCK_BA)) { | 386 | if (test_sta_flag(sta, WLAN_STA_BLOCK_BA)) { |
387 | #ifdef CONFIG_MAC80211_HT_DEBUG | 387 | #ifdef CONFIG_MAC80211_HT_DEBUG |
388 | printk(KERN_DEBUG "BA sessions blocked. " | 388 | printk(KERN_DEBUG "BA sessions blocked. " |
389 | "Denying BA session request\n"); | 389 | "Denying BA session request\n"); |
@@ -413,11 +413,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
413 | /* prepare A-MPDU MLME for Tx aggregation */ | 413 | /* prepare A-MPDU MLME for Tx aggregation */ |
414 | tid_tx = kzalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); | 414 | tid_tx = kzalloc(sizeof(struct tid_ampdu_tx), GFP_ATOMIC); |
415 | if (!tid_tx) { | 415 | if (!tid_tx) { |
416 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
417 | if (net_ratelimit()) | ||
418 | printk(KERN_ERR "allocate tx mlme to tid %d failed\n", | ||
419 | tid); | ||
420 | #endif | ||
421 | ret = -ENOMEM; | 416 | ret = -ENOMEM; |
422 | goto err_unlock_sta; | 417 | goto err_unlock_sta; |
423 | } | 418 | } |
@@ -574,14 +569,9 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, | |||
574 | struct ieee80211_ra_tid *ra_tid; | 569 | struct ieee80211_ra_tid *ra_tid; |
575 | struct sk_buff *skb = dev_alloc_skb(0); | 570 | struct sk_buff *skb = dev_alloc_skb(0); |
576 | 571 | ||
577 | if (unlikely(!skb)) { | 572 | if (unlikely(!skb)) |
578 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
579 | if (net_ratelimit()) | ||
580 | printk(KERN_WARNING "%s: Not enough memory, " | ||
581 | "dropping start BA session", sdata->name); | ||
582 | #endif | ||
583 | return; | 573 | return; |
584 | } | 574 | |
585 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | 575 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; |
586 | memcpy(&ra_tid->ra, ra, ETH_ALEN); | 576 | memcpy(&ra_tid->ra, ra, ETH_ALEN); |
587 | ra_tid->tid = tid; | 577 | ra_tid->tid = tid; |
@@ -727,14 +717,9 @@ void ieee80211_stop_tx_ba_cb_irqsafe(struct ieee80211_vif *vif, | |||
727 | struct ieee80211_ra_tid *ra_tid; | 717 | struct ieee80211_ra_tid *ra_tid; |
728 | struct sk_buff *skb = dev_alloc_skb(0); | 718 | struct sk_buff *skb = dev_alloc_skb(0); |
729 | 719 | ||
730 | if (unlikely(!skb)) { | 720 | if (unlikely(!skb)) |
731 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
732 | if (net_ratelimit()) | ||
733 | printk(KERN_WARNING "%s: Not enough memory, " | ||
734 | "dropping stop BA session", sdata->name); | ||
735 | #endif | ||
736 | return; | 721 | return; |
737 | } | 722 | |
738 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; | 723 | ra_tid = (struct ieee80211_ra_tid *) &skb->cb; |
739 | memcpy(&ra_tid->ra, ra, ETH_ALEN); | 724 | memcpy(&ra_tid->ra, ra, ETH_ALEN); |
740 | ra_tid->tid = tid; | 725 | ra_tid->tid = tid; |
@@ -777,18 +762,14 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
777 | #ifdef CONFIG_MAC80211_HT_DEBUG | 762 | #ifdef CONFIG_MAC80211_HT_DEBUG |
778 | printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid); | 763 | printk(KERN_DEBUG "switched off addBA timer for tid %d\n", tid); |
779 | #endif | 764 | #endif |
780 | 765 | /* | |
766 | * IEEE 802.11-2007 7.3.1.14: | ||
767 | * In an ADDBA Response frame, when the Status Code field | ||
768 | * is set to 0, the Buffer Size subfield is set to a value | ||
769 | * of at least 1. | ||
770 | */ | ||
781 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) | 771 | if (le16_to_cpu(mgmt->u.action.u.addba_resp.status) |
782 | == WLAN_STATUS_SUCCESS) { | 772 | == WLAN_STATUS_SUCCESS && buf_size) { |
783 | /* | ||
784 | * IEEE 802.11-2007 7.3.1.14: | ||
785 | * In an ADDBA Response frame, when the Status Code field | ||
786 | * is set to 0, the Buffer Size subfield is set to a value | ||
787 | * of at least 1. | ||
788 | */ | ||
789 | if (!buf_size) | ||
790 | goto out; | ||
791 | |||
792 | if (test_and_set_bit(HT_AGG_STATE_RESPONSE_RECEIVED, | 773 | if (test_and_set_bit(HT_AGG_STATE_RESPONSE_RECEIVED, |
793 | &tid_tx->state)) { | 774 | &tid_tx->state)) { |
794 | /* ignore duplicate response */ | 775 | /* ignore duplicate response */ |