summaryrefslogtreecommitdiff
path: root/drivers/staging/cw1200
diff options
context:
space:
mode:
authorDmitry Tarnyagin <dmitry.tarnyagin@stericsson.com>2012-02-29 15:15:12 +0100
committerPhilippe Langlais <philippe.langlais@linaro.org>2012-03-19 09:02:07 +0100
commit403b22abb65afcb9e162e1f2339a5fbf32382b28 (patch)
treedcf114a7076146bbaad2a6199c73322831e2344c /drivers/staging/cw1200
parent6722d8f5be35a9f12ad1a5b21e25ea6e4f8fb3e1 (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>
Diffstat (limited to 'drivers/staging/cw1200')
-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;