FreeBSD kernel ATH device code
if_ath_btcoex_mci.c
Go to the documentation of this file.
1/*-
2 * Copyright (c) 2014 Qualcomm Atheros, Inc.
3 * Copyright (c) 2016 Adrian Chadd <adrian@FreeBSD.org>
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer,
11 * without modification.
12 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
13 * similar to the "NO WARRANTY" disclaimer below ("Disclaimer") and any
14 * redistribution must be conditioned upon including a substantially
15 * similar Disclaimer requirement for further binary redistribution.
16 *
17 * NO WARRANTY
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF NONINFRINGEMENT, MERCHANTIBILITY
21 * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
22 * THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY,
23 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
26 * IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
28 * THE POSSIBILITY OF SUCH DAMAGES.
29 *
30 * $FreeBSD$
31 */
32#include <sys/cdefs.h>
33__FBSDID("$FreeBSD$");
34
35/*
36 * This implements the MCI bluetooth coexistence handling.
37 */
38#include "opt_ath.h"
39#include "opt_inet.h"
40#include "opt_wlan.h"
41
42#include <sys/param.h>
43#include <sys/systm.h>
44#include <sys/sysctl.h>
45#include <sys/kernel.h>
46#include <sys/lock.h>
47#include <sys/malloc.h>
48#include <sys/mutex.h>
49#include <sys/errno.h>
50
51#include <machine/bus.h>
52#include <machine/resource.h>
53
54#include <sys/bus.h>
55
56#include <sys/socket.h>
57
58#include <net/if.h>
59#include <net/if_var.h>
60#include <net/if_media.h>
61#include <net/if_arp.h>
62#include <net/ethernet.h> /* XXX for ether_sprintf */
63
64#include <net80211/ieee80211_var.h>
65
66#include <net/bpf.h>
67
68#ifdef INET
69#include <netinet/in.h>
70#include <netinet/if_ether.h>
71#endif
72
73#include <dev/ath/if_athvar.h>
77
79
81
82#define ATH_MCI_GPM_MAX_ENTRY 16
83#define ATH_MCI_GPM_BUF_SIZE (ATH_MCI_GPM_MAX_ENTRY * 16)
84#define ATH_MCI_SCHED_BUF_SIZE (16 * 16) /* 16 entries, 4 dword each */
85
87
88int
90{
91 int buflen, error;
92
94 error = ath_descdma_alloc_desc(sc, &sc->sc_btcoex.buf, NULL,
95 "MCI bufs", buflen, 1);
96 if (error != 0) {
97 device_printf(sc->sc_dev, "%s: failed to alloc MCI RAM\n",
98 __func__);
99 return (error);
100 }
101
102 /* Yes, we're going to do bluetooth MCI coex */
103 sc->sc_btcoex_mci = 1;
104
105 /* Initialise the wlan channel mapping */
106 sc->sc_btcoex.wlan_channels[0] = 0x00000000;
107 sc->sc_btcoex.wlan_channels[1] = 0xffffffff;
108 sc->sc_btcoex.wlan_channels[2] = 0xffffffff;
109 sc->sc_btcoex.wlan_channels[3] = 0x7fffffff;
110
111 /*
112 * Ok, so the API is a bit odd. It assumes sched_addr is
113 * after gpm_addr, and it does math to figure out the right
114 * sched_buf pointer.
115 *
116 * So, set gpm_addr to buf, sched_addr to gpm_addr + ATH_MCI_GPM_BUF_SIZE,
117 * the HAL call with do (gpm_buf + (sched_addr - gpm_addr)) to
118 * set sched_buf, and we're "golden".
119 *
120 * Note, it passes in 'len' here (gpm_len) as
121 * ATH_MCI_GPM_BUF_SIZE >> 4. My guess is that it's 16
122 * bytes per entry and we're storing 16 entries.
123 */
124 sc->sc_btcoex.gpm_buf = (void *) sc->sc_btcoex.buf.dd_desc;
127
131
132 /* memset the gpm buffer with MCI_GPM_RSVD_PATTERN */
133 memset(sc->sc_btcoex.gpm_buf, 0xfe, buflen);
134
135 /*
136 * This is an unfortunate x86'ism in the HAL - the
137 * HAL code expects the passed in buffer to be
138 * coherent, and doesn't implement /any/ kind
139 * of buffer sync operations at all.
140 *
141 * So, this code will only work on dma coherent buffers
142 * and will behave poorly on non-coherent systems.
143 * Fixing this would require some HAL surgery so it
144 * actually /did/ the buffer flushing as appropriate.
145 */
148 sc->sc_btcoex.gpm_buf,
151
152 return (0);
153}
154
155/*
156 * Detach btcoex from the given interface
157 */
158int
160{
161
163 ath_descdma_cleanup(sc, &sc->sc_btcoex.buf, NULL);
164 return (0);
165}
166
167/*
168 * Configure or disable bluetooth coexistence on the given channel.
169 *
170 * For MCI, we just use the top-level enable/disable flag, and
171 * then the MCI reset / channel update path will configure things
172 * appropriately based on the current band.
173 */
174int
176 const struct ieee80211_channel *chan)
177{
178
179 /*
180 * Always reconfigure stomp-all for now, so wlan wins.
181 *
182 * The default weights still don't allow beacons to win,
183 * so unless you set net.wlan.X.bmiss_max to something higher,
184 * net80211 will disconnect you during a HCI INQUIRY command.
185 *
186 * The longer-term solution is to dynamically adjust whether
187 * bmiss happens based on bluetooth requirements, and look at
188 * making the individual stomp bits configurable.
189 */
191
192 /*
193 * update wlan channels so the firmware knows what channels it
194 * can/can't use.
195 */
197
198 return (0);
199}
200
201/*
202 * XXX TODO: turn into general btcoex, and then make this
203 * the MCI specific bits.
204 */
205static void
207 void *param)
208{
209
210 if (! sc->sc_btcoex_mci)
211 return;
212
213 /*
214 * Check whether we need to flush our local profile cache.
215 * If we do, then at (XXX TODO) we should flush our state,
216 * then wait for the MCI response with the updated profile list.
217 */
220 uint32_t data = 0;
221
223 HAL_MCI_STATE_ENABLE, NULL) != 0) {
224 DPRINTF(sc, ATH_DEBUG_BTCOEX,
225 "(MCI) Flush BT profile\n");
226 /*
227 * XXX TODO: flush profile state on the ath(4)
228 * driver side; subsequent messages will come
229 * through with the current list of active
230 * profiles.
231 */
236 }
237 }
238 if (nevent == ATH_COEX_EVENT_BT_NOOP) {
239 DPRINTF(sc, ATH_DEBUG_BTCOEX, "(MCI) BT_NOOP\n");
240 return;
241 }
242}
243
244static void
245ath_btcoex_mci_send_gpm(struct ath_softc *sc, uint32_t *payload)
246{
247
248 ath_hal_btcoex_mci_send_message(sc->sc_ah, MCI_GPM, 0, payload, 16,
250}
251
252/*
253 * This starts a BT calibration. It requires a chip reset.
254 */
255static int
256ath_btcoex_mci_bt_cal_do(struct ath_softc *sc, int tx_timeout, int rx_timeout)
257{
258
259 device_printf(sc->sc_dev, "%s: TODO!\n", __func__);
260 return (0);
261}
262
263static void
264ath_btcoex_mci_cal_msg(struct ath_softc *sc, uint8_t opcode,
265 uint8_t *rx_payload)
266{
267 uint32_t payload[4] = {0, 0, 0, 0};
268
269 switch (opcode) {
271 DPRINTF(sc, ATH_DEBUG_BTCOEX, "(MCI) receive BT_CAL_REQ\n");
273 NULL) == MCI_BT_AWAKE) {
276 ath_btcoex_mci_bt_cal_do(sc, 1000, 1000);
277 } else {
278 DPRINTF(sc, ATH_DEBUG_BTCOEX,
279 "(MCI) State mismatches: %d\n",
281 HAL_MCI_STATE_BT, NULL));
282 }
283 break;
285 DPRINTF(sc, ATH_DEBUG_BTCOEX, "(MCI) receive BT_CAL_DONE\n");
287 NULL) == MCI_BT_CAL) {
288 DPRINTF(sc, ATH_DEBUG_BTCOEX,
289 "(MCI) ERROR ILLEGAL!\n");
290 } else {
291 DPRINTF(sc, ATH_DEBUG_BTCOEX,
292 "(MCI) BT not in CAL state.\n");
293 }
294 break;
296 DPRINTF(sc, ATH_DEBUG_BTCOEX, "(MCI) receive BT_CAL_GRANT\n");
297 /* Send WLAN_CAL_DONE for now */
298 DPRINTF(sc, ATH_DEBUG_BTCOEX, "(MCI) Send WLAN_CAL_DONE\n");
300 ath_btcoex_mci_send_gpm(sc, &payload[0]);
301 break;
302 default:
303 DPRINTF(sc, ATH_DEBUG_BTCOEX,
304 "(MCI) Unknown GPM CAL message.\n");
305 break;
306 }
307}
308
309/*
310 * Update the bluetooth channel map.
311 *
312 * This map tells the bluetooth device which bluetooth channels
313 * are available for data.
314 *
315 * For 5GHz, all channels are available.
316 * For 2GHz, the current wifi channel range is blocked out,
317 * and the rest are available.
318 *
319 * This narrows which frequencies are used by the device when
320 * it initiates a transfer, thus hopefully reducing the chances
321 * of collisions (both hopefully on the current device and
322 * other devices in the same channel.)
323 */
324static void
326{
327 struct ieee80211com *ic = &sc->sc_ic;
328 struct ieee80211_channel *chan = ic->ic_curchan;
329 uint32_t channel_info[4] =
330 { 0x00000000, 0xffffffff, 0xffffffff, 0x7fffffff };
331 int32_t wl_chan, bt_chan, bt_start = 0, bt_end = 79;
332
333 /* BT channel frequency is 2402 + k, k = 0 ~ 78 */
334 if (IEEE80211_IS_CHAN_2GHZ(chan)) {
335 wl_chan = chan->ic_freq - 2402;
336 if (IEEE80211_IS_CHAN_HT40U(chan)) {
337 bt_start = wl_chan - 10;
338 bt_end = wl_chan + 30;
339 } else if (IEEE80211_IS_CHAN_HT40D(chan)) {
340 bt_start = wl_chan - 30;
341 bt_end = wl_chan + 10;
342 } else {
343 /* Assume 20MHz */
344 bt_start = wl_chan - 10;
345 bt_end = wl_chan + 10;
346 }
347
348 bt_start -= 7;
349 bt_end += 7;
350
351 if (bt_start < 0) {
352 bt_start = 0;
353 }
354 if (bt_end > MCI_NUM_BT_CHANNELS) {
355 bt_end = MCI_NUM_BT_CHANNELS;
356 }
357 DPRINTF(sc, ATH_DEBUG_BTCOEX, "(MCI) WLAN use channel %d\n",
358 chan->ic_freq);
359 DPRINTF(sc, ATH_DEBUG_BTCOEX,
360 "(MCI) mask BT channel %d - %d\n", bt_start, bt_end);
361 for (bt_chan = bt_start; bt_chan < bt_end; bt_chan++) {
362 MCI_GPM_CLR_CHANNEL_BIT(&channel_info[0], bt_chan);
363 }
364 } else {
365 DPRINTF(sc, ATH_DEBUG_BTCOEX,
366 "(MCI) WLAN not use any 2G channel, unmask all for BT\n");
367 }
369 &channel_info[0]);
370}
371
372static void
373ath_btcoex_mci_coex_msg(struct ath_softc *sc, uint8_t opcode,
374 uint8_t *rx_payload)
375{
376 uint32_t version;
377 uint8_t major;
378 uint8_t minor;
379 uint32_t seq_num;
380
381 switch (opcode) {
383 DPRINTF(sc, ATH_DEBUG_BTCOEX,
384 "(MCI) Recv GPM COEX Version Query.\n");
385 version = ath_hal_btcoex_mci_state(sc->sc_ah,
387 break;
388
390 DPRINTF(sc, ATH_DEBUG_BTCOEX,
391 "(MCI) Recv GPM COEX Version Response.\n");
392 major = *(rx_payload + MCI_GPM_COEX_B_MAJOR_VERSION);
393 minor = *(rx_payload + MCI_GPM_COEX_B_MINOR_VERSION);
394 DPRINTF(sc, ATH_DEBUG_BTCOEX,
395 "(MCI) BT Coex version: %d.%d\n", major, minor);
396 version = (major << 8) + minor;
397 version = ath_hal_btcoex_mci_state(sc->sc_ah,
399 break;
400
402 DPRINTF(sc, ATH_DEBUG_BTCOEX,
403 "(MCI) Recv GPM COEX Status Query = 0x%02x.\n",
404 *(rx_payload + MCI_GPM_COEX_B_WLAN_BITMAP));
407 break;
408
410 /*
411 * XXX TODO: here is where we'd parse active profile
412 * info and make driver/stack choices as appropriate.
413 */
414 DPRINTF(sc, ATH_DEBUG_BTCOEX,
415 "(MCI) TODO: Recv GPM COEX BT_Profile_Info.\n");
416 break;
417
419 seq_num = *((uint32_t *)(rx_payload + 12));
420 DPRINTF(sc, ATH_DEBUG_BTCOEX,
421 "(MCI) Recv GPM COEX BT_Status_Update: SEQ=%d\n",
422 seq_num);
423 break;
424
425 default:
426 DPRINTF(sc, ATH_DEBUG_BTCOEX,
427 "(MCI) Unknown GPM COEX message = 0x%02x\n", opcode);
428 break;
429 }
430}
431
432void
434{
435 uint32_t mciInt, mciIntRxMsg;
436 uint32_t offset, subtype, opcode;
437 uint32_t *pGpm;
438 uint32_t more_data = HAL_MCI_GPM_MORE;
439 int8_t value_dbm;
440 bool skip_gpm = false;
441
442 DPRINTF(sc, ATH_DEBUG_BTCOEX, "%s: called\n", __func__);
443
444 ath_hal_btcoex_mci_get_interrupt(sc->sc_ah, &mciInt, &mciIntRxMsg);
445
447 NULL) == 0) {
450 DPRINTF(sc, ATH_DEBUG_BTCOEX,
451 "(MCI) INTR but MCI_disabled\n");
452 DPRINTF(sc, ATH_DEBUG_BTCOEX,
453 "(MCI) MCI interrupt: mciInt = 0x%x, mciIntRxMsg = 0x%x\n",
454 mciInt, mciIntRxMsg);
455 return;
456 }
457
458 if (mciIntRxMsg & HAL_MCI_INTERRUPT_RX_MSG_REQ_WAKE) {
459 uint32_t payload4[4] = { 0xffffffff, 0xffffffff, 0xffffffff,
460 0xffffff00};
461
462 /*
463 * The following REMOTE_RESET and SYS_WAKING used to sent
464 * only when BT wake up. Now they are always sent, as a
465 * recovery method to reset BT MCI's RX alignment.
466 */
467 DPRINTF(sc, ATH_DEBUG_BTCOEX,
468 "(MCI) 1. INTR Send REMOTE_RESET\n");
470 MCI_REMOTE_RESET, 0, payload4, 16, AH_TRUE, AH_FALSE);
471 DPRINTF(sc, ATH_DEBUG_BTCOEX,
472 "(MCI) 1. INTR Send SYS_WAKING\n");
474 MCI_SYS_WAKING, 0, NULL, 0, AH_TRUE, AH_FALSE);
475
476 mciIntRxMsg &= ~HAL_MCI_INTERRUPT_RX_MSG_REQ_WAKE;
479
480 /* always do this for recovery and 2G/5G toggling and LNA_TRANS */
481 DPRINTF(sc, ATH_DEBUG_BTCOEX,
482 "(MCI) 1. Set BT state to AWAKE.\n");
485 }
486
487 /* Processing SYS_WAKING/SYS_SLEEPING */
488 if (mciIntRxMsg & HAL_MCI_INTERRUPT_RX_MSG_SYS_WAKING) {
489 mciIntRxMsg &= ~HAL_MCI_INTERRUPT_RX_MSG_SYS_WAKING;
491 NULL) == MCI_BT_SLEEP) {
494 DPRINTF(sc, ATH_DEBUG_BTCOEX,
495 "(MCI) 2. BT stays in SLEEP mode.\n");
496 } else {
497 DPRINTF(sc, ATH_DEBUG_BTCOEX,
498 "(MCI) 2. Set BT state to AWAKE.\n");
501 }
502 } else {
503 DPRINTF(sc, ATH_DEBUG_BTCOEX,
504 "(MCI) 2. BT stays in AWAKE mode.\n");
505 }
506 }
507
508 if (mciIntRxMsg & HAL_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING) {
509 mciIntRxMsg &= ~HAL_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING;
511 NULL) == MCI_BT_AWAKE) {
514 DPRINTF(sc, ATH_DEBUG_BTCOEX,
515 "(MCI) 3. BT stays in AWAKE mode.\n");
516 } else {
517 DPRINTF(sc, ATH_DEBUG_BTCOEX,
518 "(MCI) 3. Set BT state to SLEEP.\n");
521 }
522 } else {
523 DPRINTF(sc, ATH_DEBUG_BTCOEX,
524 "(MCI) 3. BT stays in SLEEP mode.\n");
525 }
526 }
527
528 /*
529 * Recover from out-of-order / wrong-offset GPM messages.
530 */
531 if ((mciInt & HAL_MCI_INTERRUPT_RX_INVALID_HDR) ||
533 DPRINTF(sc, ATH_DEBUG_BTCOEX,
534 "(MCI) MCI RX broken, skip GPM messages\n");
537 skip_gpm = true;
538 }
539
540 if (mciIntRxMsg & HAL_MCI_INTERRUPT_RX_MSG_SCHD_INFO) {
541 mciIntRxMsg &= ~HAL_MCI_INTERRUPT_RX_MSG_SCHD_INFO;
542 offset = ath_hal_btcoex_mci_state(sc->sc_ah,
544 }
545
546 /*
547 * Parse GPM messages.
548 */
549 if (mciIntRxMsg & HAL_MCI_INTERRUPT_RX_MSG_GPM) {
550 mciIntRxMsg &= ~HAL_MCI_INTERRUPT_RX_MSG_GPM;
551
552 while (more_data == HAL_MCI_GPM_MORE) {
553 pGpm = (void *) sc->sc_btcoex.gpm_buf;
554 offset = ath_hal_btcoex_mci_state(sc->sc_ah,
556
557 if (offset == HAL_MCI_GPM_INVALID)
558 break;
559 pGpm += (offset >> 2);
560 /*
561 * The first DWORD is a timer.
562 * The real data starts from the second DWORD.
563 */
564 subtype = MCI_GPM_TYPE(pGpm);
565 opcode = MCI_GPM_OPCODE(pGpm);
566
567 if (!skip_gpm) {
568 if (MCI_GPM_IS_CAL_TYPE(subtype)) {
569 ath_btcoex_mci_cal_msg(sc, subtype,
570 (uint8_t*) pGpm);
571 } else {
572 switch (subtype) {
575 opcode, (uint8_t*) pGpm);
576 break;
577 case MCI_GPM_BT_DEBUG:
578 device_printf(sc->sc_dev,
579 "(MCI) TODO: GPM_BT_DEBUG!\n");
580 break;
581 default:
582 DPRINTF(sc, ATH_DEBUG_BTCOEX,
583 "(MCI) Unknown GPM message.\n");
584 break;
585 }
586 }
587 }
588 MCI_GPM_RECYCLE(pGpm);
589 }
590 }
591
592 /*
593 * This is monitoring/management information messages, so the driver
594 * layer can hook in and dynamically adjust things like aggregation
595 * size, expected bluetooth/wifi traffic throughput, etc.
596 *
597 * None of that is done right now; it just passes off the values
598 * to the HAL so it can update its internal state as appropriate.
599 * This code just prints out the values for debugging purposes.
600 */
601 if (mciIntRxMsg & HAL_MCI_INTERRUPT_RX_MSG_MONITOR) {
602 if (mciIntRxMsg & HAL_MCI_INTERRUPT_RX_MSG_LNA_CONTROL) {
603 mciIntRxMsg &= ~HAL_MCI_INTERRUPT_RX_MSG_LNA_CONTROL;
604 DPRINTF(sc, ATH_DEBUG_BTCOEX, "(MCI) LNA_CONTROL\n");
605 }
606 if (mciIntRxMsg & HAL_MCI_INTERRUPT_RX_MSG_LNA_INFO) {
607 mciIntRxMsg &= ~HAL_MCI_INTERRUPT_RX_MSG_LNA_INFO;
608 DPRINTF(sc, ATH_DEBUG_BTCOEX, "(MCI) LNA_INFO\n");
609 }
610 if (mciIntRxMsg & HAL_MCI_INTERRUPT_RX_MSG_CONT_INFO) {
611 value_dbm = ath_hal_btcoex_mci_state(sc->sc_ah,
613
614 mciIntRxMsg &= ~HAL_MCI_INTERRUPT_RX_MSG_CONT_INFO;
617 DPRINTF(sc, ATH_DEBUG_BTCOEX,
618 "(MCI) CONT_INFO: (tx) pri = %d, pwr = %d dBm\n",
621 value_dbm);
622 } else {
623 DPRINTF(sc, ATH_DEBUG_BTCOEX,
624 "(MCI) CONT_INFO: (rx) pri = %d, rssi = %d dBm\n",
627 value_dbm);
628 }
629 }
630 if (mciIntRxMsg & HAL_MCI_INTERRUPT_RX_MSG_CONT_NACK) {
631 mciIntRxMsg &= ~HAL_MCI_INTERRUPT_RX_MSG_CONT_NACK;
632 DPRINTF(sc, ATH_DEBUG_BTCOEX, "(MCI) CONT_NACK\n");
633 }
634 if (mciIntRxMsg & HAL_MCI_INTERRUPT_RX_MSG_CONT_RST) {
635 mciIntRxMsg &= ~HAL_MCI_INTERRUPT_RX_MSG_CONT_RST;
636 DPRINTF(sc, ATH_DEBUG_BTCOEX, "(MCI) CONT_RST\n");
637 }
638 }
639
640 /*
641 * Recover the state engine if we hit an invalid header/timeout.
642 * This is the final part of GPT out-of-sync recovery.
643 */
644 if ((mciInt & HAL_MCI_INTERRUPT_RX_INVALID_HDR) ||
649 }
650
651 if (mciIntRxMsg & 0xfffffffe) {
652 DPRINTF(sc, ATH_DEBUG_BTCOEX,
653 "(MCI) Not processed IntRxMsg = 0x%x\n", mciIntRxMsg);
654 }
655}
@ AH_FALSE
Definition: ah.h:94
@ AH_TRUE
Definition: ah.h:95
#define MCI_GPM_SET_CAL_TYPE(_p_gpm, _cal_type)
Definition: ah_btcoex.h:319
#define MCI_GPM_TYPE(_p_gpm)
Definition: ah_btcoex.h:314
#define MCI_GPM_IS_CAL_TYPE(_type)
Definition: ah_btcoex.h:328
#define HAL_MCI_INTERRUPT_CONT_INFO_TIMEOUT
Definition: ah_btcoex.h:358
#define MCI_GPM_RECYCLE(_p_gpm)
Definition: ah_btcoex.h:310
#define HAL_MCI_INTERRUPT_RX_MSG_LNA_CONTROL
Definition: ah_btcoex.h:365
#define MCI_GPM_OPCODE(_p_gpm)
Definition: ah_btcoex.h:316
@ MCI_GPM_COEX_BT_PROFILE_INFO
Definition: ah_btcoex.h:216
@ MCI_GPM_COEX_VERSION_QUERY
Definition: ah_btcoex.h:211
@ MCI_GPM_COEX_VERSION_RESPONSE
Definition: ah_btcoex.h:212
@ MCI_GPM_COEX_STATUS_QUERY
Definition: ah_btcoex.h:213
@ MCI_GPM_COEX_BT_STATUS_UPDATE
Definition: ah_btcoex.h:217
#define HAL_MCI_INTERRUPT_RX_MSG_CONT_INFO
Definition: ah_btcoex.h:367
#define HAL_MCI_INTERRUPT_RX_MSG_REQ_WAKE
Definition: ah_btcoex.h:375
@ MCI_BT_CAL
Definition: ah_btcoex.h:386
@ MCI_BT_AWAKE
Definition: ah_btcoex.h:384
@ MCI_BT_SLEEP
Definition: ah_btcoex.h:383
#define HAL_MCI_INTERRUPT_RX_MSG_SYS_SLEEPING
Definition: ah_btcoex.h:373
#define HAL_MCI_INTERRUPT_RX_MSG_CONT_NACK
Definition: ah_btcoex.h:366
#define HAL_MCI_GPM_INVALID
Definition: ah_btcoex.h:471
#define HAL_MCI_INTERRUPT_RX_INVALID_HDR
Definition: ah_btcoex.h:351
#define HAL_MCI_INTERRUPT_RX_MSG_CONT_RST
Definition: ah_btcoex.h:368
#define HAL_MCI_INTERRUPT_RX_MSG_LNA_INFO
Definition: ah_btcoex.h:372
#define HAL_MCI_INTERRUPT_RX_MSG_SCHD_INFO
Definition: ah_btcoex.h:369
#define MCI_NUM_BT_CHANNELS
Definition: ah_btcoex.h:330
#define HAL_MCI_INTERRUPT_RX_MSG_SYS_WAKING
Definition: ah_btcoex.h:374
#define HAL_MCI_INTERRUPT_RX_MSG_GPM
Definition: ah_btcoex.h:371
@ MCI_GPM_WLAN_CAL_DONE
Definition: ah_btcoex.h:203
@ MCI_GPM_BT_CAL_REQ
Definition: ah_btcoex.h:198
@ MCI_GPM_BT_CAL_GRANT
Definition: ah_btcoex.h:199
@ MCI_GPM_COEX_AGENT
Definition: ah_btcoex.h:204
@ MCI_GPM_BT_CAL_DONE
Definition: ah_btcoex.h:200
@ MCI_GPM_BT_DEBUG
Definition: ah_btcoex.h:207
@ MCI_GPM_COEX_B_MAJOR_VERSION
Definition: ah_btcoex.h:282
@ MCI_GPM_COEX_B_WLAN_BITMAP
Definition: ah_btcoex.h:286
@ MCI_GPM_COEX_B_MINOR_VERSION
Definition: ah_btcoex.h:283
#define MCI_GPM_CLR_CHANNEL_BIT(_p_gpm, _bt_chan)
Definition: ah_btcoex.h:340
@ HAL_BT_COEX_STOMP_ALL
Definition: ah_btcoex.h:99
@ HAL_MCI_STATE_CONT_PRIORITY
Definition: ah_btcoex.h:403
@ HAL_MCI_STATE_INIT_GPM_OFFSET
Definition: ah_btcoex.h:392
@ HAL_MCI_STATE_RECOVER_RX
Definition: ah_btcoex.h:413
@ HAL_MCI_STATE_RESET_REQ_WAKE
Definition: ah_btcoex.h:405
@ HAL_MCI_STATE_BT
Definition: ah_btcoex.h:395
@ HAL_MCI_STATE_LAST_SCHD_MSG_OFFSET
Definition: ah_btcoex.h:400
@ HAL_MCI_STATE_NEXT_GPM_OFFSET
Definition: ah_btcoex.h:393
@ HAL_MCI_STATE_SEND_WLAN_CHANNELS
Definition: ah_btcoex.h:408
@ HAL_MCI_STATE_SET_BT_SLEEP
Definition: ah_btcoex.h:396
@ HAL_MCI_STATE_CONT_TXRX
Definition: ah_btcoex.h:404
@ HAL_MCI_STATE_SEND_STATUS_QUERY
Definition: ah_btcoex.h:410
@ HAL_MCI_STATE_SEND_WLAN_COEX_VERSION
Definition: ah_btcoex.h:406
@ HAL_MCI_STATE_NEED_FLUSH_BT_INFO
Definition: ah_btcoex.h:411
@ HAL_MCI_STATE_ENABLE
Definition: ah_btcoex.h:391
@ HAL_MCI_STATE_SET_BT_COEX_VERSION
Definition: ah_btcoex.h:407
@ HAL_MCI_STATE_CONT_RSSI_POWER
Definition: ah_btcoex.h:402
@ HAL_MCI_STATE_SET_BT_CAL_START
Definition: ah_btcoex.h:398
@ HAL_MCI_STATE_REMOTE_SLEEP
Definition: ah_btcoex.h:401
@ HAL_MCI_STATE_SET_BT_AWAKE
Definition: ah_btcoex.h:397
@ MCI_GPM
Definition: ah_btcoex.h:179
@ MCI_REMOTE_RESET
Definition: ah_btcoex.h:187
@ MCI_SYS_WAKING
Definition: ah_btcoex.h:178
#define HAL_MCI_GPM_MORE
Definition: ah_btcoex.h:470
#define HAL_MCI_INTERRUPT_RX_MSG_MONITOR
Definition: ah_btcoex.h:376
ATH_BT_COEX_EVENT
Definition: if_ath_btcoex.h:36
@ ATH_COEX_EVENT_BT_NOOP
Definition: if_ath_btcoex.h:37
static void ath_btcoex_mci_cal_msg(struct ath_softc *sc, uint8_t opcode, uint8_t *rx_payload)
#define ATH_MCI_GPM_BUF_SIZE
static int ath_btcoex_mci_bt_cal_do(struct ath_softc *sc, int tx_timeout, int rx_timeout)
void ath_btcoex_mci_intr(struct ath_softc *sc)
static void ath_btcoex_mci_update_wlan_channels(struct ath_softc *sc)
int ath_btcoex_mci_enable(struct ath_softc *sc, const struct ieee80211_channel *chan)
static void ath_btcoex_mci_send_gpm(struct ath_softc *sc, uint32_t *payload)
int ath_btcoex_mci_detach(struct ath_softc *sc)
__FBSDID("$FreeBSD$")
#define ATH_MCI_SCHED_BUF_SIZE
int ath_btcoex_mci_attach(struct ath_softc *sc)
static void ath_btcoex_mci_event(struct ath_softc *sc, ATH_BT_COEX_EVENT nevent, void *param)
static void ath_btcoex_mci_coex_msg(struct ath_softc *sc, uint8_t opcode, uint8_t *rx_payload)
MALLOC_DECLARE(M_ATHDEV)
#define DPRINTF(sc, m, fmt,...)
Definition: if_ath_debug.h:118
int ath_descdma_alloc_desc(struct ath_softc *sc, struct ath_descdma *dd, ath_bufhead *head, const char *name, int ds_size, int ndesc)
void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd, ath_bufhead *head)
#define ath_hal_btcoex_mci_setup(_ah, _gp, _gb, _gl, _sp)
Definition: if_athvar.h:1530
#define ath_hal_btcoex_set_weights(_ah, _weight)
Definition: if_athvar.h:1519
#define ath_hal_btcoex_mci_get_interrupt(_ah, _mi, _mm)
Definition: if_athvar.h:1534
#define ath_hal_btcoex_mci_send_message(_ah, _h, _f, _p, _l, _wd, _cbt)
Definition: if_athvar.h:1532
#define ath_hal_btcoex_mci_state(_ah, _st, _pd)
Definition: if_athvar.h:1536
#define ath_hal_btcoex_mci_detach(_ah)
Definition: if_athvar.h:1538
struct ath_desc * dd_desc
Definition: if_athvar.h:330
bus_addr_t dd_desc_paddr
Definition: if_athvar.h:332
char * sched_buf
Definition: if_athvar.h:925
bus_addr_t gpm_paddr
Definition: if_athvar.h:928
uint32_t wlan_channels[4]
Definition: if_athvar.h:930
struct ath_descdma buf
Definition: if_athvar.h:922
device_t sc_dev
Definition: if_athvar.h:598
char * gpm_buf
Definition: if_athvar.h:927
u_int32_t sc_btcoex_mci
Definition: if_athvar.h:665
struct ath_hal * sc_ah
Definition: if_athvar.h:612
bus_addr_t sched_paddr
Definition: if_athvar.h:926
struct ath_softc::@36 sc_btcoex
struct ieee80211com sc_ic
Definition: if_athvar.h:562