iwlwifi: mvm: BT Coex - convert the sw boost update to new API
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / iwlwifi / mvm / coex.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  *
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
64 #include <linux/ieee80211.h>
65 #include <linux/etherdevice.h>
66 #include <net/mac80211.h>
67
68 #include "fw-api-coex.h"
69 #include "iwl-modparams.h"
70 #include "mvm.h"
71 #include "iwl-debug.h"
72
73 #define BT_ANTENNA_COUPLING_THRESHOLD           (30)
74
75 const u32 iwl_bt_ack_kill_msk[BT_KILL_MSK_MAX] = {
76         [BT_KILL_MSK_DEFAULT] = 0xffff0000,
77         [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff,
78         [BT_KILL_MSK_REDUCED_TXPOW] = 0,
79 };
80
81 const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = {
82         [BT_KILL_MSK_DEFAULT] = 0xffff0000,
83         [BT_KILL_MSK_SCO_HID_A2DP] = 0xffffffff,
84         [BT_KILL_MSK_REDUCED_TXPOW] = 0,
85 };
86
87 static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = {
88         cpu_to_le32(0xf0f0f0f0), /* 50% */
89         cpu_to_le32(0xc0c0c0c0), /* 25% */
90         cpu_to_le32(0xfcfcfcfc), /* 75% */
91         cpu_to_le32(0xfefefefe), /* 87.5% */
92 };
93
94 static const __le32 iwl_single_shared_ant[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = {
95         {
96                 cpu_to_le32(0x40000000),
97                 cpu_to_le32(0x00000000),
98                 cpu_to_le32(0x44000000),
99                 cpu_to_le32(0x00000000),
100                 cpu_to_le32(0x40000000),
101                 cpu_to_le32(0x00000000),
102                 cpu_to_le32(0x44000000),
103                 cpu_to_le32(0x00000000),
104                 cpu_to_le32(0xc0004000),
105                 cpu_to_le32(0xf0005000),
106                 cpu_to_le32(0xc0004000),
107                 cpu_to_le32(0xf0005000),
108         },
109         {
110                 cpu_to_le32(0x40000000),
111                 cpu_to_le32(0x00000000),
112                 cpu_to_le32(0x44000000),
113                 cpu_to_le32(0x00000000),
114                 cpu_to_le32(0x40000000),
115                 cpu_to_le32(0x00000000),
116                 cpu_to_le32(0x44000000),
117                 cpu_to_le32(0x00000000),
118                 cpu_to_le32(0xc0004000),
119                 cpu_to_le32(0xf0005000),
120                 cpu_to_le32(0xc0004000),
121                 cpu_to_le32(0xf0005000),
122         },
123         {
124                 cpu_to_le32(0x40000000),
125                 cpu_to_le32(0x00000000),
126                 cpu_to_le32(0x44000000),
127                 cpu_to_le32(0x00000000),
128                 cpu_to_le32(0x40000000),
129                 cpu_to_le32(0x00000000),
130                 cpu_to_le32(0x44000000),
131                 cpu_to_le32(0x00000000),
132                 cpu_to_le32(0xc0004000),
133                 cpu_to_le32(0xf0005000),
134                 cpu_to_le32(0xc0004000),
135                 cpu_to_le32(0xf0005000),
136         },
137 };
138
139 static const __le32 iwl_combined_lookup[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = {
140         {
141                 /* Tight */
142                 cpu_to_le32(0xaaaaaaaa),
143                 cpu_to_le32(0xaaaaaaaa),
144                 cpu_to_le32(0xaeaaaaaa),
145                 cpu_to_le32(0xaaaaaaaa),
146                 cpu_to_le32(0xcc00ff28),
147                 cpu_to_le32(0x0000aaaa),
148                 cpu_to_le32(0xcc00aaaa),
149                 cpu_to_le32(0x0000aaaa),
150                 cpu_to_le32(0xc0004000),
151                 cpu_to_le32(0x00004000),
152                 cpu_to_le32(0xf0005000),
153                 cpu_to_le32(0xf0005000),
154         },
155         {
156                 /* Loose */
157                 cpu_to_le32(0xaaaaaaaa),
158                 cpu_to_le32(0xaaaaaaaa),
159                 cpu_to_le32(0xaaaaaaaa),
160                 cpu_to_le32(0xaaaaaaaa),
161                 cpu_to_le32(0xcc00ff28),
162                 cpu_to_le32(0x0000aaaa),
163                 cpu_to_le32(0xcc00aaaa),
164                 cpu_to_le32(0x0000aaaa),
165                 cpu_to_le32(0x00000000),
166                 cpu_to_le32(0x00000000),
167                 cpu_to_le32(0xf0005000),
168                 cpu_to_le32(0xf0005000),
169         },
170         {
171                 /* Tx Tx disabled */
172                 cpu_to_le32(0xaaaaaaaa),
173                 cpu_to_le32(0xaaaaaaaa),
174                 cpu_to_le32(0xeeaaaaaa),
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(0xc0004000),
182                 cpu_to_le32(0xf0005000),
183                 cpu_to_le32(0xf0005000),
184         },
185 };
186
187 /* 20MHz / 40MHz below / 40Mhz above*/
188 static const __le64 iwl_ci_mask[][3] = {
189         /* dummy entry for channel 0 */
190         {cpu_to_le64(0), cpu_to_le64(0), cpu_to_le64(0)},
191         {
192                 cpu_to_le64(0x0000001FFFULL),
193                 cpu_to_le64(0x0ULL),
194                 cpu_to_le64(0x00007FFFFFULL),
195         },
196         {
197                 cpu_to_le64(0x000000FFFFULL),
198                 cpu_to_le64(0x0ULL),
199                 cpu_to_le64(0x0003FFFFFFULL),
200         },
201         {
202                 cpu_to_le64(0x000003FFFCULL),
203                 cpu_to_le64(0x0ULL),
204                 cpu_to_le64(0x000FFFFFFCULL),
205         },
206         {
207                 cpu_to_le64(0x00001FFFE0ULL),
208                 cpu_to_le64(0x0ULL),
209                 cpu_to_le64(0x007FFFFFE0ULL),
210         },
211         {
212                 cpu_to_le64(0x00007FFF80ULL),
213                 cpu_to_le64(0x00007FFFFFULL),
214                 cpu_to_le64(0x01FFFFFF80ULL),
215         },
216         {
217                 cpu_to_le64(0x0003FFFC00ULL),
218                 cpu_to_le64(0x0003FFFFFFULL),
219                 cpu_to_le64(0x0FFFFFFC00ULL),
220         },
221         {
222                 cpu_to_le64(0x000FFFF000ULL),
223                 cpu_to_le64(0x000FFFFFFCULL),
224                 cpu_to_le64(0x3FFFFFF000ULL),
225         },
226         {
227                 cpu_to_le64(0x007FFF8000ULL),
228                 cpu_to_le64(0x007FFFFFE0ULL),
229                 cpu_to_le64(0xFFFFFF8000ULL),
230         },
231         {
232                 cpu_to_le64(0x01FFFE0000ULL),
233                 cpu_to_le64(0x01FFFFFF80ULL),
234                 cpu_to_le64(0xFFFFFE0000ULL),
235         },
236         {
237                 cpu_to_le64(0x0FFFF00000ULL),
238                 cpu_to_le64(0x0FFFFFFC00ULL),
239                 cpu_to_le64(0x0ULL),
240         },
241         {
242                 cpu_to_le64(0x3FFFC00000ULL),
243                 cpu_to_le64(0x3FFFFFF000ULL),
244                 cpu_to_le64(0x0)
245         },
246         {
247                 cpu_to_le64(0xFFFE000000ULL),
248                 cpu_to_le64(0xFFFFFF8000ULL),
249                 cpu_to_le64(0x0)
250         },
251         {
252                 cpu_to_le64(0xFFF8000000ULL),
253                 cpu_to_le64(0xFFFFFE0000ULL),
254                 cpu_to_le64(0x0)
255         },
256         {
257                 cpu_to_le64(0xFFC0000000ULL),
258                 cpu_to_le64(0x0ULL),
259                 cpu_to_le64(0x0ULL)
260         },
261 };
262
263 static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = {
264         cpu_to_le32(0x28412201),
265         cpu_to_le32(0x11118451),
266 };
267
268 struct corunning_block_luts {
269         u8 range;
270         __le32 lut20[BT_COEX_CORUN_LUT_SIZE];
271 };
272
273 /*
274  * Ranges for the antenna coupling calibration / co-running block LUT:
275  *              LUT0: [ 0, 12[
276  *              LUT1: [12, 20[
277  *              LUT2: [20, 21[
278  *              LUT3: [21, 23[
279  *              LUT4: [23, 27[
280  *              LUT5: [27, 30[
281  *              LUT6: [30, 32[
282  *              LUT7: [32, 33[
283  *              LUT8: [33, - [
284  */
285 static const struct corunning_block_luts antenna_coupling_ranges[] = {
286         {
287                 .range = 0,
288                 .lut20 = {
289                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
290                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
291                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
292                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
293                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
294                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
295                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
296                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
297                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
298                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
299                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
300                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
301                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
302                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
303                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
304                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
305                 },
306         },
307         {
308                 .range = 12,
309                 .lut20 = {
310                         cpu_to_le32(0x00000001),  cpu_to_le32(0x00000000),
311                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
312                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
313                         cpu_to_le32(0x00000000),  cpu_to_le32(0x00000000),
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                 },
327         },
328         {
329                 .range = 20,
330                 .lut20 = {
331                         cpu_to_le32(0x00000002),  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                         cpu_to_le32(0x00000000),  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                 },
348         },
349         {
350                 .range = 21,
351                 .lut20 = {
352                         cpu_to_le32(0x00000003),  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                         cpu_to_le32(0x00000000),  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                 },
369         },
370         {
371                 .range = 23,
372                 .lut20 = {
373                         cpu_to_le32(0x00000004),  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                         cpu_to_le32(0x00000000),  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                 },
390         },
391         {
392                 .range = 27,
393                 .lut20 = {
394                         cpu_to_le32(0x00000005),  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                         cpu_to_le32(0x00000000),  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                 },
411         },
412         {
413                 .range = 30,
414                 .lut20 = {
415                         cpu_to_le32(0x00000006),  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                         cpu_to_le32(0x00000000),  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                 },
432         },
433         {
434                 .range = 32,
435                 .lut20 = {
436                         cpu_to_le32(0x00000007),  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                         cpu_to_le32(0x00000000),  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                 },
453         },
454         {
455                 .range = 33,
456                 .lut20 = {
457                         cpu_to_le32(0x00000008),  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                         cpu_to_le32(0x00000000),  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                 },
474         },
475 };
476
477 static enum iwl_bt_coex_lut_type
478 iwl_get_coex_type(struct iwl_mvm *mvm, const struct ieee80211_vif *vif)
479 {
480         struct ieee80211_chanctx_conf *chanctx_conf;
481         enum iwl_bt_coex_lut_type ret;
482         u16 phy_ctx_id;
483         u32 primary_ch_phy_id, secondary_ch_phy_id;
484
485         /*
486          * Checking that we hold mvm->mutex is a good idea, but the rate
487          * control can't acquire the mutex since it runs in Tx path.
488          * So this is racy in that case, but in the worst case, the AMPDU
489          * size limit will be wrong for a short time which is not a big
490          * issue.
491          */
492
493         rcu_read_lock();
494
495         chanctx_conf = rcu_dereference(vif->chanctx_conf);
496
497         if (!chanctx_conf ||
498              chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) {
499                 rcu_read_unlock();
500                 return BT_COEX_INVALID_LUT;
501         }
502
503         ret = BT_COEX_TX_DIS_LUT;
504
505         if (mvm->cfg->bt_shared_single_ant) {
506                 rcu_read_unlock();
507                 return ret;
508         }
509
510         phy_ctx_id = *((u16 *)chanctx_conf->drv_priv);
511         primary_ch_phy_id = le32_to_cpu(mvm->last_bt_ci_cmd.primary_ch_phy_id);
512         secondary_ch_phy_id =
513                 le32_to_cpu(mvm->last_bt_ci_cmd.secondary_ch_phy_id);
514
515         if (primary_ch_phy_id == phy_ctx_id)
516                 ret = le32_to_cpu(mvm->last_bt_notif.primary_ch_lut);
517         else if (secondary_ch_phy_id == phy_ctx_id)
518                 ret = le32_to_cpu(mvm->last_bt_notif.secondary_ch_lut);
519         /* else - default = TX TX disallowed */
520
521         rcu_read_unlock();
522
523         return ret;
524 }
525
526 int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
527 {
528         struct iwl_bt_coex_cmd *bt_cmd;
529         struct iwl_host_cmd cmd = {
530                 .id = BT_CONFIG,
531                 .len = { sizeof(*bt_cmd), },
532                 .dataflags = { IWL_HCMD_DFL_NOCOPY, },
533         };
534         int ret;
535         u32 mode;
536
537         if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
538                 return iwl_send_bt_init_conf_old(mvm);
539
540         bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
541         if (!bt_cmd)
542                 return -ENOMEM;
543         cmd.data[0] = bt_cmd;
544
545         lockdep_assert_held(&mvm->mutex);
546
547         if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) {
548                 u32 mode;
549
550                 switch (mvm->bt_force_ant_mode) {
551                 case BT_FORCE_ANT_BT:
552                         mode = BT_COEX_BT;
553                         break;
554                 case BT_FORCE_ANT_WIFI:
555                         mode = BT_COEX_WIFI;
556                         break;
557                 default:
558                         WARN_ON(1);
559                         mode = 0;
560                 }
561
562                 bt_cmd->mode = cpu_to_le32(mode);
563                 goto send_cmd;
564         }
565
566         bt_cmd->max_kill = cpu_to_le32(5);
567         bt_cmd->bt4_antenna_isolation_thr =
568                                 cpu_to_le32(BT_ANTENNA_COUPLING_THRESHOLD);
569         bt_cmd->bt4_tx_tx_delta_freq_thr = cpu_to_le32(15);
570         bt_cmd->bt4_tx_rx_max_freq0 = cpu_to_le32(15);
571         bt_cmd->override_primary_lut = cpu_to_le32(BT_COEX_INVALID_LUT);
572         bt_cmd->override_secondary_lut = cpu_to_le32(BT_COEX_INVALID_LUT);
573
574         mode = iwlwifi_mod_params.bt_coex_active ? BT_COEX_NW : BT_COEX_DISABLE;
575         bt_cmd->mode = cpu_to_le32(mode);
576
577         if (IWL_MVM_BT_COEX_SYNC2SCO)
578                 bt_cmd->enabled_modules |=
579                         cpu_to_le32(BT_COEX_SYNC2SCO_ENABLED);
580
581         if (IWL_MVM_BT_COEX_CORUNNING)
582                 bt_cmd->enabled_modules |= cpu_to_le32(BT_COEX_CORUN_ENABLED);
583
584         if (IWL_MVM_BT_COEX_MPLUT) {
585                 bt_cmd->enabled_modules |= cpu_to_le32(BT_COEX_MPLUT_ENABLED);
586                 bt_cmd->enabled_modules |=
587                         cpu_to_le32(BT_COEX_MPLUT_BOOST_ENABLED);
588         }
589
590         if (mvm->cfg->bt_shared_single_ant)
591                 memcpy(&bt_cmd->decision_lut, iwl_single_shared_ant,
592                        sizeof(iwl_single_shared_ant));
593         else
594                 memcpy(&bt_cmd->decision_lut, iwl_combined_lookup,
595                        sizeof(iwl_combined_lookup));
596
597         memcpy(&bt_cmd->mplut_prio_boost, iwl_bt_prio_boost,
598                sizeof(iwl_bt_prio_boost));
599         memcpy(&bt_cmd->multiprio_lut, iwl_bt_mprio_lut,
600                sizeof(iwl_bt_mprio_lut));
601
602 send_cmd:
603         memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif));
604         memset(&mvm->last_bt_ci_cmd, 0, sizeof(mvm->last_bt_ci_cmd));
605
606         ret = iwl_mvm_send_cmd(mvm, &cmd);
607
608         kfree(bt_cmd);
609         return ret;
610 }
611
612 static int iwl_mvm_bt_udpate_sw_boost(struct iwl_mvm *mvm,
613                                       bool reduced_tx_power)
614 {
615         enum iwl_bt_kill_msk bt_kill_msk;
616         struct iwl_bt_coex_sw_boost_update_cmd cmd = {};
617         struct iwl_bt_coex_profile_notif *notif = &mvm->last_bt_notif;
618
619         lockdep_assert_held(&mvm->mutex);
620
621         if (reduced_tx_power) {
622                 /* Reduced Tx power has precedence on the type of the profile */
623                 bt_kill_msk = BT_KILL_MSK_REDUCED_TXPOW;
624         } else {
625                 /* Low latency BT profile is active: give higher prio to BT */
626                 if (BT_MBOX_MSG(notif, 3, SCO_STATE)  ||
627                     BT_MBOX_MSG(notif, 3, A2DP_STATE) ||
628                     BT_MBOX_MSG(notif, 3, SNIFF_STATE))
629                         bt_kill_msk = BT_KILL_MSK_SCO_HID_A2DP;
630                 else
631                         bt_kill_msk = BT_KILL_MSK_DEFAULT;
632         }
633
634         IWL_DEBUG_COEX(mvm,
635                        "Update kill_msk: %d - SCO %sactive A2DP %sactive SNIFF %sactive\n",
636                        bt_kill_msk,
637                        BT_MBOX_MSG(notif, 3, SCO_STATE) ? "" : "in",
638                        BT_MBOX_MSG(notif, 3, A2DP_STATE) ? "" : "in",
639                        BT_MBOX_MSG(notif, 3, SNIFF_STATE) ? "" : "in");
640
641         /* Don't send HCMD if there is no update */
642         if (bt_kill_msk == mvm->bt_kill_msk)
643                 return 0;
644
645         mvm->bt_kill_msk = bt_kill_msk;
646
647         cmd.boost_values[0].kill_ack_msk =
648                 cpu_to_le32(iwl_bt_ack_kill_msk[bt_kill_msk]);
649         cmd.boost_values[0].kill_cts_msk =
650                 cpu_to_le32(iwl_bt_cts_kill_msk[bt_kill_msk]);
651
652         cmd.boost_values[1].kill_ack_msk = cmd.boost_values[0].kill_ack_msk;
653         cmd.boost_values[2].kill_cts_msk = cmd.boost_values[0].kill_cts_msk;
654         cmd.boost_values[1].kill_ack_msk = cmd.boost_values[0].kill_ack_msk;
655         cmd.boost_values[2].kill_cts_msk = cmd.boost_values[0].kill_cts_msk;
656
657         IWL_DEBUG_COEX(mvm, "ACK Kill msk = 0x%08x, CTS Kill msk = 0x%08x\n",
658                        iwl_bt_ack_kill_msk[bt_kill_msk],
659                        iwl_bt_cts_kill_msk[bt_kill_msk]);
660
661         return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_UPDATE_SW_BOOST, 0,
662                                     sizeof(cmd), &cmd);
663 }
664
665 static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
666                                        bool enable)
667 {
668         struct iwl_bt_coex_cmd_old *bt_cmd;
669         /* Send ASYNC since this can be sent from an atomic context */
670         struct iwl_host_cmd cmd = {
671                 .id = BT_CONFIG,
672                 .len = { sizeof(*bt_cmd), },
673                 .dataflags = { IWL_HCMD_DFL_NOCOPY, },
674                 .flags = CMD_ASYNC,
675         };
676         struct iwl_mvm_sta *mvmsta;
677         int ret;
678
679         return 0;
680
681         mvmsta = iwl_mvm_sta_from_staid_protected(mvm, sta_id);
682         if (!mvmsta)
683                 return 0;
684
685         /* nothing to do */
686         if (mvmsta->bt_reduced_txpower == enable)
687                 return 0;
688
689         bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_ATOMIC);
690         if (!bt_cmd)
691                 return -ENOMEM;
692         cmd.data[0] = bt_cmd;
693         bt_cmd->flags = cpu_to_le32(BT_COEX_NW_OLD);
694
695         bt_cmd->valid_bit_msk =
696                 cpu_to_le32(BT_VALID_ENABLE | BT_VALID_REDUCED_TX_POWER);
697         bt_cmd->bt_reduced_tx_power = sta_id;
698
699         if (enable)
700                 bt_cmd->bt_reduced_tx_power |= BT_REDUCED_TX_POWER_BIT;
701
702         IWL_DEBUG_COEX(mvm, "%sable reduced Tx Power for sta %d\n",
703                        enable ? "en" : "dis", sta_id);
704
705         mvmsta->bt_reduced_txpower = enable;
706
707         ret = iwl_mvm_send_cmd(mvm, &cmd);
708
709         kfree(bt_cmd);
710         return ret;
711 }
712
713 struct iwl_bt_iterator_data {
714         struct iwl_bt_coex_profile_notif *notif;
715         struct iwl_mvm *mvm;
716         u32 num_bss_ifaces;
717         bool reduced_tx_power;
718         struct ieee80211_chanctx_conf *primary;
719         struct ieee80211_chanctx_conf *secondary;
720         bool primary_ll;
721 };
722
723 static inline
724 void iwl_mvm_bt_coex_enable_rssi_event(struct iwl_mvm *mvm,
725                                        struct ieee80211_vif *vif,
726                                        bool enable, int rssi)
727 {
728         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
729
730         mvmvif->bf_data.last_bt_coex_event = rssi;
731         mvmvif->bf_data.bt_coex_max_thold =
732                 enable ? -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH : 0;
733         mvmvif->bf_data.bt_coex_min_thold =
734                 enable ? -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH : 0;
735 }
736
737 /* must be called under rcu_read_lock */
738 static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
739                                       struct ieee80211_vif *vif)
740 {
741         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
742         struct iwl_bt_iterator_data *data = _data;
743         struct iwl_mvm *mvm = data->mvm;
744         struct ieee80211_chanctx_conf *chanctx_conf;
745         enum ieee80211_smps_mode smps_mode;
746         u32 bt_activity_grading;
747         int ave_rssi;
748
749         lockdep_assert_held(&mvm->mutex);
750
751         switch (vif->type) {
752         case NL80211_IFTYPE_STATION:
753                 /* Count BSSes vifs */
754                 data->num_bss_ifaces++;
755                 /* default smps_mode for BSS / P2P client is AUTOMATIC */
756                 smps_mode = IEEE80211_SMPS_AUTOMATIC;
757                 break;
758         case NL80211_IFTYPE_AP:
759                 /* default smps_mode for AP / GO is OFF */
760                 smps_mode = IEEE80211_SMPS_OFF;
761                 if (!mvmvif->ap_ibss_active) {
762                         iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
763                                             smps_mode);
764                         return;
765                 }
766
767                 /* the Ack / Cts kill mask must be default if AP / GO */
768                 data->reduced_tx_power = false;
769                 break;
770         default:
771                 return;
772         }
773
774         chanctx_conf = rcu_dereference(vif->chanctx_conf);
775
776         /* If channel context is invalid or not on 2.4GHz .. */
777         if ((!chanctx_conf ||
778              chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ)) {
779                 /* ... relax constraints and disable rssi events */
780                 iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
781                                     smps_mode);
782                 data->reduced_tx_power = false;
783                 if (vif->type == NL80211_IFTYPE_STATION) {
784                         iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
785                                                     false);
786                         iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
787                 }
788                 return;
789         }
790
791         bt_activity_grading = le32_to_cpu(data->notif->bt_activity_grading);
792         if (bt_activity_grading >= BT_HIGH_TRAFFIC)
793                 smps_mode = IEEE80211_SMPS_STATIC;
794         else if (bt_activity_grading >= BT_LOW_TRAFFIC)
795                 smps_mode = vif->type == NL80211_IFTYPE_AP ?
796                                 IEEE80211_SMPS_OFF :
797                                 IEEE80211_SMPS_DYNAMIC;
798
799         /* relax SMPS contraints for next association */
800         if (!vif->bss_conf.assoc)
801                 smps_mode = IEEE80211_SMPS_AUTOMATIC;
802
803         IWL_DEBUG_COEX(data->mvm,
804                        "mac %d: bt_activity_grading %d smps_req %d\n",
805                        mvmvif->id, bt_activity_grading, smps_mode);
806
807         iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX, smps_mode);
808
809         /* low latency is always primary */
810         if (iwl_mvm_vif_low_latency(mvmvif)) {
811                 data->primary_ll = true;
812
813                 data->secondary = data->primary;
814                 data->primary = chanctx_conf;
815         }
816
817         if (vif->type == NL80211_IFTYPE_AP) {
818                 if (!mvmvif->ap_ibss_active)
819                         return;
820
821                 if (chanctx_conf == data->primary)
822                         return;
823
824                 if (!data->primary_ll) {
825                         /*
826                          * downgrade the current primary no matter what its
827                          * type is.
828                          */
829                         data->secondary = data->primary;
830                         data->primary = chanctx_conf;
831                 } else {
832                         /* there is low latency vif - we will be secondary */
833                         data->secondary = chanctx_conf;
834                 }
835                 return;
836         }
837
838         /*
839          * STA / P2P Client, try to be primary if first vif. If we are in low
840          * latency mode, we are already in primary and just don't do much
841          */
842         if (!data->primary || data->primary == chanctx_conf)
843                 data->primary = chanctx_conf;
844         else if (!data->secondary)
845                 /* if secondary is not NULL, it might be a GO */
846                 data->secondary = chanctx_conf;
847
848         /*
849          * don't reduce the Tx power if one of these is true:
850          *  we are in LOOSE
851          *  single share antenna product
852          *  BT is active
853          *  we are associated
854          */
855         if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
856             mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc ||
857             le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF) {
858                 data->reduced_tx_power = false;
859                 iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false);
860                 iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
861                 return;
862         }
863
864         /* try to get the avg rssi from fw */
865         ave_rssi = mvmvif->bf_data.ave_beacon_signal;
866
867         /* if the RSSI isn't valid, fake it is very low */
868         if (!ave_rssi)
869                 ave_rssi = -100;
870         if (ave_rssi > -IWL_MVM_BT_COEX_EN_RED_TXP_THRESH) {
871                 if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, true))
872                         IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
873
874                 /*
875                  * bt_kill_msk can be BT_KILL_MSK_REDUCED_TXPOW only if all the
876                  * BSS / P2P clients have rssi above threshold.
877                  * We set the bt_kill_msk to BT_KILL_MSK_REDUCED_TXPOW before
878                  * the iteration, if one interface's rssi isn't good enough,
879                  * bt_kill_msk will be set to default values.
880                  */
881         } else if (ave_rssi < -IWL_MVM_BT_COEX_DIS_RED_TXP_THRESH) {
882                 if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
883                         IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
884
885                 /*
886                  * One interface hasn't rssi above threshold, bt_kill_msk must
887                  * be set to default values.
888                  */
889                 data->reduced_tx_power = false;
890         }
891
892         /* Begin to monitor the RSSI: it may influence the reduced Tx power */
893         iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, true, ave_rssi);
894 }
895
896 static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
897 {
898         struct iwl_bt_iterator_data data = {
899                 .mvm = mvm,
900                 .notif = &mvm->last_bt_notif,
901                 .reduced_tx_power = true,
902         };
903         struct iwl_bt_coex_ci_cmd cmd = {};
904         u8 ci_bw_idx;
905
906         /* Ignore updates if we are in force mode */
907         if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
908                 return;
909
910         rcu_read_lock();
911         ieee80211_iterate_active_interfaces_atomic(
912                                         mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
913                                         iwl_mvm_bt_notif_iterator, &data);
914
915         if (data.primary) {
916                 struct ieee80211_chanctx_conf *chan = data.primary;
917                 if (WARN_ON(!chan->def.chan)) {
918                         rcu_read_unlock();
919                         return;
920                 }
921
922                 if (chan->def.width < NL80211_CHAN_WIDTH_40) {
923                         ci_bw_idx = 0;
924                 } else {
925                         if (chan->def.center_freq1 >
926                             chan->def.chan->center_freq)
927                                 ci_bw_idx = 2;
928                         else
929                                 ci_bw_idx = 1;
930                 }
931
932                 cmd.bt_primary_ci =
933                         iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx];
934                 cmd.primary_ch_phy_id =
935                         cpu_to_le32(*((u16 *)data.primary->drv_priv));
936         }
937
938         if (data.secondary) {
939                 struct ieee80211_chanctx_conf *chan = data.secondary;
940                 if (WARN_ON(!data.secondary->def.chan)) {
941                         rcu_read_unlock();
942                         return;
943                 }
944
945                 if (chan->def.width < NL80211_CHAN_WIDTH_40) {
946                         ci_bw_idx = 0;
947                 } else {
948                         if (chan->def.center_freq1 >
949                             chan->def.chan->center_freq)
950                                 ci_bw_idx = 2;
951                         else
952                                 ci_bw_idx = 1;
953                 }
954
955                 cmd.bt_secondary_ci =
956                         iwl_ci_mask[chan->def.chan->hw_value][ci_bw_idx];
957                 cmd.secondary_ch_phy_id =
958                         cpu_to_le32(*((u16 *)data.secondary->drv_priv));
959         }
960
961         rcu_read_unlock();
962
963         /* Don't spam the fw with the same command over and over */
964         if (memcmp(&cmd, &mvm->last_bt_ci_cmd, sizeof(cmd))) {
965                 if (iwl_mvm_send_cmd_pdu(mvm, BT_COEX_CI, 0,
966                                          sizeof(cmd), &cmd))
967                         IWL_ERR(mvm, "Failed to send BT_CI cmd\n");
968                 memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd));
969         }
970
971         /*
972          * If there are no BSS / P2P client interfaces, reduced Tx Power is
973          * irrelevant since it is based on the RSSI coming from the beacon.
974          * Use BT_KILL_MSK_DEFAULT in that case.
975          */
976         data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
977
978         if (iwl_mvm_bt_udpate_sw_boost(mvm, data.reduced_tx_power))
979                 IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
980 }
981
982 int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
983                              struct iwl_rx_cmd_buffer *rxb,
984                              struct iwl_device_cmd *dev_cmd)
985 {
986         struct iwl_rx_packet *pkt = rxb_addr(rxb);
987         struct iwl_bt_coex_profile_notif *notif = (void *)pkt->data;
988
989         if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
990                 return iwl_mvm_rx_bt_coex_notif_old(mvm, rxb, dev_cmd);
991
992         IWL_DEBUG_COEX(mvm, "BT Coex Notification received\n");
993         IWL_DEBUG_COEX(mvm, "\tBT ci compliance %d\n", notif->bt_ci_compliance);
994         IWL_DEBUG_COEX(mvm, "\tBT primary_ch_lut %d\n",
995                        le32_to_cpu(notif->primary_ch_lut));
996         IWL_DEBUG_COEX(mvm, "\tBT secondary_ch_lut %d\n",
997                        le32_to_cpu(notif->secondary_ch_lut));
998         IWL_DEBUG_COEX(mvm, "\tBT activity grading %d\n",
999                        le32_to_cpu(notif->bt_activity_grading));
1000
1001         /* remember this notification for future use: rssi fluctuations */
1002         memcpy(&mvm->last_bt_notif, notif, sizeof(mvm->last_bt_notif));
1003
1004         iwl_mvm_bt_coex_notif_handle(mvm);
1005
1006         /*
1007          * This is an async handler for a notification, returning anything other
1008          * than 0 doesn't make sense even if HCMD failed.
1009          */
1010         return 0;
1011 }
1012
1013 static void iwl_mvm_bt_rssi_iterator(void *_data, u8 *mac,
1014                                    struct ieee80211_vif *vif)
1015 {
1016         struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
1017         struct iwl_bt_iterator_data *data = _data;
1018         struct iwl_mvm *mvm = data->mvm;
1019
1020         struct ieee80211_sta *sta;
1021         struct iwl_mvm_sta *mvmsta;
1022
1023         struct ieee80211_chanctx_conf *chanctx_conf;
1024
1025         rcu_read_lock();
1026         chanctx_conf = rcu_dereference(vif->chanctx_conf);
1027         /* If channel context is invalid or not on 2.4GHz - don't count it */
1028         if (!chanctx_conf ||
1029             chanctx_conf->def.chan->band != IEEE80211_BAND_2GHZ) {
1030                 rcu_read_unlock();
1031                 return;
1032         }
1033         rcu_read_unlock();
1034
1035         if (vif->type != NL80211_IFTYPE_STATION ||
1036             mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT)
1037                 return;
1038
1039         sta = rcu_dereference_protected(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id],
1040                                         lockdep_is_held(&mvm->mutex));
1041
1042         /* This can happen if the station has been removed right now */
1043         if (IS_ERR_OR_NULL(sta))
1044                 return;
1045
1046         mvmsta = iwl_mvm_sta_from_mac80211(sta);
1047
1048         data->num_bss_ifaces++;
1049
1050         /*
1051          * This interface doesn't support reduced Tx power (because of low
1052          * RSSI probably), then set bt_kill_msk to default values.
1053          */
1054         if (!mvmsta->bt_reduced_txpower)
1055                 data->reduced_tx_power = false;
1056         /* else - possibly leave it to BT_KILL_MSK_REDUCED_TXPOW */
1057 }
1058
1059 void iwl_mvm_bt_rssi_event(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
1060                            enum ieee80211_rssi_event rssi_event)
1061 {
1062         struct iwl_mvm_vif *mvmvif = (void *)vif->drv_priv;
1063         struct iwl_bt_iterator_data data = {
1064                 .mvm = mvm,
1065                 .reduced_tx_power = true,
1066         };
1067         int ret;
1068
1069         if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT)) {
1070                 iwl_mvm_bt_rssi_event_old(mvm, vif, rssi_event);
1071                 return;
1072         }
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 (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF)
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         /*
1113          * If there are no BSS / P2P client interfaces, reduced Tx Power is
1114          * irrelevant since it is based on the RSSI coming from the beacon.
1115          * Use BT_KILL_MSK_DEFAULT in that case.
1116          */
1117         data.reduced_tx_power = data.reduced_tx_power && data.num_bss_ifaces;
1118
1119         if (iwl_mvm_bt_udpate_sw_boost(mvm, data.reduced_tx_power))
1120                 IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
1121 }
1122
1123 #define LINK_QUAL_AGG_TIME_LIMIT_DEF    (4000)
1124 #define LINK_QUAL_AGG_TIME_LIMIT_BT_ACT (1200)
1125
1126 u16 iwl_mvm_coex_agg_time_limit(struct iwl_mvm *mvm,
1127                                 struct ieee80211_sta *sta)
1128 {
1129         struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
1130         enum iwl_bt_coex_lut_type lut_type;
1131
1132         if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
1133                 return iwl_mvm_coex_agg_time_limit_old(mvm, sta);
1134
1135         if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) <
1136             BT_HIGH_TRAFFIC)
1137                 return LINK_QUAL_AGG_TIME_LIMIT_DEF;
1138 /*
1139         TODO
1140         if (mvm->last_bt_notif.ttc_enabled)
1141                 return LINK_QUAL_AGG_TIME_LIMIT_DEF;
1142 */
1143
1144         lut_type = iwl_get_coex_type(mvm, mvmsta->vif);
1145
1146         if (lut_type == BT_COEX_LOOSE_LUT || lut_type == BT_COEX_INVALID_LUT)
1147                 return LINK_QUAL_AGG_TIME_LIMIT_DEF;
1148
1149         /* tight coex, high bt traffic, reduce AGG time limit */
1150         return LINK_QUAL_AGG_TIME_LIMIT_BT_ACT;
1151 }
1152
1153 bool iwl_mvm_bt_coex_is_mimo_allowed(struct iwl_mvm *mvm,
1154                                      struct ieee80211_sta *sta)
1155 {
1156         struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta);
1157         enum iwl_bt_coex_lut_type lut_type;
1158
1159         if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
1160                 return iwl_mvm_coex_agg_time_limit_old(mvm, sta);
1161
1162 /*
1163         TODO
1164         if (mvm->last_bt_notif.ttc_enabled)
1165                 return true;
1166 */
1167
1168         if (le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) <
1169             BT_HIGH_TRAFFIC)
1170                 return true;
1171
1172         /*
1173          * In Tight / TxTxDis, BT can't Rx while we Tx, so use both antennas
1174          * since BT is already killed.
1175          * In Loose, BT can Rx while we Tx, so forbid MIMO to let BT Rx while
1176          * we Tx.
1177          * When we are in 5GHz, we'll get BT_COEX_INVALID_LUT allowing MIMO.
1178          */
1179         lut_type = iwl_get_coex_type(mvm, mvmsta->vif);
1180         return lut_type != BT_COEX_LOOSE_LUT;
1181 }
1182
1183 bool iwl_mvm_bt_coex_is_shared_ant_avail(struct iwl_mvm *mvm)
1184 {
1185         if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
1186                 return iwl_mvm_bt_coex_is_shared_ant_avail_old(mvm);
1187
1188         return le32_to_cpu(mvm->last_bt_notif.bt_activity_grading) == BT_OFF;
1189 }
1190
1191 bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm,
1192                                     enum ieee80211_band band)
1193 {
1194         u32 bt_activity = le32_to_cpu(mvm->last_bt_notif.bt_activity_grading);
1195
1196         if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
1197                 return iwl_mvm_bt_coex_is_tpc_allowed_old(mvm, band);
1198
1199         if (band != IEEE80211_BAND_2GHZ)
1200                 return false;
1201
1202         return bt_activity >= BT_LOW_TRAFFIC;
1203 }
1204
1205 u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
1206                            struct ieee80211_tx_info *info, u8 ac)
1207 {
1208         __le16 fc = hdr->frame_control;
1209
1210         if (info->band != IEEE80211_BAND_2GHZ)
1211                 return 0;
1212
1213         if (unlikely(mvm->bt_tx_prio))
1214                 return mvm->bt_tx_prio - 1;
1215
1216         /* High prio packet (wrt. BT coex) if it is EAPOL, MCAST or MGMT */
1217         if (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO ||
1218              is_multicast_ether_addr(hdr->addr1) ||
1219              ieee80211_is_ctl(fc) || ieee80211_is_mgmt(fc) ||
1220              ieee80211_is_nullfunc(fc) || ieee80211_is_qos_nullfunc(fc))
1221                 return 3;
1222
1223         switch (ac) {
1224         case IEEE80211_AC_BE:
1225                 return 1;
1226         case IEEE80211_AC_VO:
1227                 return 3;
1228         case IEEE80211_AC_VI:
1229                 return 2;
1230         default:
1231                 break;
1232         }
1233
1234         return 0;
1235 }
1236
1237 void iwl_mvm_bt_coex_vif_change(struct iwl_mvm *mvm)
1238 {
1239         if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT)) {
1240                 iwl_mvm_bt_coex_vif_change_old(mvm);
1241                 return;
1242         }
1243
1244         iwl_mvm_bt_coex_notif_handle(mvm);
1245 }
1246
1247 int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm,
1248                                   struct iwl_rx_cmd_buffer *rxb,
1249                                   struct iwl_device_cmd *dev_cmd)
1250 {
1251         struct iwl_rx_packet *pkt = rxb_addr(rxb);
1252         u32 ant_isolation = le32_to_cpup((void *)pkt->data);
1253         u8 __maybe_unused lower_bound, upper_bound;
1254         int ret;
1255         u8 lut;
1256
1257         struct iwl_bt_coex_cmd_old *bt_cmd;
1258         struct iwl_host_cmd cmd = {
1259                 .id = BT_CONFIG,
1260                 .len = { sizeof(*bt_cmd), },
1261                 .dataflags = { IWL_HCMD_DFL_NOCOPY, },
1262         };
1263
1264         if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_BT_COEX_SPLIT))
1265                 return iwl_mvm_rx_ant_coupling_notif_old(mvm, rxb, dev_cmd);
1266
1267         /* TODO */
1268         return 0;
1269
1270         if (!IWL_MVM_BT_COEX_CORUNNING)
1271                 return 0;
1272
1273         lockdep_assert_held(&mvm->mutex);
1274
1275         /* Ignore updates if we are in force mode */
1276         if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS))
1277                 return 0;
1278
1279         if (ant_isolation ==  mvm->last_ant_isol)
1280                 return 0;
1281
1282         for (lut = 0; lut < ARRAY_SIZE(antenna_coupling_ranges) - 1; lut++)
1283                 if (ant_isolation < antenna_coupling_ranges[lut + 1].range)
1284                         break;
1285
1286         lower_bound = antenna_coupling_ranges[lut].range;
1287
1288         if (lut < ARRAY_SIZE(antenna_coupling_ranges) - 1)
1289                 upper_bound = antenna_coupling_ranges[lut + 1].range;
1290         else
1291                 upper_bound = antenna_coupling_ranges[lut].range;
1292
1293         IWL_DEBUG_COEX(mvm, "Antenna isolation=%d in range [%d,%d[, lut=%d\n",
1294                        ant_isolation, lower_bound, upper_bound, lut);
1295
1296         mvm->last_ant_isol = ant_isolation;
1297
1298         if (mvm->last_corun_lut == lut)
1299                 return 0;
1300
1301         mvm->last_corun_lut = lut;
1302
1303         bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_KERNEL);
1304         if (!bt_cmd)
1305                 return 0;
1306         cmd.data[0] = bt_cmd;
1307
1308         bt_cmd->flags = cpu_to_le32(BT_COEX_NW_OLD);
1309         bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_ENABLE |
1310                                              BT_VALID_CORUN_LUT_20 |
1311                                              BT_VALID_CORUN_LUT_40);
1312
1313         /* For the moment, use the same LUT for 20GHz and 40GHz */
1314         memcpy(bt_cmd->bt4_corun_lut20, antenna_coupling_ranges[lut].lut20,
1315                sizeof(bt_cmd->bt4_corun_lut20));
1316
1317         memcpy(bt_cmd->bt4_corun_lut40, antenna_coupling_ranges[lut].lut20,
1318                sizeof(bt_cmd->bt4_corun_lut40));
1319
1320         ret = iwl_mvm_send_cmd(mvm, &cmd);
1321
1322         kfree(bt_cmd);
1323         return ret;
1324 }