ARM: shmobile: Remove FSF address from copyright headers
[cascardo/linux.git] / drivers / net / wireless / iwlwifi / mvm / coex_legacy.c
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  * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of version 2 of the GNU General Public License as
13  * published by the Free Software Foundation.
14  *
15  * This program is distributed in the hope that it will be useful, but
16  * WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18  * General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110,
23  * USA
24  *
25  * The full GNU General Public License is included in this distribution
26  * in the file called COPYING.
27  *
28  * Contact Information:
29  *  Intel Linux Wireless <ilw@linux.intel.com>
30  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
31  *
32  * BSD LICENSE
33  *
34  * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved.
35  * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
36  * All rights reserved.
37  *
38  * Redistribution and use in source and binary forms, with or without
39  * modification, are permitted provided that the following conditions
40  * are met:
41  *
42  *  * Redistributions of source code must retain the above copyright
43  *    notice, this list of conditions and the following disclaimer.
44  *  * Redistributions in binary form must reproduce the above copyright
45  *    notice, this list of conditions and the following disclaimer in
46  *    the documentation and/or other materials provided with the
47  *    distribution.
48  *  * Neither the name Intel Corporation nor the names of its
49  *    contributors may be used to endorse or promote products derived
50  *    from this software without specific prior written permission.
51  *
52  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
53  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
54  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
55  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
56  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
57  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
58  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
59  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
60  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
61  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
62  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
63  *
64  *****************************************************************************/
65
66 #include <linux/ieee80211.h>
67 #include <linux/etherdevice.h>
68 #include <net/mac80211.h>
69
70 #include "fw-api-coex.h"
71 #include "iwl-modparams.h"
72 #include "mvm.h"
73 #include "iwl-debug.h"
74
75 #define EVENT_PRIO_ANT(_evt, _prio, _shrd_ant)                  \
76         [(_evt)] = (((_prio) << BT_COEX_PRIO_TBL_PRIO_POS) |    \
77                    ((_shrd_ant) << BT_COEX_PRIO_TBL_SHRD_ANT_POS))
78
79 static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
80         EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_INIT_CALIB1,
81                        BT_COEX_PRIO_TBL_PRIO_BYPASS, 0),
82         EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_INIT_CALIB2,
83                        BT_COEX_PRIO_TBL_PRIO_BYPASS, 1),
84         EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW1,
85                        BT_COEX_PRIO_TBL_PRIO_LOW, 0),
86         EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_LOW2,
87                        BT_COEX_PRIO_TBL_PRIO_LOW, 1),
88         EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH1,
89                        BT_COEX_PRIO_TBL_PRIO_HIGH, 0),
90         EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_PERIODIC_CALIB_HIGH2,
91                        BT_COEX_PRIO_TBL_PRIO_HIGH, 1),
92         EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_DTIM,
93                        BT_COEX_PRIO_TBL_DISABLED, 0),
94         EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_SCAN52,
95                        BT_COEX_PRIO_TBL_PRIO_COEX_OFF, 0),
96         EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_SCAN24,
97                        BT_COEX_PRIO_TBL_PRIO_COEX_ON, 0),
98         EVENT_PRIO_ANT(BT_COEX_PRIO_TBL_EVT_IDLE,
99                        BT_COEX_PRIO_TBL_PRIO_COEX_IDLE, 0),
100         0, 0, 0, 0, 0, 0,
101 };
102
103 #undef EVENT_PRIO_ANT
104
105 #define BT_ANTENNA_COUPLING_THRESHOLD           (30)
106
107 static int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm)
108 {
109         if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
110                 return 0;
111
112         return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, 0,
113                                     sizeof(struct iwl_bt_coex_prio_tbl_cmd),
114                                     &iwl_bt_prio_tbl);
115 }
116
117 static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = {
118         cpu_to_le32(0xf0f0f0f0), /* 50% */
119         cpu_to_le32(0xc0c0c0c0), /* 25% */
120         cpu_to_le32(0xfcfcfcfc), /* 75% */
121         cpu_to_le32(0xfefefefe), /* 87.5% */
122 };
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
169 static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = {
170         {
171                 /* Tight */
172                 cpu_to_le32(0xaaaaaaaa),
173                 cpu_to_le32(0xaaaaaaaa),
174                 cpu_to_le32(0xaeaaaaaa),
175                 cpu_to_le32(0xaaaaaaaa),
176                 cpu_to_le32(0xcc00ff28),
177                 cpu_to_le32(0x0000aaaa),
178                 cpu_to_le32(0xcc00aaaa),
179                 cpu_to_le32(0x0000aaaa),
180                 cpu_to_le32(0xc0004000),
181                 cpu_to_le32(0x00004000),
182                 cpu_to_le32(0xf0005000),
183                 cpu_to_le32(0xf0005000),
184         },
185         {
186                 /* Loose */
187                 cpu_to_le32(0xaaaaaaaa),
188                 cpu_to_le32(0xaaaaaaaa),
189                 cpu_to_le32(0xaaaaaaaa),
190                 cpu_to_le32(0xaaaaaaaa),
191                 cpu_to_le32(0xcc00ff28),
192                 cpu_to_le32(0x0000aaaa),
193                 cpu_to_le32(0xcc00aaaa),
194                 cpu_to_le32(0x0000aaaa),
195                 cpu_to_le32(0x00000000),
196                 cpu_to_le32(0x00000000),
197                 cpu_to_le32(0xf0005000),
198                 cpu_to_le32(0xf0005000),
199         },
200         {
201                 /* Tx Tx disabled */
202                 cpu_to_le32(0xaaaaaaaa),
203                 cpu_to_le32(0xaaaaaaaa),
204                 cpu_to_le32(0xeeaaaaaa),
205                 cpu_to_le32(0xaaaaaaaa),
206                 cpu_to_le32(0xcc00ff28),
207                 cpu_to_le32(0x0000aaaa),
208                 cpu_to_le32(0xcc00aaaa),
209                 cpu_to_le32(0x0000aaaa),
210                 cpu_to_le32(0xc0004000),
211                 cpu_to_le32(0xc0004000),
212                 cpu_to_le32(0xf0005000),
213                 cpu_to_le32(0xf0005000),
214         },
215 };
216
217 /* 20MHz / 40MHz below / 40Mhz above*/
218 static const __le64 iwl_ci_mask[][3] = {
219         /* dummy entry for channel 0 */
220         {cpu_to_le64(0), cpu_to_le64(0), cpu_to_le64(0)},
221         {
222                 cpu_to_le64(0x0000001FFFULL),
223                 cpu_to_le64(0x0ULL),
224                 cpu_to_le64(0x00007FFFFFULL),
225         },
226         {
227                 cpu_to_le64(0x000000FFFFULL),
228                 cpu_to_le64(0x0ULL),
229                 cpu_to_le64(0x0003FFFFFFULL),
230         },
231         {
232                 cpu_to_le64(0x000003FFFCULL),
233                 cpu_to_le64(0x0ULL),
234                 cpu_to_le64(0x000FFFFFFCULL),
235         },
236         {
237                 cpu_to_le64(0x00001FFFE0ULL),
238                 cpu_to_le64(0x0ULL),
239                 cpu_to_le64(0x007FFFFFE0ULL),
240         },
241         {
242                 cpu_to_le64(0x00007FFF80ULL),
243                 cpu_to_le64(0x00007FFFFFULL),
244                 cpu_to_le64(0x01FFFFFF80ULL),
245         },
246         {
247                 cpu_to_le64(0x0003FFFC00ULL),
248                 cpu_to_le64(0x0003FFFFFFULL),
249                 cpu_to_le64(0x0FFFFFFC00ULL),
250         },
251         {
252                 cpu_to_le64(0x000FFFF000ULL),
253                 cpu_to_le64(0x000FFFFFFCULL),
254                 cpu_to_le64(0x3FFFFFF000ULL),
255         },
256         {
257                 cpu_to_le64(0x007FFF8000ULL),
258                 cpu_to_le64(0x007FFFFFE0ULL),
259                 cpu_to_le64(0xFFFFFF8000ULL),
260         },
261         {
262                 cpu_to_le64(0x01FFFE0000ULL),
263                 cpu_to_le64(0x01FFFFFF80ULL),
264                 cpu_to_le64(0xFFFFFE0000ULL),
265         },
266         {
267                 cpu_to_le64(0x0FFFF00000ULL),
268                 cpu_to_le64(0x0FFFFFFC00ULL),
269                 cpu_to_le64(0x0ULL),
270         },
271         {
272                 cpu_to_le64(0x3FFFC00000ULL),
273                 cpu_to_le64(0x3FFFFFF000ULL),
274                 cpu_to_le64(0x0)
275         },
276         {
277                 cpu_to_le64(0xFFFE000000ULL),
278                 cpu_to_le64(0xFFFFFF8000ULL),
279                 cpu_to_le64(0x0)
280         },
281         {
282                 cpu_to_le64(0xFFF8000000ULL),
283                 cpu_to_le64(0xFFFFFE0000ULL),
284                 cpu_to_le64(0x0)
285         },
286         {
287                 cpu_to_le64(0xFFC0000000ULL),
288                 cpu_to_le64(0x0ULL),
289                 cpu_to_le64(0x0ULL)
290         },
291 };
292
293 static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = {
294         cpu_to_le32(0x28412201),
295         cpu_to_le32(0x11118451),
296 };
297
298 struct corunning_block_luts {
299         u8 range;
300         __le32 lut20[BT_COEX_CORUN_LUT_SIZE];
301 };
302
303 /*
304  * Ranges for the antenna coupling calibration / co-running block LUT:
305  *              LUT0: [ 0, 12[
306  *              LUT1: [12, 20[
307  *              LUT2: [20, 21[
308  *              LUT3: [21, 23[
309  *              LUT4: [23, 27[
310  *              LUT5: [27, 30[
311  *              LUT6: [30, 32[
312  *              LUT7: [32, 33[
313  *              LUT8: [33, - [
314  */
315 static const struct corunning_block_luts antenna_coupling_ranges[] = {
316         {
317                 .range = 0,
318                 .lut20 = {
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                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
331                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
332                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
333                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
334                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
335                 },
336         },
337         {
338                 .range = 12,
339                 .lut20 = {
340                         cpu_to_le32(0x00000001),  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                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
352                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
353                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
354                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
355                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
356                 },
357         },
358         {
359                 .range = 20,
360                 .lut20 = {
361                         cpu_to_le32(0x00000002),  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                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
373                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
374                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
375                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
376                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
377                 },
378         },
379         {
380                 .range = 21,
381                 .lut20 = {
382                         cpu_to_le32(0x00000003),  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                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
394                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
395                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
396                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
397                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
398                 },
399         },
400         {
401                 .range = 23,
402                 .lut20 = {
403                         cpu_to_le32(0x00000004),  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                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
415                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
416                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
417                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
418                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
419                 },
420         },
421         {
422                 .range = 27,
423                 .lut20 = {
424                         cpu_to_le32(0x00000005),  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                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
436                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
437                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
438                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
439                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
440                 },
441         },
442         {
443                 .range = 30,
444                 .lut20 = {
445                         cpu_to_le32(0x00000006),  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                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
457                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
458                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
459                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
460                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
461                 },
462         },
463         {
464                 .range = 32,
465                 .lut20 = {
466                         cpu_to_le32(0x00000007),  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                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
478                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
479                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
480                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
481                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
482                 },
483         },
484         {
485                 .range = 33,
486                 .lut20 = {
487                         cpu_to_le32(0x00000008),  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                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
499                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
500                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
501                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
502                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
503                 },
504         },
505 };
506
507 static enum iwl_bt_coex_lut_type
508 iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif)
509 {
510         struct ieee80211_chanctx_conf *chanctx_conf;
511         enum iwl_bt_coex_lut_type ret;
512         u16 phy_ctx_id;
513
514         /*
515          * Checking that we hold mvm->mutex is a good idea, but the rate
516          * control can't acquire the mutex since it runs in Tx path.
517          * So this is racy in that case, but in the worst case, the AMPDU
518          * size limit will be wrong for a short time which is not a big
519          * issue.
520          */
521
522         rcu_read_lock();
523
524         chanctx_conf = rcu_dereference(vif->chanctx_conf);
525
526         if (!chanctx_conf ||
527             chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) {
528                 rcu_read_unlock();
529                 return BT_COEX_INVALID_LUT;
530         }
531
532         ret = BT_COEX_TX_DIS_LUT;
533
534         if (mvm->cfg->bt_shared_single_ant) {
535                 rcu_read_unlock();
536                 return ret;
537         }
538
539         phy_ctx_id = *((u16 *)chanctx_conf->drv_priv);
540
541         if (mvm->last_bt_ci_cmd_old.primary_ch_phy_id == phy_ctx_id)
542                 ret = le32_to_cpu(mvm->last_bt_notif_old.primary_ch_lut);
543         else if (mvm->last_bt_ci_cmd_old.secondary_ch_phy_id == phy_ctx_id)
544                 ret = le32_to_cpu(mvm->last_bt_notif_old.secondary_ch_lut);
545         /* else - default = TX TX disallowed */
546
547         rcu_read_unlock();
548
549         return ret;
550 }
551
552 int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm)
553 {
554         struct iwl_bt_coex_cmd_old *bt_cmd;
555         struct iwl_host_cmd cmd = {
556                 .id = BT_CONFIG,
557                 .len = { sizeof(*bt_cmd), },
558                 .dataflags = { IWL_HCMD_DFL_NOCOPY, },
559         };
560         int ret;
561         u32 flags;
562
563         ret = iwl_send_bt_prio_tbl(mvm);
564         if (ret)
565                 return ret;
566
567         bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
568         if (!bt_cmd)
569                 return -ENOMEM;
570         cmd.data[0] = bt_cmd;
571
572         lockdep_assert_held(&mvm->mutex);
573
574         if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) {
575                 switch (mvm->bt_force_ant_mode) {
576                 case BT_FORCE_ANT_AUTO:
577                         flags = BT_COEX_AUTO_OLD;
578                         break;
579                 case BT_FORCE_ANT_BT:
580                         flags = BT_COEX_BT_OLD;
581                         break;
582                 case BT_FORCE_ANT_WIFI:
583                         flags = BT_COEX_WIFI_OLD;
584                         break;
585                 default:
586                         WARN_ON(1);
587                         flags = 0;
588                 }
589
590                 bt_cmd->flags = cpu_to_le32(flags);
591                 bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_ENABLE);
592                 goto send_cmd;
593         }
594
595         bt_cmd->max_kill = 5;
596         bt_cmd->bt4_antenna_isolation_thr = BT_ANTENNA_COUPLING_THRESHOLD;
597         bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling;
598         bt_cmd->bt4_tx_tx_delta_freq_thr = 15;
599         bt_cmd->bt4_tx_rx_max_freq0 = 15;
600         bt_cmd->override_primary_lut = BT_COEX_INVALID_LUT;
601         bt_cmd->override_secondary_lut = BT_COEX_INVALID_LUT;
602
603         flags = iwlwifi_mod_params.bt_coex_active ?
604                         BT_COEX_NW_OLD : BT_COEX_DISABLE_OLD;
605         bt_cmd->flags = cpu_to_le32(flags);
606
607         bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_ENABLE |
608                                             BT_VALID_BT_PRIO_BOOST |
609                                             BT_VALID_MAX_KILL |
610                                             BT_VALID_3W_TMRS |
611                                             BT_VALID_KILL_ACK |
612                                             BT_VALID_KILL_CTS |
613                                             BT_VALID_REDUCED_TX_POWER |
614                                             BT_VALID_LUT |
615                                             BT_VALID_WIFI_RX_SW_PRIO_BOOST |
616                                             BT_VALID_WIFI_TX_SW_PRIO_BOOST |
617                                             BT_VALID_ANT_ISOLATION |
618                                             BT_VALID_ANT_ISOLATION_THRS |
619                                             BT_VALID_TXTX_DELTA_FREQ_THRS |
620                                             BT_VALID_TXRX_MAX_FREQ_0 |
621                                             BT_VALID_SYNC_TO_SCO);
622
623         if (IWL_MVM_BT_COEX_SYNC2SCO)
624                 bt_cmd->flags |= cpu_to_le32(BT_COEX_SYNC2SCO);
625
626         if (IWL_MVM_BT_COEX_CORUNNING) {
627                 bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_CORUN_LUT_20 |
628                                                      BT_VALID_CORUN_LUT_40);
629                 bt_cmd->flags |= cpu_to_le32(BT_COEX_CORUNNING);
630         }
631
632         if (IWL_MVM_BT_COEX_MPLUT) {
633                 bt_cmd->flags |= cpu_to_le32(BT_COEX_MPLUT);
634                 bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_MULTI_PRIO_LUT);
635         }
636
637         if (mvm->cfg->bt_shared_single_ant)
638                 memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant,
639                        sizeof(iwl_single_shared_ant));
640         else
641                 memcpy(&bt_cmd->decision_lut, iwl_combined_lookup,
642                        sizeof(iwl_combined_lookup));
643
644         /* Take first Co-running block LUT to get started */
645         memcpy(bt_cmd->bt4_corun_lut20, antenna_coupling_ranges[0].lut20,
646                sizeof(bt_cmd->bt4_corun_lut20));
647         memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[0].lut20,
648                sizeof(bt_cmd->bt4_corun_lut40));
649
650         memcpy(&bt_cmd->bt_prio_boost, iwl_bt_prio_boost,
651                sizeof(iwl_bt_prio_boost));
652         memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut,
653                sizeof(iwl_bt_mprio_lut));
654
655 send_cmd:
656         memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old));
657         memset(&mvm->last_bt_ci_cmd_old, 0, sizeof(mvm->last_bt_ci_cmd_old));
658
659         ret = iwl_mvm_send_cmd(mvm, &cmd);
660
661         kfree(bt_cmd);
662         return ret;
663 }
664
665 static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm)
666 {
667         struct iwl_bt_coex_profile_notif_old *notif = &mvm->last_bt_notif_old;
668         u32 primary_lut = le32_to_cpu(notif->primary_ch_lut);
669         u32 ag = le32_to_cpu(notif->bt_activity_grading);
670         struct iwl_bt_coex_cmd_old *bt_cmd;
671         u8 ack_kill_msk, cts_kill_msk;
672         struct iwl_host_cmd cmd = {
673                 .id = BT_CONFIG,
674                 .data[0] = &bt_cmd,
675                 .len = { sizeof(*bt_cmd), },
676                 .dataflags = { IWL_HCMD_DFL_NOCOPY, },
677         };
678         int ret = 0;
679
680         lockdep_assert_held(&mvm->mutex);
681
682         ack_kill_msk = iwl_bt_ack_kill_msk[ag][primary_lut];
683         cts_kill_msk = iwl_bt_cts_kill_msk[ag][primary_lut];
684
685         if (mvm->bt_ack_kill_msk[0] == ack_kill_msk &&
686             mvm->bt_cts_kill_msk[0] == cts_kill_msk)
687                 return 0;
688
689         mvm->bt_ack_kill_msk[0] = ack_kill_msk;
690         mvm->bt_cts_kill_msk[0] = cts_kill_msk;
691
692         bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
693         if (!bt_cmd)
694                 return -ENOMEM;
695         cmd.data[0] = bt_cmd;
696         bt_cmd->flags = cpu_to_le32(BT_COEX_NW_OLD);
697
698         bt_cmd->kill_ack_msk = cpu_to_le32(iwl_bt_ctl_kill_msk[ack_kill_msk]);
699         bt_cmd->kill_cts_msk = cpu_to_le32(iwl_bt_ctl_kill_msk[cts_kill_msk]);
700         bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE |
701                                              BT_VALID_KILL_ACK |
702                                              BT_VALID_KILL_CTS);
703
704         ret = iwl_mvm_send_cmd(mvm, &cmd);
705
706         kfree(bt_cmd);
707         return ret;
708 }
709
710 static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
711                                        bool enable)
712 {
713         struct iwl_bt_coex_cmd_old *bt_cmd;
714         /* Send ASYNC since this can be sent from an atomic context */
715         struct iwl_host_cmd cmd = {
716                 .id = BT_CONFIG,
717                 .len = { sizeof(*bt_cmd), },
718                 .dataflags = { IWL_HCMD_DFL_NOCOPY, },
719                 .flags = CMD_ASYNC,
720         };
721         struct iwl_mvm_sta *mvmsta;
722         int ret;
723
724         mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
725         if (!mvmsta)
726                 return 0;
727
728         /* nothing to do */
729         if (mvmsta->bt_reduced_txpower == enable)
730                 return 0;
731
732         bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_ATOMIC);
733         if (!bt_cmd)
734                 return -ENOMEM;
735         cmd.data[0] = bt_cmd;
736         bt_cmd->flags = cpu_to_le32(BT_COEX_NW_OLD);
737
738         bt_cmd->valid_bit_msk =
739                 cpu_to_le32(BT_VALID_ENABLE | BT_VALID_REDUCED_TX_POWER);
740         bt_cmd->bt_reduced_tx_power = sta_id;
741
742         if (enable)
743                 bt_cmd->bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT;
744
745         IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n",
746                        enable ? "en" : "dis", sta_id);
747
748         mvmsta->bt_reduced_txpower = enable;
749
750         ret = iwl_mvm_send_cmd(mvm, &cmd);
751
752         kfree(bt_cmd);
753         return ret;
754 }
755
756 struct iwl_bt_iterator_data {
757         struct iwl_bt_coex_profile_notif_old *notif;
758         struct iwl_mvm *mvm;
759         struct ieee80211_chanctx_conf *primary;
760         struct ieee80211_chanctx_conf *secondary;
761         bool primary_ll;
762 };
763
764 static inline
765 void iwl_mvm_bt_coex_enable_rssi_event(struct iwl_mvm *mvm,
766                                        struct ieee80211_vif *vif,
767                                        bool enable, int rssi)
768 {
769         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
770
771         mvmvif->bf_data.last_bt_coex_event = rssi;
772         mvmvif->bf_data.bt_coex_max_thold =
773                 enable ? -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH : 0;
774         mvmvif->bf_data.bt_coex_min_thold =
775                 enable ? -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH : 0;
776 }
777
778 /* must be called under rcu_read_lock */
779 static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
780                                       struct ieee80211_vif *vif)
781 {
782         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
783         struct iwl_bt_iterator_data *data = _data;
784         struct iwl_mvm *mvm = data->mvm;
785         struct ieee80211_chanctx_conf *chanctx_conf;
786         enum ieee80211_smps_mode smps_mode;
787         u32 bt_activity_grading;
788         int ave_rssi;
789
790         lockdep_assert_held(&mvm->mutex);
791
792         switch (vif->type) {
793         case NL80211_IFTYPE_STATION:
794                 /* default smps_mode for BSS / P2P client is AUTOMATIC */
795                 smps_mode = IEEE80211_SMPS_AUTOMATIC;
796                 break;
797         case NL80211_IFTYPE_AP:
798                 if (!mvmvif->ap_ibss_active)
799                         return;
800                 break;
801         default:
802                 return;
803         }
804
805         chanctx_conf = rcu_dereference(vif->chanctx_conf);
806
807         /* If channel context is invalid or not on 2.4GHz .. */
808         if ((!chanctx_conf ||
809              chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) {
810                 if (vif->type == NL80211_IFTYPE_STATION) {
811                         /* ... relax constraints and disable rssi events */
812                         iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
813                                             smps_mode);
814                         iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
815                                                     false);
816                         iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
817                 }
818                 return;
819         }
820
821         bt_activity_grading = le32_to_cpu(data->notif->bt_activity_grading);
822         if (bt_activity_grading >= BT_HIGH_TRAFFIC)
823                 smps_mode = IEEE80211_SMPS_STATIC;
824         else if (bt_activity_grading >= BT_LOW_TRAFFIC)
825                 smps_mode = vif->type == NL80211_IFTYPE_AP ?
826                                 IEEE80211_SMPS_OFF :
827                                 IEEE80211_SMPS_DYNAMIC;
828
829         /* relax SMPS contraints for next association */
830         if (!vif->bss_conf.assoc)
831                 smps_mode = IEEE80211_SMPS_AUTOMATIC;
832
833         IWL_DEBUG_COEX(data->mvm,
834                        "mac %d: bt_status %d bt_activity_grading %d smps_req %d\n",
835                        mvmvif->id, data->notif->bt_status, bt_activity_grading,
836                        smps_mode);
837
838         if (vif->type == NL80211_IFTYPE_STATION)
839                 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
840                                     smps_mode);
841
842         /* low latency is always primary */
843         if (iwl_mvm_vif_low_latency(mvmvif)) {
844                 data->primary_ll = true;
845
846                 data->secondary = data->primary;
847                 data->primary = chanctx_conf;
848         }
849
850         if (vif->type == NL80211_IFTYPE_AP) {
851                 if (!mvmvif->ap_ibss_active)
852                         return;
853
854                 if (chanctx_conf == data->primary)
855                         return;
856
857                 if (!data->primary_ll) {
858                         /*
859                          * downgrade the current primary no matter what its
860                          * type is.
861                          */
862                         data->secondary = data->primary;
863                         data->primary = chanctx_conf;
864                 } else {
865                         /* there is low latency vif - we will be secondary */
866                         data->secondary = chanctx_conf;
867                 }
868                 return;
869         }
870
871         /*
872          * STA / P2P Client, try to be primary if first vif. If we are in low
873          * latency mode, we are already in primary and just don't do much
874          */
875         if (!data->primary || data->primary == chanctx_conf)
876                 data->primary = chanctx_conf;
877         else if (!data->secondary)
878                 /* if secondary is not NULL, it might be a GO */
879                 data->secondary = chanctx_conf;
880
881         /*
882          * don't reduce the Tx power if one of these is true:
883          *  we are in LOOSE
884          *  single share antenna product
885          *  BT is active
886          *  we are associated
887          */
888         if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
889             mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc ||
890             !data->notif->bt_status) {
891                 iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false);
892                 iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
893                 return;
894         }
895
896         /* try to get the avg rssi from fw */
897         ave_rssi = mvmvif->bf_data.ave_beacon_signal;
898
899         /* if the RSSI isn't valid, fake it is very low */
900         if (!ave_rssi)
901                 ave_rssi = -100;
902         if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) {
903                 if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true))
904                         IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
905         } else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) {
906                 if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
907                         IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
908         }
909
910         /* Begin to monitor the RSSI: it may influence the reduced Tx power */
911         iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, true, ave_rssi);
912 }
913
914 static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
915 {
916         struct iwl_bt_iterator_data data = {
917                 .mvm = mvm,
918                 .notif = &mvm->last_bt_notif_old,
919         };
920         struct iwl_bt_coex_ci_cmd_old cmd = {};
921         u8 ci_bw_idx;
922
923         /* Ignore updates if we are in force mode */
924         if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
925                 return;
926
927         rcu_read_lock();
928         ieee80211_iterate_active_interfaces_atomic(
929                                         mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
930                                         iwl_mvm_bt_notif_iterator, &data);
931
932         if (data.primary) {
933                 struct ieee80211_chanctx_conf *chan = data.primary;
934
935                 if (WARN_ON(!chan->def.chan)) {
936                         rcu_read_unlock();
937                         return;
938                 }
939
940                 if (chan->def.width < NL80211_CHAN_WIDTH_40) {
941                         ci_bw_idx = 0;
942                         cmd.co_run_bw_primary = 0;
943                 } else {
944                         cmd.co_run_bw_primary = 1;
945                         if (chan->def.center_freq1 >
946                             chan->def.chan->center_freq)
947                                 ci_bw_idx = 2;
948                         else
949                                 ci_bw_idx = 1;
950                 }
951
952                 cmd.bt_primary_ci =
953                         iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx];
954                 cmd.primary_ch_phy_id = *((u16 *)data.primary->drv_priv);
955         }
956
957         if (data.secondary) {
958                 struct ieee80211_chanctx_conf *chan = data.secondary;
959
960                 if (WARN_ON(!data.secondary->def.chan)) {
961                         rcu_read_unlock();
962                         return;
963                 }
964
965                 if (chan->def.width < NL80211_CHAN_WIDTH_40) {
966                         ci_bw_idx = 0;
967                         cmd.co_run_bw_secondary = 0;
968                 } else {
969                         cmd.co_run_bw_secondary = 1;
970                         if (chan->def.center_freq1 >
971                             chan->def.chan->center_freq)
972                                 ci_bw_idx = 2;
973                         else
974                                 ci_bw_idx = 1;
975                 }
976
977                 cmd.bt_secondary_ci =
978                         iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx];
979                 cmd.secondary_ch_phy_id = *((u16 *)data.secondary->drv_priv);
980         }
981
982         rcu_read_unlock();
983
984         /* Don't spam the fw with the same command over and over */
985         if (memcmp(&cmd, &mvm->last_bt_ci_cmd_old, sizeof(cmd))) {
986                 if (iwl_mvm_send_cmd_pdu(mvm, BT_COEX_CI, 0,
987                                          sizeof(cmd), &cmd))
988                         IWL_ERR(mvm, "Failed to send BT_CI cmd\n");
989                 memcpy(&mvm->last_bt_ci_cmd_old, &cmd, sizeof(cmd));
990         }
991
992         if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm))
993                 IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
994 }
995
996 int iwl_mvm_rx_bt_coex_notif_old(struct iwl_mvm *mvm,
997                                  struct iwl_rx_cmd_buffer *rxb,
998                                  struct iwl_device_cmd *dev_cmd)
999 {
1000         struct iwl_rx_packet *pkt = rxb_addr(rxb);
1001         struct iwl_bt_coex_profile_notif_old *notif = (void *)pkt->data;
1002
1003         IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n");
1004         IWL_DEBUG_COEX(mvm, "\tBT status: %s\n",
1005                        notif->bt_status ? "ON" : "OFF");
1006         IWL_DEBUG_COEX(mvm, "\tBT open conn %d\n", notif->bt_open_conn);
1007         IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance);
1008         IWL_DEBUG_COEX(mvm, "\tBT primary_ch_lut %d\n",
1009                        le32_to_cpu(notif->primary_ch_lut));
1010         IWL_DEBUG_COEX(mvm, "\tBT secondary_ch_lut %d\n",
1011                        le32_to_cpu(notif->secondary_ch_lut));
1012         IWL_DEBUG_COEX(mvm, "\tBT activity grading %d\n",
1013                        le32_to_cpu(notif->bt_activity_grading));
1014         IWL_DEBUG_COEX(mvm, "\tBT agg traffic load %d\n",
1015                        notif->bt_agg_traffic_load);
1016
1017         /* remember this notification for future use: rssi fluctuations */
1018         memcpy(&mvm->last_bt_notif_old, notif, sizeof(mvm->last_bt_notif_old));
1019
1020         iwl_mvm_bt_coex_notif_handle(mvm);
1021
1022         /*
1023          * This is an async handler for a notification, returning anything other
1024          * than 0 doesn't make sense even if HCMD failed.
1025          */
1026         return 0;
1027 }
1028
1029 static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
1030                                      struct ieee80211_vif *vif)
1031 {
1032         struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
1033         struct iwl_bt_iterator_data *data = _data;
1034         struct iwl_mvm *mvm = data->mvm;
1035
1036         struct ieee80211_sta *sta;
1037         struct iwl_mvm_sta *mvmsta;
1038
1039         struct ieee80211_chanctx_conf *chanctx_conf;
1040
1041         rcu_read_lock();
1042         chanctx_conf = rcu_dereference(vif->chanctx_conf);
1043         /* If channel context is invalid or not on 2.4GHz - don't count it */
1044         if (!chanctx_conf ||
1045             chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) {
1046                 rcu_read_unlock();
1047                 return;
1048         }
1049         rcu_read_unlock();
1050
1051         if (vif->type != NL80211_IFTYPE_STATION ||
1052             mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)
1053                 return;
1054
1055         sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
1056                                         lockdep_is_held(&mvm->mutex));
1057
1058         /* This can happen if the station has been removed right now */
1059         if (IS_ERR_OR_NULL(sta))
1060                 return;
1061
1062         mvmsta = iwl_mvm_sta_from_mac80211(sta);
1063 }
1064
1065 void iwl_mvm_bt_rssi_event_old(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
1066                                enum ieee80211_rssi_event rssi_event)
1067 {
1068         struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
1069         struct iwl_bt_iterator_data data = {
1070                 .mvm = mvm,
1071         };
1072         int ret;
1073
1074         lockdep_assert_held(&mvm->mutex);
1075
1076         /* Ignore updates if we are in force mode */
1077         if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
1078                 return;
1079
1080         /*
1081          * Rssi update while not associated - can happen since the statistics
1082          * are handled asynchronously
1083          */
1084         if (mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)
1085                 return;
1086
1087         /* No BT - reports should be disabled */
1088         if (!mvm->last_bt_notif_old.bt_status)
1089                 return;
1090
1091         IWL_DEBUG_COEX(mvm, "RSSI for %pM is now %s\n", vif->bss_conf.bssid,
1092                        rssi_event == RSSI_EVENT_HIGH ? "HIGH" : "LOW");
1093
1094         /*
1095          * Check if rssi is good enough for reduced Tx power, but not in loose
1096          * scheme.
1097          */
1098         if (rssi_event == RSSI_EVENT_LOW || mvm->cfg->bt_shared_single_ant ||
1099             iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT)
1100                 ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
1101                                                   false);
1102         else
1103                 ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true);
1104
1105         if (ret)
1106                 IWL_ERR(mvm, "couldn't send BT_CONFIG HCMD upon RSSI event\n");
1107
1108         ieee80211_iterate_active_interfaces_atomic(
1109                 mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
1110                 iwl_mvm_bt_rssi_iterator, &data);
1111
1112         if (iwl_mvm_bt_udpate_ctrl_kill_msk(mvm))
1113                 IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
1114 }
1115
1116 #define LINK_QUAL_AGG_TIME_LIMIT_DEF    (4000)
1117 #define LINK_QUAL_AGG_TIME_LIMIT_BT_ACT (1200)
1118
1119 u16 iwl_mvm_coex_agg_time_limit_old(struct iwl_mvm *mvm,
1120                                     struct ieee80211_sta *sta)
1121 {
1122         struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
1123         enum iwl_bt_coex_lut_type lut_type;
1124
1125         if (le32_to_cpu(mvm->last_bt_notif_old.bt_activity_grading) <
1126             BT_HIGH_TRAFFIC)
1127                 return LINK_QUAL_AGG_TIME_LIMIT_DEF;
1128
1129         if (mvm->last_bt_notif_old.ttc_enabled)
1130                 return LINK_QUAL_AGG_TIME_LIMIT_DEF;
1131
1132         lut_type = iwl_get_coex_type(mvm, mvmsta->vif);
1133
1134         if (lut_type == BT_COEX_LOOSE_LUT || lut_type == BT_COEX_INVALID_LUT)
1135                 return LINK_QUAL_AGG_TIME_LIMIT_DEF;
1136
1137         /* tight coex, high bt traffic, reduce AGG time limit */
1138         return LINK_QUAL_AGG_TIME_LIMIT_BT_ACT;
1139 }
1140
1141 bool iwl_mvm_bt_coex_is_mimo_allowed_old(struct iwl_mvm *mvm,
1142                                          struct ieee80211_sta *sta)
1143 {
1144         struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
1145         enum iwl_bt_coex_lut_type lut_type;
1146
1147         if (mvm->last_bt_notif_old.ttc_enabled)
1148                 return true;
1149
1150         if (le32_to_cpu(mvm->last_bt_notif_old.bt_activity_grading) <
1151             BT_HIGH_TRAFFIC)
1152                 return true;
1153
1154         /*
1155          * In Tight / TxTxDis, BT can't Rx while we Tx, so use both antennas
1156          * since BT is already killed.
1157          * In Loose, BT can Rx while we Tx, so forbid MIMO to let BT Rx while
1158          * we Tx.
1159          * When we are in 5GHz, we'll get BT_COEX_INVALID_LUT allowing MIMO.
1160          */
1161         lut_type = iwl_get_coex_type(mvm, mvmsta->vif);
1162         return lut_type != BT_COEX_LOOSE_LUT;
1163 }
1164
1165 bool iwl_mvm_bt_coex_is_shared_ant_avail_old(struct iwl_mvm *mvm)
1166 {
1167         u32 ag = le32_to_cpu(mvm->last_bt_notif_old.bt_activity_grading);
1168         return ag == BT_OFF;
1169 }
1170
1171 bool iwl_mvm_bt_coex_is_tpc_allowed_old(struct iwl_mvm *mvm,
1172                                         enum ieee80211_band band)
1173 {
1174         u32 bt_activity =
1175                 le32_to_cpu(mvm->last_bt_notif_old.bt_activity_grading);
1176
1177         if (band != IEEE80211_BAND_2GHZ)
1178                 return false;
1179
1180         return bt_activity >= BT_LOW_TRAFFIC;
1181 }
1182
1183 void iwl_mvm_bt_coex_vif_change_old(struct iwl_mvm *mvm)
1184 {
1185         iwl_mvm_bt_coex_notif_handle(mvm);
1186 }
1187
1188 int iwl_mvm_rx_ant_coupling_notif_old(struct iwl_mvm *mvm,
1189                                       struct iwl_rx_cmd_buffer *rxb,
1190                                       struct iwl_device_cmd *dev_cmd)
1191 {
1192         struct iwl_rx_packet *pkt = rxb_addr(rxb);
1193         u32 ant_isolation = le32_to_cpup((void *)pkt->data);
1194         u8 __maybe_unused lower_bound, upper_bound;
1195         int ret;
1196         u8 lut;
1197
1198         struct iwl_bt_coex_cmd_old *bt_cmd;
1199         struct iwl_host_cmd cmd = {
1200                 .id = BT_CONFIG,
1201                 .len = { sizeof(*bt_cmd), },
1202                 .dataflags = { IWL_HCMD_DFL_NOCOPY, },
1203         };
1204
1205         if (!IWL_MVM_BT_COEX_CORUNNING)
1206                 return 0;
1207
1208         lockdep_assert_held(&mvm->mutex);
1209
1210         /* Ignore updates if we are in force mode */
1211         if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
1212                 return 0;
1213
1214         if (ant_isolation ==  mvm->last_ant_isol)
1215                 return 0;
1216
1217         for (lut = 0; lut < ARRAY_SIZE(antenna_coupling_ranges) - 1; lut++)
1218                 if (ant_isolation < antenna_coupling_ranges[lut + 1].range)
1219                         break;
1220
1221         lower_bound = antenna_coupling_ranges[lut].range;
1222
1223         if (lut < ARRAY_SIZE(antenna_coupling_ranges) - 1)
1224                 upper_bound = antenna_coupling_ranges[lut + 1].range;
1225         else
1226                 upper_bound = antenna_coupling_ranges[lut].range;
1227
1228         IWL_DEBUG_COEX(mvm, "Antenna isolation=%d in range [%d,%d[, lut=%d\n",
1229                        ant_isolation, lower_bound, upper_bound, lut);
1230
1231         mvm->last_ant_isol = ant_isolation;
1232
1233         if (mvm->last_corun_lut == lut)
1234                 return 0;
1235
1236         mvm->last_corun_lut = lut;
1237
1238         bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
1239         if (!bt_cmd)
1240                 return 0;
1241         cmd.data[0] = bt_cmd;
1242
1243         bt_cmd->flags = cpu_to_le32(BT_COEX_NW_OLD);
1244         bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE |
1245                                              BT_VALID_CORUN_LUT_20 |
1246                                              BT_VALID_CORUN_LUT_40);
1247
1248         /* For the moment, use the same LUT for 20GHz and 40GHz */
1249         memcpy(bt_cmd->bt4_corun_lut20, antenna_coupling_ranges[lut].lut20,
1250                sizeof(bt_cmd->bt4_corun_lut20));
1251
1252         memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[lut].lut20,
1253                sizeof(bt_cmd->bt4_corun_lut40));
1254
1255         ret = iwl_mvm_send_cmd(mvm, &cmd);
1256
1257         kfree(bt_cmd);
1258         return ret;
1259 }