Пример #1
0
static void ath9k_deinit_softc(struct ath_softc *sc)
{
	int i = 0;

	if (sc->sbands[IEEE80211_BAND_2GHZ].channels)
		kfree(sc->sbands[IEEE80211_BAND_2GHZ].channels);

	if (sc->sbands[IEEE80211_BAND_5GHZ].channels)
		kfree(sc->sbands[IEEE80211_BAND_5GHZ].channels);

        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);

	for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
		if (ATH_TXQ_SETUP(sc, i))
			ath_tx_cleanupq(sc, &sc->tx.txq[i]);

	ath9k_hw_deinit(sc->sc_ah);

	kfree(sc->sc_ah);
	sc->sc_ah = NULL;
}
Пример #2
0
/*
 * Pause btcoex timer and bt duty cycle timer
 */
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_3WIRE &&
	    ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_MCI)
		return;

	ath_dbg(ath9k_hw_common(ah), BTCOEX, "Stopping btcoex timers\n");

	del_timer_sync(&btcoex->period_timer);
	del_timer_sync(&btcoex->no_stomp_timer);
}
Пример #3
0
static int ath9k_init_btcoex(struct ath_softc *sc)
{
	struct ath_txq *txq;
	struct ath_hw *ah = sc->sc_ah;
	int r;

	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;

		if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_MCI) {
			ah->btcoex_hw.mci.ready = false;
			ah->btcoex_hw.mci.bt_state = 0;
			ah->btcoex_hw.mci.bt_ver_major = 3;
			ah->btcoex_hw.mci.bt_ver_minor = 0;
			ah->btcoex_hw.mci.bt_version_known = false;
			ah->btcoex_hw.mci.update_2g5g = true;
			ah->btcoex_hw.mci.is_2g = true;
			ah->btcoex_hw.mci.wlan_channels_update = false;
			ah->btcoex_hw.mci.wlan_channels[0] = 0x00000000;
			ah->btcoex_hw.mci.wlan_channels[1] = 0xffffffff;
			ah->btcoex_hw.mci.wlan_channels[2] = 0xffffffff;
			ah->btcoex_hw.mci.wlan_channels[3] = 0x7fffffff;
			ah->btcoex_hw.mci.query_bt = true;
			ah->btcoex_hw.mci.unhalt_bt_gpm = true;
			ah->btcoex_hw.mci.halted_bt_gpm = false;
			ah->btcoex_hw.mci.need_flush_btinfo = false;
			ah->btcoex_hw.mci.wlan_cal_seq = 0;
			ah->btcoex_hw.mci.wlan_cal_done = 0;
			ah->btcoex_hw.mci.config = 0x2201;
		}
		break;
	default:
		WARN_ON(1);
		break;
	}

	return 0;
}
Пример #4
0
/* Need to be called after we discover btcoex capabilities */
static void ath_pci_aspm_init(struct ath_common *common)
{
    struct ath_softc *sc = (struct ath_softc *) common->priv;
    struct ath_hw *ah = sc->sc_ah;
    struct pci_dev *pdev = to_pci_dev(sc->dev);
    struct pci_dev *parent;
    u16 aspm;

    if (!ah->is_pciexpress)
        return;

    parent = pdev->bus->self;
    if (!parent)
        return;

    if ((ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) &&
            (AR_SREV_9285(ah))) {
        /* Bluetooth coexistence requires disabling ASPM. */
        pcie_capability_clear_word(pdev, PCI_EXP_LNKCTL,
                                   PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1);

        /*
         * Both upstream and downstream PCIe components should
         * have the same ASPM settings.
         */
        pcie_capability_clear_word(parent, PCI_EXP_LNKCTL,
                                   PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1);

        ath_info(common, "Disabling ASPM since BTCOEX is enabled\n");
        return;
    }

    /*
     * 0x70c - Ack Frequency Register.
     *
     * Bits 27:29 - DEFAULT_L1_ENTRANCE_LATENCY.
     *
     * 000 : 1 us
     * 001 : 2 us
     * 010 : 4 us
     * 011 : 8 us
     * 100 : 16 us
     * 101 : 32 us
     * 110/111 : 64 us
     */
    if (AR_SREV_9462(ah))
        pci_read_config_dword(pdev, 0x70c, &ah->config.aspm_l1_fix);

    pcie_capability_read_word(parent, PCI_EXP_LNKCTL, &aspm);
    if (aspm & (PCI_EXP_LNKCTL_ASPM_L0S | PCI_EXP_LNKCTL_ASPM_L1)) {
        ah->aspm_enabled = true;
        /* Initialize PCIe PM and SERDES registers. */
        ath9k_hw_configpcipowersave(ah, false);
        ath_info(common, "ASPM enabled: 0x%x\n", aspm);
    }
}
Пример #5
0
void ath9k_htc_stop_btcoex(struct ath9k_htc_priv *priv)
{
	struct ath_hw *ah = priv->ah;

	if (ah->btcoex_hw.enabled &&
	    ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) {
		if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
			ath_htc_cancel_btcoex_work(priv);
		ath9k_hw_btcoex_disable(ah);
	}
}
Пример #6
0
void ath9k_htc_start_btcoex(struct ath9k_htc_priv *priv)
{
	struct ath_hw *ah = priv->ah;

	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, 0);
		ath9k_hw_btcoex_enable(ah);
		ath_htc_resume_btcoex_work(priv);
	}
}
Пример #7
0
/*
 * (Re)start btcoex timers
 */
