aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/wl12xx/wl1271_tx.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1271_tx.c')
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_tx.c133
1 files changed, 64 insertions, 69 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c
index 811e739d05bf..62db79508ddf 100644
--- a/drivers/net/wireless/wl12xx/wl1271_tx.c
+++ b/drivers/net/wireless/wl12xx/wl1271_tx.c
@@ -25,7 +25,6 @@
25#include <linux/module.h> 25#include <linux/module.h>
26 26
27#include "wl1271.h" 27#include "wl1271.h"
28#include "wl1271_spi.h"
29#include "wl1271_io.h" 28#include "wl1271_io.h"
30#include "wl1271_reg.h" 29#include "wl1271_reg.h"
31#include "wl1271_ps.h" 30#include "wl1271_ps.h"
@@ -47,7 +46,7 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra)
47{ 46{
48 struct wl1271_tx_hw_descr *desc; 47 struct wl1271_tx_hw_descr *desc;
49 u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra; 48 u32 total_len = skb->len + sizeof(struct wl1271_tx_hw_descr) + extra;
50 u32 total_blocks, excluded; 49 u32 total_blocks;
51 int id, ret = -EBUSY; 50 int id, ret = -EBUSY;
52 51
53 /* allocate free identifier for the packet */ 52 /* allocate free identifier for the packet */
@@ -57,12 +56,8 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra)
57 56
58 /* approximate the number of blocks required for this packet 57 /* approximate the number of blocks required for this packet
59 in the firmware */ 58 in the firmware */
60 /* FIXME: try to figure out what is done here and make it cleaner */ 59 total_blocks = total_len + TX_HW_BLOCK_SIZE - 1;
61 total_blocks = (total_len + 20) >> TX_HW_BLOCK_SHIFT_DIV; 60 total_blocks = total_blocks / TX_HW_BLOCK_SIZE + TX_HW_BLOCK_SPARE;
62 excluded = (total_blocks << 2) + ((total_len + 20) & 0xff) + 34;
63 total_blocks += (excluded > 252) ? 2 : 1;
64 total_blocks += TX_HW_BLOCK_SPARE;
65
66 if (total_blocks <= wl->tx_blocks_available) { 61 if (total_blocks <= wl->tx_blocks_available) {
67 desc = (struct wl1271_tx_hw_descr *)skb_push( 62 desc = (struct wl1271_tx_hw_descr *)skb_push(
68 skb, total_len - skb->len); 63 skb, total_len - skb->len);
@@ -87,8 +82,10 @@ static int wl1271_tx_allocate(struct wl1271 *wl, struct sk_buff *skb, u32 extra)
87static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, 82static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
88 u32 extra, struct ieee80211_tx_info *control) 83 u32 extra, struct ieee80211_tx_info *control)
89{ 84{
85 struct timespec ts;
90 struct wl1271_tx_hw_descr *desc; 86 struct wl1271_tx_hw_descr *desc;
91 int pad, ac; 87 int pad, ac;
88 s64 hosttime;
92 u16 tx_attr; 89 u16 tx_attr;
93 90
94 desc = (struct wl1271_tx_hw_descr *) skb->data; 91 desc = (struct wl1271_tx_hw_descr *) skb->data;
@@ -102,8 +99,9 @@ static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb,
102 } 99 }
103 100
104 /* configure packet life time */ 101 /* configure packet life time */
105 desc->start_time = cpu_to_le32(jiffies_to_usecs(jiffies) - 102 getnstimeofday(&ts);
106 wl->time_offset); 103 hosttime = (timespec_to_ns(&ts) >> 10);
104 desc->start_time = cpu_to_le32(hosttime - wl->time_offset);
107 desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU); 105 desc->life_time = cpu_to_le16(TX_HW_MGMT_PKT_LIFETIME_TU);
108 106
109 /* configure the tx attributes */ 107 /* configure the tx attributes */
@@ -170,7 +168,6 @@ static int wl1271_tx_send_packet(struct wl1271 *wl, struct sk_buff *skb,
170 168
171 /* write packet new counter into the write access register */ 169 /* write packet new counter into the write access register */
172 wl->tx_packets_count++; 170 wl->tx_packets_count++;
173 wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count);
174 171
175 desc = (struct wl1271_tx_hw_descr *) skb->data; 172 desc = (struct wl1271_tx_hw_descr *) skb->data;
176 wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)", 173 wl1271_debug(DEBUG_TX, "tx id %u skb 0x%p payload %u (%u words)",
@@ -223,7 +220,7 @@ static int wl1271_tx_frame(struct wl1271 *wl, struct sk_buff *skb)
223 return ret; 220 return ret;
224} 221}
225 222
226static u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set) 223u32 wl1271_tx_enabled_rates_get(struct wl1271 *wl, u32 rate_set)
227{ 224{
228 struct ieee80211_supported_band *band; 225 struct ieee80211_supported_band *band;
229 u32 enabled_rates = 0; 226 u32 enabled_rates = 0;
@@ -245,6 +242,7 @@ void wl1271_tx_work(struct work_struct *work)
245 struct sk_buff *skb; 242 struct sk_buff *skb;
246 bool woken_up = false; 243 bool woken_up = false;
247 u32 sta_rates = 0; 244 u32 sta_rates = 0;
245 u32 prev_tx_packets_count;
248 int ret; 246 int ret;
249 247
250 /* check if the rates supported by the AP have changed */ 248 /* check if the rates supported by the AP have changed */
@@ -261,6 +259,8 @@ void wl1271_tx_work(struct work_struct *work)
261 if (unlikely(wl->state == WL1271_STATE_OFF)) 259 if (unlikely(wl->state == WL1271_STATE_OFF))
262 goto out; 260 goto out;
263 261
262 prev_tx_packets_count = wl->tx_packets_count;
263
264 /* if rates have changed, re-configure the rate policy */ 264 /* if rates have changed, re-configure the rate policy */
265 if (unlikely(sta_rates)) { 265 if (unlikely(sta_rates)) {
266 wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates); 266 wl->rate_set = wl1271_tx_enabled_rates_get(wl, sta_rates);
@@ -271,31 +271,26 @@ void wl1271_tx_work(struct work_struct *work)
271 if (!woken_up) { 271 if (!woken_up) {
272 ret = wl1271_ps_elp_wakeup(wl, false); 272 ret = wl1271_ps_elp_wakeup(wl, false);
273 if (ret < 0) 273 if (ret < 0)
274 goto out; 274 goto out_ack;
275 woken_up = true; 275 woken_up = true;
276 } 276 }
277 277
278 ret = wl1271_tx_frame(wl, skb); 278 ret = wl1271_tx_frame(wl, skb);
279 if (ret == -EBUSY) { 279 if (ret == -EBUSY) {
280 /* firmware buffer is full, stop queues */ 280 /* firmware buffer is full, lets stop transmitting. */
281 wl1271_debug(DEBUG_TX, "tx_work: fw buffer full, "
282 "stop queues");
283 ieee80211_stop_queues(wl->hw);
284 set_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags);
285 skb_queue_head(&wl->tx_queue, skb); 281 skb_queue_head(&wl->tx_queue, skb);
286 goto out; 282 goto out_ack;
287 } else if (ret < 0) { 283 } else if (ret < 0) {
288 dev_kfree_skb(skb); 284 dev_kfree_skb(skb);
289 goto out; 285 goto out_ack;
290 } else if (test_and_clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED,
291 &wl->flags)) {
292 /* firmware buffer has space, restart queues */
293 wl1271_debug(DEBUG_TX,
294 "complete_packet: waking queues");
295 ieee80211_wake_queues(wl->hw);
296 } 286 }
297 } 287 }
298 288
289out_ack:
290 /* interrupt the firmware with the new packets */
291 if (prev_tx_packets_count != wl->tx_packets_count)
292 wl1271_write32(wl, WL1271_HOST_WR_ACCESS, wl->tx_packets_count);
293
299out: 294out:
300 if (woken_up) 295 if (woken_up)
301 wl1271_ps_elp_sleep(wl); 296 wl1271_ps_elp_sleep(wl);
@@ -308,11 +303,12 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
308{ 303{
309 struct ieee80211_tx_info *info; 304 struct ieee80211_tx_info *info;
310 struct sk_buff *skb; 305 struct sk_buff *skb;
311 u16 seq;
312 int id = result->id; 306 int id = result->id;
307 int rate = -1;
308 u8 retries = 0;
313 309
314 /* check for id legality */ 310 /* check for id legality */
315 if (id >= ACX_TX_DESCRIPTORS || wl->tx_frames[id] == NULL) { 311 if (unlikely(id >= ACX_TX_DESCRIPTORS || wl->tx_frames[id] == NULL)) {
316 wl1271_warning("TX result illegal id: %d", id); 312 wl1271_warning("TX result illegal id: %d", id);
317 return; 313 return;
318 } 314 }
@@ -320,31 +316,29 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
320 skb = wl->tx_frames[id]; 316 skb = wl->tx_frames[id];
321 info = IEEE80211_SKB_CB(skb); 317 info = IEEE80211_SKB_CB(skb);
322 318
323 /* update packet status */ 319 /* update the TX status info */
324 if (!(info->flags & IEEE80211_TX_CTL_NO_ACK)) { 320 if (result->status == TX_SUCCESS) {
325 if (result->status == TX_SUCCESS) 321 if (!(info->flags & IEEE80211_TX_CTL_NO_ACK))
326 info->flags |= IEEE80211_TX_STAT_ACK; 322 info->flags |= IEEE80211_TX_STAT_ACK;
327 if (result->status & TX_RETRY_EXCEEDED) { 323 rate = wl1271_rate_to_idx(wl, result->rate_class_index);
328 /* FIXME */ 324 retries = result->ack_failures;
329 /* info->status.excessive_retries = 1; */ 325 } else if (result->status == TX_RETRY_EXCEEDED) {
330 wl->stats.excessive_retries++; 326 wl->stats.excessive_retries++;
331 } 327 retries = result->ack_failures;
332 } 328 }
333 329
334 /* FIXME */ 330 info->status.rates[0].idx = rate;
335 /* info->status.retry_count = result->ack_failures; */ 331 info->status.rates[0].count = retries;
332 info->status.rates[0].flags = 0;
333 info->status.ack_signal = -1;
334
336 wl->stats.retry_count += result->ack_failures; 335 wl->stats.retry_count += result->ack_failures;
337 336
338 /* update security sequence number */ 337 /* update security sequence number */
339 seq = wl->tx_security_seq_16 + 338 wl->tx_security_seq += (result->lsb_security_sequence_number -
340 (result->lsb_security_sequence_number - 339 wl->tx_security_last_seq);
341 wl->tx_security_last_seq);
342 wl->tx_security_last_seq = result->lsb_security_sequence_number; 340 wl->tx_security_last_seq = result->lsb_security_sequence_number;
343 341
344 if (seq < wl->tx_security_seq_16)
345 wl->tx_security_seq_32++;
346 wl->tx_security_seq_16 = seq;
347
348 /* remove private header from packet */ 342 /* remove private header from packet */
349 skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); 343 skb_pull(skb, sizeof(struct wl1271_tx_hw_descr));
350 344
@@ -367,23 +361,29 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl,
367} 361}
368 362
369/* Called upon reception of a TX complete interrupt */ 363/* Called upon reception of a TX complete interrupt */
370void wl1271_tx_complete(struct wl1271 *wl, u32 count) 364void wl1271_tx_complete(struct wl1271 *wl)
371{ 365{
372 struct wl1271_acx_mem_map *memmap = 366 struct wl1271_acx_mem_map *memmap =
373 (struct wl1271_acx_mem_map *)wl->target_mem_map; 367 (struct wl1271_acx_mem_map *)wl->target_mem_map;
368 u32 count, fw_counter;
374 u32 i; 369 u32 i;
375 370
376 wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count);
377
378 /* read the tx results from the chipset */ 371 /* read the tx results from the chipset */
379 wl1271_read(wl, le32_to_cpu(memmap->tx_result), 372 wl1271_read(wl, le32_to_cpu(memmap->tx_result),
380 wl->tx_res_if, sizeof(*wl->tx_res_if), false); 373 wl->tx_res_if, sizeof(*wl->tx_res_if), false);
374 fw_counter = le32_to_cpu(wl->tx_res_if->tx_result_fw_counter);
375
376 /* write host counter to chipset (to ack) */
377 wl1271_write32(wl, le32_to_cpu(memmap->tx_result) +
378 offsetof(struct wl1271_tx_hw_res_if,
379 tx_result_host_counter), fw_counter);
380
381 count = fw_counter - wl->tx_results_count;
382 wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count);
381 383
382 /* verify that the result buffer is not getting overrun */ 384 /* verify that the result buffer is not getting overrun */
383 if (count > TX_HW_RESULT_QUEUE_LEN) { 385 if (unlikely(count > TX_HW_RESULT_QUEUE_LEN))
384 wl1271_warning("TX result overflow from chipset: %d", count); 386 wl1271_warning("TX result overflow from chipset: %d", count);
385 count = TX_HW_RESULT_QUEUE_LEN;
386 }
387 387
388 /* process the results */ 388 /* process the results */
389 for (i = 0; i < count; i++) { 389 for (i = 0; i < count; i++) {
@@ -397,11 +397,18 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count)
397 wl->tx_results_count++; 397 wl->tx_results_count++;
398 } 398 }
399 399
400 /* write host counter to chipset (to ack) */ 400 if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) &&
401 wl1271_write32(wl, le32_to_cpu(memmap->tx_result) + 401 skb_queue_len(&wl->tx_queue) <= WL1271_TX_QUEUE_LOW_WATERMARK) {
402 offsetof(struct wl1271_tx_hw_res_if, 402 unsigned long flags;
403 tx_result_host_counter), 403
404 le32_to_cpu(wl->tx_res_if->tx_result_fw_counter)); 404 /* firmware buffer has space, restart queues */
405 wl1271_debug(DEBUG_TX, "tx_complete: waking queues");
406 spin_lock_irqsave(&wl->wl_lock, flags);
407 ieee80211_wake_queues(wl->hw);
408 clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags);
409 spin_unlock_irqrestore(&wl->wl_lock, flags);
410 ieee80211_queue_work(wl->hw, &wl->tx_work);
411 }
405} 412}
406 413
407/* caller must hold wl->mutex */ 414/* caller must hold wl->mutex */
@@ -409,31 +416,19 @@ void wl1271_tx_flush(struct wl1271 *wl)
409{ 416{
410 int i; 417 int i;
411 struct sk_buff *skb; 418 struct sk_buff *skb;
412 struct ieee80211_tx_info *info;
413 419
414 /* TX failure */ 420 /* TX failure */
415/* control->flags = 0; FIXME */ 421/* control->flags = 0; FIXME */
416 422
417 while ((skb = skb_dequeue(&wl->tx_queue))) { 423 while ((skb = skb_dequeue(&wl->tx_queue))) {
418 info = IEEE80211_SKB_CB(skb);
419
420 wl1271_debug(DEBUG_TX, "flushing skb 0x%p", skb); 424 wl1271_debug(DEBUG_TX, "flushing skb 0x%p", skb);
421
422 if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS))
423 continue;
424
425 ieee80211_tx_status(wl->hw, skb); 425 ieee80211_tx_status(wl->hw, skb);
426 } 426 }
427 427
428 for (i = 0; i < ACX_TX_DESCRIPTORS; i++) 428 for (i = 0; i < ACX_TX_DESCRIPTORS; i++)
429 if (wl->tx_frames[i] != NULL) { 429 if (wl->tx_frames[i] != NULL) {
430 skb = wl->tx_frames[i]; 430 skb = wl->tx_frames[i];
431 info = IEEE80211_SKB_CB(skb);
432
433 if (!(info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS))
434 continue;
435
436 ieee80211_tx_status(wl->hw, skb);
437 wl->tx_frames[i] = NULL; 431 wl->tx_frames[i] = NULL;
432 ieee80211_tx_status(wl->hw, skb);
438 } 433 }
439} 434}