]> Pileus Git - ~andy/linux/blobdiff - net/mac80211/util.c
Merge branch 'for-davem' of git://git.kernel.org/pub/scm/linux/kernel/git/linville...
[~andy/linux] / net / mac80211 / util.c
index 556647a910acc8ea96d7d6d2e1a4a56e063a2c55..5bfb80cba634496ed67025aed8ab70f17c0ca258 100644 (file)
@@ -1018,7 +1018,8 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
 struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
                                          u8 *dst,
                                          const u8 *ssid, size_t ssid_len,
-                                         const u8 *ie, size_t ie_len)
+                                         const u8 *ie, size_t ie_len,
+                                         bool directed)
 {
        struct ieee80211_local *local = sdata->local;
        struct sk_buff *skb;
@@ -1035,8 +1036,16 @@ struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
                return NULL;
        }
 
-       chan = ieee80211_frequency_to_channel(
-               local->hw.conf.channel->center_freq);
+       /*
+        * Do not send DS Channel parameter for directed probe requests
+        * in order to maximize the chance that we get a response.  Some
+        * badly-behaved APs don't respond when this parameter is included.
+        */
+       if (directed)
+               chan = 0;
+       else
+               chan = ieee80211_frequency_to_channel(
+                       local->hw.conf.channel->center_freq);
 
        buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len,
                                           local->hw.conf.channel->band,
@@ -1062,11 +1071,13 @@ 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)
+                             const u8 *ie, size_t ie_len,
+                             bool directed)
 {
        struct sk_buff *skb;
 
-       skb = ieee80211_build_probe_req(sdata, dst, ssid, ssid_len, ie, ie_len);
+       skb = ieee80211_build_probe_req(sdata, dst, ssid, ssid_len, ie, ie_len,
+                                       directed);
        if (skb)
                ieee80211_tx_skb(sdata, skb);
 }
@@ -1125,9 +1136,27 @@ int ieee80211_reconfig(struct ieee80211_local *local)
        struct sta_info *sta;
        int res;
 
+#ifdef CONFIG_PM
        if (local->suspended)
                local->resuming = true;
 
+       if (local->wowlan) {
+               local->wowlan = false;
+               res = drv_resume(local);
+               if (res < 0) {
+                       local->resuming = false;
+                       return res;
+               }
+               if (res == 0)
+                       goto wake_up;
+               WARN_ON(res > 1);
+               /*
+                * res is 1, which means the driver requested
+                * to go through a regular reset on wakeup.
+                */
+       }
+#endif
+
        /* restart hardware */
        if (local->open_count) {
                /*
@@ -1258,6 +1287,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                if (ieee80211_sdata_running(sdata))
                        ieee80211_enable_keys(sdata);
 
+#ifdef CONFIG_PM
+ wake_up:
+#endif
        ieee80211_wake_queues_by_reason(hw,
                        IEEE80211_QUEUE_STOP_REASON_SUSPEND);
 
@@ -1290,7 +1322,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                }
        }
 
-       add_timer(&local->sta_cleanup);
+       mod_timer(&local->sta_cleanup, jiffies + 1);
 
        mutex_lock(&local->sta_mtx);
        list_for_each_entry(sta, &local->sta_list, list)
@@ -1302,6 +1334,33 @@ int ieee80211_reconfig(struct ieee80211_local *local)
        return 0;
 }
 
+void ieee80211_resume_disconnect(struct ieee80211_vif *vif)
+{
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_local *local;
+       struct ieee80211_key *key;
+
+       if (WARN_ON(!vif))
+               return;
+
+       sdata = vif_to_sdata(vif);
+       local = sdata->local;
+
+       if (WARN_ON(!local->resuming))
+               return;
+
+       if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
+               return;
+
+       sdata->flags |= IEEE80211_SDATA_DISCONNECT_RESUME;
+
+       mutex_lock(&local->key_mtx);
+       list_for_each_entry(key, &sdata->key_list, list)
+               key->flags |= KEY_FLAG_TAINTED;
+       mutex_unlock(&local->key_mtx);
+}
+EXPORT_SYMBOL_GPL(ieee80211_resume_disconnect);
+
 static int check_mgd_smps(struct ieee80211_if_managed *ifmgd,
                          enum ieee80211_smps_mode *smps_mode)
 {
@@ -1418,3 +1477,43 @@ size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset)
 
        return pos;
 }
+
+static void _ieee80211_enable_rssi_reports(struct ieee80211_sub_if_data *sdata,
+                                           int rssi_min_thold,
+                                           int rssi_max_thold)
+{
+       trace_api_enable_rssi_reports(sdata, rssi_min_thold, rssi_max_thold);
+
+       if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
+               return;
+
+       /*
+        * Scale up threshold values before storing it, as the RSSI averaging
+        * algorithm uses a scaled up value as well. Change this scaling
+        * factor if the RSSI averaging algorithm changes.
+        */
+       sdata->u.mgd.rssi_min_thold = rssi_min_thold*16;
+       sdata->u.mgd.rssi_max_thold = rssi_max_thold*16;
+}
+
+void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif,
+                                   int rssi_min_thold,
+                                   int rssi_max_thold)
+{
+       struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+
+       WARN_ON(rssi_min_thold == rssi_max_thold ||
+               rssi_min_thold > rssi_max_thold);
+
+       _ieee80211_enable_rssi_reports(sdata, rssi_min_thold,
+                                      rssi_max_thold);
+}
+EXPORT_SYMBOL(ieee80211_enable_rssi_reports);
+
+void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif)
+{
+       struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+
+       _ieee80211_enable_rssi_reports(sdata, 0, 0);
+}
+EXPORT_SYMBOL(ieee80211_disable_rssi_reports);