mac80211: Support ht-cap over-rides.
[profile/ivi/kernel-adaptation-intel-automotive.git] / net / mac80211 / work.c
index 94472eb..6884a2d 100644 (file)
@@ -94,7 +94,8 @@ static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len,
 
 /* frame sending functions */
 
-static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
+static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata,
+                               struct sk_buff *skb, const u8 *ht_info_ie,
                                struct ieee80211_supported_band *sband,
                                struct ieee80211_channel *channel,
                                enum ieee80211_smps_mode smps)
@@ -102,8 +103,10 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
        struct ieee80211_ht_info *ht_info;
        u8 *pos;
        u32 flags = channel->flags;
-       u16 cap = sband->ht_cap.cap;
-       __le16 tmp;
+       u16 cap;
+       struct ieee80211_sta_ht_cap ht_cap;
+
+       BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap));
 
        if (!sband->ht_cap.ht_supported)
                return;
@@ -114,9 +117,13 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
        if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info))
                return;
 
+       memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap));
+       ieee80211_apply_htcap_overrides(sdata, &ht_cap);
+
        ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2);
 
        /* determine capability flags */
+       cap = ht_cap.cap;
 
        switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
        case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
@@ -154,34 +161,8 @@ static void ieee80211_add_ht_ie(struct sk_buff *skb, const u8 *ht_info_ie,
        }
 
        /* reserve and fill IE */
-
        pos = skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2);
-       *pos++ = WLAN_EID_HT_CAPABILITY;
-       *pos++ = sizeof(struct ieee80211_ht_cap);
-       memset(pos, 0, sizeof(struct ieee80211_ht_cap));
-
-       /* capability flags */
-       tmp = cpu_to_le16(cap);
-       memcpy(pos, &tmp, sizeof(u16));
-       pos += sizeof(u16);
-
-       /* AMPDU parameters */
-       *pos++ = sband->ht_cap.ampdu_factor |
-                (sband->ht_cap.ampdu_density <<
-                       IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
-
-       /* MCS set */
-       memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
-       pos += sizeof(sband->ht_cap.mcs);
-
-       /* extended capabilities */
-       pos += sizeof(__le16);
-
-       /* BF capabilities */
-       pos += sizeof(__le32);
-
-       /* antenna selection */
-       pos += sizeof(u8);
+       ieee80211_ie_build_ht_cap(pos, &ht_cap, cap);
 }
 
 static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
@@ -356,7 +337,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata,
 
        if (wk->assoc.use_11n && wk->assoc.wmm_used &&
            local->hw.queues >= 4)
-               ieee80211_add_ht_ie(skb, wk->assoc.ht_information_ie,
+               ieee80211_add_ht_ie(sdata, skb, wk->assoc.ht_information_ie,
                                    sband, wk->chan, wk->assoc.smps);
 
        /* if present, add any custom non-vendor IEs that go after HT */
@@ -969,10 +950,9 @@ static void ieee80211_work_work(struct work_struct *work)
                }
 
                if (!started && !local->tmp_channel) {
-                       bool on_oper_chan;
-                       bool tmp_chan_changed = false;
-                       bool on_oper_chan2;
+                       bool on_oper_chan, on_oper_chan2;
                        enum nl80211_channel_type wk_ct;
+
                        on_oper_chan = ieee80211_cfg_on_oper_channel(local);
 
                        /* Work with existing channel type if possible. */
@@ -981,11 +961,6 @@ static void ieee80211_work_work(struct work_struct *work)
                                wk_ct = ieee80211_calc_ct(wk->chan_type,
                                                local->hw.conf.channel_type);
 
-                       if (local->tmp_channel)
-                               if ((local->tmp_channel != wk->chan) ||
-                                   (local->tmp_channel_type != wk_ct))
-                                       tmp_chan_changed = true;
-
                        local->tmp_channel = wk->chan;
                        local->tmp_channel_type = wk_ct;
                        /*
@@ -1008,12 +983,7 @@ static void ieee80211_work_work(struct work_struct *work)
                                                                    true,
                                                                    false);
                                }
-                       } else if (tmp_chan_changed)
-                               /* Still off-channel, but on some other
-                                * channel, so update hardware.
-                                * PS should already be off-channel.
-                                */
-                               ieee80211_hw_config(local, 0);
+                       }
 
                        started = true;
                        wk->timeout = jiffies;
@@ -1084,14 +1054,13 @@ static void ieee80211_work_work(struct work_struct *work)
                        continue;
                if (wk->chan != local->tmp_channel)
                        continue;
-               if (ieee80211_work_ct_coexists(wk->chan_type,
-                                              local->tmp_channel_type))
+               if (!ieee80211_work_ct_coexists(wk->chan_type,
+                                               local->tmp_channel_type))
                        continue;
                remain_off_channel = true;
        }
 
        if (!remain_off_channel && local->tmp_channel) {
-               bool on_oper_chan = ieee80211_cfg_on_oper_channel(local);
                local->tmp_channel = NULL;
                /* If tmp_channel wasn't operating channel, then
                 * we need to go back on-channel.
@@ -1101,7 +1070,7 @@ static void ieee80211_work_work(struct work_struct *work)
                 * we still need to do a hardware config.  Currently,
                 * we cannot be here while scanning, however.
                 */
-               if (ieee80211_cfg_on_oper_channel(local) && !on_oper_chan)
+               if (!ieee80211_cfg_on_oper_channel(local))
                        ieee80211_hw_config(local, 0);
 
                /* At the least, we need to disable offchannel_ps,