aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJuuso Oikarinen <juuso.oikarinen@nokia.com>2010-06-21 01:59:39 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-06-21 15:39:59 -0400
commitf90754c15f47063671aea55268a9dd6a37b51492 (patch)
tree197c239a813e426d8a675449927e381352ad4875
parentfb63bc41772259701a827e9a6117219a7393554f (diff)
mac80211: Add interface for driver to temporarily disable dynamic ps
This mechanism introduced in this patch applies (at least) for hardware designs using a single shared antenna for both WLAN and BT. In these designs, the antenna must be toggled between WLAN and BT. In those hardware, managing WLAN co-existence with Bluetooth requires WLAN full power save whenever there is Bluetooth activity in order for WLAN to be able to periodically relinquish the antenna to be used for BT. This is because BT can only access the shared antenna when WLAN is idle or asleep. Some hardware, for instance the wl1271, are able to indicate to the host whenever there is BT traffic. In essence, the hardware will send an indication to the host whenever there is, for example, SCO traffic or A2DP traffic, and will send another indication when the traffic is over. The hardware gets information of Bluetooth traffic via hardware co-existence control lines - these lines are used to negotiate the shared antenna ownership. The hardware will give the antenna to BT whenever WLAN is sleeping. This patch adds the interface to mac80211 to facilitate temporarily disabling of dynamic power save as per request of the WLAN driver. This interface will immediately force WLAN to full powersave, hence allowing BT coexistence as described above. In these kind of shared antenna desings, when WLAN powersave is fully disabled, Bluetooth will not work simultaneously with WLAN at all. This patch does not address that problem. This interface will not change PSM state, so if PSM is disabled it will remain so. Solving this problem requires knowledge about BT state, and is best done in user-space. Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--include/net/mac80211.h39
-rw-r--r--net/mac80211/ieee80211_i.h2
-rw-r--r--net/mac80211/mlme.c39
3 files changed, 79 insertions, 1 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index fe1a3a603375..7f256e23c57f 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);
2447void ieee80211_connection_loss(struct ieee80211_vif *vif); 2456void 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 */
2474void 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 */
2486void 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 fb5430188e87..f9251d50192c 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 85c3ca33333e..d1962650b254 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
481void 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}
494EXPORT_SYMBOL(ieee80211_enable_dyn_ps);
495
496void 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}
512EXPORT_SYMBOL(ieee80211_disable_dyn_ps);
513
481/* powersave */ 514/* powersave */
482static void ieee80211_enable_ps(struct ieee80211_local *local, 515static 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;