aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-12-01 07:37:02 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-12-22 13:31:16 -0500
commit0f78231bffb868a30e8533aace142213266bb811 (patch)
tree317f65dc6d89e9a89ad83f94fadd780dd1e0ca83 /net/mac80211/util.c
parent18974b5b0b5e758d416c550553b143e5c8038281 (diff)
mac80211: enable spatial multiplexing powersave
Enable spatial multiplexing in mac80211 by telling the driver what to do and, where necessary, sending action frames to the AP to update the requested SMPS mode. Also includes a trivial implementation for hwsim that just logs the requested mode. For now, the userspace interface is in debugfs only, and let you toggle the requested mode at any time. 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.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}