예제 #1
0
/*
 * This is the master bt coex timer which runs for every
 * 45ms, bt traffic will be given priority during 55% of this
 * period while wlan gets remaining 45%
 */
static void ath_btcoex_period_timer(unsigned long data)
{
    struct ath_softc *sc = (struct ath_softc *) data;
    struct ath_hw *ah = sc->sc_ah;
    struct ath_btcoex *btcoex = &sc->btcoex;
    enum ath_stomp_type stomp_type;
    u32 timer_period;
    unsigned long flags;

    spin_lock_irqsave(&sc->sc_pm_lock, flags);
    if (sc->sc_ah->power_mode == ATH9K_PM_NETWORK_SLEEP) {
        btcoex->bt_wait_time += btcoex->btcoex_period;
        spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
        goto skip_hw_wakeup;
    }
    spin_unlock_irqrestore(&sc->sc_pm_lock, flags);

    ath9k_mci_update_rssi(sc);

    ath9k_ps_wakeup(sc);

    if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
        ath_detect_bt_priority(sc);

    if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI)
        ath_mci_ftp_adjust(sc);

    spin_lock_bh(&btcoex->btcoex_lock);

    stomp_type = btcoex->bt_stomp_type;
    timer_period = btcoex->btcoex_no_stomp;

    if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI)) {
        if (test_bit(BT_OP_SCAN, &btcoex->op_flags)) {
            stomp_type = ATH_BTCOEX_STOMP_ALL;
            timer_period = btcoex->btscan_no_stomp;
        }
    } else if (btcoex->stomp_audio >= 5) {
        stomp_type = ATH_BTCOEX_STOMP_AUDIO;
        btcoex->stomp_audio = 0;
    }

    ath9k_hw_btcoex_bt_stomp(ah, stomp_type);
    ath9k_hw_btcoex_enable(ah);

    spin_unlock_bh(&btcoex->btcoex_lock);

    if (btcoex->btcoex_period != btcoex->btcoex_no_stomp)
        mod_timer(&btcoex->no_stomp_timer,
                  jiffies + msecs_to_jiffies(timer_period));

    ath9k_ps_restore(sc);

skip_hw_wakeup:
    mod_timer(&btcoex->period_timer,
              jiffies + msecs_to_jiffies(btcoex->btcoex_period));
}
예제 #2
0
파일: gpio.c 프로젝트: 03199618/linux
/*
 * This is the master bt coex timer which runs for every
 * 45ms, bt traffic will be given priority during 55% of this
 * period while wlan gets remaining 45%
 */
static void ath_btcoex_period_timer(unsigned long data)
{
	struct ath_softc *sc = (struct ath_softc *) data;
	struct ath_hw *ah = sc->sc_ah;
	struct ath_btcoex *btcoex = &sc->btcoex;
	enum ath_stomp_type stomp_type;
	u32 timer_period;
	unsigned long flags;

	spin_lock_irqsave(&sc->sc_pm_lock, flags);
	if (sc->sc_ah->power_mode == ATH9K_PM_NETWORK_SLEEP) {
		btcoex->bt_wait_time += btcoex->btcoex_period;
		spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
		goto skip_hw_wakeup;
	}
	spin_unlock_irqrestore(&sc->sc_pm_lock, flags);

	ath9k_mci_update_rssi(sc);

	ath9k_ps_wakeup(sc);

	if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI))
		ath_detect_bt_priority(sc);

	if (ah->caps.hw_caps & ATH9K_HW_CAP_MCI)
		ath_mci_ftp_adjust(sc);

	spin_lock_bh(&btcoex->btcoex_lock);

	stomp_type = btcoex->bt_stomp_type;
	timer_period = btcoex->btcoex_no_stomp;

	if (!(ah->caps.hw_caps & ATH9K_HW_CAP_MCI)) {
		if (test_bit(BT_OP_SCAN, &btcoex->op_flags)) {
			stomp_type = ATH_BTCOEX_STOMP_ALL;
			timer_period = btcoex->btscan_no_stomp;
		}
	} else if (btcoex->stomp_audio >= 5) {
		stomp_type = ATH_BTCOEX_STOMP_AUDIO;
		btcoex->stomp_audio = 0;
	}

	ath9k_hw_btcoex_bt_stomp(ah, stomp_type);
	ath9k_hw_btcoex_enable(ah);

	spin_unlock_bh(&btcoex->btcoex_lock);

	/*
	 * btcoex_period is in msec while (btocex/btscan_)no_stomp are in usec,
	 * ensure that we properly convert btcoex_period to usec
	 * for any comparision with (btcoex/btscan_)no_stomp.
	 */
	if (btcoex->btcoex_period * 1000 != btcoex->btcoex_no_stomp) {
		if (btcoex->hw_timer_enabled)
			ath9k_gen_timer_stop(ah, btcoex->no_stomp_timer);

		ath9k_gen_timer_start(ah, btcoex->no_stomp_timer, timer_period,
				      timer_period * 10);
		btcoex->hw_timer_enabled = true;
	}

	ath9k_ps_restore(sc);

skip_hw_wakeup:
	mod_timer(&btcoex->period_timer,
		  jiffies + msecs_to_jiffies(btcoex->btcoex_period));
}