#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
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) {
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);
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);
__set_bit(DRIVER_SUPPORT_CONTROL_FILTERS, &rt2x00dev->flags);
__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.
*/
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,
* 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,
}
}
-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;
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)
{