Skip to content

Commit

Permalink
ath9k_hw: make bluetooth coexistence support optional at compile time
Browse files Browse the repository at this point in the history
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: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
  • Loading branch information
Felix Fietkau authored and John W. Linville committed Dec 19, 2011
1 parent 104cfa8 commit 8a30930
Showing 13 changed files with 145 additions and 17 deletions.
8 changes: 8 additions & 0 deletions drivers/net/wireless/ath/ath9k/Kconfig
Original file line number Diff line number Diff line change
@@ -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
54 changes: 54 additions & 0 deletions drivers/net/wireless/ath/ath9k/ar9003_mci.c
Original file line number Diff line number Diff line change
@@ -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) {
25 changes: 23 additions & 2 deletions drivers/net/wireless/ath/ath9k/btcoex.c
Original file line number Diff line number Diff line change
@@ -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;
9 changes: 9 additions & 0 deletions drivers/net/wireless/ath/ath9k/gpio.c
Original file line number Diff line number Diff line change
@@ -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)
9 changes: 9 additions & 0 deletions drivers/net/wireless/ath/ath9k/htc_drv_gpio.c
Original file line number Diff line number Diff line change
@@ -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);
}
5 changes: 3 additions & 2 deletions drivers/net/wireless/ath/ath9k/htc_drv_init.c
Original file line number Diff line number Diff line change
@@ -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;
5 changes: 3 additions & 2 deletions drivers/net/wireless/ath/ath9k/htc_drv_main.c
Original file line number Diff line number Diff line change
@@ -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);
3 changes: 2 additions & 1 deletion drivers/net/wireless/ath/ath9k/hw.c
Original file line number Diff line number Diff line change
@@ -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) {
Loading

0 comments on commit 8a30930

Please sign in to comment.