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 @@ #define TBTT_TIMER 0x1124 /* - * INT_TIMER_CFG: + * INT_TIMER_CFG: timer configuration + * PRE_TBTT_TIMER: leadtime to tbtt for pretbtt interrupt in units of 1/16 TU + * GP_TIMER: period of general purpose timer in units of 1/16 TU */ #define INT_TIMER_CFG 0x1128 +#define INT_TIMER_CFG_PRE_TBTT_TIMER FIELD32(0x0000ffff) +#define INT_TIMER_CFG_GP_TIMER FIELD32(0xffff0000) /* * INT_TIMER_EN: GP-timer and pre-tbtt Int enable */ #define INT_TIMER_EN 0x112c +#define INT_TIMER_EN_PRE_TBTT_TIMER FIELD32(0x00000001) +#define INT_TIMER_EN_GP_TIMER FIELD32(0x00000002) /* * 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, rt2x00_set_field32(®, BCN_TIME_CFG_TBTT_ENABLE, (conf->sync == TSF_SYNC_BEACON)); rt2800_register_write(rt2x00dev, BCN_TIME_CFG, reg); + + /* + * Enable pre tbtt interrupt for beaconing modes + */ + rt2800_register_read(rt2x00dev, INT_TIMER_EN, ®); + rt2x00_set_field32(®, INT_TIMER_EN_PRE_TBTT_TIMER, + (conf->sync == TSF_SYNC_BEACON)); + rt2800_register_write(rt2x00dev, INT_TIMER_EN, reg); + } if (flags & CONFIG_UPDATE_MAC) { @@ -1732,6 +1741,13 @@ int rt2800_init_registers(struct rt2x00_dev *rt2x00dev) rt2800_register_read(rt2x00dev, TX_STA_CNT1, ®); rt2800_register_read(rt2x00dev, TX_STA_CNT2, ®); + /* + * Setup leadtime for pre tbtt interrupt to 6ms + */ + rt2800_register_read(rt2x00dev, INT_TIMER_CFG, ®); + rt2x00_set_field32(®, INT_TIMER_CFG_PRE_TBTT_TIMER, 6 << 4); + rt2800_register_write(rt2x00dev, INT_TIMER_CFG, reg); + return 0; } 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) u32 reg = rt2x00dev->irqvalue[0]; /* - * 1 - Rx ring done interrupt. + * 1 - Pre TBTT interrupt. + */ + if (rt2x00_get_field32(reg, INT_SOURCE_CSR_PRE_TBTT)) + rt2x00lib_pretbtt(rt2x00dev); + + /* + * 2 - Beacondone interrupt. + */ + if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT)) + rt2x00lib_beacondone(rt2x00dev); + + /* + * 3 - Rx ring done interrupt. */ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_RX_DONE)) rt2x00pci_rxdone(rt2x00dev); + /* + * 4 - Tx done interrupt. + */ if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TX_FIFO_STATUS)) rt2800pci_txdone(rt2x00dev); /* - * Current beacon was sent out, fetch the next one + * 5 - Auto wakeup interrupt. */ - if (rt2x00_get_field32(reg, INT_SOURCE_CSR_TBTT)) - rt2x00lib_beacondone(rt2x00dev); - if (rt2x00_get_field32(reg, INT_SOURCE_CSR_AUTO_WAKEUP)) rt2800pci_wakeup(rt2x00dev); @@ -1052,6 +1064,12 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev) __set_bit(DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, &rt2x00dev->flags); /* + * This device has a pre tbtt interrupt and thus fetches + * a new beacon directly prior to transmission. + */ + __set_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags); + + /* * This device requires firmware. */ 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 { CONFIG_SUPPORT_HW_CRYPTO, DRIVER_SUPPORT_CONTROL_FILTERS, DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL, + DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, DRIVER_SUPPORT_LINK_TUNING, DRIVER_SUPPORT_WATCHDOG, @@ -1071,6 +1072,7 @@ static inline void rt2x00debug_dump_frame(struct rt2x00_dev *rt2x00dev, * Interrupt context handlers. */ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev); +void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev); void rt2x00lib_txdone(struct queue_entry *entry, struct txdone_entry_desc *txdesc); 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, } } -static void rt2x00lib_beacondone_iter(void *data, u8 *mac, - struct ieee80211_vif *vif) +static void rt2x00lib_beaconupdate_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) { struct rt2x00_dev *rt2x00dev = data; @@ -223,15 +223,33 @@ void rt2x00lib_beacondone(struct rt2x00_dev *rt2x00dev) ieee80211_iterate_active_interfaces(rt2x00dev->hw, rt2x00lib_bc_buffer_iter, rt2x00dev); + /* + * Devices with pre tbtt interrupt don't need to update the beacon + * here as they will fetch the next beacon directly prior to + * transmission. + */ + if (test_bit(DRIVER_SUPPORT_PRE_TBTT_INTERRUPT, &rt2x00dev->flags)) + return; /* fetch next beacon */ ieee80211_iterate_active_interfaces(rt2x00dev->hw, - rt2x00lib_beacondone_iter, + rt2x00lib_beaconupdate_iter, rt2x00dev); - } EXPORT_SYMBOL_GPL(rt2x00lib_beacondone); +void rt2x00lib_pretbtt(struct rt2x00_dev *rt2x00dev) +{ + if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) + return; + + /* fetch next beacon */ + ieee80211_iterate_active_interfaces(rt2x00dev->hw, + rt2x00lib_beaconupdate_iter, + rt2x00dev); +} +EXPORT_SYMBOL_GPL(rt2x00lib_pretbtt); + void rt2x00lib_txdone(struct queue_entry *entry, struct txdone_entry_desc *txdesc) { |