aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/rt2x00
diff options
context:
space:
mode:
authorHelmut Schaa <helmut.schaa@googlemail.com>2010-07-11 06:28:23 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-07-12 16:05:35 -0400
commit9f926fb57a2eb14d58ea6d6699544f9ccd0df8c7 (patch)
tree968fd46eea2a5691e1be0d2cca4ec6697d53d825 /drivers/net/wireless/rt2x00
parent07896fe2f4df3802a224a2ee1aad1c7345d2513c (diff)
rt2x00: Use pretbtt irq for fetching beacons on rt2800pci
Updating the beacon on pre tbtt instead of beacondone allows much lower latency in regard to TIM updates. Hence, use the pre tbtt interrupt for updating the beacon in rt2800pci (older devices don't provide a pre tbtt interrupt). Also, add a new driver flag to indicate if a driver has pre tbtt support or not and implement the according behavior in rt2x00lib. Signed-off-by: Helmut Schaa <helmut.schaa@googlemail.com> Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/rt2x00')
-rw-r--r--drivers/net/wireless/rt2x00/rt2800.h8
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c16
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c28
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c26
5 files changed, 70 insertions, 10 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index edd3734b8b32..dc93e14f7ab7 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -719,14 +719,20 @@
719#define TBTT_TIMER 0x1124 719#define TBTT_TIMER 0x1124
720 720
721/* 721/*
722 * INT_TIMER_CFG: 722 * INT_TIMER_CFG: timer configuration
723 * PRE_TBTT_TIMER: leadtime to tbtt for pretbtt interrupt in units of 1/16 TU
724 * GP_TIMER: period of general purpose timer in units of 1/16 TU
723 */ 725 */
724#define INT_TIMER_CFG 0x1128 726#define INT_TIMER_CFG 0x1128
727#define INT_TIMER_CFG_PRE_TBTT_TIMER FIELD32(0x0000ffff)
728#define INT_TIMER_CFG_GP_TIMER FIELD32(0xffff0000)
725 729
726/* 730/*
727 * INT_TIMER_EN: GP-timer and pre-tbtt Int enable 731 * INT_TIMER_EN: GP-timer and pre-tbtt Int enable
728 */ 732 */
729#define INT_TIMER_EN 0x112c 733#define INT_TIMER_EN 0x112c
734#define INT_TIMER_EN_PRE_TBTT_TIMER FIELD32(0x00000001)
735#define INT_TIMER_EN_GP_TIMER FIELD32(0x00000002)
730 736
731/* 737/*
732 * CH_IDLE_STA: channel idle time 738 * CH_IDLE_STA: channel idle time
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index afad3e1c1838..55727328e227 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -807,6 +807,15 @@ void rt2800_config_intf(struct rt2x00_dev *rt2x00dev, struct rt2x00_intf *intf,
807 rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 807 rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE,
808 (conf->sync == TSF_SYNC_BEACON)); 808 (conf->sync == TSF_SYNC_BEACON));
809 rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); 809 rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg);
810
811 /*
812 * Enable pre tbtt interrupt for beaconing modes
813 */
814 rt2800_register_read(rt2x00dev, INT_TIMER_EN, &reg);
815 rt2x00_set_field32(&reg, INT_TIMER_EN_PRE_TBTT_TIMER,
816 (conf->sync == TSF_SYNC_BEACON));
817 rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg);
818
810 } 819 }
811 820
812 if (flags & CONFIG_UPDATE_MAC) { 821 if (flags & CONFIG_UPDATE_MAC) {
@@ -1732,6 +1741,13 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev)
1732 rt2800_register_read(rt2x00dev, TX_STA_CNT1, &reg); 1741 rt2800_register_read(rt2x00dev, TX_STA_CNT1, &reg);
1733 rt2800_register_read(rt2x00dev, TX_STA_CNT2, &reg); 1742 rt2800_register_read(rt2x00dev, TX_STA_CNT2, &reg);
1734 1743
1744 /*
1745 * Setup leadtime for pre tbtt interrupt to 6ms
1746 */
1747 rt2800_register_read(rt2x00dev, INT_TIMER_CFG, &reg);
1748 rt2x00_set_field32(&reg, INT_TIMER_CFG_PRE_TBTT_TIMER, 6 << 4);
1749 rt2800_register_write(rt2x00dev, INT_TIMER_CFG, reg);
1750
1735 return 0; 1751 return 0;
1736} 1752}
1737EXPORT_SYMBOL_GPL(rt2800_init_registers); 1753EXPORT_SYMBOL_GPL(rt2800_init_registers);
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index f21b77c61ad4..c0c38f9705ae 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -938,20 +938,32 @@ static irqreturn_t rt2800pci_interrupt_thread(int irq, void *dev_instance)
938 u32 reg = rt2x00dev->irqvalue[0]; 938 u32 reg = rt2x00dev->irqvalue[0];
939 939
940 /* 940 /*
941 * 1 - Rx ring done interrupt. 941 * 1 - Pre TBTT interrupt.
942 */
943 if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT))
944 rt2x00lib_pretbtt(rt2x00dev);
945
946 /*
947 * 2 - Beacondone interrupt.
948 */
949 if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT))
950 rt2x00lib_beacondone(rt2x00dev);
951
952 /*
953 * 3 - Rx ring done interrupt.
942 */ 954 */
943 if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE)) 955 if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE))
944 rt2x00pci_rxdone(rt2x00dev); 956 rt2x00pci_rxdone(rt2x00dev);
945 957
958 /*
959 * 4 - Tx done interrupt.
960 */
946 if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) 961 if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS))
947 rt2800pci_txdone(rt2x00dev); 962 rt2800pci_txdone(rt2x00dev);
948 963
949 /* 964 /*
950 * Current beacon was sent out, fetch the next one 965 * 5 - Auto wakeup interrupt.
951 */ 966 */
952 if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT))
953 rt2x00lib_beacondone(rt2x00dev);
954
955 if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) 967 if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP))
956 rt2800pci_wakeup(rt2x00dev); 968 rt2800pci_wakeup(rt2x00dev);
957 969
@@ -1052,6 +1064,12 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
1052 __set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags); 1064 __set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags);
1053 1065
1054 /* 1066 /*
1067 * This device has a pre tbtt interrupt and thus fetches
1068 * a new beacon directly prior to transmission.
1069 */
1070 __set_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags);
1071
1072 /*
1055 * This device requires firmware. 1073 * This device requires firmware.
1056 */ 1074 */
1057 if (!rt2x00_is_soc(rt2x00dev)) 1075 if (!rt2x00_is_soc(rt2x00dev))
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 0fa21410676f..9dd0d171abf1 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -658,6 +658,7 @@ enum rt2x00_flags {
658 CONFIG_SUPPORT_HW_CRYPTO, 658 CONFIG_SUPPORT_HW_CRYPTO,
659 DRIVER_SUPPORT_CONTROL_FILTERS, 659 DRIVER_SUPPORT_CONTROL_FILTERS,
660 DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, 660 DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL,
661 DRIVER_SUPPORT_PRE_TBTT_INTERRUPT,
661 DRIVER_SUPPORT_LINK_TUNING, 662 DRIVER_SUPPORT_LINK_TUNING,
662 DRIVER_SUPPORT_WATCHDOG, 663 DRIVER_SUPPORT_WATCHDOG,
663 664
@@ -1071,6 +1072,7 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev,
1071 * Interrupt context handlers. 1072 * Interrupt context handlers.
1072 */ 1073 */
1073void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); 1074void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev);
1075void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev);
1074void rt2x00lib_txdone(struct queue_entry *entry, 1076void rt2x00lib_txdone(struct queue_entry *entry,
1075 struct txdone_entry_desc *txdesc); 1077 struct txdone_entry_desc *txdesc);
1076void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, 1078void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev,
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index ae0adff0b832..f59b9f7226a8 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -200,8 +200,8 @@ static void rt2x00lib_bc_buffer_iter(void *data, u8 *mac,
200 } 200 }
201} 201}
202 202
203static void rt2x00lib_beacondone_iter(void *data, u8 *mac, 203static void rt2x00lib_beaconupdate_iter(void *data, u8 *mac,
204 struct ieee80211_vif *vif) 204 struct ieee80211_vif *vif)
205{ 205{
206 struct rt2x00_dev *rt2x00dev = data; 206 struct rt2x00_dev *rt2x00dev = data;
207 207
@@ -223,15 +223,33 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev)
223 ieee80211_iterate_active_interfaces(rt2x00dev->hw, 223 ieee80211_iterate_active_interfaces(rt2x00dev->hw,
224 rt2x00lib_bc_buffer_iter, 224 rt2x00lib_bc_buffer_iter,
225 rt2x00dev); 225 rt2x00dev);
226 /*
227 * Devices with pre tbtt interrupt don't need to update the beacon
228 * here as they will fetch the next beacon directly prior to
229 * transmission.
230 */
231 if (test_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags))
232 return;
226 233
227 /* fetch next beacon */ 234 /* fetch next beacon */
228 ieee80211_iterate_active_interfaces(rt2x00dev->hw, 235 ieee80211_iterate_active_interfaces(rt2x00dev->hw,
229 rt2x00lib_beacondone_iter, 236 rt2x00lib_beaconupdate_iter,
230 rt2x00dev); 237 rt2x00dev);
231
232} 238}
233EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); 239EXPORT_SYMBOL_GPL(rt2x00lib_beacondone);
234 240
241void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev)
242{
243 if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
244 return;
245
246 /* fetch next beacon */
247 ieee80211_iterate_active_interfaces(rt2x00dev->hw,
248 rt2x00lib_beaconupdate_iter,
249 rt2x00dev);
250}
251EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt);
252
235void rt2x00lib_txdone(struct queue_entry *entry, 253void rt2x00lib_txdone(struct queue_entry *entry,
236 struct txdone_entry_desc *txdesc) 254 struct txdone_entry_desc *txdesc)
237{ 255{