coex.c 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326
  1. /******************************************************************************
  2. *
  3. * This file is provided under a dual BSD/GPLv2 license. When using or
  4. * redistributing this file, you may do so under either license.
  5. *
  6. * GPL LICENSE SUMMARY
  7. *
  8. * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
  9. *
  10. * This program is free software; you can redistribute it and/or modify
  11. * it under the terms of version 2 of the GNU General Public License as
  12. * published by the Free Software Foundation.
  13. *
  14. * This program is distributed in the hope that it will be useful, but
  15. * WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with this program; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
  22. * USA
  23. *
  24. * The full GNU General Public License is included in this distribution
  25. * in the file called COPYING.
  26. *
  27. * Contact Information:
  28. * Intel Linux Wireless <ilw@linux.intel.com>
  29. * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  30. *
  31. * BSD LICENSE
  32. *
  33. * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
  34. * All rights reserved.
  35. *
  36. * Redistribution and use in source and binary forms, with or without
  37. * modification, are permitted provided that the following conditions
  38. * are met:
  39. *
  40. * * Redistributions of source code must retain the above copyright
  41. * notice, this list of conditions and the following disclaimer.
  42. * * Redistributions in binary form must reproduce the above copyright
  43. * notice, this list of conditions and the following disclaimer in
  44. * the documentation and/or other materials provided with the
  45. * distribution.
  46. * * Neither the name Intel Corporation nor the names of its
  47. * contributors may be used to endorse or promote products derived
  48. * from this software without specific prior written permission.
  49. *
  50. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  51. * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  52. * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  53. * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  54. * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  55. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  56. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  57. * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  58. * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  59. * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  60. * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  61. *
  62. *****************************************************************************/
  63. #include <linux/ieee80211.h>
  64. #include <linux/etherdevice.h>
  65. #include <net/mac80211.h>
  66. #include "fw-api-coex.h"
  67. #include "iwl-modparams.h"
  68. #include "mvm.h"
  69. #include "iwl-debug.h"
  70. #define EVENT_PRIO_ANT(_evt, _prio, _shrd_ant) \
  71. [(_evt)] = (((_prio) << BT_COEX_PRIO_TBL_PRIO_POS) | \
  72. ((_shrd_ant) << BT_COEX_PRIO_TBL_SHRD_ANT_POS))
  73. static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
  74. EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_INIT_CALIB1,
  75. BT_COEX_PRIO_TBL_PRIO_BYPASS, 0),
  76. EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_INIT_CALIB2,
  77. BT_COEX_PRIO_TBL_PRIO_BYPASS, 1),
  78. EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW1,
  79. BT_COEX_PRIO_TBL_PRIO_LOW, 0),
  80. EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW2,
  81. BT_COEX_PRIO_TBL_PRIO_LOW, 1),
  82. EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH1,
  83. BT_COEX_PRIO_TBL_PRIO_HIGH, 0),
  84. EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH2,
  85. BT_COEX_PRIO_TBL_PRIO_HIGH, 1),
  86. EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_DTIM,
  87. BT_COEX_PRIO_TBL_DISABLED, 0),
  88. EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_SCAN52,
  89. BT_COEX_PRIO_TBL_PRIO_COEX_OFF, 0),
  90. EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_SCAN24,
  91. BT_COEX_PRIO_TBL_PRIO_COEX_ON, 0),
  92. EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_IDLE,
  93. BT_COEX_PRIO_TBL_PRIO_COEX_IDLE, 0),
  94. 0, 0, 0, 0, 0, 0,
  95. };
  96. #undef EVENT_PRIO_ANT
  97. #define BT_ENABLE_REDUCED_TXPOWER_THRESHOLD (-62)
  98. #define BT_DISABLE_REDUCED_TXPOWER_THRESHOLD (-65)
  99. #define BT_ANTENNA_COUPLING_THRESHOLD (30)
  100. int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm)
  101. {
  102. if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWBT_COEX))
  103. return 0;
  104. return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, CMD_SYNC,
  105. sizeof(struct iwl_bt_coex_prio_tbl_cmd),
  106. &iwl_bt_prio_tbl);
  107. }
  108. const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = {
  109. [BT_KILL_MSK_DEFAULT] = 0xffff0000,
  110. [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff,
  111. [BT_KILL_MSK_REDUCED_TXPOW] = 0,
  112. };
  113. const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = {
  114. [BT_KILL_MSK_DEFAULT] = 0xffff0000,
  115. [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff,
  116. [BT_KILL_MSK_REDUCED_TXPOW] = 0,
  117. };
  118. static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = {
  119. cpu_to_le32(0xf0f0f0f0),
  120. cpu_to_le32(0xc0c0c0c0),
  121. cpu_to_le32(0xfcfcfcfc),
  122. cpu_to_le32(0xff00ff00),
  123. };
  124. static const __le32 iwl_single_shared_ant[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = {
  125. {
  126. cpu_to_le32(0x40000000),
  127. cpu_to_le32(0x00000000),
  128. cpu_to_le32(0x44000000),
  129. cpu_to_le32(0x00000000),
  130. cpu_to_le32(0x40000000),
  131. cpu_to_le32(0x00000000),
  132. cpu_to_le32(0x44000000),
  133. cpu_to_le32(0x00000000),
  134. cpu_to_le32(0xc0004000),
  135. cpu_to_le32(0xf0005000),
  136. cpu_to_le32(0xc0004000),
  137. cpu_to_le32(0xf0005000),
  138. },
  139. {
  140. cpu_to_le32(0x40000000),
  141. cpu_to_le32(0x00000000),
  142. cpu_to_le32(0x44000000),
  143. cpu_to_le32(0x00000000),
  144. cpu_to_le32(0x40000000),
  145. cpu_to_le32(0x00000000),
  146. cpu_to_le32(0x44000000),
  147. cpu_to_le32(0x00000000),
  148. cpu_to_le32(0xc0004000),
  149. cpu_to_le32(0xf0005000),
  150. cpu_to_le32(0xc0004000),
  151. cpu_to_le32(0xf0005000),
  152. },
  153. {
  154. cpu_to_le32(0x40000000),
  155. cpu_to_le32(0x00000000),
  156. cpu_to_le32(0x44000000),
  157. cpu_to_le32(0x00000000),
  158. cpu_to_le32(0x40000000),
  159. cpu_to_le32(0x00000000),
  160. cpu_to_le32(0x44000000),
  161. cpu_to_le32(0x00000000),
  162. cpu_to_le32(0xc0004000),
  163. cpu_to_le32(0xf0005000),
  164. cpu_to_le32(0xc0004000),
  165. cpu_to_le32(0xf0005000),
  166. },
  167. };
  168. static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = {
  169. {
  170. /* Tight */
  171. cpu_to_le32(0xaaaaaaaa),
  172. cpu_to_le32(0xaaaaaaaa),
  173. cpu_to_le32(0xaeaaaaaa),
  174. cpu_to_le32(0xaaaaaaaa),
  175. cpu_to_le32(0xcc00ff28),
  176. cpu_to_le32(0x0000aaaa),
  177. cpu_to_le32(0xcc00aaaa),
  178. cpu_to_le32(0x0000aaaa),
  179. cpu_to_le32(0xc0004000),
  180. cpu_to_le32(0x00004000),
  181. cpu_to_le32(0xf0005000),
  182. cpu_to_le32(0xf0005000),
  183. },
  184. {
  185. /* Loose */
  186. cpu_to_le32(0xaaaaaaaa),
  187. cpu_to_le32(0xaaaaaaaa),
  188. cpu_to_le32(0xaaaaaaaa),
  189. cpu_to_le32(0xaaaaaaaa),
  190. cpu_to_le32(0xcc00ff28),
  191. cpu_to_le32(0x0000aaaa),
  192. cpu_to_le32(0xcc00aaaa),
  193. cpu_to_le32(0x0000aaaa),
  194. cpu_to_le32(0x00000000),
  195. cpu_to_le32(0x00000000),
  196. cpu_to_le32(0xf0005000),
  197. cpu_to_le32(0xf0005000),
  198. },
  199. {
  200. /* Tx Tx disabled */
  201. cpu_to_le32(0xaaaaaaaa),
  202. cpu_to_le32(0xaaaaaaaa),
  203. cpu_to_le32(0xeeaaaaaa),
  204. cpu_to_le32(0xaaaaaaaa),
  205. cpu_to_le32(0xcc00ff28),
  206. cpu_to_le32(0x0000aaaa),
  207. cpu_to_le32(0xcc00aaaa),
  208. cpu_to_le32(0x0000aaaa),
  209. cpu_to_le32(0xc0004000),
  210. cpu_to_le32(0xc0004000),
  211. cpu_to_le32(0xf0005000),
  212. cpu_to_le32(0xf0005000),
  213. },
  214. };
  215. /* 20MHz / 40MHz below / 40Mhz above*/
  216. static const __le64 iwl_ci_mask[][3] = {
  217. /* dummy entry for channel 0 */
  218. {cpu_to_le64(0), cpu_to_le64(0), cpu_to_le64(0)},
  219. {
  220. cpu_to_le64(0x0000001FFFULL),
  221. cpu_to_le64(0x0ULL),
  222. cpu_to_le64(0x00007FFFFFULL),
  223. },
  224. {
  225. cpu_to_le64(0x000000FFFFULL),
  226. cpu_to_le64(0x0ULL),
  227. cpu_to_le64(0x0003FFFFFFULL),
  228. },
  229. {
  230. cpu_to_le64(0x000003FFFCULL),
  231. cpu_to_le64(0x0ULL),
  232. cpu_to_le64(0x000FFFFFFCULL),
  233. },
  234. {
  235. cpu_to_le64(0x00001FFFE0ULL),
  236. cpu_to_le64(0x0ULL),
  237. cpu_to_le64(0x007FFFFFE0ULL),
  238. },
  239. {
  240. cpu_to_le64(0x00007FFF80ULL),
  241. cpu_to_le64(0x00007FFFFFULL),
  242. cpu_to_le64(0x01FFFFFF80ULL),
  243. },
  244. {
  245. cpu_to_le64(0x0003FFFC00ULL),
  246. cpu_to_le64(0x0003FFFFFFULL),
  247. cpu_to_le64(0x0FFFFFFC00ULL),
  248. },
  249. {
  250. cpu_to_le64(0x000FFFF000ULL),
  251. cpu_to_le64(0x000FFFFFFCULL),
  252. cpu_to_le64(0x3FFFFFF000ULL),
  253. },
  254. {
  255. cpu_to_le64(0x007FFF8000ULL),
  256. cpu_to_le64(0x007FFFFFE0ULL),
  257. cpu_to_le64(0xFFFFFF8000ULL),
  258. },
  259. {
  260. cpu_to_le64(0x01FFFE0000ULL),
  261. cpu_to_le64(0x01FFFFFF80ULL),
  262. cpu_to_le64(0xFFFFFE0000ULL),
  263. },
  264. {
  265. cpu_to_le64(0x0FFFF00000ULL),
  266. cpu_to_le64(0x0FFFFFFC00ULL),
  267. cpu_to_le64(0x0ULL),
  268. },
  269. {
  270. cpu_to_le64(0x3FFFC00000ULL),
  271. cpu_to_le64(0x3FFFFFF000ULL),
  272. cpu_to_le64(0x0)
  273. },
  274. {
  275. cpu_to_le64(0xFFFE000000ULL),
  276. cpu_to_le64(0xFFFFFF8000ULL),
  277. cpu_to_le64(0x0)
  278. },
  279. {
  280. cpu_to_le64(0xFFF8000000ULL),
  281. cpu_to_le64(0xFFFFFE0000ULL),
  282. cpu_to_le64(0x0)
  283. },
  284. {
  285. cpu_to_le64(0xFFC0000000ULL),
  286. cpu_to_le64(0x0ULL),
  287. cpu_to_le64(0x0ULL)
  288. },
  289. };
  290. static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = {
  291. cpu_to_le32(0x22002200),
  292. cpu_to_le32(0x33113311),
  293. };
  294. struct corunning_block_luts {
  295. u8 range;
  296. __le32 lut20[BT_COEX_CORUN_LUT_SIZE];
  297. };
  298. /*
  299. * Ranges for the antenna coupling calibration / co-running block LUT:
  300. * LUT0: [ 0, 12[
  301. * LUT1: [12, 20[
  302. * LUT2: [20, 21[
  303. * LUT3: [21, 23[
  304. * LUT4: [23, 27[
  305. * LUT5: [27, 30[
  306. * LUT6: [30, 32[
  307. * LUT7: [32, 33[
  308. * LUT8: [33, - [
  309. */
  310. static const struct corunning_block_luts antenna_coupling_ranges[] = {
  311. {
  312. .range = 0,
  313. .lut20 = {
  314. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  315. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  316. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  317. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  318. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  319. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  320. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  321. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  322. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  323. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  324. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  325. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  326. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  327. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  328. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  329. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  330. },
  331. },
  332. {
  333. .range = 12,
  334. .lut20 = {
  335. cpu_to_le32(0x00000001), cpu_to_le32(0x00000000),
  336. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  337. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  338. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  339. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  340. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  341. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  342. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  343. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  344. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  345. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  346. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  347. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  348. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  349. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  350. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  351. },
  352. },
  353. {
  354. .range = 20,
  355. .lut20 = {
  356. cpu_to_le32(0x00000002), cpu_to_le32(0x00000000),
  357. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  358. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  359. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  360. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  361. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  362. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  363. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  364. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  365. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  366. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  367. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  368. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  369. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  370. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  371. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  372. },
  373. },
  374. {
  375. .range = 21,
  376. .lut20 = {
  377. cpu_to_le32(0x00000003), cpu_to_le32(0x00000000),
  378. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  379. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  380. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  381. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  382. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  383. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  384. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  385. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  386. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  387. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  388. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  389. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  390. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  391. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  392. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  393. },
  394. },
  395. {
  396. .range = 23,
  397. .lut20 = {
  398. cpu_to_le32(0x00000004), cpu_to_le32(0x00000000),
  399. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  400. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  401. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  402. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  403. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  404. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  405. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  406. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  407. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  408. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  409. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  410. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  411. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  412. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  413. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  414. },
  415. },
  416. {
  417. .range = 27,
  418. .lut20 = {
  419. cpu_to_le32(0x00000005), cpu_to_le32(0x00000000),
  420. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  421. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  422. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  423. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  424. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  425. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  426. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  427. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  428. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  429. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  430. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  431. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  432. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  433. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  434. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  435. },
  436. },
  437. {
  438. .range = 30,
  439. .lut20 = {
  440. cpu_to_le32(0x00000006), cpu_to_le32(0x00000000),
  441. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  442. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  443. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  444. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  445. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  446. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  447. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  448. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  449. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  450. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  451. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  452. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  453. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  454. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  455. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  456. },
  457. },
  458. {
  459. .range = 32,
  460. .lut20 = {
  461. cpu_to_le32(0x00000007), cpu_to_le32(0x00000000),
  462. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  463. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  464. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  465. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  466. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  467. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  468. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  469. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  470. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  471. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  472. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  473. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  474. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  475. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  476. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  477. },
  478. },
  479. {
  480. .range = 33,
  481. .lut20 = {
  482. cpu_to_le32(0x00000008), cpu_to_le32(0x00000000),
  483. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  484. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  485. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  486. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  487. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  488. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  489. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  490. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  491. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  492. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  493. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  494. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  495. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  496. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  497. cpu_to_le32(0x00000000), cpu_to_le32(0x00000000),
  498. },
  499. },
  500. };
  501. static enum iwl_bt_coex_lut_type
  502. iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif)
  503. {
  504. struct ieee80211_chanctx_conf *chanctx_conf;
  505. enum iwl_bt_coex_lut_type ret;
  506. u16 phy_ctx_id;
  507. /*
  508. * Checking that we hold mvm->mutex is a good idea, but the rate
  509. * control can't acquire the mutex since it runs in Tx path.
  510. * So this is racy in that case, but in the worst case, the AMPDU
  511. * size limit will be wrong for a short time which is not a big
  512. * issue.
  513. */
  514. rcu_read_lock();
  515. chanctx_conf = rcu_dereference(vif->chanctx_conf);
  516. if (!chanctx_conf ||
  517. chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) {
  518. rcu_read_unlock();
  519. return BT_COEX_LOOSE_LUT;
  520. }
  521. ret = BT_COEX_TX_DIS_LUT;
  522. if (mvm->cfg->bt_shared_single_ant) {
  523. rcu_read_unlock();
  524. return ret;
  525. }
  526. phy_ctx_id = *((u16 *)chanctx_conf->drv_priv);
  527. if (mvm->last_bt_ci_cmd.primary_ch_phy_id == phy_ctx_id)
  528. ret = le32_to_cpu(mvm->last_bt_notif.primary_ch_lut);
  529. else if (mvm->last_bt_ci_cmd.secondary_ch_phy_id == phy_ctx_id)
  530. ret = le32_to_cpu(mvm->last_bt_notif.secondary_ch_lut);
  531. /* else - default = TX TX disallowed */
  532. rcu_read_unlock();
  533. return ret;
  534. }
  535. int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
  536. {
  537. struct iwl_bt_coex_cmd *bt_cmd;
  538. struct iwl_host_cmd cmd = {
  539. .id = BT_CONFIG,
  540. .len = { sizeof(*bt_cmd), },
  541. .dataflags = { IWL_HCMD_DFL_NOCOPY, },
  542. .flags = CMD_SYNC,
  543. };
  544. int ret;
  545. u32 flags;
  546. if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWBT_COEX))
  547. return 0;
  548. bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
  549. if (!bt_cmd)
  550. return -ENOMEM;
  551. cmd.data[0] = bt_cmd;
  552. bt_cmd->max_kill = 5;
  553. bt_cmd->bt4_antenna_isolation_thr = BT_ANTENNA_COUPLING_THRESHOLD,
  554. bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling,
  555. bt_cmd->bt4_tx_tx_delta_freq_thr = 15,
  556. bt_cmd->bt4_tx_rx_max_freq0 = 15,
  557. flags = iwlwifi_mod_params.bt_coex_active ?
  558. BT_COEX_NW : BT_COEX_DISABLE;
  559. bt_cmd->flags = cpu_to_le32(flags);
  560. bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_ENABLE |
  561. BT_VALID_BT_PRIO_BOOST |
  562. BT_VALID_MAX_KILL |
  563. BT_VALID_3W_TMRS |
  564. BT_VALID_KILL_ACK |
  565. BT_VALID_KILL_CTS |
  566. BT_VALID_REDUCED_TX_POWER |
  567. BT_VALID_LUT |
  568. BT_VALID_WIFI_RX_SW_PRIO_BOOST |
  569. BT_VALID_WIFI_TX_SW_PRIO_BOOST |
  570. BT_VALID_ANT_ISOLATION |
  571. BT_VALID_ANT_ISOLATION_THRS |
  572. BT_VALID_TXTX_DELTA_FREQ_THRS |
  573. BT_VALID_TXRX_MAX_FREQ_0 |
  574. BT_VALID_SYNC_TO_SCO);
  575. if (IWL_MVM_BT_COEX_SYNC2SCO)
  576. bt_cmd->flags |= cpu_to_le32(BT_COEX_SYNC2SCO);
  577. if (IWL_MVM_BT_COEX_CORUNNING) {
  578. bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_CORUN_LUT_20 |
  579. BT_VALID_CORUN_LUT_40);
  580. bt_cmd->flags |= cpu_to_le32(BT_COEX_CORUNNING);
  581. }
  582. if (IWL_MVM_BT_COEX_MPLUT) {
  583. bt_cmd->flags |= cpu_to_le32(BT_COEX_MPLUT);
  584. bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_MULTI_PRIO_LUT);
  585. }
  586. if (mvm->cfg->bt_shared_single_ant)
  587. memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant,
  588. sizeof(iwl_single_shared_ant));
  589. else
  590. memcpy(&bt_cmd->decision_lut, iwl_combined_lookup,
  591. sizeof(iwl_combined_lookup));
  592. /* Take first Co-running block LUT to get started */
  593. memcpy(bt_cmd->bt4_corun_lut20, antenna_coupling_ranges[0].lut20,
  594. sizeof(bt_cmd->bt4_corun_lut20));
  595. memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[0].lut20,
  596. sizeof(bt_cmd->bt4_corun_lut40));
  597. memcpy(&bt_cmd->bt_prio_boost, iwl_bt_prio_boost,
  598. sizeof(iwl_bt_prio_boost));
  599. memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut,
  600. sizeof(iwl_bt_mprio_lut));
  601. bt_cmd->kill_ack_msk =
  602. cpu_to_le32(iwl_bt_ack_kill_msk[BT_KILL_MSK_DEFAULT]);
  603. bt_cmd->kill_cts_msk =
  604. cpu_to_le32(iwl_bt_cts_kill_msk[BT_KILL_MSK_DEFAULT]);
  605. memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
  606. memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd));
  607. ret = iwl_mvm_send_cmd(mvm, &cmd);
  608. kfree(bt_cmd);
  609. return ret;
  610. }
  611. static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
  612. bool reduced_tx_power)
  613. {
  614. enum iwl_bt_kill_msk bt_kill_msk;
  615. struct iwl_bt_coex_cmd *bt_cmd;
  616. struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
  617. struct iwl_host_cmd cmd = {
  618. .id = BT_CONFIG,
  619. .data[0] = &bt_cmd,
  620. .len = { sizeof(*bt_cmd), },
  621. .dataflags = { IWL_HCMD_DFL_NOCOPY, },
  622. .flags = CMD_SYNC,
  623. };
  624. int ret = 0;
  625. lockdep_assert_held(&mvm->mutex);
  626. if (reduced_tx_power) {
  627. /* Reduced Tx power has precedence on the type of the profile */
  628. bt_kill_msk = BT_KILL_MSK_REDUCED_TXPOW;
  629. } else {
  630. /* Low latency BT profile is active: give higher prio to BT */
  631. if (BT_MBOX_MSG(notif, 3, SCO_STATE) ||
  632. BT_MBOX_MSG(notif, 3, A2DP_STATE) ||
  633. BT_MBOX_MSG(notif, 3, SNIFF_STATE))
  634. bt_kill_msk = BT_KILL_MSK_SCO_HID_A2DP;
  635. else
  636. bt_kill_msk = BT_KILL_MSK_DEFAULT;
  637. }
  638. IWL_DEBUG_COEX(mvm,
  639. "Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive\n",
  640. bt_kill_msk,
  641. BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in",
  642. BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in",
  643. BT_MBOX_MSG(notif, 3, SNIFF_STATE) ? "" : "in");
  644. /* Don't send HCMD if there is no update */
  645. if (bt_kill_msk == mvm->bt_kill_msk)
  646. return 0;
  647. mvm->bt_kill_msk = bt_kill_msk;
  648. bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
  649. if (!bt_cmd)
  650. return -ENOMEM;
  651. cmd.data[0] = bt_cmd;
  652. bt_cmd->flags = cpu_to_le32(BT_COEX_NW);
  653. bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]);
  654. bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]);
  655. bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE |
  656. BT_VALID_KILL_ACK |
  657. BT_VALID_KILL_CTS);
  658. IWL_DEBUG_COEX(mvm, "ACK Kill msk = 0x%08x, CTS Kill msk = 0x%08x\n",
  659. iwl_bt_ack_kill_msk[bt_kill_msk],
  660. iwl_bt_cts_kill_msk[bt_kill_msk]);
  661. ret = iwl_mvm_send_cmd(mvm, &cmd);
  662. kfree(bt_cmd);
  663. return ret;
  664. }
  665. int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, bool enable)
  666. {
  667. struct iwl_bt_coex_cmd *bt_cmd;
  668. /* Send ASYNC since this can be sent from an atomic context */
  669. struct iwl_host_cmd cmd = {
  670. .id = BT_CONFIG,
  671. .len = { sizeof(*bt_cmd), },
  672. .dataflags = { IWL_HCMD_DFL_NOCOPY, },
  673. .flags = CMD_ASYNC,
  674. };
  675. struct iwl_mvm_sta *mvmsta;
  676. int ret;
  677. mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
  678. if (!mvmsta)
  679. return 0;
  680. /* nothing to do */
  681. if (mvmsta->bt_reduced_txpower_dbg ||
  682. mvmsta->bt_reduced_txpower == enable)
  683. return 0;
  684. bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_ATOMIC);
  685. if (!bt_cmd)
  686. return -ENOMEM;
  687. cmd.data[0] = bt_cmd;
  688. bt_cmd->flags = cpu_to_le32(BT_COEX_NW);
  689. bt_cmd->valid_bit_msk =
  690. cpu_to_le32(BT_VALID_ENABLE | BT_VALID_REDUCED_TX_POWER);
  691. bt_cmd->bt_reduced_tx_power = sta_id;
  692. if (enable)
  693. bt_cmd->bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT;
  694. IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n",
  695. enable ? "en" : "dis", sta_id);
  696. mvmsta->bt_reduced_txpower = enable;
  697. ret = iwl_mvm_send_cmd(mvm, &cmd);
  698. kfree(bt_cmd);
  699. return ret;
  700. }
  701. struct iwl_bt_iterator_data {
  702. struct iwl_bt_coex_profile_notif *notif;
  703. struct iwl_mvm *mvm;
  704. u32 num_bss_ifaces;
  705. bool reduced_tx_power;
  706. struct ieee80211_chanctx_conf *primary;
  707. struct ieee80211_chanctx_conf *secondary;
  708. bool primary_ll;
  709. };
  710. static inline
  711. void iwl_mvm_bt_coex_enable_rssi_event(struct iwl_mvm *mvm,
  712. struct ieee80211_vif *vif,
  713. bool enable, int rssi)
  714. {
  715. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  716. mvmvif->bf_data.last_bt_coex_event = rssi;
  717. mvmvif->bf_data.bt_coex_max_thold =
  718. enable ? BT_ENABLE_REDUCED_TXPOWER_THRESHOLD : 0;
  719. mvmvif->bf_data.bt_coex_min_thold =
  720. enable ? BT_DISABLE_REDUCED_TXPOWER_THRESHOLD : 0;
  721. }
  722. /* must be called under rcu_read_lock */
  723. static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
  724. struct ieee80211_vif *vif)
  725. {
  726. struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  727. struct iwl_bt_iterator_data *data = _data;
  728. struct iwl_mvm *mvm = data->mvm;
  729. struct ieee80211_chanctx_conf *chanctx_conf;
  730. enum ieee80211_smps_mode smps_mode;
  731. u32 bt_activity_grading;
  732. int ave_rssi;
  733. lockdep_assert_held(&mvm->mutex);
  734. switch (vif->type) {
  735. case NL80211_IFTYPE_STATION:
  736. /* default smps_mode for BSS / P2P client is AUTOMATIC */
  737. smps_mode = IEEE80211_SMPS_AUTOMATIC;
  738. data->num_bss_ifaces++;
  739. /*
  740. * Count unassoc BSSes, relax SMSP constraints
  741. * and disable reduced Tx Power
  742. */
  743. if (!vif->bss_conf.assoc) {
  744. iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
  745. smps_mode);
  746. if (iwl_mvm_bt_coex_reduced_txp(mvm,
  747. mvmvif->ap_sta_id,
  748. false))
  749. IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
  750. return;
  751. }
  752. break;
  753. case NL80211_IFTYPE_AP:
  754. /* default smps_mode for AP / GO is OFF */
  755. smps_mode = IEEE80211_SMPS_OFF;
  756. if (!mvmvif->ap_ibss_active) {
  757. iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
  758. smps_mode);
  759. return;
  760. }
  761. /* the Ack / Cts kill mask must be default if AP / GO */
  762. data->reduced_tx_power = false;
  763. break;
  764. default:
  765. return;
  766. }
  767. chanctx_conf = rcu_dereference(vif->chanctx_conf);
  768. /* If channel context is invalid or not on 2.4GHz .. */
  769. if ((!chanctx_conf ||
  770. chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) {
  771. /* ... relax constraints and disable rssi events */
  772. iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
  773. smps_mode);
  774. if (vif->type == NL80211_IFTYPE_STATION)
  775. iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
  776. return;
  777. }
  778. bt_activity_grading = le32_to_cpu(data->notif->bt_activity_grading);
  779. if (bt_activity_grading >= BT_HIGH_TRAFFIC)
  780. smps_mode = IEEE80211_SMPS_STATIC;
  781. else if (bt_activity_grading >= BT_LOW_TRAFFIC)
  782. smps_mode = vif->type == NL80211_IFTYPE_AP ?
  783. IEEE80211_SMPS_OFF :
  784. IEEE80211_SMPS_DYNAMIC;
  785. IWL_DEBUG_COEX(data->mvm,
  786. "mac %d: bt_status %d bt_activity_grading %d smps_req %d\n",
  787. mvmvif->id, data->notif->bt_status, bt_activity_grading,
  788. smps_mode);
  789. iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode);
  790. /* low latency is always primary */
  791. if (iwl_mvm_vif_low_latency(mvmvif)) {
  792. data->primary_ll = true;
  793. data->secondary = data->primary;
  794. data->primary = chanctx_conf;
  795. }
  796. if (vif->type == NL80211_IFTYPE_AP) {
  797. if (!mvmvif->ap_ibss_active)
  798. return;
  799. if (chanctx_conf == data->primary)
  800. return;
  801. if (!data->primary_ll) {
  802. /*
  803. * downgrade the current primary no matter what its
  804. * type is.
  805. */
  806. data->secondary = data->primary;
  807. data->primary = chanctx_conf;
  808. } else {
  809. /* there is low latency vif - we will be secondary */
  810. data->secondary = chanctx_conf;
  811. }
  812. return;
  813. }
  814. /*
  815. * STA / P2P Client, try to be primary if first vif. If we are in low
  816. * latency mode, we are already in primary and just don't do much
  817. */
  818. if (!data->primary || data->primary == chanctx_conf)
  819. data->primary = chanctx_conf;
  820. else if (!data->secondary)
  821. /* if secondary is not NULL, it might be a GO */
  822. data->secondary = chanctx_conf;
  823. /* don't reduce the Tx power if in loose scheme */
  824. if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
  825. mvm->cfg->bt_shared_single_ant) {
  826. data->reduced_tx_power = false;
  827. iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
  828. return;
  829. }
  830. /* reduced Txpower only if BT is on, so ...*/
  831. if (!data->notif->bt_status) {
  832. /* ... cancel reduced Tx power ... */
  833. if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
  834. IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
  835. data->reduced_tx_power = false;
  836. /* ... and there is no need to get reports on RSSI any more. */
  837. iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
  838. return;
  839. }
  840. /* try to get the avg rssi from fw */
  841. ave_rssi = mvmvif->bf_data.ave_beacon_signal;
  842. /* if the RSSI isn't valid, fake it is very low */
  843. if (!ave_rssi)
  844. ave_rssi = -100;
  845. if (ave_rssi > BT_ENABLE_REDUCED_TXPOWER_THRESHOLD) {
  846. if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true))
  847. IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
  848. /*
  849. * bt_kill_msk can be BT_KILL_MSK_REDUCED_TXPOW only if all the
  850. * BSS / P2P clients have rssi above threshold.
  851. * We set the bt_kill_msk to BT_KILL_MSK_REDUCED_TXPOW before
  852. * the iteration, if one interface's rssi isn't good enough,
  853. * bt_kill_msk will be set to default values.
  854. */
  855. } else if (ave_rssi < BT_DISABLE_REDUCED_TXPOWER_THRESHOLD) {
  856. if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
  857. IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
  858. /*
  859. * One interface hasn't rssi above threshold, bt_kill_msk must
  860. * be set to default values.
  861. */
  862. data->reduced_tx_power = false;
  863. }
  864. /* Begin to monitor the RSSI: it may influence the reduced Tx power */
  865. iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, true, ave_rssi);
  866. }
  867. static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
  868. {
  869. struct iwl_bt_iterator_data data = {
  870. .mvm = mvm,
  871. .notif = &mvm->last_bt_notif,
  872. .reduced_tx_power = true,
  873. };
  874. struct iwl_bt_coex_ci_cmd cmd = {};
  875. u8 ci_bw_idx;
  876. rcu_read_lock();
  877. ieee80211_iterate_active_interfaces_atomic(
  878. mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
  879. iwl_mvm_bt_notif_iterator, &data);
  880. if (data.primary) {
  881. struct ieee80211_chanctx_conf *chan = data.primary;
  882. if (WARN_ON(!chan->def.chan)) {
  883. rcu_read_unlock();
  884. return;
  885. }
  886. if (chan->def.width < NL80211_CHAN_WIDTH_40) {
  887. ci_bw_idx = 0;
  888. cmd.co_run_bw_primary = 0;
  889. } else {
  890. cmd.co_run_bw_primary = 1;
  891. if (chan->def.center_freq1 >
  892. chan->def.chan->center_freq)
  893. ci_bw_idx = 2;
  894. else
  895. ci_bw_idx = 1;
  896. }
  897. cmd.bt_primary_ci =
  898. iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx];
  899. cmd.primary_ch_phy_id = *((u16 *)data.primary->drv_priv);
  900. }
  901. if (data.secondary) {
  902. struct ieee80211_chanctx_conf *chan = data.secondary;
  903. if (WARN_ON(!data.secondary->def.chan)) {
  904. rcu_read_unlock();
  905. return;
  906. }
  907. if (chan->def.width < NL80211_CHAN_WIDTH_40) {
  908. ci_bw_idx = 0;
  909. cmd.co_run_bw_secondary = 0;
  910. } else {
  911. cmd.co_run_bw_secondary = 1;
  912. if (chan->def.center_freq1 >
  913. chan->def.chan->center_freq)
  914. ci_bw_idx = 2;
  915. else
  916. ci_bw_idx = 1;
  917. }
  918. cmd.bt_secondary_ci =
  919. iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx];
  920. cmd.secondary_ch_phy_id = *((u16 *)data.secondary->drv_priv);
  921. }
  922. rcu_read_unlock();
  923. /* Don't spam the fw with the same command over and over */
  924. if (memcmp(&cmd, &mvm->last_bt_ci_cmd, sizeof(cmd))) {
  925. if (iwl_mvm_send_cmd_pdu(mvm, BT_COEX_CI, CMD_SYNC,
  926. sizeof(cmd), &cmd))
  927. IWL_ERR(mvm, "Failed to send BT_CI cmd");
  928. memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd));
  929. }
  930. /*
  931. * If there are no BSS / P2P client interfaces, reduced Tx Power is
  932. * irrelevant since it is based on the RSSI coming from the beacon.
  933. * Use BT_KILL_MSK_DEFAULT in that case.
  934. */
  935. data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
  936. if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power))
  937. IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
  938. }
  939. /* upon association, the fw will send in BT Coex notification */
  940. int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
  941. struct iwl_rx_cmd_buffer *rxb,
  942. struct iwl_device_cmd *dev_cmd)
  943. {
  944. struct iwl_rx_packet *pkt = rxb_addr(rxb);
  945. struct iwl_bt_coex_profile_notif *notif = (void *)pkt->data;
  946. IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n");
  947. IWL_DEBUG_COEX(mvm, "\tBT status: %s\n",
  948. notif->bt_status ? "ON" : "OFF");
  949. IWL_DEBUG_COEX(mvm, "\tBT open conn %d\n", notif->bt_open_conn);
  950. IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance);
  951. IWL_DEBUG_COEX(mvm, "\tBT primary_ch_lut %d\n",
  952. le32_to_cpu(notif->primary_ch_lut));
  953. IWL_DEBUG_COEX(mvm, "\tBT secondary_ch_lut %d\n",
  954. le32_to_cpu(notif->secondary_ch_lut));
  955. IWL_DEBUG_COEX(mvm, "\tBT activity grading %d\n",
  956. le32_to_cpu(notif->bt_activity_grading));
  957. IWL_DEBUG_COEX(mvm, "\tBT agg traffic load %d\n",
  958. notif->bt_agg_traffic_load);
  959. /* remember this notification for future use: rssi fluctuations */
  960. memcpy(&mvm->last_bt_notif, notif, sizeof(mvm->last_bt_notif));
  961. iwl_mvm_bt_coex_notif_handle(mvm);
  962. /*
  963. * This is an async handler for a notification, returning anything other
  964. * than 0 doesn't make sense even if HCMD failed.
  965. */
  966. return 0;
  967. }
  968. static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
  969. struct ieee80211_vif *vif)
  970. {
  971. struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
  972. struct iwl_bt_iterator_data *data = _data;
  973. struct iwl_mvm *mvm = data->mvm;
  974. struct ieee80211_sta *sta;
  975. struct iwl_mvm_sta *mvmsta;
  976. struct ieee80211_chanctx_conf *chanctx_conf;
  977. rcu_read_lock();
  978. chanctx_conf = rcu_dereference(vif->chanctx_conf);
  979. /* If channel context is invalid or not on 2.4GHz - don't count it */
  980. if (!chanctx_conf ||
  981. chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) {
  982. rcu_read_unlock();
  983. return;
  984. }
  985. rcu_read_unlock();
  986. if (vif->type != NL80211_IFTYPE_STATION ||
  987. mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)
  988. return;
  989. sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
  990. lockdep_is_held(&mvm->mutex));
  991. /* This can happen if the station has been removed right now */
  992. if (IS_ERR_OR_NULL(sta))
  993. return;
  994. mvmsta = iwl_mvm_sta_from_mac80211(sta);
  995. data->num_bss_ifaces++;
  996. /*
  997. * This interface doesn't support reduced Tx power (because of low
  998. * RSSI probably), then set bt_kill_msk to default values.
  999. */
  1000. if (!mvmsta->bt_reduced_txpower)
  1001. data->reduced_tx_power = false;
  1002. /* else - possibly leave it to BT_KILL_MSK_REDUCED_TXPOW */
  1003. }
  1004. void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
  1005. enum ieee80211_rssi_event rssi_event)
  1006. {
  1007. struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
  1008. struct iwl_bt_iterator_data data = {
  1009. .mvm = mvm,
  1010. .reduced_tx_power = true,
  1011. };
  1012. int ret;
  1013. lockdep_assert_held(&mvm->mutex);
  1014. /*
  1015. * Rssi update while not associated - can happen since the statistics
  1016. * are handled asynchronously
  1017. */
  1018. if (mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)
  1019. return;
  1020. /* No BT - reports should be disabled */
  1021. if (!mvm->last_bt_notif.bt_status)
  1022. return;
  1023. IWL_DEBUG_COEX(mvm, "RSSI for %pM is now %s\n", vif->bss_conf.bssid,
  1024. rssi_event == RSSI_EVENT_HIGH ? "HIGH" : "LOW");
  1025. /*
  1026. * Check if rssi is good enough for reduced Tx power, but not in loose
  1027. * scheme.
  1028. */
  1029. if (rssi_event == RSSI_EVENT_LOW || mvm->cfg->bt_shared_single_ant ||
  1030. iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT)
  1031. ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
  1032. false);
  1033. else
  1034. ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true);
  1035. if (ret)
  1036. IWL_ERR(mvm, "couldn't send BT_CONFIG HCMD upon RSSI event\n");
  1037. ieee80211_iterate_active_interfaces_atomic(
  1038. mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
  1039. iwl_mvm_bt_rssi_iterator, &data);
  1040. /*
  1041. * If there are no BSS / P2P client interfaces, reduced Tx Power is
  1042. * irrelevant since it is based on the RSSI coming from the beacon.
  1043. * Use BT_KILL_MSK_DEFAULT in that case.
  1044. */
  1045. data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
  1046. if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm, data.reduced_tx_power))
  1047. IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
  1048. }
  1049. #define LINK_QUAL_AGG_TIME_LIMIT_DEF (4000)
  1050. #define LINK_QUAL_AGG_TIME_LIMIT_BT_ACT (1200)
  1051. u16 iwl_mvm_coex_agg_time_limit(struct iwl_mvm *mvm,
  1052. struct ieee80211_sta *sta)
  1053. {
  1054. struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
  1055. enum iwl_bt_coex_lut_type lut_type;
  1056. if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) <
  1057. BT_HIGH_TRAFFIC)
  1058. return LINK_QUAL_AGG_TIME_LIMIT_DEF;
  1059. lut_type = iwl_get_coex_type(mvm, mvmsta->vif);
  1060. if (lut_type == BT_COEX_LOOSE_LUT)
  1061. return LINK_QUAL_AGG_TIME_LIMIT_DEF;
  1062. /* tight coex, high bt traffic, reduce AGG time limit */
  1063. return LINK_QUAL_AGG_TIME_LIMIT_BT_ACT;
  1064. }
  1065. bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
  1066. struct ieee80211_sta *sta)
  1067. {
  1068. struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
  1069. if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) <
  1070. BT_HIGH_TRAFFIC)
  1071. return true;
  1072. /*
  1073. * In Tight, BT can't Rx while we Tx, so use both antennas since BT is
  1074. * already killed.
  1075. * In Loose, BT can Rx while we Tx, so forbid MIMO to let BT Rx while we
  1076. * Tx.
  1077. */
  1078. return iwl_get_coex_type(mvm, mvmsta->vif) == BT_COEX_TIGHT_LUT;
  1079. }
  1080. u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
  1081. struct ieee80211_tx_info *info, u8 ac)
  1082. {
  1083. __le16 fc = hdr->frame_control;
  1084. if (info->band != IEEE80211_BAND_2GHZ)
  1085. return 0;
  1086. if (unlikely(mvm->bt_tx_prio))
  1087. return mvm->bt_tx_prio - 1;
  1088. /* High prio packet (wrt. BT coex) if it is EAPOL, MCAST or MGMT */
  1089. if (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO ||
  1090. is_multicast_ether_addr(hdr->addr1) ||
  1091. ieee80211_is_ctl(fc) || ieee80211_is_mgmt(fc) ||
  1092. ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc))
  1093. return 3;
  1094. switch (ac) {
  1095. case IEEE80211_AC_BE:
  1096. return 1;
  1097. case IEEE80211_AC_VO:
  1098. return 3;
  1099. case IEEE80211_AC_VI:
  1100. return 2;
  1101. default:
  1102. break;
  1103. }
  1104. return 0;
  1105. }
  1106. void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm)
  1107. {
  1108. if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWBT_COEX))
  1109. return;
  1110. iwl_mvm_bt_coex_notif_handle(mvm);
  1111. }
  1112. int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm,
  1113. struct iwl_rx_cmd_buffer *rxb,
  1114. struct iwl_device_cmd *dev_cmd)
  1115. {
  1116. struct iwl_rx_packet *pkt = rxb_addr(rxb);
  1117. u32 ant_isolation = le32_to_cpup((void *)pkt->data);
  1118. u8 __maybe_unused lower_bound, upper_bound;
  1119. int ret;
  1120. u8 lut;
  1121. struct iwl_bt_coex_cmd *bt_cmd;
  1122. struct iwl_host_cmd cmd = {
  1123. .id = BT_CONFIG,
  1124. .len = { sizeof(*bt_cmd), },
  1125. .dataflags = { IWL_HCMD_DFL_NOCOPY, },
  1126. .flags = CMD_SYNC,
  1127. };
  1128. if (!IWL_MVM_BT_COEX_CORUNNING)
  1129. return 0;
  1130. lockdep_assert_held(&mvm->mutex);
  1131. if (ant_isolation == mvm->last_ant_isol)
  1132. return 0;
  1133. for (lut = 0; lut < ARRAY_SIZE(antenna_coupling_ranges) - 1; lut++)
  1134. if (ant_isolation < antenna_coupling_ranges[lut + 1].range)
  1135. break;
  1136. lower_bound = antenna_coupling_ranges[lut].range;
  1137. if (lut < ARRAY_SIZE(antenna_coupling_ranges) - 1)
  1138. upper_bound = antenna_coupling_ranges[lut + 1].range;
  1139. else
  1140. upper_bound = antenna_coupling_ranges[lut].range;
  1141. IWL_DEBUG_COEX(mvm, "Antenna isolation=%d in range [%d,%d[, lut=%d\n",
  1142. ant_isolation, lower_bound, upper_bound, lut);
  1143. mvm->last_ant_isol = ant_isolation;
  1144. if (mvm->last_corun_lut == lut)
  1145. return 0;
  1146. mvm->last_corun_lut = lut;
  1147. bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
  1148. if (!bt_cmd)
  1149. return 0;
  1150. cmd.data[0] = bt_cmd;
  1151. bt_cmd->flags = cpu_to_le32(BT_COEX_NW);
  1152. bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE |
  1153. BT_VALID_CORUN_LUT_20 |
  1154. BT_VALID_CORUN_LUT_40);
  1155. /* For the moment, use the same LUT for 20GHz and 40GHz */
  1156. memcpy(bt_cmd->bt4_corun_lut20, antenna_coupling_ranges[lut].lut20,
  1157. sizeof(bt_cmd->bt4_corun_lut20));
  1158. memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[lut].lut20,
  1159. sizeof(bt_cmd->bt4_corun_lut40));
  1160. ret = iwl_mvm_send_cmd(mvm, &cmd);
  1161. kfree(bt_cmd);
  1162. return ret;
  1163. }