aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/cfg.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/cfg.c')
-rw-r--r--net/mac80211/cfg.c108
1 files changed, 105 insertions, 3 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index ac28af74a414..4a3d5a414a25 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1059,6 +1059,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
1059 /* abort any running channel switch */ 1059 /* abort any running channel switch */
1060 sdata->vif.csa_active = false; 1060 sdata->vif.csa_active = false;
1061 cancel_work_sync(&sdata->csa_finalize_work); 1061 cancel_work_sync(&sdata->csa_finalize_work);
1062 cancel_work_sync(&sdata->u.ap.request_smps_work);
1062 1063
1063 /* turn off carrier for this interface and dependent VLANs */ 1064 /* turn off carrier for this interface and dependent VLANs */
1064 list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) 1065 list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
@@ -1553,6 +1554,20 @@ static int ieee80211_change_station(struct wiphy *wiphy,
1553 1554
1554 mutex_unlock(&local->sta_mtx); 1555 mutex_unlock(&local->sta_mtx);
1555 1556
1557 if ((sdata->vif.type == NL80211_IFTYPE_AP ||
1558 sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
1559 sta->known_smps_mode != sta->sdata->bss->req_smps &&
1560 test_sta_flag(sta, WLAN_STA_AUTHORIZED) &&
1561 sta_info_tx_streams(sta) != 1) {
1562 ht_dbg(sta->sdata,
1563 "%pM just authorized and MIMO capable - update SMPS\n",
1564 sta->sta.addr);
1565 ieee80211_send_smps_action(sta->sdata,
1566 sta->sdata->bss->req_smps,
1567 sta->sta.addr,
1568 sta->sdata->vif.bss_conf.bssid);
1569 }
1570
1556 if (sdata->vif.type == NL80211_IFTYPE_STATION && 1571 if (sdata->vif.type == NL80211_IFTYPE_STATION &&
1557 params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) { 1572 params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
1558 ieee80211_recalc_ps(local, -1); 1573 ieee80211_recalc_ps(local, -1);
@@ -2337,8 +2352,92 @@ static int ieee80211_testmode_dump(struct wiphy *wiphy,
2337} 2352}
2338#endif 2353#endif
2339 2354
2340int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata, 2355int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata,
2341 enum ieee80211_smps_mode smps_mode) 2356 enum ieee80211_smps_mode smps_mode)
2357{
2358 struct sta_info *sta;
2359 enum ieee80211_smps_mode old_req;
2360 int i;
2361
2362 if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP))
2363 return -EINVAL;
2364
2365 if (sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
2366 return 0;
2367
2368 old_req = sdata->u.ap.req_smps;
2369 sdata->u.ap.req_smps = smps_mode;
2370
2371 /* AUTOMATIC doesn't mean much for AP - don't allow it */
2372 if (old_req == smps_mode ||
2373 smps_mode == IEEE80211_SMPS_AUTOMATIC)
2374 return 0;
2375
2376 /* If no associated stations, there's no need to do anything */
2377 if (!atomic_read(&sdata->u.ap.num_mcast_sta)) {
2378 sdata->smps_mode = smps_mode;
2379 ieee80211_queue_work(&sdata->local->hw, &sdata->recalc_smps);
2380 return 0;
2381 }
2382
2383 ht_dbg(sdata,
2384 "SMSP %d requested in AP mode, sending Action frame to %d stations\n",
2385 smps_mode, atomic_read(&sdata->u.ap.num_mcast_sta));
2386
2387 mutex_lock(&sdata->local->sta_mtx);
2388 for (i = 0; i < STA_HASH_SIZE; i++) {
2389 for (sta = rcu_dereference_protected(sdata->local->sta_hash[i],
2390 lockdep_is_held(&sdata->local->sta_mtx));
2391 sta;
2392 sta = rcu_dereference_protected(sta->hnext,
2393 lockdep_is_held(&sdata->local->sta_mtx))) {
2394 /*
2395 * Only stations associated to our AP and
2396 * associated VLANs
2397 */
2398 if (sta->sdata->bss != &sdata->u.ap)
2399 continue;
2400
2401 /* This station doesn't support MIMO - skip it */
2402 if (sta_info_tx_streams(sta) == 1)
2403 continue;
2404
2405 /*
2406 * Don't wake up a STA just to send the action frame
2407 * unless we are getting more restrictive.
2408 */
2409 if (test_sta_flag(sta, WLAN_STA_PS_STA) &&
2410 !ieee80211_smps_is_restrictive(sta->known_smps_mode,
2411 smps_mode)) {
2412 ht_dbg(sdata,
2413 "Won't send SMPS to sleeping STA %pM\n",
2414 sta->sta.addr);
2415 continue;
2416 }
2417
2418 /*
2419 * If the STA is not authorized, wait until it gets
2420 * authorized and the action frame will be sent then.
2421 */
2422 if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED))
2423 continue;
2424
2425 ht_dbg(sdata, "Sending SMPS to %pM\n", sta->sta.addr);
2426 ieee80211_send_smps_action(sdata, smps_mode,
2427 sta->sta.addr,
2428 sdata->vif.bss_conf.bssid);
2429 }
2430 }
2431 mutex_unlock(&sdata->local->sta_mtx);
2432
2433 sdata->smps_mode = smps_mode;
2434 ieee80211_queue_work(&sdata->local->hw, &sdata->recalc_smps);
2435
2436 return 0;
2437}
2438
2439int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
2440 enum ieee80211_smps_mode smps_mode)
2342{ 2441{
2343 const u8 *ap; 2442 const u8 *ap;
2344 enum ieee80211_smps_mode old_req; 2443 enum ieee80211_smps_mode old_req;
@@ -2346,6 +2445,9 @@ int __ieee80211_request_smps(struct ieee80211_sub_if_data *sdata,
2346 2445
2347 lockdep_assert_held(&sdata->wdev.mtx); 2446 lockdep_assert_held(&sdata->wdev.mtx);
2348 2447
2448 if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION))
2449 return -EINVAL;
2450
2349 old_req = sdata->u.mgd.req_smps; 2451 old_req = sdata->u.mgd.req_smps;
2350 sdata->u.mgd.req_smps = smps_mode; 2452 sdata->u.mgd.req_smps = smps_mode;
2351 2453
@@ -2402,7 +2504,7 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
2402 2504
2403 /* no change, but if automatic follow powersave */ 2505 /* no change, but if automatic follow powersave */
2404 sdata_lock(sdata); 2506 sdata_lock(sdata);
2405 __ieee80211_request_smps(sdata, sdata->u.mgd.req_smps); 2507 __ieee80211_request_smps_mgd(sdata, sdata->u.mgd.req_smps);
2406 sdata_unlock(sdata); 2508 sdata_unlock(sdata);
2407 2509
2408 if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS) 2510 if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)