mac80211: manage RX BA session offload without SKB queue
authorJohannes Berg <johannes.berg@intel.com>
Tue, 30 May 2017 14:34:46 +0000 (16:34 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Thu, 8 Jun 2017 12:16:29 +0000 (14:16 +0200)
Instead of using the SKB queue with the fake pkt_type for the
offloaded RX BA session management, also handle this with the
normal aggregation state machine worker. This also makes the
use of this more reliable since it gets rid of the allocation
of the fake skb.

Combined with the previous patch, this finally allows us to
get rid of the pkt_type hack entirely, so do that as well.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/mac80211.h
net/mac80211/agg-rx.c
net/mac80211/ht.c
net/mac80211/ieee80211_i.h
net/mac80211/iface.c
net/mac80211/rx.c
net/mac80211/sta_info.h

index e01daff1e2558187ce2872c29c777417271cbfdf..b2b5419467cc123b4a2b70c2d926b4576651248d 100644 (file)
@@ -5452,6 +5452,9 @@ void ieee80211_mark_rx_ba_filtered_frames(struct ieee80211_sta *pubsta, u8 tid,
  */
 void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn);
 
+void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif, const u8 *addr,
+                                unsigned int bit);
+
 /**
  * ieee80211_start_rx_ba_session_offl - start a Rx BA session
  *
@@ -5466,8 +5469,13 @@ void ieee80211_send_bar(struct ieee80211_vif *vif, u8 *ra, u16 tid, u16 ssn);
  * @addr: station mac address
  * @tid: the rx tid
  */
-void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
-                                       const u8 *addr, u16 tid);
+static inline void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
+                                                     const u8 *addr, u16 tid)
+{
+       if (WARN_ON(tid >= IEEE80211_NUM_TIDS))
+               return;
+       ieee80211_manage_rx_ba_offl(vif, addr, tid);
+}
 
 /**
  * ieee80211_stop_rx_ba_session_offl - stop a Rx BA session
@@ -5483,8 +5491,13 @@ void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
  * @addr: station mac address
  * @tid: the rx tid
  */
-void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif,
-                                      const u8 *addr, u16 tid);
+static inline void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif,
+                                                    const u8 *addr, u16 tid)
+{
+       if (WARN_ON(tid >= IEEE80211_NUM_TIDS))
+               return;
+       ieee80211_manage_rx_ba_offl(vif, addr, tid + IEEE80211_NUM_TIDS);
+}
 
 /* Rate control API */
 
index 1b7a4daf283c5191c19eaa4f3571d316c866906a..3a0282188ad6e55f291cf7079fea304d3cebc52a 100644 (file)
@@ -449,44 +449,21 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
                                        buf_size, true, false);
 }
 
-void ieee80211_start_rx_ba_session_offl(struct ieee80211_vif *vif,
-                                       const u8 *addr, u16 tid)
+void ieee80211_manage_rx_ba_offl(struct ieee80211_vif *vif,
+                                const u8 *addr, unsigned int bit)
 {
        struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
        struct ieee80211_local *local = sdata->local;
-       struct ieee80211_rx_agg *rx_agg;
-       struct sk_buff *skb = dev_alloc_skb(0);
-
-       if (unlikely(!skb))
-               return;
-
-       rx_agg = (struct ieee80211_rx_agg *) &skb->cb;
-       memcpy(&rx_agg->addr, addr, ETH_ALEN);
-       rx_agg->tid = tid;
-
-       skb->pkt_type = IEEE80211_SDATA_QUEUE_RX_AGG_START;
-       skb_queue_tail(&sdata->skb_queue, skb);
-       ieee80211_queue_work(&local->hw, &sdata->work);
-}
-EXPORT_SYMBOL(ieee80211_start_rx_ba_session_offl);
-
-void ieee80211_stop_rx_ba_session_offl(struct ieee80211_vif *vif,
-                                      const u8 *addr, u16 tid)
-{
-       struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
-       struct ieee80211_local *local = sdata->local;
-       struct ieee80211_rx_agg *rx_agg;
-       struct sk_buff *skb = dev_alloc_skb(0);
-
-       if (unlikely(!skb))
-               return;
+       struct sta_info *sta;
 
-       rx_agg = (struct ieee80211_rx_agg *) &skb->cb;
-       memcpy(&rx_agg->addr, addr, ETH_ALEN);
-       rx_agg->tid = tid;
+       rcu_read_lock();
+       sta = sta_info_get_bss(sdata, addr);
+       if (!sta)
+               goto unlock;
 
-       skb->pkt_type = IEEE80211_SDATA_QUEUE_RX_AGG_STOP;
-       skb_queue_tail(&sdata->skb_queue, skb);
-       ieee80211_queue_work(&local->hw, &sdata->work);
+       set_bit(bit, sta->ampdu_mlme.tid_rx_manage_offl);
+       ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
+ unlock:
+       rcu_read_unlock();
 }
