aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c74
1 files changed, 74 insertions, 0 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index d54dbe8e09ba..086ef6257b4b 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1170,3 +1170,77 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1170 return 0; 1170 return 0;
1171} 1171}
1172 1172
1173static int check_mgd_smps(struct ieee80211_if_managed *ifmgd,
1174 enum ieee80211_smps_mode *smps_mode)
1175{
1176 if (ifmgd->associated) {
1177 *smps_mode = ifmgd->ap_smps;
1178
1179 if (*smps_mode == IEEE80211_SMPS_AUTOMATIC) {
1180 if (ifmgd->powersave)
1181 *smps_mode = IEEE80211_SMPS_DYNAMIC;
1182 else
1183 *smps_mode = IEEE80211_SMPS_OFF;
1184 }
1185
1186 return 1;
1187 }
1188
1189 return 0;
1190}
1191
1192/* must hold iflist_mtx */
1193void ieee80211_recalc_smps(struct ieee80211_local *local,
1194 struct ieee80211_sub_if_data *forsdata)
1195{
1196 struct ieee80211_sub_if_data *sdata;
1197 enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF;
1198 int count = 0;
1199
1200 if (forsdata)
1201 WARN_ON(!mutex_is_locked(&forsdata->u.mgd.mtx));
1202
1203 WARN_ON(!mutex_is_locked(&local->iflist_mtx));
1204
1205 /*
1206 * This function could be improved to handle multiple
1207 * interfaces better, but right now it makes any
1208 * non-station interfaces force SM PS to be turned
1209 * off. If there are multiple station interfaces it
1210 * could also use the best possible mode, e.g. if
1211 * one is in static and the other in dynamic then
1212 * dynamic is ok.
1213 */
1214
1215 list_for_each_entry(sdata, &local->interfaces, list) {
1216 if (!netif_running(sdata->dev))
1217 continue;
1218 if (sdata->vif.type != NL80211_IFTYPE_STATION)
1219 goto set;
1220 if (sdata != forsdata) {
1221 /*
1222 * This nested is ok -- we are holding the iflist_mtx
1223 * so can't get here twice or so. But it's required
1224 * since normally we acquire it first and then the
1225 * iflist_mtx.
1226 */
1227 mutex_lock_nested(&sdata->u.mgd.mtx, SINGLE_DEPTH_NESTING);
1228 count += check_mgd_smps(&sdata->u.mgd, &smps_mode);
1229 mutex_unlock(&sdata->u.mgd.mtx);
1230 } else
1231 count += check_mgd_smps(&sdata->u.mgd, &smps_mode);
1232
1233 if (count > 1) {
1234 smps_mode = IEEE80211_SMPS_OFF;
1235 break;
1236 }
1237 }
1238
1239 if (smps_mode == local->smps_mode)
1240 return;
1241
1242 set:
1243 local->smps_mode = smps_mode;
1244 /* changed flag is auto-detected for this */
1245 ieee80211_hw_config(local, 0);
1246}