Commit 8a309305 authored by Felix Fietkau's avatar Felix Fietkau Committed by John W. Linville

ath9k_hw: make bluetooth coexistence support optional at compile time

Many systems (e.g. embedded systems) do not have wifi modules connected to
bluetooth modules, so bluetooth coexistence is irrelevant there. With the
addition of MCI support, ath9k picked up quite a bit of extra code that
can be compiled out this way.

This patch redefines ATH9K_HW_CAP_MCI and adds an inline wrapper for
querying the bluetooth coexistence scheme, allowing the compiler to
eliminate code that uses it, with only very little use of #ifdef.

On MIPS this reduces the total size for the modules by about 20k.
Signed-off-by: default avatarFelix Fietkau <nbd@openwrt.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 104cfa88
......@@ -81,6 +81,14 @@ config ATH9K_RATE_CONTROL
Say Y, if you want to use the ath9k specific rate control
module instead of minstrel_ht.
config ATH9K_BTCOEX_SUPPORT
bool "Atheros ath9k bluetooth coexistence support"
depends on ATH9K
default y
---help---
Say Y, if you want to use the ath9k radios together with
Bluetooth modules in the same system.
config ATH9K_HTC
tristate "Atheros HTC based wireless cards support"
depends on USB && MAC80211
......
......@@ -85,6 +85,9 @@ void ar9003_mci_remote_reset(struct ath_hw *ah, bool wait_done)
{
u32 payload[4] = { 0xffffffff, 0xffffffff, 0xffffffff, 0xffffff00};
if (!ATH9K_HW_CAP_MCI)
return;
ar9003_mci_send_message(ah, MCI_REMOTE_RESET, 0, payload, 16,
wait_done, false);
udelay(5);
......@@ -94,6 +97,9 @@ void ar9003_mci_send_lna_transfer(struct ath_hw *ah, bool wait_done)
{
u32 payload = 0x00000000;
if (!ATH9K_HW_CAP_MCI)
return;
ar9003_mci_send_message(ah, MCI_LNA_TRANS, 0, &payload, 1,
wait_done, false);
}
......@@ -107,6 +113,9 @@ static void ar9003_mci_send_req_wake(struct ath_hw *ah, bool wait_done)
void ar9003_mci_send_sys_waking(struct ath_hw *ah, bool wait_done)
{
if (!ATH9K_HW_CAP_MCI)
return;
ar9003_mci_send_message(ah, MCI_SYS_WAKING, MCI_FLAG_DISABLE_TIMESTAMP,
NULL, 0, wait_done, false);
}
......@@ -220,6 +229,9 @@ void ar9003_mci_send_coex_halt_bt_gpm(struct ath_hw *ah, bool halt,
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
u32 payload[4] = {0, 0, 0, 0};
if (!ATH9K_HW_CAP_MCI)
return;
ath_dbg(common, MCI, "MCI Send Coex %s BT GPM\n",
(halt) ? "halt" : "unhalt");
......@@ -374,12 +386,17 @@ static void ar9003_mci_prep_interface(struct ath_hw *ah)
void ar9003_mci_disable_interrupt(struct ath_hw *ah)
{
if (!ATH9K_HW_CAP_MCI)
return;
REG_WRITE(ah, AR_MCI_INTERRUPT_EN, 0);
REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN, 0);
}
void ar9003_mci_enable_interrupt(struct ath_hw *ah)
{
if (!ATH9K_HW_CAP_MCI)
return;
REG_WRITE(ah, AR_MCI_INTERRUPT_EN, AR_MCI_INTERRUPT_DEFAULT);
REG_WRITE(ah, AR_MCI_INTERRUPT_RX_MSG_EN,
......@@ -390,6 +407,9 @@ bool ar9003_mci_check_int(struct ath_hw *ah, u32 ints)
{
u32 intr;
if (!ATH9K_HW_CAP_MCI)
return false;
intr = REG_READ(ah, AR_MCI_INTERRUPT_RX_MSG_RAW);
return ((intr & ints) == ints);
}
......@@ -398,6 +418,10 @@ void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr,
u32 *rx_msg_intr)
{
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
if (!ATH9K_HW_CAP_MCI)
return;
*raw_intr = mci->raw_intr;
*rx_msg_intr = mci->rx_msg_intr;
......@@ -411,6 +435,9 @@ void ar9003_mci_2g5g_changed(struct ath_hw *ah, bool is_2g)
{
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
if (!ATH9K_HW_CAP_MCI)
return;
if (!mci->update_2g5g &&
(mci->is_2g != is_2g))
mci->update_2g5g = true;
......@@ -524,6 +551,9 @@ void ar9003_mci_reset(struct ath_hw *ah, bool en_int, bool is_2g,
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
u32 regval, thresh;
if (!ATH9K_HW_CAP_MCI)
return;
ath_dbg(common, MCI, "MCI full_sleep = %d, is_2g = %d\n",
is_full_sleep, is_2g);
......@@ -650,6 +680,9 @@ void ar9003_mci_mute_bt(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
if (!ATH9K_HW_CAP_MCI)
return;
/* disable all MCI messages */
REG_WRITE(ah, AR_MCI_MSG_ATTRIBUTES_TABLE, 0xffff0000);
REG_WRITE(ah, AR_BTCOEX_WL_WEIGHTS0, 0xffffffff);
......@@ -682,6 +715,9 @@ void ar9003_mci_sync_bt_state(struct ath_hw *ah)
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
u32 cur_bt_state;
if (!ATH9K_HW_CAP_MCI)
return;
cur_bt_state = ar9003_mci_state(ah, MCI_STATE_REMOTE_SLEEP, NULL);
if (mci->bt_state != cur_bt_state) {
......@@ -844,6 +880,9 @@ void ar9003_mci_2g5g_switch(struct ath_hw *ah, bool wait_done)
struct ath_common *common = ath9k_hw_common(ah);
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
if (!ATH9K_HW_CAP_MCI)
return;
if (mci->update_2g5g) {
if (mci->is_2g) {
......@@ -895,6 +934,9 @@ bool ar9003_mci_send_message(struct ath_hw *ah, u8 header, u32 flag,
u32 saved_mci_int_en;
int i;
if (!ATH9K_HW_CAP_MCI)
return false;
saved_mci_int_en = REG_READ(ah, AR_MCI_INTERRUPT_EN);
regval = REG_READ(ah, AR_BTCOEX_CTRL);
......@@ -961,6 +1003,9 @@ void ar9003_mci_setup(struct ath_hw *ah, u32 gpm_addr, void *gpm_buf,
struct ath9k_hw_mci *mci = &ah->btcoex_hw.mci;
void *sched_buf = (void *)((char *) gpm_buf + (sched_addr - gpm_addr));
if (!ATH9K_HW_CAP_MCI)
return;
mci->gpm_addr = gpm_addr;
mci->gpm_buf = gpm_buf;
mci->gpm_len = len;
......@@ -975,6 +1020,9 @@ void ar9003_mci_cleanup(struct ath_hw *ah)
{
struct ath_common *common = ath9k_hw_common(ah);
if (!ATH9K_HW_CAP_MCI)
return;
/* Turn off MCI and Jupiter mode. */
REG_WRITE(ah, AR_BTCOEX_CTRL, 0x00);
ath_dbg(common, MCI, "MCI ar9003_mci_cleanup\n");
......@@ -1039,6 +1087,9 @@ u32 ar9003_mci_wait_for_gpm(struct ath_hw *ah, u8 gpm_type,
u8 recv_type = 0, recv_opcode = 0;
bool b_is_bt_cal_done = (gpm_type == MCI_GPM_BT_CAL_DONE);
if (!ATH9K_HW_CAP_MCI)
return 0;
more_data = time_out ? MCI_GPM_NOMORE : MCI_GPM_MORE;
while (time_out > 0) {
......@@ -1168,6 +1219,9 @@ u32 ar9003_mci_state(struct ath_hw *ah, u32 state_type, u32 *p_data)
u32 value = 0, more_gpm = 0, gpm_ptr;
u8 query_type;
if (!ATH9K_HW_CAP_MCI)
return 0;
switch (state_type) {
case MCI_STATE_ENABLE:
if (mci->ready) {
......
......@@ -68,6 +68,9 @@ void ath9k_hw_init_btcoex_hw(struct ath_hw *ah, int qnum)
u32 i, idx;
bool rxclear_polarity = ath_bt_config.bt_rxclear_polarity;
if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
return;
if (AR_SREV_9300_20_OR_LATER(ah))
rxclear_polarity = !ath_bt_config.bt_rxclear_polarity;
......@@ -99,6 +102,9 @@ void ath9k_hw_btcoex_init_2wire(struct ath_hw *ah)
{
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
return;
/* connect bt_active to baseband */
REG_CLR_BIT(ah, AR_GPIO_INPUT_EN_VAL,
(AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_DEF |
......@@ -121,6 +127,9 @@ void ath9k_hw_btcoex_init_3wire(struct ath_hw *ah)
{
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
return;
/* btcoex 3-wire */
REG_SET_BIT(ah, AR_GPIO_INPUT_EN_VAL,
(AR_GPIO_INPUT_EN_VAL_BT_PRIORITY_BB |
......@@ -147,6 +156,9 @@ static void ath9k_hw_btcoex_enable_2wire(struct ath_hw *ah)
{
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
return;
/* Configure the desired GPIO port for TX_FRAME output */
ath9k_hw_cfg_output(ah, btcoex_hw->wlanactive_gpio,
AR_GPIO_OUTPUT_MUX_AS_TX_FRAME);
......@@ -158,6 +170,9 @@ void ath9k_hw_btcoex_set_weight(struct ath_hw *ah,
{
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
return;
btcoex_hw->bt_coex_weights = SM(bt_weight, AR_BTCOEX_BT_WGHT) |
SM(wlan_weight, AR_BTCOEX_WL_WGHT);
}
......@@ -219,9 +234,9 @@ void ath9k_hw_btcoex_enable(struct ath_hw *ah)
{
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
switch (btcoex_hw->scheme) {
switch (ath9k_hw_get_btcoex_scheme(ah)) {
case ATH_BTCOEX_CFG_NONE:
break;
return;
case ATH_BTCOEX_CFG_2WIRE:
ath9k_hw_btcoex_enable_2wire(ah);
break;
......@@ -246,6 +261,9 @@ void ath9k_hw_btcoex_disable(struct ath_hw *ah)
struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
int i;
if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
return;
btcoex_hw->enabled = false;
if (btcoex_hw->scheme == ATH_BTCOEX_CFG_MCI) {
ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
......@@ -294,6 +312,9 @@ static void ar9003_btcoex_bt_stomp(struct ath_hw *ah,
void ath9k_hw_btcoex_bt_stomp(struct ath_hw *ah,
enum ath_stomp_type stomp_type)
{
if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
return;
if (AR_SREV_9300_20_OR_LATER(ah)) {
ar9003_btcoex_bt_stomp(ah, stomp_type);
return;
......
......@@ -249,6 +249,9 @@ 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;
......@@ -281,6 +284,9 @@ 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);
......@@ -301,6 +307,9 @@ 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)
......
......@@ -115,6 +115,9 @@ void ath_htc_init_btcoex_work(struct ath9k_htc_priv *priv)
{
struct ath_btcoex *btcoex = &priv->btcoex;
if (ath9k_hw_get_btcoex_scheme(priv->ah) == ATH_BTCOEX_CFG_NONE)
return;
btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD;
btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
btcoex->btcoex_period / 100;
......@@ -133,6 +136,9 @@ void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv)
struct ath_btcoex *btcoex = &priv->btcoex;
struct ath_hw *ah = priv->ah;
if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
return;
ath_dbg(ath9k_hw_common(ah), BTCOEX, "Starting btcoex work\n");
btcoex->bt_priority_cnt = 0;
......@@ -147,6 +153,9 @@ void ath_htc_resume_btcoex_work(struct ath9k_htc_priv *priv)
*/
void ath_htc_cancel_btcoex_work(struct ath9k_htc_priv *priv)
{
if (ath9k_hw_get_btcoex_scheme(priv->ah) == ATH_BTCOEX_CFG_NONE)
return;
cancel_delayed_work_sync(&priv->coex_period_work);
cancel_delayed_work_sync(&priv->duty_cycle_work);
}
......
......@@ -607,7 +607,7 @@ static void ath9k_init_btcoex(struct ath9k_htc_priv *priv)
{
int qnum;
switch (priv->ah->btcoex_hw.scheme) {
switch (ath9k_hw_get_btcoex_scheme(priv->ah)) {
case ATH_BTCOEX_CFG_NONE:
break;
case ATH_BTCOEX_CFG_3WIRE:
......@@ -701,7 +701,8 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
if (product && strncmp(product, ATH_HTC_BTCOEX_PRODUCT_ID, 5) == 0) {
ah->btcoex_hw.scheme = ATH_BTCOEX_CFG_3WIRE;
ath9k_init_btcoex(priv);
if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE)
ath9k_init_btcoex(priv);
}
return 0;
......
......@@ -957,7 +957,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
mod_timer(&priv->tx.cleanup_timer,
jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL));
if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE) {
if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE) {
ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
AR_STOMP_LOW_WLAN_WGHT);
ath9k_hw_btcoex_enable(ah);
......@@ -1009,7 +1009,8 @@ static void ath9k_htc_stop(struct ieee80211_hw *hw)
mutex_lock(&priv->mutex);
if (ah->btcoex_hw.enabled) {
if (ah->btcoex_hw.enabled &&
ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) {
ath9k_hw_btcoex_disable(ah);
if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
ath_htc_cancel_btcoex_work(priv);
......
......@@ -1891,7 +1891,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
#endif
}
if (ah->btcoex_hw.enabled)
if (ah->btcoex_hw.enabled &&
ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE)
ath9k_hw_btcoex_enable(ah);
if (mci && mci_hw->ready) {
......
......@@ -209,7 +209,11 @@ enum ath9k_hw_caps {
ATH9K_HW_CAP_5GHZ = BIT(12),
ATH9K_HW_CAP_APM = BIT(13),
ATH9K_HW_CAP_RTT = BIT(14),
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
ATH9K_HW_CAP_MCI = BIT(15),
#else
ATH9K_HW_CAP_MCI = 0,
#endif
ATH9K_HW_CAP_DFS = BIT(16),
};
......@@ -1228,6 +1232,16 @@ void ar9003_mci_sync_bt_state(struct ath_hw *ah);
void ar9003_mci_get_interrupt(struct ath_hw *ah, u32 *raw_intr,
u32 *rx_msg_intr);
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
static inline enum ath_btcoex_scheme
ath9k_hw_get_btcoex_scheme(struct ath_hw *ah)
{
return ah->btcoex_hw.scheme;
}
#else
#define ath9k_hw_get_btcoex_scheme(...) ATH_BTCOEX_CFG_NONE
#endif
#define ATH9K_CLOCK_RATE_CCK 22
#define ATH9K_CLOCK_RATE_5GHZ_OFDM 40
#define ATH9K_CLOCK_RATE_2GHZ_OFDM 44
......
......@@ -425,7 +425,7 @@ static int ath9k_init_btcoex(struct ath_softc *sc)
struct ath_hw *ah = sc->sc_ah;
int r;
switch (sc->sc_ah->btcoex_hw.scheme) {
switch (ath9k_hw_get_btcoex_scheme(sc->sc_ah)) {
case ATH_BTCOEX_CFG_NONE:
break;
case ATH_BTCOEX_CFG_2WIRE:
......@@ -880,10 +880,10 @@ static void ath9k_deinit_softc(struct ath_softc *sc)
kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels);
if ((sc->btcoex.no_stomp_timer) &&
sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
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 (sc->sc_ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_MCI)
if (ath9k_hw_get_btcoex_scheme(sc->sc_ah) == ATH_BTCOEX_CFG_MCI)
ath_mci_cleanup(sc);
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
......
......@@ -741,11 +741,11 @@ void ath9k_tasklet(unsigned long data)
ath_tx_tasklet(sc);
}
if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
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)
if ((status & ATH9K_INT_MCI) && ATH9K_HW_CAP_MCI)
ath_mci_intr(sc);
out:
......@@ -1081,14 +1081,14 @@ static int ath9k_start(struct ieee80211_hw *hw)
spin_unlock_bh(&sc->sc_pcu_lock);
if ((ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) &&
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 (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
ath9k_btcoex_timer_resume(sc);
}
......@@ -1191,9 +1191,10 @@ static void ath9k_stop(struct ieee80211_hw *hw)
/* Ensure HW is awake when we try to shut it down. */
ath9k_ps_wakeup(sc);
if (ah->btcoex_hw.enabled) {
if (ah->btcoex_hw.enabled &&
ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) {
ath9k_hw_btcoex_disable(ah);
if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
if (ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_3WIRE)
ath9k_btcoex_timer_pause(sc);
ath_mci_flush_profile(&sc->btcoex.mci);
}
......
......@@ -417,6 +417,9 @@ int ath_mci_setup(struct ath_softc *sc)
struct ath_mci_coex *mci = &sc->mci_coex;
int error = 0;
if (!ATH9K_HW_CAP_MCI)
return 0;
mci->sched_buf.bf_len = ATH_MCI_SCHED_BUF_SIZE + ATH_MCI_GPM_BUF_SIZE;
if (ath_mci_buf_alloc(sc, &mci->sched_buf)) {
......@@ -450,6 +453,9 @@ void ath_mci_cleanup(struct ath_softc *sc)
struct ath_hw *ah = sc->sc_ah;
struct ath_mci_coex *mci = &sc->mci_coex;
if (!ATH9K_HW_CAP_MCI)
return;
/*
* both schedule and gpm buffers will be released
*/
......@@ -468,6 +474,9 @@ void ath_mci_intr(struct ath_softc *sc)
u32 more_data = MCI_GPM_MORE;
bool skip_gpm = false;
if (!ATH9K_HW_CAP_MCI)
return;
ar9003_mci_get_interrupt(sc->sc_ah, &mci_int, &mci_int_rxmsg);
if (ar9003_mci_state(ah, MCI_STATE_ENABLE, NULL) == 0) {
......
......@@ -121,7 +121,7 @@ static void ath_pci_aspm_init(struct ath_common *common)
if (!parent)
return;
if (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE) {
if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) {
/* Bluetooth coexistance requires disabling ASPM. */
pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &aspm);
aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment