linux-wireless.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/2] wl1251: Prepare for idle mode support
@ 2011-03-31 13:04 Jarkko Nikula
  2011-04-01 19:22 ` Kalle Valo
  0 siblings, 1 reply; 7+ messages in thread
From: Jarkko Nikula @ 2011-03-31 13:04 UTC (permalink / raw)
  To: linux-wireless; +Cc: John W. Linville, Kalle Valo, Jarkko Nikula

RFC for WL1251 idle mode support brought a few issues that are worth to
update before adding the idle mode support.

Since the idle mode can reuse the code that is now used in Power Save Mode
(PSM), the flag psm in struct wl1251 is changed to variable station_mode
to be able to distinguish between PSM and idle modes.
Confusing comment about psm and elp relation is removed since the PSM is
actually activated by putting the chip into Entreme Low Power (ELP) mode.

Then enum wl1251_cmd_ps_mod in cmd.h is renamed and moved to wl1251.h as it
is a state rather than chip level command.

Signed-off-by: Jarkko Nikula <jhnikula@gmail.com>
---
RFC for WL1251 idle mode:
http://marc.info/?l=linux-wireless&m=130140818011186&w=2
---
 drivers/net/wireless/wl1251/cmd.h    |    5 -----
 drivers/net/wireless/wl1251/event.c  |    6 ++++--
 drivers/net/wireless/wl1251/main.c   |    6 +++---
 drivers/net/wireless/wl1251/ps.c     |   10 ++++------
 drivers/net/wireless/wl1251/ps.h     |    2 +-
 drivers/net/wireless/wl1251/wl1251.h |    8 ++++++--
 6 files changed, 18 insertions(+), 19 deletions(-)

diff --git a/drivers/net/wireless/wl1251/cmd.h b/drivers/net/wireless/wl1251/cmd.h
index e5c74c6..669d5bc 100644
--- a/drivers/net/wireless/wl1251/cmd.h
+++ b/drivers/net/wireless/wl1251/cmd.h
@@ -312,11 +312,6 @@ struct wl1251_cmd_vbm_update {
 	struct wl1251_tim tim;
 } __packed;
 
-enum wl1251_cmd_ps_mode {
-	STATION_ACTIVE_MODE,
-	STATION_POWER_SAVE_MODE
-};
-
 struct wl1251_cmd_ps_params {
 	struct wl1251_cmd_header header;
 
diff --git a/drivers/net/wireless/wl1251/event.c b/drivers/net/wireless/wl1251/event.c
index dfc4579..9f15cca 100644
--- a/drivers/net/wireless/wl1251/event.c
+++ b/drivers/net/wireless/wl1251/event.c
@@ -68,14 +68,16 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
 	if (vector & BSS_LOSE_EVENT_ID) {
 		wl1251_debug(DEBUG_EVENT, "BSS_LOSE_EVENT");
 
-		if (wl->psm_requested && wl->psm) {
+		if (wl->psm_requested &&
+		    wl->station_mode != STATION_ACTIVE_MODE) {
 			ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE);
 			if (ret < 0)
 				return ret;
 		}
 	}
 
-	if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID && wl->psm) {
+	if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID &&
+	    wl->station_mode != STATION_ACTIVE_MODE) {
 		wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT");
 
 		/* indicate to the stack, that beacons have been lost */
diff --git a/drivers/net/wireless/wl1251/main.c b/drivers/net/wireless/wl1251/main.c
index 12c9e63..04a0549 100644
--- a/drivers/net/wireless/wl1251/main.c
+++ b/drivers/net/wireless/wl1251/main.c
@@ -497,7 +497,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
 	wl->rx_last_id = 0;
 	wl->next_tx_complete = 0;
 	wl->elp = false;
-	wl->psm = 0;
+	wl->station_mode = STATION_ACTIVE_MODE;
 	wl->tx_queue_stopped = false;
 	wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
 	wl->rssi_thold = 0;
@@ -632,7 +632,7 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
 
 		wl->psm_requested = false;
 
-		if (wl->psm) {
+		if (wl->station_mode != STATION_ACTIVE_MODE) {
 			ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE);
 			if (ret < 0)
 				goto out_sleep;
@@ -1384,7 +1384,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void)
 	wl->rx_config = WL1251_DEFAULT_RX_CONFIG;
 	wl->rx_filter = WL1251_DEFAULT_RX_FILTER;
 	wl->elp = false;
-	wl->psm = 0;
+	wl->station_mode = STATION_ACTIVE_MODE;
 	wl->psm_requested = false;
 	wl->tx_queue_stopped = false;
 	wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
diff --git a/drivers/net/wireless/wl1251/ps.c b/drivers/net/wireless/wl1251/ps.c
index 9cc5147..5485f03 100644
--- a/drivers/net/wireless/wl1251/ps.c
+++ b/drivers/net/wireless/wl1251/ps.c
@@ -39,7 +39,7 @@ void wl1251_elp_work(struct work_struct *work)
 
 	mutex_lock(&wl->mutex);
 
-	if (wl->elp || !wl->psm)
+	if (wl->elp || wl->station_mode == STATION_ACTIVE_MODE)
 		goto out;
 
 	wl1251_debug(DEBUG_PSM, "chip to elp");
@@ -57,7 +57,7 @@ void wl1251_ps_elp_sleep(struct wl1251 *wl)
 {
 	unsigned long delay;
 
-	if (wl->psm) {
+	if (wl->station_mode != STATION_ACTIVE_MODE) {
 		delay = msecs_to_jiffies(ELP_ENTRY_DELAY);
 		ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, delay);
 	}
@@ -104,7 +104,7 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl)
 	return 0;
 }
 
-int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode)
+int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_station_mode mode)
 {
 	int ret;
 
@@ -135,8 +135,6 @@ int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode)
 		ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_ELP);
 		if (ret < 0)
 			return ret;
-
-		wl->psm = 1;
 		break;
 	case STATION_ACTIVE_MODE:
 	default:
@@ -167,9 +165,9 @@ int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode)
 		if (ret < 0)
 			return ret;
 
-		wl->psm = 0;
 		break;
 	}
+	wl->station_mode = mode;
 
 	return ret;
 }
diff --git a/drivers/net/wireless/wl1251/ps.h b/drivers/net/wireless/wl1251/ps.h
index 55c3dda..75efad2 100644
--- a/drivers/net/wireless/wl1251/ps.h
+++ b/drivers/net/wireless/wl1251/ps.h
@@ -26,7 +26,7 @@
 #include "wl1251.h"
 #include "acx.h"
 
-int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode);
+int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_station_mode mode);
 void wl1251_ps_elp_sleep(struct wl1251 *wl);
 int wl1251_ps_elp_wakeup(struct wl1251 *wl);
 void wl1251_elp_work(struct work_struct *work);
diff --git a/drivers/net/wireless/wl1251/wl1251.h b/drivers/net/wireless/wl1251/wl1251.h
index bb23cd5..bf245a8 100644
--- a/drivers/net/wireless/wl1251/wl1251.h
+++ b/drivers/net/wireless/wl1251/wl1251.h
@@ -129,6 +129,11 @@ enum wl1251_partition_type {
 	PART_TABLE_LEN
 };
 
+enum wl1251_station_mode {
+	STATION_ACTIVE_MODE,
+	STATION_POWER_SAVE_MODE,
+};
+
 struct wl1251_partition {
 	u32 size;
 	u32 start;
@@ -358,8 +363,7 @@ struct wl1251 {
 
 	struct delayed_work elp_work;
 
-	/* we can be in psm, but not in elp, we have to differentiate */
-	bool psm;
+	enum wl1251_station_mode station_mode;
 
 	/* PSM mode requested */
 	bool psm_requested;
-- 
1.7.0.4


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

* Re: [PATCH 1/2] wl1251: Prepare for idle mode support
  2011-03-31 13:04 Jarkko Nikula
@ 2011-04-01 19:22 ` Kalle Valo
  2011-04-04  6:49   ` Jarkko Nikula
  0 siblings, 1 reply; 7+ messages in thread
From: Kalle Valo @ 2011-04-01 19:22 UTC (permalink / raw)
  To: Jarkko Nikula; +Cc: linux-wireless, John W. Linville

Jarkko Nikula <jhnikula@gmail.com> writes:

> RFC for WL1251 idle mode support brought a few issues that are worth to
> update before adding the idle mode support.
>

[...]

> Then enum wl1251_cmd_ps_mod in cmd.h is renamed and moved to wl1251.h as it
> is a state rather than chip level command.

But now you are moving a firmware interface value outside cmd.h. I was
thinking that you would touch wl1251_cmd_ps_mod at all, instead just
create a new enum wl1251_station_mode which will be used as the driver
state variable.

That way it's clear which enum is for the firmware interface and which
one is an internal variable.

To make it even more clear we could change the function to this:

int wl1251_cmd_ps_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mod mode);

Otherwise patch looks very good to me.

-- 
Kalle Valo

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

* Re: [PATCH 1/2] wl1251: Prepare for idle mode support
  2011-04-01 19:22 ` Kalle Valo
