aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHelmut Schaa <helmut.schaa@googlemail.com>2012-03-09 09:31:50 -0500
committerJohn W. Linville <linville@tuxdriver.com>2012-03-12 14:21:49 -0400
commit290d60891eb659e52204ec209e08cc0cabc5b99f (patch)
treefcca74bae4b2431424bcb49f5d57bf01fa1bad13
parente9219779f943dfa1010ccbb63de14d49a47c43ee (diff)
rt2x00: Fix beacon skew in rt2800pci
rt2800pci is suffering from beacon skew in AP mode. Some powersaving clients (like VOIP phones) are getting into trouble after some time when the beacon skew is getting too big. The ralink legacy drivers contain a function that indicates that the beacon timer is off by 1us per tbtt. And this function works around that by reducing the beacon interval for every 64th beacon transmission by 64us (the smallest possible value). Do the same in rt2800pci. This allows proper powersaving when rt2800pci is used in AP mode. Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--drivers/net/wireless/rt2x00/rt2800.h7
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c26
2 files changed, 33 insertions, 0 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index e5c05d8c7448..063bfa8b91f4 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -2475,6 +2475,12 @@ struct mac_iveiv_entry {
2475#define EIRP_MAX_TX_POWER_LIMIT 0x50 2475#define EIRP_MAX_TX_POWER_LIMIT 0x50
2476 2476
2477/* 2477/*
2478 * Number of TBTT intervals after which we have to adjust
2479 * the hw beacon timer.
2480 */
2481#define BCN_TBTT_OFFSET 64
2482
2483/*
2478 * RT2800 driver data structure 2484 * RT2800 driver data structure
2479 */ 2485 */
2480struct rt2800_drv_data { 2486struct rt2800_drv_data {
@@ -2484,6 +2490,7 @@ struct rt2800_drv_data {
2484 u8 bbp26; 2490 u8 bbp26;
2485 u8 txmixer_gain_24g; 2491 u8 txmixer_gain_24g;
2486 u8 txmixer_gain_5g; 2492 u8 txmixer_gain_5g;
2493 unsigned int tbtt_tick;
2487}; 2494};
2488 2495
2489#endif /* RT2800_H */ 2496#endif /* RT2800_H */
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 9375db455456..0397bbf0ce01 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -809,7 +809,33 @@ static void rt2800pci_pretbtt_tasklet(unsigned long data)
809static void rt2800pci_tbtt_tasklet(unsigned long data) 809static void rt2800pci_tbtt_tasklet(unsigned long data)
810{ 810{
811 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; 811 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
812 struct rt2800_drv_data *drv_data = rt2x00dev->drv_data;
813 u32 reg;
814
812 rt2x00lib_beacondone(rt2x00dev); 815 rt2x00lib_beacondone(rt2x00dev);
816
817 if (rt2x00dev->intf_ap_count) {
818 /*
819 * The rt2800pci hardware tbtt timer is off by 1us per tbtt
820 * causing beacon skew and as a result causing problems with
821 * some powersaving clients over time. Shorten the beacon
822 * interval every 64 beacons by 64us to mitigate this effect.
823 */
824 if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 2)) {
825 rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
826 rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
827 (rt2x00dev->beacon_int * 16) - 1);
828 rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
829 } else if (drv_data->tbtt_tick == (BCN_TBTT_OFFSET - 1)) {
830 rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
831 rt2x00_set_field32(&reg, BCN_TIME_CFG_BEACON_INTERVAL,
832 (rt2x00dev->beacon_int * 16));
833 rt2x00pci_register_write(rt2x00dev, BCN_TIME_CFG, reg);
834 }
835 drv_data->tbtt_tick++;
836 drv_data->tbtt_tick %= BCN_TBTT_OFFSET;
837 }
838
813 if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) 839 if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
814 rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT); 840 rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT);
815} 841}