[rt2x00-users] [PATCH 1/4] rt2x00: new beaconing interface for rt2x00pci

Helmut Schaa helmut.schaa at googlemail.com
Thu Jul 1 02:29:50 AEST 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