void ath9k_btcoex_timer_resume(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_3WIRE &&
	    ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_MCI)
		return;

	ath_dbg(ath9k_hw_common(ah), BTCOEX, "Starting btcoex timers\n");

	/* make sure duty cycle timer is also stopped when resuming */
	del_timer_sync(&btcoex->no_stomp_timer);

	btcoex->bt_priority_cnt = 0;
	btcoex->bt_priority_time = jiffies;
	clear_bit(BT_OP_PRIORITY_DETECTED, &btcoex->op_flags);
	clear_bit(BT_OP_SCAN, &btcoex->op_flags);

	mod_timer(&btcoex->period_timer, jiffies);
}
Пример #8
0
/* Need to be called after we discover btcoex capabilities */
static void ath_pci_aspm_init(struct ath_common *common)
{
	struct ath_softc *sc = (struct ath_softc *) common->priv;
	struct ath_hw *ah = sc->sc_ah;
	struct pci_dev *pdev = to_pci_dev(sc->dev);
	struct pci_dev *parent;
	int pos;
	u8 aspm;

	if (!ah->is_pciexpress)
		return;

	pos = pci_pcie_cap(pdev);
	if (!pos)
		return;

	parent = pdev->bus->self;
	if (!parent)
		return;

	if ((ath9k_hw_get_btcoex_scheme(ah) != ATH_BTCOEX_CFG_NONE) &&
	    (AR_SREV_9285(ah))) {
		/* Bluetooth coexistance requires disabling ASPM for AR9285. */
		pci_read_config_byte(pdev, pos + PCI_EXP_LNKCTL, &aspm);
		aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
		pci_write_config_byte(pdev, pos + PCI_EXP_LNKCTL, aspm);

		/*
		 * Both upstream and downstream PCIe components should
		 * have the same ASPM settings.
		 */
		pos = pci_pcie_cap(parent);
		pci_read_config_byte(parent, pos + PCI_EXP_LNKCTL, &aspm);
		aspm &= ~(PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1);
		pci_write_config_byte(parent, pos + PCI_EXP_LNKCTL, aspm);

		ath_info(common, "Disabling ASPM since BTCOEX is enabled\n");
		return;
	}

	pos = pci_pcie_cap(parent);
	pci_read_config_byte(parent, pos +  PCI_EXP_LNKCTL, &aspm);
	if (aspm & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) {
		ah->aspm_enabled = true;
		/* Initialize PCIe PM and SERDES registers. */
		ath9k_hw_configpcipowersave(ah, false);
		ath_info(common, "ASPM enabled: 0x%x\n", aspm);
	}
}
Пример #9
0
void ath9k_htc_init_btcoex(struct ath9k_htc_priv *priv, char *product)
{
	struct ath_hw *ah = priv->ah;
	struct ath_common *common = ath9k_hw_common(ah);
	int qnum;

	/*
	 * Check if BTCOEX is globally disabled.
	 */
	if (!common->btcoex_enabled) {
		ah->btcoex_hw.scheme = ATH_BTCOEX_CFG_NONE;
		return;
	}

	if (product && strncmp(product, ATH_HTC_BTCOEX_PRODUCT_ID, 5) == 0) {
		ah->btcoex_hw.scheme = ATH_BTCOEX_CFG_3WIRE;
	}

	switch (ath9k_hw_get_btcoex_scheme(priv->ah)) {
	case ATH_BTCOEX_CFG_NONE:
		break;
	case ATH_BTCOEX_CFG_3WIRE:
		priv->ah->btcoex_hw.btactive_gpio = 7;
		priv->ah->btcoex_hw.btpriority_gpio = 6;
		priv->ah->btcoex_hw.wlanactive_gpio = 8;
		priv->btcoex.bt_stomp_type = ATH_BTCOEX_STOMP_LOW;
		ath9k_hw_btcoex_init_3wire(priv->ah);
		ath_htc_init_btcoex_work(priv);
		qnum = priv->hwq_map[IEEE80211_AC_BE];
		ath9k_hw_init_btcoex_hw(priv->ah, qnum);
		break;
	default:
		WARN_ON(1);
		break;
	}
}