All of lore.kernel.org
 help / color / mirror / Atom feed
* [RFC PATCHv2 0/1] mac80211: Shared BT/WLAN antenna co-existence management
@ 2010-05-31  7:05 Juuso Oikarinen
  2010-05-31  7:05 ` [RFC PATCHv2 1/1] mac80211: Add interface for driver to temporarily disable dynamic ps Juuso Oikarinen
  0 siblings, 1 reply; 4+ messages in thread
From: Juuso Oikarinen @ 2010-05-31  7:05 UTC (permalink / raw)
  To: linux-wireless

v2 of these RFC patches only add more elaboration to the description of the
patch itself.

The following patch proposes an implementation to handle WLAN-Bluetooth
coexistence in the case of a shared WLAN/BT antenna.

The patch adds to mac80211 an interface for the driver to be able to
temporarily disable dynamic power save. When power save is enabled, a call to
the function will cause mac80211 to immediately enter full PSM until the driver
indicates that dynamic PSM can be resumed. If power save is enabled the 
function does nothing.

The driver uses this function to disable dynamic PSM whenever there are bursts
Bluetooth traffic. Full PSM allows the WLAN hardware to relinquish the antenna
for use by BT during the inactive WLAN periods.

The driver gets information on Bluetooth traffic from the WLAN chipset. The
chipset has hardware lines to coordinate the co-existence, and the chipset will
indicate to the driver whenever there is Bluetooth traffic.

Comments are welcomed!

Juuso Oikarinen (1):
  mac80211: Add interface for driver to temporarily disable dynamic ps

 include/net/mac80211.h     |   15 +++++++++++++++
 net/mac80211/ieee80211_i.h |    3 +++
 net/mac80211/iface.c       |    1 +
 net/mac80211/mlme.c        |   20 +++++++++++++++++++-
 net/mac80211/rx.c          |    3 ++-
 net/mac80211/tx.c          |    4 ++++
 6 files changed, 44 insertions(+), 2 deletions(-)


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [RFC PATCHv2 1/1] mac80211: Add interface for driver to temporarily disable dynamic ps
  2010-05-31  7:05 [RFC PATCHv2 0/1] mac80211: Shared BT/WLAN antenna co-existence management Juuso Oikarinen
@ 2010-05-31  7:05 ` Juuso Oikarinen
  2010-06-01  8:00   ` Johannes Berg
  0 siblings, 1 reply; 4+ messages in thread
From: Juuso Oikarinen @ 2010-05-31  7:05 UTC (permalink / raw)
  To: linux-wireless

This mechanism introduced in this patch applies (at least) for hardware
designs using a single shared antenna for both WLAN and BT. In these designs,
the antenna must be toggled between WLAN and BT.

In those hardware, managing WLAN co-existence with Bluetooth requires WLAN
full power save whenever there is Bluetooth activity in order for WLAN to be
able to periodically relinquish the antenna to be used for BT. This is because
BT can only access the shared antenna when WLAN is idle or asleep.

Some hardware, for instance the wl1271, are able to indicate to the host
whenever there is BT traffic. In essence, the hardware will send an indication
to the host whenever there is, for example, SCO traffic or A2DP traffic, and
will send another indication when the traffic is over.

The hardware gets information of Bluetooth traffic via hardware co-existence
control lines - these lines are used to negotiate the shared antenna
ownership. The hardware will give the antenna to BT whenever WLAN is sleeping.

This patch adds the interface to mac80211 to facilitate temporarily disabling
of dynamic power save as per request of the WLAN driver. This interface will
immediately force WLAN to full powersave, hence allowing BT coexistence as
described above.

In these kind of shared antenna desings, when WLAN powersave is fully disabled,
Bluetooth will not work simultaneously with WLAN at all. This patch does not
address that problem. This interface will not change PSM state, so if PSM is
disabled it will remain so. Solving this problem requires knowledge about BT
state, and is best done in user-space.

Signed-off-by: Juuso Oikarinen <juuso.oikarinen@nokia.com>
---
 include/net/mac80211.h     |   15 +++++++++++++++
 net/mac80211/ieee80211_i.h |    3 +++
 net/mac80211/iface.c       |    1 +
 net/mac80211/mlme.c        |   20 +++++++++++++++++++-
 net/mac80211/rx.c          |    3 ++-
 net/mac80211/tx.c          |    4 ++++
 6 files changed, 44 insertions(+), 2 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index de22cbf..e4a97ea 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2460,6 +2460,21 @@ void ieee80211_beacon_loss(struct ieee80211_vif *vif);
 void ieee80211_connection_loss(struct ieee80211_vif *vif);
 
 /**
+ * ieee80211_disable_dyn_ps - force mac80211 to temporarily disable dynamic psm
+ *
+ * @vif: &struct ieee80211_vif pointer from the add_interface callback.
+ *
+ * Some hardware require full power save to manage simultaneous BT traffic
+ * on the WLAN frequency. Full PSM is required periodically, whenever there are
+ * burst of BT traffic. The hardware gets information of BT traffic via
+ * hardware co-existence lines, and consequentially requests mac80211 to
+ * (temporarily) enter full psm.
+ * This function will only temporarily disable dynamic PS, not enable PSM if
+ * it was not already enabled.
+ */
+void ieee80211_disable_dyn_ps(struct ieee80211_vif *vif, bool disable);
+
+/**
  * ieee80211_cqm_rssi_notify - inform a configured connection quality monitoring
  *	rssi threshold triggered
  *
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 1a9e2da..cab32c7 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -505,6 +505,9 @@ struct ieee80211_sub_if_data {
 	 */
 	bool ht_opmode_valid;
 
+	/* dynamic powersave temporarily disabled by driver */
+	bool disable_dyn_ps;
+
 	/* Fragment table for host-based reassembly */
 	struct ieee80211_fragment_entry	fragments[IEEE80211_FRAGMENT_MAX];
 	unsigned int fragment_next;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 50deb01..ac2b8a5 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -421,6 +421,7 @@ static int ieee80211_stop(struct net_device *dev)
 
 	del_timer_sync(&local->dynamic_ps_timer);
 	cancel_work_sync(&local->dynamic_ps_enable_work);
+	sdata->disable_dyn_ps = false;
 
 	/* APs need special treatment */
 	if (sdata->vif.type == NL80211_IFTYPE_AP) {
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 0839c4e..aaa86ee 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -478,6 +478,24 @@ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
 	}
 }
 
+void ieee80211_disable_dyn_ps(struct ieee80211_vif *vif, bool disable)
+{
+	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+	struct ieee80211_local *local = sdata->local;
+
+	WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION);
+
+	sdata->disable_dyn_ps = disable;
+
+	/* immediately go to psm */
+	if (disable && timer_pending(&local->dynamic_ps_timer)) {
+		ieee80211_queue_work(&local->hw,
+				     &local->dynamic_ps_enable_work);
+		del_timer_sync(&local->dynamic_ps_timer);
+	}
+}
+EXPORT_SYMBOL(ieee80211_disable_dyn_ps);
+
 /* powersave */
 static void ieee80211_enable_ps(struct ieee80211_local *local,
 				struct ieee80211_sub_if_data *sdata)
@@ -491,7 +509,7 @@ static void ieee80211_enable_ps(struct ieee80211_local *local,
 	if (local->scanning)
 		return;
 
-	if (conf->dynamic_ps_timeout > 0 &&
+	if (conf->dynamic_ps_timeout > 0 && !sdata->disable_dyn_ps &&
 	    !(local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)) {
 		mod_timer(&local->dynamic_ps_timer, jiffies +
 			  msecs_to_jiffies(conf->dynamic_ps_timeout));
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 6e2a7bc..e11d52b 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -1793,7 +1793,8 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
 
 	if (ieee80211_is_data(hdr->frame_control) &&
 	    !is_multicast_ether_addr(hdr->addr1) &&
-	    local->hw.conf.dynamic_ps_timeout > 0 && local->ps_sdata) {
+	    local->hw.conf.dynamic_ps_timeout > 0 && !sdata->disable_dyn_ps &&
+	    local->ps_sdata) {
 			mod_timer(&local->dynamic_ps_timer, jiffies +
 			 msecs_to_jiffies(local->hw.conf.dynamic_ps_timeout));
 	}
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index 680bcb7..6f6b046 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -194,6 +194,10 @@ ieee80211_tx_h_dynamic_ps(struct ieee80211_tx_data *tx)
 	if (local->hw.flags & IEEE80211_HW_SUPPORTS_DYNAMIC_PS)
 		return TX_CONTINUE;
 
+	/* dynamic PS has not been temporarily disabled by driver */
+	if (tx->sdata->disable_dyn_ps)
+		return TX_CONTINUE;
+
 	/* dynamic power save disabled */
 	if (local->hw.conf.dynamic_ps_timeout <= 0)
 		return TX_CONTINUE;
-- 
1.6.3.3


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [RFC PATCHv2 1/1] mac80211: Add interface for driver to temporarily disable dynamic ps
  2010-05-31  7:05 ` [RFC PATCHv2 1/1] mac80211: Add interface for driver to temporarily disable dynamic ps Juuso Oikarinen
