From 1f08e84ff642294e42d138442a388989ffb20865 Mon Sep 17 00:00:00 2001 From: Igor Perminov Date: Tue, 22 Sep 2009 00:25:44 +0400 Subject: [PATCH 1/5] mac80211: Fix [re]association power saving issue on AP side Consider the following step-by step: 1. A STA authenticates and associates with the AP and exchanges traffic. 2. The STA reports to the AP that it is going to PS state. 3. Some time later the STA device goes to the stand-by mode (not only its wi-fi card, but the device itself) and drops the association state without sending a disassociation frame. 4. The STA device wakes up and begins authentication with an Auth frame as it hasn't been authenticated/associated previously. At the step 4 the AP "remembers" the STA and considers it is still in the PS state, so the AP buffers frames, which it has to send to the STA. But the STA isn't actually in the PS state and so it neither checks TIM bits nor reports to the AP that it isn't power saving. Because of that authentication/[re]association fails. To fix authentication/[re]association stage of this issue, Auth, Assoc Resp and Reassoc Resp frames are transmitted disregarding of STA's power saving state. N.B. This patch doesn't fix further data frame exchange after authentication/[re]association. A patch in hostapd is required to fix that. Signed-off-by: Igor Perminov Signed-off-by: John W. Linville --- net/mac80211/tx.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 5143d203256b..fd4028296613 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -367,7 +367,10 @@ ieee80211_tx_h_unicast_ps_buf(struct ieee80211_tx_data *tx) struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)tx->skb->data; u32 staflags; - if (unlikely(!sta || ieee80211_is_probe_resp(hdr->frame_control))) + if (unlikely(!sta || ieee80211_is_probe_resp(hdr->frame_control) + || ieee80211_is_auth(hdr->frame_control) + || ieee80211_is_assoc_resp(hdr->frame_control) + || ieee80211_is_reassoc_resp(hdr->frame_control))) return TX_CONTINUE; staflags = get_sta_flags(sta); From b96ab540c1deac17238c4902c328ee08c3130370 Mon Sep 17 00:00:00 2001 From: Michael Buesch Date: Wed, 23 Sep 2009 18:51:21 +0200 Subject: [PATCH 2/5] b43: Always use block-I/O for the PIO data registers On SDIO the PIO data register seems to be hardwired to LE. So the MACCTL bit has no effect on the endianness. So also use block-I/O for the last word of the packet. block-I/O is always LE. Signed-off-by: Michael Buesch Tested-by: Albert Herranz Signed-off-by: John W. Linville --- drivers/net/wireless/b43/pio.c | 60 +++++++++++++++++++++------------- 1 file changed, 38 insertions(+), 22 deletions(-) diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c index e96091b31499..9c1397996e0a 100644 --- a/drivers/net/wireless/b43/pio.c +++ b/drivers/net/wireless/b43/pio.c @@ -340,10 +340,15 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q, q->mmio_base + B43_PIO_TXDATA, sizeof(u16)); if (data_len & 1) { + u8 tail[2] = { 0, }; + /* Write the last byte. */ ctl &= ~B43_PIO_TXCTL_WRITEHI; b43_piotx_write16(q, B43_PIO_TXCTL, ctl); - b43_piotx_write16(q, B43_PIO_TXDATA, data[data_len - 1]); + tail[0] = data[data_len - 1]; + ssb_block_write(dev->dev, tail, 2, + q->mmio_base + B43_PIO_TXDATA, + sizeof(u16)); } return ctl; @@ -386,26 +391,31 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q, q->mmio_base + B43_PIO8_TXDATA, sizeof(u32)); if (data_len & 3) { - u32 value = 0; + u8 tail[4] = { 0, }; /* Write the last few bytes. */ ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_24_31); - data = &(data[data_len - 1]); switch (data_len & 3) { case 3: - ctl |= B43_PIO8_TXCTL_16_23; - value |= (u32)(*data) << 16; - data--; + ctl |= B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_8_15; + tail[0] = data[data_len - 3]; + tail[1] = data[data_len - 2]; + tail[2] = data[data_len - 1]; + break; case 2: ctl |= B43_PIO8_TXCTL_8_15; - value |= (u32)(*data) << 8; - data--; + tail[0] = data[data_len - 2]; + tail[1] = data[data_len - 1]; + break; case 1: - value |= (u32)(*data); + tail[0] = data[data_len - 1]; + break; } b43_piotx_write32(q, B43_PIO8_TXCTL, ctl); - b43_piotx_write32(q, B43_PIO8_TXDATA, value); + ssb_block_write(dev->dev, tail, 4, + q->mmio_base + B43_PIO8_TXDATA, + sizeof(u32)); } return ctl; @@ -693,21 +703,25 @@ static bool pio_rx_frame(struct b43_pio_rxqueue *q) q->mmio_base + B43_PIO8_RXDATA, sizeof(u32)); if (len & 3) { - u32 value; - char *data; + u8 tail[4] = { 0, }; /* Read the last few bytes. */ - value = b43_piorx_read32(q, B43_PIO8_RXDATA); - data = &(skb->data[len + padding - 1]); + ssb_block_read(dev->dev, tail, 4, + q->mmio_base + B43_PIO8_RXDATA, + sizeof(u32)); switch (len & 3) { case 3: - *data = (value >> 16); - data--; + skb->data[len + padding - 3] = tail[0]; + skb->data[len + padding - 2] = tail[1]; + skb->data[len + padding - 1] = tail[2]; + break; case 2: - *data = (value >> 8); - data--; + skb->data[len + padding - 2] = tail[0]; + skb->data[len + padding - 1] = tail[1]; + break; case 1: - *data = value; + skb->data[len + padding - 1] = tail[0]; + break; } } } else { @@ -715,11 +729,13 @@ static bool pio_rx_frame(struct b43_pio_rxqueue *q) q->mmio_base + B43_PIO_RXDATA, sizeof(u16)); if (len & 1) { - u16 value; + u8 tail[2] = { 0, }; /* Read the last byte. */ - value = b43_piorx_read16(q, B43_PIO_RXDATA); - skb->data[len + padding - 1] = value; + ssb_block_read(dev->dev, tail, 2, + q->mmio_base + B43_PIO_RXDATA, + sizeof(u16)); + skb->data[len + padding - 1] = tail[0]; } } From ffed1307c9672337fc7d051ab5ed04f8806467e2 Mon Sep 17 00:00:00 2001 From: Jouni Malinen Date: Sat, 26 Sep 2009 22:30:15 +0300 Subject: [PATCH 3/5] mac80211_hwsim: Fix initial beacon timer configuration mac80211_hwsim does not start transmitting Beacon frames when hostapd is started for the first time and restarting hostapd fixes this. The issue is caused by the config() handler not being able to start beacon_timer when beacon interval is not yet known and bss_info_changed() handler not starting the timer. This can be fixed by making the bss_info_changed() update the timer. Signed-off-by: Jouni Malinen Signed-off-by: John W. Linville --- drivers/net/wireless/mac80211_hwsim.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index 896f532182f0..38cfd79e0590 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -631,6 +631,9 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, data->beacon_int = 1024 * info->beacon_int / 1000 * HZ / 1000; if (WARN_ON(!data->beacon_int)) data->beacon_int = 1; + if (data->started) + mod_timer(&data->beacon_timer, + jiffies + data->beacon_int); } if (changed & BSS_CHANGED_ERP_CTS_PROT) { From 78bd6bbf3c12f49e2cb6897bfd73a62325ed3aaa Mon Sep 17 00:00:00 2001 From: Michal Szalata Date: Tue, 29 Sep 2009 15:37:53 +0200 Subject: [PATCH 4/5] rt2x00: Thrustmaster FunAccess WIFI USB and rt73usb Thrustmaster FunAccess WIFI USB works with rt73usb with little modification of rt73usb.c. Tested with version 2.3.0 of driver. Signed-off-by: Michal Szalata Signed-off-by: Ivo van Doorn Signed-off-by: John W. Linville --- drivers/net/wireless/rt2x00/rt73usb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c index 1cbd9b4a3efc..b8f5ee33445e 100644 --- a/drivers/net/wireless/rt2x00/rt73usb.c +++ b/drivers/net/wireless/rt2x00/rt73usb.c @@ -2381,6 +2381,7 @@ static struct usb_device_id rt73usb_device_table[] = { /* Huawei-3Com */ { USB_DEVICE(0x1472, 0x0009), USB_DEVICE_DATA(&rt73usb_ops) }, /* Hercules */ + { USB_DEVICE(0x06f8, 0xe002), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x06f8, 0xe010), USB_DEVICE_DATA(&rt73usb_ops) }, { USB_DEVICE(0x06f8, 0xe020), USB_DEVICE_DATA(&rt73usb_ops) }, /* Linksys */ From e16c1bb67a0010b5bad26ddc3e691655fd7456e3 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Tue, 29 Sep 2009 20:47:25 +0200 Subject: [PATCH 5/5] ar9170: fix bug in iq-auto calibration value calculation This patch fixes a embarrassing bug which was introduced by: "[PATCH] ar9170: implement frequency calibration for one-stage/openfw" The phy_data variable initialization has to done outside the for-loop scope. This is because the for-loop uses u32 phy_data variable more like a 4-byte field. But in each run only a single byte is calculated. Therefore phy_data content needs to stay the same for at least 3 more iterations, before the complete set can be uploaded. Reported-by: Andrew Morton Signed-off-by: Christian Lamparter Signed-off-by: John W. Linville --- drivers/net/wireless/ath/ar9170/phy.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/net/wireless/ath/ar9170/phy.c b/drivers/net/wireless/ath/ar9170/phy.c index b3e5cf3735b0..dbd488da18b1 100644 --- a/drivers/net/wireless/ath/ar9170/phy.c +++ b/drivers/net/wireless/ath/ar9170/phy.c @@ -1141,7 +1141,8 @@ static int ar9170_set_freq_cal_data(struct ar9170 *ar, u8 vpds[2][AR5416_PD_GAIN_ICEPTS]; u8 pwrs[2][AR5416_PD_GAIN_ICEPTS]; int chain, idx, i; - u8 f; + u32 phy_data = 0; + u8 f, tmp; switch (channel->band) { case IEEE80211_BAND_2GHZ: @@ -1208,9 +1209,6 @@ static int ar9170_set_freq_cal_data(struct ar9170 *ar, } for (i = 0; i < 76; i++) { - u32 phy_data; - u8 tmp; - if (i < 25) { tmp = ar9170_interpolate_val(i, &pwrs[0][0], &vpds[0][0]);