diff options
-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 | } |