1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2011 Intel Corporation. All rights reserved.
4  *
5  * Portions of this file are derived from the ipw3945 project, as well
6  * as portions of the ieee80211 subsystem header files.
7  *
8  * This program is free software; you can redistribute it and/or modify it
9  * under the terms of version 2 of the GNU General Public License as
10  * published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but WITHOUT
13  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
15  * more details.
16  *
17  * You should have received a copy of the GNU General Public License along with
18  * this program; if not, write to the Free Software Foundation, Inc.,
19  * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
20  *
21  * The full GNU General Public License is included in this distribution in the
22  * file called LICENSE.
23  *
24  * Contact Information:
25  *  Intel Linux Wireless <ilw@linux.intel.com>
26  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
27  *****************************************************************************/
28 
29 
30 #include <linux/kernel.h>
31 #include <linux/module.h>
32 #include <linux/slab.h>
33 #include <linux/init.h>
34 
35 #include <net/mac80211.h>
36 
37 #include "iwl-eeprom.h"
38 #include "iwl-dev.h"
39 #include "iwl-core.h"
40 #include "iwl-io.h"
41 #include "iwl-commands.h"
42 #include "iwl-debug.h"
43 #include "iwl-power.h"
44 
45 /*
46  * Setting power level allows the card to go to sleep when not busy.
47  *
48  * We calculate a sleep command based on the required latency, which
49  * we get from mac80211. In order to handle thermal throttling, we can
50  * also use pre-defined power levels.
51  */
52 
53 /*
54  * This defines the old power levels. They are still used by default
55  * (level 1) and for thermal throttle (levels 3 through 5)
56  */
57 
58 struct iwl_power_vec_entry {
59 	struct iwl_powertable_cmd cmd;
60 	u8 no_dtim;	/* number of skip dtim */
61 };
62 
iwl_legacy_power_sleep_cam_cmd(struct iwl_priv * priv,struct iwl_powertable_cmd * cmd)63 static void iwl_legacy_power_sleep_cam_cmd(struct iwl_priv *priv,
64 				    struct iwl_powertable_cmd *cmd)
65 {
66 	memset(cmd, 0, sizeof(*cmd));
67 
68 	if (priv->power_data.pci_pm)
69 		cmd->flags |= IWL_POWER_PCI_PM_MSK;
70 
71 	IWL_DEBUG_POWER(priv, "Sleep command for CAM\n");
72 }
73 
74 static int
iwl_legacy_set_power(struct iwl_priv * priv,struct iwl_powertable_cmd * cmd)75 iwl_legacy_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
76 {
77 	IWL_DEBUG_POWER(priv, "Sending power/sleep command\n");
78 	IWL_DEBUG_POWER(priv, "Flags value = 0x%08X\n", cmd->flags);
79 	IWL_DEBUG_POWER(priv, "Tx timeout = %u\n",
80 					le32_to_cpu(cmd->tx_data_timeout));
81 	IWL_DEBUG_POWER(priv, "Rx timeout = %u\n",
82 					le32_to_cpu(cmd->rx_data_timeout));
83 	IWL_DEBUG_POWER(priv,
84 			"Sleep interval vector = { %d , %d , %d , %d , %d }\n",
85 			le32_to_cpu(cmd->sleep_interval[0]),
86 			le32_to_cpu(cmd->sleep_interval[1]),
87 			le32_to_cpu(cmd->sleep_interval[2]),
88 			le32_to_cpu(cmd->sleep_interval[3]),
89 			le32_to_cpu(cmd->sleep_interval[4]));
90 
91 	return iwl_legacy_send_cmd_pdu(priv, POWER_TABLE_CMD,
92 				sizeof(struct iwl_powertable_cmd), cmd);
93 }
94 
95 int
iwl_legacy_power_set_mode(struct iwl_priv * priv,struct iwl_powertable_cmd * cmd,bool force)96 iwl_legacy_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
97 		       bool force)
98 {
99 	int ret;
100 	bool update_chains;
101 
102 	lockdep_assert_held(&priv->mutex);
103 
104 	/* Don't update the RX chain when chain noise calibration is running */
105 	update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
106 			priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;
107 
108 	if (!memcmp(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force)
109 		return 0;
110 
111 	if (!iwl_legacy_is_ready_rf(priv))
112 		return -EIO;
113 
114 	/* scan complete use sleep_power_next, need to be updated */
115 	memcpy(&priv->power_data.sleep_cmd_next, cmd, sizeof(*cmd));
116 	if (test_bit(STATUS_SCANNING, &priv->status) && !force) {
117 		IWL_DEBUG_INFO(priv, "Defer power set mode while scanning\n");
118 		return 0;
119 	}
120 
121 	if (cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)
122 		set_bit(STATUS_POWER_PMI, &priv->status);
123 
124 	ret = iwl_legacy_set_power(priv, cmd);
125 	if (!ret) {
126 		if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
127 			clear_bit(STATUS_POWER_PMI, &priv->status);
128 
129 		if (priv->cfg->ops->lib->update_chain_flags && update_chains)
130 			priv->cfg->ops->lib->update_chain_flags(priv);
131 		else if (priv->cfg->ops->lib->update_chain_flags)
132 			IWL_DEBUG_POWER(priv,
133 					"Cannot update the power, chain noise "
134 					"calibration running: %d\n",
135 					priv->chain_noise_data.state);
136 
137 		memcpy(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd));
138 	} else
139 		IWL_ERR(priv, "set power fail, ret = %d", ret);
140 
141 	return ret;
142 }
143 
iwl_legacy_power_update_mode(struct iwl_priv * priv,bool force)144 int iwl_legacy_power_update_mode(struct iwl_priv *priv, bool force)
145 {
146 	struct iwl_powertable_cmd cmd;
147 
148 	iwl_legacy_power_sleep_cam_cmd(priv, &cmd);
149 	return iwl_legacy_power_set_mode(priv, &cmd, force);
150 }
151 EXPORT_SYMBOL(iwl_legacy_power_update_mode);
152 
153 /* initialize to default */
iwl_legacy_power_initialize(struct iwl_priv * priv)154 void iwl_legacy_power_initialize(struct iwl_priv *priv)
155 {
156 	u16 lctl = iwl_legacy_pcie_link_ctl(priv);
157 
158 	priv->power_data.pci_pm = !(lctl & PCI_CFG_LINK_CTRL_VAL_L0S_EN);
159 
160 	priv->power_data.debug_sleep_level_override = -1;
161 
162 	memset(&priv->power_data.sleep_cmd, 0,
163 		sizeof(priv->power_data.sleep_cmd));
164 }
165 EXPORT_SYMBOL(iwl_legacy_power_initialize);
166