aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-08-07 18:41:51 -0400
committerJohn W. Linville <linville@tuxdriver.com>2009-08-14 09:13:50 -0400
commite312c24cf8229f9b6e76dbfd5d99eefe21f4ac0a (patch)
tree79e3b967f3905716baef4bc73b4510543b38ceb5 /drivers/net/wireless
parentd91b1ba37744bc7fb7524516be855c9fa81142e2 (diff)
iwlwifi: automatically adjust sleep level
Depending on required latency requested by pm_qos (via mac80211) we can automatically adjust the sleep state. Also, mac80211 has a user-visible dynamic sleep feature where we are supposed to stay awake after sending/receiving frames to better receive response frames to our packets, this can be integrated into the sleep command. Currently, and this patch doesn't change that yet, we default to using sleep level 1 if PS is enabled. With a module parameter to iwlcore, automatic adjustment to changing network latency requirements can be enabled -- this isn't yet the default due to requiring more testing. The goal is to enable automatic adjustment and then go into the deepest possible sleep state possible depending on the networking latency requirements. This patch does, however, enable IEEE80211_HW_SUPPORTS_DYNAMIC_PS to avoid the double-timer (one in software and one in the device) when transmitting -- the exact timeout may be ignored but that is not of big concern. Note also that we keep the hard-coded power indices around for thermal throttling -- the specification of that calls for using the specified power levels. Those can also be selected in debugfs to allow easier testing of such parameters. Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: Reinette Chatre <reinette.chatre@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c46
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-calib.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c15
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debugfs.c83
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.c317
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.h30
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c66
10 files changed, 256 insertions, 313 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index 319df4ab7f13..2232b1794e76 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1606,7 +1606,7 @@ static void iwl_alive_start(struct iwl_priv *priv)
1606 set_bit(STATUS_READY, &priv->status); 1606 set_bit(STATUS_READY, &priv->status);
1607 wake_up_interruptible(&priv->wait_command_queue); 1607 wake_up_interruptible(&priv->wait_command_queue);
1608 1608
1609 iwl_power_update_mode(priv, 1); 1609 iwl_power_update_mode(priv, true);
1610 1610
1611 /* reassociate for ADHOC mode */ 1611 /* reassociate for ADHOC mode */
1612 if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) { 1612 if (priv->vif && (priv->iw_mode == NL80211_IFTYPE_ADHOC)) {
@@ -2075,7 +2075,7 @@ void iwl_post_associate(struct iwl_priv *priv)
2075 * If chain noise has already been run, then we need to enable 2075 * If chain noise has already been run, then we need to enable
2076 * power management here */ 2076 * power management here */
2077 if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE) 2077 if (priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE)
2078 iwl_power_update_mode(priv, 0); 2078 iwl_power_update_mode(priv, false);
2079 2079
2080 /* Enable Rx differential gain and sensitivity calibrations */ 2080 /* Enable Rx differential gain and sensitivity calibrations */
2081 iwl_chain_noise_reset(priv); 2081 iwl_chain_noise_reset(priv);
@@ -2565,47 +2565,6 @@ static ssize_t store_filter_flags(struct device *d,
2565static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags, 2565static DEVICE_ATTR(filter_flags, S_IWUSR | S_IRUGO, show_filter_flags,
2566 store_filter_flags); 2566 store_filter_flags);
2567 2567
2568static ssize_t store_power_level(struct device *d,
2569 struct device_attribute *attr,
2570 const char *buf, size_t count)
2571{
2572 struct iwl_priv *priv = dev_get_drvdata(d);
2573 int ret;
2574 unsigned long mode;
2575
2576
2577 mutex_lock(&priv->mutex);
2578
2579 ret = strict_strtoul(buf, 10, &mode);
2580 if (ret)
2581 goto out;
2582
2583 ret = iwl_power_set_user_mode(priv, mode);
2584 if (ret) {
2585 IWL_DEBUG_MAC80211(priv, "failed setting power mode.\n");
2586 goto out;
2587 }
2588 ret = count;
2589
2590 out:
2591 mutex_unlock(&priv->mutex);
2592 return ret;
2593}
2594
2595static ssize_t show_power_level(struct device *d,
2596 struct device_attribute *attr, char *buf)
2597{
2598 struct iwl_priv *priv = dev_get_drvdata(d);
2599 int level = priv->power_data.power_mode;
2600 char *p = buf;
2601
2602 p += sprintf(p, "%d\n", level);
2603 return p - buf + 1;
2604}
2605
2606static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR, show_power_level,
2607 store_power_level);
2608
2609 2568
2610static ssize_t show_statistics(struct device *d, 2569static ssize_t show_statistics(struct device *d,
2611 struct device_attribute *attr, char *buf) 2570 struct device_attribute *attr, char *buf)
@@ -2698,7 +2657,6 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
2698static struct attribute *iwl_sysfs_entries[] = { 2657static struct attribute *iwl_sysfs_entries[] = {
2699 &dev_attr_flags.attr, 2658 &dev_attr_flags.attr,
2700 &dev_attr_filter_flags.attr, 2659 &dev_attr_filter_flags.attr,
2701 &dev_attr_power_level.attr,
2702 &dev_attr_statistics.attr, 2660 &dev_attr_statistics.attr,
2703 &dev_attr_temperature.attr, 2661 &dev_attr_temperature.attr,
2704 &dev_attr_tx_power.attr, 2662 &dev_attr_tx_power.attr,
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c
index 13180d6ee2f7..c4b565a2de94 100644
--- a/drivers/net/wireless/iwlwifi/iwl-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-calib.c
@@ -852,7 +852,7 @@ void iwl_chain_noise_calibration(struct iwl_priv *priv,
852 priv->cfg->ops->lib->update_chain_flags(priv); 852 priv->cfg->ops->lib->update_chain_flags(priv);
853 853
854 data->state = IWL_CHAIN_NOISE_DONE; 854 data->state = IWL_CHAIN_NOISE_DONE;
855 iwl_power_update_mode(priv, 0); 855 iwl_power_update_mode(priv, false);
856} 856}
857EXPORT_SYMBOL(iwl_chain_noise_calibration); 857EXPORT_SYMBOL(iwl_chain_noise_calibration);
858 858
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 6188c54113b0..68d7719071f7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -2313,15 +2313,22 @@ struct iwl_spectrum_notification {
2313 * PM allow: 2313 * PM allow:
2314 * bit 0 - '0' Driver not allow power management 2314 * bit 0 - '0' Driver not allow power management
2315 * '1' Driver allow PM (use rest of parameters) 2315 * '1' Driver allow PM (use rest of parameters)
2316 *
2316 * uCode send sleep notifications: 2317 * uCode send sleep notifications:
2317 * bit 1 - '0' Don't send sleep notification 2318 * bit 1 - '0' Don't send sleep notification
2318 * '1' send sleep notification (SEND_PM_NOTIFICATION) 2319 * '1' send sleep notification (SEND_PM_NOTIFICATION)
2320 *
2319 * Sleep over DTIM 2321 * Sleep over DTIM
2320 * bit 2 - '0' PM have to walk up every DTIM 2322 * bit 2 - '0' PM have to walk up every DTIM
2321 * '1' PM could sleep over DTIM till listen Interval. 2323 * '1' PM could sleep over DTIM till listen Interval.
2324 *
2322 * PCI power managed 2325 * PCI power managed
2323 * bit 3 - '0' (PCI_CFG_LINK_CTRL & 0x1) 2326 * bit 3 - '0' (PCI_CFG_LINK_CTRL & 0x1)
2324 * '1' !(PCI_CFG_LINK_CTRL & 0x1) 2327 * '1' !(PCI_CFG_LINK_CTRL & 0x1)
2328 *
2329 * Fast PD
2330 * bit 4 - '1' Put radio to sleep when receiving frame for others
2331 *
2325 * Force sleep Modes 2332 * Force sleep Modes
2326 * bit 31/30- '00' use both mac/xtal sleeps 2333 * bit 31/30- '00' use both mac/xtal sleeps
2327 * '01' force Mac sleep 2334 * '01' force Mac sleep
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 36c6e16285de..af735128333a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1568,7 +1568,8 @@ int iwl_setup_mac(struct iwl_priv *priv)
1568 IEEE80211_HW_NOISE_DBM | 1568 IEEE80211_HW_NOISE_DBM |
1569 IEEE80211_HW_AMPDU_AGGREGATION | 1569 IEEE80211_HW_AMPDU_AGGREGATION |
1570 IEEE80211_HW_SPECTRUM_MGMT | 1570 IEEE80211_HW_SPECTRUM_MGMT |
1571 IEEE80211_HW_SUPPORTS_PS; 1571 IEEE80211_HW_SUPPORTS_PS |
1572 IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
1572 hw->wiphy->interface_modes = 1573 hw->wiphy->interface_modes =
1573 BIT(NL80211_IFTYPE_STATION) | 1574 BIT(NL80211_IFTYPE_STATION) |
1574 BIT(NL80211_IFTYPE_ADHOC); 1575 BIT(NL80211_IFTYPE_ADHOC);
@@ -1663,8 +1664,6 @@ int iwl_init_drv(struct iwl_priv *priv)
1663 priv->qos_data.qos_cap.val = 0; 1664 priv->qos_data.qos_cap.val = 0;
1664 1665
1665 priv->rates_mask = IWL_RATES_MASK; 1666 priv->rates_mask = IWL_RATES_MASK;
1666 /* If power management is turned on, default to CAM mode */
1667 priv->power_mode = IWL_POWER_MODE_CAM;
1668 priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MAX; 1667 priv->tx_power_user_lmt = IWL_TX_POWER_TARGET_POWER_MAX;
1669 1668
1670 ret = iwl_init_channel_map(priv); 1669 ret = iwl_init_channel_map(priv);
@@ -2551,7 +2550,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
2551 if (bss_conf->assoc) { 2550 if (bss_conf->assoc) {
2552 priv->assoc_id = bss_conf->aid; 2551 priv->assoc_id = bss_conf->aid;
2553 priv->beacon_int = bss_conf->beacon_int; 2552 priv->beacon_int = bss_conf->beacon_int;
2554 priv->power_data.dtim_period = bss_conf->dtim_period;
2555 priv->timestamp = bss_conf->timestamp; 2553 priv->timestamp = bss_conf->timestamp;
2556 priv->assoc_capability = bss_conf->assoc_capability; 2554 priv->assoc_capability = bss_conf->assoc_capability;
2557 2555
@@ -2801,13 +2799,10 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
2801 iwl_set_rate(priv); 2799 iwl_set_rate(priv);
2802 } 2800 }
2803 2801
2804 if (changed & IEEE80211_CONF_CHANGE_PS && 2802 if (changed & IEEE80211_CONF_CHANGE_PS) {
2805 priv->iw_mode == NL80211_IFTYPE_STATION) { 2803 ret = iwl_power_update_mode(priv, false);
2806 priv->power_data.power_disabled =
2807 !(conf->flags & IEEE80211_CONF_PS);
2808 ret = iwl_power_update_mode(priv, 0);
2809 if (ret) 2804 if (ret)
2810 IWL_DEBUG_MAC80211(priv, "Error setting power level\n"); 2805 IWL_DEBUG_MAC80211(priv, "Error setting sleep level\n");
2811 } 2806 }
2812 2807
2813 if (changed & IEEE80211_CONF_CHANGE_POWER) { 2808 if (changed & IEEE80211_CONF_CHANGE_POWER) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index 82befb7ce997..723f38a023ce 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -88,6 +88,8 @@ struct iwl_debugfs {
88 struct dentry *file_led; 88 struct dentry *file_led;
89#endif 89#endif
90 struct dentry *file_disable_ht40; 90 struct dentry *file_disable_ht40;
91 struct dentry *file_sleep_level_override;
92 struct dentry *file_current_sleep_command;
91 } dbgfs_data_files; 93 } dbgfs_data_files;
92 struct dir_rf_files { 94 struct dir_rf_files {
93 struct dentry *file_disable_sensitivity; 95 struct dentry *file_disable_sensitivity;
diff --git a/drivers/net/wireless/iwlwifi/iwl-debugfs.c b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
index 7b578d41101f..f68fb4711da2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debugfs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debugfs.c
@@ -776,6 +776,83 @@ static ssize_t iwl_dbgfs_disable_ht40_read(struct file *file,
776 return ret; 776 return ret;
777} 777}
778 778
779static ssize_t iwl_dbgfs_sleep_level_override_write(struct file *file,
780 const char __user *user_buf,
781 size_t count, loff_t *ppos)
782{
783 struct iwl_priv *priv = file->private_data;
784 char buf[8];
785 int buf_size;
786 int value;
787
788 memset(buf, 0, sizeof(buf));
789 buf_size = min(count, sizeof(buf) - 1);
790 if (copy_from_user(buf, user_buf, buf_size))
791 return -EFAULT;
792
793 if (sscanf(buf, "%d", &value) != 1)
794 return -EINVAL;
795
796 /*
797 * Our users expect 0 to be "CAM", but 0 isn't actually
798 * valid here. However, let's not confuse them and present
799 * IWL_POWER_INDEX_1 as "1", not "0".
800 */
801 if (value > 0)
802 value -= 1;
803
804 if (value != -1 && (value < 0 || value >= IWL_POWER_NUM))
805 return -EINVAL;
806
807 priv->power_data.debug_sleep_level_override = value;
808
809 iwl_power_update_mode(priv, false);
810
811 return count;
812}
813
814static ssize_t iwl_dbgfs_sleep_level_override_read(struct file *file,
815 char __user *user_buf,
816 size_t count, loff_t *ppos)
817{
818 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
819 char buf[10];
820 int pos, value;
821 const size_t bufsz = sizeof(buf);
822
823 /* see the write function */
824 value = priv->power_data.debug_sleep_level_override;
825 if (value >= 0)
826 value += 1;
827
828 pos = scnprintf(buf, bufsz, "%d\n", value);
829 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
830}
831
832static ssize_t iwl_dbgfs_current_sleep_command_read(struct file *file,
833 char __user *user_buf,
834 size_t count, loff_t *ppos)
835{
836 struct iwl_priv *priv = (struct iwl_priv *)file->private_data;
837 char buf[200];
838 int pos = 0, i;
839 const size_t bufsz = sizeof(buf);
840 struct iwl_powertable_cmd *cmd = &priv->power_data.sleep_cmd;
841
842 pos += scnprintf(buf + pos, bufsz - pos,
843 "flags: %#.2x\n", le16_to_cpu(cmd->flags));
844 pos += scnprintf(buf + pos, bufsz - pos,
845 "RX/TX timeout: %d/%d usec\n",
846 le32_to_cpu(cmd->rx_data_timeout),
847 le32_to_cpu(cmd->tx_data_timeout));
848 for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
849 pos += scnprintf(buf + pos, bufsz - pos,
850 "sleep_interval[%d]: %d\n", i,
851 le32_to_cpu(cmd->sleep_interval[i]));
852
853 return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
854}
855
779DEBUGFS_READ_WRITE_FILE_OPS(sram); 856DEBUGFS_READ_WRITE_FILE_OPS(sram);
780DEBUGFS_WRITE_FILE_OPS(log_event); 857DEBUGFS_WRITE_FILE_OPS(log_event);
781DEBUGFS_READ_FILE_OPS(nvm); 858DEBUGFS_READ_FILE_OPS(nvm);
@@ -789,6 +866,8 @@ DEBUGFS_READ_FILE_OPS(led);
789#endif 866#endif
790DEBUGFS_READ_FILE_OPS(thermal_throttling); 867DEBUGFS_READ_FILE_OPS(thermal_throttling);
791DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40); 868DEBUGFS_READ_WRITE_FILE_OPS(disable_ht40);
869DEBUGFS_READ_WRITE_FILE_OPS(sleep_level_override);
870DEBUGFS_READ_FILE_OPS(current_sleep_command);
792 871
793static ssize_t iwl_dbgfs_traffic_log_read(struct file *file, 872static ssize_t iwl_dbgfs_traffic_log_read(struct file *file,
794 char __user *user_buf, 873 char __user *user_buf,
@@ -1533,6 +1612,8 @@ int iwl_dbgfs_register(struct iwl_priv *priv, const char *name)
1533#ifdef CONFIG_IWLWIFI_LEDS 1612#ifdef CONFIG_IWLWIFI_LEDS
1534 DEBUGFS_ADD_FILE(led, data); 1613 DEBUGFS_ADD_FILE(led, data);
1535#endif 1614#endif
1615 DEBUGFS_ADD_FILE(sleep_level_override, data);
1616 DEBUGFS_ADD_FILE(current_sleep_command, data);
1536 DEBUGFS_ADD_FILE(thermal_throttling, data); 1617 DEBUGFS_ADD_FILE(thermal_throttling, data);
1537 DEBUGFS_ADD_FILE(disable_ht40, data); 1618 DEBUGFS_ADD_FILE(disable_ht40, data);
1538 DEBUGFS_ADD_FILE(rx_statistics, debug); 1619 DEBUGFS_ADD_FILE(rx_statistics, debug);
@@ -1572,6 +1653,8 @@ void iwl_dbgfs_unregister(struct iwl_priv *priv)
1572 if (!priv->dbgfs) 1653 if (!priv->dbgfs)
1573 return; 1654 return;
1574 1655
1656 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sleep_level_override);
1657 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_current_sleep_command);
1575 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm); 1658 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_nvm);
1576 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram); 1659 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_sram);
1577 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event); 1660 DEBUGFS_REMOVE(priv->dbgfs->dbgfs_data_files.file_log_event);
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 1aa2ae6d0756..b96c3c9e92a9 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1119,7 +1119,6 @@ struct iwl_priv {
1119 /* context information */ 1119 /* context information */
1120 u16 rates_mask; 1120 u16 rates_mask;
1121 1121
1122 u32 power_mode;
1123 u8 bssid[ETH_ALEN]; 1122 u8 bssid[ETH_ALEN];
1124 u16 rts_threshold; 1123 u16 rts_threshold;
1125 u8 mac_addr[ETH_ALEN]; 1124 u8 mac_addr[ETH_ALEN];
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index 27ad59d8643e..0b16841f45f4 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -42,20 +42,35 @@
42#include "iwl-power.h" 42#include "iwl-power.h"
43 43
44/* 44/*
45 * Setting power level allow the card to go to sleep when not busy. 45 * Setting power level allows the card to go to sleep when not busy.
46 * 46 *
47 * The power level is set to INDEX_1 (the least deep state) by 47 * We calculate a sleep command based on the required latency, which
48 * default, and will, in the future, be the deepest state unless 48 * we get from mac80211. In order to handle thermal throttling, we can
49 * otherwise required by pm_qos network latency requirements. 49 * also use pre-defined power levels.
50 *
51 * Using INDEX_1 without pm_qos is ok because mac80211 will disable
52 * PS when even checking every beacon for the TIM bit would exceed
53 * the required latency.
54 */ 50 */
55 51
56#define IWL_POWER_RANGE_0_MAX (2) 52/*
57#define IWL_POWER_RANGE_1_MAX (10) 53 * For now, keep using power level 1 instead of automatically
54 * adjusting ...
55 */
56bool no_sleep_autoadjust = true;
57module_param(no_sleep_autoadjust, bool, S_IRUGO);
58MODULE_PARM_DESC(no_sleep_autoadjust,
59 "don't automatically adjust sleep level "
60 "according to maximum network latency");
58 61
62/*
63 * This defines the old power levels. They are still used by default
64 * (level 1) and for thermal throttle (levels 3 through 5)
65 */
66
67struct iwl_power_vec_entry {
68 struct iwl_powertable_cmd cmd;
69 u8 no_dtim;
70};
71
72#define IWL_DTIM_RANGE_0_MAX 2
73#define IWL_DTIM_RANGE_1_MAX 10
59 74
60#define NOSLP cpu_to_le16(0), 0, 0 75#define NOSLP cpu_to_le16(0), 0, 0
61#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0 76#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0
@@ -67,9 +82,8 @@
67 cpu_to_le32(X3), \ 82 cpu_to_le32(X3), \
68 cpu_to_le32(X4)} 83 cpu_to_le32(X4)}
69/* default power management (not Tx power) table values */ 84/* default power management (not Tx power) table values */
70/* for DTIM period 0 through IWL_POWER_RANGE_0_MAX */ 85/* for DTIM period 0 through IWL_DTIM_RANGE_0_MAX */
71static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = { 86static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = {
72 {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
73 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, 87 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
74 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0}, 88 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
75 {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0}, 89 {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0},
@@ -78,9 +92,8 @@ static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = {
78}; 92};
79 93
80 94
81/* for DTIM period IWL_POWER_RANGE_0_MAX + 1 through IWL_POWER_RANGE_1_MAX */ 95/* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */
82static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = { 96static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = {
83 {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
84 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0}, 97 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
85 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0}, 98 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0},
86 {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0}, 99 {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0},
@@ -88,9 +101,8 @@ static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = {
88 {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2} 101 {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 7, 10, 10)}, 2}
89}; 102};
90 103
91/* for DTIM period > IWL_POWER_RANGE_1_MAX */ 104/* for DTIM period > IWL_DTIM_RANGE_1_MAX */
92static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = { 105static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
93 {{NOSLP, SLP_TOUT(0), SLP_TOUT(0), SLP_VEC(0, 0, 0, 0, 0)}, 0},
94 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0}, 106 {{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
95 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0}, 107 {{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0},
96 {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0}, 108 {{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0},
@@ -98,6 +110,56 @@ static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
98 {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0} 110 {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
99}; 111};
100 112
113static void iwl_static_sleep_cmd(struct iwl_priv *priv,
114 struct iwl_powertable_cmd *cmd,
115 enum iwl_power_level lvl, int period)
116{
117 const struct iwl_power_vec_entry *table;
118 int max_sleep, i;
119 bool skip;
120
121 table = range_2;
122 if (period < IWL_DTIM_RANGE_1_MAX)
123 table = range_1;
124 if (period < IWL_DTIM_RANGE_0_MAX)
125 table = range_0;
126
127 BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM);
128
129 *cmd = table[lvl].cmd;
130
131 if (period == 0) {
132 skip = false;
133 period = 1;
134 } else {
135 skip = !!table[lvl].no_dtim;
136 }
137
138 if (skip) {
139 __le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1];
140 max_sleep = le32_to_cpu(slp_itrvl);
141 if (max_sleep == 0xFF)
142 max_sleep = period * (skip + 1);
143 else if (max_sleep > period)
144 max_sleep = (le32_to_cpu(slp_itrvl) / period) * period;
145 cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK;
146 } else {
147 max_sleep = period;
148 cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
149 }
150
151 for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
152 if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep)
153 cmd->sleep_interval[i] = cpu_to_le32(max_sleep);
154
155 if (priv->power_data.pci_pm)
156 cmd->flags |= IWL_POWER_PCI_PM_MSK;
157 else
158 cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
159
160 IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1);
161}
162
101/* default Thermal Throttling transaction table 163/* default Thermal Throttling transaction table
102 * Current state | Throttling Down | Throttling Up 164 * Current state | Throttling Down | Throttling Up
103 *============================================================================= 165 *=============================================================================
@@ -138,98 +200,44 @@ static const struct iwl_tt_restriction restriction_range[IWL_TI_STATE_MAX] = {
138 {IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false } 200 {IWL_ANT_OK_NONE, IWL_ANT_OK_NONE, false }
139}; 201};
140 202
141/* set card power command */
142static int iwl_set_power(struct iwl_priv *priv, void *cmd)
143{
144 return iwl_send_cmd_pdu(priv, POWER_TABLE_CMD,
145 sizeof(struct iwl_powertable_cmd), cmd);
146}
147 203
148/* initialize to default */ 204static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv,
149static void iwl_power_init_handle(struct iwl_priv *priv) 205 struct iwl_powertable_cmd *cmd)
150{ 206{
151 struct iwl_power_mgr *pow_data; 207 memset(cmd, 0, sizeof(*cmd));
152 int size = sizeof(struct iwl_power_vec_entry) * IWL_POWER_NUM;
153 struct iwl_powertable_cmd *cmd;
154 int i;
155 u16 lctl;
156
157 IWL_DEBUG_POWER(priv, "Initialize power \n");
158
159 pow_data = &priv->power_data;
160
161 memset(pow_data, 0, sizeof(*pow_data));
162
163 memcpy(&pow_data->pwr_range_0[0], &range_0[0], size);
164 memcpy(&pow_data->pwr_range_1[0], &range_1[0], size);
165 memcpy(&pow_data->pwr_range_2[0], &range_2[0], size);
166
167 lctl = iwl_pcie_link_ctl(priv);
168 208
169 IWL_DEBUG_POWER(priv, "adjust power command flags\n"); 209 if (priv->power_data.pci_pm)
210 cmd->flags |= IWL_POWER_PCI_PM_MSK;
170 211
171 for (i = 0; i < IWL_POWER_NUM; i++) { 212 IWL_DEBUG_POWER(priv, "Sleep command for CAM\n");
172 cmd = &pow_data->pwr_range_0[i].cmd;
173
174 if (lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN)
175 cmd->flags &= ~IWL_POWER_PCI_PM_MSK;
176 else
177 cmd->flags |= IWL_POWER_PCI_PM_MSK;
178 }
179} 213}
180 214
181/* adjust power command according to DTIM period and power level*/ 215static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv,
182static int iwl_update_power_cmd(struct iwl_priv *priv, 216 struct iwl_powertable_cmd *cmd,
183 struct iwl_powertable_cmd *cmd, u16 mode) 217 int dynps_ms, int wakeup_period)
184{ 218{
185 struct iwl_power_vec_entry *range;
186 struct iwl_power_mgr *pow_data;
187 int i; 219 int i;
188 u32 max_sleep = 0;
189 u8 period;
190 bool skip;
191 220
192 if (mode > IWL_POWER_INDEX_5) { 221 memset(cmd, 0, sizeof(*cmd));
193 IWL_DEBUG_POWER(priv, "Error invalid power mode \n");
194 return -EINVAL;
195 }
196 222
197 pow_data = &priv->power_data; 223 cmd->flags = IWL_POWER_DRIVER_ALLOW_SLEEP_MSK |
224 IWL_POWER_FAST_PD; /* no use seeing frames for others */
198 225
199 if (pow_data->dtim_period <= IWL_POWER_RANGE_0_MAX) 226 if (priv->power_data.pci_pm)
200 range = &pow_data->pwr_range_0[0]; 227 cmd->flags |= IWL_POWER_PCI_PM_MSK;
201 else if (pow_data->dtim_period <= IWL_POWER_RANGE_1_MAX)
202 range = &pow_data->pwr_range_1[0];
203 else
204 range = &pow_data->pwr_range_2[0];
205 228
206 period = pow_data->dtim_period; 229 cmd->rx_data_timeout = cpu_to_le32(1000 * dynps_ms);
207 memcpy(cmd, &range[mode].cmd, sizeof(struct iwl_powertable_cmd)); 230 cmd->tx_data_timeout = cpu_to_le32(1000 * dynps_ms);
208
209 if (period == 0) {
210 period = 1;
211 skip = false;
212 } else {
213 skip = !!range[mode].no_dtim;
214 }
215
216 if (skip) {
217 __le32 slp_itrvl = cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1];
218 max_sleep = le32_to_cpu(slp_itrvl);
219 if (max_sleep == 0xFF)
220 max_sleep = period * (skip + 1);
221 else if (max_sleep > period)
222 max_sleep = (le32_to_cpu(slp_itrvl) / period) * period;
223 cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK;
224 } else {
225 max_sleep = period;
226 cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;
227 }
228 231
229 for (i = 0; i < IWL_POWER_VEC_SIZE; i++) 232 for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
230 if (le32_to_cpu(cmd->sleep_interval[i]) > max_sleep) 233 cmd->sleep_interval[i] = cpu_to_le32(wakeup_period);
231 cmd->sleep_interval[i] = cpu_to_le32(max_sleep); 234
235 IWL_DEBUG_POWER(priv, "Automatic sleep command\n");
236}
232 237
238static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
239{
240 IWL_DEBUG_POWER(priv, "Sending power/sleep command\n");
233 IWL_DEBUG_POWER(priv, "Flags value = 0x%08X\n", cmd->flags); 241 IWL_DEBUG_POWER(priv, "Flags value = 0x%08X\n", cmd->flags);
234 IWL_DEBUG_POWER(priv, "Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout)); 242 IWL_DEBUG_POWER(priv, "Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout));
235 IWL_DEBUG_POWER(priv, "Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout)); 243 IWL_DEBUG_POWER(priv, "Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout));
@@ -240,50 +248,54 @@ static int iwl_update_power_cmd(struct iwl_priv *priv,
240 le32_to_cpu(cmd->sleep_interval[3]), 248 le32_to_cpu(cmd->sleep_interval[3]),
241 le32_to_cpu(cmd->sleep_interval[4])); 249 le32_to_cpu(cmd->sleep_interval[4]));
242 250
243 return 0; 251 return iwl_send_cmd_pdu(priv, POWER_TABLE_CMD,
252 sizeof(struct iwl_powertable_cmd), cmd);
244} 253}
245 254
246 255
247/*
248 * compute the final power mode index
249 */
250int iwl_power_update_mode(struct iwl_priv *priv, bool force) 256int iwl_power_update_mode(struct iwl_priv *priv, bool force)
251{ 257{
252 struct iwl_power_mgr *setting = &(priv->power_data);
253 int ret = 0; 258 int ret = 0;
254 struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 259 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
255 u16 uninitialized_var(final_mode); 260 bool enabled = (priv->iw_mode == NL80211_IFTYPE_STATION) &&
261 (priv->hw->conf.flags & IEEE80211_CONF_PS);
256 bool update_chains; 262 bool update_chains;
263 struct iwl_powertable_cmd cmd;
264 int dtimper;
257 265
258 /* Don't update the RX chain when chain noise calibration is running */ 266 /* Don't update the RX chain when chain noise calibration is running */
259 update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE || 267 update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
260 priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE; 268 priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
261 269
262 final_mode = priv->power_data.user_power_setting; 270 if (priv->vif)
263 271 dtimper = priv->vif->bss_conf.dtim_period;
264 if (setting->power_disabled) 272 else
265 final_mode = IWL_POWER_MODE_CAM; 273 dtimper = 1;
274
275 /* TT power setting overwrites everything */
276 if (tt->state >= IWL_TI_1)
277 iwl_static_sleep_cmd(priv, &cmd, tt->tt_power_mode, dtimper);
278 else if (!enabled)
279 iwl_power_sleep_cam_cmd(priv, &cmd);
280 else if (priv->power_data.debug_sleep_level_override >= 0)
281 iwl_static_sleep_cmd(priv, &cmd,
282 priv->power_data.debug_sleep_level_override,
283 dtimper);
284 else if (no_sleep_autoadjust)
285 iwl_static_sleep_cmd(priv, &cmd, IWL_POWER_INDEX_1, dtimper);
286 else
287 iwl_power_fill_sleep_cmd(priv, &cmd,
288 priv->hw->conf.dynamic_ps_timeout,
289 priv->hw->conf.max_sleep_period);
266 290
267 if (tt->state >= IWL_TI_1) {
268 /* TT power setting overwrite user & system power setting */
269 final_mode = tt->tt_power_mode;
270 }
271 if (iwl_is_ready_rf(priv) && 291 if (iwl_is_ready_rf(priv) &&
272 ((setting->power_mode != final_mode) || force)) { 292 (memcmp(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd)) || force)) {
273 struct iwl_powertable_cmd cmd; 293 if (cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)
274
275 if (final_mode != IWL_POWER_MODE_CAM)
276 set_bit(STATUS_POWER_PMI, &priv->status); 294 set_bit(STATUS_POWER_PMI, &priv->status);
277 295
278 iwl_update_power_cmd(priv, &cmd, final_mode);
279 cmd.keep_alive_beacons = 0;
280
281 if (final_mode == IWL_POWER_INDEX_5)
282 cmd.flags |= IWL_POWER_FAST_PD;
283
284 ret = iwl_set_power(priv, &cmd); 296 ret = iwl_set_power(priv, &cmd);
285 if (!ret) { 297 if (!ret) {
286 if (final_mode == IWL_POWER_MODE_CAM) 298 if (!(cmd.flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
287 clear_bit(STATUS_POWER_PMI, &priv->status); 299 clear_bit(STATUS_POWER_PMI, &priv->status);
288 300
289 if (priv->cfg->ops->lib->update_chain_flags && 301 if (priv->cfg->ops->lib->update_chain_flags &&
@@ -294,7 +306,7 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
294 "Cannot update the power, chain noise " 306 "Cannot update the power, chain noise "
295 "calibration running: %d\n", 307 "calibration running: %d\n",
296 priv->chain_noise_data.state); 308 priv->chain_noise_data.state);
297 setting->power_mode = final_mode; 309 memcpy(&priv->power_data.sleep_cmd, &cmd, sizeof(cmd));
298 } else 310 } else
299 IWL_ERR(priv, "set power fail, ret = %d", ret); 311 IWL_ERR(priv, "set power fail, ret = %d", ret);
300 } 312 }
@@ -303,18 +315,6 @@ int iwl_power_update_mode(struct iwl_priv *priv, bool force)
303} 315}
304EXPORT_SYMBOL(iwl_power_update_mode); 316EXPORT_SYMBOL(iwl_power_update_mode);
305 317
306/* set user_power_setting */
307int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode)
308{
309 if (mode >= IWL_POWER_NUM)
310 return -EINVAL;
311
312 priv->power_data.user_power_setting = mode;
313
314 return iwl_power_update_mode(priv, 0);
315}
316EXPORT_SYMBOL(iwl_power_set_user_mode);
317
318bool iwl_ht_enabled(struct iwl_priv *priv) 318bool iwl_ht_enabled(struct iwl_priv *priv)
319{ 319{
320 struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 320 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
@@ -349,7 +349,6 @@ enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv)
349 restriction = tt->restriction + tt->state; 349 restriction = tt->restriction + tt->state;
350 return restriction->rx_stream; 350 return restriction->rx_stream;
351} 351}
352EXPORT_SYMBOL(iwl_rx_ant_restriction);
353 352
354#define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */ 353#define CT_KILL_EXIT_DURATION (5) /* 5 seconds duration */
355 354
@@ -429,7 +428,6 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
429{ 428{
430 struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 429 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
431 enum iwl_tt_state old_state; 430 enum iwl_tt_state old_state;
432 struct iwl_power_mgr *setting = &priv->power_data;
433 431
434#ifdef CONFIG_IWLWIFI_DEBUG 432#ifdef CONFIG_IWLWIFI_DEBUG
435 if ((tt->tt_previous_temp) && 433 if ((tt->tt_previous_temp) &&
@@ -456,24 +454,13 @@ static void iwl_legacy_tt_handler(struct iwl_priv *priv, s32 temp)
456 tt->tt_previous_temp = temp; 454 tt->tt_previous_temp = temp;
457#endif 455#endif
458 if (tt->state != old_state) { 456 if (tt->state != old_state) {
459 if (old_state == IWL_TI_0) {
460 tt->sys_power_mode = setting->power_mode;
461 IWL_DEBUG_POWER(priv, "current power mode: %u\n",
462 setting->power_mode);
463 }
464 switch (tt->state) { 457 switch (tt->state) {
465 case IWL_TI_0: 458 case IWL_TI_0:
466 /* when system ready to go back to IWL_TI_0 state 459 /*
467 * using system power mode instead of TT power mode 460 * When the system is ready to go back to IWL_TI_0
468 * revert back to the orginal power mode which was saved 461 * we only have to call iwl_power_update_mode() to
469 * before enter Thermal Throttling state 462 * do so.
470 * update priv->power_data.user_power_setting to the
471 * required power mode to make sure
472 * iwl_power_update_mode() will update power correctly.
473 */ 463 */
474 priv->power_data.user_power_setting =
475 tt->sys_power_mode;
476 tt->tt_power_mode = tt->sys_power_mode;
477 break; 464 break;
478 case IWL_TI_1: 465 case IWL_TI_1:
479 tt->tt_power_mode = IWL_POWER_INDEX_3; 466 tt->tt_power_mode = IWL_POWER_INDEX_3;
@@ -576,13 +563,8 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
576 } 563 }
577 if (changed) { 564 if (changed) {
578 struct iwl_rxon_cmd *rxon = &priv->staging_rxon; 565 struct iwl_rxon_cmd *rxon = &priv->staging_rxon;
579 struct iwl_power_mgr *setting = &priv->power_data;
580 566
581 if (tt->state >= IWL_TI_1) { 567 if (tt->state >= IWL_TI_1) {
582 /* if switching from IWL_TI_0 to other TT state
583 * save previous power setting in tt->sys_power_mode */
584 if (old_state == IWL_TI_0)
585 tt->sys_power_mode = setting->power_mode;
586 /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */ 568 /* force PI = IWL_POWER_INDEX_5 in the case of TI > 0 */
587 tt->tt_power_mode = IWL_POWER_INDEX_5; 569 tt->tt_power_mode = IWL_POWER_INDEX_5;
588 if (!iwl_ht_enabled(priv)) 570 if (!iwl_ht_enabled(priv))
@@ -599,17 +581,11 @@ static void iwl_advance_tt_handler(struct iwl_priv *priv, s32 temp)
599 } 581 }
600 582
601 } else { 583 } else {
602 /* restore system power setting */ 584 /*
603 /* the previous power mode was saved in 585 * restore system power setting -- it will be
604 * tt->sys_power_mode when system move into 586 * recalculated automatically.
605 * Thermal Throttling state
606 * set power_data.user_power_setting to the previous
607 * system power mode to make sure power will get
608 * updated correctly
609 */ 587 */
610 priv->power_data.user_power_setting = 588
611 tt->sys_power_mode;
612 tt->tt_power_mode = tt->sys_power_mode;
613 /* check HT capability and set 589 /* check HT capability and set
614 * according to the system HT capability 590 * according to the system HT capability
615 * in case get disabled before */ 591 * in case get disabled before */
@@ -761,7 +737,6 @@ EXPORT_SYMBOL(iwl_tt_handler);
761void iwl_tt_initialize(struct iwl_priv *priv) 737void iwl_tt_initialize(struct iwl_priv *priv)
762{ 738{
763 struct iwl_tt_mgmt *tt = &priv->thermal_throttle; 739 struct iwl_tt_mgmt *tt = &priv->thermal_throttle;
764 struct iwl_power_mgr *setting = &priv->power_data;
765 int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1); 740 int size = sizeof(struct iwl_tt_trans) * (IWL_TI_STATE_MAX - 1);
766 struct iwl_tt_trans *transaction; 741 struct iwl_tt_trans *transaction;
767 742
@@ -770,8 +745,6 @@ void iwl_tt_initialize(struct iwl_priv *priv)
770 memset(tt, 0, sizeof(struct iwl_tt_mgmt)); 745 memset(tt, 0, sizeof(struct iwl_tt_mgmt));
771 746
772 tt->state = IWL_TI_0; 747 tt->state = IWL_TI_0;
773 tt->sys_power_mode = setting->power_mode;
774 tt->tt_power_mode = tt->sys_power_mode;
775 init_timer(&priv->thermal_throttle.ct_kill_exit_tm); 748 init_timer(&priv->thermal_throttle.ct_kill_exit_tm);
776 priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv; 749 priv->thermal_throttle.ct_kill_exit_tm.data = (unsigned long)priv;
777 priv->thermal_throttle.ct_kill_exit_tm.function = iwl_tt_check_exit_ct_kill; 750 priv->thermal_throttle.ct_kill_exit_tm.function = iwl_tt_check_exit_ct_kill;
@@ -849,9 +822,13 @@ EXPORT_SYMBOL(iwl_tt_exit);
849/* initialize to default */ 822/* initialize to default */
850void iwl_power_initialize(struct iwl_priv *priv) 823void iwl_power_initialize(struct iwl_priv *priv)
851{ 824{
852 iwl_power_init_handle(priv); 825 u16 lctl = iwl_pcie_link_ctl(priv);
853 priv->power_data.user_power_setting = IWL_POWER_INDEX_1; 826
854 /* default to disabled until mac80211 says otherwise */ 827 priv->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
855 priv->power_data.power_disabled = 1; 828
829 priv->power_data.debug_sleep_level_override = -1;
830
831 memset(&priv->power_data.sleep_cmd, 0,
832 sizeof(priv->power_data.sleep_cmd));
856} 833}
857EXPORT_SYMBOL(iwl_power_initialize); 834EXPORT_SYMBOL(iwl_power_initialize);
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.h b/drivers/net/wireless/iwlwifi/iwl-power.h
index 15e3eabd2e84..df6f6a49712b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.h
+++ b/drivers/net/wireless/iwlwifi/iwl-power.h
@@ -28,11 +28,8 @@
28#ifndef __iwl_power_setting_h__ 28#ifndef __iwl_power_setting_h__
29#define __iwl_power_setting_h__ 29#define __iwl_power_setting_h__
30 30
31#include <net/mac80211.h>
32#include "iwl-commands.h" 31#include "iwl-commands.h"
33 32
34struct iwl_priv;
35
36#define IWL_ABSOLUTE_ZERO 0 33#define IWL_ABSOLUTE_ZERO 0
37#define IWL_ABSOLUTE_MAX 0xFFFFFFFF 34#define IWL_ABSOLUTE_MAX 0xFFFFFFFF
38#define IWL_TT_INCREASE_MARGIN 5 35#define IWL_TT_INCREASE_MARGIN 5
@@ -93,8 +90,6 @@ struct iwl_tt_trans {
93 * when thermal throttling state != IWL_TI_0 90 * when thermal throttling state != IWL_TI_0
94 * the tt_power_mode should set to different 91 * the tt_power_mode should set to different
95 * power mode based on the current tt state 92 * power mode based on the current tt state
96 * @sys_power_mode: previous system power mode
97 * before transition into TT state
98 * @tt_previous_temperature: last measured temperature 93 * @tt_previous_temperature: last measured temperature
99 * @iwl_tt_restriction: ptr to restriction tbl, used by advance 94 * @iwl_tt_restriction: ptr to restriction tbl, used by advance
100 * thermal throttling to determine how many tx/rx streams 95 * thermal throttling to determine how many tx/rx streams
@@ -108,7 +103,6 @@ struct iwl_tt_mgmt {
108 enum iwl_tt_state state; 103 enum iwl_tt_state state;
109 bool advanced_tt; 104 bool advanced_tt;
110 u8 tt_power_mode; 105 u8 tt_power_mode;
111 u8 sys_power_mode;
112 bool ct_kill_toggle; 106 bool ct_kill_toggle;
113#ifdef CONFIG_IWLWIFI_DEBUG 107#ifdef CONFIG_IWLWIFI_DEBUG
114 s32 tt_previous_temp; 108 s32 tt_previous_temp;
@@ -118,8 +112,7 @@ struct iwl_tt_mgmt {
118 struct timer_list ct_kill_exit_tm; 112 struct timer_list ct_kill_exit_tm;
119}; 113};
120 114
121enum { 115enum iwl_power_level {
122 IWL_POWER_MODE_CAM, /* Continuously Aware Mode, always on */
123 IWL_POWER_INDEX_1, 116 IWL_POWER_INDEX_1,
124 IWL_POWER_INDEX_2, 117 IWL_POWER_INDEX_2,
125 IWL_POWER_INDEX_3, 118 IWL_POWER_INDEX_3,
@@ -128,26 +121,13 @@ enum {
128 IWL_POWER_NUM 121 IWL_POWER_NUM
129}; 122};
130 123
131/* Power management (not Tx power) structures */
132
133struct iwl_power_vec_entry {
134 struct iwl_powertable_cmd cmd;
135 u8 no_dtim;
136};
137
138struct iwl_power_mgr { 124struct iwl_power_mgr {
139 struct iwl_power_vec_entry pwr_range_0[IWL_POWER_NUM]; 125 struct iwl_powertable_cmd sleep_cmd;
140 struct iwl_power_vec_entry pwr_range_1[IWL_POWER_NUM]; 126 int debug_sleep_level_override;
141 struct iwl_power_vec_entry pwr_range_2[IWL_POWER_NUM]; 127 bool pci_pm;
142 u32 dtim_period;
143 /* final power level that used to calculate final power command */
144 u8 power_mode;
145 u8 user_power_setting; /* set by user through sysfs */
146 u8 power_disabled; /* set by mac80211's CONF_PS */
147}; 128};
148 129
149int iwl_power_update_mode(struct iwl_priv *priv, bool force); 130int iwl_power_update_mode(struct iwl_priv *priv, bool force);
150int iwl_power_set_user_mode(struct iwl_priv *priv, u16 mode);
151bool iwl_ht_enabled(struct iwl_priv *priv); 131bool iwl_ht_enabled(struct iwl_priv *priv);
152enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv); 132enum iwl_antenna_ok iwl_tx_ant_restriction(struct iwl_priv *priv);
153enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv); 133enum iwl_antenna_ok iwl_rx_ant_restriction(struct iwl_priv *priv);
@@ -158,4 +138,6 @@ void iwl_tt_initialize(struct iwl_priv *priv);
158void iwl_tt_exit(struct iwl_priv *priv); 138void iwl_tt_exit(struct iwl_priv *priv);
159void iwl_power_initialize(struct iwl_priv *priv); 139void iwl_power_initialize(struct iwl_priv *priv);
160 140
141extern bool no_sleep_autoadjust;
142
161#endif /* __iwl_power_setting_h__ */ 143#endif /* __iwl_power_setting_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index e5fa672e8390..e617411d0c5e 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -3554,65 +3554,6 @@ static DEVICE_ATTR(retry_rate, S_IWUSR | S_IRUSR, show_retry_rate,
3554 store_retry_rate); 3554 store_retry_rate);
3555 3555
3556 3556
3557static ssize_t store_power_level(struct device *d,
3558 struct device_attribute *attr,
3559 const char *buf, size_t count)
3560{
3561 struct iwl_priv *priv = dev_get_drvdata(d);
3562 int ret;
3563 unsigned long mode;
3564
3565
3566 mutex_lock(&priv->mutex);
3567
3568 ret = strict_strtoul(buf, 10, &mode);
3569 if (ret)
3570 goto out;
3571
3572 ret = iwl_power_set_user_mode(priv, mode);
3573 if (ret) {
3574 IWL_DEBUG_MAC80211(priv, "failed setting power mode.\n");
3575 goto out;
3576 }
3577 ret = count;
3578
3579 out:
3580 mutex_unlock(&priv->mutex);
3581 return ret;
3582}
3583
3584static ssize_t show_power_level(struct device *d,
3585 struct device_attribute *attr, char *buf)
3586{
3587 struct iwl_priv *priv = dev_get_drvdata(d);
3588 int level = priv->power_data.power_mode;
3589 char *p = buf;
3590
3591 p += sprintf(p, "%d\n", level);
3592 return p - buf + 1;
3593}
3594
3595static DEVICE_ATTR(power_level, S_IWUSR | S_IRUSR,
3596 show_power_level, store_power_level);
3597
3598#define MAX_WX_STRING 80
3599
3600/* Values are in microsecond */
3601static const s32 timeout_duration[] = {
3602 350000,
3603 250000,
3604 75000,
3605 37000,
3606 25000,
3607};
3608static const s32 period_duration[] = {
3609 400000,
3610 700000,
3611 1000000,
3612 1000000,
3613 1000000
3614};
3615
3616static ssize_t show_channels(struct device *d, 3557static ssize_t show_channels(struct device *d,
3617 struct device_attribute *attr, char *buf) 3558 struct device_attribute *attr, char *buf)
3618{ 3559{
@@ -3789,7 +3730,6 @@ static struct attribute *iwl3945_sysfs_entries[] = {
3789#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT 3730#ifdef CONFIG_IWL3945_SPECTRUM_MEASUREMENT
3790 &dev_attr_measurement.attr, 3731 &dev_attr_measurement.attr,
3791#endif 3732#endif
3792 &dev_attr_power_level.attr,
3793 &dev_attr_retry_rate.attr, 3733 &dev_attr_retry_rate.attr,
3794 &dev_attr_statistics.attr, 3734 &dev_attr_statistics.attr,
3795 &dev_attr_status.attr, 3735 &dev_attr_status.attr,
@@ -3854,8 +3794,6 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
3854 priv->qos_data.qos_cap.val = 0; 3794 priv->qos_data.qos_cap.val = 0;
3855 3795
3856 priv->rates_mask = IWL_RATES_MASK; 3796 priv->rates_mask = IWL_RATES_MASK;
3857 /* If power management is turned on, default to CAM mode */
3858 priv->power_mode = IWL_POWER_MODE_CAM;
3859 priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER; 3797 priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
3860 3798
3861 if (eeprom->version < EEPROM_3945_EEPROM_VERSION) { 3799 if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
@@ -3902,7 +3840,9 @@ static int iwl3945_setup_mac(struct iwl_priv *priv)
3902 /* Tell mac80211 our characteristics */ 3840 /* Tell mac80211 our characteristics */
3903 hw->flags = IEEE80211_HW_SIGNAL_DBM | 3841 hw->flags = IEEE80211_HW_SIGNAL_DBM |
3904 IEEE80211_HW_NOISE_DBM | 3842 IEEE80211_HW_NOISE_DBM |
3905 IEEE80211_HW_SPECTRUM_MGMT; 3843 IEEE80211_HW_SPECTRUM_MGMT |
3844 IEEE80211_HW_SUPPORTS_PS |
3845 IEEE80211_HW_SUPPORTS_DYNAMIC_PS;
3906 3846
3907 hw->wiphy->interface_modes = 3847 hw->wiphy->interface_modes =
3908 BIT(NL80211_IFTYPE_STATION) | 3848 BIT(NL80211_IFTYPE_STATION) |