diff options
author | Benoit Papillault <benoit.papillault@free.fr> | 2009-12-11 18:22:35 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-12-21 11:32:00 -0500 |
commit | 4d91f9f3730d6d82a3ba67cae215a1823ba6a191 (patch) | |
tree | b3784db7bc8b1c4eeb814f1c2e7c2ba182c140bb | |
parent | 521d9bce86331d8261213b807a9127f7e2ec046b (diff) |
ath9k: Last fix for TX software padding.
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>
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 23 |
1 files changed, 12 insertions, 11 deletions
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 2a11cc57ceea..67706205699b 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -1780,7 +1780,8 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1780 | struct ath_wiphy *aphy = hw->priv; | 1780 | struct ath_wiphy *aphy = hw->priv; |
1781 | struct ath_softc *sc = aphy->sc; | 1781 | struct ath_softc *sc = aphy->sc; |
1782 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1782 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1783 | int hdrlen, padsize; | 1783 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
1784 | int padpos, padsize; | ||
1784 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | 1785 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); |
1785 | struct ath_tx_control txctl; | 1786 | struct ath_tx_control txctl; |
1786 | 1787 | ||
@@ -1792,7 +1793,6 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1792 | * BSSes. | 1793 | * BSSes. |
1793 | */ | 1794 | */ |
1794 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | 1795 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { |
1795 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
1796 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) | 1796 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) |
1797 | sc->tx.seq_no += 0x10; | 1797 | sc->tx.seq_no += 0x10; |
1798 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | 1798 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); |
@@ -1800,9 +1800,9 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1800 | } | 1800 | } |
1801 | 1801 | ||
1802 | /* Add the padding after the header if this is not already done */ | 1802 | /* Add the padding after the header if this is not already done */ |
1803 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 1803 | padpos = ath9k_cmn_padpos(hdr->frame_control); |
1804 | if (hdrlen & 3) { | 1804 | padsize = padpos & 3; |
1805 | padsize = hdrlen % 4; | 1805 | if (padsize && skb->len>padpos) { |
1806 | if (skb_headroom(skb) < padsize) { | 1806 | if (skb_headroom(skb) < padsize) { |
1807 | ath_print(common, ATH_DBG_XMIT, | 1807 | ath_print(common, ATH_DBG_XMIT, |
1808 | "TX CABQ padding failed\n"); | 1808 | "TX CABQ padding failed\n"); |
@@ -1810,7 +1810,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
1810 | return; | 1810 | return; |
1811 | } | 1811 | } |
1812 | skb_push(skb, padsize); | 1812 | skb_push(skb, padsize); |
1813 | memmove(skb->data, skb->data + padsize, hdrlen); | 1813 | memmove(skb->data, skb->data + padsize, padpos); |
1814 | } | 1814 | } |
1815 | 1815 | ||
1816 | txctl.txq = sc->beacon.cabq; | 1816 | txctl.txq = sc->beacon.cabq; |
@@ -1838,7 +1838,8 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1838 | struct ieee80211_hw *hw = sc->hw; | 1838 | struct ieee80211_hw *hw = sc->hw; |
1839 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 1839 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
1840 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1840 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1841 | int hdrlen, padsize; | 1841 | struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; |
1842 | int padpos, padsize; | ||
1842 | 1843 | ||
1843 | ath_print(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); | 1844 | ath_print(common, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); |
1844 | 1845 | ||
@@ -1853,14 +1854,14 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
1853 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | 1854 | tx_info->flags |= IEEE80211_TX_STAT_ACK; |
1854 | } | 1855 | } |
1855 | 1856 | ||
1856 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 1857 | padpos = ath9k_cmn_padpos(hdr->frame_control); |
1857 | padsize = hdrlen & 3; | 1858 | padsize = padpos & 3; |
1858 | if (padsize && hdrlen >= 24) { | 1859 | if (padsize && skb->len>padpos+padsize) { |
1859 | /* | 1860 | /* |
1860 | * Remove MAC header padding before giving the frame back to | 1861 | * Remove MAC header padding before giving the frame back to |
1861 | * mac80211. | 1862 | * mac80211. |
1862 | */ | 1863 | */ |
1863 | memmove(skb->data + padsize, skb->data, hdrlen); | 1864 | memmove(skb->data + padsize, skb->data, padpos); |
1864 | skb_pull(skb, padsize); | 1865 | skb_pull(skb, padsize); |
1865 | } | 1866 | } |
1866 | 1867 | ||