diff options
-rw-r--r-- | include/net/mac80211.h | 39 | ||||
-rw-r--r-- | net/mac80211/ieee80211_i.h | 2 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 39 |
3 files changed, 79 insertions, 1 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index fe1a3a60337..7f256e23c57 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -1271,6 +1271,15 @@ ieee80211_get_alt_retry_rate(const struct ieee80211_hw *hw, | |||
1271 | * dynamic PS feature in stack and will just keep %IEEE80211_CONF_PS | 1271 | * dynamic PS feature in stack and will just keep %IEEE80211_CONF_PS |
1272 | * enabled whenever user has enabled powersave. | 1272 | * enabled whenever user has enabled powersave. |
1273 | * | 1273 | * |
1274 | * Some hardware need to toggle a single shared antenna between WLAN and | ||
1275 | * Bluetooth to facilitate co-existence. These types of hardware set | ||
1276 | * limitations on the use of host controlled dynamic powersave whenever there | ||
1277 | * is simultaneous WLAN and Bluetooth traffic. For these types of hardware, the | ||
1278 | * driver may request temporarily going into full power save, in order to | ||
1279 | * enable toggling the antenna between BT and WLAN. If the driver requests | ||
1280 | * disabling dynamic powersave, the @dynamic_ps_timeout value will be | ||
1281 | * temporarily set to zero until the driver re-enables dynamic powersave. | ||
1282 | * | ||
1274 | * Driver informs U-APSD client support by enabling | 1283 | * Driver informs U-APSD client support by enabling |
1275 | * %IEEE80211_HW_SUPPORTS_UAPSD flag. The mode is configured through the | 1284 | * %IEEE80211_HW_SUPPORTS_UAPSD flag. The mode is configured through the |
1276 | * uapsd paramater in conf_tx() operation. Hardware needs to send the QoS | 1285 | * uapsd paramater in conf_tx() operation. Hardware needs to send the QoS |
@@ -2447,6 +2456,36 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif); | |||
2447 | void ieee80211_connection_loss(struct ieee80211_vif *vif); | 2456 | void ieee80211_connection_loss(struct ieee80211_vif *vif); |
2448 | 2457 | ||
2449 | /** | 2458 | /** |
2459 | * ieee80211_disable_dyn_ps - force mac80211 to temporarily disable dynamic psm | ||
2460 | * | ||
2461 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. | ||
2462 | * | ||
2463 | * Some hardware require full power save to manage simultaneous BT traffic | ||
2464 | * on the WLAN frequency. Full PSM is required periodically, whenever there are | ||
2465 | * burst of BT traffic. The hardware gets information of BT traffic via | ||
2466 | * hardware co-existence lines, and consequentially requests mac80211 to | ||
2467 | * (temporarily) enter full psm. | ||
2468 | * This function will only temporarily disable dynamic PS, not enable PSM if | ||
2469 | * it was not already enabled. | ||
2470 | * The driver must make sure to re-enable dynamic PS using | ||
2471 | * ieee80211_enable_dyn_ps() if the driver has disabled it. | ||
2472 | * | ||
2473 | */ | ||
2474 | void ieee80211_disable_dyn_ps(struct ieee80211_vif *vif); | ||
2475 | |||
2476 | /** | ||
2477 | * ieee80211_enable_dyn_ps - restore dynamic psm after being disabled | ||
2478 | * | ||
2479 | * @vif: &struct ieee80211_vif pointer from the add_interface callback. | ||
2480 | * | ||
2481 | * This function restores dynamic PS after being temporarily disabled via | ||
2482 | * ieee80211_disable_dyn_ps(). Each ieee80211_disable_dyn_ps() call must | ||
2483 | * be coupled with an eventual call to this function. | ||
2484 | * | ||
2485 | */ | ||
2486 | void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif); | ||
2487 | |||
2488 | /** | ||
2450 | * ieee80211_cqm_rssi_notify - inform a configured connection quality monitoring | 2489 | * ieee80211_cqm_rssi_notify - inform a configured connection quality monitoring |
2451 | * rssi threshold triggered | 2490 | * rssi threshold triggered |
2452 | * | 2491 | * |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index fb5430188e8..f9251d50192 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -855,6 +855,8 @@ struct ieee80211_local { | |||
855 | * this will override whatever chosen by mac80211 internally. | 855 | * this will override whatever chosen by mac80211 internally. |
856 | */ | 856 | */ |
857 | int dynamic_ps_forced_timeout; | 857 | int dynamic_ps_forced_timeout; |
858 | int dynamic_ps_user_timeout; | ||
859 | bool disable_dynamic_ps; | ||
858 | 860 | ||
859 | int user_power_level; /* in dBm */ | 861 | int user_power_level; /* in dBm */ |
860 | int power_constr_level; /* in dBm */ | 862 | int power_constr_level; /* in dBm */ |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 85c3ca33333..d1962650b25 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -478,6 +478,39 @@ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata, | |||
478 | } | 478 | } |
479 | } | 479 | } |
480 | 480 | ||
481 | void ieee80211_enable_dyn_ps(struct ieee80211_vif *vif) | ||
482 | { | ||
483 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
484 | struct ieee80211_local *local = sdata->local; | ||
485 | struct ieee80211_conf *conf = &local->hw.conf; | ||
486 | |||
487 | WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION || | ||
488 | !(local->hw.flags & IEEE80211_HW_SUPPORTS_PS) || | ||
489 | (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)); | ||
490 | |||
491 | local->disable_dynamic_ps = false; | ||
492 | conf->dynamic_ps_timeout = local->dynamic_ps_user_timeout; | ||
493 | } | ||
494 | EXPORT_SYMBOL(ieee80211_enable_dyn_ps); | ||
495 | |||
496 | void ieee80211_disable_dyn_ps(struct ieee80211_vif *vif) | ||
497 | { | ||
498 | struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif); | ||
499 | struct ieee80211_local *local = sdata->local; | ||
500 | struct ieee80211_conf *conf = &local->hw.conf; | ||
501 | |||
502 | WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION || | ||
503 | !(local->hw.flags & IEEE80211_HW_SUPPORTS_PS) || | ||
504 | (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)); | ||
505 | |||
506 | local->disable_dynamic_ps = true; | ||
507 | conf->dynamic_ps_timeout = 0; | ||
508 | del_timer_sync(&local->dynamic_ps_timer); | ||
509 | ieee80211_queue_work(&local->hw, | ||
510 | &local->dynamic_ps_enable_work); | ||
511 | } | ||
512 | EXPORT_SYMBOL(ieee80211_disable_dyn_ps); | ||
513 | |||
481 | /* powersave */ | 514 | /* powersave */ |
482 | static void ieee80211_enable_ps(struct ieee80211_local *local, | 515 | static void ieee80211_enable_ps(struct ieee80211_local *local, |
483 | struct ieee80211_sub_if_data *sdata) | 516 | struct ieee80211_sub_if_data *sdata) |
@@ -553,6 +586,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
553 | found->u.mgd.associated->beacon_ies && | 586 | found->u.mgd.associated->beacon_ies && |
554 | !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL | | 587 | !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL | |
555 | IEEE80211_STA_CONNECTION_POLL))) { | 588 | IEEE80211_STA_CONNECTION_POLL))) { |
589 | struct ieee80211_conf *conf = &local->hw.conf; | ||
556 | s32 beaconint_us; | 590 | s32 beaconint_us; |
557 | 591 | ||
558 | if (latency < 0) | 592 | if (latency < 0) |
@@ -575,7 +609,10 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) | |||
575 | else | 609 | else |
576 | timeout = 100; | 610 | timeout = 100; |
577 | } | 611 | } |
578 | local->hw.conf.dynamic_ps_timeout = timeout; | 612 | local->dynamic_ps_user_timeout = timeout; |
613 | if (!local->disable_dynamic_ps) | ||
614 | conf->dynamic_ps_timeout = | ||
615 | local->dynamic_ps_user_timeout; | ||
579 | 616 | ||
580 | if (beaconint_us > latency) { | 617 | if (beaconint_us > latency) { |
581 | local->ps_sdata = NULL; | 618 | local->ps_sdata = NULL; |