Skip to content

Commit

Permalink
ath9k: Last fix for TX software padding.
Browse files Browse the repository at this point in the history
First, we copy/paste the padding stuff from ath9k_tx to ath_tx_cabq since it
needs to same kind of padding, but for internally generated beacons.
Next, software padding done on TX needs to be removed before calling
ieee80211_tx_status. The code was already there in ath_tx_complete but it
was wrong. Fix it by using ath9k_cmn_padpos. This later code has been
tested by sending packets to a monitor interface and reading packets from the
same interface.

Signed-off-by: Benoit PAPILLAULT <benoit.papillault@free.fr>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Benoit Papillault authored and John W. Linville committed Dec 21, 2009
1 parent 521d9bc commit 4d91f9f
Showing 1 changed file with 12 additions and 11 deletions.
23 changes: 12 additions & 11 deletions drivers/net/wireless/ath/ath9k/xmit.c
Original file line number Diff line number Diff line change
Expand Up @@ -1780,7 +1780,8 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
struct ath_wiphy *aphy = hw->priv;
struct ath_softc *sc = aphy->sc;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
int hdrlen, padsize;
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
int padpos, padsize;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ath_tx_control txctl;

Expand All @@ -1792,25 +1793,24 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
* BSSes.
*/
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
sc->tx.seq_no += 0x10;
hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
}

/* Add the padding after the header if this is not already done */
hdrlen = ieee80211_get_hdrlen_from_skb(skb);
if (hdrlen & 3) {
padsize = hdrlen % 4;
padpos = ath9k_cmn_padpos(hdr->frame_control);
padsize = padpos & 3;
if (padsize && skb->len>padpos) {
if (skb_headroom(skb) < padsize) {
ath_print(common, ATH_DBG_XMIT,
"TX CABQ padding failed\n");
dev_kfree_skb_any(skb);
return;
}
skb_push(skb, padsize);
memmove(skb->data, skb->data + padsize, hdrlen);
memmove(skb->data, skb->data + padsize, padpos);
}

txctl.txq = sc->beacon.cabq;
Expand Down Expand Up @@ -1838,7 +1838,8 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
struct ieee80211_hw *hw = sc->hw;
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
int hdrlen, padsize;
struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
int padpos, padsize;

ath_print(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb);

Expand All @@ -1853,14 +1854,14 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
tx_info->flags |= IEEE80211_TX_STAT_ACK;
}

hdrlen = ieee80211_get_hdrlen_from_skb(skb);
padsize = hdrlen & 3;
if (padsize && hdrlen >= 24) {
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, hdrlen);
memmove(skb->data + padsize, skb->data, padpos);
skb_pull(skb, padsize);
}

Expand Down

0 comments on commit 4d91f9f

Please sign in to comment.