sctp: fix possible seqlock seadlock in sctp_packet_transmit()
[firefly-linux-kernel-4.4.55.git] / net / mac80211 / status.c
index 07d99578a2b1406aecd72e38934a05ea82d09d9e..9e78206bd9bb899025a2f996688a16ab173a1cdf 100644 (file)
@@ -180,6 +180,9 @@ static void ieee80211_frame_acked(struct sta_info *sta, struct sk_buff *skb)
        struct ieee80211_local *local = sta->local;
        struct ieee80211_sub_if_data *sdata = sta->sdata;
 
+       if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
+               sta->last_rx = jiffies;
+
        if (ieee80211_is_data_qos(mgmt->frame_control)) {
                struct ieee80211_hdr *hdr = (void *) skb->data;
                u8 *qc = ieee80211_get_qos_ctl(hdr);
@@ -335,7 +338,8 @@ static void ieee80211_report_used_skb(struct ieee80211_local *local,
        if (dropped)
                acked = false;
 
-       if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) {
+       if (info->flags & (IEEE80211_TX_INTFL_NL80211_FRAME_TX |
+                          IEEE80211_TX_INTFL_MLME_CONN_TX)) {
                struct ieee80211_sub_if_data *sdata = NULL;
                struct ieee80211_sub_if_data *iter_sdata;
                u64 cookie = (unsigned long)skb;
@@ -357,10 +361,13 @@ static void ieee80211_report_used_skb(struct ieee80211_local *local,
                        sdata = rcu_dereference(local->p2p_sdata);
                }
 
-               if (!sdata)
+               if (!sdata) {
                        skb->dev = NULL;
-               else if (ieee80211_is_nullfunc(hdr->frame_control) ||
-                        ieee80211_is_qos_nullfunc(hdr->frame_control)) {
+               } else if (info->flags & IEEE80211_TX_INTFL_MLME_CONN_TX) {
+                       ieee80211_mgd_conn_tx_status(sdata, hdr->frame_control,
+                                                    acked);
+               } else if (ieee80211_is_nullfunc(hdr->frame_control) ||
+                          ieee80211_is_qos_nullfunc(hdr->frame_control)) {
                        cfg80211_probe_status(sdata->dev, hdr->addr1,
                                              cookie, acked, GFP_ATOMIC);
                } else {
@@ -468,6 +475,13 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
                        return;
                }
 
+               /* mesh Peer Service Period support */
+               if (ieee80211_vif_is_mesh(&sta->sdata->vif) &&
+                   ieee80211_is_data_qos(fc))
+                       ieee80211_mpsp_trigger_process(
+                                       ieee80211_get_qos_ctl(hdr),
+                                       sta, true, acked);
+
                if ((local->hw.flags & IEEE80211_HW_HAS_RATE_CONTROL) &&
                    (rates_idx != -1))
                        sta->last_tx_rate = info->status.rates[rates_idx];
@@ -502,11 +516,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
                                       IEEE80211_BAR_CTRL_TID_INFO_MASK) >>
                                      IEEE80211_BAR_CTRL_TID_INFO_SHIFT;
 
-                               if (local->hw.flags &
-                                   IEEE80211_HW_TEARDOWN_AGGR_ON_BAR_FAIL)
-                                       ieee80211_stop_tx_ba_session(&sta->sta, tid);
-                               else
-                                       ieee80211_set_bar_pending(sta, tid, ssn);
+                               ieee80211_set_bar_pending(sta, tid, ssn);
                        }
                }