@ 2011-04-04  6:49   ` Jarkko Nikula
  0 siblings, 0 replies; 7+ messages in thread
From: Jarkko Nikula @ 2011-04-04  6:49 UTC (permalink / raw)
  To: Kalle Valo; +Cc: linux-wireless, John W. Linville

On Fri, 01 Apr 2011 22:22:01 +0300
Kalle Valo <kvalo@adurom.com> wrote:

> > Then enum wl1251_cmd_ps_mod in cmd.h is renamed and moved to wl1251.h as it
> > is a state rather than chip level command.
> 
> But now you are moving a firmware interface value outside cmd.h. I was
> thinking that you would touch wl1251_cmd_ps_mod at all, instead just
> create a new enum wl1251_station_mode which will be used as the driver
> state variable.
> 
> That way it's clear which enum is for the firmware interface and which
> one is an internal variable.
> 
I agree, I was blind to see that the wl1251_cmd_ps_mode indeed sends the
value to chip... I'll send an update where the enum wl1251_cmd_ps_mod is
kept intact.

-- 
Jarkko

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

* [PATCH 1/2] wl1251: Prepare for idle mode support
@ 2011-04-04  8:04 Jarkko Nikula
  2011-04-04  8:04 ` [PATCH 2/2] wl1251: Add support for idle mode Jarkko Nikula
  2011-04-04 18:15 ` [PATCH 1/2] wl1251: Prepare for idle mode support Kalle Valo
  0 siblings, 2 replies; 7+ messages in thread
From: Jarkko Nikula @ 2011-04-04  8:04 UTC (permalink / raw)
  To: linux-wireless; +Cc: Kalle Valo, John W. Linville, Jarkko Nikula

RFC for WL1251 idle mode support brought a few issues that are worth to
update before adding the idle mode support.

Since the idle mode can reuse the code that is now used in Power Save Mode
(PSM), the flag psm in struct wl1251 is changed to variable station_mode
to be able to distinguish between PSM and idle modes.

As the station mode is different than the power power save mode command
that is sent to chip, the enum wl1251_cmd_ps_mod values are used only when
communicating with the chip and new enum wl1251_station_mode values are used
inside the driver.

Confusing comment about psm and elp relation is removed since the PSM is
actually activated by putting the chip into Entreme Low Power (ELP) mode.

Signed-off-by: Jarkko Nikula <jhnikula@gmail.com>
---
v2:
- Since the enum wl1251_cmd_ps_mod values are sent to chip they are kept in
  cmd.h but prefixed with CHIP_.
---
 drivers/net/wireless/wl1251/cmd.h    |    4 ++--
 drivers/net/wireless/wl1251/event.c  |    6 ++++--
 drivers/net/wireless/wl1251/main.c   |    6 +++---
 drivers/net/wireless/wl1251/ps.c     |   14 ++++++--------
 drivers/net/wireless/wl1251/ps.h     |    2 +-
 drivers/net/wireless/wl1251/wl1251.h |    8 ++++++--
 6 files changed, 22 insertions(+), 18 deletions(-)

diff --git a/drivers/net/wireless/wl1251/cmd.h b/drivers/net/wireless/wl1251/cmd.h
index e5c74c6..79ca527 100644
--- a/drivers/net/wireless/wl1251/cmd.h
+++ b/drivers/net/wireless/wl1251/cmd.h
@@ -313,8 +313,8 @@ struct wl1251_cmd_vbm_update {
 } __packed;
 
 enum wl1251_cmd_ps_mode {
-	STATION_ACTIVE_MODE,
-	STATION_POWER_SAVE_MODE
+	CHIP_ACTIVE_MODE,
+	CHIP_POWER_SAVE_MODE
 };
 
 struct wl1251_cmd_ps_params {
diff --git a/drivers/net/wireless/wl1251/event.c b/drivers/net/wireless/wl1251/event.c
index dfc4579..9f15cca 100644
--- a/drivers/net/wireless/wl1251/event.c
+++ b/drivers/net/wireless/wl1251/event.c
@@ -68,14 +68,16 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
 	if (vector & BSS_LOSE_EVENT_ID) {
 		wl1251_debug(DEBUG_EVENT, "BSS_LOSE_EVENT");
 
-		if (wl->psm_requested && wl->psm) {
+		if (wl->psm_requested &&
+		    wl->station_mode != STATION_ACTIVE_MODE) {
 			ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE);
 			if (ret < 0)
 				return ret;
 		}
 	}
 
-	if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID && wl->psm) {
+	if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID &&
+	    wl->station_mode != STATION_ACTIVE_MODE) {
 		wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT");
 
 		/* indicate to the stack, that beacons have been lost */
diff --git a/drivers/net/wireless/wl1251/main.c b/drivers/net/wireless/wl1251/main.c
index 12c9e63..04a0549 100644
--- a/drivers/net/wireless/wl1251/main.c
+++ b/drivers/net/wireless/wl1251/main.c
@@ -497,7 +497,7 @@ static void wl1251_op_stop(struct ieee80211_hw *hw)
 	wl->rx_last_id = 0;
 	wl->next_tx_complete = 0;
 	wl->elp = false;
-	wl->psm = 0;
+	wl->station_mode = STATION_ACTIVE_MODE;
 	wl->tx_queue_stopped = false;
 	wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
 	wl->rssi_thold = 0;
@@ -632,7 +632,7 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
 
 		wl->psm_requested = false;
 
-		if (wl->psm) {
+		if (wl->station_mode != STATION_ACTIVE_MODE) {
 			ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE);
 			if (ret < 0)
 				goto out_sleep;
@@ -1384,7 +1384,7 @@ struct ieee80211_hw *wl1251_alloc_hw(void)
 	wl->rx_config = WL1251_DEFAULT_RX_CONFIG;
 	wl->rx_filter = WL1251_DEFAULT_RX_FILTER;
 	wl->elp = false;
-	wl->psm = 0;
+	wl->station_mode = STATION_ACTIVE_MODE;
 	wl->psm_requested = false;
 	wl->tx_queue_stopped = false;
 	wl->power_level = WL1251_DEFAULT_POWER_LEVEL;
diff --git a/drivers/net/wireless/wl1251/ps.c b/drivers/net/wireless/wl1251/ps.c
index 9cc5147..97a5b8c 100644
--- a/drivers/net/wireless/wl1251/ps.c
+++ b/drivers/net/wireless/wl1251/ps.c
@@ -39,7 +39,7 @@ void wl1251_elp_work(struct work_struct *work)
 
 	mutex_lock(&wl->mutex);
 
-	if (wl->elp || !wl->psm)
+	if (wl->elp || wl->station_mode == STATION_ACTIVE_MODE)
 		goto out;
 
 	wl1251_debug(DEBUG_PSM, "chip to elp");
@@ -57,7 +57,7 @@ void wl1251_ps_elp_sleep(struct wl1251 *wl)
 {
 	unsigned long delay;
 
-	if (wl->psm) {
+	if (wl->station_mode != STATION_ACTIVE_MODE) {
 		delay = msecs_to_jiffies(ELP_ENTRY_DELAY);
 		ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, delay);
 	}
@@ -104,7 +104,7 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl)
 	return 0;
 }
 
-int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode)
+int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_station_mode mode)
 {
 	int ret;
 
@@ -128,15 +128,13 @@ int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode)
 		if (ret < 0)
 			return ret;
 
-		ret = wl1251_cmd_ps_mode(wl, STATION_POWER_SAVE_MODE);
+		ret = wl1251_cmd_ps_mode(wl, CHIP_POWER_SAVE_MODE);
 		if (ret < 0)
 			return ret;
 
 		ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_ELP);
 		if (ret < 0)
 			return ret;
-
-		wl->psm = 1;
 		break;
 	case STATION_ACTIVE_MODE:
 	default:
@@ -163,13 +161,13 @@ int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode)
 		if (ret < 0)
 			return ret;
 
-		ret = wl1251_cmd_ps_mode(wl, STATION_ACTIVE_MODE);
+		ret = wl1251_cmd_ps_mode(wl, CHIP_ACTIVE_MODE);
 		if (ret < 0)
 			return ret;
 
-		wl->psm = 0;
 		break;
 	}
+	wl->station_mode = mode;
 
 	return ret;
 }
diff --git a/drivers/net/wireless/wl1251/ps.h b/drivers/net/wireless/wl1251/ps.h
index 55c3dda..75efad2 100644
--- a/drivers/net/wireless/wl1251/ps.h
+++ b/drivers/net/wireless/wl1251/ps.h
@@ -26,7 +26,7 @@
 #include "wl1251.h"
 #include "acx.h"
 
-int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode);
+int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_station_mode mode);
 void wl1251_ps_elp_sleep(struct wl1251 *wl);
 int wl1251_ps_elp_wakeup(struct wl1251 *wl);
 void wl1251_elp_work(struct work_struct *work);
diff --git a/drivers/net/wireless/wl1251/wl1251.h b/drivers/net/wireless/wl1251/wl1251.h
index bb23cd5..bf245a8 100644
--- a/drivers/net/wireless/wl1251/wl1251.h
+++ b/drivers/net/wireless/wl1251/wl1251.h
@@ -129,6 +129,11 @@ enum wl1251_partition_type {
 	PART_TABLE_LEN
 };
 
+enum wl1251_station_mode {
+	STATION_ACTIVE_MODE,
+	STATION_POWER_SAVE_MODE,
+};
+
 struct wl1251_partition {
 	u32 size;
 	u32 start;
@@ -358,8 +363,7 @@ struct wl1251 {
 
 	struct delayed_work elp_work;
 
-	/* we can be in psm, but not in elp, we have to differentiate */
-	bool psm;
+	enum wl1251_station_mode station_mode;
 
 	/* PSM mode requested */
 	bool psm_requested;
-- 
1.7.4.1


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

* [PATCH 2/2] wl1251: Add support for idle mode
  2011-04-04  8:04 [PATCH 1/2] wl1251: Prepare for idle mode support Jarkko Nikula
@ 2011-04-04  8:04 ` Jarkko Nikula
  2011-04-04 18:18   ` Kalle Valo
  2011-04-04 18:15 ` [PATCH 1/2] wl1251: Prepare for idle mode support Kalle Valo
  1 sibling, 1 reply; 7+ messages in thread
