iwl-power.c 14.3 KB
Newer Older
M
Mohamed Abbas 已提交
1 2
/******************************************************************************
 *
W
Wey-Yi Guy 已提交
3
 * Copyright(c) 2007 - 2012 Intel Corporation. All rights reserved.
M
Mohamed Abbas 已提交
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
 *
 * Portions of this file are derived from the ipw3945 project, as well
 * as portions of the ieee80211 subsystem header files.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of version 2 of the GNU General Public License as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
 *
 * The full GNU General Public License is included in this distribution in the
 * file called LICENSE.
 *
 * Contact Information:
25
 *  Intel Linux Wireless <ilw@linux.intel.com>
M
Mohamed Abbas 已提交
26 27 28 29 30 31
 * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 *****************************************************************************/


#include <linux/kernel.h>
#include <linux/module.h>
32
#include <linux/slab.h>
M
Mohamed Abbas 已提交
33 34 35 36 37
#include <linux/init.h>

#include <net/mac80211.h>

#include "iwl-eeprom.h"
38
#include "iwl-dev.h"
39
#include "iwl-agn.h"
M
Mohamed Abbas 已提交
40
#include "iwl-core.h"
41
#include "iwl-io.h"
42
#include "iwl-commands.h"
M
Mohamed Abbas 已提交
43 44
#include "iwl-debug.h"
#include "iwl-power.h"
45
#include "iwl-trans.h"
46
#include "iwl-shared.h"
M
Mohamed Abbas 已提交
47 48

/*
49
 * Setting power level allows the card to go to sleep when not busy.
M
Mohamed Abbas 已提交
50
 *
51 52 53
 * 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.
M
Mohamed Abbas 已提交
54 55
 */

56 57 58 59 60 61 62
/*
 * This defines the old power levels. They are still used by default
 * (level 1) and for thermal throttle (levels 3 through 5)
 */

struct iwl_power_vec_entry {
	struct iwl_powertable_cmd cmd;
W
Wey-Yi Guy 已提交
63
	u8 no_dtim;	/* number of skip dtim */
64 65 66 67
};

#define IWL_DTIM_RANGE_0_MAX	2
#define IWL_DTIM_RANGE_1_MAX	10
M
Mohamed Abbas 已提交
68

J
Johannes Berg 已提交
69 70
#define NOSLP cpu_to_le16(0), 0, 0
#define SLP IWL_POWER_DRIVER_ALLOW_SLEEP_MSK, 0, 0
71 72 73 74
#define ASLP (IWL_POWER_POWER_SAVE_ENA_MSK |	\
		IWL_POWER_POWER_MANAGEMENT_ENA_MSK | \
		IWL_POWER_ADVANCE_PM_ENA_MSK)
#define ASLP_TOUT(T) cpu_to_le32(T)
J
Johannes Berg 已提交
75 76 77 78 79 80 81
#define TU_TO_USEC 1024
#define SLP_TOUT(T) cpu_to_le32((T) * TU_TO_USEC)
#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)}
M
Mohamed Abbas 已提交
82
/* default power management (not Tx power) table values */
83
/* for DTIM period 0 through IWL_DTIM_RANGE_0_MAX */
W
Wey-Yi Guy 已提交
84
/* DTIM 0 - 2 */
J
Johannes Berg 已提交
85
static const struct iwl_power_vec_entry range_0[IWL_POWER_NUM] = {
W
Wey-Yi Guy 已提交
86
	{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 1, 2, 2, 0xFF)}, 0},
M
Mohamed Abbas 已提交
87 88 89 90 91 92 93
	{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 2, 2, 0xFF)}, 0},
	{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 2, 2, 2, 0xFF)}, 0},
	{{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 2, 4, 4, 0xFF)}, 1},
	{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 2, 4, 6, 0xFF)}, 2}
};


94
/* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */
W
Wey-Yi Guy 已提交
95
/* DTIM 3 - 10 */
J
Johannes Berg 已提交
96
static const struct iwl_power_vec_entry range_1[IWL_POWER_NUM] = {
M
Mohamed Abbas 已提交
97 98 99 100
	{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 4)}, 0},
	{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(1, 2, 3, 4, 7)}, 0},
	{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 4, 6, 7, 9)}, 0},
	{{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 4, 6, 9, 10)}, 1},
