diff options
Diffstat (limited to 'drivers/net/wireless/wl12xx/wl1271_tx.c')
-rw-r--r-- | drivers/net/wireless/wl12xx/wl1271_tx.c | 94 |
1 files changed, 49 insertions, 45 deletions
diff --git a/drivers/net/wireless/wl12xx/wl1271_tx.c b/drivers/net/wireless/wl12xx/wl1271_tx.c index 811e739d05bf..6d109df9a0a0 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) | |||
87 | static int wl1271_tx_fill_hdr(struct wl1271 *wl, struct sk_buff *skb, | 82 | static 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)", |
@@ -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 | ||
289 | out_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 | |||
299 | out: | 294 | out: |
300 | if (woken_up) | 295 | if (woken_up) |
301 | wl1271_ps_elp_sleep(wl); | 296 | wl1271_ps_elp_sleep(wl); |
@@ -308,11 +303,10 @@ 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; |
313 | 307 | ||
314 | /* check for id legality */ | 308 | /* check for id legality */ |
315 | if (id >= ACX_TX_DESCRIPTORS || wl->tx_frames[id] == NULL) { | 309 | if (unlikely(id >= ACX_TX_DESCRIPTORS || wl->tx_frames[id] == NULL)) { |
316 | wl1271_warning("TX result illegal id: %d", id); | 310 | wl1271_warning("TX result illegal id: %d", id); |
317 | return; | 311 | return; |
318 | } | 312 | } |
@@ -336,15 +330,10 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
336 | wl->stats.retry_count += result->ack_failures; | 330 | wl->stats.retry_count += result->ack_failures; |
337 | 331 | ||
338 | /* update security sequence number */ | 332 | /* update security sequence number */ |
339 | seq = wl->tx_security_seq_16 + | 333 | wl->tx_security_seq += (result->lsb_security_sequence_number - |
340 | (result->lsb_security_sequence_number - | 334 | wl->tx_security_last_seq); |
341 | wl->tx_security_last_seq); | ||
342 | wl->tx_security_last_seq = result->lsb_security_sequence_number; | 335 | wl->tx_security_last_seq = result->lsb_security_sequence_number; |
343 | 336 | ||
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 */ | 337 | /* remove private header from packet */ |
349 | skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); | 338 | skb_pull(skb, sizeof(struct wl1271_tx_hw_descr)); |
350 | 339 | ||
@@ -361,29 +350,37 @@ static void wl1271_tx_complete_packet(struct wl1271 *wl, | |||
361 | result->id, skb, result->ack_failures, | 350 | result->id, skb, result->ack_failures, |
362 | result->rate_class_index, result->status); | 351 | result->rate_class_index, result->status); |
363 | 352 | ||
353 | /* FIXME: do we need to tell the stack about the used rate? */ | ||
354 | |||
364 | /* return the packet to the stack */ | 355 | /* return the packet to the stack */ |
365 | ieee80211_tx_status(wl->hw, skb); | 356 | ieee80211_tx_status(wl->hw, skb); |
366 | wl->tx_frames[result->id] = NULL; | 357 | wl->tx_frames[result->id] = NULL; |
367 | } | 358 | } |
368 | 359 | ||
369 | /* Called upon reception of a TX complete interrupt */ | 360 | /* Called upon reception of a TX complete interrupt */ |
370 | void wl1271_tx_complete(struct wl1271 *wl, u32 count) | 361 | void wl1271_tx_complete(struct wl1271 *wl) |
371 | { | 362 | { |
372 | struct wl1271_acx_mem_map *memmap = | 363 | struct wl1271_acx_mem_map *memmap = |
373 | (struct wl1271_acx_mem_map *)wl->target_mem_map; | 364 | (struct wl1271_acx_mem_map *)wl->target_mem_map; |
365 | u32 count, fw_counter; | ||
374 | u32 i; | 366 | u32 i; |
375 | 367 | ||
376 | wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); | ||
377 | |||
378 | /* read the tx results from the chipset */ | 368 | /* read the tx results from the chipset */ |
379 | wl1271_read(wl, le32_to_cpu(memmap->tx_result), | 369 | wl1271_read(wl, le32_to_cpu(memmap->tx_result), |
380 | wl->tx_res_if, sizeof(*wl->tx_res_if), false); | 370 | wl->tx_res_if, sizeof(*wl->tx_res_if), false); |
371 | fw_counter = le32_to_cpu(wl->tx_res_if->tx_result_fw_counter); | ||
372 | |||
373 | /* write host counter to chipset (to ack) */ | ||
374 | wl1271_write32(wl, le32_to_cpu(memmap->tx_result) + | ||
375 | offsetof(struct wl1271_tx_hw_res_if, | ||
376 | tx_result_host_counter), fw_counter); | ||
377 | |||
378 | count = fw_counter - wl->tx_results_count; | ||
379 | wl1271_debug(DEBUG_TX, "tx_complete received, packets: %d", count); | ||
381 | 380 | ||
382 | /* verify that the result buffer is not getting overrun */ | 381 | /* verify that the result buffer is not getting overrun */ |
383 | if (count > TX_HW_RESULT_QUEUE_LEN) { | 382 | if (unlikely(count > TX_HW_RESULT_QUEUE_LEN)) |
384 | wl1271_warning("TX result overflow from chipset: %d", count); | 383 | wl1271_warning("TX result overflow from chipset: %d", count); |
385 | count = TX_HW_RESULT_QUEUE_LEN; | ||
386 | } | ||
387 | 384 | ||
388 | /* process the results */ | 385 | /* process the results */ |
389 | for (i = 0; i < count; i++) { | 386 | for (i = 0; i < count; i++) { |
@@ -397,11 +394,18 @@ void wl1271_tx_complete(struct wl1271 *wl, u32 count) | |||
397 | wl->tx_results_count++; | 394 | wl->tx_results_count++; |
398 | } | 395 | } |
399 | 396 | ||
400 | /* write host counter to chipset (to ack) */ | 397 | if (test_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags) && |
401 | wl1271_write32(wl, le32_to_cpu(memmap->tx_result) + | 398 | skb_queue_len(&wl->tx_queue) <= WL1271_TX_QUEUE_LOW_WATERMARK) { |
402 | offsetof(struct wl1271_tx_hw_res_if, | 399 | unsigned long flags; |
403 | tx_result_host_counter), | 400 | |
404 | le32_to_cpu(wl->tx_res_if->tx_result_fw_counter)); | 401 | /* firmware buffer has space, restart queues */ |
402 | wl1271_debug(DEBUG_TX, "tx_complete: waking queues"); | ||
403 | spin_lock_irqsave(&wl->wl_lock, flags); | ||
404 | ieee80211_wake_queues(wl->hw); | ||
405 | clear_bit(WL1271_FLAG_TX_QUEUE_STOPPED, &wl->flags); | ||
406 | spin_unlock_irqrestore(&wl->wl_lock, flags); | ||
407 | ieee80211_queue_work(wl->hw, &wl->tx_work); | ||
408 | } | ||
405 | } | 409 | } |
406 | 410 | ||
407 | /* caller must hold wl->mutex */ | 411 | /* caller must hold wl->mutex */ |