-EXPORT_SYMBOL(ieee80211_stop_rx_ba_session_offl);
+EXPORT_SYMBOL(ieee80211_manage_rx_ba_offl);
index 6ca5442b1e03b18aa81764089bf74c002d337690..9e71226c2d2508515f88872a6a23e4b56e48f999 100644 (file)
@@ -331,6 +331,18 @@ void ieee80211_ba_session_work(struct work_struct *work)
                                sta, tid, WLAN_BACK_RECIPIENT,
                                WLAN_REASON_UNSPECIFIED, true);
 
+               if (test_and_clear_bit(tid,
+                                      sta->ampdu_mlme.tid_rx_manage_offl))
+                       __ieee80211_start_rx_ba_session(sta, 0, 0, 0, 1, tid,
+                                                       IEEE80211_MAX_AMPDU_BUF,
+                                                       false, true);
+
+               if (test_and_clear_bit(tid + IEEE80211_NUM_TIDS,
+                                      sta->ampdu_mlme.tid_rx_manage_offl))
+                       ___ieee80211_stop_rx_ba_session(
+                               sta, tid, WLAN_BACK_RECIPIENT,
+                               0, false);
+
                spin_lock_bh(&sta->lock);
 
                tid_tx = sta->ampdu_mlme.tid_start_tx[tid];
index f24f1d7b8937e6184f46211265a01473f37ec262..392fbab73c046708b20f81ea86ed429aeb8a5c85 100644 (file)
@@ -1031,17 +1031,6 @@ ieee80211_vif_get_shift(struct ieee80211_vif *vif)
        return shift;
 }
 