W
Wey-Yi Guy 已提交
101
	{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(2, 4, 6, 10, 10)}, 2}
M
Mohamed Abbas 已提交
102 103
};

104
/* for DTIM period > IWL_DTIM_RANGE_1_MAX */
W
Wey-Yi Guy 已提交
105
/* DTIM 11 - */
J
Johannes Berg 已提交
106
static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
M
Mohamed Abbas 已提交
107 108 109 110 111 112 113
	{{SLP, SLP_TOUT(200), SLP_TOUT(500), SLP_VEC(1, 2, 3, 4, 0xFF)}, 0},
	{{SLP, SLP_TOUT(200), SLP_TOUT(300), SLP_VEC(2, 4, 6, 7, 0xFF)}, 0},
	{{SLP, SLP_TOUT(50), SLP_TOUT(100), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0},
	{{SLP, SLP_TOUT(50), SLP_TOUT(25), SLP_VEC(2, 7, 9, 9, 0xFF)}, 0},
	{{SLP, SLP_TOUT(25), SLP_TOUT(25), SLP_VEC(4, 7, 10, 10, 0xFF)}, 0}
};

114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
/* advance power management */
/* DTIM 0 - 2 */
static const struct iwl_power_vec_entry apm_range_0[IWL_POWER_NUM] = {
	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
		SLP_VEC(1, 2, 6, 8, 0xFF), ASLP_TOUT(2)}, 2}
};


/* for DTIM period IWL_DTIM_RANGE_0_MAX + 1 through IWL_DTIM_RANGE_1_MAX */
/* DTIM 3 - 10 */
static const struct iwl_power_vec_entry apm_range_1[IWL_POWER_NUM] = {
	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
		SLP_VEC(1, 2, 6, 8, 0xFF), 0}, 2}
};

/* for DTIM period > IWL_DTIM_RANGE_1_MAX */
/* DTIM 11 - */
static const struct iwl_power_vec_entry apm_range_2[IWL_POWER_NUM] = {
	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
		SLP_VEC(1, 2, 4, 6, 0xFF), 0}, 0},
	{{ASLP, 0, 0, ASLP_TOUT(50), ASLP_TOUT(50),
		SLP_VEC(1, 2, 6, 8, 0xFF), ASLP_TOUT(2)}, 2}
};

160 161 162 163 164
static void iwl_static_sleep_cmd(struct iwl_priv *priv,
				 struct iwl_powertable_cmd *cmd,
				 enum iwl_power_level lvl, int period)
{
	const struct iwl_power_vec_entry *table;
W
Wey-Yi Guy 已提交
165 166 167 168
	int max_sleep[IWL_POWER_VEC_SIZE] = { 0 };
	int i;
	u8 skip;
	u32 slp_itrvl;
169

170
	if (cfg(priv)->adv_pm) {
171 172 173 174 175 176 177 178 179 180 181 182
		table = apm_range_2;
		if (period <= IWL_DTIM_RANGE_1_MAX)
			table = apm_range_1;
		if (period <= IWL_DTIM_RANGE_0_MAX)
			table = apm_range_0;
	} else {
		table = range_2;
		if (period <= IWL_DTIM_RANGE_1_MAX)
			table = range_1;
		if (period <= IWL_DTIM_RANGE_0_MAX)
			table = range_0;
	}
183

184 185 186 187
	if (WARN_ON(lvl < 0 || lvl >= IWL_POWER_NUM))
		memset(cmd, 0, sizeof(*cmd));
	else
		*cmd = table[lvl].cmd;
188 189

