Index: if_ath.c =================================================================== --- if_ath.c (revision 301185) +++ if_ath.c (working copy) @@ -1352,6 +1352,7 @@ * Stop things cleanly. */ ath_stop(sc); + ath_btcoex_detach(sc); ATH_UNLOCK(sc); ieee80211_ifdetach(&sc->sc_ic); @@ -1365,7 +1366,6 @@ if_ath_alq_tidyup(&sc->sc_alq); #endif ath_lna_div_detach(sc); - ath_btcoex_detach(sc); ath_spectral_detach(sc); ath_dfs_detach(sc); ath_desc_free(sc); @@ -1849,6 +1849,7 @@ ATH_LOCK(sc); callout_stop(&sc->sc_cal_ch); + ath_btcoex_disable(sc); ATH_UNLOCK(sc); /* @@ -2630,6 +2631,7 @@ sc->sc_wd_timer = 0; sc->sc_running = 0; if (!sc->sc_invalid) { + ath_btcoex_disable(sc); if (sc->sc_softled) { callout_stop(&sc->sc_ledtimer); ath_hal_gpioset(ah, sc->sc_ledpin, @@ -2845,6 +2847,11 @@ */ ath_draintxq(sc, reset_type); /* stop xmit side */ + /* Kill any btcoex timers currently running */ + ATH_LOCK(sc); + ath_btcoex_disable(sc); + ATH_UNLOCK(sc); + ath_settkipmic(sc); /* configure TKIP MIC handling */ /* NB: indicate channel change so we do a full reset */ ath_update_chainmasks(sc, ic->ic_curchan); @@ -3412,6 +3419,9 @@ finish: ATH_TX_UNLOCK(sc); + /* EDMA: Push into hardware list as appropriate */ + ath_tx_push_hwq(sc); + /* * Finished transmitting! */ @@ -3954,6 +3964,7 @@ */ qi.tqi_qflags = HAL_TXQ_TXOKINT_ENABLE | HAL_TXQ_TXERRINT_ENABLE + | HAL_TXQ_TXDESCINT_ENABLE | HAL_TXQ_TXURNINT_ENABLE | HAL_TXQ_TXEOLINT_ENABLE | HAL_TXQ_DBA_GATED @@ -4589,6 +4600,9 @@ } ATH_TX_UNLOCK(sc); + /* EDMA: Push into hardware list as appropriate */ + ath_tx_push_hwq(sc); + ATH_LOCK(sc); ath_power_restore_power_state(sc); ATH_UNLOCK(sc); @@ -6168,7 +6182,7 @@ } ATH_UNLOCK(sc); - if (error == 0) { + if (error == 0) { #ifdef ATH_TX99_DIAG if (sc->sc_tx99 != NULL) sc->sc_tx99->start(sc->sc_tx99); Index: if_ath_btcoex.c =================================================================== --- if_ath_btcoex.c (revision 301186) +++ if_ath_btcoex.c (working copy) @@ -70,6 +70,7 @@ #endif #include +#include #include #include @@ -126,10 +127,13 @@ ath_hal_btcoex_set_config(ah, &btconfig); + sc->sc_btcoex.bt_stompmode = HAL_BT_COEX_STOMP_ALL; + /* * Enable antenna diversity. */ ath_hal_btcoex_set_parameter(ah, HAL_BT_COEX_ANTENNA_DIVERSITY, 1); + sc->sc_btcoex_legacy = 1; return (0); } @@ -183,10 +187,13 @@ ath_hal_btcoex_set_config(ah, &btconfig); + sc->sc_btcoex.bt_stompmode = HAL_BT_COEX_STOMP_ALL; + /* * Enable antenna diversity. */ ath_hal_btcoex_set_parameter(ah, HAL_BT_COEX_ANTENNA_DIVERSITY, 1); + sc->sc_btcoex_legacy = 1; return (0); } @@ -232,10 +239,6 @@ btinfo.bt_single_ant = 0; /* 2 antenna on WB335 */ btinfo.bt_isolation = 0; /* in dB, not used */ - /* Implement a default dutycycle/period */ - btinfo.bt_dutyCycle = 55; - btinfo.bt_period = 40; - ath_hal_btcoex_set_info(ah, &btinfo); btconfig.bt_time_extend = 0; @@ -250,11 +253,10 @@ ath_hal_btcoex_set_config(ah, &btconfig); - /* Enable */ - ath_hal_btcoex_enable(sc->sc_ah); - /* Stomp */ - ath_hal_btcoex_set_weights(ah, HAL_BT_COEX_STOMP_NONE); + /* Stomp - XXX should eventually default to LOW */ + ath_hal_btcoex_set_weights(ah, HAL_BT_COEX_STOMP_ALL); + sc->sc_btcoex.bt_stompmode = HAL_BT_COEX_STOMP_ALL; /* * Enable antenna diversity. @@ -262,6 +264,9 @@ ath_hal_btcoex_set_parameter(ah, HAL_BT_COEX_ANTENNA_DIVERSITY, do_btdiv); + /* Enable */ + ath_hal_btcoex_enable(sc->sc_ah); + return (0); } @@ -336,6 +341,102 @@ } #endif +static void +ath_btcoex_nostomp_timer(void *arg) +{ + struct ath_softc *sc = arg; + + DPRINTF(sc, ATH_DEBUG_BTCOEX, "%s: called\n", __func__); + + /* Only do this if we're awake */ + if (sc->sc_cur_powerstate != HAL_PM_AWAKE) + return; + +#if 0 + if (sc->sc_btcoex.bt_stompmode == HAL_BT_COEX_STOMP_LOW) + ath_hal_btcoex_set_weights(sc->sc_ah, HAL_BT_COEX_STOMP_NONE); + else + ath_hal_btcoex_set_weights(sc->sc_ah, HAL_BT_COEX_STOMP_LOW); +#else + ath_hal_btcoex_set_weights(sc->sc_ah, sc->sc_btcoex.bt_stompmode_off); +#endif + ath_hal_btcoex_enable(sc->sc_ah); +} + +static void +ath_btcoex_period_timer(void *arg) +{ + struct ath_softc *sc = arg; + int msec; + + DPRINTF(sc, ATH_DEBUG_BTCOEX, "%s: called\n", __func__); + if (sc->sc_btcoex.bt_period == 0) + return; + + /* Run the configured stomp mode */ + if (sc->sc_cur_powerstate == HAL_PM_AWAKE) { + ath_hal_btcoex_set_weights(sc->sc_ah, sc->sc_btcoex.bt_stompmode); + ath_hal_btcoex_enable(sc->sc_ah); + } + + /* Figure out the next period timer */ + callout_reset(&sc->sc_btcoex.bt_period_timer, + sc->sc_btcoex.bt_period * hz / 1000, + ath_btcoex_period_timer, sc); + + /* Figure out how many ticks for the duty cycle */ + if (sc->sc_btcoex.bt_dutycycle > 0) { + msec = sc->sc_btcoex.bt_period * + sc->sc_btcoex.bt_dutycycle / 100; + DPRINTF(sc, ATH_DEBUG_BTCOEX, "%s: dutycycle=%d msec\n", + __func__, msec); + callout_reset(&sc->sc_btcoex.bt_nostomp_timer, + msec, + ath_btcoex_nostomp_timer, sc); + } +} + +static int +ath_btcoex_sysctl_btstompmode(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + int error, val; + + val = sc->sc_btcoex.bt_stompmode; + + error = sysctl_handle_int(oidp, &val, 0, req); + if (error || !req->newptr) + return (error); + if (val < 0 || val > 6) + return (EINVAL); + sc->sc_btcoex.bt_stompmode = val; + device_printf(sc->sc_dev, "%s: setting btstomp mode to %d\n", + __func__, + sc->sc_btcoex.bt_stompmode); + return (0); +} + +static int +ath_btcoex_sysctl_btstompmode_off(SYSCTL_HANDLER_ARGS) +{ + struct ath_softc *sc = arg1; + int error, val; + + val = sc->sc_btcoex.bt_stompmode_off; + + error = sysctl_handle_int(oidp, &val, 0, req); + if (error || !req->newptr) + return (error); + if (val < 0 || val > 6) + return (EINVAL); + sc->sc_btcoex.bt_stompmode_off = val; + device_printf(sc->sc_dev, "%s: setting btstomp_off mode to %d\n", + __func__, + sc->sc_btcoex.bt_stompmode_off); + return (0); +} + + /* * Methods which are required */ @@ -349,6 +450,8 @@ int ret; struct ath_hal *ah = sc->sc_ah; const char *profname; + struct sysctl_ctx_list *ctx = device_get_sysctl_ctx(sc->sc_dev); + struct sysctl_oid *tree = device_get_sysctl_tree(sc->sc_dev); /* * No chipset bluetooth coexistence? Then do nothing. @@ -387,6 +490,32 @@ if (ret != 0) return (ret); + sc->sc_btcoex_active = 1; + + /* Implement a default dutycycle/period */ + sc->sc_btcoex.bt_dutycycle = 55; /* percent of period */ + sc->sc_btcoex.bt_period = 40; /* msec */ + + /* Default to wlan always winning */ + sc->sc_btcoex.bt_stompmode = HAL_BT_COEX_STOMP_ALL; + sc->sc_btcoex.bt_stompmode_off = HAL_BT_COEX_STOMP_LOW; + + callout_init_mtx(&sc->sc_btcoex.bt_nostomp_timer, &sc->sc_mtx, 0); + callout_init_mtx(&sc->sc_btcoex.bt_period_timer, &sc->sc_mtx, 0); + + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "bt_dutycycle", CTLFLAG_RW, &sc->sc_btcoex.bt_dutycycle, 0, + "no-stomp dutycycle"); + SYSCTL_ADD_INT(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "bt_period", CTLFLAG_RW, &sc->sc_btcoex.bt_period, 0, + "bt period (msec)"); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "bt_stompmode", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_btcoex_sysctl_btstompmode, "I", "stompmode"); + SYSCTL_ADD_PROC(ctx, SYSCTL_CHILDREN(tree), OID_AUTO, + "bt_stompmode_off", CTLTYPE_INT | CTLFLAG_RW, sc, 0, + ath_btcoex_sysctl_btstompmode_off, "I", "stompmode_off"); + return (0); } @@ -396,6 +525,8 @@ int ath_btcoex_detach(struct ath_softc *sc) { + /* Final chance! */ + ath_btcoex_disable(sc); if (sc->sc_btcoex_mci) { ath_btcoex_mci_detach(sc); } @@ -415,6 +546,24 @@ int ath_btcoex_enable(struct ath_softc *sc, const struct ieee80211_channel *chan) { + + DPRINTF(sc, ATH_DEBUG_BTCOEX, "%s: called; active=%d\n", + __func__, sc->sc_btcoex_active); + + if (! sc->sc_btcoex_active) + return (0); + + /* + * If it's a 2g channel, then (re)-start the coex profile timers. + */ + /* Figure out the next period timer */ + if (IEEE80211_IS_CHAN_2GHZ(chan) && sc->sc_btcoex.bt_period > 0) { + callout_reset(&sc->sc_btcoex.bt_period_timer, + sc->sc_btcoex.bt_period * hz / 1000, + ath_btcoex_period_timer, sc); + } + + /* MCI? Hand off to the MCI specific bits */ if (sc->sc_btcoex_mci) { ath_btcoex_mci_enable(sc, chan); } @@ -423,6 +572,23 @@ } /* + * Disable btcoex - eg, during interface shutdown, admin down, detach. + */ +void +ath_btcoex_disable(struct ath_softc *sc) +{ + + DPRINTF(sc, ATH_DEBUG_BTCOEX, "%s: called; active=%d\n", + __func__, sc->sc_btcoex_active); + + if (! sc->sc_btcoex_active) + return; + + callout_stop(&sc->sc_btcoex.bt_nostomp_timer); + callout_stop(&sc->sc_btcoex.bt_period_timer); +} + +/* * Handle ioctl requests from the diagnostic interface. * * The initial part of this code resembles ath_ioctl_diag(); Index: if_ath_btcoex.h =================================================================== --- if_ath_btcoex.h (revision 301185) +++ if_ath_btcoex.h (working copy) @@ -40,5 +40,6 @@ extern int ath_btcoex_ioctl(struct ath_softc *sc, struct ath_diag *ad); extern int ath_btcoex_enable(struct ath_softc *sc, const struct ieee80211_channel *ch); +extern void ath_btcoex_disable(struct ath_softc *sc); #endif /* __IF_ATH_BTCOEX_H__ */ Index: if_ath_btcoex_mci.c =================================================================== --- if_ath_btcoex_mci.c (revision 301185) +++ if_ath_btcoex_mci.c (working copy) @@ -188,6 +188,8 @@ * making the individual stomp bits configurable. */ ath_hal_btcoex_set_weights(sc->sc_ah, HAL_BT_COEX_STOMP_ALL); + //ath_hal_btcoex_set_weights(sc->sc_ah, HAL_BT_COEX_STOMP_LOW); + ath_hal_btcoex_enable(sc->sc_ah); /* * update wlan channels so the firmware knows what channels it @@ -411,7 +413,7 @@ * XXX TODO: here is where we'd parse active profile * info and make driver/stack choices as appropriate. */ - DPRINTF(sc, ATH_DEBUG_BTCOEX, + device_printf(sc->sc_dev, "(MCI) TODO: Recv GPM COEX BT_Profile_Info.\n"); break; Index: if_ath_rx_edma.c =================================================================== --- if_ath_rx_edma.c (revision 301185) +++ if_ath_rx_edma.c (working copy) @@ -427,6 +427,8 @@ rs = &bf->bf_status.ds_rxstat; bf->bf_rxstatus = ath_hal_rxprocdesc(ah, ds, bf->bf_daddr, NULL, rs); + if (bf->bf_rxstatus == HAL_EINPROGRESS) + break; #ifdef ATH_DEBUG if (sc->sc_debug & ATH_DEBUG_RECV_DESC) ath_printrxbuf(sc, bf, 0, bf->bf_rxstatus == HAL_OK); @@ -436,8 +438,6 @@ if_ath_alq_post(&sc->sc_alq, ATH_ALQ_EDMA_RXSTATUS, sc->sc_rx_statuslen, (char *) ds); #endif /* ATH_DEBUG */ - if (bf->bf_rxstatus == HAL_EINPROGRESS) - break; /* * Completed descriptor. Index: if_ath_tdma.c =================================================================== --- if_ath_tdma.c (revision 301185) +++ if_ath_tdma.c (working copy) @@ -143,7 +143,7 @@ bt.bt_nextatim = nexttbtt+1; /* Enables TBTT, DBA, SWBA timers by default */ bt.bt_flags = 0; -#if 0 +#if 1 DPRINTF(sc, ATH_DEBUG_TDMA_TIMER, "%s: intval=%d (0x%08x) nexttbtt=%u (0x%08x), nextdba=%u (0x%08x), nextswba=%u (0x%08x),nextatim=%u (0x%08x)\n", __func__, @@ -664,7 +664,7 @@ * are still pending on the queue. */ if ((! sc->sc_isedma) && - (! ath_hal_stoptxdma(ah, sc->sc_bhalq))) { + (! ath_hal_stoptxdma(ah, sc->sc_bhalq))) { DPRINTF(sc, ATH_DEBUG_ANY, "%s: beacon queue %u did not stop?\n", __func__, sc->sc_bhalq); Index: if_ath_tx.c =================================================================== --- if_ath_tx.c (revision 301185) +++ if_ath_tx.c (working copy) @@ -159,6 +159,7 @@ bf = bf->bf_next; } } + #endif /* ATH_DEBUG_ALQ */ /* @@ -2423,6 +2424,9 @@ ATH_TX_UNLOCK(sc); + /* EDMA: Push into hardware list as appropriate */ + ath_tx_push_hwq(sc); + ATH_PCU_LOCK(sc); sc->sc_txstart_cnt--; ATH_PCU_UNLOCK(sc); Index: if_ath_tx.h =================================================================== --- if_ath_tx.h (revision 301185) +++ if_ath_tx.h (working copy) @@ -163,6 +163,12 @@ #define ath_draintxq(_sc, _rtype) \ (_sc)->sc_tx.xmit_drain((_sc), (_rtype)) +#define ath_tx_push_hwq(_sc) \ + do { \ + if ((_sc)->sc_tx.xmit_push_hwq) \ + (_sc)->sc_tx.xmit_push_hwq((_sc)); \ + } while (0) + extern void ath_xmit_setup_legacy(struct ath_softc *sc); #endif Index: if_ath_tx_edma.c =================================================================== --- if_ath_tx_edma.c (revision 301185) +++ if_ath_tx_edma.c (working copy) @@ -138,6 +138,147 @@ static void ath_edma_tx_processq(struct ath_softc *sc, int dosched); +#ifdef ATH_DEBUG_ALQ +static void +ath_tx_alq_edma_push(struct ath_softc *sc, int txq, int nframes, + int fifo_depth, int frame_cnt) +{ + struct if_ath_alq_tx_fifo_push aq; + + aq.txq = htobe32(txq); + aq.nframes = htobe32(nframes); + aq.fifo_depth = htobe32(fifo_depth); + aq.frame_cnt = htobe32(frame_cnt); + + if_ath_alq_post(&sc->sc_alq, ATH_ALQ_TX_FIFO_PUSH, + sizeof(aq), + (const char *) &aq); +} +#endif /* ATH_DEBUG_ALQ */ + +static void +ath_tx_edma_push_staging_list(struct ath_softc *sc, struct ath_txq *txq, + int limit) +{ + struct ath_buf *bf, *bf_last; + struct ath_buf *bfi, *bfp; + int i, sqdepth; + TAILQ_HEAD(axq_q_f_s, ath_buf) sq; + + ATH_TXQ_LOCK_ASSERT(txq); + + /* + * Don't bother doing any work if it's full. + */ + if (txq->axq_fifo_depth >= HAL_TXFIFO_DEPTH) + return; + + if (TAILQ_EMPTY(&txq->axq_q)) + return; + + TAILQ_INIT(&sq); + + /* + * First pass - walk sq, queue up to 'limit' entries, + * subtract them from the staging queue. + */ + sqdepth = 0; + for (i = 0; i < limit; i++) { + /* Grab the head entry */ + bf = ATH_TXQ_FIRST(txq); + if (bf == NULL) + break; + ATH_TXQ_REMOVE(txq, bf, bf_list); + + /* Queue it into our staging list */ + TAILQ_INSERT_TAIL(&sq, bf, bf_list); + sqdepth++; + } + + /* + * Ok, so now we have a staging list of up to 'limit' + * frames from the txq. Now let's wrap that up + * into its own list and pass that to the hardware + * as one FIFO entry. + */ + + bf = TAILQ_FIRST(&sq); + bf_last = TAILQ_LAST(&sq, axq_q_s); + + /* + * TODO: + * Assemble a local list of frames, up to the dispatch + * limit. That way we don't end up just populating + * this FIFO entry with all the frames, hopefully allowing + * incoming traffic to continue flowing in. + */ + + /* + * Ok, so here's the gymnastics reqiured to make this + * all sensible. + */ + + /* + * Tag the first/last buffer appropriately. + */ + bf->bf_flags |= ATH_BUF_FIFOPTR; + bf_last->bf_flags |= ATH_BUF_FIFOEND; + + /* + * Walk the descriptor list and link them appropriately. + */ + bfp = NULL; + TAILQ_FOREACH(bfi, &sq, bf_list) { + if (bfp != NULL) { + ath_hal_settxdesclink(sc->sc_ah, bfp->bf_lastds, + bfi->bf_daddr); + } + bfp = bfi; + } + + i = 0; + TAILQ_FOREACH(bfi, &sq, bf_list) { +#ifdef ATH_DEBUG + if (sc->sc_debug & ATH_DEBUG_XMIT_DESC) + ath_printtxbuf(sc, bfi, txq->axq_qnum, i, 0); +#endif/* ATH_DEBUG */ +#ifdef ATH_DEBUG_ALQ + if (if_ath_alq_checkdebug(&sc->sc_alq, ATH_ALQ_EDMA_TXDESC)) + ath_tx_alq_post(sc, bfi); +#endif /* ATH_DEBUG_ALQ */ + i++; + } + + /* + * We now need to push this set of frames onto the tail + * of the FIFO queue. We don't adjust the aggregate + * count, only the queue depth counter(s). + * We also need to blank the link pointer now. + */ + TAILQ_CONCAT(&txq->fifo.axq_q, &sq, bf_list); + // axq_link isn't relevant for FIFO entries... + //txq->axq_link = NULL; + + /* Bump total queue tracking in FIFO queue */ + txq->fifo.axq_depth += sqdepth; + + /* Bump FIFO queue */ + txq->axq_fifo_depth++; + DPRINTF(sc, ATH_DEBUG_RESET, "%s: queued %d packets; depth=%d, fifo depth=%d\n", __func__, sqdepth, txq->fifo.axq_depth, txq->axq_fifo_depth); + + /* Push the first entry into the hardware */ + ath_hal_puttxbuf(sc->sc_ah, txq->axq_qnum, bf->bf_daddr); + + /* NB: gated by beacon so safe to start here */ + ath_hal_txstart(sc->sc_ah, txq->axq_qnum); + +#ifdef ATH_DEBUG_ALQ + ath_tx_alq_edma_push(sc, txq->axq_qnum, sqdepth, + txq->axq_fifo_depth, + txq->fifo.axq_depth); +#endif /* ATH_DEBUG_ALQ */ +} + /* * Push some frames into the TX FIFO if we have space. */ @@ -144,8 +285,10 @@ static void ath_edma_tx_fifo_fill(struct ath_softc *sc, struct ath_txq *txq) { +#if 0 struct ath_buf *bf, *bf_last; int i = 0; +#endif ATH_TXQ_LOCK_ASSERT(txq); @@ -153,6 +296,9 @@ __func__, txq->axq_qnum); + ath_tx_edma_push_staging_list(sc, txq, 32); + +#if 0 TAILQ_FOREACH(bf, &txq->axq_q, bf_list) { if (txq->axq_fifo_depth >= HAL_TXFIFO_DEPTH) break; @@ -211,8 +357,25 @@ } if (i > 0) ath_hal_txstart(sc->sc_ah, txq->axq_qnum); +#endif } +#define TXQACTIVE(t, q) ( (t) & (1 << (q))) +static void +ath_edma_tx_push_hwq(struct ath_softc *sc) +{ + int i; + int txqs = sc->sc_txq_active; + + for (i = 0; i < HAL_NUM_TX_QUEUES; i++) + if (ATH_TXQ_SETUP(sc, i) && TXQACTIVE(txqs, i)) { + ATH_TXQ_LOCK(&sc->sc_txq[i]); + ath_edma_tx_fifo_fill(sc, &sc->sc_txq[i]); + ATH_TXQ_UNLOCK(&sc->sc_txq[i]); + } +} +#undef TXQACTIVE + /* * Re-initialise the DMA FIFO with the current contents of * said TXQ. @@ -375,11 +538,13 @@ * in one FIFO push, we can link descriptors together this way. */ +#if 0 /* * Finally, call the FIFO schedule routine to schedule some * frames to the FIFO. */ ath_edma_tx_fifo_fill(sc, txq); +#endif ATH_TXQ_UNLOCK(txq); } @@ -824,8 +989,17 @@ * more frames into it. */ ATH_TXQ_LOCK(txq); - if (dosched) + if (dosched) { +#if 0 ath_edma_tx_fifo_fill(sc, txq); +#endif + /* Quick hack to test */ + /* + * XXX TODO: doesn't do anything yet; the TX queue + * still gets stuck + */ + //ath_hal_txstart(sc->sc_ah, txq->axq_qnum); + } ATH_TXQ_UNLOCK(txq); } @@ -873,4 +1047,5 @@ sc->sc_tx.xmit_dma_restart = ath_edma_dma_restart; sc->sc_tx.xmit_handoff = ath_edma_xmit_handoff; sc->sc_tx.xmit_drain = ath_edma_tx_drain; + sc->sc_tx.xmit_push_hwq = ath_edma_tx_push_hwq; } Index: if_athvar.h =================================================================== --- if_athvar.h (revision 301185) +++ if_athvar.h (working copy) @@ -551,6 +551,7 @@ struct ath_txq *txq, struct ath_buf *bf); void (*xmit_drain)(struct ath_softc *sc, ATH_RESET_TYPE reset_type); + void (*xmit_push_hwq)(struct ath_softc *sc); }; struct ath_softc { @@ -657,7 +658,9 @@ sc_hasenforcetxop : 1, /* support enforce TxOP */ sc_hasdivcomb : 1, /* RX diversity combining */ sc_rx_lnamixer : 1, /* RX using LNA mixing */ - sc_btcoex_mci : 1; /* MCI bluetooth coex */ + sc_btcoex_mci : 1, /* MCI bluetooth coex */ + sc_btcoex_legacy : 1, + sc_btcoex_active : 1; int sc_cabq_enable; /* Enable cabq transmission */ @@ -912,8 +915,8 @@ /* BT coex */ struct { + /* MCI buffer */ struct ath_descdma buf; - /* gpm/sched buffer, saved pointers */ char *sched_buf; bus_addr_t sched_paddr; @@ -920,7 +923,19 @@ char *gpm_buf; bus_addr_t gpm_paddr; + /* Current channel map for MCI */ uint32_t wlan_channels[4]; + + /* Current stomp mode */ + HAL_BT_COEX_STOMP_TYPE bt_stompmode; + HAL_BT_COEX_STOMP_TYPE bt_stompmode_off; + + /* Current BT priority duty cycle/period */ + int bt_dutycycle; /* %age, from 0..100 */ + int bt_period; /* in msec */ + + struct callout bt_nostomp_timer; + struct callout bt_period_timer; } sc_btcoex; };