From: Stanislaw Gruszka <sgruszka@redhat.com>
To: Tino Keitel <tino.keitel@tikei.de>
Cc: linux-wireless@vger.kernel.org
Subject: Re: Power saving features for iwl4965
Date: Mon, 3 Jun 2013 16:18:05 +0200 [thread overview]
Message-ID: <20130603141804.GA2146@redhat.com> (raw)
In-Reply-To: <20130603085239.GA26920@mac.home>
On Mon, Jun 03, 2013 at 10:52:39AM +0200, Tino Keitel wrote:
> On Mon, Jan 07, 2013 at 12:08:00 +0100, Stanislaw Gruszka wrote:
>
> [...]
>
> > I posted patch here
> > http://marc.info/?l=linux-wireless&m=135601033021616&w=2
> >
> > But I did not review code regarding power save to catch possible
> > problems. Testing are bug reporting are welcome ...
>
> Hi,
>
> the patch is surprisingly small. To me it looks like it only contains
> the code to make "iwconfig wlan0 power on" work, the actual power
> management is missing.
>
> I just did some tests using powertop to see if I'm right. With the old
> pre-iwlegacy driver, the difference between "iwconfig wlan0 power on"
> and "... power off" is more then 0,8W, which is ~10% of the total idle
> power usage of my X61s with dimmed screen. With a current kernel and
> your patch, I can't measure a difference between "iwconfig wlan0 power
> on" and "... power off". To me it seems that the patch is pretty
> useless, at least on 4965AGN hardware.
Yes, we do not send any command to put hardware in sleep mode when
mac80211 enable PS.
> It would be really nice to have proper power management in a current
> kernel, as the laptop gets noticeably hotter with the current iwlegacy
> driver. That's why I still use a 3.1.10 kernel with an old
> forward-ported iwlagn driver.
Could you try this experimental patch?
diff --git a/drivers/net/wireless/iwlegacy/commands.h b/drivers/net/wireless/iwlegacy/commands.h
index 3b6c994..baf3ae7 100644
--- a/drivers/net/wireless/iwlegacy/commands.h
+++ b/drivers/net/wireless/iwlegacy/commands.h
@@ -2278,7 +2278,8 @@ struct il_spectrum_notification {
*/
#define IL_POWER_VEC_SIZE 5
-#define IL_POWER_DRIVER_ALLOW_SLEEP_MSK cpu_to_le16(BIT(0))
+#define IL_POWER_DRIVER_ALLOW_SLEEP_MSK cpu_to_le16(BIT(0))
+#define IL_POWER_SLEEP_OVER_DTIM_MSK cpu_to_le16(BIT(2))
#define IL_POWER_PCI_PM_MSK cpu_to_le16(BIT(3))
struct il3945_powertable_cmd {
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c
index 592d0aa..07769ae 100644
--- a/drivers/net/wireless/iwlegacy/common.c
+++ b/drivers/net/wireless/iwlegacy/common.c
@@ -1079,29 +1079,80 @@ EXPORT_SYMBOL(il_get_channel_info);
* Setting power level allows the card to go to sleep when not busy.
*
* We calculate a sleep command based on the required latency, which
- * we get from mac80211. In order to handle thermal throttling, we can
- * also use pre-defined power levels.
+ * we get from mac80211.
*/
-/*
- * This defines the old power levels. They are still used by default
- * (level 1) and for thermal throttle (levels 3 through 5)
- */
-
-struct il_power_vec_entry {
- struct il_powertable_cmd cmd;
- u8 no_dtim; /* number of skip dtim */
-};
+#define SLP_VEC(X0, X1, X2, X3, X4) {cpu_to_le32(X0), \
+ cpu_to_le32(X1), \
+ cpu_to_le32(X2), \
+ cpu_to_le32(X3), \
+ cpu_to_le32(X4)}
static void
-il_power_sleep_cam_cmd(struct il_priv *il, struct il_powertable_cmd *cmd)
+il_build_powertable_cmd(struct il_priv *il, struct il_powertable_cmd *cmd)
{
+ const __le32 interval[3][IL_POWER_VEC_SIZE] = {
+ SLP_VEC(2, 2, 4, 6, 0xFF),
+ SLP_VEC(2, 4, 7, 10, 10),
+ SLP_VEC(4, 7, 10, 10, 0xFF)
+ };
+ int i, dtim_period, no_dtim;
+ u32 max_sleep;
+ bool skip;
+
memset(cmd, 0, sizeof(*cmd));
if (il->power_data.pci_pm)
cmd->flags |= IL_POWER_PCI_PM_MSK;
- D_POWER("Sleep command for CAM\n");
+ /* if no Power Save, we are done */
+ if (il->power_data.ps_disabled)
+ return;
+
+ cmd->flags = IL_POWER_DRIVER_ALLOW_SLEEP_MSK;
+ cmd->keep_alive_seconds = 0;
+ cmd->debug_flags = 0;
+ cmd->rx_data_timeout = cpu_to_le32(25 * 1024);
+ cmd->tx_data_timeout = cpu_to_le32(25 * 1024);
+ cmd->keep_alive_beacons = 0;
+
+ dtim_period = il->vif ? il->vif->bss_conf.dtim_period : 0;
+
+ if (dtim_period <= 2) {
+ memcpy(cmd->sleep_interval, interval[0], sizeof(interval[0]));
+ no_dtim = 2;
+ } else if (dtim_period <= 10) {
+ memcpy(cmd->sleep_interval, interval[1], sizeof(interval[1]));
+ no_dtim = 2;
+ } else {
+ memcpy(cmd->sleep_interval, interval[2], sizeof(interval[2]));
+ no_dtim = 0;
+ }
+
+ if (dtim_period == 0) {
+ dtim_period = 1;
+ skip = false;
+ } else {
+ skip = !!no_dtim;
+ }
+
+ if (skip) {
+ __le32 tmp = cmd->sleep_interval[IL_POWER_VEC_SIZE - 1];
+
+ max_sleep = le32_to_cpu(tmp);
+ if (max_sleep == 0xFF)
+ max_sleep = dtim_period * (skip + 1);
+ else if (max_sleep > dtim_period)
+ max_sleep = (max_sleep / dtim_period) * dtim_period;
+ cmd->flags |= IL_POWER_SLEEP_OVER_DTIM_MSK;
+ } else {
+ max_sleep = dtim_period;
+ cmd->flags &= ~IL_POWER_SLEEP_OVER_DTIM_MSK;
+ }
+
+ for (i = 0; i < IL_POWER_VEC_SIZE; i++)
+ if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep)
+ cmd->sleep_interval[i] = cpu_to_le32(max_sleep);
}
static int
@@ -1174,7 +1225,8 @@ il_power_update_mode(struct il_priv *il, bool force)
{
struct il_powertable_cmd cmd;
- il_power_sleep_cam_cmd(il, &cmd);
+ il_build_powertable_cmd(il, &cmd);
+
return il_power_set_mode(il, &cmd, force);
}
EXPORT_SYMBOL(il_power_update_mode);
@@ -5081,6 +5133,7 @@ set_ch_out:
}
if (changed & (IEEE80211_CONF_CHANGE_PS | IEEE80211_CONF_CHANGE_IDLE)) {
+ il->power_data.ps_disabled = !(conf->flags & IEEE80211_CONF_PS);
ret = il_power_update_mode(il, false);
if (ret)
D_MAC80211("Error setting sleep level\n");
diff --git a/drivers/net/wireless/iwlegacy/common.h b/drivers/net/wireless/iwlegacy/common.h
index f8246f2..8f81983 100644
--- a/drivers/net/wireless/iwlegacy/common.h
+++ b/drivers/net/wireless/iwlegacy/common.h
@@ -1123,6 +1123,7 @@ struct il_power_mgr {
struct il_powertable_cmd sleep_cmd_next;
int debug_sleep_level_override;
bool pci_pm;
+ bool ps_disabled;
};
struct il_priv {
next prev parent reply other threads:[~2013-06-03 14:16 UTC|newest]
Thread overview: 34+ messages / expand[flat|nested] mbox.gz Atom feed top
2012-04-18 20:35 Power saving features for iwl4965 Tino Keitel
2012-04-19 14:25 ` Johannes Berg
2012-04-19 18:50 ` tino
2012-04-25 12:25 ` Stanislaw Gruszka
2012-05-03 18:28 ` Tino Keitel
2012-12-26 18:54 ` Tino Keitel
2013-01-07 11:08 ` Stanislaw Gruszka
2013-01-08 1:48 ` Pedro Francisco
2013-01-08 8:47 ` Stanislaw Gruszka
2013-06-03 8:52 ` Tino Keitel
2013-06-03 14:18 ` Stanislaw Gruszka [this message]
2013-06-09 0:28 ` Pedro Francisco
2013-06-10 19:31 ` Pedro Francisco
2013-06-11 16:19 ` Stanislaw Gruszka
2013-06-11 18:55 ` Tino Keitel
2013-06-14 12:50 ` Pedro Francisco
2013-06-14 13:18 ` Stanislaw Gruszka
2013-06-25 14:25 ` Stanislaw Gruszka
2013-07-11 21:02 ` Pedro Francisco
2013-07-16 10:27 ` Stanislaw Gruszka
2013-07-16 11:02 ` Pedro Francisco
2013-07-17 11:48 ` Pedro Francisco
2013-07-31 12:08 ` Stanislaw Gruszka
2013-08-04 14:24 ` Pedro Francisco
2013-08-04 14:53 ` Pedro Francisco
2013-10-17 9:06 ` Stanislaw Gruszka
2013-10-17 13:32 ` Stanislaw Gruszka
2013-06-11 18:51 ` Tino Keitel
2014-02-18 10:57 ` Stanislaw Gruszka
2014-02-18 11:32 ` Emmanuel Grumbach
2014-02-18 11:59 ` Stanislaw Gruszka
2014-02-20 12:08 ` Pedro Francisco
2014-02-25 16:16 ` Pedro Francisco
-- strict thread matches above, loose matches on Subject: below --
2012-10-01 16:06 Tino Keitel
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130603141804.GA2146@redhat.com \
--to=sgruszka@redhat.com \
--cc=linux-wireless@vger.kernel.org \
--cc=tino.keitel@tikei.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
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).