	if (period == 0) {
W
Wey-Yi Guy 已提交
190
		skip = 0;
191
		period = 1;
W
Wey-Yi Guy 已提交
192 193 194
		for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
			max_sleep[i] =  1;

195
	} else {
W
Wey-Yi Guy 已提交
196 197 198 199
		skip = table[lvl].no_dtim;
		for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
			max_sleep[i] = le32_to_cpu(cmd->sleep_interval[i]);
		max_sleep[IWL_POWER_VEC_SIZE - 1] = skip + 1;
200 201
	}

W
Wey-Yi Guy 已提交
202 203 204 205 206 207 208 209 210 211 212 213
	slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]);
	/* figure out the listen interval based on dtim period and skip */
	if (slp_itrvl == 0xFF)
		cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] =
			cpu_to_le32(period * (skip + 1));

	slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]);
	if (slp_itrvl > period)
		cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] =
			cpu_to_le32((slp_itrvl / period) * period);

	if (skip)
214
		cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK;
W
Wey-Yi Guy 已提交
215
	else
216 217
		cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;

218
	if (hw_params(priv).shadow_reg_enable)
219 220 221 222
		cmd->flags |= IWL_POWER_SHADOW_REG_ENA;
	else
		cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;

223
	if (iwl_advanced_bt_coexist(priv)) {
224
		if (!cfg(priv)->bt_params->bt_sco_disable)
225 226 227 228 229 230
			cmd->flags |= IWL_POWER_BT_SCO_ENA;
		else
			cmd->flags &= ~IWL_POWER_BT_SCO_ENA;
	}


W
Wey-Yi Guy 已提交
231
	slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]);
W
Wey-Yi Guy 已提交
232
	if (slp_itrvl > IWL_CONN_MAX_LISTEN_INTERVAL)
W
Wey-Yi Guy 已提交
233
		cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] =
W
Wey-Yi Guy 已提交
234
			cpu_to_le32(IWL_CONN_MAX_LISTEN_INTERVAL);
W
Wey-Yi Guy 已提交
235 236 237 238 239 240 241 242 243 244 245 246 247 248

	/* enforce max sleep interval */
	for (i = IWL_POWER_VEC_SIZE - 1; i >= 0 ; i--) {
		if (le32_to_cpu(cmd->sleep_interval[i]) >
		    (max_sleep[i] * period))
			cmd->sleep_interval[i] =
				cpu_to_le32(max_sleep[i] * period);
		if (i != (IWL_POWER_VEC_SIZE - 1)) {
			if (le32_to_cpu(cmd->sleep_interval[i]) >
			    le32_to_cpu(cmd->sleep_interval[i+1]))
				cmd->sleep_interval[i] =
					cmd->sleep_interval[i+1];
		}
	}
249

250
	if (priv->power_data.bus_pm)
251 252 253 254
		cmd->flags |= IWL_POWER_PCI_PM_MSK;
	else
		cmd->flags &= ~IWL_POWER_PCI_PM_MSK;

W
Wey-Yi Guy 已提交
255 256
	IWL_DEBUG_POWER(priv, "numSkipDtim = %u, dtimPeriod = %d\n",
			skip, period);
257 258 259 260 261
	IWL_DEBUG_POWER(priv, "Sleep command for index %d\n", lvl + 1);
}

static void iwl_power_sleep_cam_cmd(struct iwl_priv *priv,
				    struct iwl_powertable_cmd *cmd)
M
Mohamed Abbas 已提交
262
{
263
	memset(cmd, 0, sizeof(*cmd));
M
Mohamed Abbas 已提交
264

265
	if (priv->power_data.bus_pm)
266
		cmd->flags |= IWL_POWER_PCI_PM_MSK;
M
Mohamed Abbas 已提交
267

268
	IWL_DEBUG_POWER(priv, "Sleep command for CAM\n");
M
Mohamed Abbas 已提交
269 270
}

271 272 273
static void iwl_power_fill_sleep_cmd(struct iwl_priv *priv,
				     struct iwl_powertable_cmd *cmd,
				     int dynps_ms, int wakeup_period)
