aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorWey-Yi Guy <wey-yi.w.guy@intel.com>2010-11-23 13:58:56 -0500
committerJohn W. Linville <linville@tuxdriver.com>2010-11-24 16:19:37 -0500
commit35162ba75900209755628ccf7357763797037ba6 (patch)
treeefbe6afc4cf985565fd22333418d29cdc91dcbd4 /drivers
parent1f37daf3233ccda5072f715d6c322d84833cdd92 (diff)
iwlwifi: advance power management support
For 6000g2b and up, adding advance power management support for better power consumption Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-power.c68
4 files changed, 76 insertions, 6 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index f650282a3ad3..93e3fe92f389 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -621,6 +621,7 @@ struct iwl_cfg iwl6000g2b_2agn_cfg = {
621 .need_dc_calib = true, 621 .need_dc_calib = true,
622 .need_temp_offset_calib = true, 622 .need_temp_offset_calib = true,
623 .led_mode = IWL_LED_RF_STATE, 623 .led_mode = IWL_LED_RF_STATE,
624 .adv_pm = true,
624 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ 625 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
625 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, 626 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
626}; 627};
@@ -641,6 +642,7 @@ struct iwl_cfg iwl6000g2b_2abg_cfg = {
641 .need_dc_calib = true, 642 .need_dc_calib = true,
642 .need_temp_offset_calib = true, 643 .need_temp_offset_calib = true,
643 .led_mode = IWL_LED_RF_STATE, 644 .led_mode = IWL_LED_RF_STATE,
645 .adv_pm = true,
644 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ 646 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
645 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, 647 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
646}; 648};
@@ -662,6 +664,7 @@ struct iwl_cfg iwl6000g2b_2bgn_cfg = {
662 .need_dc_calib = true, 664 .need_dc_calib = true,
663 .need_temp_offset_calib = true, 665 .need_temp_offset_calib = true,
664 .led_mode = IWL_LED_RF_STATE, 666 .led_mode = IWL_LED_RF_STATE,
667 .adv_pm = true,
665 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ 668 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
666 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, 669 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
667}; 670};
@@ -682,6 +685,7 @@ struct iwl_cfg iwl6000g2b_2bg_cfg = {
682 .need_dc_calib = true, 685 .need_dc_calib = true,
683 .need_temp_offset_calib = true, 686 .need_temp_offset_calib = true,
684 .led_mode = IWL_LED_RF_STATE, 687 .led_mode = IWL_LED_RF_STATE,
688 .adv_pm = true,
685 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ 689 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
686 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, 690 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
687}; 691};
@@ -703,6 +707,7 @@ struct iwl_cfg iwl6000g2b_bgn_cfg = {
703 .need_dc_calib = true, 707 .need_dc_calib = true,
704 .need_temp_offset_calib = true, 708 .need_temp_offset_calib = true,
705 .led_mode = IWL_LED_RF_STATE, 709 .led_mode = IWL_LED_RF_STATE,
710 .adv_pm = true,
706 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ 711 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
707 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, 712 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
708}; 713};
@@ -723,6 +728,7 @@ struct iwl_cfg iwl6000g2b_bg_cfg = {
723 .need_dc_calib = true, 728 .need_dc_calib = true,
724 .need_temp_offset_calib = true, 729 .need_temp_offset_calib = true,
725 .led_mode = IWL_LED_RF_STATE, 730 .led_mode = IWL_LED_RF_STATE,
731 .adv_pm = true,
726 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ 732 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
727 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, 733 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
728}; 734};
@@ -862,6 +868,7 @@ struct iwl_cfg iwl130_bgn_cfg = {
862 .ht_params = &iwl6000_ht_params, 868 .ht_params = &iwl6000_ht_params,
863 .need_dc_calib = true, 869 .need_dc_calib = true,
864 .led_mode = IWL_LED_RF_STATE, 870 .led_mode = IWL_LED_RF_STATE,
871 .adv_pm = true,
865 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ 872 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
866 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, 873 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
867}; 874};
@@ -881,6 +888,7 @@ struct iwl_cfg iwl130_bg_cfg = {
881 .bt_params = &iwl6000_bt_params, 888 .bt_params = &iwl6000_bt_params,
882 .need_dc_calib = true, 889 .need_dc_calib = true,
883 .led_mode = IWL_LED_RF_STATE, 890 .led_mode = IWL_LED_RF_STATE,
891 .adv_pm = true,
884 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */ 892 /* Due to bluetooth, we transmit 2.4 GHz probes only on antenna A */
885 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A, 893 .scan_tx_antennas[IEEE80211_BAND_2GHZ] = ANT_A,
886}; 894};
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index f9e7fa4b532c..c9448cba1e20 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -2668,6 +2668,8 @@ struct iwl_spectrum_notification {
2668#define IWL_POWER_VEC_SIZE 5 2668#define IWL_POWER_VEC_SIZE 5
2669 2669
2670#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK cpu_to_le16(BIT(0)) 2670#define IWL_POWER_DRIVER_ALLOW_SLEEP_MSK cpu_to_le16(BIT(0))
2671#define IWL_POWER_POWER_SAVE_ENA_MSK cpu_to_le16(BIT(0))
2672#define IWL_POWER_POWER_MANAGEMENT_ENA_MSK cpu_to_le16(BIT(1))
2671#define IWL_POWER_SLEEP_OVER_DTIM_MSK cpu_to_le16(BIT(2)) 2673#define IWL_POWER_SLEEP_OVER_DTIM_MSK cpu_to_le16(BIT(2))
2672#define IWL_POWER_PCI_PM_MSK cpu_to_le16(BIT(3)) 2674#define IWL_POWER_PCI_PM_MSK cpu_to_le16(BIT(3))
2673#define IWL_POWER_FAST_PD cpu_to_le16(BIT(4)) 2675#define IWL_POWER_FAST_PD cpu_to_le16(BIT(4))
@@ -2675,7 +2677,7 @@ struct iwl_spectrum_notification {
2675#define IWL_POWER_SHADOW_REG_ENA cpu_to_le16(BIT(6)) 2677#define IWL_POWER_SHADOW_REG_ENA cpu_to_le16(BIT(6))
2676#define IWL_POWER_CT_KILL_SET cpu_to_le16(BIT(7)) 2678#define IWL_POWER_CT_KILL_SET cpu_to_le16(BIT(7))
2677#define IWL_POWER_BT_SCO_ENA cpu_to_le16(BIT(8)) 2679#define IWL_POWER_BT_SCO_ENA cpu_to_le16(BIT(8))
2678#define IWL_POWER_ADVANCE_PM_ENA cpu_to_le16(BIT(9)) 2680#define IWL_POWER_ADVANCE_PM_ENA_MSK cpu_to_le16(BIT(9))
2679 2681
2680struct iwl3945_powertable_cmd { 2682struct iwl3945_powertable_cmd {
2681 __le16 flags; 2683 __le16 flags;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 3f7bd4012c29..808be731ecb7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -366,6 +366,7 @@ struct iwl_ht_params {
366 * @need_temp_offset_calib: need to perform temperature offset calibration 366 * @need_temp_offset_calib: need to perform temperature offset calibration
367 * @scan_antennas: available antenna for scan operation 367 * @scan_antennas: available antenna for scan operation
368 * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off) 368 * @led_mode: 0=blinking, 1=On(RF On)/Off(RF Off)
369 * @adv_pm: advance power management
369 * 370 *
370 * We enable the driver to be backward compatible wrt API version. The 371 * We enable the driver to be backward compatible wrt API version. The
371 * driver specifies which APIs it supports (with @ucode_api_max being the 372 * driver specifies which APIs it supports (with @ucode_api_max being the
@@ -413,6 +414,7 @@ struct iwl_cfg {
413 u8 scan_rx_antennas[IEEE80211_NUM_BANDS]; 414 u8 scan_rx_antennas[IEEE80211_NUM_BANDS];
414 u8 scan_tx_antennas[IEEE80211_NUM_BANDS]; 415 u8 scan_tx_antennas[IEEE80211_NUM_BANDS];
415 enum iwl_led_mode led_mode; 416 enum iwl_led_mode led_mode;
417 const bool adv_pm;
416}; 418};
417 419
418/*************************** 420/***************************
diff --git a/drivers/net/wireless/iwlwifi/iwl-power.c b/drivers/net/wireless/iwlwifi/iwl-power.c
index 21c5e6abfbd0..1eec18d909d8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-power.c
+++ b/drivers/net/wireless/iwlwifi/iwl-power.c
@@ -75,6 +75,10 @@ struct iwl_power_vec_entry {
75 75
76#define NOSLP cpu_to_le16(0), 0, 0 76#define NOSLP cpu_to_le16(0), 0, 0
77#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0 77#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0
78#define ASLP (IWL_POWER_POWER_SAVE_ENA_MSK | \
79 IWL_POWER_POWER_MANAGEMENT_ENA_MSK | \
80 IWL_POWER_ADVANCE_PM_ENA_MSK)
81#define ASLP_TOUT(T) cpu_to_le32(T)
78#define TU_TO_USEC 1024 82#define TU_TO_USEC 1024
79#define SLP_TOUT(T) cpu_to_le32((T) * TU_TO_USEC) 83#define SLP_TOUT(T) cpu_to_le32((T) * TU_TO_USEC)
80#define SLP_VEC(X0, X1, X2, X3, X4) {cpu_to_le32(X0), \ 84#define SLP_VEC(X0, X1, X2, X3, X4) {cpu_to_le32(X0), \
@@ -114,6 +118,52 @@ static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
114 {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0} 118 {{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
115}; 119};
116 120
121/* advance power management */
122/* DTIM 0 - 2 */
123static const struct iwl_power_vec_entry apm_range_0[IWL_POWER_NUM] = {
124 {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
125 SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
126 {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
127 SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
128 {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
129 SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
130 {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
131 SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
132 {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
133 SLP_VEC(1, 2, 6, 8, 0xFF), ASLP_TOUT(2)}, 2}
134};
135
136
137/* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */
138/* DTIM 3 - 10 */
139static const struct iwl_power_vec_entry apm_range_1[IWL_POWER_NUM] = {
140 {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
141 SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
142 {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
143 SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
144 {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
145 SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
146 {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
147 SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
148 {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
149 SLP_VEC(1, 2, 6, 8, 0xFF), 0}, 2}
150};
151
152/* for DTIM period > IWL_DTIM_RANGE_1_MAX */
153/* DTIM 11 - */
154static const struct iwl_power_vec_entry apm_range_2[IWL_POWER_NUM] = {
155 {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
156 SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
157 {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
158 SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
159 {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
160 SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
161 {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
162 SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
163 {{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
164 SLP_VEC(1, 2, 6, 8, 0xFF), ASLP_TOUT(2)}, 2}
165};
166
117static void iwl_static_sleep_cmd(struct iwl_priv *priv, 167static void iwl_static_sleep_cmd(struct iwl_priv *priv,
118 struct iwl_powertable_cmd *cmd, 168 struct iwl_powertable_cmd *cmd,
119 enum iwl_power_level lvl, int period) 169 enum iwl_power_level lvl, int period)
@@ -124,11 +174,19 @@ static void iwl_static_sleep_cmd(struct iwl_priv *priv,
124 u8 skip; 174 u8 skip;
125 u32 slp_itrvl; 175 u32 slp_itrvl;
126 176
127 table = range_2; 177 if (priv->cfg->adv_pm) {
128 if (period <= IWL_DTIM_RANGE_1_MAX) 178 table = apm_range_2;
129 table = range_1; 179 if (period <= IWL_DTIM_RANGE_1_MAX)
130 if (period <= IWL_DTIM_RANGE_0_MAX) 180 table = apm_range_1;
131 table = range_0; 181 if (period <= IWL_DTIM_RANGE_0_MAX)
182 table = apm_range_0;
183 } else {
184 table = range_2;
185 if (period <= IWL_DTIM_RANGE_1_MAX)
186 table = range_1;
187 if (period <= IWL_DTIM_RANGE_0_MAX)
188 table = range_0;
189 }
132 190
133 BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM); 191 BUG_ON(lvl < 0 || lvl >= IWL_POWER_NUM);
134 192