diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/gpio.c')
| -rw-r--r-- | drivers/net/wireless/ath/ath9k/gpio.c | 123 | 
1 files changed, 113 insertions, 10 deletions
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index 597c84e31ad..63e4c4b1cb3 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c @@ -110,6 +110,8 @@ void ath_start_rfkill_poll(struct ath_softc *sc)  		wiphy_rfkill_start_polling(sc->hw->wiphy);  } +#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT +  /******************/  /*     BTCOEX     */  /******************/ @@ -245,13 +247,10 @@ static void ath_btcoex_no_stomp_timer(void *arg)  	ath9k_ps_restore(sc);  } -int ath_init_btcoex_timer(struct ath_softc *sc) +static int ath_init_btcoex_timer(struct ath_softc *sc)  {  	struct ath_btcoex *btcoex = &sc->btcoex; -	if (ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_NONE) -		return 0; -  	btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD * 1000;  	btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *  		btcoex->btcoex_period / 100; @@ -284,9 +283,6 @@ void ath9k_btcoex_timer_resume(struct ath_softc *sc)  	ath_dbg(ath9k_hw_common(ah), BTCOEX, "Starting btcoex timers\n"); -	if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE) -		return; -  	/* make sure duty cycle timer is also stopped when resuming */  	if (btcoex->hw_timer_enabled)  		ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer); @@ -307,9 +303,6 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc)  	struct ath_btcoex *btcoex = &sc->btcoex;  	struct ath_hw *ah = sc->sc_ah; -	if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE) -		return; -  	del_timer_sync(&btcoex->period_timer);  	if (btcoex->hw_timer_enabled) @@ -317,3 +310,113 @@ void ath9k_btcoex_timer_pause(struct ath_softc *sc)  	btcoex->hw_timer_enabled = false;  } + +u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen) +{ +	struct ath_mci_profile *mci = &sc->btcoex.mci; +	u16 aggr_limit = 0; + +	if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI) && mci->aggr_limit) +		aggr_limit = (max_4ms_framelen * mci->aggr_limit) >> 4; +	else if (sc->sc_flags & SC_OP_BT_PRIORITY_DETECTED) +		aggr_limit = min((max_4ms_framelen * 3) / 8, +				 (u32)ATH_AMPDU_LIMIT_MAX); + +	return aggr_limit; +} + +void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status) +{ +	struct ath_hw *ah = sc->sc_ah; + +	if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE) +		if (status & ATH9K_INT_GENTIMER) +			ath_gen_timer_isr(sc->sc_ah); + +	if (status & ATH9K_INT_MCI) +		ath_mci_intr(sc); +} + +void ath9k_start_btcoex(struct ath_softc *sc) +{ +	struct ath_hw *ah = sc->sc_ah; + +	if ((ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) && +	    !ah->btcoex_hw.enabled) { +		if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI)) +			ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT, +						   AR_STOMP_LOW_WLAN_WGHT); +		ath9k_hw_btcoex_enable(ah); + +		if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE) +			ath9k_btcoex_timer_resume(sc); +	} +} + +void ath9k_stop_btcoex(struct ath_softc *sc) +{ +	struct ath_hw *ah = sc->sc_ah; + +	if (ah->btcoex_hw.enabled && +	    ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) { +		ath9k_hw_btcoex_disable(ah); +		if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE) +			ath9k_btcoex_timer_pause(sc); +		ath_mci_flush_profile(&sc->btcoex.mci); +	} +} + +void ath9k_deinit_btcoex(struct ath_softc *sc) +{ +        if ((sc->btcoex.no_stomp_timer) && +	    ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_3WIRE) +		ath_gen_timer_free(sc->sc_ah, sc->btcoex.no_stomp_timer); + +	if (ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_MCI) +		ath_mci_cleanup(sc); +} + +int ath9k_init_btcoex(struct ath_softc *sc) +{ +	struct ath_txq *txq; +	struct ath_hw *ah = sc->sc_ah; +	int r; + +	ath9k_hw_btcoex_init_scheme(ah); + +	switch (ath9k_hw_get_btcoex_scheme(sc->sc_ah)) { +	case ATH_BTCOEX_CFG_NONE: +		break; +	case ATH_BTCOEX_CFG_2WIRE: +		ath9k_hw_btcoex_init_2wire(sc->sc_ah); +		break; +	case ATH_BTCOEX_CFG_3WIRE: +		ath9k_hw_btcoex_init_3wire(sc->sc_ah); +		r = ath_init_btcoex_timer(sc); +		if (r) +			return -1; +		txq = sc->tx.txq_map[WME_AC_BE]; +		ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum); +		sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; +		break; +	case ATH_BTCOEX_CFG_MCI: +		sc->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW; +		sc->btcoex.duty_cycle = ATH_BTCOEX_DEF_DUTY_CYCLE; +		INIT_LIST_HEAD(&sc->btcoex.mci.info); + +		r = ath_mci_setup(sc); +		if (r) +			return r; + +		ath9k_hw_btcoex_init_mci(ah); + +		break; +	default: +		WARN_ON(1); +		break; +	} + +	return 0; +} + +#endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */  |