summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAmit <amit.shakya@stericsson.com>2011-08-11 19:33:19 +0530
committerPhilippe LANGLAIS <philippe.langlais@stericsson.com>2011-10-13 10:03:25 +0200
commit3dded119d7f7479e563b20d89aafa0b165249e36 (patch)
treea3305abae2c6468c89d099fbe9d94c0dbba44062
parent0c985dc57c573459b04a5d0188bf4a1be5250ab7 (diff)
cw1200: Add changes for UAPSD
* Added OID configuration for UAPSD configuration and related data structure updates * Added code to disable FastPS at FW in driver when UAPSD is enabled. * Restructured the code Change-Id: Ia64533960698646494268599c7f8f9aea57e4d88 Signed-off-by: Amit Shakya <amit.shakya@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/29063 Reviewed-by: Dmitry TARNYAGIN <dmitry.tarnyagin@stericsson.com> Reviewed-by: Bartosz MARKOWSKI <bartosz.markowski@tieto.com> Tested-by: Bartosz MARKOWSKI <bartosz.markowski@tieto.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33509 Tested-by: Dmitry TARNYAGIN <dmitry.tarnyagin@stericsson.com> Reviewed-by: Philippe LANGLAIS <philippe.langlais@stericsson.com>
-rwxr-xr-xdrivers/staging/cw1200/ap.c4
-rw-r--r--drivers/staging/cw1200/cw1200.h2
-rw-r--r--drivers/staging/cw1200/main.c2
-rw-r--r--drivers/staging/cw1200/sta.c76
-rw-r--r--drivers/staging/cw1200/sta.h4
-rw-r--r--drivers/staging/cw1200/wsm.h28
6 files changed, 107 insertions, 9 deletions
diff --git a/drivers/staging/cw1200/ap.c b/drivers/staging/cw1200/ap.c
index 28cb11faa35..2a6d27f212f 100755
--- a/drivers/staging/cw1200/ap.c
+++ b/drivers/staging/cw1200/ap.c
@@ -352,9 +352,10 @@ void cw1200_bss_info_changed(struct ieee80211_hw *dev,
WARN_ON(wsm_set_association_mode(priv,
&priv->association_mode));
WARN_ON(wsm_set_bss_params(priv, &priv->bss_params));
+ priv->setbssparams_done = true;
WARN_ON(wsm_set_beacon_wakeup_period(priv,
dtim_interval, listen_interval));
- WARN_ON(wsm_set_pm(priv, &priv->powersave_mode));
+ cw1200_set_pm(priv, &priv->powersave_mode);
#if 0
/* It's better to override internal TX rete; otherwise
* device sends RTS at too high rate. However device
@@ -460,6 +461,7 @@ void cw1200_bss_info_changed(struct ieee80211_hw *dev,
priv->cqm_beacon_loss_count :
priv->cqm_link_loss_count;
WARN_ON(wsm_set_bss_params(priv, &priv->bss_params));
+ priv->setbssparams_done = true;
}
#endif /* CONFIG_CW1200_USE_STE_EXTENSIONS */
}
diff --git a/drivers/staging/cw1200/cw1200.h b/drivers/staging/cw1200/cw1200.h
index 80eb3c49f81..e4fda896b78 100644
--- a/drivers/staging/cw1200/cw1200.h
+++ b/drivers/staging/cw1200/cw1200.h
@@ -118,6 +118,8 @@ struct cw1200_common {
struct wsm_multicast_filter multicast_filter;
struct cw1200_pm_state pm_state;
struct wsm_p2p_ps_modeinfo p2p_ps_modeinfo;
+ struct wsm_uapsd_info uapsd_info;
+ bool setbssparams_done;
/* BH */
atomic_t bh_rx;
diff --git a/drivers/staging/cw1200/main.c b/drivers/staging/cw1200/main.c
index 8ba8629cb03..e9e6806e811 100644
--- a/drivers/staging/cw1200/main.c
+++ b/drivers/staging/cw1200/main.c
@@ -251,7 +251,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_SUPPORTS_UAPSD |
IEEE80211_HW_CONNECTION_MONITOR |
IEEE80211_HW_SUPPORTS_CQM_RSSI |
/* Aggregation is fully controlled by firmware.
diff --git a/drivers/staging/cw1200/sta.c b/drivers/staging/cw1200/sta.c
index df9a8ead315..055d231fc01 100644
--- a/drivers/staging/cw1200/sta.c
+++ b/drivers/staging/cw1200/sta.c
@@ -50,14 +50,20 @@ int cw1200_start(struct ieee80211_hw *dev)
mutex_lock(&priv->conf_mutex);
/* default ECDA */
- WSM_EDCA_SET(&priv->edca, 0, 0x0002, 0x0003, 0x0007, 47);
- WSM_EDCA_SET(&priv->edca, 1, 0x0002, 0x0007, 0x000f, 94);
- WSM_EDCA_SET(&priv->edca, 2, 0x0003, 0x000f, 0x03ff, 0);
- WSM_EDCA_SET(&priv->edca, 3, 0x0007, 0x000f, 0x03ff, 0);
+ WSM_EDCA_SET(&priv->edca, 0, 0x0002, 0x0003, 0x0007, 47, false);
+ WSM_EDCA_SET(&priv->edca, 1, 0x0002, 0x0007, 0x000f, 94, false);
+ WSM_EDCA_SET(&priv->edca, 2, 0x0003, 0x000f, 0x03ff, 0, false);
+ WSM_EDCA_SET(&priv->edca, 3, 0x0007, 0x000f, 0x03ff, 0, false);
ret = wsm_set_edca_params(priv, &priv->edca);
if (WARN_ON(ret))
goto out;
+ ret = cw1200_set_uapsd_param(priv, &priv->edca);
+ if (WARN_ON(ret))
+ goto out;
+
+ priv->setbssparams_done = false;
+
memset(priv->bssid, ~0, ETH_ALEN);
memcpy(priv->mac_addr, dev->wiphy->perm_addr, ETH_ALEN);
priv->mode = NL80211_IFTYPE_MONITOR;
@@ -315,7 +321,7 @@ int cw1200_config(struct ieee80211_hw *dev, u32 changed)
conf->dynamic_ps_timeout << 1;
if (priv->join_status == CW1200_JOIN_STATUS_STA)
- WARN_ON(wsm_set_pm(priv, &priv->powersave_mode));
+ cw1200_set_pm(priv, &priv->powersave_mode);
}
if (changed & IEEE80211_CONF_CHANGE_P2P_PS) {
@@ -505,13 +511,26 @@ int cw1200_conf_tx(struct ieee80211_hw *dev, u16 queue,
{
struct cw1200_common *priv = dev->priv;
int ret = 0;
+ /* To prevent re-applying PM request OID again and again*/
+ bool old_uapsdFlags;
mutex_lock(&priv->conf_mutex);
if (queue < dev->queues) {
+ old_uapsdFlags = priv->uapsd_info.uapsdFlags;
+
WSM_EDCA_SET(&priv->edca, queue, params->aifs,
- params->cw_min, params->cw_max, params->txop);
+ params->cw_min, params->cw_max, params->txop,
+ params->uapsd);
ret = wsm_set_edca_params(priv, &priv->edca);
+
+ if (!ret && (priv->mode == NL80211_IFTYPE_STATION)) {
+ ret = cw1200_set_uapsd_param(priv, &priv->edca);
+ if (!ret && priv->setbssparams_done &&
+ (priv->join_status == CW1200_JOIN_STATUS_STA) &&
+ (old_uapsdFlags != priv->uapsd_info.uapsdFlags))
+ cw1200_set_pm(priv, &priv->powersave_mode);
+ }
} else
ret = -EINVAL;
@@ -542,6 +561,16 @@ int cw1200_get_tx_stats(struct ieee80211_hw *dev,
}
*/
+int cw1200_set_pm(struct cw1200_common *priv, const struct wsm_set_pm *arg)
+{
+ struct wsm_set_pm pm = *arg;
+
+ if (priv->uapsd_info.uapsdFlags != 0)
+ pm.pmMode &= ~WSM_PSM_FAST_PS_FLAG;
+
+ return wsm_set_pm(priv, &pm);
+}
+
int cw1200_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd,
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
struct ieee80211_key_conf *key)
@@ -1169,6 +1198,8 @@ void cw1200_unjoin_work(struct work_struct *work)
cancel_delayed_work_sync(&priv->connection_loss_work);
cw1200_update_listening(priv, priv->listening);
cw1200_update_filtering(priv);
+ priv->setbssparams_done = false;
+
sta_printk(KERN_DEBUG "[STA] Unjoin.\n");
}
mutex_unlock(&priv->conf_mutex);
@@ -1222,6 +1253,39 @@ void cw1200_update_listening(struct cw1200_common *priv, bool enabled)
}
}
+int cw1200_set_uapsd_param(struct cw1200_common *priv,
+ const struct wsm_edca_params *arg)
+{
+ int ret;
+ u16 uapsdFlags = 0;
+
+ /* Here's the mapping AC [queue, bit]
+ VO [0,3], VI [1, 2], BE [2, 1], BK [3, 0]*/
+
+ if (arg->params[0].uapsdEnable)
+ uapsdFlags |= 1 << 3;
+
+ if (arg->params[1].uapsdEnable)
+ uapsdFlags |= 1 << 2;
+
+ if (arg->params[2].uapsdEnable)
+ uapsdFlags |= 1 << 1;
+
+ if (arg->params[3].uapsdEnable)
+ uapsdFlags |= 1;
+
+ /* Currently pseudo U-APSD operation is not supported, so setting
+ * MinAutoTriggerInterval, MaxAutoTriggerInterval and
+ * AutoTriggerStep to 0 */
+
+ priv->uapsd_info.uapsdFlags = cpu_to_le16(uapsdFlags);
+ priv->uapsd_info.minAutoTriggerInterval = 0;
+ priv->uapsd_info.maxAutoTriggerInterval = 0;
+ priv->uapsd_info.autoTriggerStep = 0;
+
+ ret = wsm_set_uapsd_info(priv, &priv->uapsd_info);
+ return ret;
+}
/* ******************************************************************** */
/* STA privates */
diff --git a/drivers/staging/cw1200/sta.h b/drivers/staging/cw1200/sta.h
index 88c1cf6a34b..88a08aaceaf 100644
--- a/drivers/staging/cw1200/sta.h
+++ b/drivers/staging/cw1200/sta.h
@@ -45,6 +45,8 @@ void cw1200_flush(struct ieee80211_hw *hw, bool drop);
u64 cw1200_prepare_multicast(struct ieee80211_hw *hw,
struct netdev_hw_addr_list *mc_list);
+int cw1200_set_pm(struct cw1200_common *priv, const struct wsm_set_pm *arg);
+
/* ******************************************************************** */
/* WSM callbacks */
@@ -76,5 +78,7 @@ void cw1200_update_filtering(struct cw1200_common *priv);
int __cw1200_flush(struct cw1200_common *priv, bool drop);
int cw1200_enable_listening(struct cw1200_common *priv);
int cw1200_disable_listening(struct cw1200_common *priv);
+int cw1200_set_uapsd_param(struct cw1200_common *priv,
+ const struct wsm_edca_params *arg);
#endif
diff --git a/drivers/staging/cw1200/wsm.h b/drivers/staging/cw1200/wsm.h
index 542eededffc..30db888e535 100644
--- a/drivers/staging/cw1200/wsm.h
+++ b/drivers/staging/cw1200/wsm.h
@@ -135,6 +135,9 @@ struct cw1200_common;
/* 802.11 PS mode */
#define WSM_PSM_PS BIT(0)
+/* Fast Power Save bit */
+#define WSM_PSM_FAST_PS_FLAG BIT(7)
+
/* Dynamic aka Fast power save */
#define WSM_PSM_FAST_PS (BIT(0) | BIT(7))
@@ -1044,6 +1047,9 @@ struct wsm_edca_queue_params {
/* the access class. Overrides the global */
/* dot11MaxReceiveLifetime value */
/* [in] */ u32 maxReceiveLifetime;
+
+ /* UAPSD trigger support for the access class. */
+ /* [in] */ bool uapsdEnable;
};
struct wsm_edca_params {
@@ -1051,18 +1057,22 @@ struct wsm_edca_params {
struct wsm_edca_queue_params params[4];
};
-#define WSM_EDCA_SET(edca, queue, aifs, cw_min, cw_max, txop) \
+#define WSM_EDCA_SET(edca, queue, aifs, cw_min, cw_max, txop, uapsd) \
do { \
struct wsm_edca_queue_params *p = &(edca)->params[queue]; \
p->cwMin = (cw_min); \
p->cwMax = (cw_max); \
p->aifns = (aifs); \
p->txOpLimit = (txop); \
+ p->uapsdEnable = (uapsd); \
} while (0)
int wsm_set_edca_params(struct cw1200_common *priv,
const struct wsm_edca_params *arg);
+int wsm_set_uapsd_param(struct cw1200_common *priv,
+ const struct wsm_edca_params *arg);
+
/* 3.38 */
/* Set-System info. Skipped for now. Irrelevent. */
@@ -1548,6 +1558,22 @@ static inline int wsm_use_multi_tx_conf(struct cw1200_common *priv,
&arg, sizeof(arg));
}
+
+/* 4.26 SetUpasdInformation */
+struct wsm_uapsd_info {
+ __le16 uapsdFlags;
+ __le16 minAutoTriggerInterval;
+ __le16 maxAutoTriggerInterval;
+ __le16 autoTriggerStep;
+};
+
+static inline int wsm_set_uapsd_info(struct cw1200_common *priv,
+ struct wsm_uapsd_info *arg)
+{
+ return wsm_write_mib(priv, WSM_MIB_ID_SET_UAPSD_INFORMATION,
+ arg, sizeof(*arg));
+}
+
/* ******************************************************************** */
/* WSM TX port control */