summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Tarnyagin <dmitry.tarnyagin@stericsson.com>2011-07-07 22:12:01 +0200
committerPhilippe LANGLAIS <philippe.langlais@stericsson.com>2011-10-12 13:44:49 +0200
commit7fe82611337427cea5c6eae91df202b8a2985252 (patch)
tree77381f020e952e1e1cda7a61d79c0418d106bd70
parent033b8d2a992e339e2dfdeb83144efa41695e4068 (diff)
cw1200: Dynamic power save is offloaded to the firmware.
Signed-off-by: Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com> Change-Id: Iff214651c82fe1f7203f3ce016e7646e41cccc35 Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/27071 Reviewed-by: Bartosz MARKOWSKI <bartosz.markowski@tieto.com> Tested-by: Bartosz MARKOWSKI <bartosz.markowski@tieto.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33478 Reviewed-by: Philippe LANGLAIS <philippe.langlais@stericsson.com>
-rw-r--r--drivers/staging/cw1200/debug.c15
-rw-r--r--drivers/staging/cw1200/main.c1
-rw-r--r--drivers/staging/cw1200/scan.c4
-rw-r--r--drivers/staging/cw1200/sta.c19
-rw-r--r--drivers/staging/cw1200/wsm.c5
-rw-r--r--drivers/staging/cw1200/wsm.h10
6 files changed, 41 insertions, 13 deletions
diff --git a/drivers/staging/cw1200/debug.c b/drivers/staging/cw1200/debug.c
index 13c4570372f..612c74a7174 100644
--- a/drivers/staging/cw1200/debug.c
+++ b/drivers/staging/cw1200/debug.c
@@ -153,6 +153,18 @@ static int cw1200_status_show(struct seq_file *seq, void *v)
priv->edca.params[i].maxReceiveLifetime);
}
if (priv->join_status == CW1200_JOIN_STATUS_STA) {
+ static const char *pmMode = "unknown";
+ switch (priv->powersave_mode.pmMode) {
+ case WSM_PSM_ACTIVE:
+ pmMode = "off";
+ break;
+ case WSM_PSM_PS:
+ pmMode = "on";
+ break;
+ case WSM_PSM_FAST_PS:
+ pmMode = "dynamic";
+ break;
+ }
seq_printf(seq, "Preamble: %s\n",
cw1200_debug_preamble[
priv->association_mode.preambleType]);
@@ -166,8 +178,7 @@ static int cw1200_status_show(struct seq_file *seq, void *v)
priv->bss_params.aid);
seq_printf(seq, "Rates: 0x%.8X\n",
priv->bss_params.operationalRateSet);
- seq_printf(seq, "Powersave: %s\n",
- priv->powersave_mode.pmMode ? "off" : "on");
+ seq_printf(seq, "Powersave: %s\n", pmMode);
}
seq_printf(seq, "HT: %s\n",
cw1200_is_ht(&priv->ht_info) ? "on" : "off");
diff --git a/drivers/staging/cw1200/main.c b/drivers/staging/cw1200/main.c
index 7aef0ea1c60..f809ebc7584 100644
--- a/drivers/staging/cw1200/main.c
+++ b/drivers/staging/cw1200/main.c
@@ -242,6 +242,7 @@ struct ieee80211_hw *cw1200_init_common(size_t priv_data_len)
hw->flags = IEEE80211_HW_SIGNAL_DBM |
IEEE80211_HW_SUPPORTS_PS |
+ IEEE80211_HW_SUPPORTS_DYNAMIC_PS |
/* IEEE80211_HW_SUPPORTS_UAPSD | */
IEEE80211_HW_CONNECTION_MONITOR |
IEEE80211_HW_SUPPORTS_CQM_RSSI |
diff --git a/drivers/staging/cw1200/scan.c b/drivers/staging/cw1200/scan.c
index 71268291181..6e5b89c5635 100644
--- a/drivers/staging/cw1200/scan.c
+++ b/drivers/staging/cw1200/scan.c
@@ -88,7 +88,7 @@ int cw1200_hw_scan(struct ieee80211_hw *hw,
wsm_lock_tx(priv);
if (priv->join_status == CW1200_JOIN_STATUS_STA &&
- priv->powersave_mode.pmMode != WSM_PSM_PS) {
+ !(priv->powersave_mode.pmMode & WSM_PSM_PS)) {
struct wsm_set_pm pm = priv->powersave_mode;
pm.pmMode = WSM_PSM_PS;
WARN_ON(wsm_set_pm(priv, &pm));
@@ -139,7 +139,7 @@ void cw1200_scan_work(struct work_struct *work)
WARN_ON(wsm_set_output_power(priv,
priv->output_power * 10));
if (priv->join_status == CW1200_JOIN_STATUS_STA &&
- priv->powersave_mode.pmMode != WSM_PSM_PS)
+ !(priv->powersave_mode.pmMode & WSM_PSM_PS))
WARN_ON(wsm_set_pm(priv, &priv->powersave_mode));
if (priv->scan.req)
diff --git a/drivers/staging/cw1200/sta.c b/drivers/staging/cw1200/sta.c
index a5b0f0ea759..fb5576f688a 100644
--- a/drivers/staging/cw1200/sta.c
+++ b/drivers/staging/cw1200/sta.c
@@ -285,9 +285,22 @@ int cw1200_config(struct ieee80211_hw *dev, u32 changed)
}
if (changed & IEEE80211_CONF_CHANGE_PS) {
- priv->powersave_mode.pmMode =
- (conf->flags & IEEE80211_CONF_PS) ?
- WSM_PSM_PS : WSM_PSM_ACTIVE;
+ if (!(conf->flags & IEEE80211_CONF_PS))
+ priv->powersave_mode.pmMode = WSM_PSM_ACTIVE;
+ else if (conf->dynamic_ps_timeout <= 0)
+ priv->powersave_mode.pmMode = WSM_PSM_PS;
+ else
+ priv->powersave_mode.pmMode = WSM_PSM_FAST_PS;
+
+ /* Firmware requires that value for this 1-byte field must
+ * be specified in units of 500us. Values above the 128ms
+ * threshold are not supported. */
+ if (conf->dynamic_ps_timeout >= 0x80)
+ priv->powersave_mode.fastPsmIdlePeriod = 0xFF;
+ else
+ priv->powersave_mode.fastPsmIdlePeriod =
+ conf->dynamic_ps_timeout << 1;
+
if (priv->join_status == CW1200_JOIN_STATUS_STA)
WARN_ON(wsm_set_pm(priv, &priv->powersave_mode));
}
diff --git a/drivers/staging/cw1200/wsm.c b/drivers/staging/cw1200/wsm.c
index c562f982477..e8662fa6054 100644
--- a/drivers/staging/cw1200/wsm.c
+++ b/drivers/staging/cw1200/wsm.c
@@ -654,7 +654,10 @@ int wsm_set_pm(struct cw1200_common *priv, const struct wsm_set_pm *arg)
wsm_cmd_lock(priv);
- WSM_PUT32(buf, arg->pmMode);
+ WSM_PUT8(buf, arg->pmMode);
+ WSM_PUT8(buf, arg->fastPsmIdlePeriod);
+ WSM_PUT8(buf, arg->apPsmChangePeriod);
+ WSM_PUT8(buf, arg->minAutoPsPollPeriod);
ret = wsm_cmd_send(priv, buf, NULL, 0x0010, WSM_CMD_TIMEOUT);
diff --git a/drivers/staging/cw1200/wsm.h b/drivers/staging/cw1200/wsm.h
index 4d446e9b924..d8db64da9b3 100644
--- a/drivers/staging/cw1200/wsm.h
+++ b/drivers/staging/cw1200/wsm.h
@@ -133,16 +133,16 @@ struct cw1200_common;
#define WSM_PSM_ACTIVE (0)
/* 802.11 PS mode */
-#define WSM_PSM_PS (1)
+#define WSM_PSM_PS BIT(0)
+
+/* Dynamic aka Fast power save */
+#define WSM_PSM_FAST_PS (BIT(0) | BIT(7))
/* Undetermined */
/* Note : Undetermined status is reported when the */
/* NULL data frame used to advertise the PM mode to */
/* the AP at Pre or Post Background Scan is not Acknowledged */
-#define WSM_PSM_UNKNOWN (2)
-
-/* Use this flag to enable the fast power-saving mode */
-#define WSM_PM_F_FAST_PSM_ENABLE (0x80)
+#define WSM_PSM_UNKNOWN BIT(1)
/* Queue IDs */
/* best effort/legacy */