summaryrefslogtreecommitdiff
path: root/multitech/recipes/compat-wireless/ti-compat-wireless-wl12xx-r5.sp4.01/0002-wl12xx-Decrease-number-of-TX-transactions.patch
blob: 3e2185a451e372c7421411170bd709098c5117cd (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
From a7807fffc76117a9d0a40fdcc85b56644e81f34c Mon Sep 17 00:00:00 2001
From: Eyal Reizer <eyalr@ti.com>
Date: Tue, 27 Nov 2012 16:05:20 +0200
Subject: [PATCH] wl12xx: Decrease number of TX transactions

On weak platforms, it is crucial to keep the number of SDIO transactions
to a bare minimum. It is probably more important to keep CPU utilization
low, than to handle FW events asap.

In order to decrease the number of TX transactions, don't schedule tx
work right away for every outgoing packet. Instead, try to wait for a
short period before scheduling tx work if there aren't enough pending
packets.

In addition, increase the TX pacing timeout, so the FW will have enough
free memory blocks for larger transfers.

Adapted from original patch made by Ido Yariv <ido@wizery.com>
Signed-off-by: Eyal Reizer <eyalr@ti.com>
---
 drivers/net/wireless/wl12xx/main.c   |   39 ++++++++++++++++++++++++++++++----
 drivers/net/wireless/wl12xx/wl12xx.h |    3 +++
 2 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index c9888f4..a59ac43 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -218,8 +218,8 @@ static struct conf_drv_settings default_conf = {
 			},
 		},
 		.frag_threshold              = IEEE80211_MAX_FRAG_THRESHOLD,
-		.tx_compl_timeout            = 700,
-		.tx_compl_threshold          = 4,
+		.tx_compl_timeout            = 1500,
+		.tx_compl_threshold          = 6,
 		.basic_rate                  = CONF_HW_BIT_RATE_1MBPS,
 		.basic_rate_5                = CONF_HW_BIT_RATE_6MBPS,
 		.tmpl_short_retry_limit      = 10,
@@ -1199,6 +1199,8 @@ static int wl12xx_irq_locked(struct wl1271 *wl)
 			spin_lock_irqsave(&wl->wl_lock, flags);
 			if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) &&
 			    wl1271_tx_total_queue_count(wl) > 0) {
+				hrtimer_try_to_cancel(&wl->tx_timer);
+				clear_bit(WL1271_FLAG_TX_TIMER_SET, &wl->flags);
 				spin_unlock_irqrestore(&wl->wl_lock, flags);
 				/*
 				 * In order to avoid starvation of the TX path,
@@ -2056,6 +2058,9 @@ out:
 	return ret;
 }
 
+#define TX_PACKETS_THRESHOLD	6
+#define TX_WORK_DELAY_NS	(1500 * 1000)
+
 static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 {
 	struct wl1271 *wl = hw->priv;
@@ -2113,14 +2118,37 @@ static void wl1271_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
 	 * before that, the tx_work will not be initialized!
 	 */
 
-	if (!test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) &&
-	    !test_bit(WL1271_FLAG_TX_PENDING, &wl->flags))
+	if (test_bit(WL1271_FLAG_FW_TX_BUSY, &wl->flags) ||
+	    test_bit(WL1271_FLAG_TX_PENDING, &wl->flags))
+		goto out;
+
+	if (wl1271_tx_total_queue_count(wl) < TX_PACKETS_THRESHOLD) {
+		if (!test_and_set_bit(WL1271_FLAG_TX_TIMER_SET, &wl->flags))
+			hrtimer_start(&wl->tx_timer,
+				      ktime_set(0, TX_WORK_DELAY_NS),
+				      HRTIMER_MODE_REL);
+	} else {
+		hrtimer_try_to_cancel(&wl->tx_timer);
+		clear_bit(WL1271_FLAG_TX_TIMER_SET, &wl->flags);
 		ieee80211_queue_work(wl->hw, &wl->tx_work);
+	}
 
 out:
 	spin_unlock_irqrestore(&wl->wl_lock, flags);
 }
 
+enum hrtimer_restart wl12xx_tx_timer(struct hrtimer *timer)
+{
+	struct wl1271 *wl = container_of(timer, struct wl1271, tx_timer);
+	unsigned long flags;
+
+	spin_lock_irqsave(&wl->wl_lock, flags);
+	clear_bit(WL1271_FLAG_TX_TIMER_SET, &wl->flags);
+	ieee80211_queue_work(wl->hw, &wl->tx_work);
+	spin_unlock_irqrestore(&wl->wl_lock, flags);
+	return HRTIMER_NORESTART;
+}
+
 int wl1271_tx_dummy_packet(struct wl1271 *wl)
 {
 	unsigned long flags;
@@ -2740,6 +2768,7 @@ static void wl1271_op_stop_locked(struct wl1271 *wl)
 	 * held while doing so without deadlocking.
 	 */
 	wlcore_disable_interrupts_nosync(wl);
+	hrtimer_cancel(&wl->tx_timer);
 	mutex_unlock(&wl->mutex);
 
 	mutex_lock(&wl_list_mutex);
@@ -6798,6 +6827,8 @@ static struct ieee80211_hw *wl1271_alloc_hw(void)
 	wl->active_sta_count = 0;
 	wl->fwlog_size = 0;
 	init_waitqueue_head(&wl->fwlog_waitq);
+	hrtimer_init(&wl->tx_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL);
+	wl->tx_timer.function = wl12xx_tx_timer;
 
 	/* The system link is always allocated */
 	__set_bit(WL12XX_SYSTEM_HLID, wl->links_map);
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 9c00dbf..e34f095 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -275,6 +275,7 @@ enum wl12xx_flags {
 	WL1271_FLAG_VIF_CHANGE_IN_PROGRESS,
 	WL1271_FLAG_INTENDED_FW_RECOVERY,
 	WL1271_FLAG_IO_FAILED,
+	WL1271_FLAG_TX_TIMER_SET,
 };
 
 enum wl12xx_vif_flags {
@@ -594,6 +595,8 @@ struct wl1271 {
 
 	/* Patterns configured with set_rx_filters */
 	struct cfg80211_wowlan *wowlan_patterns;
+
+	struct hrtimer tx_timer;
 };
 
 struct wl1271_station {
-- 
1.7.9.5