iwl-ucode.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682
  1. /******************************************************************************
  2. *
  3. * GPL LICENSE SUMMARY
  4. *
  5. * Copyright(c) 2008 - 2012 Intel Corporation. All rights reserved.
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of version 2 of the GNU General Public License as
  9. * published by the Free Software Foundation.
  10. *
  11. * This program is distributed in the hope that it will be useful, but
  12. * WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
  19. * USA
  20. *
  21. * The full GNU General Public License is included in this distribution
  22. * in the file called LICENSE.GPL.
  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. #include <linux/kernel.h>
  30. #include <linux/module.h>
  31. #include <linux/init.h>
  32. #include <linux/sched.h>
  33. #include <linux/dma-mapping.h>
  34. #include "iwl-wifi.h"
  35. #include "iwl-dev.h"
  36. #include "iwl-core.h"
  37. #include "iwl-io.h"
  38. #include "iwl-agn-hw.h"
  39. #include "iwl-agn.h"
  40. #include "iwl-agn-calib.h"
  41. #include "iwl-trans.h"
  42. #include "iwl-fh.h"
  43. static struct iwl_wimax_coex_event_entry cu_priorities[COEX_NUM_OF_EVENTS] = {
  44. {COEX_CU_UNASSOC_IDLE_RP, COEX_CU_UNASSOC_IDLE_WP,
  45. 0, COEX_UNASSOC_IDLE_FLAGS},
  46. {COEX_CU_UNASSOC_MANUAL_SCAN_RP, COEX_CU_UNASSOC_MANUAL_SCAN_WP,
  47. 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS},
  48. {COEX_CU_UNASSOC_AUTO_SCAN_RP, COEX_CU_UNASSOC_AUTO_SCAN_WP,
  49. 0, COEX_UNASSOC_AUTO_SCAN_FLAGS},
  50. {COEX_CU_CALIBRATION_RP, COEX_CU_CALIBRATION_WP,
  51. 0, COEX_CALIBRATION_FLAGS},
  52. {COEX_CU_PERIODIC_CALIBRATION_RP, COEX_CU_PERIODIC_CALIBRATION_WP,
  53. 0, COEX_PERIODIC_CALIBRATION_FLAGS},
  54. {COEX_CU_CONNECTION_ESTAB_RP, COEX_CU_CONNECTION_ESTAB_WP,
  55. 0, COEX_CONNECTION_ESTAB_FLAGS},
  56. {COEX_CU_ASSOCIATED_IDLE_RP, COEX_CU_ASSOCIATED_IDLE_WP,
  57. 0, COEX_ASSOCIATED_IDLE_FLAGS},
  58. {COEX_CU_ASSOC_MANUAL_SCAN_RP, COEX_CU_ASSOC_MANUAL_SCAN_WP,
  59. 0, COEX_ASSOC_MANUAL_SCAN_FLAGS},
  60. {COEX_CU_ASSOC_AUTO_SCAN_RP, COEX_CU_ASSOC_AUTO_SCAN_WP,
  61. 0, COEX_ASSOC_AUTO_SCAN_FLAGS},
  62. {COEX_CU_ASSOC_ACTIVE_LEVEL_RP, COEX_CU_ASSOC_ACTIVE_LEVEL_WP,
  63. 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS},
  64. {COEX_CU_RF_ON_RP, COEX_CU_RF_ON_WP, 0, COEX_CU_RF_ON_FLAGS},
  65. {COEX_CU_RF_OFF_RP, COEX_CU_RF_OFF_WP, 0, COEX_RF_OFF_FLAGS},
  66. {COEX_CU_STAND_ALONE_DEBUG_RP, COEX_CU_STAND_ALONE_DEBUG_WP,
  67. 0, COEX_STAND_ALONE_DEBUG_FLAGS},
  68. {COEX_CU_IPAN_ASSOC_LEVEL_RP, COEX_CU_IPAN_ASSOC_LEVEL_WP,
  69. 0, COEX_IPAN_ASSOC_LEVEL_FLAGS},
  70. {COEX_CU_RSRVD1_RP, COEX_CU_RSRVD1_WP, 0, COEX_RSRVD1_FLAGS},
  71. {COEX_CU_RSRVD2_RP, COEX_CU_RSRVD2_WP, 0, COEX_RSRVD2_FLAGS}
  72. };
  73. /******************************************************************************
  74. *
  75. * uCode download functions
  76. *
  77. ******************************************************************************/
  78. static void iwl_free_fw_desc(struct iwl_trans *trans, struct fw_desc *desc)
  79. {
  80. if (desc->v_addr)
  81. dma_free_coherent(trans->dev, desc->len,
  82. desc->v_addr, desc->p_addr);
  83. desc->v_addr = NULL;
  84. desc->len = 0;
  85. }
  86. static void iwl_free_fw_img(struct iwl_trans *trans, struct fw_img *img)
  87. {
  88. iwl_free_fw_desc(trans, &img->code);
  89. iwl_free_fw_desc(trans, &img->data);
  90. }
  91. void iwl_dealloc_ucode(struct iwl_trans *trans)
  92. {
  93. iwl_free_fw_img(trans, &trans->ucode_rt);
  94. iwl_free_fw_img(trans, &trans->ucode_init);
  95. iwl_free_fw_img(trans, &trans->ucode_wowlan);
  96. }
  97. int iwl_alloc_fw_desc(struct iwl_trans *trans, struct fw_desc *desc,
  98. const void *data, size_t len)
  99. {
  100. if (!len) {
  101. desc->v_addr = NULL;
  102. return -EINVAL;
  103. }
  104. desc->v_addr = dma_alloc_coherent(trans->dev, len,
  105. &desc->p_addr, GFP_KERNEL);
  106. if (!desc->v_addr)
  107. return -ENOMEM;
  108. desc->len = len;
  109. memcpy(desc->v_addr, data, len);
  110. return 0;
  111. }
  112. static inline struct fw_img *iwl_get_ucode_image(struct iwl_trans *trans,
  113. enum iwl_ucode_type ucode_type)
  114. {
  115. switch (ucode_type) {
  116. case IWL_UCODE_INIT:
  117. return &trans->ucode_init;
  118. case IWL_UCODE_WOWLAN:
  119. return &trans->ucode_wowlan;
  120. case IWL_UCODE_REGULAR:
  121. return &trans->ucode_rt;
  122. case IWL_UCODE_NONE:
  123. break;
  124. }
  125. return NULL;
  126. }
  127. /*
  128. * Calibration
  129. */
  130. static int iwl_set_Xtal_calib(struct iwl_trans *trans)
  131. {
  132. struct iwl_calib_xtal_freq_cmd cmd;
  133. __le16 *xtal_calib =
  134. (__le16 *)iwl_eeprom_query_addr(trans->shrd, EEPROM_XTAL);
  135. iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_CRYSTAL_FRQ_CMD);
  136. cmd.cap_pin1 = le16_to_cpu(xtal_calib[0]);
  137. cmd.cap_pin2 = le16_to_cpu(xtal_calib[1]);
  138. return iwl_calib_set(trans, (void *)&cmd, sizeof(cmd));
  139. }
  140. static int iwl_set_temperature_offset_calib(struct iwl_trans *trans)
  141. {
  142. struct iwl_calib_temperature_offset_cmd cmd;
  143. __le16 *offset_calib =
  144. (__le16 *)iwl_eeprom_query_addr(trans->shrd,
  145. EEPROM_RAW_TEMPERATURE);
  146. memset(&cmd, 0, sizeof(cmd));
  147. iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
  148. memcpy(&cmd.radio_sensor_offset, offset_calib, sizeof(*offset_calib));
  149. if (!(cmd.radio_sensor_offset))
  150. cmd.radio_sensor_offset = DEFAULT_RADIO_SENSOR_OFFSET;
  151. IWL_DEBUG_CALIB(trans, "Radio sensor offset: %d\n",
  152. le16_to_cpu(cmd.radio_sensor_offset));
  153. return iwl_calib_set(trans, (void *)&cmd, sizeof(cmd));
  154. }
  155. static int iwl_set_temperature_offset_calib_v2(struct iwl_trans *trans)
  156. {
  157. struct iwl_calib_temperature_offset_v2_cmd cmd;
  158. __le16 *offset_calib_high = (__le16 *)iwl_eeprom_query_addr(trans->shrd,
  159. EEPROM_KELVIN_TEMPERATURE);
  160. __le16 *offset_calib_low =
  161. (__le16 *)iwl_eeprom_query_addr(trans->shrd,
  162. EEPROM_RAW_TEMPERATURE);
  163. struct iwl_eeprom_calib_hdr *hdr;
  164. memset(&cmd, 0, sizeof(cmd));
  165. iwl_set_calib_hdr(&cmd.hdr, IWL_PHY_CALIBRATE_TEMP_OFFSET_CMD);
  166. hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(trans->shrd,
  167. EEPROM_CALIB_ALL);
  168. memcpy(&cmd.radio_sensor_offset_high, offset_calib_high,
  169. sizeof(*offset_calib_high));
  170. memcpy(&cmd.radio_sensor_offset_low, offset_calib_low,
  171. sizeof(*offset_calib_low));
  172. if (!(cmd.radio_sensor_offset_low)) {
  173. IWL_DEBUG_CALIB(trans, "no info in EEPROM, use default\n");
  174. cmd.radio_sensor_offset_low = DEFAULT_RADIO_SENSOR_OFFSET;
  175. cmd.radio_sensor_offset_high = DEFAULT_RADIO_SENSOR_OFFSET;
  176. }
  177. memcpy(&cmd.burntVoltageRef, &hdr->voltage,
  178. sizeof(hdr->voltage));
  179. IWL_DEBUG_CALIB(trans, "Radio sensor offset high: %d\n",
  180. le16_to_cpu(cmd.radio_sensor_offset_high));
  181. IWL_DEBUG_CALIB(trans, "Radio sensor offset low: %d\n",
  182. le16_to_cpu(cmd.radio_sensor_offset_low));
  183. IWL_DEBUG_CALIB(trans, "Voltage Ref: %d\n",
  184. le16_to_cpu(cmd.burntVoltageRef));
  185. return iwl_calib_set(trans, (void *)&cmd, sizeof(cmd));
  186. }
  187. static int iwl_send_calib_cfg(struct iwl_trans *trans)
  188. {
  189. struct iwl_calib_cfg_cmd calib_cfg_cmd;
  190. struct iwl_host_cmd cmd = {
  191. .id = CALIBRATION_CFG_CMD,
  192. .len = { sizeof(struct iwl_calib_cfg_cmd), },
  193. .data = { &calib_cfg_cmd, },
  194. };
  195. memset(&calib_cfg_cmd, 0, sizeof(calib_cfg_cmd));
  196. calib_cfg_cmd.ucd_calib_cfg.once.is_enable = IWL_CALIB_INIT_CFG_ALL;
  197. calib_cfg_cmd.ucd_calib_cfg.once.start = IWL_CALIB_INIT_CFG_ALL;
  198. calib_cfg_cmd.ucd_calib_cfg.once.send_res = IWL_CALIB_INIT_CFG_ALL;
  199. calib_cfg_cmd.ucd_calib_cfg.flags =
  200. IWL_CALIB_CFG_FLAG_SEND_COMPLETE_NTFY_MSK;
  201. return iwl_trans_send_cmd(trans, &cmd);
  202. }
  203. int iwlagn_rx_calib_result(struct iwl_priv *priv,
  204. struct iwl_rx_mem_buffer *rxb,
  205. struct iwl_device_cmd *cmd)
  206. {
  207. struct iwl_rx_packet *pkt = rxb_addr(rxb);
  208. struct iwl_calib_hdr *hdr = (struct iwl_calib_hdr *)pkt->u.raw;
  209. int len = le32_to_cpu(pkt->len_n_flags) & FH_RSCSR_FRAME_SIZE_MSK;
  210. /* reduce the size of the length field itself */
  211. len -= 4;
  212. if (iwl_calib_set(trans(priv), hdr, len))
  213. IWL_ERR(priv, "Failed to record calibration data %d\n",
  214. hdr->op_code);
  215. return 0;
  216. }
  217. int iwl_init_alive_start(struct iwl_trans *trans)
  218. {
  219. int ret;
  220. if (cfg(trans)->bt_params &&
  221. cfg(trans)->bt_params->advanced_bt_coexist) {
  222. /*
  223. * Tell uCode we are ready to perform calibration
  224. * need to perform this before any calibration
  225. * no need to close the envlope since we are going
  226. * to load the runtime uCode later.
  227. */
  228. ret = iwl_send_bt_env(trans, IWL_BT_COEX_ENV_OPEN,
  229. BT_COEX_PRIO_TBL_EVT_INIT_CALIB2);
  230. if (ret)
  231. return ret;
  232. }
  233. ret = iwl_send_calib_cfg(trans);
  234. if (ret)
  235. return ret;
  236. /**
  237. * temperature offset calibration is only needed for runtime ucode,
  238. * so prepare the value now.
  239. */
  240. if (cfg(trans)->need_temp_offset_calib) {
  241. if (cfg(trans)->temp_offset_v2)
  242. return iwl_set_temperature_offset_calib_v2(trans);
  243. else
  244. return iwl_set_temperature_offset_calib(trans);
  245. }
  246. return 0;
  247. }
  248. static int iwl_send_wimax_coex(struct iwl_trans *trans)
  249. {
  250. struct iwl_wimax_coex_cmd coex_cmd;
  251. if (cfg(trans)->base_params->support_wimax_coexist) {
  252. /* UnMask wake up src at associated sleep */
  253. coex_cmd.flags = COEX_FLAGS_ASSOC_WA_UNMASK_MSK;
  254. /* UnMask wake up src at unassociated sleep */
  255. coex_cmd.flags |= COEX_FLAGS_UNASSOC_WA_UNMASK_MSK;
  256. memcpy(coex_cmd.sta_prio, cu_priorities,
  257. sizeof(struct iwl_wimax_coex_event_entry) *
  258. COEX_NUM_OF_EVENTS);
  259. /* enabling the coexistence feature */
  260. coex_cmd.flags |= COEX_FLAGS_COEX_ENABLE_MSK;
  261. /* enabling the priorities tables */
  262. coex_cmd.flags |= COEX_FLAGS_STA_TABLE_VALID_MSK;
  263. } else {
  264. /* coexistence is disabled */
  265. memset(&coex_cmd, 0, sizeof(coex_cmd));
  266. }
  267. return iwl_trans_send_cmd_pdu(trans,
  268. COEX_PRIORITY_TABLE_CMD, CMD_SYNC,
  269. sizeof(coex_cmd), &coex_cmd);
  270. }
  271. static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
  272. ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
  273. (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
  274. ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
  275. (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
  276. ((BT_COEX_PRIO_TBL_PRIO_LOW << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
  277. (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
  278. ((BT_COEX_PRIO_TBL_PRIO_LOW << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
  279. (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
  280. ((BT_COEX_PRIO_TBL_PRIO_HIGH << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
  281. (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
  282. ((BT_COEX_PRIO_TBL_PRIO_HIGH << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
  283. (1 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
  284. ((BT_COEX_PRIO_TBL_PRIO_BYPASS << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
  285. (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
  286. ((BT_COEX_PRIO_TBL_PRIO_COEX_OFF << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
  287. (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
  288. ((BT_COEX_PRIO_TBL_PRIO_COEX_ON << IWL_BT_COEX_PRIO_TBL_PRIO_POS) |
  289. (0 << IWL_BT_COEX_PRIO_TBL_SHARED_ANTENNA_POS)),
  290. 0, 0, 0, 0, 0, 0, 0
  291. };
  292. void iwl_send_prio_tbl(struct iwl_trans *trans)
  293. {
  294. struct iwl_bt_coex_prio_table_cmd prio_tbl_cmd;
  295. memcpy(prio_tbl_cmd.prio_tbl, iwl_bt_prio_tbl,
  296. sizeof(iwl_bt_prio_tbl));
  297. if (iwl_trans_send_cmd_pdu(trans,
  298. REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC,
  299. sizeof(prio_tbl_cmd), &prio_tbl_cmd))
  300. IWL_ERR(trans, "failed to send BT prio tbl command\n");
  301. }
  302. int iwl_send_bt_env(struct iwl_trans *trans, u8 action, u8 type)
  303. {
  304. struct iwl_bt_coex_prot_env_cmd env_cmd;
  305. int ret;
  306. env_cmd.action = action;
  307. env_cmd.type = type;
  308. ret = iwl_trans_send_cmd_pdu(trans,
  309. REPLY_BT_COEX_PROT_ENV, CMD_SYNC,
  310. sizeof(env_cmd), &env_cmd);
  311. if (ret)
  312. IWL_ERR(trans, "failed to send BT env command\n");
  313. return ret;
  314. }
  315. static int iwl_alive_notify(struct iwl_trans *trans)
  316. {
  317. struct iwl_priv *priv = priv(trans);
  318. struct iwl_rxon_context *ctx;
  319. int ret;
  320. if (!priv->tx_cmd_pool)
  321. priv->tx_cmd_pool =
  322. kmem_cache_create("iwl_dev_cmd",
  323. sizeof(struct iwl_device_cmd),
  324. sizeof(void *), 0, NULL);
  325. if (!priv->tx_cmd_pool)
  326. return -ENOMEM;
  327. iwl_trans_fw_alive(trans);
  328. for_each_context(priv, ctx)
  329. ctx->last_tx_rejected = false;
  330. ret = iwl_send_wimax_coex(trans);
  331. if (ret)
  332. return ret;
  333. if (!cfg(priv)->no_xtal_calib) {
  334. ret = iwl_set_Xtal_calib(trans);
  335. if (ret)
  336. return ret;
  337. }
  338. return iwl_send_calib_results(trans);
  339. }
  340. /**
  341. * iwl_verify_inst_sparse - verify runtime uCode image in card vs. host,
  342. * using sample data 100 bytes apart. If these sample points are good,
  343. * it's a pretty good bet that everything between them is good, too.
  344. */
  345. static int iwl_verify_inst_sparse(struct iwl_trans *trans,
  346. struct fw_desc *fw_desc)
  347. {
  348. __le32 *image = (__le32 *)fw_desc->v_addr;
  349. u32 len = fw_desc->len;
  350. u32 val;
  351. u32 i;
  352. IWL_DEBUG_FW(trans, "ucode inst image size is %u\n", len);
  353. for (i = 0; i < len; i += 100, image += 100/sizeof(u32)) {
  354. /* read data comes through single port, auto-incr addr */
  355. /* NOTE: Use the debugless read so we don't flood kernel log
  356. * if IWL_DL_IO is set */
  357. iwl_write_direct32(trans, HBUS_TARG_MEM_RADDR,
  358. i + IWLAGN_RTC_INST_LOWER_BOUND);
  359. val = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
  360. if (val != le32_to_cpu(*image))
  361. return -EIO;
  362. }
  363. return 0;
  364. }
  365. static void iwl_print_mismatch_inst(struct iwl_trans *trans,
  366. struct fw_desc *fw_desc)
  367. {
  368. __le32 *image = (__le32 *)fw_desc->v_addr;
  369. u32 len = fw_desc->len;
  370. u32 val;
  371. u32 offs;
  372. int errors = 0;
  373. IWL_DEBUG_FW(trans, "ucode inst image size is %u\n", len);
  374. iwl_write_direct32(trans, HBUS_TARG_MEM_RADDR,
  375. IWLAGN_RTC_INST_LOWER_BOUND);
  376. for (offs = 0;
  377. offs < len && errors < 20;
  378. offs += sizeof(u32), image++) {
  379. /* read data comes through single port, auto-incr addr */
  380. val = iwl_read32(trans, HBUS_TARG_MEM_RDAT);
  381. if (val != le32_to_cpu(*image)) {
  382. IWL_ERR(trans, "uCode INST section at "
  383. "offset 0x%x, is 0x%x, s/b 0x%x\n",
  384. offs, val, le32_to_cpu(*image));
  385. errors++;
  386. }
  387. }
  388. }
  389. /**
  390. * iwl_verify_ucode - determine which instruction image is in SRAM,
  391. * and verify its contents
  392. */
  393. static int iwl_verify_ucode(struct iwl_trans *trans,
  394. enum iwl_ucode_type ucode_type)
  395. {
  396. struct fw_img *img = iwl_get_ucode_image(trans, ucode_type);
  397. if (!img) {
  398. IWL_ERR(trans, "Invalid ucode requested (%d)\n", ucode_type);
  399. return -EINVAL;
  400. }
  401. if (!iwl_verify_inst_sparse(trans, &img->code)) {
  402. IWL_DEBUG_FW(trans, "uCode is good in inst SRAM\n");
  403. return 0;
  404. }
  405. IWL_ERR(trans, "UCODE IMAGE IN INSTRUCTION SRAM NOT VALID!!\n");
  406. iwl_print_mismatch_inst(trans, &img->code);
  407. return -EIO;
  408. }
  409. struct iwl_alive_data {
  410. bool valid;
  411. u8 subtype;
  412. };
  413. static void iwl_alive_fn(struct iwl_trans *trans,
  414. struct iwl_rx_packet *pkt,
  415. void *data)
  416. {
  417. struct iwl_alive_data *alive_data = data;
  418. struct iwl_alive_resp *palive;
  419. palive = &pkt->u.alive_frame;
  420. IWL_DEBUG_FW(trans, "Alive ucode status 0x%08X revision "
  421. "0x%01X 0x%01X\n",
  422. palive->is_valid, palive->ver_type,
  423. palive->ver_subtype);
  424. trans->shrd->device_pointers.error_event_table =
  425. le32_to_cpu(palive->error_event_table_ptr);
  426. trans->shrd->device_pointers.log_event_table =
  427. le32_to_cpu(palive->log_event_table_ptr);
  428. alive_data->subtype = palive->ver_subtype;
  429. alive_data->valid = palive->is_valid == UCODE_VALID_OK;
  430. }
  431. /* notification wait support */
  432. void iwl_init_notification_wait(struct iwl_shared *shrd,
  433. struct iwl_notification_wait *wait_entry,
  434. u8 cmd,
  435. void (*fn)(struct iwl_trans *trans,
  436. struct iwl_rx_packet *pkt,
  437. void *data),
  438. void *fn_data)
  439. {
  440. wait_entry->fn = fn;
  441. wait_entry->fn_data = fn_data;
  442. wait_entry->cmd = cmd;
  443. wait_entry->triggered = false;
  444. wait_entry->aborted = false;
  445. spin_lock_bh(&shrd->notif_wait_lock);
  446. list_add(&wait_entry->list, &shrd->notif_waits);
  447. spin_unlock_bh(&shrd->notif_wait_lock);
  448. }
  449. int iwl_wait_notification(struct iwl_shared *shrd,
  450. struct iwl_notification_wait *wait_entry,
  451. unsigned long timeout)
  452. {
  453. int ret;
  454. ret = wait_event_timeout(shrd->notif_waitq,
  455. wait_entry->triggered || wait_entry->aborted,
  456. timeout);
  457. spin_lock_bh(&shrd->notif_wait_lock);
  458. list_del(&wait_entry->list);
  459. spin_unlock_bh(&shrd->notif_wait_lock);
  460. if (wait_entry->aborted)
  461. return -EIO;
  462. /* return value is always >= 0 */
  463. if (ret <= 0)
  464. return -ETIMEDOUT;
  465. return 0;
  466. }
  467. void iwl_remove_notification(struct iwl_shared *shrd,
  468. struct iwl_notification_wait *wait_entry)
  469. {
  470. spin_lock_bh(&shrd->notif_wait_lock);
  471. list_del(&wait_entry->list);
  472. spin_unlock_bh(&shrd->notif_wait_lock);
  473. }
  474. void iwl_abort_notification_waits(struct iwl_shared *shrd)
  475. {
  476. unsigned long flags;
  477. struct iwl_notification_wait *wait_entry;
  478. spin_lock_irqsave(&shrd->notif_wait_lock, flags);
  479. list_for_each_entry(wait_entry, &shrd->notif_waits, list)
  480. wait_entry->aborted = true;
  481. spin_unlock_irqrestore(&shrd->notif_wait_lock, flags);
  482. wake_up_all(&shrd->notif_waitq);
  483. }
  484. #define UCODE_ALIVE_TIMEOUT HZ
  485. #define UCODE_CALIB_TIMEOUT (2*HZ)
  486. int iwl_load_ucode_wait_alive(struct iwl_trans *trans,
  487. enum iwl_ucode_type ucode_type)
  488. {
  489. struct iwl_notification_wait alive_wait;
  490. struct iwl_alive_data alive_data;
  491. struct fw_img *fw;
  492. int ret;
  493. enum iwl_ucode_type old_type;
  494. iwl_init_notification_wait(trans->shrd, &alive_wait, REPLY_ALIVE,
  495. iwl_alive_fn, &alive_data);
  496. old_type = trans->shrd->ucode_type;
  497. trans->shrd->ucode_type = ucode_type;
  498. fw = iwl_get_ucode_image(trans, ucode_type);
  499. if (!fw)
  500. return -EINVAL;
  501. ret = iwl_trans_start_fw(trans, fw);
  502. if (ret) {
  503. trans->shrd->ucode_type = old_type;
  504. iwl_remove_notification(trans->shrd, &alive_wait);
  505. return ret;
  506. }
  507. /*
  508. * Some things may run in the background now, but we
  509. * just wait for the ALIVE notification here.
  510. */
  511. ret = iwl_wait_notification(trans->shrd, &alive_wait,
  512. UCODE_ALIVE_TIMEOUT);
  513. if (ret) {
  514. trans->shrd->ucode_type = old_type;
  515. return ret;
  516. }
  517. if (!alive_data.valid) {
  518. IWL_ERR(trans, "Loaded ucode is not valid!\n");
  519. trans->shrd->ucode_type = old_type;
  520. return -EIO;
  521. }
  522. /*
  523. * This step takes a long time (60-80ms!!) and
  524. * WoWLAN image should be loaded quickly, so
  525. * skip it for WoWLAN.
  526. */
  527. if (ucode_type != IWL_UCODE_WOWLAN) {
  528. ret = iwl_verify_ucode(trans, ucode_type);
  529. if (ret) {
  530. trans->shrd->ucode_type = old_type;
  531. return ret;
  532. }
  533. /* delay a bit to give rfkill time to run */
  534. msleep(5);
  535. }
  536. ret = iwl_alive_notify(trans);
  537. if (ret) {
  538. IWL_WARN(trans,
  539. "Could not complete ALIVE transition: %d\n", ret);
  540. trans->shrd->ucode_type = old_type;
  541. return ret;
  542. }
  543. return 0;
  544. }
  545. int iwl_run_init_ucode(struct iwl_trans *trans)
  546. {
  547. struct iwl_notification_wait calib_wait;
  548. int ret;
  549. lockdep_assert_held(&trans->shrd->mutex);
  550. /* No init ucode required? Curious, but maybe ok */
  551. if (!trans->ucode_init.code.len)
  552. return 0;
  553. if (trans->shrd->ucode_type != IWL_UCODE_NONE)
  554. return 0;
  555. iwl_init_notification_wait(trans->shrd, &calib_wait,
  556. CALIBRATION_COMPLETE_NOTIFICATION,
  557. NULL, NULL);
  558. /* Will also start the device */
  559. ret = iwl_load_ucode_wait_alive(trans, IWL_UCODE_INIT);
  560. if (ret)
  561. goto error;
  562. ret = iwl_init_alive_start(trans);
  563. if (ret)
  564. goto error;
  565. /*
  566. * Some things may run in the background now, but we
  567. * just wait for the calibration complete notification.
  568. */
  569. ret = iwl_wait_notification(trans->shrd, &calib_wait,
  570. UCODE_CALIB_TIMEOUT);
  571. goto out;
  572. error:
  573. iwl_remove_notification(trans->shrd, &calib_wait);
  574. out:
  575. /* Whatever happened, stop the device */
  576. iwl_trans_stop_device(trans);
  577. return ret;
  578. }