This is a note to let you know that I've just added the patch titled

    ath9k: skip ->config_pci_powersave() if PCIe port has ASPM disabled

to the 3.0-stable tree which can be found at:
    
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     ath9k-skip-config_pci_powersave-if-pcie-port-has-aspm-disabled.patch
and it can be found in the queue-3.0 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <sta...@kernel.org> know about it.


>From d4930086bdd0c08a8b3a4d66a9c702297cb74a99 Mon Sep 17 00:00:00 2001
From: Stanislaw Gruszka <sgrus...@redhat.com>
Date: Fri, 29 Jul 2011 15:59:08 +0200
Subject: ath9k: skip ->config_pci_powersave() if PCIe port has ASPM disabled

From: Stanislaw Gruszka <sgrus...@redhat.com>

commit d4930086bdd0c08a8b3a4d66a9c702297cb74a99 upstream.

We receive many bug reports about system hang during suspend/resume
when ath9k driver is in use. Adrian Chadd remarked that this problem
happens on systems that have ASPM disabled.

To do not hit the bug, skip doing ->config_pci_powersave magic if PCIe
downstream port device, which ath9k device is connected to, has ASPM
disabled.

Bug was introduced by:

commit 53bc7aa08b48e5cd745f986731cc7dc24eef2a9f
Author: Vivek Natarajan <vnatara...@atheros.com>
Date:   Mon Apr 5 14:48:04 2010 +0530

    ath9k: Add support for newer AR9285 chipsets.

Patch should address:
https://bugzilla.kernel.org/show_bug.cgi?id=37462
https://bugzilla.kernel.org/show_bug.cgi?id=37082
https://bugzilla.redhat.com/show_bug.cgi?id=697157

however I did not receive confirmation about that, except from Camilo
Mesias, whose system stops hang regularly with this patch (but still
hangs from time to time, but this is probably some other bug).

Tested-by: Camilo Mesias <cam...@mesias.co.uk>
Signed-off-by: Stanislaw Gruszka <sgrus...@redhat.com>
Signed-off-by: John W. Linville <linvi...@tuxdriver.com>
Signed-off-by: Greg Kroah-Hartman <gre...@suse.de>

---
 drivers/net/wireless/ath/ath9k/ar9002_hw.c |    6 +-----
 drivers/net/wireless/ath/ath9k/ar9003_hw.c |    6 +-----
 drivers/net/wireless/ath/ath9k/hw.c        |   11 +++++++++--
 drivers/net/wireless/ath/ath9k/hw.h        |    3 ++-
 drivers/net/wireless/ath/ath9k/pci.c       |   27 +++++++++++++++++++++++++++
 5 files changed, 40 insertions(+), 13 deletions(-)

--- a/drivers/net/wireless/ath/ath9k/ar9002_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_hw.c
@@ -309,11 +309,7 @@ static void ar9002_hw_configpcipowersave
        u8 i;
        u32 val;
 
-       if (ah->is_pciexpress != true)
-               return;
-
-       /* Do not touch SerDes registers */
-       if (ah->config.pcie_powersave_enable == 2)
+       if (ah->is_pciexpress != true || ah->aspm_enabled != true)
                return;
 
        /* Nothing to do on restore for 11N */
--- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c
@@ -351,11 +351,7 @@ static void ar9003_hw_configpcipowersave
                                         int restore,
                                         int power_off)
 {
-       if (ah->is_pciexpress != true)
-               return;
-
-       /* Do not touch SerDes registers */
-       if (ah->config.pcie_powersave_enable == 2)
+       if (ah->is_pciexpress != true || ah->aspm_enabled != true)
                return;
 
        /* Nothing to do on restore for 11N */
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -299,6 +299,14 @@ static void ath9k_hw_disablepcie(struct
        REG_WRITE(ah, AR_PCIE_SERDES2, 0x00000000);
 }
 
+static void ath9k_hw_aspm_init(struct ath_hw *ah)
+{
+       struct ath_common *common = ath9k_hw_common(ah);
+
+       if (common->bus_ops->aspm_init)
+               common->bus_ops->aspm_init(common);
+}
+
 /* This should work for all families including legacy */
 static bool ath9k_hw_chip_test(struct ath_hw *ah)
 {
@@ -359,7 +367,6 @@ static void ath9k_hw_init_config(struct
        ah->config.additional_swba_backoff = 0;
        ah->config.ack_6mb = 0x0;
        ah->config.cwm_ignore_extcca = 0;
-       ah->config.pcie_powersave_enable = 0;
        ah->config.pcie_clock_req = 0;
        ah->config.pcie_waen = 0;
        ah->config.analog_shiftreg = 1;
@@ -577,7 +584,7 @@ static int __ath9k_hw_init(struct ath_hw
 
 
        if (ah->is_pciexpress)
-               ath9k_hw_configpcipowersave(ah, 0, 0);
+               ath9k_hw_aspm_init(ah);
        else
                ath9k_hw_disablepcie(ah);
 
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -215,7 +215,6 @@ struct ath9k_ops_config {
        int additional_swba_backoff;
        int ack_6mb;
        u32 cwm_ignore_extcca;
-       u8 pcie_powersave_enable;
        bool pcieSerDesWrite;
        u8 pcie_clock_req;
        u32 pcie_waen;
@@ -671,6 +670,7 @@ struct ath_hw {
 
        bool sw_mgmt_crypto;
        bool is_pciexpress;
+       bool aspm_enabled;
        bool is_monitoring;
        bool need_an_top2_fixup;
        u16 tx_trig_level;
@@ -870,6 +870,7 @@ struct ath_bus_ops {
        bool (*eeprom_read)(struct ath_common *common, u32 off, u16 *data);
        void (*bt_coex_prep)(struct ath_common *common);
        void (*extn_synch_en)(struct ath_common *common);
+       void (*aspm_init)(struct ath_common *common);
 };
 
 static inline struct ath_common *ath9k_hw_common(struct ath_hw *ah)
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -16,6 +16,7 @@
 
 #include <linux/nl80211.h>
 #include <linux/pci.h>
+#include <linux/pci-aspm.h>
 #include <linux/ath9k_platform.h>
 #include "ath9k.h"
 
@@ -115,12 +116,38 @@ static void ath_pci_extn_synch_enable(st
        pci_write_config_byte(pdev, sc->sc_ah->caps.pcie_lcr_offset, lnkctl);
 }
 
+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 (!pci_is_pcie(pdev))
+               return;
+
+       parent = pdev->bus->self;
+       if (WARN_ON(!parent))
+               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, 0, 0);
+       }
+}
+
 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,
 };
 
 static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)


Patches currently in stable-queue which might be from sgrus...@redhat.com are

queue-3.0/ath9k-skip-config_pci_powersave-if-pcie-port-has-aspm-disabled.patch
queue-3.0/rt2x00-rt2800-fix-zeroing-skb-structure.patch
queue-3.0/rt2x00-fix-usage-of-null-queue.patch
queue-3.0/iwlegacy-set-tx-power-after-rxon_assoc.patch

_______________________________________________
stable mailing list
stable@linux.kernel.org
http://linux.kernel.org/mailman/listinfo/stable

Reply via email to