diff options
Diffstat (limited to 'drivers/staging/cw1200/sta.c')
-rw-r--r-- | drivers/staging/cw1200/sta.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/drivers/staging/cw1200/sta.c b/drivers/staging/cw1200/sta.c index 85e57d2f7b3..c5b79f25060 100644 --- a/drivers/staging/cw1200/sta.c +++ b/drivers/staging/cw1200/sta.c @@ -123,6 +123,7 @@ void cw1200_stop(struct ieee80211_hw *dev) cancel_delayed_work_sync(&priv->link_id_gc_work); flush_workqueue(priv->workqueue); del_timer_sync(&priv->mcast_timeout); + del_timer_sync(&priv->ba_timer); mutex_lock(&priv->conf_mutex); priv->mode = NL80211_IFTYPE_UNSPECIFIED; @@ -1360,6 +1361,13 @@ void cw1200_join_work(struct work_struct *work) WARN_ON(wsm_set_block_ack_policy(priv, 0, priv->ba_tid_mask)); + spin_lock_bh(&priv->ba_lock); + priv->ba_ena = false; + priv->ba_cnt = 0; + priv->ba_acc = 0; + priv->ba_hist = 0; + spin_unlock_bh(&priv->ba_lock); + mgmt_policy.protectedMgmtEnable = 0; mgmt_policy.unprotectedMgmtFramesAllowed = 1; mgmt_policy.encryptionForAuthFrame = 1; @@ -1409,6 +1417,7 @@ void cw1200_unjoin_work(struct work_struct *work) .reset_statistics = true, }; + del_timer_sync(&priv->ba_timer); mutex_lock(&priv->conf_mutex); if (unlikely(atomic_read(&priv->scan.in_progress))) { if (priv->delayed_unjoin) { @@ -1543,6 +1552,53 @@ int cw1200_set_uapsd_param(struct cw1200_common *priv, return ret; } +void cw1200_ba_work(struct work_struct *work) +{ + struct cw1200_common *priv = + container_of(work, struct cw1200_common, ba_work); + u8 tx_ba_tid_mask; + + if (priv->join_status != CW1200_JOIN_STATUS_STA) + return; + if (!priv->setbssparams_done) + return; + + spin_lock_bh(&priv->ba_lock); + tx_ba_tid_mask = priv->ba_ena ? priv->ba_tid_mask : 0; + spin_unlock_bh(&priv->ba_lock); + + WARN_ON(wsm_set_block_ack_policy(priv, + tx_ba_tid_mask, priv->ba_tid_mask)); +} + +void cw1200_ba_timer(unsigned long arg) +{ + bool ba_ena; + struct cw1200_common *priv = + (struct cw1200_common *)arg; + + spin_lock_bh(&priv->ba_lock); + cw1200_debug_ba(priv, priv->ba_cnt, priv->ba_acc); + + ba_ena = (priv->ba_cnt >= CW1200_BLOCK_ACK_CNT && + priv->ba_acc / priv->ba_cnt >= CW1200_BLOCK_ACK_THLD); + priv->ba_cnt = 0; + priv->ba_acc = 0; + + if (ba_ena != priv->ba_ena) { + if (ba_ena || ++priv->ba_hist >= CW1200_BLOCK_ACK_HIST) { + priv->ba_ena = ba_ena; + priv->ba_hist = 0; + sta_printk(KERN_DEBUG "[STA] %s block ACK:\n", + ba_ena ? "enable" : "disable"); + queue_work(priv->workqueue, &priv->ba_work); + } + } else if (priv->ba_hist) + --priv->ba_hist; + + spin_unlock_bh(&priv->ba_lock); +} + /* ******************************************************************** */ /* STA privates */ |