aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorVasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com>2012-05-30 02:57:12 -0400
committerKalle Valo <kvalo@qca.qualcomm.com>2012-06-11 09:13:41 -0400
commit7940bad50859026c0f11d2b7766571175b5e55c3 (patch)
tree4c3321d670b53de2f9f4b7c6b6dfd85537054ae4 /drivers
parent0faf745872f6d00afb318185e8fb181587974b5a (diff)
ath6kl: Fix unstable downlink throughput
There is frequent downlink throughput drop to 0 when operating at the signal level between -42dBm to -53dBm. This has been root caused to the delay in releasing pending a-mpdu subframes in reorder buffer. Right now the timeout value is 400ms, there is also a race condition where timeout handler can be delayed to run at an extra timeout interval. This patch reduces the timout interval to reasonable 100ms and makes sure releasing pending frames are not skipped in the timeout handler by removing the flag (rxtid->progress) which can delay the timeout logic. Reported-by: Yu Yanzhi <yanzhiy@qca.qualcomm.com> Signed-off-by: Vasanthakumar Thiagarajan <vthiagar@qca.qualcomm.com> Signed-off-by: Kalle Valo <kvalo@qca.qualcomm.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h3
-rw-r--r--drivers/net/wireless/ath/ath6kl/txrx.c42
2 files changed, 19 insertions, 26 deletions
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
index 12441f7d9036..b3eee10cf016 100644
--- a/drivers/net/wireless/ath/ath6kl/core.h
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -215,7 +215,7 @@ enum ath6kl_hw_flags {
215 215
216#define AGGR_NUM_OF_FREE_NETBUFS 16 216#define AGGR_NUM_OF_FREE_NETBUFS 16
217 217
218#define AGGR_RX_TIMEOUT 400 /* in ms */ 218#define AGGR_RX_TIMEOUT 100 /* in ms */
219 219
220#define WMI_TIMEOUT (2 * HZ) 220#define WMI_TIMEOUT (2 * HZ)
221 221
@@ -264,7 +264,6 @@ struct skb_hold_q {
264 264
265struct rxtid { 265struct rxtid {
266 bool aggr; 266 bool aggr;
267 bool progress;
268 bool timer_mon; 267 bool timer_mon;
269 u16 win_sz; 268 u16 win_sz;
270 u16 seq_next; 269 u16 seq_next;
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c
index 974c51053a71..7dfa0fd86d7b 100644
--- a/drivers/net/wireless/ath/ath6kl/txrx.c
+++ b/drivers/net/wireless/ath/ath6kl/txrx.c
@@ -1186,28 +1186,25 @@ static bool aggr_process_recv_frm(struct aggr_info_conn *agg_conn, u8 tid,
1186 aggr_deque_frms(agg_conn, tid, 0, 1); 1186 aggr_deque_frms(agg_conn, tid, 0, 1);
1187 1187
1188 if (agg_conn->timer_scheduled) 1188 if (agg_conn->timer_scheduled)
1189 rxtid->progress = true; 1189 return is_queued;
1190 else { 1190
1191 spin_lock_bh(&rxtid->lock); 1191 spin_lock_bh(&rxtid->lock);
1192 for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) { 1192 for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) {
1193 if (rxtid->hold_q[idx].skb) { 1193 if (rxtid->hold_q[idx].skb) {
1194 /* 1194 /*
1195 * There is a frame in the queue and no 1195 * There is a frame in the queue and no
1196 * timer so start a timer to ensure that 1196 * timer so start a timer to ensure that
1197 * the frame doesn't remain stuck 1197 * the frame doesn't remain stuck
1198 * forever. 1198 * forever.
1199 */ 1199 */
1200 agg_conn->timer_scheduled = true; 1200 agg_conn->timer_scheduled = true;
1201 mod_timer(&agg_conn->timer, 1201 mod_timer(&agg_conn->timer,
1202 (jiffies + 1202 (jiffies + (HZ * AGGR_RX_TIMEOUT) / 1000));
1203 HZ * (AGGR_RX_TIMEOUT) / 1000)); 1203 rxtid->timer_mon = true;
1204 rxtid->progress = false; 1204 break;
1205 rxtid->timer_mon = true;
1206 break;
1207 }
1208 } 1205 }
1209 spin_unlock_bh(&rxtid->lock);
1210 } 1206 }
1207 spin_unlock_bh(&rxtid->lock);
1211 1208
1212 return is_queued; 1209 return is_queued;
1213} 1210}
@@ -1612,7 +1609,7 @@ static void aggr_timeout(unsigned long arg)
1612 rxtid = &aggr_conn->rx_tid[i]; 1609 rxtid = &aggr_conn->rx_tid[i];
1613 stats = &aggr_conn->stat[i]; 1610 stats = &aggr_conn->stat[i];
1614 1611
1615 if (!rxtid->aggr || !rxtid->timer_mon || rxtid->progress) 1612 if (!rxtid->aggr || !rxtid->timer_mon)
1616 continue; 1613 continue;
1617 1614
1618 stats->num_timeouts++; 1615 stats->num_timeouts++;
@@ -1635,7 +1632,6 @@ static void aggr_timeout(unsigned long arg)
1635 if (rxtid->hold_q[j].skb) { 1632 if (rxtid->hold_q[j].skb) {
1636 aggr_conn->timer_scheduled = true; 1633 aggr_conn->timer_scheduled = true;
1637 rxtid->timer_mon = true; 1634 rxtid->timer_mon = true;
1638 rxtid->progress = false;
1639 break; 1635 break;
1640 } 1636 }
1641 } 1637 }
@@ -1666,7 +1662,6 @@ static void aggr_delete_tid_state(struct aggr_info_conn *aggr_conn, u8 tid)
1666 aggr_deque_frms(aggr_conn, tid, 0, 0); 1662 aggr_deque_frms(aggr_conn, tid, 0, 0);
1667 1663
1668 rxtid->aggr = false; 1664 rxtid->aggr = false;
1669 rxtid->progress = false;
1670 rxtid->timer_mon = false; 1665 rxtid->timer_mon = false;
1671 rxtid->win_sz = 0; 1666 rxtid->win_sz = 0;
1672 rxtid->seq_next = 0; 1667 rxtid->seq_next = 0;
@@ -1745,7 +1740,6 @@ void aggr_conn_init(struct ath6kl_vif *vif, struct aggr_info *aggr_info,
1745 for (i = 0; i < NUM_OF_TIDS; i++) { 1740 for (i = 0; i < NUM_OF_TIDS; i++) {
1746 rxtid = &aggr_conn->rx_tid[i]; 1741 rxtid = &aggr_conn->rx_tid[i];
1747 rxtid->aggr = false; 1742 rxtid->aggr = false;
1748 rxtid->progress = false;
1749 rxtid->timer_mon = false; 1743 rxtid->timer_mon = false;
1750 skb_queue_head_init(&rxtid->q); 1744 skb_queue_head_init(&rxtid->q);
1751 spin_lock_init(&rxtid->lock); 1745 spin_lock_init(&rxtid->lock);