summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDmitry Tarnyagin <dmitry.tarnyagin@stericsson.com>2012-02-29 15:15:12 +0100
committerPhilippe Langlais <philippe.langlais@stericsson.com>2012-05-22 11:06:45 +0200
commitcf34ec6ed84c0193c1c73d4f453542772dbb3d8b (patch)
treea2cfe07869736c234c38f083ff94cf3915b1e2ad
parentaaf70cd3abfd3a856c01382905021225b6fd1d8a (diff)
cw1200: Correctly handle requeuing for NOA.
Firmware may report exit of GO absence interval as a start: unicast suspend/resume notification with link id equals to 0. This case was not handled correctly. The patch implements (costly!) solution for that. Start: unicast indication resets power save states of all connected STAs, and driver performs an attempt to deliver buffered frames for them. For STAs in powersave frirmware rejects frames, syncronizing power state. The solution is really costly and can be used as a workaround in short time prospective. It's much better if firmware reports proper link id in the suspend/resume notification. ST-Ericsson ID: 400498 Change-Id: Iaa124ce7013605abee264e503e160eda32140bdc Signed-off-by: Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/42108 Tested-by: Bartosz MARKOWSKI <bartosz.markowski@tieto.com> Reviewed-by: Bartosz MARKOWSKI <bartosz.markowski@tieto.com>
-rw-r--r--drivers/staging/cw1200/ap.c46
1 files changed, 23 insertions, 23 deletions
diff --git a/drivers/staging/cw1200/ap.c b/drivers/staging/cw1200/ap.c
index c104b39d8f8..ca2abbe93b8 100644
--- a/drivers/staging/cw1200/ap.c
+++ b/drivers/staging/cw1200/ap.c
@@ -32,7 +32,7 @@ static int cw1200_enable_beaconing(struct cw1200_common *priv,
static void __cw1200_sta_notify(struct ieee80211_hw *dev,
struct ieee80211_vif *vif,
enum sta_notify_cmd notify_cmd,
- struct ieee80211_sta *sta);
+ int link_id);
/* ******************************************************************** */
/* AP API */
@@ -94,13 +94,19 @@ int cw1200_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
static void __cw1200_sta_notify(struct ieee80211_hw *dev,
struct ieee80211_vif *vif,
enum sta_notify_cmd notify_cmd,
- struct ieee80211_sta *sta)
+ int link_id)
{
struct cw1200_common *priv = dev->priv;
- struct cw1200_sta_priv *sta_priv =
- (struct cw1200_sta_priv *)&sta->drv_priv;
- u32 bit = BIT(sta_priv->link_id);
- u32 prev = priv->sta_asleep_mask & bit;
+ u32 bit, prev;
+
+ /* Zero link id means "for all link IDs" */
+ if (link_id)
+ bit = BIT(link_id);
+ else if (WARN_ON_ONCE(notify_cmd != STA_NOTIFY_AWAKE))
+ bit = 0;
+ else
+ bit = priv->link_id_map;
+ prev = priv->sta_asleep_mask & bit;
switch (notify_cmd) {
case STA_NOTIFY_SLEEP:
@@ -116,7 +122,7 @@ static void __cw1200_sta_notify(struct ieee80211_hw *dev,
if (prev) {
priv->sta_asleep_mask &= ~bit;
priv->pspoll_mask &= ~bit;
- if (priv->tx_multicast &&
+ if (priv->tx_multicast && link_id &&
!priv->sta_asleep_mask)
queue_work(priv->workqueue,
&priv->multicast_stop_work);
@@ -132,8 +138,11 @@ void cw1200_sta_notify(struct ieee80211_hw *dev,
struct ieee80211_sta *sta)
{
struct cw1200_common *priv = dev->priv;
+ struct cw1200_sta_priv *sta_priv =
+ (struct cw1200_sta_priv *)&sta->drv_priv;
+
spin_lock_bh(&priv->ps_state_lock);
- __cw1200_sta_notify(dev, vif, notify_cmd, sta);
+ __cw1200_sta_notify(dev, vif, notify_cmd, sta_priv->link_id);
spin_unlock_bh(&priv->ps_state_lock);
}
@@ -142,21 +151,15 @@ static void cw1200_ps_notify(struct cw1200_common *priv,
{
struct ieee80211_sta *sta;
- if (!link_id || link_id > CW1200_MAX_STA_IN_AP_MODE)
+ if (link_id > CW1200_MAX_STA_IN_AP_MODE)
return;
txrx_printk(KERN_DEBUG "%s for LinkId: %d. STAs asleep: %.8X\n",
ps ? "Stop" : "Start",
link_id, priv->sta_asleep_mask);
- rcu_read_lock();
- sta = ieee80211_find_sta(priv->vif,
- priv->link_id_db[link_id - 1].mac);
- if (sta) {
- __cw1200_sta_notify(priv->hw, priv->vif,
- ps ? STA_NOTIFY_SLEEP : STA_NOTIFY_AWAKE, sta);
- }
- rcu_read_unlock();
+ __cw1200_sta_notify(priv->hw, priv->vif,
+ ps ? STA_NOTIFY_SLEEP : STA_NOTIFY_AWAKE, link_id);
}
static int cw1200_set_tim_impl(struct cw1200_common *priv, bool aid0_bit_set)
@@ -680,12 +683,9 @@ int cw1200_ampdu_action(struct ieee80211_hw *hw,
void cw1200_suspend_resume(struct cw1200_common *priv,
struct wsm_suspend_resume *arg)
{
- /* if () is intendend to protect against spam. FW sends
- * "start multicast" request on every DTIM. */
- if (arg->stop || !arg->multicast || priv->buffered_multicasts)
- ap_printk(KERN_DEBUG "[AP] %s: %s\n",
- arg->stop ? "stop" : "start",
- arg->multicast ? "broadcast" : "unicast");
+ ap_printk(KERN_DEBUG "[AP] %s: %s\n",
+ arg->stop ? "stop" : "start",
+ arg->multicast ? "broadcast" : "unicast");
if (arg->multicast) {
bool cancel_tmo = false;