This adds the survey function to both mac80211 itself and to mac80211_hwsim.
For the latter driver, we simply invent some noise level.A real driver which
cannot determine the real channel noise MUST NOT report any noise, especially
not a magically conjured one :-)
Signed-off-by: Holger Schurig <holgerschurig@gmail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
        return 0;
 }
 
+static int mac80211_hwsim_get_survey(
+       struct ieee80211_hw *hw, int idx,
+       struct survey_info *survey)
+{
+       struct ieee80211_conf *conf = &hw->conf;
+
+       printk(KERN_DEBUG "%s:%s (idx=%d)\n",
+              wiphy_name(hw->wiphy), __func__, idx);
+
+       if (idx != 0)
+               return -ENOENT;
+
+       /* Current channel */
+       survey->channel = conf->channel;
+
+       /*
+        * Magically conjured noise level --- this is only ok for simulated hardware.
+        *
+        * A real driver which cannot determine the real channel noise MUST NOT
+        * report any noise, especially not a magically conjured one :-)
+        */
+       survey->filled = SURVEY_INFO_NOISE_DBM;
+       survey->noise = -92;
+
+       return 0;
+}
+
 #ifdef CONFIG_NL80211_TESTMODE
 /*
  * This section contains example code for using netlink
        .sta_notify = mac80211_hwsim_sta_notify,
        .set_tim = mac80211_hwsim_set_tim,
        .conf_tx = mac80211_hwsim_conf_tx,
+       .get_survey = mac80211_hwsim_get_survey,
        CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd)
        .ampdu_action = mac80211_hwsim_ampdu_action,
        .sw_scan_start = mac80211_hwsim_sw_scan,
 
                            struct ieee80211_vif *vif,
                            enum ieee80211_ampdu_mlme_action action,
                            struct ieee80211_sta *sta, u16 tid, u16 *ssn);
-
+       int (*get_survey)(struct ieee80211_hw *hw, int idx,
+               struct survey_info *survey);
        void (*rfkill_poll)(struct ieee80211_hw *hw);
        void (*set_coverage_class)(struct ieee80211_hw *hw, u8 coverage_class);
 #ifdef CONFIG_NL80211_TESTMODE
 
        return ret;
 }
 
+static int ieee80211_dump_survey(struct wiphy *wiphy, struct net_device *dev,
+                                int idx, struct survey_info *survey)
+{
+       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+
+       if (!local->ops->get_survey)
+               return -EOPNOTSUPP;
+
+       return drv_get_survey(local, idx, survey);
+}
+
 static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
                                 u8 *mac, struct station_info *sinfo)
 {
        .change_station = ieee80211_change_station,
        .get_station = ieee80211_get_station,
        .dump_station = ieee80211_dump_station,
+       .dump_survey = ieee80211_dump_survey,
 #ifdef CONFIG_MAC80211_MESH
        .add_mpath = ieee80211_add_mpath,
        .del_mpath = ieee80211_del_mpath,
 
        return ret;
 }
 
+static inline int drv_get_survey(struct ieee80211_local *local, int idx,
+                               struct survey_info *survey)
+{
+       int ret = -EOPNOTSUPP;
+       if (local->ops->conf_tx)
+               ret = local->ops->get_survey(&local->hw, idx, survey);
+       /* trace_drv_get_survey(local, idx, survey, ret); */
+       return ret;
+}
 
 static inline void drv_rfkill_poll(struct ieee80211_local *local)
 {