From: Jarkko Nikula @ 2011-04-04  8:04 UTC (permalink / raw)
  To: linux-wireless; +Cc: Kalle Valo, John W. Linville, Jarkko Nikula

On Nokia N900 the wl1251 consumes the most power when the interface is up
but not associated to access point (that supports PSM). In terms of battery
current consumption, the consumption is ~180 mA higher when the interface is
up but not associated and only ~5 mA higher when associated compared to
interface down and driver not loaded cases.

This patch adds support for the mac80211 idle notifications. Chip is put into
idle very much the same way when entering into PSM by utilizing the Extreme
Low Power (ELP) mode. I.e. idle is entered by setting necessary conditions
in wl1251_ps_set_mode followed by a call to wl1251_ps_elp_sleep.

It seems it is just enough the authorize ELP mode followed by
CMD_DISCONNECT (thanks to Kalle Valo about the idea to use it).
Without disconnect command the chip remains somewhat active and stays
consuming ~20 mA. Idle mode is left by same way than PSM. The wl1251_join
call is used to revert the CMD_DISCONNECT. Without it association to AP
doesn't work when trying second time.

With this patch the interface up but not associated case the battery current
consumption is less than 1 mA higher compared to interface down case.

Signed-off-by: Jarkko Nikula <jhnikula@gmail.com>
---
v3:
- No changes. Resend with updated patch 1/2.
v2:
- cmd.h change not needed because of the patch 1/2
- developed on top vanilla commit 6aba74f2791287ec407e0f92487a725a25908067
v1:
- I don't have specs for the chip and this patch is developed heavily by
  trial and error method. Anyway, I believe the chip enters into idle properly
  as the consumption is very near to interface down case.