M
Mohamed Abbas 已提交
274
{
275 276 277 278 279 280 281 282 283 284 285 286 287 288
	/*
	 * These are the original power level 3 sleep successions. The
	 * device may behave better with such succession and was also
	 * only tested with that. Just like the original sleep commands,
	 * also adjust the succession here to the wakeup_period below.
	 * The ranges are the same as for the sleep commands, 0-2, 3-9
	 * and >10, which is selected based on the DTIM interval for
	 * the sleep index but here we use the wakeup period since that
	 * is what we need to do for the latency requirements.
	 */
	static const u8 slp_succ_r0[IWL_POWER_VEC_SIZE] = { 2, 2, 2, 2, 2 };
	static const u8 slp_succ_r1[IWL_POWER_VEC_SIZE] = { 2, 4, 6, 7, 9 };
	static const u8 slp_succ_r2[IWL_POWER_VEC_SIZE] = { 2, 7, 9, 9, 0xFF };
	const u8 *slp_succ = slp_succ_r0;
289
	int i;
M
Mohamed Abbas 已提交
290

291 292 293 294 295
	if (wakeup_period > IWL_DTIM_RANGE_0_MAX)
		slp_succ = slp_succ_r1;
	if (wakeup_period > IWL_DTIM_RANGE_1_MAX)
		slp_succ = slp_succ_r2;

296
	memset(cmd, 0, sizeof(*cmd));
297

298 299
	cmd->flags = IWL_POWER_DRIVER_ALLOW_SLEEP_MSK |
		     IWL_POWER_FAST_PD; /* no use seeing frames for others */
M
Mohamed Abbas 已提交
300

301
	if (priv->power_data.bus_pm)
302
		cmd->flags |= IWL_POWER_PCI_PM_MSK;
M
Mohamed Abbas 已提交
303

304
	if (hw_params(priv).shadow_reg_enable)
305 306 307 308
		cmd->flags |= IWL_POWER_SHADOW_REG_ENA;
	else
		cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;

309
	if (iwl_advanced_bt_coexist(priv)) {
310
		if (!cfg(priv)->bt_params->bt_sco_disable)
311 312 313 314 315
			cmd->flags |= IWL_POWER_BT_SCO_ENA;
		else
			cmd->flags &= ~IWL_POWER_BT_SCO_ENA;
	}

316 317
	cmd->rx_data_timeout = cpu_to_le32(1000 * dynps_ms);
	cmd->tx_data_timeout = cpu_to_le32(1000 * dynps_ms);
M
Mohamed Abbas 已提交
318

319
	for (i = 0; i < IWL_POWER_VEC_SIZE; i++)
320 321
		cmd->sleep_interval[i] =
			cpu_to_le32(min_t(int, slp_succ[i], wakeup_period));
322 323 324

	IWL_DEBUG_POWER(priv, "Automatic sleep command\n");
}
M
Mohamed Abbas 已提交
325

326 327 328
static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
{
	IWL_DEBUG_POWER(priv, "Sending power/sleep command\n");
329 330 331 332
	IWL_DEBUG_POWER(priv, "Flags value = 0x%08X\n", cmd->flags);
	IWL_DEBUG_POWER(priv, "Tx timeout = %u\n", le32_to_cpu(cmd->tx_data_timeout));
	IWL_DEBUG_POWER(priv, "Rx timeout = %u\n", le32_to_cpu(cmd->rx_data_timeout));
	IWL_DEBUG_POWER(priv, "Sleep interval vector = { %d , %d , %d , %d , %d }\n",
M
Mohamed Abbas 已提交
333 334 335 336 337 338
			le32_to_cpu(cmd->sleep_interval[0]),
			le32_to_cpu(cmd->sleep_interval[1]),
			le32_to_cpu(cmd->sleep_interval[2]),
			le32_to_cpu(cmd->sleep_interval[3]),
			le32_to_cpu(cmd->sleep_interval[4]));

339
	return iwl_dvm_send_cmd_pdu(priv, POWER_TABLE_CMD, CMD_SYNC,
340
				sizeof(struct iwl_powertable_cmd), cmd);
M
Mohamed Abbas 已提交
341 342
}

343 344
static void iwl_power_build_cmd(struct iwl_priv *priv,
				struct iwl_powertable_cmd *cmd)
M
Mohamed Abbas 已提交
345
{
346
	bool enabled = priv->hw->conf.flags & IEEE80211_CONF_PS;
347
	int dtimper;
M
Mohamed Abbas 已提交
348

349
	dtimper = priv->hw->conf.ps_dtim_period ?: 1;
350

351
	if (priv->wowlan)
J
Johannes Berg 已提交
352
		iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper);
