summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Tarnyagin <dmitry.tarnyagin@stericsson.com>2012-02-29 15:14:56 +0100
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-05-22 11:06:43 +0200
commit4b342aae42b72bec87d77ae09c01f38bf6b985a3 (patch)
treef729d6e8165bc75950de2306e9dd03d3a9f5d456
parent3b60c6178c1b44e01aebe2139b1187719a3b7cbd (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.h1
-rw-r--r--drivers/staging/cw1200/pm.c20
-rw-r--r--drivers/staging/cw1200/sta.c10
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++;
}