aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00/rt2x00dev.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00dev.c')
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c101
1 files changed, 100 insertions, 1 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 44f8b3f3cbed..b40a53857498 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -271,6 +271,50 @@ void rt2x00lib_dmadone(struct queue_entry *entry)
271} 271}
272EXPORT_SYMBOL_GPL(rt2x00lib_dmadone); 272EXPORT_SYMBOL_GPL(rt2x00lib_dmadone);
273 273
274static inline int rt2x00lib_txdone_bar_status(struct queue_entry *entry)
275{
276 struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev;
277 struct ieee80211_bar *bar = (void *) entry->skb->data;
278 struct rt2x00_bar_list_entry *bar_entry;
279 int ret;
280
281 if (likely(!ieee80211_is_back_req(bar->frame_control)))
282 return 0;
283
284 /*
285 * Unlike all other frames, the status report for BARs does
286 * not directly come from the hardware as it is incapable of
287 * matching a BA to a previously send BAR. The hardware will
288 * report all BARs as if they weren't acked at all.
289 *
290 * Instead the RX-path will scan for incoming BAs and set the
291 * block_acked flag if it sees one that was likely caused by
292 * a BAR from us.
293 *
294 * Remove remaining BARs here and return their status for
295 * TX done processing.
296 */
297 ret = 0;
298 rcu_read_lock();
299 list_for_each_entry_rcu(bar_entry, &rt2x00dev->bar_list, list) {
300 if (bar_entry->entry != entry)
301 continue;
302
303 spin_lock_bh(&rt2x00dev->bar_list_lock);
304 /* Return whether this BAR was blockacked or not */
305 ret = bar_entry->block_acked;
306 /* Remove the BAR from our checklist */
307 list_del_rcu(&bar_entry->list);
308 spin_unlock_bh(&rt2x00dev->bar_list_lock);
309 kfree_rcu(bar_entry, head);
310
311 break;
312 }
313 rcu_read_unlock();
314
315 return ret;
316}
317
274void rt2x00lib_txdone(struct queue_entry *entry, 318void rt2x00lib_txdone(struct queue_entry *entry,
275 struct txdone_entry_desc *txdesc) 319 struct txdone_entry_desc *txdesc)
276{ 320{
@@ -324,9 +368,12 @@ void rt2x00lib_txdone(struct queue_entry *entry,
324 rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TXDONE, entry->skb); 368 rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_TXDONE, entry->skb);
325 369
326 /* 370 /*
327 * Determine if the frame has been successfully transmitted. 371 * Determine if the frame has been successfully transmitted and
372 * remove BARs from our check list while checking for their
373 * TX status.
328 */ 374 */
329 success = 375 success =
376 rt2x00lib_txdone_bar_status(entry) ||
330 test_bit(TXDONE_SUCCESS, &txdesc->flags) || 377 test_bit(TXDONE_SUCCESS, &txdesc->flags) ||
331 test_bit(TXDONE_UNKNOWN, &txdesc->flags); 378 test_bit(TXDONE_UNKNOWN, &txdesc->flags);
332 379
@@ -491,6 +538,50 @@ static void rt2x00lib_sleep(struct work_struct *work)
491 IEEE80211_CONF_CHANGE_PS); 538 IEEE80211_CONF_CHANGE_PS);
492} 539}
493 540
541static void rt2x00lib_rxdone_check_ba(struct rt2x00_dev *rt2x00dev,
542 struct sk_buff *skb,
543 struct rxdone_entry_desc *rxdesc)
544{
545 struct rt2x00_bar_list_entry *entry;
546 struct ieee80211_bar *ba = (void *)skb->data;
547
548 if (likely(!ieee80211_is_back(ba->frame_control)))
549 return;
550
551 if (rxdesc->size < sizeof(*ba) + FCS_LEN)
552 return;
553
554 rcu_read_lock();
555 list_for_each_entry_rcu(entry, &rt2x00dev->bar_list, list) {
556
557 if (ba->start_seq_num != entry->start_seq_num)
558 continue;
559
560#define TID_CHECK(a, b) ( \
561 ((a) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK)) == \
562 ((b) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK))) \
563
564 if (!TID_CHECK(ba->control, entry->control))
565 continue;
566
567#undef TID_CHECK
568
569 if (compare_ether_addr(ba->ra, entry->ta))
570 continue;
571
572 if (compare_ether_addr(ba->ta, entry->ra))
573 continue;
574
575 /* Mark BAR since we received the according BA */
576 spin_lock_bh(&rt2x00dev->bar_list_lock);
577 entry->block_acked = 1;
578 spin_unlock_bh(&rt2x00dev->bar_list_lock);
579 break;
580 }
581 rcu_read_unlock();
582
583}
584
494static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev, 585static void rt2x00lib_rxdone_check_ps(struct rt2x00_dev *rt2x00dev,
495 struct sk_buff *skb, 586 struct sk_buff *skb,
496 struct rxdone_entry_desc *rxdesc) 587 struct rxdone_entry_desc *rxdesc)
@@ -674,6 +765,12 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp)
674 rt2x00lib_rxdone_check_ps(rt2x00dev, entry->skb, &rxdesc); 765 rt2x00lib_rxdone_check_ps(rt2x00dev, entry->skb, &rxdesc);
675 766
676 /* 767 /*
768 * Check for incoming BlockAcks to match to the BlockAckReqs
769 * we've send out.
770 */
771 rt2x00lib_rxdone_check_ba(rt2x00dev, entry->skb, &rxdesc);
772
773 /*
677 * Update extra components 774 * Update extra components
678 */ 775 */
679 rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc); 776 rt2x00link_update_stats(rt2x00dev, entry->skb, &rxdesc);
@@ -1183,6 +1280,8 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
1183 1280
1184 spin_lock_init(&rt2x00dev->irqmask_lock); 1281 spin_lock_init(&rt2x00dev->irqmask_lock);
1185 mutex_init(&rt2x00dev->csr_mutex); 1282 mutex_init(&rt2x00dev->csr_mutex);
1283 INIT_LIST_HEAD(&rt2x00dev->bar_list);
1284 spin_lock_init(&rt2x00dev->bar_list_lock);
1186 1285
1187 set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags); 1286 set_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
1188 1287