Skip to content

Commit

Permalink
ath9k: do not insert padding into tx buffers on AR9380+
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Felix Fietkau authored and John W. Linville committed Sep 16, 2011
1 parent 3afd21e commit 4245d31
Showing 1 changed file with 37 additions and 19 deletions.
56 changes: 37 additions & 19 deletions drivers/net/wireless/ath/ath9k/xmit.c
Original file line number Diff line number Diff line change
Expand Up @@ -1017,15 +1017,29 @@ 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)
info.link = bf->bf_next->bf_daddr;
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;
Expand Down Expand Up @@ -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 &&
Expand Down Expand Up @@ -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) {
Expand Down

0 comments on commit 4245d31

Please sign in to comment.