diff options
| -rw-r--r-- | net/mac80211/iface.c | 32 | ||||
| -rw-r--r-- | net/mac80211/rx.c | 5 |
2 files changed, 33 insertions, 4 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 7a3dbde9979..87fc012e4ab 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
| @@ -707,6 +707,7 @@ static void ieee80211_iface_work(struct work_struct *work) | |||
| 707 | container_of(work, struct ieee80211_sub_if_data, work); | 707 | container_of(work, struct ieee80211_sub_if_data, work); |
| 708 | struct ieee80211_local *local = sdata->local; | 708 | struct ieee80211_local *local = sdata->local; |
| 709 | struct sk_buff *skb; | 709 | struct sk_buff *skb; |
| 710 | struct sta_info *sta; | ||
| 710 | 711 | ||
| 711 | if (!ieee80211_sdata_running(sdata)) | 712 | if (!ieee80211_sdata_running(sdata)) |
| 712 | return; | 713 | return; |
| @@ -729,7 +730,6 @@ static void ieee80211_iface_work(struct work_struct *work) | |||
| 729 | if (ieee80211_is_action(mgmt->frame_control) && | 730 | if (ieee80211_is_action(mgmt->frame_control) && |
| 730 | mgmt->u.action.category == WLAN_CATEGORY_BACK) { | 731 | mgmt->u.action.category == WLAN_CATEGORY_BACK) { |
| 731 | int len = skb->len; | 732 | int len = skb->len; |
| 732 | struct sta_info *sta; | ||
| 733 | 733 | ||
| 734 | rcu_read_lock(); | 734 | rcu_read_lock(); |
| 735 | sta = sta_info_get(sdata, mgmt->sa); | 735 | sta = sta_info_get(sdata, mgmt->sa); |
| @@ -753,6 +753,36 @@ static void ieee80211_iface_work(struct work_struct *work) | |||
| 753 | } | 753 | } |
| 754 | } | 754 | } |
| 755 | rcu_read_unlock(); | 755 | rcu_read_unlock(); |
| 756 | } else if (ieee80211_is_data_qos(mgmt->frame_control)) { | ||
| 757 | struct ieee80211_hdr *hdr = (void *)mgmt; | ||
| 758 | /* | ||
| 759 | * So the frame isn't mgmt, but frame_control | ||
| 760 | * is at the right place anyway, of course, so | ||
| 761 | * the if statement is correct. | ||
| 762 | * | ||
| 763 | * Warn if we have other data frame types here, | ||
| 764 | * they must not get here. | ||
| 765 | */ | ||
| 766 | WARN_ON(hdr->frame_control & | ||
| 767 | cpu_to_le16(IEEE80211_STYPE_NULLFUNC)); | ||
| 768 | WARN_ON(!(hdr->seq_ctrl & | ||
| 769 | cpu_to_le16(IEEE80211_SCTL_FRAG))); | ||
| 770 | /* | ||
| 771 | * This was a fragment of a frame, received while | ||
| 772 | * a block-ack session was active. That cannot be | ||
| 773 | * right, so terminate the session. | ||
| 774 | */ | ||
| 775 | rcu_read_lock(); | ||
| 776 | sta = sta_info_get(sdata, mgmt->sa); | ||
| 777 | if (sta) { | ||
| 778 | u16 tid = *ieee80211_get_qos_ctl(hdr) & | ||
| 779 | IEEE80211_QOS_CTL_TID_MASK; | ||
| 780 | |||
| 781 | __ieee80211_stop_rx_ba_session( | ||
| 782 | sta, tid, WLAN_BACK_RECIPIENT, | ||
| 783 | WLAN_REASON_QSTA_REQUIRE_SETUP); | ||
| 784 | } | ||
| 785 | rcu_read_unlock(); | ||
| 756 | } else switch (sdata->vif.type) { | 786 | } else switch (sdata->vif.type) { |
| 757 | case NL80211_IFTYPE_STATION: | 787 | case NL80211_IFTYPE_STATION: |
| 758 | ieee80211_sta_rx_queued_mgmt(sdata, skb); | 788 | ieee80211_sta_rx_queued_mgmt(sdata, skb); |
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 435c2166e0c..b716fa2370b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
| @@ -741,9 +741,8 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx, | |||
| 741 | sc = le16_to_cpu(hdr->seq_ctrl); | 741 | sc = le16_to_cpu(hdr->seq_ctrl); |
| 742 | if (sc & IEEE80211_SCTL_FRAG) { | 742 | if (sc & IEEE80211_SCTL_FRAG) { |
| 743 | spin_unlock(&sta->lock); | 743 | spin_unlock(&sta->lock); |
| 744 | __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, | 744 | skb_queue_tail(&rx->sdata->skb_queue, skb); |
| 745 | WLAN_REASON_QSTA_REQUIRE_SETUP); | 745 | ieee80211_queue_work(&local->hw, &rx->sdata->work); |
| 746 | dev_kfree_skb(skb); | ||
| 747 | return; | 746 | return; |
| 748 | } | 747 | } |
| 749 | 748 | ||
