Skip to content

Commit

Permalink
ath5k: correct padding in tx descriptors
Browse files Browse the repository at this point in the history
when setting up the tx descriptors for the hardware we must account for any
padding between the header and the data we might have added previously. frame
len is the length of the frame in the air (including FCS but no padding) and
buffer len is the length of the buffer (including padding, but without FCS).

changing the way ah_setup_tx_desc is called: now excluding the FCS, since it's
easier to add that in the function where we need it.

before this fix we sent trailing zero bytes after the packet (because frame len
included the padding) which was not a big problem without WEP, but with WEP
this resultes in a wrong WEP checksum and the packet is discarded - which is
how i noticed at all ;)

an easy way to run into header padding problems, btw, is to connect to a QoS
(WME) enabled access point (eg. madwifi) - QoS data frames are 2 byte longer
and will require padding.

this patch applies on top of luis latest patch series from 04.02.2008.

drivers/net/wireless/ath5k/base.c:      Changes-licensed-under: 3-Clause-BSD
drivers/net/wireless/ath5k/hw.c:        Changes-licensed-under: ISC

Signed-off-by: Bruno Randolf <bruno@thinktube.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Bruno Randolf authored and John W. Linville committed Feb 15, 2008
1 parent bd196ec commit 281c56d
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 16 deletions.
4 changes: 2 additions & 2 deletions drivers/net/wireless/ath5k/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -1256,7 +1256,7 @@ ath5k_txbuf_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
if (ctl->flags & IEEE80211_TXCTL_NO_ACK)
flags |= AR5K_TXDESC_NOACK;

pktlen = skb->len + FCS_LEN;
pktlen = skb->len;

if (!(ctl->flags & IEEE80211_TXCTL_DO_NOT_ENCRYPT)) {
keyidx = ctl->key_idx;
Expand Down Expand Up @@ -1952,7 +1952,7 @@ ath5k_beacon_setup(struct ath5k_softc *sc, struct ath5k_buf *bf,
}

ds->ds_data = bf->skbaddr;
ret = ah->ah_setup_tx_desc(ah, ds, skb->len + FCS_LEN,
ret = ah->ah_setup_tx_desc(ah, ds, skb->len,
ieee80211_get_hdrlen_from_skb(skb),
AR5K_PKT_TYPE_BEACON, (ctl->power_level * 2), ctl->tx_rate, 1,
AR5K_TXKEYIX_INVALID, antenna, flags, 0, 0);
Expand Down
34 changes: 20 additions & 14 deletions drivers/net/wireless/ath5k/hw.c
Original file line number Diff line number Diff line change
Expand Up @@ -3506,7 +3506,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
{
u32 frame_type;
struct ath5k_hw_2w_tx_desc *tx_desc;
unsigned int buff_len;
unsigned int frame_len;

tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0;

Expand Down Expand Up @@ -3537,22 +3537,25 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
/* Setup control descriptor */

/* Verify and set frame length */
if (pkt_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)

/* remove padding we might have added before */
frame_len = pkt_len - (hdr_len & 3) + FCS_LEN;

if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
return -EINVAL;

tx_desc->tx_control_0 = pkt_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
tx_desc->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;

/* Verify and set buffer length */
buff_len = pkt_len - FCS_LEN;

/* NB: beacon's BufLen must be a multiple of 4 bytes */
if(type == AR5K_PKT_TYPE_BEACON)
buff_len = roundup(buff_len, 4);
pkt_len = roundup(pkt_len, 4);

if (buff_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
return -EINVAL;

tx_desc->tx_control_1 = buff_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
tx_desc->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;

/*
* Verify and set header length
Expand Down Expand Up @@ -3634,7 +3637,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
{
struct ath5k_hw_4w_tx_desc *tx_desc;
struct ath5k_hw_tx_status *tx_status;
unsigned int buff_len;
unsigned int frame_len;

ATH5K_TRACE(ah->ah_sc);
tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
Expand Down Expand Up @@ -3669,22 +3672,25 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
/* Setup control descriptor */

/* Verify and set frame length */
if (pkt_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)

/* remove padding we might have added before */
frame_len = pkt_len - (hdr_len & 3) + FCS_LEN;

if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
return -EINVAL;

tx_desc->tx_control_0 = pkt_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
tx_desc->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;

/* Verify and set buffer length */
buff_len = pkt_len - FCS_LEN;

/* NB: beacon's BufLen must be a multiple of 4 bytes */
if(type == AR5K_PKT_TYPE_BEACON)
buff_len = roundup(buff_len, 4);
pkt_len = roundup(pkt_len, 4);

if (buff_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
return -EINVAL;

tx_desc->tx_control_1 = buff_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
tx_desc->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;

tx_desc->tx_control_0 |=
AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |
Expand Down

0 comments on commit 281c56d

Please sign in to comment.