summaryrefslogtreecommitdiff
path: root/drivers/staging/cw1200/wsm.c
diff options
context:
space:
mode:
authorDmitry Tarnyagin <dmitry.tarnyagin@stericsson.com>2011-05-15 14:19:19 +0200
committerPhilippe Langlais <philippe.langlais@linaro.org>2012-03-19 09:01:46 +0100
commite9556031ee54755e70a3df7389e7dd2607051879 (patch)
tree993d84c8d49059e75f85f9611a8af53e04e0b2d6 /drivers/staging/cw1200/wsm.c
parent4cafdc7b2b56b7e0d791d17abbc6f653abdae62d (diff)
cw1200: Fix for buffered multicasts in AP-PS mode.
Refactoring of multicast handling: * When multicast is coming, driver sets aid0 bit in TIM IE and puts multicas in the queue with "AFTER_DTIM" link id. * When WSM indicates DTIM beacon, driver verifies if aid0 indicating beacon was sent and sends buffered multicasts. * Driver clears aid0 bit in the TIM IE when no more multicasts are available. + A stilistic change: 1 << shift is replaced by BIT(shift) Change-Id: I15b134bf847913a907f00293ae99d7a71bbc7343 Signed-off-by: Dmitry Tarnyagin <dmitry.tarnyagin@stericsson.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/27306 Reviewed-by: Bartosz MARKOWSKI <bartosz.markowski@tieto.com> Tested-by: Bartosz MARKOWSKI <bartosz.markowski@tieto.com> Reviewed-on: http://gerrit.lud.stericsson.com/gerrit/33488 Reviewed-by: Philippe LANGLAIS <philippe.langlais@stericsson.com>
Diffstat (limited to 'drivers/staging/cw1200/wsm.c')
-rw-r--r--drivers/staging/cw1200/wsm.c41
1 files changed, 31 insertions, 10 deletions
diff --git a/drivers/staging/cw1200/wsm.c b/drivers/staging/cw1200/wsm.c
index 604fa067ccc..6f40934ed8f 100644
--- a/drivers/staging/cw1200/wsm.c
+++ b/drivers/staging/cw1200/wsm.c
@@ -1423,7 +1423,7 @@ static int wsm_get_tx_queue_and_mask(struct cw1200_common *priv,
/* Search for a queue with multicast frames buffered */
if (priv->sta_asleep_mask && !priv->suspend_multicast) {
- tx_allowed_mask = 1 << CW1200_LINK_ID_AFTER_DTIM;
+ tx_allowed_mask = BIT(CW1200_LINK_ID_AFTER_DTIM);
for (i = 0; i < 4; ++i) {
mcasts += cw1200_queue_get_num_queued(
&priv->tx_queue[i], tx_allowed_mask);
@@ -1443,7 +1443,7 @@ static int wsm_get_tx_queue_and_mask(struct cw1200_common *priv,
if (priv->sta_asleep_mask) {
tx_allowed_mask |= ~priv->tx_suspend_mask[i];
} else {
- tx_allowed_mask |= 1 << CW1200_LINK_ID_AFTER_DTIM;
+ tx_allowed_mask |= BIT(CW1200_LINK_ID_AFTER_DTIM);
}
if (cw1200_queue_get_num_queued(
queue, tx_allowed_mask))
@@ -1486,13 +1486,39 @@ int wsm_get_tx(struct cw1200_common *priv, u8 **data,
spin_unlock(&priv->wsm_cmd.lock);
} else {
for (;;) {
+ bool obtain_lock = priv->sta_asleep_mask &&
+ !priv->suspend_multicast;
+ int ret;
+
if (atomic_add_return(0, &priv->tx_lock))
break;
- if (wsm_get_tx_queue_and_mask(priv, &queue,
- &tx_allowed_mask, &more))
+ if (obtain_lock)
+ spin_lock_bh(
+ &priv->buffered_multicasts_lock);
+
+ ret = wsm_get_tx_queue_and_mask(priv, &queue,
+ &tx_allowed_mask, &more);
+
+ if (priv->buffered_multicasts &&
+ priv->sta_asleep_mask &&
+ !priv->suspend_multicast &&
+ (ret || tx_allowed_mask !=
+ BIT(CW1200_LINK_ID_AFTER_DTIM))) {
+ priv->buffered_multicasts = false;
+ priv->suspend_multicast = true;
+ queue_work(priv->workqueue,
+ &priv->multicast_stop_work);
+ }
+
+ if (obtain_lock)
+ spin_unlock_bh(
+ &priv->buffered_multicasts_lock);
+
+ if (ret)
break;
+
if (cw1200_queue_get(queue,
tx_allowed_mask,
&wsm, &tx_info))
@@ -1513,6 +1539,7 @@ int wsm_get_tx(struct cw1200_common *priv, u8 **data,
*data = (u8 *)wsm;
*tx_len = __le16_to_cpu(wsm->hdr.len);
+
if (more) {
struct ieee80211_hdr *hdr =
(struct ieee80211_hdr *) &wsm[1];
@@ -1521,12 +1548,6 @@ int wsm_get_tx(struct cw1200_common *priv, u8 **data,
* to inform PS STAs */
hdr->frame_control |=
cpu_to_le16(IEEE80211_FCTL_MOREDATA);
- } else if (priv->mode == NL80211_IFTYPE_AP &&
- !priv->suspend_multicast) {
- priv->suspend_multicast = true;
- wsm_lock_tx_async(priv);
- queue_work(priv->workqueue,
- &priv->multicast_stop_work);
}
wsm_printk(KERN_DEBUG "[WSM] >>> 0x%.4X (%d) %p %c\n",