summaryrefslogtreecommitdiff
path: root/drivers/staging/cw1200/sta.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/cw1200/sta.c')
-rw-r--r--drivers/staging/cw1200/sta.c56
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 */