diff options
author | Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com> | 2012-02-29 15:14:56 +0100 |
---|---|---|
committer | Philippe Langlais <philippe.langlais@stericsson.com> | 2012-05-22 11:06:43 +0200 |
commit | 4b342aae42b72bec87d77ae09c01f38bf6b985a3 (patch) | |
tree | f729d6e8165bc75950de2306e9dd03d3a9f5d456 | |
parent | 3b60c6178c1b44e01aebe2139b1187719a3b7cbd (diff) |
cw1200: Enable beacon skipping.
Beacon skipping is implemented to reduce power consumption in
suspend state. It is enabled in STA mode when there is no
active milticast subscriptions. Up to 2 beacons can be skipped
in a row.
ST-Ericsson ID: 373856
ST-Ericsson FOSS-OUT ID: Trivial
Change-Id: Idd47937a21d7e2e188e0081d937770181f1f3f0e
Signed-off-by: Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com>
Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/39312
Reviewed-by: Bartosz MARKOWSKI <bartosz.markowski@tieto.com>
Tested-by: Bartosz MARKOWSKI <bartosz.markowski@tieto.com>
-rw-r--r-- | drivers/staging/cw1200/cw1200.h | 1 | ||||
-rw-r--r-- | drivers/staging/cw1200/pm.c | 20 | ||||
-rw-r--r-- | drivers/staging/cw1200/sta.c | 10 |
3 files changed, 31 insertions, 0 deletions
diff --git a/drivers/staging/cw1200/cw1200.h b/drivers/staging/cw1200/cw1200.h index 8ee88b64e38..d3ecb2a950f 100644 --- a/drivers/staging/cw1200/cw1200.h +++ b/drivers/staging/cw1200/cw1200.h @@ -145,6 +145,7 @@ struct cw1200_common { struct wsm_beacon_filter_table bf_table; struct wsm_beacon_filter_control bf_control; struct wsm_multicast_filter multicast_filter; + bool has_multicast_subscription; bool disable_beacon_filter; struct work_struct update_filtering_work; u8 ba_tid_mask; diff --git a/drivers/staging/cw1200/pm.c b/drivers/staging/cw1200/pm.c index 7c1a957de3e..9eece65a709 100644 --- a/drivers/staging/cw1200/pm.c +++ b/drivers/staging/cw1200/pm.c @@ -16,6 +16,8 @@ #include "bh.h" #include "sbus.h" +#define CW1200_BEACON_SKIPPING_MULTIPLIER 3 + static int cw1200_suspend_late(struct device *dev); static void cw1200_pm_release(struct device *dev); static int cw1200_pm_probe(struct platform_device *pdev); @@ -27,6 +29,7 @@ struct cw1200_suspend_state { unsigned long join_tmo; unsigned long direct_probe; unsigned long link_id_gc; + bool beacon_skipping; }; static const struct dev_pm_ops cw1200_pm_ops = { @@ -252,6 +255,17 @@ int cw1200_wow_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) state->link_id_gc = cw1200_suspend_work(&priv->link_id_gc_work); + /* Enable beacon skipping */ + if (priv->join_status == CW1200_JOIN_STATUS_STA + && priv->join_dtim_period + && !priv->has_multicast_subscription) { + state->beacon_skipping = true; + wsm_set_beacon_wakeup_period(priv, + priv->join_dtim_period, + CW1200_BEACON_SKIPPING_MULTIPLIER * + priv->join_dtim_period); + } + /* Stop serving thread */ if (cw1200_bh_suspend(priv)) goto revert4; @@ -318,6 +332,12 @@ int cw1200_wow_resume(struct ieee80211_hw *hw) /* Resume BH thread */ WARN_ON(cw1200_bh_resume(priv)); + if (state->beacon_skipping) { + wsm_set_beacon_wakeup_period(priv, + priv->join_dtim_period, 0); + state->beacon_skipping = false; + } + /* Resume delayed work */ cw1200_resume_work(priv, &priv->bss_loss_work, state->bss_loss_tmo); diff --git a/drivers/staging/cw1200/sta.c b/drivers/staging/cw1200/sta.c index 5f431a0e2de..7a0830e5410 100644 --- a/drivers/staging/cw1200/sta.c +++ b/drivers/staging/cw1200/sta.c @@ -462,11 +462,18 @@ void cw1200_update_filtering_work(struct work_struct *work) u64 cw1200_prepare_multicast(struct ieee80211_hw *hw, struct netdev_hw_addr_list *mc_list) { + static u8 broadcast_ipv6[ETH_ALEN] = { + 0x33, 0x33, 0x00, 0x00, 0x00, 0x01 + }; + static u8 broadcast_ipv4[ETH_ALEN] = { + 0x01, 0x00, 0x5e, 0x00, 0x00, 0x01 + }; struct cw1200_common *priv = hw->priv; struct netdev_hw_addr *ha; int count = 0; /* Disable multicast filtering */ + priv->has_multicast_subscription = false; memset(&priv->multicast_filter, 0x00, sizeof(priv->multicast_filter)); if (netdev_hw_addr_list_count(mc_list) > WSM_MAX_GRP_ADDRTABLE_ENTRIES) @@ -477,6 +484,9 @@ u64 cw1200_prepare_multicast(struct ieee80211_hw *hw, sta_printk(KERN_DEBUG "[STA] multicast: %pM\n", ha->addr); memcpy(&priv->multicast_filter.macAddress[count], ha->addr, ETH_ALEN); + if (memcmp(ha->addr, broadcast_ipv4, ETH_ALEN) && + memcmp(ha->addr, broadcast_ipv6, ETH_ALEN)) + priv->has_multicast_subscription = true; count++; } |