aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-04-14 04:09:24 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-04-22 16:57:14 -0400
commitf2753ddbadb0873a98421415882318251bbd9eaa (patch)
treedaad40232be13d91835b30234e5743dfdd582f19 /net/mac80211/util.c
parenta1c555802a62c845520d2486d783c9bb1d5e68a9 (diff)
mac80211: add hardware restart function
Some hardware defects may require the hardware to be re-initialised completely from scratch. Drivers would need much information (for instance the current MAC address, crypto keys, beaconing information, etc.) stored duplicated from mac80211 to be able to do this, so let mac80211 help them. The new ieee80211_restart_hw() function requires the same code as resuming, so move that code into a new ieee80211_reconfig() function in util.c and leave only the suspend code in pm.c. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c118
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 */
33void *mac80211_wiphy_privid = &mac80211_wiphy_privid; 34void *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
971int 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}