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

Helmut Schaa helmut.schaa at googlemail.com
Thu Jul 1 02:36:36 AEST 2010


Am Mittwoch 30 Juni 2010 schrieb Helmut Schaa:
> 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.

And btw. in the pre tbtt case the beacon is updated in hard irq context as
otherwise we would need a much larger delay. Even when using a tasklet it
can happen that the tasklet is executed in the next tick which can simply be
something around 10ms (CONFIG_HZ=100).

> 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)
> 





More information about the users mailing list