iwl-power.c 14.3 KB
Newer Older
M
Mohamed Abbas 已提交
1 2
/******************************************************************************
 *
W
Wey-Yi Guy 已提交
3
 * Copyright(c) 2007 - 2011 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"
M
Mohamed Abbas 已提交
46 47

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

55 56 57 58 59 60 61
/*
 * 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 已提交
62
	u8 no_dtim;	/* number of skip dtim */
63 64 65 66
};

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

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


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

103
/* for DTIM period > IWL_DTIM_RANGE_1_MAX */
W
Wey-Yi Guy 已提交
104
/* DTIM 11 - */
J
Johannes Berg 已提交
105
static const struct iwl_power_vec_entry range_2[IWL_POWER_NUM] = {
M
Mohamed Abbas 已提交
106 107 108 109 110 111 112
	{{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}
};

113 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
/* 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}
};

159 160 161 162 163
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 已提交
164 165 166 167
	int max_sleep[IWL_POWER_VEC_SIZE] = { 0 };
	int i;
	u8 skip;
	u32 slp_itrvl;
168

169 170 171 172 173 174 175 176 177 178 179 180 181
	if (priv->cfg->adv_pm) {
		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;
	}
182

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

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

194
	} else {
W
Wey-Yi Guy 已提交
195 196 197 198
		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;
199 200
	}

W
Wey-Yi Guy 已提交
201 202 203 204 205 206 207 208 209 210 211 212
	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)
213
		cmd->flags |= IWL_POWER_SLEEP_OVER_DTIM_MSK;
W
Wey-Yi Guy 已提交
214
	else
215 216
		cmd->flags &= ~IWL_POWER_SLEEP_OVER_DTIM_MSK;

217 218 219 220 221
	if (priv->cfg->base_params->shadow_reg_enable)
		cmd->flags |= IWL_POWER_SHADOW_REG_ENA;
	else
		cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;

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


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

	/* 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];
		}
	}
248

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

W
Wey-Yi Guy 已提交
254 255
	IWL_DEBUG_POWER(priv, "numSkipDtim = %u, dtimPeriod = %d\n",
			skip, period);
256 257 258 259 260
	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 已提交
261
{
262
	memset(cmd, 0, sizeof(*cmd));
M
Mohamed Abbas 已提交
263

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

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

270 271 272
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 已提交
273
{
274 275 276 277 278 279 280 281 282 283 284 285 286 287
	/*
	 * 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;
288
	int i;
M
Mohamed Abbas 已提交
289

290 291 292 293 294
	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;

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

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

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

303 304 305 306 307
	if (priv->cfg->base_params->shadow_reg_enable)
		cmd->flags |= IWL_POWER_SHADOW_REG_ENA;
	else
		cmd->flags &= ~IWL_POWER_SHADOW_REG_ENA;

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

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

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

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

325 326 327
static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
{
	IWL_DEBUG_POWER(priv, "Sending power/sleep command\n");
328 329 330 331
	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 已提交
332 333 334 335 336 337
			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]));

338
	return trans_send_cmd_pdu(&priv->trans, POWER_TABLE_CMD, CMD_SYNC,
339
				sizeof(struct iwl_powertable_cmd), cmd);
M
Mohamed Abbas 已提交
340 341
}

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

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

J
Johannes Berg 已提交
350 351
	if (priv->wowlan)
		iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, dtimper);
352 353
	else if (!priv->cfg->base_params->no_idle_support &&
		 priv->hw->conf.flags & IEEE80211_CONF_IDLE)
354
		iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20);
355
	else if (iwl_tt_is_low_power_state(priv)) {
356
		/* in thermal throttling low power state */
357
		iwl_static_sleep_cmd(priv, cmd,
358
		    iwl_tt_current_power_mode(priv), dtimper);
359
	} else if (!enabled)
360
		iwl_power_sleep_cam_cmd(priv, cmd);
361
	else if (priv->power_data.debug_sleep_level_override >= 0)
362
		iwl_static_sleep_cmd(priv, cmd,
363 364
				     priv->power_data.debug_sleep_level_override,
				     dtimper);
365 366 367 368 369 370 371 372 373
	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
374
		iwl_power_fill_sleep_cmd(priv, cmd,
375 376
					 priv->hw->conf.dynamic_ps_timeout,
					 priv->hw->conf.max_sleep_period);
377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405
}

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

	lockdep_assert_held(&priv->mutex);

	/* 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;

	if (!iwl_is_ready_rf(priv))
		return -EIO;

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

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

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

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

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

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

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 已提交
434

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

	priv->power_data.debug_sleep_level_override = -1;

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