diff options
author | Luis R. Rodriguez <lrodriguez@atheros.com> | 2009-11-04 11:20:42 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-11-11 17:09:07 -0500 |
commit | 5ca42627f3ddc0e4fc3e62d879cc35ab5beaaa8b (patch) | |
tree | 097aec55f4b63beb7d2d37d81161e51d93d09be7 /drivers/net/wireless | |
parent | dbfc22df1afbeb91d528e2f84d6603ac9ce98bc2 (diff) |
ath9k: avoid the copy skb->cb on every RX'd skb
The skb->cb (control buffer, 48 bytes) is available to the skb
upon skb allocation. You can fill it up imediately after skb
allocation. ath9k was copying onto the skb->cb the data from the
processed skb for mac80211 from a stack struct ieee80211_rx_status
structure. This is unnecessary, instead use the skb->cb for the
rx status immediately after the skb becomes available and DMA
synched.
Additionally, avoid the copy of the skb->cb also for virtual wiphys
as skb_copy() will copy over the skb->cb for us as well.
Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/recv.c | 38 |
1 files changed, 16 insertions, 22 deletions
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 4c4c22f54e99..079361423efc 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -283,8 +283,6 @@ static int ath_rx_prepare(struct ath_common *common, | |||
283 | { | 283 | { |
284 | struct ath_hw *ah = common->ah; | 284 | struct ath_hw *ah = common->ah; |
285 | 285 | ||
286 | memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); | ||
287 | |||
288 | if (!ath9k_rx_accept(common, skb, rx_status, rx_stats, decrypt_error)) | 286 | if (!ath9k_rx_accept(common, skb, rx_status, rx_stats, decrypt_error)) |
289 | goto rx_next; | 287 | goto rx_next; |
290 | 288 | ||
@@ -654,7 +652,7 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb) | |||
654 | 652 | ||
655 | static void ath_rx_send_to_mac80211(struct ieee80211_hw *hw, | 653 | static void ath_rx_send_to_mac80211(struct ieee80211_hw *hw, |
656 | struct ath_softc *sc, struct sk_buff *skb, | 654 | struct ath_softc *sc, struct sk_buff *skb, |
657 | struct ieee80211_rx_status *rx_status) | 655 | struct ieee80211_rx_status *rxs) |
658 | { | 656 | { |
659 | struct ieee80211_hdr *hdr; | 657 | struct ieee80211_hdr *hdr; |
660 | 658 | ||
@@ -674,19 +672,14 @@ static void ath_rx_send_to_mac80211(struct ieee80211_hw *hw, | |||
674 | if (aphy == NULL) | 672 | if (aphy == NULL) |
675 | continue; | 673 | continue; |
676 | nskb = skb_copy(skb, GFP_ATOMIC); | 674 | nskb = skb_copy(skb, GFP_ATOMIC); |
677 | if (nskb) { | 675 | if (!nskb) |
678 | memcpy(IEEE80211_SKB_RXCB(nskb), rx_status, | 676 | continue; |
679 | sizeof(*rx_status)); | 677 | ieee80211_rx(aphy->hw, nskb); |
680 | ieee80211_rx(aphy->hw, nskb); | ||
681 | } | ||
682 | } | 678 | } |
683 | memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status)); | ||
684 | ieee80211_rx(sc->hw, skb); | 679 | ieee80211_rx(sc->hw, skb); |
685 | } else { | 680 | } else |
686 | /* Deliver unicast frames based on receiver address */ | 681 | /* Deliver unicast frames based on receiver address */ |
687 | memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status)); | ||
688 | ieee80211_rx(hw, skb); | 682 | ieee80211_rx(hw, skb); |
689 | } | ||
690 | } | 683 | } |
691 | 684 | ||
692 | int ath_rx_tasklet(struct ath_softc *sc, int flush) | 685 | int ath_rx_tasklet(struct ath_softc *sc, int flush) |
@@ -699,7 +692,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
699 | struct ath_desc *ds; | 692 | struct ath_desc *ds; |
700 | struct ath_rx_status *rx_stats; | 693 | struct ath_rx_status *rx_stats; |
701 | struct sk_buff *skb = NULL, *requeue_skb; | 694 | struct sk_buff *skb = NULL, *requeue_skb; |
702 | struct ieee80211_rx_status rx_status; | 695 | struct ieee80211_rx_status *rxs; |
703 | struct ath_hw *ah = sc->sc_ah; | 696 | struct ath_hw *ah = sc->sc_ah; |
704 | struct ath_common *common = ath9k_hw_common(ah); | 697 | struct ath_common *common = ath9k_hw_common(ah); |
705 | /* | 698 | /* |
@@ -788,6 +781,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
788 | DMA_FROM_DEVICE); | 781 | DMA_FROM_DEVICE); |
789 | 782 | ||
790 | hdr = (struct ieee80211_hdr *) skb->data; | 783 | hdr = (struct ieee80211_hdr *) skb->data; |
784 | rxs = IEEE80211_SKB_RXCB(skb); | ||
785 | |||
791 | hw = ath_get_virt_hw(sc, hdr); | 786 | hw = ath_get_virt_hw(sc, hdr); |
792 | rx_stats = &ds->ds_rxstat; | 787 | rx_stats = &ds->ds_rxstat; |
793 | 788 | ||
@@ -806,7 +801,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
806 | goto requeue; | 801 | goto requeue; |
807 | 802 | ||
808 | if (!ath_rx_prepare(common, hw, skb, rx_stats, | 803 | if (!ath_rx_prepare(common, hw, skb, rx_stats, |
809 | &rx_status, &decrypt_error)) | 804 | rxs, &decrypt_error)) |
810 | goto requeue; | 805 | goto requeue; |
811 | 806 | ||
812 | /* Ensure we always have an skb to requeue once we are done | 807 | /* Ensure we always have an skb to requeue once we are done |
@@ -848,20 +843,19 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
848 | keyix = rx_stats->rs_keyix; | 843 | keyix = rx_stats->rs_keyix; |
849 | 844 | ||
850 | if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) { | 845 | if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) { |
851 | rx_status.flag |= RX_FLAG_DECRYPTED; | 846 | rxs->flag |= RX_FLAG_DECRYPTED; |
852 | } else if (ieee80211_has_protected(fc) | 847 | } else if (ieee80211_has_protected(fc) |
853 | && !decrypt_error && skb->len >= hdrlen + 4) { | 848 | && !decrypt_error && skb->len >= hdrlen + 4) { |
854 | keyix = skb->data[hdrlen + 3] >> 6; | 849 | keyix = skb->data[hdrlen + 3] >> 6; |
855 | 850 | ||
856 | if (test_bit(keyix, sc->keymap)) | 851 | if (test_bit(keyix, sc->keymap)) |
857 | rx_status.flag |= RX_FLAG_DECRYPTED; | 852 | rxs->flag |= RX_FLAG_DECRYPTED; |
858 | } | 853 | } |
859 | if (ah->sw_mgmt_crypto && | 854 | if (ah->sw_mgmt_crypto && |
860 | (rx_status.flag & RX_FLAG_DECRYPTED) && | 855 | (rxs->flag & RX_FLAG_DECRYPTED) && |
861 | ieee80211_is_mgmt(fc)) { | 856 | ieee80211_is_mgmt(fc)) |
862 | /* Use software decrypt for management frames. */ | 857 | /* Use software decrypt for management frames. */ |
863 | rx_status.flag &= ~RX_FLAG_DECRYPTED; | 858 | rxs->flag &= ~RX_FLAG_DECRYPTED; |
864 | } | ||
865 | 859 | ||
866 | /* We will now give hardware our shiny new allocated skb */ | 860 | /* We will now give hardware our shiny new allocated skb */ |
867 | bf->bf_mpdu = requeue_skb; | 861 | bf->bf_mpdu = requeue_skb; |
@@ -874,7 +868,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
874 | bf->bf_mpdu = NULL; | 868 | bf->bf_mpdu = NULL; |
875 | ath_print(common, ATH_DBG_FATAL, | 869 | ath_print(common, ATH_DBG_FATAL, |
876 | "dma_mapping_error() on RX\n"); | 870 | "dma_mapping_error() on RX\n"); |
877 | ath_rx_send_to_mac80211(hw, sc, skb, &rx_status); | 871 | ath_rx_send_to_mac80211(hw, sc, skb, rxs); |
878 | break; | 872 | break; |
879 | } | 873 | } |
880 | bf->bf_dmacontext = bf->bf_buf_addr; | 874 | bf->bf_dmacontext = bf->bf_buf_addr; |
@@ -895,7 +889,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
895 | SC_OP_WAIT_FOR_PSPOLL_DATA))) | 889 | SC_OP_WAIT_FOR_PSPOLL_DATA))) |
896 | ath_rx_ps(sc, skb); | 890 | ath_rx_ps(sc, skb); |
897 | 891 | ||
898 | ath_rx_send_to_mac80211(hw, sc, skb, &rx_status); | 892 | ath_rx_send_to_mac80211(hw, sc, skb, rxs); |
899 | 893 | ||
900 | requeue: | 894 | requeue: |
901 | list_move_tail(&bf->list, &sc->rx.rxbuf); | 895 | list_move_tail(&bf->list, &sc->rx.rxbuf); |