ath9k: do btcoex ASPM disabling at initialization time
authorStanislaw Gruszka <sgruszka@redhat.com>
Fri, 5 Aug 2011 11:10:34 +0000 (13:10 +0200)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 22 Aug 2011 18:45:57 +0000 (14:45 -0400)
Disable ASPM in pci ->probe on upstream (device) and downstream
(PCIe port) component. According to e1000e driver authors this is
required. I did not find that requirement in PCIe spec, but it seems
to be logical for me.

This need to be fixed for CONFIG_PCIEASPM, that will be done later ...

Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/main.c
drivers/net/wireless/ath/ath9k/pci.c

index db44e5b..875faf6 100644 (file)
@@ -603,10 +603,7 @@ static int __ath9k_hw_init(struct ath_hw *ah)
 
        ath9k_hw_init_mode_regs(ah);
 
-
-       if (ah->is_pciexpress)
-               ath9k_hw_aspm_init(ah);
-       else
+       if (!ah->is_pciexpress)
                ath9k_hw_disablepcie(ah);
 
        if (!AR_SREV_9300_20_OR_LATER(ah))
@@ -621,6 +618,9 @@ static int __ath9k_hw_init(struct ath_hw *ah)
        if (r)
                return r;
 
+       if (ah->is_pciexpress)
+               ath9k_hw_aspm_init(ah);
+
        r = ath9k_hw_init_macaddr(ah);
        if (r) {
                ath_err(common, "Failed to initialize MAC address\n");
index 2ea10f3..ee0d944 100644 (file)
@@ -1036,10 +1036,6 @@ void ath9k_ani_reset(struct ath_hw *ah, bool is_scanning);
 void ath9k_hw_proc_mib_event(struct ath_hw *ah);
 void ath9k_hw_ani_monitor(struct ath_hw *ah, struct ath9k_channel *chan);
 
-#define ATH_PCIE_CAP_LINK_CTRL 0x70
-#define ATH_PCIE_CAP_LINK_L0S  1
-#define ATH_PCIE_CAP_LINK_L1   2
-
 #define ATH9K_CLOCK_RATE_CCK           22
 #define ATH9K_CLOCK_RATE_5GHZ_OFDM     40
 #define ATH9K_CLOCK_RATE_2GHZ_OFDM     44
index e408732..781af25 100644 (file)
@@ -1145,8 +1145,6 @@ static int ath9k_start(struct ieee80211_hw *hw)
                                           AR_STOMP_LOW_WLAN_WGHT);
                ath9k_hw_btcoex_enable(ah);
 
-               if (common->bus_ops->bt_coex_prep)
-                       common->bus_ops->bt_coex_prep(common);
                if (ah->btcoex_hw.scheme == ATH_BTCOEX_CFG_3WIRE)
                        ath9k_btcoex_timer_resume(sc);
        }
index 65cf728..daa26b5 100644 (file)
@@ -89,23 +89,6 @@ static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data)
        return true;
 }
 
-/*
- * Bluetooth coexistance requires disabling ASPM.
- */
-static void ath_pci_bt_coex_prep(struct ath_common *common)
-{
-       struct ath_softc *sc = (struct ath_softc *) common->priv;
-       struct pci_dev *pdev = to_pci_dev(sc->dev);
-       u8 aspm;
-
-       if (!pci_is_pcie(pdev))
-               return;
-
-       pci_read_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, &aspm);
-       aspm &= ~(ATH_PCIE_CAP_LINK_L0S | ATH_PCIE_CAP_LINK_L1);
-       pci_write_config_byte(pdev, ATH_PCIE_CAP_LINK_CTRL, aspm);
-}
-
 static void ath_pci_extn_synch_enable(struct ath_common *common)
 {
        struct ath_softc *sc = (struct ath_softc *) common->priv;
@@ -117,6 +100,7 @@ static void ath_pci_extn_synch_enable(struct ath_common *common)
        pci_write_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, lnkctl);
 }
 
+/* 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;
@@ -126,10 +110,33 @@ static void ath_pci_aspm_init(struct ath_common *common)
        int pos;
        u8 aspm;
 
-       if (!pci_is_pcie(pdev))
+       pos = pci_pcie_cap(pdev);
+       if (!pos)
                return;
 
        parent = pdev->bus->self;
+
+       if (ah->btcoex_hw.scheme != 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);
+               pci_write_config_byte(pdev, pos + PCI_EXP_LNKCTL, aspm);
+
+               /*
+                * Both upstream and downstream PCIe components should
+                * have the same ASPM settings.
+                */
+               if (WARN_ON(!parent))
+                       return;
+
+               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);
+
+               return;
+       }
+
        if (WARN_ON(!parent))
                return;
 
@@ -146,7 +153,6 @@ static const struct ath_bus_ops ath_pci_bus_ops = {
        .ath_bus_type = ATH_PCI,
        .read_cachesize = ath_pci_read_cachesize,
        .eeprom_read = ath_pci_eeprom_read,
-       .bt_coex_prep = ath_pci_bt_coex_prep,
        .extn_synch_en = ath_pci_extn_synch_enable,
        .aspm_init = ath_pci_aspm_init,
 };