aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorBenoit Papillault <benoit.papillault@free.fr>2009-11-24 09:49:18 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-11-28 15:04:50 -0500
commit1bc1488067ee2c295b933ef6decd6035230f1a1c (patch)
tree3e378bdeee251367d08fec654056e046b9853c6b /drivers/net/wireless/ath
parente7824a50662f7f79b1a739f705b4d906c31cf221 (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')
-rw-r--r--drivers/net/wireless/ath/ath9k/common.c24
-rw-r--r--drivers/net/wireless/ath/ath9k/common.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c14
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c9
4 files changed, 31 insertions, 18 deletions
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index d96751ccee96..4d775ae141db 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -236,16 +236,8 @@ void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
236 /* see if any padding is done by the hw and remove it */ 236 /* see if any padding is done by the hw and remove it */
237 hdr = (struct ieee80211_hdr *) skb->data; 237 hdr = (struct ieee80211_hdr *) skb->data;
238 hdrlen = ieee80211_get_hdrlen_from_skb(skb); 238 hdrlen = ieee80211_get_hdrlen_from_skb(skb);
239 padpos = 24;
240 fc = hdr->frame_control; 239 fc = hdr->frame_control;
241 if ((fc & cpu_to_le16(IEEE80211_FCTL_FROMDS|IEEE80211_FCTL_TODS)) == 240 padpos = ath9k_cmn_padpos(hdr->frame_control);
242 cpu_to_le16(IEEE80211_FCTL_FROMDS|IEEE80211_FCTL_TODS)) {
243 padpos += 6; /* ETH_ALEN */
244 }
245 if ((fc & cpu_to_le16(IEEE80211_STYPE_QOS_DATA|IEEE80211_FCTL_FTYPE)) ==
246 cpu_to_le16(IEEE80211_STYPE_QOS_DATA|IEEE80211_FTYPE_DATA)) {
247 padpos += 2;
248 }
249 241
250 /* The MAC header is padded to have 32-bit boundary if the 242 /* The MAC header is padded to have 32-bit boundary if the
251 * packet payload is non-zero. The general calculation for 243 * packet payload is non-zero. The general calculation for
@@ -280,6 +272,20 @@ void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
280} 272}
281EXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess); 273EXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess);
282 274
275int ath9k_cmn_padpos(__le16 frame_control)
276{
277 int padpos = 24;
278 if (ieee80211_has_a4(frame_control)) {
279 padpos += ETH_ALEN;
280 }
281 if (ieee80211_is_data_qos(frame_control)) {
282 padpos += IEEE80211_QOS_CTL_LEN;
283 }
284
285 return padpos;
286}
287EXPORT_SYMBOL(ath9k_cmn_padpos);
288
283static int __init ath9k_cmn_init(void) 289static int __init ath9k_cmn_init(void)
284{ 290{
285 return 0; 291 return 0;
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index b230bb15279e..042999c2fe9c 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -123,3 +123,5 @@ void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
123 struct ath_rx_status *rx_stats, 123 struct ath_rx_status *rx_stats,
124 struct ieee80211_rx_status *rxs, 124 struct ieee80211_rx_status *rxs,
125 bool decrypt_error); 125 bool decrypt_error);
126
127int ath9k_cmn_padpos(__le16 frame_control);
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 */
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 6f91a8ae616f..564c6cb1c2b4 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1596,6 +1596,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
1596 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 1596 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
1597 int hdrlen; 1597 int hdrlen;
1598 __le16 fc; 1598 __le16 fc;
1599 int padpos, padsize;
1599 1600
1600 tx_info->pad[0] = 0; 1601 tx_info->pad[0] = 0;
1601 switch (txctl->frame_type) { 1602 switch (txctl->frame_type) {
@@ -1614,7 +1615,13 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
1614 ATH_TXBUF_RESET(bf); 1615 ATH_TXBUF_RESET(bf);
1615 1616
1616 bf->aphy = aphy; 1617 bf->aphy = aphy;
1617 bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3); 1618 bf->bf_frmlen = skb->len + FCS_LEN;
1619 /* Remove the padding size from bf_frmlen, if any */
1620 padpos = ath9k_cmn_padpos(hdr->frame_control);
1621 padsize = padpos & 3;
1622 if (padsize && skb->len>padpos+padsize) {
1623 bf->bf_frmlen -= padsize;
1624 }
1618 1625
1619 if (conf_is_ht(&hw->conf) && !is_pae(skb)) 1626 if (conf_is_ht(&hw->conf) && !is_pae(skb))
1620 bf->bf_state.bf_type |= BUF_HT; 1627 bf->bf_state.bf_type |= BUF_HT;