- I have verified the patch by making sure that the driver can scan the APs
  and connect/disconnect multiple times after the idle mode was entered.
- There is still problem that the consumption jumps again ~+180 mA after
  disconnection happens. Reason is the BSS_LOSE_EVENT which puts the chip
  again into active mode and driver doesn't receive an idle mode request
  after that. For me it looks the driver doesn't notify the mac80211
  properly and thus no idle mode request is coming. As this patch doesn't
  affect that I see that is better to handle separately.
---
 drivers/net/wireless/wl1251/main.c   |   16 ++++++++++++++++
 drivers/net/wireless/wl1251/ps.c     |   11 +++++++++++
 drivers/net/wireless/wl1251/wl1251.h |    1 +
 3 files changed, 28 insertions(+), 0 deletions(-)

diff --git a/drivers/net/wireless/wl1251/main.c b/drivers/net/wireless/wl1251/main.c
index 04a0549..a14a48c 100644
--- a/drivers/net/wireless/wl1251/main.c
+++ b/drivers/net/wireless/wl1251/main.c
@@ -639,6 +639,22 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
 		}
 	}
 
+	if (changed & IEEE80211_CONF_CHANGE_IDLE) {
+		if (conf->flags & IEEE80211_CONF_IDLE) {
+			ret = wl1251_ps_set_mode(wl, STATION_IDLE);
+			if (ret < 0)
+				goto out_sleep;
+		} else {
+			ret = wl1251_ps_set_mode(wl, STATION_ACTIVE_MODE);
+			if (ret < 0)
+				goto out_sleep;
+			ret = wl1251_join(wl, wl->bss_type, wl->channel,
+					  wl->beacon_int, wl->dtim_period);
+			if (ret < 0)
+				goto out_sleep;
+		}
+	}
+
 	if (conf->power_level != wl->power_level) {
 		ret = wl1251_acx_tx_power(wl, conf->power_level);
 		if (ret < 0)
diff --git a/drivers/net/wireless/wl1251/ps.c b/drivers/net/wireless/wl1251/ps.c
index 97a5b8c..db719f7 100644
--- a/drivers/net/wireless/wl1251/ps.c
+++ b/drivers/net/wireless/wl1251/ps.c
@@ -136,6 +136,17 @@ int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_station_mode mode)
 		if (ret < 0)
 			return ret;
 		break;
