diff options
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r-- | net/mac80211/util.c | 118 |
1 files changed, 118 insertions, 0 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 1ff83532120f..b361e2acfce9 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -28,6 +28,7 @@ | |||
28 | #include "rate.h" | 28 | #include "rate.h" |
29 | #include "mesh.h" | 29 | #include "mesh.h" |
30 | #include "wme.h" | 30 | #include "wme.h" |
31 | #include "led.h" | ||
31 | 32 | ||
32 | /* privid for wiphys to determine whether they belong to us or not */ | 33 | /* privid for wiphys to determine whether they belong to us or not */ |
33 | void *mac80211_wiphy_privid = &mac80211_wiphy_privid; | 34 | void *mac80211_wiphy_privid = &mac80211_wiphy_privid; |
@@ -966,3 +967,120 @@ u32 ieee80211_sta_get_rates(struct ieee80211_local *local, | |||
966 | } | 967 | } |
967 | return supp_rates; | 968 | return supp_rates; |
968 | } | 969 | } |
970 | |||
971 | int ieee80211_reconfig(struct ieee80211_local *local) | ||
972 | { | ||
973 | struct ieee80211_hw *hw = &local->hw; | ||
974 | struct ieee80211_sub_if_data *sdata; | ||
975 | struct ieee80211_if_init_conf conf; | ||
976 | struct sta_info *sta; | ||
977 | unsigned long flags; | ||
978 | int res; | ||
979 | |||
980 | /* restart hardware */ | ||
981 | if (local->open_count) { | ||
982 | res = local->ops->start(hw); | ||
983 | |||
984 | ieee80211_led_radio(local, hw->conf.radio_enabled); | ||
985 | } | ||
986 | |||
987 | /* add interfaces */ | ||
988 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
989 | if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && | ||
990 | sdata->vif.type != NL80211_IFTYPE_MONITOR && | ||
991 | netif_running(sdata->dev)) { | ||
992 | conf.vif = &sdata->vif; | ||
993 | conf.type = sdata->vif.type; | ||
994 | conf.mac_addr = sdata->dev->dev_addr; | ||
995 | res = local->ops->add_interface(hw, &conf); | ||
996 | } | ||
997 | } | ||
998 | |||
999 | /* add STAs back */ | ||
1000 | if (local->ops->sta_notify) { | ||
1001 | spin_lock_irqsave(&local->sta_lock, flags); | ||
1002 | list_for_each_entry(sta, &local->sta_list, list) { | ||
1003 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) | ||
1004 | sdata = container_of(sdata->bss, | ||
1005 | struct ieee80211_sub_if_data, | ||
1006 | u.ap); | ||
1007 | |||
1008 | local->ops->sta_notify(hw, &sdata->vif, | ||
1009 | STA_NOTIFY_ADD, &sta->sta); | ||
1010 | } | ||
1011 | spin_unlock_irqrestore(&local->sta_lock, flags); | ||
1012 | } | ||
1013 | |||
1014 | /* Clear Suspend state so that ADDBA requests can be processed */ | ||
1015 | |||
1016 | rcu_read_lock(); | ||
1017 | |||
1018 | if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { | ||
1019 | list_for_each_entry_rcu(sta, &local->sta_list, list) { | ||
1020 | clear_sta_flags(sta, WLAN_STA_SUSPEND); | ||
1021 | } | ||
1022 | } | ||
1023 | |||
1024 | rcu_read_unlock(); | ||
1025 | |||
1026 | /* setup RTS threshold */ | ||
1027 | if (local->ops->set_rts_threshold) | ||
1028 | local->ops->set_rts_threshold(hw, local->rts_threshold); | ||
1029 | |||
1030 | /* reconfigure hardware */ | ||
1031 | ieee80211_hw_config(local, ~0); | ||
1032 | |||
1033 | netif_addr_lock_bh(local->mdev); | ||
1034 | ieee80211_configure_filter(local); | ||
1035 | netif_addr_unlock_bh(local->mdev); | ||
1036 | |||
1037 | /* Finally also reconfigure all the BSS information */ | ||
1038 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
1039 | u32 changed = ~0; | ||
1040 | if (!netif_running(sdata->dev)) | ||
1041 | continue; | ||
1042 | switch (sdata->vif.type) { | ||
1043 | case NL80211_IFTYPE_STATION: | ||
1044 | /* disable beacon change bits */ | ||
1045 | changed &= ~IEEE80211_IFCC_BEACON; | ||
1046 | /* fall through */ | ||
1047 | case NL80211_IFTYPE_ADHOC: | ||
1048 | case NL80211_IFTYPE_AP: | ||
1049 | case NL80211_IFTYPE_MESH_POINT: | ||
1050 | /* | ||
1051 | * Driver's config_interface can fail if rfkill is | ||
1052 | * enabled. Accommodate this return code. | ||
1053 | * FIXME: When mac80211 has knowledge of rfkill | ||
1054 | * state the code below can change back to: | ||
1055 | * WARN(ieee80211_if_config(sdata, changed)); | ||
1056 | * ieee80211_bss_info_change_notify(sdata, ~0); | ||
1057 | */ | ||
1058 | if (ieee80211_if_config(sdata, changed)) | ||
1059 | printk(KERN_DEBUG "%s: failed to configure interface during resume\n", | ||
1060 | sdata->dev->name); | ||
1061 | else | ||
1062 | ieee80211_bss_info_change_notify(sdata, ~0); | ||
1063 | break; | ||
1064 | case NL80211_IFTYPE_WDS: | ||
1065 | break; | ||
1066 | case NL80211_IFTYPE_AP_VLAN: | ||
1067 | case NL80211_IFTYPE_MONITOR: | ||
1068 | /* ignore virtual */ | ||
1069 | break; | ||
1070 | case NL80211_IFTYPE_UNSPECIFIED: | ||
1071 | case __NL80211_IFTYPE_AFTER_LAST: | ||
1072 | WARN_ON(1); | ||
1073 | break; | ||
1074 | } | ||
1075 | } | ||
1076 | |||
1077 | /* add back keys */ | ||
1078 | list_for_each_entry(sdata, &local->interfaces, list) | ||
1079 | if (netif_running(sdata->dev)) | ||
1080 | ieee80211_enable_keys(sdata); | ||
1081 | |||
1082 | ieee80211_wake_queues_by_reason(hw, | ||
1083 | IEEE80211_QUEUE_STOP_REASON_SUSPEND); | ||
1084 | |||
1085 | return 0; | ||
1086 | } | ||