diff options
Diffstat (limited to 'net/mac80211/iface.c')
-rw-r--r-- | net/mac80211/iface.c | 106 |
1 files changed, 18 insertions, 88 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 0a36dc6346bb..40ff0307d089 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c | |||
@@ -78,8 +78,7 @@ void ieee80211_recalc_txpower(struct ieee80211_sub_if_data *sdata) | |||
78 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER); | 78 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_TXPOWER); |
79 | } | 79 | } |
80 | 80 | ||
81 | static u32 ieee80211_idle_off(struct ieee80211_local *local, | 81 | static u32 ieee80211_idle_off(struct ieee80211_local *local) |
82 | const char *reason) | ||
83 | { | 82 | { |
84 | if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE)) | 83 | if (!(local->hw.conf.flags & IEEE80211_CONF_IDLE)) |
85 | return 0; | 84 | return 0; |
@@ -99,110 +98,45 @@ static u32 ieee80211_idle_on(struct ieee80211_local *local) | |||
99 | return IEEE80211_CONF_CHANGE_IDLE; | 98 | return IEEE80211_CONF_CHANGE_IDLE; |
100 | } | 99 | } |
101 | 100 | ||
102 | static u32 __ieee80211_recalc_idle(struct ieee80211_local *local) | 101 | void ieee80211_recalc_idle(struct ieee80211_local *local) |
103 | { | 102 | { |
104 | struct ieee80211_sub_if_data *sdata; | 103 | bool working = false, scanning, active; |
105 | int count = 0; | ||
106 | bool working = false, scanning = false; | ||
107 | unsigned int led_trig_start = 0, led_trig_stop = 0; | 104 | unsigned int led_trig_start = 0, led_trig_stop = 0; |
108 | struct ieee80211_roc_work *roc; | 105 | struct ieee80211_roc_work *roc; |
106 | u32 change; | ||
109 | 107 | ||
110 | #ifdef CONFIG_PROVE_LOCKING | ||
111 | WARN_ON(debug_locks && !lockdep_rtnl_is_held() && | ||
112 | !lockdep_is_held(&local->iflist_mtx)); | ||
113 | #endif | ||
114 | lockdep_assert_held(&local->mtx); | 108 | lockdep_assert_held(&local->mtx); |
115 | 109 | ||
116 | list_for_each_entry(sdata, &local->interfaces, list) { | 110 | active = !list_empty(&local->chanctx_list); |
117 | if (!ieee80211_sdata_running(sdata)) { | ||
118 | sdata->vif.bss_conf.idle = true; | ||
119 | continue; | ||
120 | } | ||
121 | |||
122 | sdata->old_idle = sdata->vif.bss_conf.idle; | ||
123 | |||
124 | /* do not count disabled managed interfaces */ | ||
125 | if (sdata->vif.type == NL80211_IFTYPE_STATION && | ||
126 | !sdata->u.mgd.associated && | ||
127 | !sdata->u.mgd.auth_data && | ||
128 | !sdata->u.mgd.assoc_data) { | ||
129 | sdata->vif.bss_conf.idle = true; | ||
130 | continue; | ||
131 | } | ||
132 | /* do not count unused IBSS interfaces */ | ||
133 | if (sdata->vif.type == NL80211_IFTYPE_ADHOC && | ||
134 | !sdata->u.ibss.ssid_len) { | ||
135 | sdata->vif.bss_conf.idle = true; | ||
136 | continue; | ||
137 | } | ||
138 | |||
139 | if (sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) | ||
140 | continue; | ||
141 | |||
142 | /* count everything else */ | ||
143 | sdata->vif.bss_conf.idle = false; | ||
144 | count++; | ||
145 | } | ||
146 | 111 | ||
147 | if (!local->ops->remain_on_channel) { | 112 | if (!local->ops->remain_on_channel) { |
148 | list_for_each_entry(roc, &local->roc_list, list) { | 113 | list_for_each_entry(roc, &local->roc_list, list) { |
149 | working = true; | 114 | working = true; |
150 | roc->sdata->vif.bss_conf.idle = false; | 115 | break; |
151 | } | 116 | } |
152 | } | 117 | } |
153 | 118 | ||
154 | sdata = rcu_dereference_protected(local->scan_sdata, | 119 | scanning = test_bit(SCAN_SW_SCANNING, &local->scanning) || |
155 | lockdep_is_held(&local->mtx)); | 120 | test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning); |
156 | if (sdata && !(local->hw.flags & IEEE80211_HW_SCAN_WHILE_IDLE)) { | ||
157 | scanning = true; | ||
158 | sdata->vif.bss_conf.idle = false; | ||
159 | } | ||
160 | |||
161 | list_for_each_entry(sdata, &local->interfaces, list) { | ||
162 | if (sdata->vif.type == NL80211_IFTYPE_MONITOR || | ||
163 | sdata->vif.type == NL80211_IFTYPE_AP_VLAN || | ||
164 | sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE) | ||
165 | continue; | ||
166 | if (sdata->old_idle == sdata->vif.bss_conf.idle) | ||
167 | continue; | ||
168 | if (!ieee80211_sdata_running(sdata)) | ||
169 | continue; | ||
170 | ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE); | ||
171 | } | ||
172 | 121 | ||
173 | if (working || scanning) | 122 | if (working || scanning) |
174 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK; | 123 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK; |
175 | else | 124 | else |
176 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK; | 125 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK; |
177 | 126 | ||
178 | if (count) | 127 | if (active) |
179 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; | 128 | led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; |
180 | else | 129 | else |
181 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; | 130 | led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; |
182 | 131 | ||
183 | ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop); | 132 | ieee80211_mod_tpt_led_trig(local, led_trig_start, led_trig_stop); |
184 | 133 | ||
185 | if (working) | 134 | if (working || scanning || active) |
186 | return ieee80211_idle_off(local, "working"); | 135 | change = ieee80211_idle_off(local); |
187 | if (scanning) | ||
188 | return ieee80211_idle_off(local, "scanning"); | ||
189 | if (!count) | ||
190 | return ieee80211_idle_on(local); | ||
191 | else | 136 | else |
192 | return ieee80211_idle_off(local, "in use"); | 137 | change = ieee80211_idle_on(local); |
193 | 138 | if (change) | |
194 | return 0; | 139 | ieee80211_hw_config(local, change); |
195 | } | ||
196 | |||
197 | void ieee80211_recalc_idle(struct ieee80211_local *local) | ||
198 | { | ||
199 | u32 chg; | ||
200 | |||
201 | mutex_lock(&local->iflist_mtx); | ||
202 | chg = __ieee80211_recalc_idle(local); | ||
203 | mutex_unlock(&local->iflist_mtx); | ||
204 | if (chg) | ||
205 | ieee80211_hw_config(local, chg); | ||
206 | } | 140 | } |
207 | 141 | ||
208 | static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) | 142 | static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) |
@@ -621,6 +555,8 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
621 | goto err_del_interface; | 555 | goto err_del_interface; |
622 | } | 556 | } |
623 | 557 | ||
558 | drv_add_interface_debugfs(local, sdata); | ||
559 | |||
624 | if (sdata->vif.type == NL80211_IFTYPE_AP) { | 560 | if (sdata->vif.type == NL80211_IFTYPE_AP) { |
625 | local->fif_pspoll++; | 561 | local->fif_pspoll++; |
626 | local->fif_probe_req++; | 562 | local->fif_probe_req++; |
@@ -694,10 +630,6 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) | |||
694 | if (sdata->flags & IEEE80211_SDATA_PROMISC) | 630 | if (sdata->flags & IEEE80211_SDATA_PROMISC) |
695 | atomic_inc(&local->iff_promiscs); | 631 | atomic_inc(&local->iff_promiscs); |
696 | 632 | ||
697 | mutex_lock(&local->mtx); | ||
698 | hw_reconf_flags |= __ieee80211_recalc_idle(local); | ||
699 | mutex_unlock(&local->mtx); | ||
700 | |||
701 | if (coming_up) | 633 | if (coming_up) |
702 | local->open_count++; | 634 | local->open_count++; |
703 | 635 | ||
@@ -882,16 +814,14 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata, | |||
882 | */ | 814 | */ |
883 | ieee80211_free_keys(sdata); | 815 | ieee80211_free_keys(sdata); |
884 | 816 | ||
817 | drv_remove_interface_debugfs(local, sdata); | ||
818 | |||
885 | if (going_down) | 819 | if (going_down) |
886 | drv_remove_interface(local, sdata); | 820 | drv_remove_interface(local, sdata); |
887 | } | 821 | } |
888 | 822 | ||
889 | sdata->bss = NULL; | 823 | sdata->bss = NULL; |
890 | 824 | ||
891 | mutex_lock(&local->mtx); | ||
892 | hw_reconf_flags |= __ieee80211_recalc_idle(local); | ||
893 | mutex_unlock(&local->mtx); | ||
894 | |||
895 | ieee80211_recalc_ps(local, -1); | 825 | ieee80211_recalc_ps(local, -1); |
896 | 826 | ||
897 | if (local->open_count == 0) { | 827 | if (local->open_count == 0) { |