aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelix Fietkau2011-09-14 21:24:27 +0200
committerJohn W. Linville2011-09-16 16:45:42 -0400
commit4245d31347bdc99a608dc1d1cfe64e44aa3d1771 (patch)
tree0e0dbf7f829660ad4abe2dc24dc68040f458104d
parent3afd21e7c5b3b6312193fbee628b000dce82ecf5 (diff)
ath9k: do not insert padding into tx buffers on AR9380+
With the new EDMA descriptor format, a single descriptor can contain up to four buffer pointers. By splitting the buffer into two parts, we can let the hardware add the padding internally instead of using memmove on the skb data. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c56
1 files changed, 37 insertions, 19 deletions
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index a0cd51f28596..2c6aefad3728 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1017,6 +1017,8 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,
while (bf) {
struct sk_buff *skb = bf->bf_mpdu;
struct ath_frame_info *fi = get_frame_info(skb);
+ struct ieee80211_hdr *hdr;
+ int padpos, padsize;
info.type = get_hw_packet_type(skb);
if (bf->bf_next)
@@ -1024,8 +1026,20 @@ static void ath_tx_fill_desc(struct ath_softc *sc, struct ath_buf *bf,
else
info.link = 0;
- info.buf_addr[0] = bf->bf_buf_addr;
- info.buf_len[0] = skb->len;
+ if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) {
+ hdr = (struct ieee80211_hdr *)skb->data;
+ padpos = ath9k_cmn_padpos(hdr->frame_control);
+ padsize = padpos & 3;
+
+ info.buf_addr[0] = bf->bf_buf_addr;
+ info.buf_len[0] = padpos + padsize;
+ info.buf_addr[1] = info.buf_addr[0] + padpos;
+ info.buf_len[1] = skb->len - padpos;
+ } else {
+ info.buf_addr[0] = bf->bf_buf_addr;
+ info.buf_len[0] = skb->len;
+ }
+
info.pkt_len = fi->framelen;
info.keyix = fi->keyix;
info.keytype = fi->keytype;
@@ -1878,15 +1892,17 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
}
- /* Add the padding after the header if this is not already done */
- padpos = ath9k_cmn_padpos(hdr->frame_control);
- padsize = padpos & 3;
- if (padsize && skb->len > padpos) {
- if (skb_headroom(skb) < padsize)
- return -ENOMEM;
+ if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
+ /* Add the padding after the header if this is not already done */
+ padpos = ath9k_cmn_padpos(hdr->frame_control);
+ padsize = padpos & 3;
+ if (padsize && skb->len > padpos) {
+ if (skb_headroom(skb) < padsize)
+ return -ENOMEM;
- skb_push(skb, padsize);
- memmove(skb->data, skb->data + padsize, padpos);
+ skb_push(skb, padsize);
+ memmove(skb->data, skb->data + padsize, padpos);
+ }
}
if ((vif && vif->type != NL80211_IFTYPE_AP &&
@@ -1936,15 +1952,17 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
/* Frame was ACKed */
tx_info->flags |= IEEE80211_TX_STAT_ACK;
- padpos = ath9k_cmn_padpos(hdr->frame_control);
- padsize = padpos & 3;
- if (padsize && skb->len>padpos+padsize) {
- /*
- * Remove MAC header padding before giving the frame back to
- * mac80211.
- */
- memmove(skb->data + padsize, skb->data, padpos);
- skb_pull(skb, padsize);
+ if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)) {
+ padpos = ath9k_cmn_padpos(hdr->frame_control);
+ padsize = padpos & 3;
+ if (padsize && skb->len>padpos+padsize) {
+ /*
+ * Remove MAC header padding before giving the frame back to
+ * mac80211.
+ */
+ memmove(skb->data + padsize, skb->data, padpos);
+ skb_pull(skb, padsize);
+ }
}
if (sc->ps_flags & PS_WAIT_FOR_TX_ACK) {