+	case STATION_IDLE:
+		wl1251_debug(DEBUG_PSM, "entering idle");
+
+		ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_ELP);
+		if (ret < 0)
+			return ret;
+
+		ret = wl1251_cmd_template_set(wl, CMD_DISCONNECT, NULL, 0);
+		if (ret < 0)
+			return ret;
+		break;
 	case STATION_ACTIVE_MODE:
 	default:
 		wl1251_debug(DEBUG_PSM, "leaving psm");
diff --git a/drivers/net/wireless/wl1251/wl1251.h b/drivers/net/wireless/wl1251/wl1251.h
index bf245a8..a77f1bb 100644
--- a/drivers/net/wireless/wl1251/wl1251.h
+++ b/drivers/net/wireless/wl1251/wl1251.h
@@ -132,6 +132,7 @@ enum wl1251_partition_type {
 enum wl1251_station_mode {
 	STATION_ACTIVE_MODE,
 	STATION_POWER_SAVE_MODE,
+	STATION_IDLE,
 };
 
 struct wl1251_partition {
-- 
1.7.4.1


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

* Re: [PATCH 1/2] wl1251: Prepare for idle mode support
  2011-04-04  8:04 [PATCH 1/2] wl1251: Prepare for idle mode support Jarkko Nikula
  2011-04-04  8:04 ` [PATCH 2/2] wl1251: Add support for idle mode Jarkko Nikula
@ 2011-04-04 18:15 ` Kalle Valo
  1 sibling, 0 replies; 7+ messages in thread
From: Kalle Valo @ 2011-04-04 18:15 UTC (permalink / raw)
  To: Jarkko Nikula; +Cc: linux-wireless, John W. Linville

Jarkko Nikula <jhnikula@gmail.com> writes:

> RFC for WL1251 idle mode support brought a few issues that are worth to
> update before adding the idle mode support.
>
> Since the idle mode can reuse the code that is now used in Power Save Mode
> (PSM), the flag psm in struct wl1251 is changed to variable station_mode
> to be able to distinguish between PSM and idle modes.
>
> As the station mode is different than the power power save mode command
> that is sent to chip, the enum wl1251_cmd_ps_mod values are used only when
> communicating with the chip and new enum wl1251_station_mode values are used
> inside the driver.
>
> Confusing comment about psm and elp relation is removed since the PSM is
> actually activated by putting the chip into Entreme Low Power (ELP) mode.

This is perfect now, thank you for your patience.

> Signed-off-by: Jarkko Nikula <jhnikula@gmail.com>

Acked-by: Kalle Valo <kvalo@adurom.com>

-- 
Kalle Valo

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

* Re: [PATCH 2/2] wl1251: Add support for idle mode
  2011-04-04  8:04 ` [PATCH 2/2] wl1251: Add support for idle mode Jarkko Nikula
@ 2011-04-04 18:18   ` Kalle Valo
  0 siblings, 0 replies; 7+ messages in thread
From: Kalle Valo @ 2011-04-04 18:18 UTC (permalink / raw)
  To: Jarkko Nikula; +Cc: linux-wireless, John W. Linville

Jarkko Nikula <jhnikula@gmail.com> writes:

> On Nokia N900 the wl1251 consumes the most power when the interface is up
> but not associated to access point (that supports PSM). In terms of battery
> current consumption, the consumption is ~180 mA higher when the interface is
> up but not associated and only ~5 mA higher when associated compared to
> interface down and driver not loaded cases.

Still looking good. You are going to make a lot of meego people happy
with this patch. :)

> Signed-off-by: Jarkko Nikula <jhnikula@gmail.com>

Acked-by: Kalle Valo <kvalo@adurom.com>

-- 
Kalle Valo

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

end of thread, other threads:[~2011-04-04 18:18 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-04-04  8:04 [PATCH 1/2] wl1251: Prepare for idle mode support Jarkko Nikula
2011-04-04  8:04 ` [PATCH 2/2] wl1251: Add support for idle mode Jarkko Nikula
2011-04-04 18:18   ` Kalle Valo
2011-04-04 18:15 ` [PATCH 1/2] wl1251: Prepare for idle mode support Kalle Valo
  -- strict thread matches above, loose matches on Subject: below --
2011-03-31 13:04 Jarkko Nikula
2011-04-01 19:22 ` Kalle Valo
2011-04-04  6:49   ` Jarkko Nikula

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).