-struct ieee80211_rx_agg {
-       u8 addr[ETH_ALEN];
-       u16 tid;
-};
-
-enum sdata_queue_type {
-       IEEE80211_SDATA_QUEUE_TYPE_FRAME        = 0,
-       IEEE80211_SDATA_QUEUE_RX_AGG_START      = 3,
-       IEEE80211_SDATA_QUEUE_RX_AGG_STOP       = 4,
-};
-
 enum {
        IEEE80211_RX_MSG        = 1,
        IEEE80211_TX_STATUS_MSG = 2,
index 8fae1a72e6a7c7ea4f71ec3a3beb215b987a715f..6ac0a0198d195c72ad05340d142958e735a397c8 100644 (file)
@@ -1237,7 +1237,6 @@ static void ieee80211_iface_work(struct work_struct *work)
        struct ieee80211_local *local = sdata->local;
        struct sk_buff *skb;
        struct sta_info *sta;
-       struct ieee80211_rx_agg *rx_agg;
 
        if (!ieee80211_sdata_running(sdata))
                return;
@@ -1252,28 +1251,8 @@ static void ieee80211_iface_work(struct work_struct *work)
        while ((skb = skb_dequeue(&sdata->skb_queue))) {
                struct ieee80211_mgmt *mgmt = (void *)skb->data;
 
-               if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_START) {
-                       rx_agg = (void *)&skb->cb;
-                       mutex_lock(&local->sta_mtx);
-                       sta = sta_info_get_bss(sdata, rx_agg->addr);
-                       if (sta)
-                               __ieee80211_start_rx_ba_session(sta,
-                                               0, 0, 0, 1, rx_agg->tid,
-                                               IEEE80211_MAX_AMPDU_BUF,
-                                               false, true);
-                       mutex_unlock(&local->sta_mtx);
-               } else if (skb->pkt_type == IEEE80211_SDATA_QUEUE_RX_AGG_STOP) {
-                       rx_agg = (void *)&skb->cb;
-                       mutex_lock(&local->sta_mtx);
-                       sta = sta_info_get_bss(sdata, rx_agg->addr);
-                       if (sta)
-                               __ieee80211_stop_rx_ba_session(sta,
-                                                       rx_agg->tid,
-                                                       WLAN_BACK_RECIPIENT, 0,
-                                                       false);
-                       mutex_unlock(&local->sta_mtx);
-               } else if (ieee80211_is_action(mgmt->frame_control) &&
-                          mgmt->u.action.category == WLAN_CATEGORY_BACK) {
+               if (ieee80211_is_action(mgmt->frame_control) &&
+                   mgmt->u.action.category == WLAN_CATEGORY_BACK) {
                        int len = skb->len;
 
                        mutex_lock(&local->sta_mtx);
index 1f75280ba26c78b3ad9864d0b63305cbba43f8fe..8c7d932fd09b2d6b9a0d7cd24014e1cd48b7d1ee 100644 (file)
@@ -237,7 +237,6 @@ static void ieee80211_handle_mu_mimo_mon(struct ieee80211_sub_if_data *sdata,
        if (!skb)
                return;
 
-       skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
        skb_queue_tail(&sdata->skb_queue, skb);
        ieee80211_queue_work(&sdata->local->hw, &sdata->work);
 }
@@ -1217,7 +1216,6 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,
        /* if this mpdu is fragmented - terminate rx aggregation session */
        sc = le16_to_cpu(hdr->seq_ctrl);
        if (sc & IEEE80211_SCTL_FRAG) {
-               skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
                skb_queue_tail(&rx->sdata->skb_queue, skb);
                ieee80211_queue_work(&local->hw, &rx->sdata->work);
                return;
@@ -3100,7 +3098,6 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
        return RX_QUEUED;
 
  queue:
-       rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
        skb_queue_tail(&sdata->skb_queue, rx->skb);
        ieee80211_queue_work(&local->hw, &sdata->work);
        if (rx->sta)
@@ -3246,7 +3243,6 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
        }
 
        /* queue up frame and kick off work to process it */
-       rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
        skb_queue_tail(&sdata->skb_queue, rx->skb);
        ieee80211_queue_work(&rx->local->hw, &sdata->work);
        if (rx->sta)
index cde89c6d03869553a54f2715c3742b8f8a62ed7e..3acbdfa9f649f4832f01b70360d379272cd3258b 100644 (file)
@@ -233,6 +233,8 @@ struct tid_ampdu_rx {
  *     RX timer expired until the work for it runs
  * @tid_rx_stop_requested:  bitmap indicating which BA sessions per TID the
  *     driver requested to close until the work for it runs
+ * @tid_rx_manage_offl: bitmap indicating which BA sessions were requested
+ *     to be treated as started/stopped due to offloading
  * @agg_session_valid: bitmap indicating which TID has a rx BA session open on
  * @unexpected_agg: bitmap indicating which TID already sent a delBA due to
  *     unexpected aggregation related frames outside a session
@@ -250,6 +252,7 @@ struct sta_ampdu_mlme {
        u8 tid_rx_token[IEEE80211_NUM_TIDS];
        unsigned long tid_rx_timer_expired[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
        unsigned long tid_rx_stop_requested[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
+       unsigned long tid_rx_manage_offl[BITS_TO_LONGS(2 * IEEE80211_NUM_TIDS)];
        unsigned long agg_session_valid[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
        unsigned long unexpected_agg[BITS_TO_LONGS(IEEE80211_NUM_TIDS)];
        /* tx */