aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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{