@ 2010-06-01  8:00   ` Johannes Berg
  2010-06-01  9:07     ` Juuso Oikarinen
  0 siblings, 1 reply; 4+ messages in thread
From: Johannes Berg @ 2010-06-01  8:00 UTC (permalink / raw)
  To: Juuso Oikarinen; +Cc: linux-wireless

On Mon, 2010-05-31 at 10:05 +0300, Juuso Oikarinen wrote:

>  /**
> + * ieee80211_disable_dyn_ps - force mac80211 to temporarily disable dynamic psm
> + *
> + * @vif: &struct ieee80211_vif pointer from the add_interface callback.

* @disable: ...

The name is also a bit odd since you can re-enable it, but I can't think
of a better name either.

> --- a/net/mac80211/mlme.c
> +++ b/net/mac80211/mlme.c
> @@ -478,6 +478,24 @@ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
>  	}
>  }
>  
> +void ieee80211_disable_dyn_ps(struct ieee80211_vif *vif, bool disable)
> +{
> +	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
> +	struct ieee80211_local *local = sdata->local;
> +
> +	WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION);
> +
> +	sdata->disable_dyn_ps = disable;
> +
> +	/* immediately go to psm */
> +	if (disable && timer_pending(&local->dynamic_ps_timer)) {
> +		ieee80211_queue_work(&local->hw,
> +				     &local->dynamic_ps_enable_work);
> +		del_timer_sync(&local->dynamic_ps_timer);
> +	}
> +}