353
	else if (!cfg(priv)->base_params->no_idle_support &&
354
		 priv->hw->conf.flags & IEEE80211_CONF_IDLE)
355
		iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20);
356
	else if (iwl_tt_is_low_power_state(priv)) {
357
		/* in thermal throttling low power state */
358
		iwl_static_sleep_cmd(priv, cmd,
359
		    iwl_tt_current_power_mode(priv), dtimper);
360
	} else if (!enabled)
361
		iwl_power_sleep_cam_cmd(priv, cmd);
362
	else if (priv->power_data.debug_sleep_level_override >= 0)
363
		iwl_static_sleep_cmd(priv, cmd,
364 365
				     priv->power_data.debug_sleep_level_override,
				     dtimper);
366 367 368 369 370 371 372 373 374
	else if (iwlagn_mod_params.no_sleep_autoadjust) {
		if (iwlagn_mod_params.power_level > IWL_POWER_INDEX_1 &&
		    iwlagn_mod_params.power_level <= IWL_POWER_INDEX_5)
			iwl_static_sleep_cmd(priv, cmd,
				iwlagn_mod_params.power_level, dtimper);
		else
			iwl_static_sleep_cmd(priv, cmd,
				IWL_POWER_INDEX_1, dtimper);
	} else
375
		iwl_power_fill_sleep_cmd(priv, cmd,
376 377
					 priv->hw->conf.dynamic_ps_timeout,
					 priv->hw->conf.max_sleep_period);
378 379 380 381 382 383 384 385
}

int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
		       bool force)
{
	int ret;
	bool update_chains;

386
	lockdep_assert_held(&priv->shrd->mutex);
387 388 389 390 391 392 393 394

	/* Don't update the RX chain when chain noise calibration is running */
	update_chains = priv->chain_noise_data.state == IWL_CHAIN_NOISE_DONE ||
			priv->chain_noise_data.state == IWL_CHAIN_NOISE_ALIVE;

	if (!memcmp(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd)) && !force)
		return 0;

395
	if (!iwl_is_ready_rf(priv->shrd))
396 397 398 399
		return -EIO;

	/* scan complete use sleep_power_next, need to be updated */
	memcpy(&priv->power_data.sleep_cmd_next, cmd, sizeof(*cmd));
400
	if (test_bit(STATUS_SCANNING, &priv->shrd->status) && !force) {
401 402 403 404 405
		IWL_DEBUG_INFO(priv, "Defer power set mode while scanning\n");
		return 0;
	}

	if (cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK)
406
		set_bit(STATUS_POWER_PMI, &priv->shrd->status);
M
Mohamed Abbas 已提交
407

408 409 410
	ret = iwl_set_power(priv, cmd);
	if (!ret) {
		if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
411
			clear_bit(STATUS_POWER_PMI, &priv->shrd->status);
412

413 414 415
		if (update_chains)
			iwl_update_chain_flags(priv);
		else
416
			IWL_DEBUG_POWER(priv,
417
					"Cannot update the power, chain noise "
418 419
					"calibration running: %d\n",
					priv->chain_noise_data.state);
420 421 422 423

		memcpy(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd));
	} else
		IWL_ERR(priv, "set power fail, ret = %d", ret);
M
Mohamed Abbas 已提交
424 425 426

	return ret;
}
427 428 429 430 431 432 433 434

int iwl_power_update_mode(struct iwl_priv *priv, bool force)
{
	struct iwl_powertable_cmd cmd;

	iwl_power_build_cmd(priv, &cmd);
	return iwl_power_set_mode(priv, &cmd, force);
}
M
Mohamed Abbas 已提交
435

T
Tomas Winkler 已提交
436
/* initialize to default */
M
Mohamed Abbas 已提交
437 438
void iwl_power_initialize(struct iwl_priv *priv)
{
439
	priv->power_data.bus_pm = trans(priv)->pm_support;
440 441 442 443 444

	priv->power_data.debug_sleep_level_override = -1;

	memset(&priv->power_data.sleep_cmd, 0,
		sizeof(priv->power_data.sleep_cmd));
M
Mohamed Abbas 已提交
445
}