iwl-agn-lib.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985
  1. /******************************************************************************
  2. *
  3. * GPL LICENSE SUMMARY
  4. *
  5. * Copyright(c) 2008 - 2011 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/etherdevice.h>
  30. #include <linux/kernel.h>
  31. #include <linux/module.h>
  32. #include <linux/init.h>
  33. #include <linux/sched.h>
  34. #include "iwl-dev.h"
  35. #include "iwl-core.h"
  36. #include "iwl-io.h"
  37. #include "iwl-agn-hw.h"
  38. #include "iwl-agn.h"
  39. #include "iwl-trans.h"
  40. #include "iwl-shared.h"
  41. int iwlagn_hw_valid_rtc_data_addr(u32 addr)
  42. {
  43. return (addr >= IWLAGN_RTC_DATA_LOWER_BOUND) &&
  44. (addr < IWLAGN_RTC_DATA_UPPER_BOUND);
  45. }
  46. int iwlagn_send_tx_power(struct iwl_priv *priv)
  47. {
  48. struct iwlagn_tx_power_dbm_cmd tx_power_cmd;
  49. u8 tx_ant_cfg_cmd;
  50. if (WARN_ONCE(test_bit(STATUS_SCAN_HW, &priv->shrd->status),
  51. "TX Power requested while scanning!\n"))
  52. return -EAGAIN;
  53. /* half dBm need to multiply */
  54. tx_power_cmd.global_lmt = (s8)(2 * priv->tx_power_user_lmt);
  55. if (priv->tx_power_lmt_in_half_dbm &&
  56. priv->tx_power_lmt_in_half_dbm < tx_power_cmd.global_lmt) {
  57. /*
  58. * For the newer devices which using enhanced/extend tx power
  59. * table in EEPROM, the format is in half dBm. driver need to
  60. * convert to dBm format before report to mac80211.
  61. * By doing so, there is a possibility of 1/2 dBm resolution
  62. * lost. driver will perform "round-up" operation before
  63. * reporting, but it will cause 1/2 dBm tx power over the
  64. * regulatory limit. Perform the checking here, if the
  65. * "tx_power_user_lmt" is higher than EEPROM value (in
  66. * half-dBm format), lower the tx power based on EEPROM
  67. */
  68. tx_power_cmd.global_lmt = priv->tx_power_lmt_in_half_dbm;
  69. }
  70. tx_power_cmd.flags = IWLAGN_TX_POWER_NO_CLOSED;
  71. tx_power_cmd.srv_chan_lmt = IWLAGN_TX_POWER_AUTO;
  72. if (IWL_UCODE_API(priv->ucode_ver) == 1)
  73. tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD_V1;
  74. else
  75. tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD;
  76. return iwl_trans_send_cmd_pdu(trans(priv), tx_ant_cfg_cmd, CMD_SYNC,
  77. sizeof(tx_power_cmd), &tx_power_cmd);
  78. }
  79. void iwlagn_temperature(struct iwl_priv *priv)
  80. {
  81. /* store temperature from correct statistics (in Celsius) */
  82. priv->temperature = le32_to_cpu(priv->statistics.common.temperature);
  83. iwl_tt_handler(priv);
  84. }
  85. u16 iwlagn_eeprom_calib_version(struct iwl_priv *priv)
  86. {
  87. struct iwl_eeprom_calib_hdr *hdr;
  88. hdr = (struct iwl_eeprom_calib_hdr *)iwl_eeprom_query_addr(priv,
  89. EEPROM_CALIB_ALL);
  90. return hdr->version;
  91. }
  92. /*
  93. * EEPROM
  94. */
  95. static u32 eeprom_indirect_address(const struct iwl_priv *priv, u32 address)
  96. {
  97. u16 offset = 0;
  98. if ((address & INDIRECT_ADDRESS) == 0)
  99. return address;
  100. switch (address & INDIRECT_TYPE_MSK) {
  101. case INDIRECT_HOST:
  102. offset = iwl_eeprom_query16(priv, EEPROM_LINK_HOST);
  103. break;
  104. case INDIRECT_GENERAL:
  105. offset = iwl_eeprom_query16(priv, EEPROM_LINK_GENERAL);
  106. break;
  107. case INDIRECT_REGULATORY:
  108. offset = iwl_eeprom_query16(priv, EEPROM_LINK_REGULATORY);
  109. break;
  110. case INDIRECT_TXP_LIMIT:
  111. offset = iwl_eeprom_query16(priv, EEPROM_LINK_TXP_LIMIT);
  112. break;
  113. case INDIRECT_TXP_LIMIT_SIZE:
  114. offset = iwl_eeprom_query16(priv, EEPROM_LINK_TXP_LIMIT_SIZE);
  115. break;
  116. case INDIRECT_CALIBRATION:
  117. offset = iwl_eeprom_query16(priv, EEPROM_LINK_CALIBRATION);
  118. break;
  119. case INDIRECT_PROCESS_ADJST:
  120. offset = iwl_eeprom_query16(priv, EEPROM_LINK_PROCESS_ADJST);
  121. break;
  122. case INDIRECT_OTHERS:
  123. offset = iwl_eeprom_query16(priv, EEPROM_LINK_OTHERS);
  124. break;
  125. default:
  126. IWL_ERR(priv, "illegal indirect type: 0x%X\n",
  127. address & INDIRECT_TYPE_MSK);
  128. break;
  129. }
  130. /* translate the offset from words to byte */
  131. return (address & ADDRESS_MSK) + (offset << 1);
  132. }
  133. const u8 *iwl_eeprom_query_addr(const struct iwl_priv *priv, size_t offset)
  134. {
  135. u32 address = eeprom_indirect_address(priv, offset);
  136. BUG_ON(address >= priv->cfg->base_params->eeprom_size);
  137. return &priv->eeprom[address];
  138. }
  139. struct iwl_mod_params iwlagn_mod_params = {
  140. .amsdu_size_8K = 1,
  141. .restart_fw = 1,
  142. .plcp_check = true,
  143. .bt_coex_active = true,
  144. .no_sleep_autoadjust = true,
  145. .power_level = IWL_POWER_INDEX_1,
  146. .bt_ch_announce = true,
  147. .wanted_ucode_alternative = 1,
  148. .auto_agg = true,
  149. /* the rest are 0 by default */
  150. };
  151. int iwlagn_hwrate_to_mac80211_idx(u32 rate_n_flags, enum ieee80211_band band)
  152. {
  153. int idx = 0;
  154. int band_offset = 0;
  155. /* HT rate format: mac80211 wants an MCS number, which is just LSB */
  156. if (rate_n_flags & RATE_MCS_HT_MSK) {
  157. idx = (rate_n_flags & 0xff);
  158. return idx;
  159. /* Legacy rate format, search for match in table */
  160. } else {
  161. if (band == IEEE80211_BAND_5GHZ)
  162. band_offset = IWL_FIRST_OFDM_RATE;
  163. for (idx = band_offset; idx < IWL_RATE_COUNT_LEGACY; idx++)
  164. if (iwl_rates[idx].plcp == (rate_n_flags & 0xFF))
  165. return idx - band_offset;
  166. }
  167. return -1;
  168. }
  169. int iwlagn_manage_ibss_station(struct iwl_priv *priv,
  170. struct ieee80211_vif *vif, bool add)
  171. {
  172. struct iwl_vif_priv *vif_priv = (void *)vif->drv_priv;
  173. if (add)
  174. return iwlagn_add_bssid_station(priv, vif_priv->ctx,
  175. vif->bss_conf.bssid,
  176. &vif_priv->ibss_bssid_sta_id);
  177. return iwl_remove_station(priv, vif_priv->ibss_bssid_sta_id,
  178. vif->bss_conf.bssid);
  179. }
  180. /**
  181. * iwlagn_txfifo_flush: send REPLY_TXFIFO_FLUSH command to uCode
  182. *
  183. * pre-requirements:
  184. * 1. acquire mutex before calling
  185. * 2. make sure rf is on and not in exit state
  186. */
  187. int iwlagn_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
  188. {
  189. struct iwl_txfifo_flush_cmd flush_cmd;
  190. struct iwl_host_cmd cmd = {
  191. .id = REPLY_TXFIFO_FLUSH,
  192. .len = { sizeof(struct iwl_txfifo_flush_cmd), },
  193. .flags = CMD_SYNC,
  194. .data = { &flush_cmd, },
  195. };
  196. might_sleep();
  197. memset(&flush_cmd, 0, sizeof(flush_cmd));
  198. if (flush_control & BIT(IWL_RXON_CTX_BSS))
  199. flush_cmd.fifo_control = IWL_SCD_VO_MSK | IWL_SCD_VI_MSK |
  200. IWL_SCD_BE_MSK | IWL_SCD_BK_MSK |
  201. IWL_SCD_MGMT_MSK;
  202. if ((flush_control & BIT(IWL_RXON_CTX_PAN)) &&
  203. (priv->shrd->valid_contexts != BIT(IWL_RXON_CTX_BSS)))
  204. flush_cmd.fifo_control |= IWL_PAN_SCD_VO_MSK |
  205. IWL_PAN_SCD_VI_MSK | IWL_PAN_SCD_BE_MSK |
  206. IWL_PAN_SCD_BK_MSK | IWL_PAN_SCD_MGMT_MSK |
  207. IWL_PAN_SCD_MULTICAST_MSK;
  208. if (priv->cfg->sku & EEPROM_SKU_CAP_11N_ENABLE)
  209. flush_cmd.fifo_control |= IWL_AGG_TX_QUEUE_MSK;
  210. IWL_DEBUG_INFO(priv, "fifo queue control: 0X%x\n",
  211. flush_cmd.fifo_control);
  212. flush_cmd.flush_control = cpu_to_le16(flush_control);
  213. return iwl_trans_send_cmd(trans(priv), &cmd);
  214. }
  215. void iwlagn_dev_txfifo_flush(struct iwl_priv *priv, u16 flush_control)
  216. {
  217. mutex_lock(&priv->shrd->mutex);
  218. ieee80211_stop_queues(priv->hw);
  219. if (iwlagn_txfifo_flush(priv, IWL_DROP_ALL)) {
  220. IWL_ERR(priv, "flush request fail\n");
  221. goto done;
  222. }
  223. IWL_DEBUG_INFO(priv, "wait transmit/flush all frames\n");
  224. iwl_trans_wait_tx_queue_empty(trans(priv));
  225. done:
  226. ieee80211_wake_queues(priv->hw);
  227. mutex_unlock(&priv->shrd->mutex);
  228. }
  229. /*
  230. * BT coex
  231. */
  232. /*
  233. * Macros to access the lookup table.
  234. *
  235. * The lookup table has 7 inputs: bt3_prio, bt3_txrx, bt_rf_act, wifi_req,
  236. * wifi_prio, wifi_txrx and wifi_sh_ant_req.
  237. *
  238. * It has three outputs: WLAN_ACTIVE, WLAN_KILL and ANT_SWITCH
  239. *
  240. * The format is that "registers" 8 through 11 contain the WLAN_ACTIVE bits
  241. * one after another in 32-bit registers, and "registers" 0 through 7 contain
  242. * the WLAN_KILL and ANT_SWITCH bits interleaved (in that order).
  243. *
  244. * These macros encode that format.
  245. */
  246. #define LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, wifi_req, wifi_prio, \
  247. wifi_txrx, wifi_sh_ant_req) \
  248. (bt3_prio | (bt3_txrx << 1) | (bt_rf_act << 2) | (wifi_req << 3) | \
  249. (wifi_prio << 4) | (wifi_txrx << 5) | (wifi_sh_ant_req << 6))
  250. #define LUT_PTA_WLAN_ACTIVE_OP(lut, op, val) \
  251. lut[8 + ((val) >> 5)] op (cpu_to_le32(BIT((val) & 0x1f)))
  252. #define LUT_TEST_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
  253. wifi_prio, wifi_txrx, wifi_sh_ant_req) \
  254. (!!(LUT_PTA_WLAN_ACTIVE_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, \
  255. bt_rf_act, wifi_req, wifi_prio, wifi_txrx, \
  256. wifi_sh_ant_req))))
  257. #define LUT_SET_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
  258. wifi_prio, wifi_txrx, wifi_sh_ant_req) \
  259. LUT_PTA_WLAN_ACTIVE_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, \
  260. bt_rf_act, wifi_req, wifi_prio, wifi_txrx, \
  261. wifi_sh_ant_req))
  262. #define LUT_CLEAR_PTA_WLAN_ACTIVE(lut, bt3_prio, bt3_txrx, bt_rf_act, \
  263. wifi_req, wifi_prio, wifi_txrx, \
  264. wifi_sh_ant_req) \
  265. LUT_PTA_WLAN_ACTIVE_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, \
  266. bt_rf_act, wifi_req, wifi_prio, wifi_txrx, \
  267. wifi_sh_ant_req))
  268. #define LUT_WLAN_KILL_OP(lut, op, val) \
  269. lut[(val) >> 4] op (cpu_to_le32(BIT(((val) << 1) & 0x1e)))
  270. #define LUT_TEST_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
  271. wifi_prio, wifi_txrx, wifi_sh_ant_req) \
  272. (!!(LUT_WLAN_KILL_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
  273. wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))))
  274. #define LUT_SET_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
  275. wifi_prio, wifi_txrx, wifi_sh_ant_req) \
  276. LUT_WLAN_KILL_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
  277. wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
  278. #define LUT_CLEAR_WLAN_KILL(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
  279. wifi_prio, wifi_txrx, wifi_sh_ant_req) \
  280. LUT_WLAN_KILL_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
  281. wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
  282. #define LUT_ANT_SWITCH_OP(lut, op, val) \
  283. lut[(val) >> 4] op (cpu_to_le32(BIT((((val) << 1) & 0x1e) + 1)))
  284. #define LUT_TEST_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
  285. wifi_prio, wifi_txrx, wifi_sh_ant_req) \
  286. (!!(LUT_ANT_SWITCH_OP(lut, &, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
  287. wifi_req, wifi_prio, wifi_txrx, \
  288. wifi_sh_ant_req))))
  289. #define LUT_SET_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
  290. wifi_prio, wifi_txrx, wifi_sh_ant_req) \
  291. LUT_ANT_SWITCH_OP(lut, |=, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
  292. wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
  293. #define LUT_CLEAR_ANT_SWITCH(lut, bt3_prio, bt3_txrx, bt_rf_act, wifi_req, \
  294. wifi_prio, wifi_txrx, wifi_sh_ant_req) \
  295. LUT_ANT_SWITCH_OP(lut, &= ~, LUT_VALUE(bt3_prio, bt3_txrx, bt_rf_act, \
  296. wifi_req, wifi_prio, wifi_txrx, wifi_sh_ant_req))
  297. static const __le32 iwlagn_def_3w_lookup[12] = {
  298. cpu_to_le32(0xaaaaaaaa),
  299. cpu_to_le32(0xaaaaaaaa),
  300. cpu_to_le32(0xaeaaaaaa),
  301. cpu_to_le32(0xaaaaaaaa),
  302. cpu_to_le32(0xcc00ff28),
  303. cpu_to_le32(0x0000aaaa),
  304. cpu_to_le32(0xcc00aaaa),
  305. cpu_to_le32(0x0000aaaa),
  306. cpu_to_le32(0xc0004000),
  307. cpu_to_le32(0x00004000),
  308. cpu_to_le32(0xf0005000),
  309. cpu_to_le32(0xf0005000),
  310. };
  311. static const __le32 iwlagn_concurrent_lookup[12] = {
  312. cpu_to_le32(0xaaaaaaaa),
  313. cpu_to_le32(0xaaaaaaaa),
  314. cpu_to_le32(0xaaaaaaaa),
  315. cpu_to_le32(0xaaaaaaaa),
  316. cpu_to_le32(0xaaaaaaaa),
  317. cpu_to_le32(0xaaaaaaaa),
  318. cpu_to_le32(0xaaaaaaaa),
  319. cpu_to_le32(0xaaaaaaaa),
  320. cpu_to_le32(0x00000000),
  321. cpu_to_le32(0x00000000),
  322. cpu_to_le32(0x00000000),
  323. cpu_to_le32(0x00000000),
  324. };
  325. void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
  326. {
  327. struct iwl_basic_bt_cmd basic = {
  328. .max_kill = IWLAGN_BT_MAX_KILL_DEFAULT,
  329. .bt3_timer_t7_value = IWLAGN_BT3_T7_DEFAULT,
  330. .bt3_prio_sample_time = IWLAGN_BT3_PRIO_SAMPLE_DEFAULT,
  331. .bt3_timer_t2_value = IWLAGN_BT3_T2_DEFAULT,
  332. };
  333. struct iwl6000_bt_cmd bt_cmd_6000;
  334. struct iwl2000_bt_cmd bt_cmd_2000;
  335. int ret;
  336. BUILD_BUG_ON(sizeof(iwlagn_def_3w_lookup) !=
  337. sizeof(basic.bt3_lookup_table));
  338. if (priv->cfg->bt_params) {
  339. if (priv->cfg->bt_params->bt_session_2) {
  340. bt_cmd_2000.prio_boost = cpu_to_le32(
  341. priv->cfg->bt_params->bt_prio_boost);
  342. bt_cmd_2000.tx_prio_boost = 0;
  343. bt_cmd_2000.rx_prio_boost = 0;
  344. } else {
  345. bt_cmd_6000.prio_boost =
  346. priv->cfg->bt_params->bt_prio_boost;
  347. bt_cmd_6000.tx_prio_boost = 0;
  348. bt_cmd_6000.rx_prio_boost = 0;
  349. }
  350. } else {
  351. IWL_ERR(priv, "failed to construct BT Coex Config\n");
  352. return;
  353. }
  354. basic.kill_ack_mask = priv->kill_ack_mask;
  355. basic.kill_cts_mask = priv->kill_cts_mask;
  356. basic.valid = priv->bt_valid;
  357. /*
  358. * Configure BT coex mode to "no coexistence" when the
  359. * user disabled BT coexistence, we have no interface
  360. * (might be in monitor mode), or the interface is in
  361. * IBSS mode (no proper uCode support for coex then).
  362. */
  363. if (!iwlagn_mod_params.bt_coex_active ||
  364. priv->iw_mode == NL80211_IFTYPE_ADHOC) {
  365. basic.flags = IWLAGN_BT_FLAG_COEX_MODE_DISABLED;
  366. } else {
  367. basic.flags = IWLAGN_BT_FLAG_COEX_MODE_3W <<
  368. IWLAGN_BT_FLAG_COEX_MODE_SHIFT;
  369. if (!priv->bt_enable_pspoll)
  370. basic.flags |= IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE;
  371. else
  372. basic.flags &= ~IWLAGN_BT_FLAG_SYNC_2_BT_DISABLE;
  373. if (priv->bt_ch_announce)
  374. basic.flags |= IWLAGN_BT_FLAG_CHANNEL_INHIBITION;
  375. IWL_DEBUG_COEX(priv, "BT coex flag: 0X%x\n", basic.flags);
  376. }
  377. priv->bt_enable_flag = basic.flags;
  378. if (priv->bt_full_concurrent)
  379. memcpy(basic.bt3_lookup_table, iwlagn_concurrent_lookup,
  380. sizeof(iwlagn_concurrent_lookup));
  381. else
  382. memcpy(basic.bt3_lookup_table, iwlagn_def_3w_lookup,
  383. sizeof(iwlagn_def_3w_lookup));
  384. IWL_DEBUG_COEX(priv, "BT coex %s in %s mode\n",
  385. basic.flags ? "active" : "disabled",
  386. priv->bt_full_concurrent ?
  387. "full concurrency" : "3-wire");
  388. if (priv->cfg->bt_params->bt_session_2) {
  389. memcpy(&bt_cmd_2000.basic, &basic,
  390. sizeof(basic));
  391. ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG,
  392. CMD_SYNC, sizeof(bt_cmd_2000), &bt_cmd_2000);
  393. } else {
  394. memcpy(&bt_cmd_6000.basic, &basic,
  395. sizeof(basic));
  396. ret = iwl_trans_send_cmd_pdu(trans(priv), REPLY_BT_CONFIG,
  397. CMD_SYNC, sizeof(bt_cmd_6000), &bt_cmd_6000);
  398. }
  399. if (ret)
  400. IWL_ERR(priv, "failed to send BT Coex Config\n");
  401. }
  402. void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena)
  403. {
  404. struct iwl_rxon_context *ctx, *found_ctx = NULL;
  405. bool found_ap = false;
  406. lockdep_assert_held(&priv->shrd->mutex);
  407. /* Check whether AP or GO mode is active. */
  408. if (rssi_ena) {
  409. for_each_context(priv, ctx) {
  410. if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_AP &&
  411. iwl_is_associated_ctx(ctx)) {
  412. found_ap = true;
  413. break;
  414. }
  415. }
  416. }
  417. /*
  418. * If disable was received or If GO/AP mode, disable RSSI
  419. * measurements.
  420. */
  421. if (!rssi_ena || found_ap) {
  422. if (priv->cur_rssi_ctx) {
  423. ctx = priv->cur_rssi_ctx;
  424. ieee80211_disable_rssi_reports(ctx->vif);
  425. priv->cur_rssi_ctx = NULL;
  426. }
  427. return;
  428. }
  429. /*
  430. * If rssi measurements need to be enabled, consider all cases now.
  431. * Figure out how many contexts are active.
  432. */
  433. for_each_context(priv, ctx) {
  434. if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION &&
  435. iwl_is_associated_ctx(ctx)) {
  436. found_ctx = ctx;
  437. break;
  438. }
  439. }
  440. /*
  441. * rssi monitor already enabled for the correct interface...nothing
  442. * to do.
  443. */
  444. if (found_ctx == priv->cur_rssi_ctx)
  445. return;
  446. /*
  447. * Figure out if rssi monitor is currently enabled, and needs
  448. * to be changed. If rssi monitor is already enabled, disable
  449. * it first else just enable rssi measurements on the
  450. * interface found above.
  451. */
  452. if (priv->cur_rssi_ctx) {
  453. ctx = priv->cur_rssi_ctx;
  454. if (ctx->vif)
  455. ieee80211_disable_rssi_reports(ctx->vif);
  456. }
  457. priv->cur_rssi_ctx = found_ctx;
  458. if (!found_ctx)
  459. return;
  460. ieee80211_enable_rssi_reports(found_ctx->vif,
  461. IWLAGN_BT_PSP_MIN_RSSI_THRESHOLD,
  462. IWLAGN_BT_PSP_MAX_RSSI_THRESHOLD);
  463. }
  464. static bool iwlagn_bt_traffic_is_sco(struct iwl_bt_uart_msg *uart_msg)
  465. {
  466. return BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3 >>
  467. BT_UART_MSG_FRAME3SCOESCO_POS;
  468. }
  469. static void iwlagn_bt_traffic_change_work(struct work_struct *work)
  470. {
  471. struct iwl_priv *priv =
  472. container_of(work, struct iwl_priv, bt_traffic_change_work);
  473. struct iwl_rxon_context *ctx;
  474. int smps_request = -1;
  475. if (priv->bt_enable_flag == IWLAGN_BT_FLAG_COEX_MODE_DISABLED) {
  476. /* bt coex disabled */
  477. return;
  478. }
  479. /*
  480. * Note: bt_traffic_load can be overridden by scan complete and
  481. * coex profile notifications. Ignore that since only bad consequence
  482. * can be not matching debug print with actual state.
  483. */
  484. IWL_DEBUG_COEX(priv, "BT traffic load changes: %d\n",
  485. priv->bt_traffic_load);
  486. switch (priv->bt_traffic_load) {
  487. case IWL_BT_COEX_TRAFFIC_LOAD_NONE:
  488. if (priv->bt_status)
  489. smps_request = IEEE80211_SMPS_DYNAMIC;
  490. else
  491. smps_request = IEEE80211_SMPS_AUTOMATIC;
  492. break;
  493. case IWL_BT_COEX_TRAFFIC_LOAD_LOW:
  494. smps_request = IEEE80211_SMPS_DYNAMIC;
  495. break;
  496. case IWL_BT_COEX_TRAFFIC_LOAD_HIGH:
  497. case IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS:
  498. smps_request = IEEE80211_SMPS_STATIC;
  499. break;
  500. default:
  501. IWL_ERR(priv, "Invalid BT traffic load: %d\n",
  502. priv->bt_traffic_load);
  503. break;
  504. }
  505. mutex_lock(&priv->shrd->mutex);
  506. /*
  507. * We can not send command to firmware while scanning. When the scan
  508. * complete we will schedule this work again. We do check with mutex
  509. * locked to prevent new scan request to arrive. We do not check
  510. * STATUS_SCANNING to avoid race when queue_work two times from
  511. * different notifications, but quit and not perform any work at all.
  512. */
  513. if (test_bit(STATUS_SCAN_HW, &priv->shrd->status))
  514. goto out;
  515. iwl_update_chain_flags(priv);
  516. if (smps_request != -1) {
  517. priv->current_ht_config.smps = smps_request;
  518. for_each_context(priv, ctx) {
  519. if (ctx->vif && ctx->vif->type == NL80211_IFTYPE_STATION)
  520. ieee80211_request_smps(ctx->vif, smps_request);
  521. }
  522. }
  523. /*
  524. * Dynamic PS poll related functionality. Adjust RSSI measurements if
  525. * necessary.
  526. */
  527. iwlagn_bt_coex_rssi_monitor(priv);
  528. out:
  529. mutex_unlock(&priv->shrd->mutex);
  530. }
  531. /*
  532. * If BT sco traffic, and RSSI monitor is enabled, move measurements to the
  533. * correct interface or disable it if this is the last interface to be
  534. * removed.
  535. */
  536. void iwlagn_bt_coex_rssi_monitor(struct iwl_priv *priv)
  537. {
  538. if (priv->bt_is_sco &&
  539. priv->bt_traffic_load == IWL_BT_COEX_TRAFFIC_LOAD_CONTINUOUS)
  540. iwlagn_bt_adjust_rssi_monitor(priv, true);
  541. else
  542. iwlagn_bt_adjust_rssi_monitor(priv, false);
  543. }
  544. static void iwlagn_print_uartmsg(struct iwl_priv *priv,
  545. struct iwl_bt_uart_msg *uart_msg)
  546. {
  547. IWL_DEBUG_COEX(priv, "Message Type = 0x%X, SSN = 0x%X, "
  548. "Update Req = 0x%X",
  549. (BT_UART_MSG_FRAME1MSGTYPE_MSK & uart_msg->frame1) >>
  550. BT_UART_MSG_FRAME1MSGTYPE_POS,
  551. (BT_UART_MSG_FRAME1SSN_MSK & uart_msg->frame1) >>
  552. BT_UART_MSG_FRAME1SSN_POS,
  553. (BT_UART_MSG_FRAME1UPDATEREQ_MSK & uart_msg->frame1) >>
  554. BT_UART_MSG_FRAME1UPDATEREQ_POS);
  555. IWL_DEBUG_COEX(priv, "Open connections = 0x%X, Traffic load = 0x%X, "
  556. "Chl_SeqN = 0x%X, In band = 0x%X",
  557. (BT_UART_MSG_FRAME2OPENCONNECTIONS_MSK & uart_msg->frame2) >>
  558. BT_UART_MSG_FRAME2OPENCONNECTIONS_POS,
  559. (BT_UART_MSG_FRAME2TRAFFICLOAD_MSK & uart_msg->frame2) >>
  560. BT_UART_MSG_FRAME2TRAFFICLOAD_POS,
  561. (BT_UART_MSG_FRAME2CHLSEQN_MSK & uart_msg->frame2) >>
  562. BT_UART_MSG_FRAME2CHLSEQN_POS,
  563. (BT_UART_MSG_FRAME2INBAND_MSK & uart_msg->frame2) >>
  564. BT_UART_MSG_FRAME2INBAND_POS);
  565. IWL_DEBUG_COEX(priv, "SCO/eSCO = 0x%X, Sniff = 0x%X, A2DP = 0x%X, "
  566. "ACL = 0x%X, Master = 0x%X, OBEX = 0x%X",
  567. (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) >>
  568. BT_UART_MSG_FRAME3SCOESCO_POS,
  569. (BT_UART_MSG_FRAME3SNIFF_MSK & uart_msg->frame3) >>
  570. BT_UART_MSG_FRAME3SNIFF_POS,
  571. (BT_UART_MSG_FRAME3A2DP_MSK & uart_msg->frame3) >>
  572. BT_UART_MSG_FRAME3A2DP_POS,
  573. (BT_UART_MSG_FRAME3ACL_MSK & uart_msg->frame3) >>
  574. BT_UART_MSG_FRAME3ACL_POS,
  575. (BT_UART_MSG_FRAME3MASTER_MSK & uart_msg->frame3) >>
  576. BT_UART_MSG_FRAME3MASTER_POS,
  577. (BT_UART_MSG_FRAME3OBEX_MSK & uart_msg->frame3) >>
  578. BT_UART_MSG_FRAME3OBEX_POS);
  579. IWL_DEBUG_COEX(priv, "Idle duration = 0x%X",
  580. (BT_UART_MSG_FRAME4IDLEDURATION_MSK & uart_msg->frame4) >>
  581. BT_UART_MSG_FRAME4IDLEDURATION_POS);
  582. IWL_DEBUG_COEX(priv, "Tx Activity = 0x%X, Rx Activity = 0x%X, "
  583. "eSCO Retransmissions = 0x%X",
  584. (BT_UART_MSG_FRAME5TXACTIVITY_MSK & uart_msg->frame5) >>
  585. BT_UART_MSG_FRAME5TXACTIVITY_POS,
  586. (BT_UART_MSG_FRAME5RXACTIVITY_MSK & uart_msg->frame5) >>
  587. BT_UART_MSG_FRAME5RXACTIVITY_POS,
  588. (BT_UART_MSG_FRAME5ESCORETRANSMIT_MSK & uart_msg->frame5) >>
  589. BT_UART_MSG_FRAME5ESCORETRANSMIT_POS);
  590. IWL_DEBUG_COEX(priv, "Sniff Interval = 0x%X, Discoverable = 0x%X",
  591. (BT_UART_MSG_FRAME6SNIFFINTERVAL_MSK & uart_msg->frame6) >>
  592. BT_UART_MSG_FRAME6SNIFFINTERVAL_POS,
  593. (BT_UART_MSG_FRAME6DISCOVERABLE_MSK & uart_msg->frame6) >>
  594. BT_UART_MSG_FRAME6DISCOVERABLE_POS);
  595. IWL_DEBUG_COEX(priv, "Sniff Activity = 0x%X, Page = "
  596. "0x%X, Inquiry = 0x%X, Connectable = 0x%X",
  597. (BT_UART_MSG_FRAME7SNIFFACTIVITY_MSK & uart_msg->frame7) >>
  598. BT_UART_MSG_FRAME7SNIFFACTIVITY_POS,
  599. (BT_UART_MSG_FRAME7PAGE_MSK & uart_msg->frame7) >>
  600. BT_UART_MSG_FRAME7PAGE_POS,
  601. (BT_UART_MSG_FRAME7INQUIRY_MSK & uart_msg->frame7) >>
  602. BT_UART_MSG_FRAME7INQUIRY_POS,
  603. (BT_UART_MSG_FRAME7CONNECTABLE_MSK & uart_msg->frame7) >>
  604. BT_UART_MSG_FRAME7CONNECTABLE_POS);
  605. }
  606. static void iwlagn_set_kill_msk(struct iwl_priv *priv,
  607. struct iwl_bt_uart_msg *uart_msg)
  608. {
  609. u8 kill_msk;
  610. static const __le32 bt_kill_ack_msg[2] = {
  611. IWLAGN_BT_KILL_ACK_MASK_DEFAULT,
  612. IWLAGN_BT_KILL_ACK_CTS_MASK_SCO };
  613. static const __le32 bt_kill_cts_msg[2] = {
  614. IWLAGN_BT_KILL_CTS_MASK_DEFAULT,
  615. IWLAGN_BT_KILL_ACK_CTS_MASK_SCO };
  616. kill_msk = (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3)
  617. ? 1 : 0;
  618. if (priv->kill_ack_mask != bt_kill_ack_msg[kill_msk] ||
  619. priv->kill_cts_mask != bt_kill_cts_msg[kill_msk]) {
  620. priv->bt_valid |= IWLAGN_BT_VALID_KILL_ACK_MASK;
  621. priv->kill_ack_mask = bt_kill_ack_msg[kill_msk];
  622. priv->bt_valid |= IWLAGN_BT_VALID_KILL_CTS_MASK;
  623. priv->kill_cts_mask = bt_kill_cts_msg[kill_msk];
  624. /* schedule to send runtime bt_config */
  625. queue_work(priv->shrd->workqueue, &priv->bt_runtime_config);
  626. }
  627. }
  628. int iwlagn_bt_coex_profile_notif(struct iwl_priv *priv,
  629. struct iwl_rx_mem_buffer *rxb,
  630. struct iwl_device_cmd *cmd)
  631. {
  632. unsigned long flags;
  633. struct iwl_rx_packet *pkt = rxb_addr(rxb);
  634. struct iwl_bt_coex_profile_notif *coex = &pkt->u.bt_coex_profile_notif;
  635. struct iwl_bt_uart_msg *uart_msg = &coex->last_bt_uart_msg;
  636. if (priv->bt_enable_flag == IWLAGN_BT_FLAG_COEX_MODE_DISABLED) {
  637. /* bt coex disabled */
  638. return 0;
  639. }
  640. IWL_DEBUG_COEX(priv, "BT Coex notification:\n");
  641. IWL_DEBUG_COEX(priv, " status: %d\n", coex->bt_status);
  642. IWL_DEBUG_COEX(priv, " traffic load: %d\n", coex->bt_traffic_load);
  643. IWL_DEBUG_COEX(priv, " CI compliance: %d\n",
  644. coex->bt_ci_compliance);
  645. iwlagn_print_uartmsg(priv, uart_msg);
  646. priv->last_bt_traffic_load = priv->bt_traffic_load;
  647. priv->bt_is_sco = iwlagn_bt_traffic_is_sco(uart_msg);
  648. if (priv->iw_mode != NL80211_IFTYPE_ADHOC) {
  649. if (priv->bt_status != coex->bt_status ||
  650. priv->last_bt_traffic_load != coex->bt_traffic_load) {
  651. if (coex->bt_status) {
  652. /* BT on */
  653. if (!priv->bt_ch_announce)
  654. priv->bt_traffic_load =
  655. IWL_BT_COEX_TRAFFIC_LOAD_HIGH;
  656. else
  657. priv->bt_traffic_load =
  658. coex->bt_traffic_load;
  659. } else {
  660. /* BT off */
  661. priv->bt_traffic_load =
  662. IWL_BT_COEX_TRAFFIC_LOAD_NONE;
  663. }
  664. priv->bt_status = coex->bt_status;
  665. queue_work(priv->shrd->workqueue,
  666. &priv->bt_traffic_change_work);
  667. }
  668. }
  669. iwlagn_set_kill_msk(priv, uart_msg);
  670. /* FIXME: based on notification, adjust the prio_boost */
  671. spin_lock_irqsave(&priv->shrd->lock, flags);
  672. priv->bt_ci_compliance = coex->bt_ci_compliance;
  673. spin_unlock_irqrestore(&priv->shrd->lock, flags);
  674. return 0;
  675. }
  676. void iwlagn_bt_rx_handler_setup(struct iwl_priv *priv)
  677. {
  678. priv->rx_handlers[REPLY_BT_COEX_PROFILE_NOTIF] =
  679. iwlagn_bt_coex_profile_notif;
  680. }
  681. void iwlagn_bt_setup_deferred_work(struct iwl_priv *priv)
  682. {
  683. INIT_WORK(&priv->bt_traffic_change_work,
  684. iwlagn_bt_traffic_change_work);
  685. }
  686. void iwlagn_bt_cancel_deferred_work(struct iwl_priv *priv)
  687. {
  688. cancel_work_sync(&priv->bt_traffic_change_work);
  689. }
  690. static bool is_single_rx_stream(struct iwl_priv *priv)
  691. {
  692. return priv->current_ht_config.smps == IEEE80211_SMPS_STATIC ||
  693. priv->current_ht_config.single_chain_sufficient;
  694. }
  695. #define IWL_NUM_RX_CHAINS_MULTIPLE 3
  696. #define IWL_NUM_RX_CHAINS_SINGLE 2
  697. #define IWL_NUM_IDLE_CHAINS_DUAL 2
  698. #define IWL_NUM_IDLE_CHAINS_SINGLE 1
  699. /*
  700. * Determine how many receiver/antenna chains to use.
  701. *
  702. * More provides better reception via diversity. Fewer saves power
  703. * at the expense of throughput, but only when not in powersave to
  704. * start with.
  705. *
  706. * MIMO (dual stream) requires at least 2, but works better with 3.
  707. * This does not determine *which* chains to use, just how many.
  708. */
  709. static int iwl_get_active_rx_chain_count(struct iwl_priv *priv)
  710. {
  711. if (priv->cfg->bt_params &&
  712. priv->cfg->bt_params->advanced_bt_coexist &&
  713. (priv->bt_full_concurrent ||
  714. priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
  715. /*
  716. * only use chain 'A' in bt high traffic load or
  717. * full concurrency mode
  718. */
  719. return IWL_NUM_RX_CHAINS_SINGLE;
  720. }
  721. /* # of Rx chains to use when expecting MIMO. */
  722. if (is_single_rx_stream(priv))
  723. return IWL_NUM_RX_CHAINS_SINGLE;
  724. else
  725. return IWL_NUM_RX_CHAINS_MULTIPLE;
  726. }
  727. /*
  728. * When we are in power saving mode, unless device support spatial
  729. * multiplexing power save, use the active count for rx chain count.
  730. */
  731. static int iwl_get_idle_rx_chain_count(struct iwl_priv *priv, int active_cnt)
  732. {
  733. /* # Rx chains when idling, depending on SMPS mode */
  734. switch (priv->current_ht_config.smps) {
  735. case IEEE80211_SMPS_STATIC:
  736. case IEEE80211_SMPS_DYNAMIC:
  737. return IWL_NUM_IDLE_CHAINS_SINGLE;
  738. case IEEE80211_SMPS_OFF:
  739. return active_cnt;
  740. default:
  741. WARN(1, "invalid SMPS mode %d",
  742. priv->current_ht_config.smps);
  743. return active_cnt;
  744. }
  745. }
  746. /* up to 4 chains */
  747. static u8 iwl_count_chain_bitmap(u32 chain_bitmap)
  748. {
  749. u8 res;
  750. res = (chain_bitmap & BIT(0)) >> 0;
  751. res += (chain_bitmap & BIT(1)) >> 1;
  752. res += (chain_bitmap & BIT(2)) >> 2;
  753. res += (chain_bitmap & BIT(3)) >> 3;
  754. return res;
  755. }
  756. /**
  757. * iwlagn_set_rxon_chain - Set up Rx chain usage in "staging" RXON image
  758. *
  759. * Selects how many and which Rx receivers/antennas/chains to use.
  760. * This should not be used for scan command ... it puts data in wrong place.
  761. */
  762. void iwlagn_set_rxon_chain(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
  763. {
  764. bool is_single = is_single_rx_stream(priv);
  765. bool is_cam = !test_bit(STATUS_POWER_PMI, &priv->shrd->status);
  766. u8 idle_rx_cnt, active_rx_cnt, valid_rx_cnt;
  767. u32 active_chains;
  768. u16 rx_chain;
  769. /* Tell uCode which antennas are actually connected.
  770. * Before first association, we assume all antennas are connected.
  771. * Just after first association, iwl_chain_noise_calibration()
  772. * checks which antennas actually *are* connected. */
  773. if (priv->chain_noise_data.active_chains)
  774. active_chains = priv->chain_noise_data.active_chains;
  775. else
  776. active_chains = hw_params(priv).valid_rx_ant;
  777. if (priv->cfg->bt_params &&
  778. priv->cfg->bt_params->advanced_bt_coexist &&
  779. (priv->bt_full_concurrent ||
  780. priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)) {
  781. /*
  782. * only use chain 'A' in bt high traffic load or
  783. * full concurrency mode
  784. */
  785. active_chains = first_antenna(active_chains);
  786. }
  787. rx_chain = active_chains << RXON_RX_CHAIN_VALID_POS;
  788. /* How many receivers should we use? */
  789. active_rx_cnt = iwl_get_active_rx_chain_count(priv);
  790. idle_rx_cnt = iwl_get_idle_rx_chain_count(priv, active_rx_cnt);
  791. /* correct rx chain count according hw settings
  792. * and chain noise calibration
  793. */
  794. valid_rx_cnt = iwl_count_chain_bitmap(active_chains);
  795. if (valid_rx_cnt < active_rx_cnt)
  796. active_rx_cnt = valid_rx_cnt;
  797. if (valid_rx_cnt < idle_rx_cnt)
  798. idle_rx_cnt = valid_rx_cnt;
  799. rx_chain |= active_rx_cnt << RXON_RX_CHAIN_MIMO_CNT_POS;
  800. rx_chain |= idle_rx_cnt << RXON_RX_CHAIN_CNT_POS;
  801. ctx->staging.rx_chain = cpu_to_le16(rx_chain);
  802. if (!is_single && (active_rx_cnt >= IWL_NUM_RX_CHAINS_SINGLE) && is_cam)
  803. ctx->staging.rx_chain |= RXON_RX_CHAIN_MIMO_FORCE_MSK;
  804. else
  805. ctx->staging.rx_chain &= ~RXON_RX_CHAIN_MIMO_FORCE_MSK;
  806. IWL_DEBUG_ASSOC(priv, "rx_chain=0x%X active=%d idle=%d\n",
  807. ctx->staging.rx_chain,
  808. active_rx_cnt, idle_rx_cnt);
  809. WARN_ON(active_rx_cnt == 0 || idle_rx_cnt == 0 ||
  810. active_rx_cnt < idle_rx_cnt);
  811. }
  812. u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant, u8 valid)
  813. {
  814. int i;
  815. u8 ind = ant;
  816. if (priv->band == IEEE80211_BAND_2GHZ &&
  817. priv->bt_traffic_load >= IWL_BT_COEX_TRAFFIC_LOAD_HIGH)
  818. return 0;
  819. for (i = 0; i < RATE_ANT_NUM - 1; i++) {
  820. ind = (ind + 1) < RATE_ANT_NUM ? ind + 1 : 0;
  821. if (valid & BIT(ind))
  822. return ind;
  823. }
  824. return ant;
  825. }
  826. /* notification wait support */
  827. void iwlagn_init_notification_wait(struct iwl_priv *priv,
  828. struct iwl_notification_wait *wait_entry,
  829. u8 cmd,
  830. void (*fn)(struct iwl_priv *priv,
  831. struct iwl_rx_packet *pkt,
  832. void *data),
  833. void *fn_data)
  834. {
  835. wait_entry->fn = fn;
  836. wait_entry->fn_data = fn_data;
  837. wait_entry->cmd = cmd;
  838. wait_entry->triggered = false;
  839. wait_entry->aborted = false;
  840. spin_lock_bh(&priv->notif_wait_lock);
  841. list_add(&wait_entry->list, &priv->notif_waits);
  842. spin_unlock_bh(&priv->notif_wait_lock);
  843. }
  844. int iwlagn_wait_notification(struct iwl_priv *priv,
  845. struct iwl_notification_wait *wait_entry,
  846. unsigned long timeout)
  847. {
  848. int ret;
  849. ret = wait_event_timeout(priv->notif_waitq,
  850. wait_entry->triggered || wait_entry->aborted,
  851. timeout);
  852. spin_lock_bh(&priv->notif_wait_lock);
  853. list_del(&wait_entry->list);
  854. spin_unlock_bh(&priv->notif_wait_lock);
  855. if (wait_entry->aborted)
  856. return -EIO;
  857. /* return value is always >= 0 */
  858. if (ret <= 0)
  859. return -ETIMEDOUT;
  860. return 0;
  861. }
  862. void iwlagn_remove_notification(struct iwl_priv *priv,
  863. struct iwl_notification_wait *wait_entry)
  864. {
  865. spin_lock_bh(&priv->notif_wait_lock);
  866. list_del(&wait_entry->list);
  867. spin_unlock_bh(&priv->notif_wait_lock);
  868. }