The timer trickery seems weird, why not just queue the work and ignore
the timer?

> -	if (conf->dynamic_ps_timeout > 0 &&
> +	if (conf->dynamic_ps_timeout > 0 && !sdata->disable_dyn_ps &&

As we just discussed on IRC, it might be worthwhile to adjust
dynamic_ps_timeout to 0 instead in this case, so this and the RX and TX
paths need not be touched.

johannes


^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [RFC PATCHv2 1/1] mac80211: Add interface for driver to temporarily disable dynamic ps
  2010-06-01  8:00   ` Johannes Berg
@ 2010-06-01  9:07     ` Juuso Oikarinen
  0 siblings, 0 replies; 4+ messages in thread
From: Juuso Oikarinen @ 2010-06-01  9:07 UTC (permalink / raw)
  To: ext Johannes Berg; +Cc: linux-wireless

On Tue, 2010-06-01 at 10:00 +0200, ext Johannes Berg wrote:
> On Mon, 2010-05-31 at 10:05 +0300, Juuso Oikarinen wrote:
> 
> >  /**
> > + * ieee80211_disable_dyn_ps - force mac80211 to temporarily disable dynamic psm
> > + *
> > + * @vif: &struct ieee80211_vif pointer from the add_interface callback.
> 
> * @disable: ...
> 
> The name is also a bit odd since you can re-enable it, but I can't think
> of a better name either.

I'll try to come up with a better name. If I cannot, I'll leave it as it
is.

> > --- a/net/mac80211/mlme.c
> > +++ b/net/mac80211/mlme.c
> > @@ -478,6 +478,24 @@ static void ieee80211_handle_pwr_constr(struct ieee80211_sub_if_data *sdata,
> >  	}
> >  }
> >  
> > +void ieee80211_disable_dyn_ps(struct ieee80211_vif *vif, bool disable)
> > +{
> > +	struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
> > +	struct ieee80211_local *local = sdata->local;
> > +
> > +	WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION);
> > +
> > +	sdata->disable_dyn_ps = disable;
> > +
> > +	/* immediately go to psm */
> > +	if (disable && timer_pending(&local->dynamic_ps_timer)) {
> > +		ieee80211_queue_work(&local->hw,
> > +				     &local->dynamic_ps_enable_work);
> > +		del_timer_sync(&local->dynamic_ps_timer);
> > +	}
> > +}
> 
> The timer trickery seems weird, why not just queue the work and ignore
> the timer?

It's there for the obvious reason - it just saves an extra execution of
the dynamic_ps_enable_work. That said, maybe the saving is not worth the
added complexity.

> > -	if (conf->dynamic_ps_timeout > 0 &&
> > +	if (conf->dynamic_ps_timeout > 0 && !sdata->disable_dyn_ps &&
> 
> As we just discussed on IRC, it might be worthwhile to adjust
> dynamic_ps_timeout to 0 instead in this case, so this and the RX and TX
> paths need not be touched.

Yes, as we discussed I'll change this to adjusting the
dynamic_ps_timeout to zero, and using a separate variable to track the
actual value of the timer.

-Juuso

> johannes
> 



^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2010-06-01  9:04 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-05-31  7:05 [RFC PATCHv2 0/1] mac80211: Shared BT/WLAN antenna co-existence management Juuso Oikarinen
2010-05-31  7:05 ` [RFC PATCHv2 1/1] mac80211: Add interface for driver to temporarily disable dynamic ps Juuso Oikarinen
2010-06-01  8:00   ` Johannes Berg
2010-06-01  9:07     ` Juuso Oikarinen

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.