[rt2x00-users] [PATCH 1/4] rt2x00: new beaconing interface for rt2x00pci
Helmut Schaa
helmut.schaa at googlemail.com
Wed Jun 30 16:29:50 UTC 2010
This patch adds a new beaconing interface for use in pci drivers. Differences
to the previous implementation in rt2x00lib are:
Buffered broadcast and multicast frames are sent out after DTIM beacons
in a tasklet to maintain low latency. Since USB devices are not able to
report when the beacon was sent out we just implement this for pci/soc
devices.
Allow drivers to make use of pre tbtt interrupts to update the beacon.
Introduce a new hw flag DRIVER_SUPPORT_PRE_TBTT_INTERRUPT to indicate if a
driver updates the beacon prior to the tbtt or now. If no pre_tbtt interrupt
is available we still stick to the set_tim callback to update the beacon
when the TIM changes.
Nevertheless, if a driver does not support pre tbtt interrupts the DTIM
count will be incorrect under some circumstances (DTIM period > 1). Devices
that support pre tbtt interrupts the beacon is updated directly prior to
transmission and thus does not need to update the beacon in set_tim anymore.
Resulting in a correct TIM and a correct DTIM count in the beacon.
Signed-off-by: Helmut Schaa <helmut.schaa at googlemail.com>
---
drivers/net/wireless/rt2x00/rt2x00.h | 6 +++
drivers/net/wireless/rt2x00/rt2x00mac.c | 8 +++
drivers/net/wireless/rt2x00/rt2x00pci.c | 69 +++++++++++++++++++++++++++++
drivers/net/wireless/rt2x00/rt2x00pci.h | 13 +++++
drivers/net/wireless/rt2x00/rt2x00queue.c | 1 +
5 files changed, 97 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 788b0e4..dffe80f 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -646,6 +646,7 @@ enum rt2x00_flags {
CONFIG_SUPPORT_HW_CRYPTO,
DRIVER_SUPPORT_CONTROL_FILTERS,
DRIVER_SUPPORT_CONTROL_FILTER_PSPOLL,
+ DRIVER_SUPPORT_PRE_TBTT_INTERRUPT,
/*
* Driver configuration
@@ -848,6 +849,11 @@ struct rt2x00_dev {
struct work_struct intf_work;
/*
+ * Tasklet to send out buffered bc/mc frames after DTIM
+ */
+ struct tasklet_struct bc_buffer_task;
+
+ /*
* Data queue arrays for RX, TX and Beacon.
* The Beacon array also contains the Atim queue
* if that is supported by the device.
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 3b838c0..9f09818 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -436,6 +436,14 @@ int rt2x00mac_set_tim(struct ieee80211_hw *hw, struct ieee80211_sta *sta,
{
struct rt2x00_dev *rt2x00dev = hw->priv;
+ /*
+ * 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 0;
+
rt2x00lib_beacondone(rt2x00dev);
return 0;
}
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.c b/drivers/net/wireless/rt2x00/rt2x00pci.c
index fc9da83..c73816b 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.c
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.c
@@ -31,6 +31,69 @@
#include "rt2x00.h"
#include "rt2x00pci.h"
+#include "rt2x00lib.h"
+
+/*
+ * TBTT handling
+ */
+
+static void rt2x00pci_bc_buffer_iter(void *data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct rt2x00_dev *rt2x00dev = data;
+ struct sk_buff *skb;
+
+ /*
+ * Send out buffered broad- and multicast frames
+ */
+ skb = ieee80211_get_buffered_bc(rt2x00dev->hw, vif);
+ while (skb) {
+ rt2x00mac_tx(rt2x00dev->hw, skb);
+ skb = ieee80211_get_buffered_bc(rt2x00dev->hw, vif);
+ }
+}
+
+static void rt2x00pci_send_bc_buffer(unsigned long data)
+{
+ struct rt2x00_dev *rt2x00dev = (void*) data;
+
+ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ return;
+
+ /* send buffered bc/mc frames out for every bssid */
+ ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
+ rt2x00pci_bc_buffer_iter,
+ rt2x00dev);
+}
+
+void rt2x00pci_beacondone(struct rt2x00_dev *rt2x00dev)
+{
+ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ return;
+
+ /* send buffered bc/mc traffic out asap */
+ tasklet_schedule(&rt2x00dev->bc_buffer_task);
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_beacondone);
+
+static void rt2x00pci_beacon_update_iter(void *data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct rt2x00_dev *rt2x00dev = data;
+ rt2x00queue_update_beacon(rt2x00dev, vif, true);
+}
+
+void rt2x00pci_pretbtt(struct rt2x00_dev *rt2x00dev)
+{
+ if (!test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
+ return;
+
+ /* update beacon for every bssid */
+ ieee80211_iterate_active_interfaces_atomic(rt2x00dev->hw,
+ rt2x00pci_beacon_update_iter,
+ rt2x00dev);
+}
+EXPORT_SYMBOL_GPL(rt2x00pci_pretbtt);
/*
* Register access.
@@ -151,6 +214,12 @@ int rt2x00pci_initialize(struct rt2x00_dev *rt2x00dev)
}
/*
+ * Initialize buffered bc tasklet.
+ */
+ tasklet_init(&rt2x00dev->bc_buffer_task, rt2x00pci_send_bc_buffer,
+ (unsigned long)rt2x00dev);
+
+ /*
* Register interrupt handler.
*/
status = request_irq(rt2x00dev->irq, rt2x00dev->ops->lib->irq_handler,
diff --git a/drivers/net/wireless/rt2x00/rt2x00pci.h b/drivers/net/wireless/rt2x00/rt2x00pci.h
index b854d62..8ef2e38 100644
--- a/drivers/net/wireless/rt2x00/rt2x00pci.h
+++ b/drivers/net/wireless/rt2x00/rt2x00pci.h
@@ -104,6 +104,19 @@ struct queue_entry_priv_pci {
*/
void rt2x00pci_rxdone(struct rt2x00_dev *rt2x00dev);
+/**
+ * rt2x00pci_rxdone - Handle beacon done events
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ */
+void rt2x00pci_beacondone(struct rt2x00_dev *rt2x00dev);
+
+
+/**
+ * rt2x00pci_rxdone - Handle pre tbtt events
+ * @rt2x00dev: Device pointer, see &struct rt2x00_dev.
+ */
+void rt2x00pci_pretbtt(struct rt2x00_dev *rt2x00dev);
+
/*
* Device initialization handlers.
*/
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index 5097fe0..0580783 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -624,6 +624,7 @@ int rt2x00queue_update_beacon(struct rt2x00_dev *rt2x00dev,
return 0;
}
+EXPORT_SYMBOL_GPL(rt2x00queue_update_beacon);
struct data_queue *rt2x00queue_get_queue(struct rt2x00_dev *rt2x00dev,
const enum data_queue_qid queue)
--
1.6.4.2
More information about the users
mailing list