diff options
Diffstat (limited to 'drivers/net/wireless/mac80211_hwsim.c')
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 96 |
1 files changed, 82 insertions, 14 deletions
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 7cd5f56662fc..6f8cb3ee6fed 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -291,7 +291,8 @@ struct mac80211_hwsim_data { | |||
291 | struct ieee80211_channel *channel; | 291 | struct ieee80211_channel *channel; |
292 | unsigned long beacon_int; /* in jiffies unit */ | 292 | unsigned long beacon_int; /* in jiffies unit */ |
293 | unsigned int rx_filter; | 293 | unsigned int rx_filter; |
294 | bool started, idle; | 294 | bool started, idle, scanning; |
295 | struct mutex mutex; | ||
295 | struct timer_list beacon_timer; | 296 | struct timer_list beacon_timer; |
296 | enum ps_mode { | 297 | enum ps_mode { |
297 | PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL | 298 | PS_DISABLED, PS_ENABLED, PS_AUTO_POLL, PS_MANUAL_POLL |
@@ -651,17 +652,17 @@ static void mac80211_hwsim_beacon(unsigned long arg) | |||
651 | add_timer(&data->beacon_timer); | 652 | add_timer(&data->beacon_timer); |
652 | } | 653 | } |
653 | 654 | ||
655 | static const char *hwsim_chantypes[] = { | ||
656 | [NL80211_CHAN_NO_HT] = "noht", | ||
657 | [NL80211_CHAN_HT20] = "ht20", | ||
658 | [NL80211_CHAN_HT40MINUS] = "ht40-", | ||
659 | [NL80211_CHAN_HT40PLUS] = "ht40+", | ||
660 | }; | ||
654 | 661 | ||
655 | static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) | 662 | static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) |
656 | { | 663 | { |
657 | struct mac80211_hwsim_data *data = hw->priv; | 664 | struct mac80211_hwsim_data *data = hw->priv; |
658 | struct ieee80211_conf *conf = &hw->conf; | 665 | struct ieee80211_conf *conf = &hw->conf; |
659 | static const char *chantypes[4] = { | ||
660 | [NL80211_CHAN_NO_HT] = "noht", | ||
661 | [NL80211_CHAN_HT20] = "ht20", | ||
662 | [NL80211_CHAN_HT40MINUS] = "ht40-", | ||
663 | [NL80211_CHAN_HT40PLUS] = "ht40+", | ||
664 | }; | ||
665 | static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = { | 666 | static const char *smps_modes[IEEE80211_SMPS_NUM_MODES] = { |
666 | [IEEE80211_SMPS_AUTOMATIC] = "auto", | 667 | [IEEE80211_SMPS_AUTOMATIC] = "auto", |
667 | [IEEE80211_SMPS_OFF] = "off", | 668 | [IEEE80211_SMPS_OFF] = "off", |
@@ -672,7 +673,7 @@ static int mac80211_hwsim_config(struct ieee80211_hw *hw, u32 changed) | |||
672 | printk(KERN_DEBUG "%s:%s (freq=%d/%s idle=%d ps=%d smps=%s)\n", | 673 | printk(KERN_DEBUG "%s:%s (freq=%d/%s idle=%d ps=%d smps=%s)\n", |
673 | wiphy_name(hw->wiphy), __func__, | 674 | wiphy_name(hw->wiphy), __func__, |
674 | conf->channel->center_freq, | 675 | conf->channel->center_freq, |
675 | chantypes[conf->channel_type], | 676 | hwsim_chantypes[conf->channel_type], |
676 | !!(conf->flags & IEEE80211_CONF_IDLE), | 677 | !!(conf->flags & IEEE80211_CONF_IDLE), |
677 | !!(conf->flags & IEEE80211_CONF_PS), | 678 | !!(conf->flags & IEEE80211_CONF_PS), |
678 | smps_modes[conf->smps_mode]); | 679 | smps_modes[conf->smps_mode]); |
@@ -760,9 +761,10 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, | |||
760 | } | 761 | } |
761 | 762 | ||
762 | if (changed & BSS_CHANGED_HT) { | 763 | if (changed & BSS_CHANGED_HT) { |
763 | printk(KERN_DEBUG " %s: HT: op_mode=0x%x\n", | 764 | printk(KERN_DEBUG " %s: HT: op_mode=0x%x, chantype=%s\n", |
764 | wiphy_name(hw->wiphy), | 765 | wiphy_name(hw->wiphy), |
765 | info->ht_operation_mode); | 766 | info->ht_operation_mode, |
767 | hwsim_chantypes[info->channel_type]); | ||
766 | } | 768 | } |
767 | 769 | ||
768 | if (changed & BSS_CHANGED_BASIC_RATES) { | 770 | if (changed & BSS_CHANGED_BASIC_RATES) { |
@@ -829,6 +831,33 @@ static int mac80211_hwsim_conf_tx( | |||
829 | return 0; | 831 | return 0; |
830 | } | 832 | } |
831 | 833 | ||
834 | static int mac80211_hwsim_get_survey( | ||
835 | struct ieee80211_hw *hw, int idx, | ||
836 | struct survey_info *survey) | ||
837 | { | ||
838 | struct ieee80211_conf *conf = &hw->conf; | ||
839 | |||
840 | printk(KERN_DEBUG "%s:%s (idx=%d)\n", | ||
841 | wiphy_name(hw->wiphy), __func__, idx); | ||
842 | |||
843 | if (idx != 0) | ||
844 | return -ENOENT; | ||
845 | |||
846 | /* Current channel */ | ||
847 | survey->channel = conf->channel; | ||
848 | |||
849 | /* | ||
850 | * Magically conjured noise level --- this is only ok for simulated hardware. | ||
851 | * | ||
852 | * A real driver which cannot determine the real channel noise MUST NOT | ||
853 | * report any noise, especially not a magically conjured one :-) | ||
854 | */ | ||
855 | survey->filled = SURVEY_INFO_NOISE_DBM; | ||
856 | survey->noise = -92; | ||
857 | |||
858 | return 0; | ||
859 | } | ||
860 | |||
832 | #ifdef CONFIG_NL80211_TESTMODE | 861 | #ifdef CONFIG_NL80211_TESTMODE |
833 | /* | 862 | /* |
834 | * This section contains example code for using netlink | 863 | * This section contains example code for using netlink |
@@ -946,6 +975,7 @@ static void hw_scan_done(struct work_struct *work) | |||
946 | } | 975 | } |
947 | 976 | ||
948 | static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, | 977 | static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, |
978 | struct ieee80211_vif *vif, | ||
949 | struct cfg80211_scan_request *req) | 979 | struct cfg80211_scan_request *req) |
950 | { | 980 | { |
951 | struct hw_scan_done *hsd = kzalloc(sizeof(*hsd), GFP_KERNEL); | 981 | struct hw_scan_done *hsd = kzalloc(sizeof(*hsd), GFP_KERNEL); |
@@ -957,9 +987,9 @@ static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, | |||
957 | hsd->hw = hw; | 987 | hsd->hw = hw; |
958 | INIT_DELAYED_WORK(&hsd->w, hw_scan_done); | 988 | INIT_DELAYED_WORK(&hsd->w, hw_scan_done); |
959 | 989 | ||
960 | printk(KERN_DEBUG "hwsim scan request\n"); | 990 | printk(KERN_DEBUG "hwsim hw_scan request\n"); |
961 | for (i = 0; i < req->n_channels; i++) | 991 | for (i = 0; i < req->n_channels; i++) |
962 | printk(KERN_DEBUG "hwsim scan freq %d\n", | 992 | printk(KERN_DEBUG "hwsim hw_scan freq %d\n", |
963 | req->channels[i]->center_freq); | 993 | req->channels[i]->center_freq); |
964 | 994 | ||
965 | ieee80211_queue_delayed_work(hw, &hsd->w, 2 * HZ); | 995 | ieee80211_queue_delayed_work(hw, &hsd->w, 2 * HZ); |
@@ -967,6 +997,36 @@ static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, | |||
967 | return 0; | 997 | return 0; |
968 | } | 998 | } |
969 | 999 | ||
1000 | static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw) | ||
1001 | { | ||
1002 | struct mac80211_hwsim_data *hwsim = hw->priv; | ||
1003 | |||
1004 | mutex_lock(&hwsim->mutex); | ||
1005 | |||
1006 | if (hwsim->scanning) { | ||
1007 | printk(KERN_DEBUG "two hwsim sw_scans detected!\n"); | ||
1008 | goto out; | ||
1009 | } | ||
1010 | |||
1011 | printk(KERN_DEBUG "hwsim sw_scan request, prepping stuff\n"); | ||
1012 | hwsim->scanning = true; | ||
1013 | |||
1014 | out: | ||
1015 | mutex_unlock(&hwsim->mutex); | ||
1016 | } | ||
1017 | |||
1018 | static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw) | ||
1019 | { | ||
1020 | struct mac80211_hwsim_data *hwsim = hw->priv; | ||
1021 | |||
1022 | mutex_lock(&hwsim->mutex); | ||
1023 | |||
1024 | printk(KERN_DEBUG "hwsim sw_scan_complete\n"); | ||
1025 | hwsim->scanning = false; | ||
1026 | |||
1027 | mutex_unlock(&hwsim->mutex); | ||
1028 | } | ||
1029 | |||
970 | static struct ieee80211_ops mac80211_hwsim_ops = | 1030 | static struct ieee80211_ops mac80211_hwsim_ops = |
971 | { | 1031 | { |
972 | .tx = mac80211_hwsim_tx, | 1032 | .tx = mac80211_hwsim_tx, |
@@ -982,8 +1042,11 @@ static struct ieee80211_ops mac80211_hwsim_ops = | |||
982 | .sta_notify = mac80211_hwsim_sta_notify, | 1042 | .sta_notify = mac80211_hwsim_sta_notify, |
983 | .set_tim = mac80211_hwsim_set_tim, | 1043 | .set_tim = mac80211_hwsim_set_tim, |
984 | .conf_tx = mac80211_hwsim_conf_tx, | 1044 | .conf_tx = mac80211_hwsim_conf_tx, |
1045 | .get_survey = mac80211_hwsim_get_survey, | ||
985 | CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) | 1046 | CFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd) |
986 | .ampdu_action = mac80211_hwsim_ampdu_action, | 1047 | .ampdu_action = mac80211_hwsim_ampdu_action, |
1048 | .sw_scan_start = mac80211_hwsim_sw_scan, | ||
1049 | .sw_scan_complete = mac80211_hwsim_sw_scan_complete, | ||
987 | .flush = mac80211_hwsim_flush, | 1050 | .flush = mac80211_hwsim_flush, |
988 | }; | 1051 | }; |
989 | 1052 | ||
@@ -1179,8 +1242,11 @@ static int __init init_mac80211_hwsim(void) | |||
1179 | if (radios < 1 || radios > 100) | 1242 | if (radios < 1 || radios > 100) |
1180 | return -EINVAL; | 1243 | return -EINVAL; |
1181 | 1244 | ||
1182 | if (fake_hw_scan) | 1245 | if (fake_hw_scan) { |
1183 | mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan; | 1246 | mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan; |
1247 | mac80211_hwsim_ops.sw_scan_start = NULL; | ||
1248 | mac80211_hwsim_ops.sw_scan_complete = NULL; | ||
1249 | } | ||
1184 | 1250 | ||
1185 | spin_lock_init(&hwsim_radio_lock); | 1251 | spin_lock_init(&hwsim_radio_lock); |
1186 | INIT_LIST_HEAD(&hwsim_radios); | 1252 | INIT_LIST_HEAD(&hwsim_radios); |
@@ -1235,7 +1301,8 @@ static int __init init_mac80211_hwsim(void) | |||
1235 | hw->flags = IEEE80211_HW_MFP_CAPABLE | | 1301 | hw->flags = IEEE80211_HW_MFP_CAPABLE | |
1236 | IEEE80211_HW_SIGNAL_DBM | | 1302 | IEEE80211_HW_SIGNAL_DBM | |
1237 | IEEE80211_HW_SUPPORTS_STATIC_SMPS | | 1303 | IEEE80211_HW_SUPPORTS_STATIC_SMPS | |
1238 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS; | 1304 | IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS | |
1305 | IEEE80211_HW_AMPDU_AGGREGATION; | ||
1239 | 1306 | ||
1240 | /* ask mac80211 to reserve space for magic */ | 1307 | /* ask mac80211 to reserve space for magic */ |
1241 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); | 1308 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); |
@@ -1285,6 +1352,7 @@ static int __init init_mac80211_hwsim(void) | |||
1285 | } | 1352 | } |
1286 | /* By default all radios are belonging to the first group */ | 1353 | /* By default all radios are belonging to the first group */ |
1287 | data->group = 1; | 1354 | data->group = 1; |
1355 | mutex_init(&data->mutex); | ||
1288 | 1356 | ||
1289 | /* Work to be done prior to ieee80211_register_hw() */ | 1357 | /* Work to be done prior to ieee80211_register_hw() */ |
1290 | switch (regtest) { | 1358 | switch (regtest) { |