aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath5k/hw.c
diff options
context:
space:
mode:
authorBruno Randolf <bruno@thinktube.com>2008-02-05 04:44:55 -0500
committerJohn W. Linville <linville@tuxdriver.com>2008-02-15 13:44:17 -0500
commit281c56dd276e587a7b4a65764ac68ae250e73235 (patch)
treeeead674f8740656d386465cc9dcef7feb867f9ff /drivers/net/wireless/ath5k/hw.c
parentbd196ec7f03fff6935f66a9a3cf27accd34a75b9 (diff)
ath5k: correct padding in tx descriptors
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>
Diffstat (limited to 'drivers/net/wireless/ath5k/hw.c')
-rw-r--r--drivers/net/wireless/ath5k/hw.c34
1 files changed, 20 insertions, 14 deletions
diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c
index 3a4bf4035a23..1ab57aa6e4dc 100644
--- a/drivers/net/wireless/ath5k/hw.c
+++ b/drivers/net/wireless/ath5k/hw.c
@@ -3506,7 +3506,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
3506{ 3506{
3507 u32 frame_type; 3507 u32 frame_type;
3508 struct ath5k_hw_2w_tx_desc *tx_desc; 3508 struct ath5k_hw_2w_tx_desc *tx_desc;
3509 unsigned int buff_len; 3509 unsigned int frame_len;
3510 3510
3511 tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0; 3511 tx_desc = (struct ath5k_hw_2w_tx_desc *)&desc->ds_ctl0;
3512 3512
@@ -3537,22 +3537,25 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc,
3537 /* Setup control descriptor */ 3537 /* Setup control descriptor */
3538 3538
3539 /* Verify and set frame length */ 3539 /* Verify and set frame length */
3540 if (pkt_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN) 3540
3541 /* remove padding we might have added before */
3542 frame_len = pkt_len - (hdr_len & 3) + FCS_LEN;
3543
3544 if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN)
3541 return -EINVAL; 3545 return -EINVAL;
3542 3546
3543 tx_desc->tx_control_0 = pkt_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN; 3547 tx_desc->tx_control_0 = frame_len & AR5K_2W_TX_DESC_CTL0_FRAME_LEN;
3544 3548
3545 /* Verify and set buffer length */ 3549 /* Verify and set buffer length */
3546 buff_len = pkt_len - FCS_LEN;
3547 3550
3548 /* NB: beacon's BufLen must be a multiple of 4 bytes */ 3551 /* NB: beacon's BufLen must be a multiple of 4 bytes */
3549 if(type == AR5K_PKT_TYPE_BEACON) 3552 if(type == AR5K_PKT_TYPE_BEACON)
3550 buff_len = roundup(buff_len, 4); 3553 pkt_len = roundup(pkt_len, 4);
3551 3554
3552 if (buff_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN) 3555 if (pkt_len & ~AR5K_2W_TX_DESC_CTL1_BUF_LEN)
3553 return -EINVAL; 3556 return -EINVAL;
3554 3557
3555 tx_desc->tx_control_1 = buff_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN; 3558 tx_desc->tx_control_1 = pkt_len & AR5K_2W_TX_DESC_CTL1_BUF_LEN;
3556 3559
3557 /* 3560 /*
3558 * Verify and set header length 3561 * Verify and set header length
@@ -3634,7 +3637,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
3634{ 3637{
3635 struct ath5k_hw_4w_tx_desc *tx_desc; 3638 struct ath5k_hw_4w_tx_desc *tx_desc;
3636 struct ath5k_hw_tx_status *tx_status; 3639 struct ath5k_hw_tx_status *tx_status;
3637 unsigned int buff_len; 3640 unsigned int frame_len;
3638 3641
3639 ATH5K_TRACE(ah->ah_sc); 3642 ATH5K_TRACE(ah->ah_sc);
3640 tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0; 3643 tx_desc = (struct ath5k_hw_4w_tx_desc *)&desc->ds_ctl0;
@@ -3669,22 +3672,25 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah,
3669 /* Setup control descriptor */ 3672 /* Setup control descriptor */
3670 3673
3671 /* Verify and set frame length */ 3674 /* Verify and set frame length */
3672 if (pkt_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) 3675
3676 /* remove padding we might have added before */
3677 frame_len = pkt_len - (hdr_len & 3) + FCS_LEN;
3678
3679 if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN)
3673 return -EINVAL; 3680 return -EINVAL;
3674 3681
3675 tx_desc->tx_control_0 = pkt_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN; 3682 tx_desc->tx_control_0 = frame_len & AR5K_4W_TX_DESC_CTL0_FRAME_LEN;
3676 3683
3677 /* Verify and set buffer length */ 3684 /* Verify and set buffer length */
3678 buff_len = pkt_len - FCS_LEN;
3679 3685
3680 /* NB: beacon's BufLen must be a multiple of 4 bytes */ 3686 /* NB: beacon's BufLen must be a multiple of 4 bytes */
3681 if(type == AR5K_PKT_TYPE_BEACON) 3687 if(type == AR5K_PKT_TYPE_BEACON)
3682 buff_len = roundup(buff_len, 4); 3688 pkt_len = roundup(pkt_len, 4);
3683 3689
3684 if (buff_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN) 3690 if (pkt_len & ~AR5K_4W_TX_DESC_CTL1_BUF_LEN)
3685 return -EINVAL; 3691 return -EINVAL;
3686 3692
3687 tx_desc->tx_control_1 = buff_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN; 3693 tx_desc->tx_control_1 = pkt_len & AR5K_4W_TX_DESC_CTL1_BUF_LEN;
3688 3694
3689 tx_desc->tx_control_0 |= 3695 tx_desc->tx_control_0 |=
3690 AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) | 3696 AR5K_REG_SM(tx_power, AR5K_4W_TX_DESC_CTL0_XMIT_POWER) |