iwl-power.c 14.0 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 45 46
#include "iwl-debug.h"
#include "iwl-power.h"

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

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

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

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


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

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

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

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

168 169 170 171 172 173 174 175 176 177 178 179 180
	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;
	}
181

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

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

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

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

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

221
	if (iwl_advanced_bt_coexist(priv)) {
222 223 224 225 226 227 228
		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 已提交
229
	slp_itrvl = le32_to_cpu(cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1]);
W
Wey-Yi Guy 已提交
230
	if (slp_itrvl > IWL_CONN_MAX_LISTEN_INTERVAL)
W
Wey-Yi Guy 已提交
231
		cmd->sleep_interval[IWL_POWER_VEC_SIZE - 1] =
W
Wey-Yi Guy 已提交
232
			cpu_to_le32(IWL_CONN_MAX_LISTEN_INTERVAL);
W
Wey-Yi Guy 已提交
233 234 235 236 237 238 239 240 241 242 243 244 245 246

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

337 338
	return iwl_send_cmd_pdu(priv, POWER_TABLE_CMD,
				sizeof(struct iwl_powertable_cmd), cmd);
M
Mohamed Abbas 已提交
339 340
}

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

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

349
	if (priv->hw->conf.flags & IEEE80211_CONF_IDLE)
350
		iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_5, 20);
351
	else if (iwl_tt_is_low_power_state(priv)) {
352
		/* in thermal throttling low power state */
353
		iwl_static_sleep_cmd(priv, cmd,
354
		    iwl_tt_current_power_mode(priv), dtimper);
355
	} else if (!enabled)
356
		iwl_power_sleep_cam_cmd(priv, cmd);
357
	else if (priv->power_data.debug_sleep_level_override >= 0)
358
		iwl_static_sleep_cmd(priv, cmd,
359 360
				     priv->power_data.debug_sleep_level_override,
				     dtimper);
361
	else if (iwlagn_mod_params.no_sleep_autoadjust)
362
		iwl_static_sleep_cmd(priv, cmd, IWL_POWER_INDEX_1, dtimper);
363
	else
364
		iwl_power_fill_sleep_cmd(priv, cmd,
365 366
					 priv->hw->conf.dynamic_ps_timeout,
					 priv->hw->conf.max_sleep_period);
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395
}

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

397 398 399 400 401 402 403 404 405
	ret = iwl_set_power(priv, cmd);
	if (!ret) {
		if (!(cmd->flags & IWL_POWER_DRIVER_ALLOW_SLEEP_MSK))
			clear_bit(STATUS_POWER_PMI, &priv->status);

		if (priv->cfg->ops->lib->update_chain_flags && update_chains)
			priv->cfg->ops->lib->update_chain_flags(priv);
		else if (priv->cfg->ops->lib->update_chain_flags)
			IWL_DEBUG_POWER(priv,
406
					"Cannot update the power, chain noise "
407 408
					"calibration running: %d\n",
					priv->chain_noise_data.state);
409 410 411 412

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

	return ret;
}
416 417 418 419 420 421 422 423

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

T
Tomas Winkler 已提交
425
/* initialize to default */
M
Mohamed Abbas 已提交
426 427
void iwl_power_initialize(struct iwl_priv *priv)
{
428
	priv->power_data.bus_pm = priv->bus.ops->get_pm_support(&priv->bus);
429 430 431 432 433

	priv->power_data.debug_sleep_level_override = -1;

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