diff options
author | David S. Miller <davem@davemloft.net> | 2008-06-29 01:57:58 -0400 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-06-29 01:57:58 -0400 |
commit | 28f49d8fec19833672a6a813bfde0068fee50bc9 (patch) | |
tree | 6905c5cabc063e44b891ae0af5b5d7cce69e6e71 /drivers/net/wireless/rt2x00/rt2x00dev.c | |
parent | 332e4af80d1214fbf0e263e1408fc7c5b64ecdd6 (diff) | |
parent | ff28bd94e307c67abb1bccda5d3a9018bd798e08 (diff) |
Merge branch 'master' of master.kernel.org:/pub/scm/linux/kernel/git/linville/wireless-next-2.6
Diffstat (limited to 'drivers/net/wireless/rt2x00/rt2x00dev.c')
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 100 |
1 files changed, 80 insertions, 20 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c index cc4fee105ed6..ae8ab71fe474 100644 --- a/drivers/net/wireless/rt2x00/rt2x00dev.c +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c | |||
@@ -469,12 +469,19 @@ static void rt2x00lib_intf_scheduled(struct work_struct *work) | |||
469 | static void rt2x00lib_beacondone_iter(void *data, u8 *mac, | 469 | static void rt2x00lib_beacondone_iter(void *data, u8 *mac, |
470 | struct ieee80211_vif *vif) | 470 | struct ieee80211_vif *vif) |
471 | { | 471 | { |
472 | struct rt2x00_dev *rt2x00dev = data; | ||
472 | struct rt2x00_intf *intf = vif_to_intf(vif); | 473 | struct rt2x00_intf *intf = vif_to_intf(vif); |
473 | 474 | ||
474 | if (vif->type != IEEE80211_IF_TYPE_AP && | 475 | if (vif->type != IEEE80211_IF_TYPE_AP && |
475 | vif->type != IEEE80211_IF_TYPE_IBSS) | 476 | vif->type != IEEE80211_IF_TYPE_IBSS) |
476 | return; | 477 | return; |
477 | 478 | ||
479 | /* | ||
480 | * Clean up the beacon skb. | ||
481 | */ | ||
482 | rt2x00queue_free_skb(rt2x00dev, intf->beacon->skb); | ||
483 | intf->beacon->skb = NULL; | ||
484 | |||
478 | spin_lock(&intf->lock); | 485 | spin_lock(&intf->lock); |
479 | intf->delayed_flags |= DELAYED_UPDATE_BEACON; | 486 | intf->delayed_flags |= DELAYED_UPDATE_BEACON; |
480 | spin_unlock(&intf->lock); | 487 | spin_unlock(&intf->lock); |
@@ -498,6 +505,12 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
498 | { | 505 | { |
499 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 506 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; |
500 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); | 507 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(entry->skb); |
508 | enum data_queue_qid qid = skb_get_queue_mapping(entry->skb); | ||
509 | |||
510 | /* | ||
511 | * Unmap the skb. | ||
512 | */ | ||
513 | rt2x00queue_unmap_skb(rt2x00dev, entry->skb); | ||
501 | 514 | ||
502 | /* | 515 | /* |
503 | * Send frame to debugfs immediately, after this call is completed | 516 | * Send frame to debugfs immediately, after this call is completed |
@@ -546,39 +559,77 @@ void rt2x00lib_txdone(struct queue_entry *entry, | |||
546 | ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb); | 559 | ieee80211_tx_status_irqsafe(rt2x00dev->hw, entry->skb); |
547 | else | 560 | else |
548 | dev_kfree_skb_irq(entry->skb); | 561 | dev_kfree_skb_irq(entry->skb); |
562 | |||
563 | /* | ||
564 | * Make this entry available for reuse. | ||
565 | */ | ||
549 | entry->skb = NULL; | 566 | entry->skb = NULL; |
567 | entry->flags = 0; | ||
568 | |||
569 | rt2x00dev->ops->lib->init_txentry(rt2x00dev, entry); | ||
570 | |||
571 | __clear_bit(ENTRY_OWNER_DEVICE_DATA, &entry->flags); | ||
572 | rt2x00queue_index_inc(entry->queue, Q_INDEX_DONE); | ||
573 | |||
574 | /* | ||
575 | * If the data queue was below the threshold before the txdone | ||
576 | * handler we must make sure the packet queue in the mac80211 stack | ||
577 | * is reenabled when the txdone handler has finished. | ||
578 | */ | ||
579 | if (!rt2x00queue_threshold(entry->queue)) | ||
580 | ieee80211_wake_queue(rt2x00dev->hw, qid); | ||
550 | } | 581 | } |
551 | EXPORT_SYMBOL_GPL(rt2x00lib_txdone); | 582 | EXPORT_SYMBOL_GPL(rt2x00lib_txdone); |
552 | 583 | ||
553 | void rt2x00lib_rxdone(struct queue_entry *entry, | 584 | void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, |
554 | struct rxdone_entry_desc *rxdesc) | 585 | struct queue_entry *entry) |
555 | { | 586 | { |
556 | struct rt2x00_dev *rt2x00dev = entry->queue->rt2x00dev; | 587 | struct rxdone_entry_desc rxdesc; |
588 | struct sk_buff *skb; | ||
557 | struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; | 589 | struct ieee80211_rx_status *rx_status = &rt2x00dev->rx_status; |
558 | unsigned int header_size = ieee80211_get_hdrlen_from_skb(entry->skb); | ||
559 | struct ieee80211_supported_band *sband; | 590 | struct ieee80211_supported_band *sband; |
560 | struct ieee80211_hdr *hdr; | 591 | struct ieee80211_hdr *hdr; |
561 | const struct rt2x00_rate *rate; | 592 | const struct rt2x00_rate *rate; |
593 | unsigned int header_size; | ||
562 | unsigned int align; | 594 | unsigned int align; |
563 | unsigned int i; | 595 | unsigned int i; |
564 | int idx = -1; | 596 | int idx = -1; |
565 | u16 fc; | 597 | |
598 | /* | ||
599 | * Allocate a new sk_buffer. If no new buffer available, drop the | ||
600 | * received frame and reuse the existing buffer. | ||
601 | */ | ||
602 | skb = rt2x00queue_alloc_rxskb(rt2x00dev, entry); | ||
603 | if (!skb) | ||
604 | return; | ||
605 | |||
606 | /* | ||
607 | * Unmap the skb. | ||
608 | */ | ||
609 | rt2x00queue_unmap_skb(rt2x00dev, entry->skb); | ||
610 | |||
611 | /* | ||
612 | * Extract the RXD details. | ||
613 | */ | ||
614 | memset(&rxdesc, 0, sizeof(rxdesc)); | ||
615 | rt2x00dev->ops->lib->fill_rxdone(entry, &rxdesc); | ||
566 | 616 | ||
567 | /* | 617 | /* |
568 | * The data behind the ieee80211 header must be | 618 | * The data behind the ieee80211 header must be |
569 | * aligned on a 4 byte boundary. | 619 | * aligned on a 4 byte boundary. |
570 | */ | 620 | */ |
621 | header_size = ieee80211_get_hdrlen_from_skb(entry->skb); | ||
571 | align = ((unsigned long)(entry->skb->data + header_size)) & 3; | 622 | align = ((unsigned long)(entry->skb->data + header_size)) & 3; |
572 | 623 | ||
573 | if (align) { | 624 | if (align) { |
574 | skb_push(entry->skb, align); | 625 | skb_push(entry->skb, align); |
575 | /* Move entire frame in 1 command */ | 626 | /* Move entire frame in 1 command */ |
576 | memmove(entry->skb->data, entry->skb->data + align, | 627 | memmove(entry->skb->data, entry->skb->data + align, |
577 | rxdesc->size); | 628 | rxdesc.size); |
578 | } | 629 | } |
579 | 630 | ||
580 | /* Update data pointers, trim buffer to correct size */ | 631 | /* Update data pointers, trim buffer to correct size */ |
581 | skb_trim(entry->skb, rxdesc->size); | 632 | skb_trim(entry->skb, rxdesc.size); |
582 | 633 | ||
583 | /* | 634 | /* |
584 | * Update RX statistics. | 635 | * Update RX statistics. |
@@ -587,10 +638,10 @@ void rt2x00lib_rxdone(struct queue_entry *entry, | |||
587 | for (i = 0; i < sband->n_bitrates; i++) { | 638 | for (i = 0; i < sband->n_bitrates; i++) { |
588 | rate = rt2x00_get_rate(sband->bitrates[i].hw_value); | 639 | rate = rt2x00_get_rate(sband->bitrates[i].hw_value); |
589 | 640 | ||
590 | if (((rxdesc->dev_flags & RXDONE_SIGNAL_PLCP) && | 641 | if (((rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) && |
591 | (rate->plcp == rxdesc->signal)) || | 642 | (rate->plcp == rxdesc.signal)) || |
592 | (!(rxdesc->dev_flags & RXDONE_SIGNAL_PLCP) && | 643 | (!(rxdesc.dev_flags & RXDONE_SIGNAL_PLCP) && |
593 | (rate->bitrate == rxdesc->signal))) { | 644 | (rate->bitrate == rxdesc.signal))) { |
594 | idx = i; | 645 | idx = i; |
595 | break; | 646 | break; |
596 | } | 647 | } |
@@ -598,8 +649,8 @@ void rt2x00lib_rxdone(struct queue_entry *entry, | |||
598 | 649 | ||
599 | if (idx < 0) { | 650 | if (idx < 0) { |
600 | WARNING(rt2x00dev, "Frame received with unrecognized signal," | 651 | WARNING(rt2x00dev, "Frame received with unrecognized signal," |
601 | "signal=0x%.2x, plcp=%d.\n", rxdesc->signal, | 652 | "signal=0x%.2x, plcp=%d.\n", rxdesc.signal, |
602 | !!(rxdesc->dev_flags & RXDONE_SIGNAL_PLCP)); | 653 | !!(rxdesc.dev_flags & RXDONE_SIGNAL_PLCP)); |
603 | idx = 0; | 654 | idx = 0; |
604 | } | 655 | } |
605 | 656 | ||
@@ -607,17 +658,17 @@ void rt2x00lib_rxdone(struct queue_entry *entry, | |||
607 | * Only update link status if this is a beacon frame carrying our bssid. | 658 | * Only update link status if this is a beacon frame carrying our bssid. |
608 | */ | 659 | */ |
609 | hdr = (struct ieee80211_hdr *)entry->skb->data; | 660 | hdr = (struct ieee80211_hdr *)entry->skb->data; |
610 | fc = le16_to_cpu(hdr->frame_control); | 661 | if (ieee80211_is_beacon(hdr->frame_control) && |
611 | if (is_beacon(fc) && (rxdesc->dev_flags & RXDONE_MY_BSS)) | 662 | (rxdesc.dev_flags & RXDONE_MY_BSS)) |
612 | rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc->rssi); | 663 | rt2x00lib_update_link_stats(&rt2x00dev->link, rxdesc.rssi); |
613 | 664 | ||
614 | rt2x00dev->link.qual.rx_success++; | 665 | rt2x00dev->link.qual.rx_success++; |
615 | 666 | ||
616 | rx_status->rate_idx = idx; | 667 | rx_status->rate_idx = idx; |
617 | rx_status->qual = | 668 | rx_status->qual = |
618 | rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc->rssi); | 669 | rt2x00lib_calculate_link_signal(rt2x00dev, rxdesc.rssi); |
619 | rx_status->signal = rxdesc->rssi; | 670 | rx_status->signal = rxdesc.rssi; |
620 | rx_status->flag = rxdesc->flags; | 671 | rx_status->flag = rxdesc.flags; |
621 | rx_status->antenna = rt2x00dev->link.ant.active.rx; | 672 | rx_status->antenna = rt2x00dev->link.ant.active.rx; |
622 | 673 | ||
623 | /* | 674 | /* |
@@ -626,7 +677,16 @@ void rt2x00lib_rxdone(struct queue_entry *entry, | |||
626 | */ | 677 | */ |
627 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); | 678 | rt2x00debug_dump_frame(rt2x00dev, DUMP_FRAME_RXDONE, entry->skb); |
628 | ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb, rx_status); | 679 | ieee80211_rx_irqsafe(rt2x00dev->hw, entry->skb, rx_status); |
629 | entry->skb = NULL; | 680 | |
681 | /* | ||
682 | * Replace the skb with the freshly allocated one. | ||
683 | */ | ||
684 | entry->skb = skb; | ||
685 | entry->flags = 0; | ||
686 | |||
687 | rt2x00dev->ops->lib->init_rxentry(rt2x00dev, entry); | ||
688 | |||
689 | rt2x00queue_index_inc(entry->queue, Q_INDEX); | ||
630 | } | 690 | } |
631 | EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); | 691 | EXPORT_SYMBOL_GPL(rt2x00lib_rxdone); |
632 | 692 | ||