mac80211: uapsd_queues is in QoS IE order
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Tue, 18 Oct 2016 20:12:12 +0000 (23:12 +0300)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 19 Oct 2016 10:13:54 +0000 (12:13 +0200)
The uapsd_queue field is in QoS IE order and not in
IEEE80211_AC_*'s order.
This means that mac80211 would get confused between
BK and BE which is certainly not such a big deal but
needs to be fixed.

Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
include/net/cfg80211.h
include/net/mac80211.h
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c
net/mac80211/rx.c
net/mac80211/sta_info.c
net/mac80211/util.c

index 5000ec758eb3d3fa3b418749a2c8ade6d0cf753d..10a26f0fbafeafb0d2fb8104f536b90b9b794813 100644 (file)
@@ -4574,7 +4574,8 @@ void cfg80211_auth_timeout(struct net_device *dev, const u8 *addr);
  *     moves to cfg80211 in this call
  * @buf: authentication frame (header + body)
  * @len: length of the frame data
- * @uapsd_queues: bitmap of ACs configured to uapsd. -1 if n/a.
+ * @uapsd_queues: bitmap of queues configured for uapsd. Same format
+ *     as the AC bitmap in the QoS info field
  *
  * After being asked to associate via cfg80211_ops::assoc() the driver must
  * call either this function or cfg80211_auth_timeout().
index a1a27021f45279859534bfe4721bb6c85a7635f8..b9b24abd9103c21c8d7fa3f78b2daf9a443040a0 100644 (file)
@@ -1745,7 +1745,8 @@ struct ieee80211_sta_rates {
  * @drv_priv: data area for driver use, will always be aligned to
  *     sizeof(void *), size is determined in hw information.
  * @uapsd_queues: bitmap of queues configured for uapsd. Only valid
- *     if wme is supported.
+ *     if wme is supported. The bits order is like in
+ *     IEEE80211_WMM_IE_STA_QOSINFO_AC_*.
  * @max_sp: max Service Period. Only valid if wme is supported.
  * @bandwidth: current bandwidth the station can receive with
  * @rx_nss: in HT/VHT, the maximum number of spatial streams the
index 42d194a04e1acea378a3cc18817995124795e8cd..b4e2b6cf4099e0715a78da2da640856ad330a217 100644 (file)
@@ -84,6 +84,8 @@ struct ieee80211_local;
 #define IEEE80211_DEFAULT_MAX_SP_LEN           \
        IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL
 
+extern const u8 ieee80211_ac_to_qos_mask[IEEE80211_NUM_ACS];
+
 #define IEEE80211_DEAUTH_FRAME_LEN     (24 /* hdr */ + 2 /* reason */)
 
 #define IEEE80211_MAX_NAN_INSTANCE_ID 255
index 7486f2dab4ba70ade0b2faf48ffa7f3880ac2ad4..c8d3a9b02fb6f405d4178b1b9fae43d26d44f5fc 100644 (file)
@@ -3193,7 +3193,7 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata,
                uapsd_queues = 0;
                for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
                        if (sdata->tx_conf[ac].uapsd)
-                               uapsd_queues |= BIT(ac);
+                               uapsd_queues |= ieee80211_ac_to_qos_mask[ac];
        }
 
        cfg80211_rx_assoc_resp(sdata->dev, bss, (u8 *)mgmt, len, uapsd_queues);
index 837d56261bb26c3466d157fe0c069604c41f8daa..21a8947651e1577ef035320e3ad6762528090ae6 100644 (file)
@@ -1401,7 +1401,8 @@ void ieee80211_sta_uapsd_trigger(struct ieee80211_sta *pubsta, u8 tid)
         * enabled queues, but for now we only implement uAPSD w/o
         * TSPEC changes to the ACs, so they're always the same.
         */
-       if (!(sta->sta.uapsd_queues & BIT(ac)) && tid != IEEE80211_NUM_TIDS)
+       if (!(sta->sta.uapsd_queues & ieee80211_ac_to_qos_mask[ac]) &&
+           tid != IEEE80211_NUM_TIDS)
                return;
 
        /* if we are in a service period, do nothing */
index ab91e1e1b8eceaab8fc90509e4aeeb0a8c722d10..236d47e76ced4f625039f063258deee20f6536ca 100644 (file)
@@ -709,7 +709,7 @@ static void __sta_info_recalc_tim(struct sta_info *sta, bool ignore_pending)
        for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
                unsigned long tids;
 
-               if (ignore_for_tim & BIT(ac))
+               if (ignore_for_tim & ieee80211_ac_to_qos_mask[ac])
                        continue;
 
                indicate_tim |= !skb_queue_empty(&sta->tx_filtered[ac]) ||
@@ -1389,7 +1389,7 @@ ieee80211_sta_ps_more_data(struct sta_info *sta, u8 ignored_acs,
                return true;
 
        for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
-               if (ignored_acs & BIT(ac))
+               if (ignored_acs & ieee80211_ac_to_qos_mask[ac])
                        continue;
 
                if (!skb_queue_empty(&sta->tx_filtered[ac]) ||
@@ -1414,7 +1414,7 @@ ieee80211_sta_ps_get_frames(struct sta_info *sta, int n_frames, u8 ignored_acs,
        for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
                unsigned long tids;
 
-               if (ignored_acs & BIT(ac))
+               if (ignored_acs & ieee80211_ac_to_qos_mask[ac])
                        continue;
 
                tids = ieee80211_tids_for_ac(ac);
@@ -1482,7 +1482,7 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
                        BIT(find_highest_prio_tid(driver_release_tids));
 
        if (skb_queue_empty(&frames) && !driver_release_tids) {
-               int tid;
+               int tid, ac;
 
                /*
                 * For PS-Poll, this can only happen due to a race condition
@@ -1500,7 +1500,10 @@ ieee80211_sta_ps_deliver_response(struct sta_info *sta,
                 */
 
                /* This will evaluate to 1, 3, 5 or 7. */
-               tid = 7 - ((ffs(~ignored_acs) - 1) << 1);
+               for (ac = IEEE80211_AC_VO; ac < IEEE80211_NUM_ACS; ac++)
+                       if (ignored_acs & BIT(ac))
+                               continue;
+               tid = 7 - 2 * ac;
 
                ieee80211_send_null_response(sta, tid, reason, true, false);
        } else if (!driver_release_tids) {
index 031273a61d273291886e4db2070e833b480ee8f6..7f24bdc68f71b38bd9224981a2c506acda811efe 100644 (file)
@@ -3452,3 +3452,10 @@ void ieee80211_txq_get_depth(struct ieee80211_txq *txq,
                *byte_cnt = txqi->tin.backlog_bytes + frag_bytes;
 }
 EXPORT_SYMBOL(ieee80211_txq_get_depth);
+
+const u8 ieee80211_ac_to_qos_mask[IEEE80211_NUM_ACS] = {
+       IEEE80211_WMM_IE_STA_QOSINFO_AC_VO,
+       IEEE80211_WMM_IE_STA_QOSINFO_AC_VI,
+       IEEE80211_WMM_IE_STA_QOSINFO_AC_BE,
+       IEEE80211_WMM_IE_STA_QOSINFO_AC_BK
+};