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>
This commit is contained in:
Luis R. Rodriguez 2009-11-04 08:20:42 -08:00 committed by John W. Linville
parent dbfc22df1a
commit 5ca42627f3

View File

@ -283,8 +283,6 @@ static int ath_rx_prepare(struct ath_common *common,
{ {
struct ath_hw *ah = common->ah; struct ath_hw *ah = common->ah;
memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
if (!ath9k_rx_accept(common, skb, rx_status, rx_stats, decrypt_error)) if (!ath9k_rx_accept(common, skb, rx_status, rx_stats, decrypt_error))
goto rx_next; goto rx_next;
@ -654,7 +652,7 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb)
static void ath_rx_send_to_mac80211(struct ieee80211_hw *hw, static void ath_rx_send_to_mac80211(struct ieee80211_hw *hw,
struct ath_softc *sc, struct sk_buff *skb, struct ath_softc *sc, struct sk_buff *skb,
struct ieee80211_rx_status *rx_status) struct ieee80211_rx_status *rxs)
{ {
struct ieee80211_hdr *hdr; struct ieee80211_hdr *hdr;
@ -674,19 +672,14 @@ static void ath_rx_send_to_mac80211(struct ieee80211_hw *hw,
if (aphy == NULL) if (aphy == NULL)
continue; continue;
nskb = skb_copy(skb, GFP_ATOMIC); nskb = skb_copy(skb, GFP_ATOMIC);
if (nskb) { if (!nskb)
memcpy(IEEE80211_SKB_RXCB(nskb), rx_status, continue;
sizeof(*rx_status)); ieee80211_rx(aphy->hw, nskb);
ieee80211_rx(aphy->hw, nskb);
}
} }
memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status));
ieee80211_rx(sc->hw, skb); ieee80211_rx(sc->hw, skb);
} else { } else
/* Deliver unicast frames based on receiver address */ /* Deliver unicast frames based on receiver address */
memcpy(IEEE80211_SKB_RXCB(skb), rx_status, sizeof(*rx_status));
ieee80211_rx(hw, skb); ieee80211_rx(hw, skb);
}
} }
int ath_rx_tasklet(struct ath_softc *sc, int flush) int ath_rx_tasklet(struct ath_softc *sc, int flush)
@ -699,7 +692,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
struct ath_desc *ds; struct ath_desc *ds;
struct ath_rx_status *rx_stats; struct ath_rx_status *rx_stats;
struct sk_buff *skb = NULL, *requeue_skb; struct sk_buff *skb = NULL, *requeue_skb;
struct ieee80211_rx_status rx_status; struct ieee80211_rx_status *rxs;
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
/* /*
@ -788,6 +781,8 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
DMA_FROM_DEVICE); DMA_FROM_DEVICE);
hdr = (struct ieee80211_hdr *) skb->data; hdr = (struct ieee80211_hdr *) skb->data;
rxs = IEEE80211_SKB_RXCB(skb);
hw = ath_get_virt_hw(sc, hdr); hw = ath_get_virt_hw(sc, hdr);
rx_stats = &ds->ds_rxstat; rx_stats = &ds->ds_rxstat;
@ -806,7 +801,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
goto requeue; goto requeue;
if (!ath_rx_prepare(common, hw, skb, rx_stats, if (!ath_rx_prepare(common, hw, skb, rx_stats,
&rx_status, &decrypt_error)) rxs, &decrypt_error))
goto requeue; goto requeue;
/* Ensure we always have an skb to requeue once we are done /* 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)
keyix = rx_stats->rs_keyix; keyix = rx_stats->rs_keyix;
if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) { if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) {
rx_status.flag |= RX_FLAG_DECRYPTED; rxs->flag |= RX_FLAG_DECRYPTED;
} else if (ieee80211_has_protected(fc) } else if (ieee80211_has_protected(fc)
&& !decrypt_error && skb->len >= hdrlen + 4) { && !decrypt_error && skb->len >= hdrlen + 4) {
keyix = skb->data[hdrlen + 3] >> 6; keyix = skb->data[hdrlen + 3] >> 6;
if (test_bit(keyix, sc->keymap)) if (test_bit(keyix, sc->keymap))
rx_status.flag |= RX_FLAG_DECRYPTED; rxs->flag |= RX_FLAG_DECRYPTED;
} }
if (ah->sw_mgmt_crypto && if (ah->sw_mgmt_crypto &&
(rx_status.flag & RX_FLAG_DECRYPTED) && (rxs->flag & RX_FLAG_DECRYPTED) &&
ieee80211_is_mgmt(fc)) { ieee80211_is_mgmt(fc))
/* Use software decrypt for management frames. */ /* Use software decrypt for management frames. */
rx_status.flag &= ~RX_FLAG_DECRYPTED; rxs->flag &= ~RX_FLAG_DECRYPTED;
}
/* We will now give hardware our shiny new allocated skb */ /* We will now give hardware our shiny new allocated skb */
bf->bf_mpdu = requeue_skb; bf->bf_mpdu = requeue_skb;
@ -874,7 +868,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
bf->bf_mpdu = NULL; bf->bf_mpdu = NULL;
ath_print(common, ATH_DBG_FATAL, ath_print(common, ATH_DBG_FATAL,
"dma_mapping_error() on RX\n"); "dma_mapping_error() on RX\n");
ath_rx_send_to_mac80211(hw, sc, skb, &rx_status); ath_rx_send_to_mac80211(hw, sc, skb, rxs);
break; break;
} }
bf->bf_dmacontext = bf->bf_buf_addr; bf->bf_dmacontext = bf->bf_buf_addr;
@ -895,7 +889,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush)
SC_OP_WAIT_FOR_PSPOLL_DATA))) SC_OP_WAIT_FOR_PSPOLL_DATA)))
ath_rx_ps(sc, skb); ath_rx_ps(sc, skb);
ath_rx_send_to_mac80211(hw, sc, skb, &rx_status); ath_rx_send_to_mac80211(hw, sc, skb, rxs);
requeue: requeue:
list_move_tail(&bf->list, &sc->rx.rxbuf); list_move_tail(&bf->list, &sc->rx.rxbuf);