diff options
author | Wey-Yi Guy <wey-yi.w.guy@intel.com> | 2010-11-23 13:58:56 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-11-24 16:19:37 -0500 |
commit | 35162ba75900209755628ccf7357763797037ba6 (patch) | |
tree | efbe6afc4cf985565fd22333418d29cdc91dcbd4 /drivers/net | |
parent | 1f37daf3233ccda5072f715d6c322d84833cdd92 (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/net')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-6000.c | 8 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-commands.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-power.c | 68 |
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 | ||
2680 | struct iwl3945_powertable_cmd { | 2682 | struct 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 */ | ||
123 | static 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 */ | ||
139 | static 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 - */ | ||
154 | static 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 | |||
117 | static void iwl_static_sleep_cmd(struct iwl_priv *priv, | 167 | static 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 | ||