aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/iface.c32
-rw-r--r--net/mac80211/rx.c5
2 files changed, 33 insertions, 4 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 7a3dbde9979e..87fc012e4ab3 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 435c2166e0c5..b716fa2370b3 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