diff options
author | Ido Yariv <ido@wizery.com> | 2010-10-12 08:49:09 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-11-15 13:25:03 -0500 |
commit | 6c6e669ed6282788d6045397ce0f201edc400d9d (patch) | |
tree | 2ecd33ed575f1a4121cdd558eab1e4e82a4b89c9 /drivers/net/wireless | |
parent | c8aea565e8f715d9f10064b1cbfbc15bf75df501 (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>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_tx.c | 27 |
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 | } |