]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - net/mac80211/util.c
Merge tag 'stable/for-linus-3.9-rc0-tag' of git://git.kernel.org/pub/scm/linux/kernel...
[karo-tx-linux.git] / net / mac80211 / util.c
index 7519018ff71af2844241f43697a1926f54122def..0f38f43ac62eac316434c60614694d41efed09ff 100644 (file)
@@ -739,11 +739,7 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
                                if (calc_crc)
                                        crc = crc32_be(crc, pos - 2, elen + 2);
 
-                               if (pos[3] == 1) {
-                                       /* OUI Type 1 - WPA IE */
-                                       elems->wpa = pos;
-                                       elems->wpa_len = elen;
-                               } else if (elen >= 5 && pos[3] == 2) {
+                               if (elen >= 5 && pos[3] == 2) {
                                        /* OUI Type 2 - WMM IE */
                                        if (pos[4] == 0) {
                                                elems->wmm_info = pos;
@@ -791,6 +787,12 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
                        else
                                elem_parse_failed = true;
                        break;
+               case WLAN_EID_OPMODE_NOTIF:
+                       if (elen > 0)
+                               elems->opmode_notif = pos;
+                       else
+                               elem_parse_failed = true;
+                       break;
                case WLAN_EID_MESH_ID:
                        elems->mesh_id = pos;
                        elems->mesh_id_len = elen;
@@ -805,6 +807,10 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
                        elems->peering = pos;
                        elems->peering_len = elen;
                        break;
+               case WLAN_EID_MESH_AWAKE_WINDOW:
+                       if (elen >= 2)
+                               elems->awake_window = (void *)pos;
+                       break;
                case WLAN_EID_PREQ:
                        elems->preq = pos;
                        elems->preq_len = elen;
@@ -1029,8 +1035,9 @@ u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
 
 void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
                         u16 transaction, u16 auth_alg, u16 status,
-                        u8 *extra, size_t extra_len, const u8 *da,
-                        const u8 *bssid, const u8 *key, u8 key_len, u8 key_idx)
+                        const u8 *extra, size_t extra_len, const u8 *da,
+                        const u8 *bssid, const u8 *key, u8 key_len, u8 key_idx,
+                        u32 tx_flags)
 {
        struct ieee80211_local *local = sdata->local;
        struct sk_buff *skb;
@@ -1063,7 +1070,8 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
                WARN_ON(err);
        }
 
-       IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
+       IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
+                                       tx_flags;
        ieee80211_tx_skb(sdata, skb);
 }
 
@@ -1277,7 +1285,7 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
 void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
                              const u8 *ssid, size_t ssid_len,
                              const u8 *ie, size_t ie_len,
-                             u32 ratemask, bool directed, bool no_cck,
+                             u32 ratemask, bool directed, u32 tx_flags,
                              struct ieee80211_channel *channel, bool scan)
 {
        struct sk_buff *skb;
@@ -1286,9 +1294,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
                                        ssid, ssid_len,
                                        ie, ie_len, directed);
        if (skb) {
-               if (no_cck)
-                       IEEE80211_SKB_CB(skb)->flags |=
-                               IEEE80211_TX_CTL_NO_CCK_RATE;
+               IEEE80211_SKB_CB(skb)->flags |= tx_flags;
                if (scan)
                        ieee80211_tx_skb_tid_band(sdata, skb, 7, channel->band);
                else
@@ -1538,6 +1544,10 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                        changed |= BSS_CHANGED_ASSOC |
                                   BSS_CHANGED_ARP_FILTER |
                                   BSS_CHANGED_PS;
+
+                       if (sdata->u.mgd.dtim_period)
+                               changed |= BSS_CHANGED_DTIM_PERIOD;
+
                        mutex_lock(&sdata->u.mgd.mtx);
                        ieee80211_bss_info_change_notify(sdata, changed);
                        mutex_unlock(&sdata->u.mgd.mtx);
@@ -1937,7 +1947,7 @@ u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
 }
 
 void ieee80211_ht_oper_to_chandef(struct ieee80211_channel *control_chan,
-                                 struct ieee80211_ht_operation *ht_oper,
+                                 const struct ieee80211_ht_operation *ht_oper,
                                  struct cfg80211_chan_def *chandef)
 {
        enum nl80211_channel_type channel_type;
@@ -2125,3 +2135,49 @@ u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
 
        return ts;
 }
+
+void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
+{
+       struct ieee80211_sub_if_data *sdata;
+
+       mutex_lock(&local->iflist_mtx);
+       list_for_each_entry(sdata, &local->interfaces, list) {
+               cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
+
+               if (sdata->wdev.cac_started) {
+                       ieee80211_vif_release_channel(sdata);
+                       cfg80211_cac_event(sdata->dev,
+                                          NL80211_RADAR_CAC_ABORTED,
+                                          GFP_KERNEL);
+               }
+       }
+       mutex_unlock(&local->iflist_mtx);
+}
+
+void ieee80211_dfs_radar_detected_work(struct work_struct *work)
+{
+       struct ieee80211_local *local =
+               container_of(work, struct ieee80211_local, radar_detected_work);
+       struct cfg80211_chan_def chandef;
+
+       ieee80211_dfs_cac_cancel(local);
+
+       if (local->use_chanctx)
+               /* currently not handled */
+               WARN_ON(1);
+       else {
+               cfg80211_chandef_create(&chandef, local->hw.conf.channel,
+                                       local->hw.conf.channel_type);
+               cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL);
+       }
+}
+
+void ieee80211_radar_detected(struct ieee80211_hw *hw)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+
+       trace_api_radar_detected(local);
+
+       ieee80211_queue_work(hw, &local->radar_detected_work);
+}
+EXPORT_SYMBOL(ieee80211_radar_detected);