diff options
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800.h | 8 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.c | 16 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800pci.c | 28 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2x00dev.c | 26 |
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(®, BCN_TIME_CFG_TBTT_ENABLE, | 807 | rt2x00_set_field32(®, 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, ®); | ||
815 | rt2x00_set_field32(®, 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, ®); | 1741 | rt2800_register_read(rt2x00dev, TX_STA_CNT1, ®); |
1733 | rt2800_register_read(rt2x00dev, TX_STA_CNT2, ®); | 1742 | rt2800_register_read(rt2x00dev, TX_STA_CNT2, ®); |
1734 | 1743 | ||
1744 | /* | ||
1745 | * Setup leadtime for pre tbtt interrupt to 6ms | ||
1746 | */ | ||
1747 | rt2800_register_read(rt2x00dev, INT_TIMER_CFG, ®); | ||
1748 | rt2x00_set_field32(®, 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 | } |
1737 | EXPORT_SYMBOL_GPL(rt2800_init_registers); | 1753 | EXPORT_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 | */ |
1073 | void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); | 1074 | void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); |
1075 | void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev); | ||
1074 | void rt2x00lib_txdone(struct queue_entry *entry, | 1076 | void rt2x00lib_txdone(struct queue_entry *entry, |
1075 | struct txdone_entry_desc *txdesc); | 1077 | struct txdone_entry_desc *txdesc); |
1076 | void rt2x00lib_rxdone(struct rt2x00_dev *rt2x00dev, | 1078 | void 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 | ||
203 | static void rt2x00lib_beacondone_iter(void *data, u8 *mac, | 203 | static 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 | } |
233 | EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); | 239 | EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); |
234 | 240 | ||
241 | void 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 | } | ||
251 | EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt); | ||
252 | |||
235 | void rt2x00lib_txdone(struct queue_entry *entry, | 253 | void rt2x00lib_txdone(struct queue_entry *entry, |
236 | struct txdone_entry_desc *txdesc) | 254 | struct txdone_entry_desc *txdesc) |
237 | { | 255 | { |