diff options
author | Benoit Papillault <benoit.papillault@free.fr> | 2009-11-24 09:49:18 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2009-11-28 15:04:50 -0500 |
commit | 1bc1488067ee2c295b933ef6decd6035230f1a1c (patch) | |
tree | 3e378bdeee251367d08fec654056e046b9853c6b /drivers/net/wireless/ath/ath9k/main.c | |
parent | e7824a50662f7f79b1a739f705b4d906c31cf221 (diff) |
ath9k: Proper padding/unpadding for the TX/RX path.
Software padding is done on the TX path and software unpadding is done on the
RX path. This patch corrects the position where the padding occurs. A specific
function computes the pad position and this function is used in the TX and RX
path. This patch has been tested by generating every possible 802.11 frames
with every possible frame_control field and a varying length. This patch is
useful for analyzing non standard 802.11 frames going over the air
Signed-off-by: Benoit Papillault <benoit.papillault@free.fr>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/main.c')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 14 |
1 files changed, 6 insertions, 8 deletions
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 55c669648bd6..cfe710b01d85 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -2364,7 +2364,8 @@ static int ath9k_tx(struct ieee80211_hw *hw, | |||
2364 | struct ath_softc *sc = aphy->sc; | 2364 | struct ath_softc *sc = aphy->sc; |
2365 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 2365 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
2366 | struct ath_tx_control txctl; | 2366 | struct ath_tx_control txctl; |
2367 | int hdrlen, padsize; | 2367 | int padpos, padsize; |
2368 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
2368 | 2369 | ||
2369 | if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) { | 2370 | if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) { |
2370 | ath_print(common, ATH_DBG_XMIT, | 2371 | ath_print(common, ATH_DBG_XMIT, |
@@ -2374,7 +2375,6 @@ static int ath9k_tx(struct ieee80211_hw *hw, | |||
2374 | } | 2375 | } |
2375 | 2376 | ||
2376 | if (sc->ps_enabled) { | 2377 | if (sc->ps_enabled) { |
2377 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
2378 | /* | 2378 | /* |
2379 | * mac80211 does not set PM field for normal data frames, so we | 2379 | * mac80211 does not set PM field for normal data frames, so we |
2380 | * need to update that based on the current PS mode. | 2380 | * need to update that based on the current PS mode. |
@@ -2394,7 +2394,6 @@ static int ath9k_tx(struct ieee80211_hw *hw, | |||
2394 | * power save mode. Need to wake up hardware for the TX to be | 2394 | * power save mode. Need to wake up hardware for the TX to be |
2395 | * completed and if needed, also for RX of buffered frames. | 2395 | * completed and if needed, also for RX of buffered frames. |
2396 | */ | 2396 | */ |
2397 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
2398 | ath9k_ps_wakeup(sc); | 2397 | ath9k_ps_wakeup(sc); |
2399 | ath9k_hw_setrxabort(sc->sc_ah, 0); | 2398 | ath9k_hw_setrxabort(sc->sc_ah, 0); |
2400 | if (ieee80211_is_pspoll(hdr->frame_control)) { | 2399 | if (ieee80211_is_pspoll(hdr->frame_control)) { |
@@ -2422,7 +2421,6 @@ static int ath9k_tx(struct ieee80211_hw *hw, | |||
2422 | * BSSes. | 2421 | * BSSes. |
2423 | */ | 2422 | */ |
2424 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | 2423 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { |
2425 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
2426 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) | 2424 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) |
2427 | sc->tx.seq_no += 0x10; | 2425 | sc->tx.seq_no += 0x10; |
2428 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | 2426 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); |
@@ -2430,13 +2428,13 @@ static int ath9k_tx(struct ieee80211_hw *hw, | |||
2430 | } | 2428 | } |
2431 | 2429 | ||
2432 | /* Add the padding after the header if this is not already done */ | 2430 | /* Add the padding after the header if this is not already done */ |
2433 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 2431 | padpos = ath9k_cmn_padpos(hdr->frame_control); |
2434 | if (hdrlen & 3) { | 2432 | padsize = padpos & 3; |
2435 | padsize = hdrlen % 4; | 2433 | if (padsize && skb->len>padpos) { |
2436 | if (skb_headroom(skb) < padsize) | 2434 | if (skb_headroom(skb) < padsize) |
2437 | return -1; | 2435 | return -1; |
2438 | skb_push(skb, padsize); | 2436 | skb_push(skb, padsize); |
2439 | memmove(skb->data, skb->data + padsize, hdrlen); | 2437 | memmove(skb->data, skb->data + padsize, padpos); |
2440 | } | 2438 | } |
2441 | 2439 | ||
2442 | /* Check if a tx queue is available */ | 2440 | /* Check if a tx queue is available */ |