Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2008-2011 Atheros Communications Inc.
0003  *
0004  * Permission to use, copy, modify, and/or distribute this software for any
0005  * purpose with or without fee is hereby granted, provided that the above
0006  * copyright notice and this permission notice appear in all copies.
0007  *
0008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
0009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
0010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
0011  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
0012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
0013  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
0014  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0015  */
0016 
0017 #include "ath9k.h"
0018 
0019 /********************************/
0020 /*   LED functions      */
0021 /********************************/
0022 
0023 #ifdef CONFIG_MAC80211_LEDS
0024 
0025 static void ath_fill_led_pin(struct ath_softc *sc)
0026 {
0027     struct ath_hw *ah = sc->sc_ah;
0028 
0029     /* Set default led pin if invalid */
0030     if (ah->led_pin < 0) {
0031         if (AR_SREV_9287(ah))
0032             ah->led_pin = ATH_LED_PIN_9287;
0033         else if (AR_SREV_9485(ah))
0034             ah->led_pin = ATH_LED_PIN_9485;
0035         else if (AR_SREV_9300(ah))
0036             ah->led_pin = ATH_LED_PIN_9300;
0037         else if (AR_SREV_9462(ah) || AR_SREV_9565(ah))
0038             ah->led_pin = ATH_LED_PIN_9462;
0039         else
0040             ah->led_pin = ATH_LED_PIN_DEF;
0041     }
0042 
0043     /* Configure gpio for output */
0044     ath9k_hw_gpio_request_out(ah, ah->led_pin, "ath9k-led",
0045                   AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
0046 
0047     /* LED off, active low */
0048     ath9k_hw_set_gpio(ah, ah->led_pin, ah->config.led_active_high ? 0 : 1);
0049 }
0050 
0051 static void ath_led_brightness(struct led_classdev *led_cdev,
0052                    enum led_brightness brightness)
0053 {
0054     struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev);
0055     u32 val = (brightness == LED_OFF);
0056 
0057     if (sc->sc_ah->config.led_active_high)
0058         val = !val;
0059 
0060     ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val);
0061 }
0062 
0063 void ath_deinit_leds(struct ath_softc *sc)
0064 {
0065     if (!sc->led_registered)
0066         return;
0067 
0068     ath_led_brightness(&sc->led_cdev, LED_OFF);
0069     led_classdev_unregister(&sc->led_cdev);
0070 
0071     ath9k_hw_gpio_free(sc->sc_ah, sc->sc_ah->led_pin);
0072 }
0073 
0074 void ath_init_leds(struct ath_softc *sc)
0075 {
0076     int ret;
0077 
0078     if (AR_SREV_9100(sc->sc_ah))
0079         return;
0080 
0081     ath_fill_led_pin(sc);
0082 
0083     if (!ath9k_led_blink)
0084         sc->led_cdev.default_trigger =
0085             ieee80211_get_radio_led_name(sc->hw);
0086 
0087     snprintf(sc->led_name, sizeof(sc->led_name),
0088         "ath9k-%s", wiphy_name(sc->hw->wiphy));
0089     sc->led_cdev.name = sc->led_name;
0090     sc->led_cdev.brightness_set = ath_led_brightness;
0091 
0092     ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev);
0093     if (ret < 0)
0094         return;
0095 
0096     sc->led_registered = true;
0097 }
0098 #endif
0099 
0100 /*******************/
0101 /*  Rfkill     */
0102 /*******************/
0103 
0104 static bool ath_is_rfkill_set(struct ath_softc *sc)
0105 {
0106     struct ath_hw *ah = sc->sc_ah;
0107     bool is_blocked;
0108 
0109     ath9k_ps_wakeup(sc);
0110     is_blocked = ath9k_hw_gpio_get(ah, ah->rfkill_gpio) ==
0111                   ah->rfkill_polarity;
0112     ath9k_ps_restore(sc);
0113 
0114     return is_blocked;
0115 }
0116 
0117 void ath9k_rfkill_poll_state(struct ieee80211_hw *hw)
0118 {
0119     struct ath_softc *sc = hw->priv;
0120     bool blocked = !!ath_is_rfkill_set(sc);
0121 
0122     wiphy_rfkill_set_hw_state(hw->wiphy, blocked);
0123 }
0124 
0125 void ath_start_rfkill_poll(struct ath_softc *sc)
0126 {
0127     struct ath_hw *ah = sc->sc_ah;
0128 
0129     if (ah->caps.hw_caps & ATH9K_HW_CAP_RFSILENT)
0130         wiphy_rfkill_start_polling(sc->hw->wiphy);
0131 }
0132 
0133 #ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
0134 
0135 /******************/
0136 /*     BTCOEX     */
0137 /******************/
0138 
0139 /*
0140  * Detects if there is any priority bt traffic
0141  */
0142 static void ath_detect_bt_priority(struct ath_softc *sc)
0143 {
0144     struct ath_btcoex *btcoex = &sc->btcoex;
0145     struct ath_hw *ah = sc->sc_ah;
0146 
0147     if (ath9k_hw_gpio_get(sc->sc_ah, ah->btcoex_hw.btpriority_gpio))
0148         btcoex->bt_priority_cnt++;
0149 
0150     if (time_after(jiffies, btcoex->bt_priority_time +
0151             msecs_to_jiffies(ATH_BT_PRIORITY_TIME_THRESHOLD))) {
0152         clear_bit(BT_OP_PRIORITY_DETECTED, &btcoex->op_flags);
0153         clear_bit(BT_OP_SCAN, &btcoex->op_flags);
0154         /* Detect if colocated bt started scanning */
0155         if (btcoex->bt_priority_cnt >= ATH_BT_CNT_SCAN_THRESHOLD) {
0156             ath_dbg(ath9k_hw_common(sc->sc_ah), BTCOEX,
0157                 "BT scan detected\n");
0158             set_bit(BT_OP_PRIORITY_DETECTED, &btcoex->op_flags);
0159             set_bit(BT_OP_SCAN, &btcoex->op_flags);
0160         } else if (btcoex->bt_priority_cnt >= ATH_BT_CNT_THRESHOLD) {
0161             ath_dbg(ath9k_hw_common(sc->sc_ah), BTCOEX,
0162                 "BT priority traffic detected\n");
0163             set_bit(BT_OP_PRIORITY_DETECTED, &btcoex->op_flags);
0164         }
0165 
0166         btcoex->bt_priority_cnt = 0;
0167         btcoex->bt_priority_time = jiffies;
0168     }
0169 }
0170 
0171 static void ath_mci_ftp_adjust(struct ath_softc *sc)
0172 {
0173     struct ath_btcoex *btcoex = &sc->btcoex;
0174     struct ath_mci_profile *mci = &btcoex->mci;
0175     struct ath_hw *ah = sc->sc_ah;
0176 
0177     if (btcoex->bt_wait_time > ATH_BTCOEX_RX_WAIT_TIME) {
0178         if (ar9003_mci_state(ah, MCI_STATE_NEED_FTP_STOMP) &&
0179             (mci->num_pan || mci->num_other_acl))
0180             ah->btcoex_hw.mci.stomp_ftp =
0181                 (sc->rx.num_pkts < ATH_BTCOEX_STOMP_FTP_THRESH);
0182         else
0183             ah->btcoex_hw.mci.stomp_ftp = false;
0184         btcoex->bt_wait_time = 0;
0185         sc->rx.num_pkts = 0;
0186     }
0187 }
0188 
0189 /*
0190  * This is the master bt coex timer which runs for every
0191  * 45ms, bt traffic will be given priority during 55% of this
0192  * period while wlan gets remaining 45%
0193  */
0194 static void ath_btcoex_period_timer(struct timer_list *t)
0195 {
0196     struct ath_softc *sc = from_timer(sc, t, btcoex.period_timer);
0197     struct ath_hw *ah = sc->sc_ah;
0198     struct ath_btcoex *btcoex = &sc->btcoex;
0199     enum ath_stomp_type stomp_type;
0200     u32 timer_period;
0201     unsigned long flags;
0202 
0203     spin_lock_irqsave(&sc->sc_pm_lock, flags);
0204     if (sc->sc_ah->power_mode == ATH9K_PM_NETWORK_SLEEP) {
0205         btcoex->bt_wait_time += btcoex->btcoex_period;
0206         spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
0207         goto skip_hw_wakeup;
0208     }
0209     spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
0210 
0211     ath9k_ps_wakeup(sc);
0212     spin_lock_bh(&btcoex->btcoex_lock);
0213 
0214     if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI) {
0215         ath9k_mci_update_rssi(sc);
0216         ath_mci_ftp_adjust(sc);
0217     }
0218 
0219     if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
0220         ath_detect_bt_priority(sc);
0221 
0222     stomp_type = btcoex->bt_stomp_type;
0223     timer_period = btcoex->btcoex_no_stomp;
0224 
0225     if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI)) {
0226         if (test_bit(BT_OP_SCAN, &btcoex->op_flags)) {
0227             stomp_type = ATH_BTCOEX_STOMP_ALL;
0228             timer_period = btcoex->btscan_no_stomp;
0229         }
0230     } else if (btcoex->stomp_audio >= 5) {
0231         stomp_type = ATH_BTCOEX_STOMP_AUDIO;
0232         btcoex->stomp_audio = 0;
0233     }
0234 
0235     ath9k_hw_btcoex_bt_stomp(ah, stomp_type);
0236     ath9k_hw_btcoex_enable(ah);
0237 
0238     spin_unlock_bh(&btcoex->btcoex_lock);
0239 
0240     if (btcoex->btcoex_period != btcoex->btcoex_no_stomp)
0241         mod_timer(&btcoex->no_stomp_timer,
0242              jiffies + msecs_to_jiffies(timer_period));
0243 
0244     ath9k_ps_restore(sc);
0245 
0246 skip_hw_wakeup:
0247     mod_timer(&btcoex->period_timer,
0248           jiffies + msecs_to_jiffies(btcoex->btcoex_period));
0249 }
0250 
0251 /*
0252  * Generic tsf based hw timer which configures weight
0253  * registers to time slice between wlan and bt traffic
0254  */
0255 static void ath_btcoex_no_stomp_timer(struct timer_list *t)
0256 {
0257     struct ath_softc *sc = from_timer(sc, t, btcoex.no_stomp_timer);
0258     struct ath_hw *ah = sc->sc_ah;
0259     struct ath_btcoex *btcoex = &sc->btcoex;
0260 
0261     ath9k_ps_wakeup(sc);
0262     spin_lock_bh(&btcoex->btcoex_lock);
0263 
0264     if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_LOW ||
0265         (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI) &&
0266          test_bit(BT_OP_SCAN, &btcoex->op_flags)))
0267         ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_NONE);
0268     else if (btcoex->bt_stomp_type == ATH_BTCOEX_STOMP_ALL)
0269         ath9k_hw_btcoex_bt_stomp(ah, ATH_BTCOEX_STOMP_LOW);
0270 
0271     ath9k_hw_btcoex_enable(ah);
0272     spin_unlock_bh(&btcoex->btcoex_lock);
0273     ath9k_ps_restore(sc);
0274 }
0275 
0276 static void ath_init_btcoex_timer(struct ath_softc *sc)
0277 {
0278     struct ath_btcoex *btcoex = &sc->btcoex;
0279 
0280     btcoex->btcoex_period = ATH_BTCOEX_DEF_BT_PERIOD;
0281     btcoex->btcoex_no_stomp = (100 - ATH_BTCOEX_DEF_DUTY_CYCLE) *
0282         btcoex->btcoex_period / 100;
0283     btcoex->btscan_no_stomp = (100 - ATH_BTCOEX_BTSCAN_DUTY_CYCLE) *
0284                    btcoex->btcoex_period / 100;
0285     btcoex->bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
0286 
0287     timer_setup(&btcoex->period_timer, ath_btcoex_period_timer, 0);
0288     timer_setup(&btcoex->no_stomp_timer, ath_btcoex_no_stomp_timer, 0);
0289 
0290     spin_lock_init(&btcoex->btcoex_lock);
0291 }
0292 
0293 /*
0294  * (Re)start btcoex timers
0295  */
0296 void ath9k_btcoex_timer_resume(struct ath_softc *sc)
0297 {
0298     struct ath_btcoex *btcoex = &sc->btcoex;
0299     struct ath_hw *ah = sc->sc_ah;
0300 
0301     if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_3WIRE &&
0302         ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_MCI)
0303         return;
0304 
0305     ath_dbg(ath9k_hw_common(ah), BTCOEX, "Starting btcoex timers\n");
0306 
0307     /* make sure duty cycle timer is also stopped when resuming */
0308     del_timer_sync(&btcoex->no_stomp_timer);
0309 
0310     btcoex->bt_priority_cnt = 0;
0311     btcoex->bt_priority_time = jiffies;
0312     clear_bit(BT_OP_PRIORITY_DETECTED, &btcoex->op_flags);
0313     clear_bit(BT_OP_SCAN, &btcoex->op_flags);
0314 
0315     mod_timer(&btcoex->period_timer, jiffies);
0316 }
0317 
0318 /*
0319  * Pause btcoex timer and bt duty cycle timer
0320  */
0321 void ath9k_btcoex_timer_pause(struct ath_softc *sc)
0322 {
0323     struct ath_btcoex *btcoex = &sc->btcoex;
0324     struct ath_hw *ah = sc->sc_ah;
0325 
0326     if (ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_3WIRE &&
0327         ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_MCI)
0328         return;
0329 
0330     ath_dbg(ath9k_hw_common(ah), BTCOEX, "Stopping btcoex timers\n");
0331 
0332     del_timer_sync(&btcoex->period_timer);
0333     del_timer_sync(&btcoex->no_stomp_timer);
0334 }
0335 
0336 void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
0337 {
0338     struct ath_btcoex *btcoex = &sc->btcoex;
0339 
0340     del_timer_sync(&btcoex->no_stomp_timer);
0341 }
0342 
0343 u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen)
0344 {
0345     struct ath_btcoex *btcoex = &sc->btcoex;
0346     struct ath_mci_profile *mci = &sc->btcoex.mci;
0347     u16 aggr_limit = 0;
0348 
0349     if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI) && mci->aggr_limit)
0350         aggr_limit = (max_4ms_framelen * mci->aggr_limit) >> 4;
0351     else if (test_bit(BT_OP_PRIORITY_DETECTED, &btcoex->op_flags))
0352         aggr_limit = min((max_4ms_framelen * 3) / 8,
0353                  (u32)ATH_AMPDU_LIMIT_MAX);
0354 
0355     return aggr_limit;
0356 }
0357 
0358 void ath9k_btcoex_handle_interrupt(struct ath_softc *sc, u32 status)
0359 {
0360     if (status & ATH9K_INT_MCI)
0361         ath_mci_intr(sc);
0362 }
0363 
0364 void ath9k_start_btcoex(struct ath_softc *sc)
0365 {
0366     struct ath_hw *ah = sc->sc_ah;
0367 
0368     if (ah->btcoex_hw.enabled ||
0369         ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
0370         return;
0371 
0372     if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
0373         ath9k_hw_btcoex_set_weight(ah, AR_BT_COEX_WGHT,
0374                        AR_STOMP_LOW_WLAN_WGHT, 0);
0375     else
0376         ath9k_hw_btcoex_set_weight(ah, 0, 0,
0377                        ATH_BTCOEX_STOMP_NONE);
0378     ath9k_hw_btcoex_enable(ah);
0379     ath9k_btcoex_timer_resume(sc);
0380 }
0381 
0382 void ath9k_stop_btcoex(struct ath_softc *sc)
0383 {
0384     struct ath_hw *ah = sc->sc_ah;
0385 
0386     if (!ah->btcoex_hw.enabled ||
0387         ath9k_hw_get_btcoex_scheme(ah) == ATH_BTCOEX_CFG_NONE)
0388         return;
0389 
0390     ath9k_btcoex_timer_pause(sc);
0391     ath9k_hw_btcoex_disable(ah);
0392 
0393     if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI)
0394         ath_mci_flush_profile(&sc->btcoex.mci);
0395 }
0396 
0397 void ath9k_deinit_btcoex(struct ath_softc *sc)
0398 {
0399     struct ath_hw *ah = sc->sc_ah;
0400 
0401     if (ath9k_hw_mci_is_enabled(ah))
0402         ath_mci_cleanup(sc);
0403     else {
0404         enum ath_btcoex_scheme scheme = ath9k_hw_get_btcoex_scheme(ah);
0405 
0406         if (scheme == ATH_BTCOEX_CFG_2WIRE ||
0407             scheme == ATH_BTCOEX_CFG_3WIRE)
0408             ath9k_hw_btcoex_deinit(sc->sc_ah);
0409     }
0410 }
0411 
0412 int ath9k_init_btcoex(struct ath_softc *sc)
0413 {
0414     struct ath_txq *txq;
0415     struct ath_hw *ah = sc->sc_ah;
0416     int r;
0417 
0418     ath9k_hw_btcoex_init_scheme(ah);
0419 
0420     switch (ath9k_hw_get_btcoex_scheme(sc->sc_ah)) {
0421     case ATH_BTCOEX_CFG_NONE:
0422         break;
0423     case ATH_BTCOEX_CFG_2WIRE:
0424         ath9k_hw_btcoex_init_2wire(sc->sc_ah);
0425         break;
0426     case ATH_BTCOEX_CFG_3WIRE:
0427         ath9k_hw_btcoex_init_3wire(sc->sc_ah);
0428         ath_init_btcoex_timer(sc);
0429         txq = sc->tx.txq_map[IEEE80211_AC_BE];
0430         ath9k_hw_init_btcoex_hw(sc->sc_ah, txq->axq_qnum);
0431         break;
0432     case ATH_BTCOEX_CFG_MCI:
0433         ath_init_btcoex_timer(sc);
0434 
0435         sc->btcoex.duty_cycle = ATH_BTCOEX_DEF_DUTY_CYCLE;
0436         INIT_LIST_HEAD(&sc->btcoex.mci.info);
0437         ath9k_hw_btcoex_init_mci(ah);
0438 
0439         r = ath_mci_setup(sc);
0440         if (r)
0441             return r;
0442 
0443         break;
0444     default:
0445         WARN_ON(1);
0446         break;
0447     }
0448 
0449     return 0;
0450 }
0451 
0452 static int ath9k_dump_mci_btcoex(struct ath_softc *sc, u8 *buf, u32 size)
0453 {
0454     struct ath_btcoex *btcoex = &sc->btcoex;
0455     struct ath_mci_profile *mci = &btcoex->mci;
0456     struct ath_hw *ah = sc->sc_ah;
0457     struct ath_btcoex_hw *btcoex_hw = &ah->btcoex_hw;
0458     u32 len = 0;
0459     int i;
0460 
0461     ATH_DUMP_BTCOEX("Total BT profiles", NUM_PROF(mci));
0462     ATH_DUMP_BTCOEX("MGMT", mci->num_mgmt);
0463     ATH_DUMP_BTCOEX("SCO", mci->num_sco);
0464     ATH_DUMP_BTCOEX("A2DP", mci->num_a2dp);
0465     ATH_DUMP_BTCOEX("HID", mci->num_hid);
0466     ATH_DUMP_BTCOEX("PAN", mci->num_pan);
0467     ATH_DUMP_BTCOEX("ACL", mci->num_other_acl);
0468     ATH_DUMP_BTCOEX("BDR", mci->num_bdr);
0469     ATH_DUMP_BTCOEX("Aggr. Limit", mci->aggr_limit);
0470     ATH_DUMP_BTCOEX("Stomp Type", btcoex->bt_stomp_type);
0471     ATH_DUMP_BTCOEX("BTCoex Period (msec)", btcoex->btcoex_period);
0472     ATH_DUMP_BTCOEX("Duty Cycle", btcoex->duty_cycle);
0473     ATH_DUMP_BTCOEX("BT Wait time", btcoex->bt_wait_time);
0474     ATH_DUMP_BTCOEX("Concurrent Tx", btcoex_hw->mci.concur_tx);
0475     ATH_DUMP_BTCOEX("Concurrent RSSI cnt", btcoex->rssi_count);
0476 
0477     len += scnprintf(buf + len, size - len, "BT Weights: ");
0478     for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
0479         len += scnprintf(buf + len, size - len, "%08x ",
0480                  btcoex_hw->bt_weight[i]);
0481     len += scnprintf(buf + len, size - len, "\n");
0482     len += scnprintf(buf + len, size - len, "WLAN Weights: ");
0483     for (i = 0; i < AR9300_NUM_BT_WEIGHTS; i++)
0484         len += scnprintf(buf + len, size - len, "%08x ",
0485                  btcoex_hw->wlan_weight[i]);
0486     len += scnprintf(buf + len, size - len, "\n");
0487     len += scnprintf(buf + len, size - len, "Tx Priorities: ");
0488     for (i = 0; i < ATH_BTCOEX_STOMP_MAX; i++)
0489         len += scnprintf(buf + len, size - len, "%08x ",
0490                 btcoex_hw->tx_prio[i]);
0491 
0492     len += scnprintf(buf + len, size - len, "\n");
0493 
0494     return len;
0495 }
0496 
0497 static int ath9k_dump_legacy_btcoex(struct ath_softc *sc, u8 *buf, u32 size)
0498 {
0499 
0500     struct ath_btcoex *btcoex = &sc->btcoex;
0501     u32 len = 0;
0502 
0503     ATH_DUMP_BTCOEX("Stomp Type", btcoex->bt_stomp_type);
0504     ATH_DUMP_BTCOEX("BTCoex Period (msec)", btcoex->btcoex_period);
0505     ATH_DUMP_BTCOEX("Duty Cycle", btcoex->duty_cycle);
0506     ATH_DUMP_BTCOEX("BT Wait time", btcoex->bt_wait_time);
0507 
0508     return len;
0509 }
0510 
0511 int ath9k_dump_btcoex(struct ath_softc *sc, u8 *buf, u32 size)
0512 {
0513     if (ath9k_hw_mci_is_enabled(sc->sc_ah))
0514         return ath9k_dump_mci_btcoex(sc, buf, size);
0515     else
0516         return ath9k_dump_legacy_btcoex(sc, buf, size);
0517 }
0518 
0519 #endif /* CONFIG_ATH9K_BTCOEX_SUPPORT */