[RFC/RFT v2 11/12] ath9k: be prepare for dynamic ASPM settings change
From: Stanislaw Gruszka <hidden>
Date: 2011-07-27 12:14:03
Subsystem:
atheros ath generic utilities, qualcomm atheros ath9k wireless driver, the rest · Maintainers:
Jeff Johnson, Toke Høiland-Jørgensen, Linus Torvalds
Kernel offer possibility to change ASPM settings using /sys/module/pcie_aspm/parameters/policy interface. As settings can be changed, we also need to change ath9k hw registers. Patch implement this by monitoring power_off state, and based on that state setup register when pci core inform us about ASPM change. Signed-off-by: Stanislaw Gruszka <redacted> --- drivers/net/wireless/ath/ath9k/hw-ops.h | 1 + drivers/net/wireless/ath/ath9k/hw.h | 1 + drivers/net/wireless/ath/ath9k/pci.c | 31 +++++++++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 0 deletions(-)
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h
index dd9003e..0743e82 100644
--- a/drivers/net/wireless/ath/ath9k/hw-ops.h
+++ b/drivers/net/wireless/ath/ath9k/hw-ops.h@@ -24,6 +24,7 @@ static inline void ath9k_hw_configpcipowersave(struct ath_hw *ah, bool power_off) { + ah->power_off = power_off; if (ah->aspm_enabled != true) return;
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 6abf26d..eb736ca 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h@@ -672,6 +672,7 @@ struct ath_hw { bool sw_mgmt_crypto; bool is_pciexpress; bool aspm_enabled; + bool power_off; bool is_monitoring; bool need_an_top2_fixup; u16 tx_trig_level;
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index a92e55f..c46920b 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c@@ -286,6 +286,34 @@ static void ath_pci_remove(struct pci_dev *pdev) pci_release_region(pdev, 0); } +#ifdef CONFIG_PCIEASPM + +static void ath_pci_aspm_changed(struct pci_dev *pdev, u32 state) +{ + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct ath_softc *sc = hw->priv; + struct ath_hw *ah = sc->sc_ah; + + spin_lock_irq(&sc->sc_pcu_lock); + + /* + * ASPM settings were changed, we have to configure PCIe PM and SERDES + * registers based on current state of device and new ASPM settings. + */ + if (state & (PCIE_LINK_STATE_L0S | PCIE_LINK_STATE_L1)) { + ah->aspm_enabled = true; + ath9k_hw_configpcipowersave(ah, ah->power_off); + } else { + if (!ah->power_off) + ath9k_hw_configpcipowersave(ah, true); + ah->aspm_enabled = false; + } + + spin_unlock_irq(&sc->sc_pcu_lock); +} + +#endif + #ifdef CONFIG_PM static int ath_pci_suspend(struct device *device)
@@ -365,6 +393,9 @@ static struct pci_driver ath_pci_driver = { .id_table = ath_pci_id_table, .probe = ath_pci_probe, .remove = ath_pci_remove, +#ifdef CONFIG_PCIEASPM + .aspm_changed = ath_pci_aspm_changed, +#endif .driver.pm = ATH9K_PM_OPS, };
--
1.7.1