aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIdo Yariv <ido@wizery.com>2010-10-12 08:49:09 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-11-15 13:25:03 -0500
commit6c6e669ed6282788d6045397ce0f201edc400d9d (patch)
tree2ecd33ed575f1a4121cdd558eab1e4e82a4b89c9
parentc8aea565e8f715d9f10064b1cbfbc15bf75df501 (diff)
wl1271: TX aggregation optimization
In case the aggregation buffer is too small to hold all available packets, the buffer is transferred to the FW and no more packets are aggregated. Although there may be enough available TX blocks, no additional packets will be handled by the current TX work. Fix this by flushing the aggregation buffer when it's full, and continue transferring packets as long as there are enough available TX blocks. Signed-off-by: Ido Yariv <ido@wizery.com> Reviewed-by: Juuso Oikarinen <juuso.oikarinen@nokia.com> Signed-off-by: Luciano Coelho <luciano.coelho@nokia.com>
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_tx.c27
1 files changed, 19 insertions, 8 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c
index e3dc13c4d01a..b13b37330036 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.c
@@ -52,7 +52,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra,
52 int id, ret = -EBUSY; 52 int id, ret = -EBUSY;
53 53
54 if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE) 54 if (buf_offset + total_len > WL1271_AGGR_BUFFER_SIZE)
55 return -EBUSY; 55 return -EAGAIN;
56 56
57 /* allocate free identifier for the packet */ 57 /* allocate free identifier for the packet */
58 id = wl1271_tx_id(wl, skb); 58 id = wl1271_tx_id(wl, skb);
@@ -210,7 +210,8 @@ void wl1271_tx_work(struct work_struct *work)
210 struct sk_buff *skb; 210 struct sk_buff *skb;
211 bool woken_up = false; 211 bool woken_up = false;
212 u32 sta_rates = 0; 212 u32 sta_rates = 0;
213 u32 buf_offset; 213 u32 buf_offset = 0;
214 bool sent_packets = false;
214 int ret; 215 int ret;
215 216
216 /* check if the rates supported by the AP have changed */ 217 /* check if the rates supported by the AP have changed */
@@ -233,9 +234,6 @@ void wl1271_tx_work(struct work_struct *work)
233 wl1271_acx_rate_policies(wl); 234 wl1271_acx_rate_policies(wl);
234 } 235 }
235 236
236 /* Prepare the transfer buffer, by aggregating all
237 * available packets */
238 buf_offset = 0;
239 while ((skb = skb_dequeue(&wl->tx_queue))) { 237 while ((skb = skb_dequeue(&wl->tx_queue))) {
240 if (!woken_up) { 238 if (!woken_up) {
241 ret = wl1271_ps_elp_wakeup(wl, false); 239 ret = wl1271_ps_elp_wakeup(wl, false);
@@ -245,10 +243,20 @@ void wl1271_tx_work(struct work_struct *work)
245 } 243 }
246 244
247 ret = wl1271_prepare_tx_frame(wl, skb, buf_offset); 245 ret = wl1271_prepare_tx_frame(wl, skb, buf_offset);
248 if (ret == -EBUSY) { 246 if (ret == -EAGAIN) {
249 /* 247 /*
250 * Either the firmware buffer is full, or the 248 * Aggregation buffer is full.
251 * aggregation buffer is. 249 * Flush buffer and try again.
250 */
251 skb_queue_head(&wl->tx_queue, skb);
252 wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf,
253 buf_offset, true);
254 sent_packets = true;
255 buf_offset = 0;
256 continue;
257 } else if (ret == -EBUSY) {
258 /*
259 * Firmware buffer is full.
252 * Queue back last skb, and stop aggregating. 260 * Queue back last skb, and stop aggregating.
253 */ 261 */
254 skb_queue_head(&wl->tx_queue, skb); 262 skb_queue_head(&wl->tx_queue, skb);
@@ -265,6 +273,9 @@ out_ack:
265 if (buf_offset) { 273 if (buf_offset) {
266 wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf, 274 wl1271_write(wl, WL1271_SLV_MEM_DATA, wl->aggr_buf,
267 buf_offset, true); 275 buf_offset, true);
276 sent_packets = true;
277 }
278 if (sent_packets) {
268 /* interrupt the firmware with the new packets */ 279 /* interrupt the firmware with the new packets */
269 wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count); 280 wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count);
270 } 281 }