12a2786edSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2e705c121SKalle Valo /******************************************************************************
3e705c121SKalle Valo  *
4e705c121SKalle Valo  * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved.
5e705c121SKalle Valo  * Copyright(c) 2015 Intel Deutschland GmbH
6e705c121SKalle Valo  *****************************************************************************/
7e705c121SKalle Valo 
8e705c121SKalle Valo #include <linux/kernel.h>
9e705c121SKalle Valo 
10e705c121SKalle Valo #include "iwl-io.h"
11e705c121SKalle Valo #include "iwl-agn-hw.h"
12e705c121SKalle Valo #include "iwl-trans.h"
13e705c121SKalle Valo #include "iwl-fh.h"
14e705c121SKalle Valo #include "iwl-op-mode.h"
15e705c121SKalle Valo 
16e705c121SKalle Valo #include "dev.h"
17e705c121SKalle Valo #include "agn.h"
18e705c121SKalle Valo #include "calib.h"
19e705c121SKalle Valo 
20e705c121SKalle Valo /******************************************************************************
21e705c121SKalle Valo  *
22e705c121SKalle Valo  * uCode download functions
23e705c121SKalle Valo  *
24e705c121SKalle Valo  ******************************************************************************/
25e705c121SKalle Valo 
26e705c121SKalle Valo /*
27e705c121SKalle Valo  *  Calibration
28e705c121SKalle Valo  */
iwl_set_Xtal_calib(struct iwl_priv * priv)29e705c121SKalle Valo static int iwl_set_Xtal_calib(struct iwl_priv *priv)
30e705c121SKalle Valo {
31e705c121SKalle Valo 	struct iwl_calib_xtal_freq_cmd cmd;
32e705c121SKalle Valo 	__le16 *xtal_calib = priv->nvm_data->xtal_calib;
33e705c121SKalle Valo 
34e705c121SKalle Valo 	iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD);
35e705c121SKalle Valo 	cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]);
36e705c121SKalle Valo 	cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]);
37e705c121SKalle Valo 	return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd));
38e705c121SKalle Valo }
39e705c121SKalle Valo 
iwl_set_temperature_offset_calib(struct iwl_priv * priv)40e705c121SKalle Valo static int iwl_set_temperature_offset_calib(struct iwl_priv *priv)
41e705c121SKalle Valo {
42e705c121SKalle Valo 	struct iwl_calib_temperature_offset_cmd cmd;
43e705c121SKalle Valo 
44e705c121SKalle Valo 	memset(&cmd, 0, sizeof(cmd));
45e705c121SKalle Valo 	iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
46e705c121SKalle Valo 	cmd.radio_sensor_offset = priv->nvm_data->raw_temperature;
47e705c121SKalle Valo 	if (!(cmd.radio_sensor_offset))
48e705c121SKalle Valo 		cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET;
49e705c121SKalle Valo 
50e705c121SKalle Valo 	IWL_DEBUG_CALIB(priv, "Radio sensor offset: %d\n",
51e705c121SKalle Valo 			le16_to_cpu(cmd.radio_sensor_offset));
52e705c121SKalle Valo 	return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd));
53e705c121SKalle Valo }
54e705c121SKalle Valo 
iwl_set_temperature_offset_calib_v2(struct iwl_priv * priv)55e705c121SKalle Valo static int iwl_set_temperature_offset_calib_v2(struct iwl_priv *priv)
56e705c121SKalle Valo {
57e705c121SKalle Valo 	struct iwl_calib_temperature_offset_v2_cmd cmd;
58e705c121SKalle Valo 
59e705c121SKalle Valo 	memset(&cmd, 0, sizeof(cmd));
60e705c121SKalle Valo 	iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
61e705c121SKalle Valo 	cmd.radio_sensor_offset_high = priv->nvm_data->kelvin_temperature;
62e705c121SKalle Valo 	cmd.radio_sensor_offset_low = priv->nvm_data->raw_temperature;
63e705c121SKalle Valo 	if (!cmd.radio_sensor_offset_low) {
64e705c121SKalle Valo 		IWL_DEBUG_CALIB(priv, "no info in EEPROM, use default\n");
65e705c121SKalle Valo 		cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET;
66e705c121SKalle Valo 		cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET;
67e705c121SKalle Valo 	}
68e705c121SKalle Valo 	cmd.burntVoltageRef = priv->nvm_data->calib_voltage;
69e705c121SKalle Valo 
70e705c121SKalle Valo 	IWL_DEBUG_CALIB(priv, "Radio sensor offset high: %d\n",
71e705c121SKalle Valo 			le16_to_cpu(cmd.radio_sensor_offset_high));
72e705c121SKalle Valo 	IWL_DEBUG_CALIB(priv, "Radio sensor offset low: %d\n",
73e705c121SKalle Valo 			le16_to_cpu(cmd.radio_sensor_offset_low));
74e705c121SKalle Valo 	IWL_DEBUG_CALIB(priv, "Voltage Ref: %d\n",
75e705c121SKalle Valo 			le16_to_cpu(cmd.burntVoltageRef));
76e705c121SKalle Valo 
77e705c121SKalle Valo 	return iwl_calib_set(priv, (void *)&cmd, sizeof(cmd));
78e705c121SKalle Valo }
79e705c121SKalle Valo 
iwl_send_calib_cfg(struct iwl_priv * priv)80e705c121SKalle Valo static int iwl_send_calib_cfg(struct iwl_priv *priv)
81e705c121SKalle Valo {
82e705c121SKalle Valo 	struct iwl_calib_cfg_cmd calib_cfg_cmd;
83e705c121SKalle Valo 	struct iwl_host_cmd cmd = {
84e705c121SKalle Valo 		.id = CALIBRATION_CFG_CMD,
85e705c121SKalle Valo 		.len = { sizeof(struct iwl_calib_cfg_cmd), },
86e705c121SKalle Valo 		.data = { &calib_cfg_cmd, },
87e705c121SKalle Valo 	};
88e705c121SKalle Valo 
89e705c121SKalle Valo 	memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd));
90e705c121SKalle Valo 	calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL;
91e705c121SKalle Valo 	calib_cfg_cmd.ucd_calib_cfg.once.start = IWL_CALIB_INIT_CFG_ALL;
92e705c121SKalle Valo 	calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL;
93e705c121SKalle Valo 	calib_cfg_cmd.ucd_calib_cfg.flags =
94e705c121SKalle Valo 		IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK;
95e705c121SKalle Valo 
96e705c121SKalle Valo 	return iwl_dvm_send_cmd(priv, &cmd);
97e705c121SKalle Valo }
98e705c121SKalle Valo 
iwl_init_alive_start(struct iwl_priv * priv)99e705c121SKalle Valo int iwl_init_alive_start(struct iwl_priv *priv)
100e705c121SKalle Valo {
101e705c121SKalle Valo 	int ret;
102e705c121SKalle Valo 
103e705c121SKalle Valo 	if (priv->lib->bt_params &&
104e705c121SKalle Valo 	    priv->lib->bt_params->advanced_bt_coexist) {
105e705c121SKalle Valo 		/*
106e705c121SKalle Valo 		 * Tell uCode we are ready to perform calibration
107e705c121SKalle Valo 		 * need to perform this before any calibration
108e705c121SKalle Valo 		 * no need to close the envlope since we are going
109e705c121SKalle Valo 		 * to load the runtime uCode later.
110e705c121SKalle Valo 		 */
111e705c121SKalle Valo 		ret = iwl_send_bt_env(priv, IWL_BT_COEX_ENV_OPEN,
112e705c121SKalle Valo 			BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
113e705c121SKalle Valo 		if (ret)
114e705c121SKalle Valo 			return ret;
115e705c121SKalle Valo 
116e705c121SKalle Valo 	}
117e705c121SKalle Valo 
118e705c121SKalle Valo 	ret = iwl_send_calib_cfg(priv);
119e705c121SKalle Valo 	if (ret)
120e705c121SKalle Valo 		return ret;
121e705c121SKalle Valo 
122e705c121SKalle Valo 	/**
123e705c121SKalle Valo 	 * temperature offset calibration is only needed for runtime ucode,
124e705c121SKalle Valo 	 * so prepare the value now.
125e705c121SKalle Valo 	 */
126e705c121SKalle Valo 	if (priv->lib->need_temp_offset_calib) {
127e705c121SKalle Valo 		if (priv->lib->temp_offset_v2)
128e705c121SKalle Valo 			return iwl_set_temperature_offset_calib_v2(priv);
129e705c121SKalle Valo 		else
130e705c121SKalle Valo 			return iwl_set_temperature_offset_calib(priv);
131e705c121SKalle Valo 	}
132e705c121SKalle Valo 
133e705c121SKalle Valo 	return 0;
134e705c121SKalle Valo }
135e705c121SKalle Valo 
iwl_send_wimax_coex(struct iwl_priv * priv)136e705c121SKalle Valo static int iwl_send_wimax_coex(struct iwl_priv *priv)
137e705c121SKalle Valo {
138e705c121SKalle Valo 	struct iwl_wimax_coex_cmd coex_cmd;
139e705c121SKalle Valo 
140e705c121SKalle Valo 	/* coexistence is disabled */
141e705c121SKalle Valo 	memset(&coex_cmd, 0, sizeof(coex_cmd));
142e705c121SKalle Valo 
143e705c121SKalle Valo 	return iwl_dvm_send_cmd_pdu(priv,
144e705c121SKalle Valo 				COEX_PRIORITY_TABLE_CMD, 0,
145e705c121SKalle Valo 				sizeof(coex_cmd), &coex_cmd);
146e705c121SKalle Valo }
147e705c121SKalle Valo 
148e705c121SKalle Valo static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
149e705c121SKalle Valo 	((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
150e705c121SKalle Valo 		(0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
151e705c121SKalle Valo 	((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
152e705c121SKalle Valo 		(1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
153e705c121SKalle Valo 	((BT_COEX_PRIO_TBL_PRIO_LOW << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
154e705c121SKalle Valo 		(0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
155e705c121SKalle Valo 	((BT_COEX_PRIO_TBL_PRIO_LOW << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
156e705c121SKalle Valo 		(1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
157e705c121SKalle Valo 	((BT_COEX_PRIO_TBL_PRIO_HIGH << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
158e705c121SKalle Valo 		(0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
159e705c121SKalle Valo 	((BT_COEX_PRIO_TBL_PRIO_HIGH << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
160e705c121SKalle Valo 		(1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
161e705c121SKalle Valo 	((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
162e705c121SKalle Valo 		(0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
163e705c121SKalle Valo 	((BT_COEX_PRIO_TBL_PRIO_COEX_OFF << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
164e705c121SKalle Valo 		(0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
165e705c121SKalle Valo 	((BT_COEX_PRIO_TBL_PRIO_COEX_ON << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
166e705c121SKalle Valo 		(0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
167e705c121SKalle Valo 	0, 0, 0, 0, 0, 0, 0
168e705c121SKalle Valo };
169e705c121SKalle Valo 
iwl_send_prio_tbl(struct iwl_priv * priv)170e705c121SKalle Valo void iwl_send_prio_tbl(struct iwl_priv *priv)
171e705c121SKalle Valo {
172e705c121SKalle Valo 	struct iwl_bt_coex_prio_table_cmd prio_tbl_cmd;
173e705c121SKalle Valo 
174e705c121SKalle Valo 	memcpy(prio_tbl_cmd.prio_tbl, iwl_bt_prio_tbl,
175e705c121SKalle Valo 		sizeof(iwl_bt_prio_tbl));
176e705c121SKalle Valo 	if (iwl_dvm_send_cmd_pdu(priv,
177e705c121SKalle Valo 				REPLY_BT_COEX_PRIO_TABLE, 0,
178e705c121SKalle Valo 				sizeof(prio_tbl_cmd), &prio_tbl_cmd))
179e705c121SKalle Valo 		IWL_ERR(priv, "failed to send BT prio tbl command\n");
180e705c121SKalle Valo }
181e705c121SKalle Valo 
iwl_send_bt_env(struct iwl_priv * priv,u8 action,u8 type)182e705c121SKalle Valo int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
183e705c121SKalle Valo {
184e705c121SKalle Valo 	struct iwl_bt_coex_prot_env_cmd env_cmd;
185e705c121SKalle Valo 	int ret;
186e705c121SKalle Valo 
187e705c121SKalle Valo 	env_cmd.action = action;
188e705c121SKalle Valo 	env_cmd.type = type;
189e705c121SKalle Valo 	ret = iwl_dvm_send_cmd_pdu(priv,
190e705c121SKalle Valo 			       REPLY_BT_COEX_PROT_ENV, 0,
191e705c121SKalle Valo 			       sizeof(env_cmd), &env_cmd);
192e705c121SKalle Valo 	if (ret)
193e705c121SKalle Valo 		IWL_ERR(priv, "failed to send BT env command\n");
194e705c121SKalle Valo 	return ret;
195e705c121SKalle Valo }
196e705c121SKalle Valo 
197e705c121SKalle Valo static const u8 iwlagn_default_queue_to_tx_fifo[] = {
198e705c121SKalle Valo 	IWL_TX_FIFO_VO,
199e705c121SKalle Valo 	IWL_TX_FIFO_VI,
200e705c121SKalle Valo 	IWL_TX_FIFO_BE,
201e705c121SKalle Valo 	IWL_TX_FIFO_BK,
202e705c121SKalle Valo };
203e705c121SKalle Valo 
204e705c121SKalle Valo static const u8 iwlagn_ipan_queue_to_tx_fifo[] = {
205e705c121SKalle Valo 	IWL_TX_FIFO_VO,
206e705c121SKalle Valo 	IWL_TX_FIFO_VI,
207e705c121SKalle Valo 	IWL_TX_FIFO_BE,
208e705c121SKalle Valo 	IWL_TX_FIFO_BK,
209e705c121SKalle Valo 	IWL_TX_FIFO_BK_IPAN,
210e705c121SKalle Valo 	IWL_TX_FIFO_BE_IPAN,
211e705c121SKalle Valo 	IWL_TX_FIFO_VI_IPAN,
212e705c121SKalle Valo 	IWL_TX_FIFO_VO_IPAN,
213e705c121SKalle Valo 	IWL_TX_FIFO_BE_IPAN,
214e705c121SKalle Valo 	IWL_TX_FIFO_UNUSED,
215e705c121SKalle Valo 	IWL_TX_FIFO_AUX,
216e705c121SKalle Valo };
217e705c121SKalle Valo 
iwl_alive_notify(struct iwl_priv * priv)218e705c121SKalle Valo static int iwl_alive_notify(struct iwl_priv *priv)
219e705c121SKalle Valo {
220e705c121SKalle Valo 	const u8 *queue_to_txf;
221e705c121SKalle Valo 	u8 n_queues;
222e705c121SKalle Valo 	int ret;
223e705c121SKalle Valo 	int i;
224e705c121SKalle Valo 
225e705c121SKalle Valo 	iwl_trans_fw_alive(priv->trans, 0);
226e705c121SKalle Valo 
227e705c121SKalle Valo 	if (priv->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN &&
228e705c121SKalle Valo 	    priv->nvm_data->sku_cap_ipan_enable) {
229e705c121SKalle Valo 		n_queues = ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo);
230e705c121SKalle Valo 		queue_to_txf = iwlagn_ipan_queue_to_tx_fifo;
231e705c121SKalle Valo 	} else {
232e705c121SKalle Valo 		n_queues = ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo);
233e705c121SKalle Valo 		queue_to_txf = iwlagn_default_queue_to_tx_fifo;
234e705c121SKalle Valo 	}
235e705c121SKalle Valo 
236e705c121SKalle Valo 	for (i = 0; i < n_queues; i++)
237e705c121SKalle Valo 		if (queue_to_txf[i] != IWL_TX_FIFO_UNUSED)
238e705c121SKalle Valo 			iwl_trans_ac_txq_enable(priv->trans, i,
239e705c121SKalle Valo 						queue_to_txf[i], 0);
240e705c121SKalle Valo 
241e705c121SKalle Valo 	priv->passive_no_rx = false;
242e705c121SKalle Valo 	priv->transport_queue_stop = 0;
243e705c121SKalle Valo 
244e705c121SKalle Valo 	ret = iwl_send_wimax_coex(priv);
245e705c121SKalle Valo 	if (ret)
246e705c121SKalle Valo 		return ret;
247e705c121SKalle Valo 
248e705c121SKalle Valo 	if (!priv->lib->no_xtal_calib) {
249e705c121SKalle Valo 		ret = iwl_set_Xtal_calib(priv);
250e705c121SKalle Valo 		if (ret)
251e705c121SKalle Valo 			return ret;
252e705c121SKalle Valo 	}
253e705c121SKalle Valo 
254e705c121SKalle Valo 	return iwl_send_calib_results(priv);
255e705c121SKalle Valo }
256e705c121SKalle Valo 
257e705c121SKalle Valo struct iwl_alive_data {
258e705c121SKalle Valo 	bool valid;
259e705c121SKalle Valo 	u8 subtype;
260e705c121SKalle Valo };
261e705c121SKalle Valo 
iwl_alive_fn(struct iwl_notif_wait_data * notif_wait,struct iwl_rx_packet * pkt,void * data)262e705c121SKalle Valo static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
263e705c121SKalle Valo 			 struct iwl_rx_packet *pkt, void *data)
264e705c121SKalle Valo {
265e705c121SKalle Valo 	struct iwl_priv *priv =
266e705c121SKalle Valo 		container_of(notif_wait, struct iwl_priv, notif_wait);
267e705c121SKalle Valo 	struct iwl_alive_data *alive_data = data;
268e705c121SKalle Valo 	struct iwl_alive_resp *palive;
269e705c121SKalle Valo 
270e705c121SKalle Valo 	palive = (void *)pkt->data;
271e705c121SKalle Valo 
272e705c121SKalle Valo 	IWL_DEBUG_FW(priv, "Alive ucode status 0x%08X revision "
273e705c121SKalle Valo 		       "0x%01X 0x%01X\n",
274e705c121SKalle Valo 		       palive->is_valid, palive->ver_type,
275e705c121SKalle Valo 		       palive->ver_subtype);
276e705c121SKalle Valo 
277e705c121SKalle Valo 	priv->device_pointers.error_event_table =
278e705c121SKalle Valo 		le32_to_cpu(palive->error_event_table_ptr);
279e705c121SKalle Valo 	priv->device_pointers.log_event_table =
280e705c121SKalle Valo 		le32_to_cpu(palive->log_event_table_ptr);
281e705c121SKalle Valo 
282e705c121SKalle Valo 	alive_data->subtype = palive->ver_subtype;
283e705c121SKalle Valo 	alive_data->valid = palive->is_valid == UCODE_VALID_OK;
284e705c121SKalle Valo 
285e705c121SKalle Valo 	return true;
286e705c121SKalle Valo }
287e705c121SKalle Valo 
288e705c121SKalle Valo #define UCODE_ALIVE_TIMEOUT	HZ
289e705c121SKalle Valo #define UCODE_CALIB_TIMEOUT	(2*HZ)
290e705c121SKalle Valo 
iwl_load_ucode_wait_alive(struct iwl_priv * priv,enum iwl_ucode_type ucode_type)291e705c121SKalle Valo int iwl_load_ucode_wait_alive(struct iwl_priv *priv,
292e705c121SKalle Valo 				 enum iwl_ucode_type ucode_type)
293e705c121SKalle Valo {
294e705c121SKalle Valo 	struct iwl_notification_wait alive_wait;
295e705c121SKalle Valo 	struct iwl_alive_data alive_data;
296e705c121SKalle Valo 	const struct fw_img *fw;
297e705c121SKalle Valo 	int ret;
298e705c121SKalle Valo 	enum iwl_ucode_type old_type;
299e705c121SKalle Valo 	static const u16 alive_cmd[] = { REPLY_ALIVE };
300e705c121SKalle Valo 
301612da1efSSharon Dvir 	fw = iwl_get_ucode_image(priv->fw, ucode_type);
302e705c121SKalle Valo 	if (WARN_ON(!fw))
303e705c121SKalle Valo 		return -EINVAL;
304e705c121SKalle Valo 
305e705c121SKalle Valo 	old_type = priv->cur_ucode;
306e705c121SKalle Valo 	priv->cur_ucode = ucode_type;
307e705c121SKalle Valo 	priv->ucode_loaded = false;
308e705c121SKalle Valo 
309e705c121SKalle Valo 	iwl_init_notification_wait(&priv->notif_wait, &alive_wait,
310e705c121SKalle Valo 				   alive_cmd, ARRAY_SIZE(alive_cmd),
311e705c121SKalle Valo 				   iwl_alive_fn, &alive_data);
312e705c121SKalle Valo 
313e705c121SKalle Valo 	ret = iwl_trans_start_fw(priv->trans, fw, false);
314e705c121SKalle Valo 	if (ret) {
315e705c121SKalle Valo 		priv->cur_ucode = old_type;
316e705c121SKalle Valo 		iwl_remove_notification(&priv->notif_wait, &alive_wait);
317e705c121SKalle Valo 		return ret;
318e705c121SKalle Valo 	}
319e705c121SKalle Valo 
320e705c121SKalle Valo 	/*
321e705c121SKalle Valo 	 * Some things may run in the background now, but we
322e705c121SKalle Valo 	 * just wait for the ALIVE notification here.
323e705c121SKalle Valo 	 */
324e705c121SKalle Valo 	ret = iwl_wait_notification(&priv->notif_wait, &alive_wait,
325e705c121SKalle Valo 					UCODE_ALIVE_TIMEOUT);
326e705c121SKalle Valo 	if (ret) {
327e705c121SKalle Valo 		priv->cur_ucode = old_type;
328e705c121SKalle Valo 		return ret;
329e705c121SKalle Valo 	}
330e705c121SKalle Valo 
331e705c121SKalle Valo 	if (!alive_data.valid) {
332e705c121SKalle Valo 		IWL_ERR(priv, "Loaded ucode is not valid!\n");
333e705c121SKalle Valo 		priv->cur_ucode = old_type;
334e705c121SKalle Valo 		return -EIO;
335e705c121SKalle Valo 	}
336e705c121SKalle Valo 
337e705c121SKalle Valo 	priv->ucode_loaded = true;
338e705c121SKalle Valo 
339e705c121SKalle Valo 	if (ucode_type != IWL_UCODE_WOWLAN) {
340e705c121SKalle Valo 		/* delay a bit to give rfkill time to run */
341e705c121SKalle Valo 		msleep(5);
342e705c121SKalle Valo 	}
343e705c121SKalle Valo 
344e705c121SKalle Valo 	ret = iwl_alive_notify(priv);
345e705c121SKalle Valo 	if (ret) {
346e705c121SKalle Valo 		IWL_WARN(priv,
347e705c121SKalle Valo 			"Could not complete ALIVE transition: %d\n", ret);
348e705c121SKalle Valo 		priv->cur_ucode = old_type;
349e705c121SKalle Valo 		return ret;
350e705c121SKalle Valo 	}
351e705c121SKalle Valo 
352e705c121SKalle Valo 	return 0;
353e705c121SKalle Valo }
354e705c121SKalle Valo 
iwlagn_wait_calib(struct iwl_notif_wait_data * notif_wait,struct iwl_rx_packet * pkt,void * data)355e705c121SKalle Valo static bool iwlagn_wait_calib(struct iwl_notif_wait_data *notif_wait,
356e705c121SKalle Valo 			      struct iwl_rx_packet *pkt, void *data)
357e705c121SKalle Valo {
358e705c121SKalle Valo 	struct iwl_priv *priv = data;
359*0d24201fSKees Cook 	struct iwl_calib_cmd *cmd;
360e705c121SKalle Valo 
361e705c121SKalle Valo 	if (pkt->hdr.cmd != CALIBRATION_RES_NOTIFICATION) {
362e705c121SKalle Valo 		WARN_ON(pkt->hdr.cmd != CALIBRATION_COMPLETE_NOTIFICATION);
363e705c121SKalle Valo 		return true;
364e705c121SKalle Valo 	}
365e705c121SKalle Valo 
366*0d24201fSKees Cook 	cmd = (struct iwl_calib_cmd *)pkt->data;
367e705c121SKalle Valo 
368*0d24201fSKees Cook 	if (iwl_calib_set(priv, cmd, iwl_rx_packet_payload_len(pkt)))
369e705c121SKalle Valo 		IWL_ERR(priv, "Failed to record calibration data %d\n",
370*0d24201fSKees Cook 			cmd->hdr.op_code);
371e705c121SKalle Valo 
372e705c121SKalle Valo 	return false;
373e705c121SKalle Valo }
374e705c121SKalle Valo 
iwl_run_init_ucode(struct iwl_priv * priv)375e705c121SKalle Valo int iwl_run_init_ucode(struct iwl_priv *priv)
376e705c121SKalle Valo {
377e705c121SKalle Valo 	struct iwl_notification_wait calib_wait;
378e705c121SKalle Valo 	static const u16 calib_complete[] = {
379e705c121SKalle Valo 		CALIBRATION_RES_NOTIFICATION,
380e705c121SKalle Valo 		CALIBRATION_COMPLETE_NOTIFICATION
381e705c121SKalle Valo 	};
382e705c121SKalle Valo 	int ret;
383e705c121SKalle Valo 
384e705c121SKalle Valo 	lockdep_assert_held(&priv->mutex);
385e705c121SKalle Valo 
386e705c121SKalle Valo 	/* No init ucode required? Curious, but maybe ok */
387eef187a7SSara Sharon 	if (!priv->fw->img[IWL_UCODE_INIT].num_sec)
388e705c121SKalle Valo 		return 0;
389e705c121SKalle Valo 
390e705c121SKalle Valo 	iwl_init_notification_wait(&priv->notif_wait, &calib_wait,
391e705c121SKalle Valo 				   calib_complete, ARRAY_SIZE(calib_complete),
392e705c121SKalle Valo 				   iwlagn_wait_calib, priv);
393e705c121SKalle Valo 
394e705c121SKalle Valo 	/* Will also start the device */
395e705c121SKalle Valo 	ret = iwl_load_ucode_wait_alive(priv, IWL_UCODE_INIT);
396e705c121SKalle Valo 	if (ret)
397e705c121SKalle Valo 		goto error;
398e705c121SKalle Valo 
399e705c121SKalle Valo 	ret = iwl_init_alive_start(priv);
400e705c121SKalle Valo 	if (ret)
401e705c121SKalle Valo 		goto error;
402e705c121SKalle Valo 
403e705c121SKalle Valo 	/*
404e705c121SKalle Valo 	 * Some things may run in the background now, but we
405e705c121SKalle Valo 	 * just wait for the calibration complete notification.
406e705c121SKalle Valo 	 */
407e705c121SKalle Valo 	ret = iwl_wait_notification(&priv->notif_wait, &calib_wait,
408e705c121SKalle Valo 					UCODE_CALIB_TIMEOUT);
409e705c121SKalle Valo 
410e705c121SKalle Valo 	goto out;
411e705c121SKalle Valo 
412e705c121SKalle Valo  error:
413e705c121SKalle Valo 	iwl_remove_notification(&priv->notif_wait, &calib_wait);
414e705c121SKalle Valo  out:
415e705c121SKalle Valo 	/* Whatever happened, stop the device */
416e705c121SKalle Valo 	iwl_trans_stop_device(priv->trans);
417e705c121SKalle Valo 	priv->ucode_loaded = false;
418e705c121SKalle Valo 
419e705c121SKalle Valo 	return ret;
420e705c121SKalle Valo }
421