aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--net/mac80211/chan.c13
-rw-r--r--net/mac80211/ibss.c8
-rw-r--r--net/mac80211/ieee80211_i.h3
-rw-r--r--net/mac80211/iface.c94
-rw-r--r--net/mac80211/mlme.c34
5 files changed, 25 insertions, 127 deletions
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index b5b50762f03e..038f249966d6 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -91,6 +91,10 @@ ieee80211_new_chanctx(struct ieee80211_local *local,
91 91
92 list_add_rcu(&ctx->list, &local->chanctx_list); 92 list_add_rcu(&ctx->list, &local->chanctx_list);
93 93
94 mutex_lock(&local->mtx);
95 ieee80211_recalc_idle(local);
96 mutex_unlock(&local->mtx);
97
94 return ctx; 98 return ctx;
95} 99}
96 100
@@ -110,6 +114,10 @@ static void ieee80211_free_chanctx(struct ieee80211_local *local,
110 114
111 list_del_rcu(&ctx->list); 115 list_del_rcu(&ctx->list);
112 kfree_rcu(ctx, rcu_head); 116 kfree_rcu(ctx, rcu_head);
117
118 mutex_lock(&local->mtx);
119 ieee80211_recalc_idle(local);
120 mutex_unlock(&local->mtx);
113} 121}
114 122
115static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata, 123static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
@@ -128,6 +136,8 @@ static int ieee80211_assign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
128 ctx->refcount++; 136 ctx->refcount++;
129 137
130 ieee80211_recalc_txpower(sdata); 138 ieee80211_recalc_txpower(sdata);
139 sdata->vif.bss_conf.idle = false;
140 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
131 141
132 return 0; 142 return 0;
133} 143}
@@ -175,6 +185,9 @@ static void ieee80211_unassign_vif_chanctx(struct ieee80211_sub_if_data *sdata,
175 ctx->refcount--; 185 ctx->refcount--;
176 rcu_assign_pointer(sdata->vif.chanctx_conf, NULL); 186 rcu_assign_pointer(sdata->vif.chanctx_conf, NULL);
177 187
188 sdata->vif.bss_conf.idle = true;
189 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
190
178 drv_unassign_vif_chanctx(local, sdata, ctx); 191 drv_unassign_vif_chanctx(local, sdata, ctx);
179 192
180 if (ctx->refcount > 0) { 193 if (ctx->refcount > 0) {
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 055fa9436e95..2db1f2b90bfe 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -1108,10 +1108,6 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
1108 1108
1109 mutex_unlock(&sdata->u.ibss.mtx); 1109 mutex_unlock(&sdata->u.ibss.mtx);
1110 1110
1111 mutex_lock(&sdata->local->mtx);
1112 ieee80211_recalc_idle(sdata->local);
1113 mutex_unlock(&sdata->local->mtx);
1114
1115 /* 1111 /*
1116 * 802.11n-2009 9.13.3.1: In an IBSS, the HT Protection field is 1112 * 802.11n-2009 9.13.3.1: In an IBSS, the HT Protection field is
1117 * reserved, but an HT STA shall protect HT transmissions as though 1113 * reserved, but an HT STA shall protect HT transmissions as though
@@ -1209,9 +1205,5 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)
1209 1205
1210 mutex_unlock(&sdata->u.ibss.mtx); 1206 mutex_unlock(&sdata->u.ibss.mtx);
1211 1207
1212 mutex_lock(&local->mtx);
1213 ieee80211_recalc_idle(sdata->local);
1214 mutex_unlock(&local->mtx);
1215
1216 return 0; 1208 return 0;
1217} 1209}
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index fafeb309a5fe..5635dfc7da34 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -689,9 +689,6 @@ struct ieee80211_sub_if_data {
689 689
690 char name[IFNAMSIZ]; 690 char name[IFNAMSIZ];
691 691
692 /* to detect idle changes */
693 bool old_idle;
694
695 /* Fragment table for host-based reassembly */ 692 /* Fragment table for host-based reassembly */
696 struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX]; 693 struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX];
697 unsigned int fragment_next; 694 unsigned int fragment_next;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 3ece8eb6d2df..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
81static u32 ieee80211_idle_off(struct ieee80211_local *local, 81static 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,106 +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
102static u32 __ieee80211_recalc_idle(struct ieee80211_local *local) 101void 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 scanning = test_bit(SCAN_SW_SCANNING, &local->scanning) || 119 scanning = test_bit(SCAN_SW_SCANNING, &local->scanning) ||
155 test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning); 120 test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning);
156 121
157 list_for_each_entry(sdata, &local->interfaces, list) {
158 if (sdata->vif.type == NL80211_IFTYPE_MONITOR ||
159 sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
160 sdata->vif.type == NL80211_IFTYPE_P2P_DEVICE)
161 continue;
162 if (sdata->old_idle == sdata->vif.bss_conf.idle)
163 continue;
164 if (!ieee80211_sdata_running(sdata))
165 continue;
166 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
167 }
168
169 if (working || scanning) 122 if (working || scanning)
170 led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK; 123 led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_WORK;
171 else 124 else
172 led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK; 125 led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_WORK;
173 126
174 if (count) 127 if (active)
175 led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; 128 led_trig_start |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED;
176 else 129 else
177 led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED; 130 led_trig_stop |= IEEE80211_TPT_LEDTRIG_FL_CONNECTED;
178 131
179 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);
180 133
181 if (working) 134 if (working || scanning || active)
182 return ieee80211_idle_off(local, "working"); 135 change = ieee80211_idle_off(local);
183 if (scanning)
184 return ieee80211_idle_off(local, "scanning");
185 if (!count)
186 return ieee80211_idle_on(local);
187 else 136 else
188 return ieee80211_idle_off(local, "in use"); 137 change = ieee80211_idle_on(local);
189 138 if (change)
190 return 0; 139 ieee80211_hw_config(local, change);
191}
192
193void ieee80211_recalc_idle(struct ieee80211_local *local)
194{
195 u32 chg;
196
197 mutex_lock(&local->iflist_mtx);
198 chg = __ieee80211_recalc_idle(local);
199 mutex_unlock(&local->iflist_mtx);
200 if (chg)
201 ieee80211_hw_config(local, chg);
202} 140}
203 141
204static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) 142static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
@@ -692,10 +630,6 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
692 if (sdata->flags & IEEE80211_SDATA_PROMISC) 630 if (sdata->flags & IEEE80211_SDATA_PROMISC)
693 atomic_inc(&local->iff_promiscs); 631 atomic_inc(&local->iff_promiscs);
694 632
695 mutex_lock(&local->mtx);
696 hw_reconf_flags |= __ieee80211_recalc_idle(local);
697 mutex_unlock(&local->mtx);
698
699 if (coming_up) 633 if (coming_up)
700 local->open_count++; 634 local->open_count++;
701 635
@@ -888,10 +822,6 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
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) {
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 1e7662c5788e..3bcf39365be8 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1792,7 +1792,6 @@ EXPORT_SYMBOL(ieee80211_ap_probereq_get);
1792static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata) 1792static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
1793{ 1793{
1794 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 1794 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
1795 struct ieee80211_local *local = sdata->local;
1796 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; 1795 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
1797 1796
1798 mutex_lock(&ifmgd->mtx); 1797 mutex_lock(&ifmgd->mtx);
@@ -1812,10 +1811,6 @@ static void __ieee80211_disconnect(struct ieee80211_sub_if_data *sdata)
1812 * but that's not a problem. 1811 * but that's not a problem.
1813 */ 1812 */
1814 cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); 1813 cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN);
1815
1816 mutex_lock(&local->mtx);
1817 ieee80211_recalc_idle(local);
1818 mutex_unlock(&local->mtx);
1819} 1814}
1820 1815
1821static void ieee80211_beacon_connection_loss_work(struct work_struct *work) 1816static void ieee80211_beacon_connection_loss_work(struct work_struct *work)
@@ -2048,10 +2043,6 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
2048 2043
2049 ieee80211_set_disassoc(sdata, 0, 0, false, NULL); 2044 ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
2050 2045
2051 mutex_lock(&sdata->local->mtx);
2052 ieee80211_recalc_idle(sdata->local);
2053 mutex_unlock(&sdata->local->mtx);
2054
2055 return RX_MGMT_CFG80211_DEAUTH; 2046 return RX_MGMT_CFG80211_DEAUTH;
2056} 2047}
2057 2048
@@ -2079,10 +2070,6 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
2079 2070
2080 ieee80211_set_disassoc(sdata, 0, 0, false, NULL); 2071 ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
2081 2072
2082 mutex_lock(&sdata->local->mtx);
2083 ieee80211_recalc_idle(sdata->local);
2084 mutex_unlock(&sdata->local->mtx);
2085
2086 return RX_MGMT_CFG80211_DISASSOC; 2073 return RX_MGMT_CFG80211_DISASSOC;
2087} 2074}
2088 2075
@@ -2839,7 +2826,6 @@ static void ieee80211_sta_timer(unsigned long data)
2839static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata, 2826static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
2840 u8 *bssid, u8 reason, bool tx) 2827 u8 *bssid, u8 reason, bool tx)
2841{ 2828{
2842 struct ieee80211_local *local = sdata->local;
2843 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 2829 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
2844 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; 2830 u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN];
2845 2831
@@ -2853,10 +2839,6 @@ static void ieee80211_sta_connection_lost(struct ieee80211_sub_if_data *sdata,
2853 */ 2839 */
2854 cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); 2840 cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN);
2855 2841
2856 mutex_lock(&local->mtx);
2857 ieee80211_recalc_idle(local);
2858 mutex_unlock(&local->mtx);
2859
2860 mutex_lock(&ifmgd->mtx); 2842 mutex_lock(&ifmgd->mtx);
2861} 2843}
2862 2844
@@ -3127,10 +3109,6 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
3127 } 3109 }
3128 3110
3129 mutex_unlock(&ifmgd->mtx); 3111 mutex_unlock(&ifmgd->mtx);
3130
3131 mutex_lock(&local->mtx);
3132 ieee80211_recalc_idle(local);
3133 mutex_unlock(&local->mtx);
3134} 3112}
3135 3113
3136static void ieee80211_sta_bcn_mon_timer(unsigned long data) 3114static void ieee80211_sta_bcn_mon_timer(unsigned long data)
@@ -3644,10 +3622,6 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
3644 return -ENOMEM; 3622 return -ENOMEM;
3645 } 3623 }
3646 3624
3647 mutex_lock(&local->mtx);
3648 ieee80211_recalc_idle(sdata->local);
3649 mutex_unlock(&local->mtx);
3650
3651 if (new_sta) { 3625 if (new_sta) {
3652 u32 rates = 0, basic_rates = 0; 3626 u32 rates = 0, basic_rates = 0;
3653 bool have_higher_than_11mbit; 3627 bool have_higher_than_11mbit;
@@ -4138,10 +4112,6 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
4138 mutex_unlock(&ifmgd->mtx); 4112 mutex_unlock(&ifmgd->mtx);
4139 4113
4140 out: 4114 out:
4141 mutex_lock(&sdata->local->mtx);
4142 ieee80211_recalc_idle(sdata->local);
4143 mutex_unlock(&sdata->local->mtx);
4144
4145 if (sent_frame) 4115 if (sent_frame)
4146 __cfg80211_send_deauth(sdata->dev, frame_buf, 4116 __cfg80211_send_deauth(sdata->dev, frame_buf,
4147 IEEE80211_DEAUTH_FRAME_LEN); 4117 IEEE80211_DEAUTH_FRAME_LEN);
@@ -4182,10 +4152,6 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
4182 __cfg80211_send_disassoc(sdata->dev, frame_buf, 4152 __cfg80211_send_disassoc(sdata->dev, frame_buf,
4183 IEEE80211_DEAUTH_FRAME_LEN); 4153 IEEE80211_DEAUTH_FRAME_LEN);
4184 4154
4185 mutex_lock(&sdata->local->mtx);
4186 ieee80211_recalc_idle(sdata->local);
4187 mutex_unlock(&sdata->local->mtx);
4188
4189 return 0; 4155 return 0;
4190} 4156}
4191 4157