ath9k: Reset keycache on resume
authorMohammed Shafi Shajakhan <mshajakhan@atheros.com>
Wed, 22 Dec 2010 06:50:12 +0000 (12:20 +0530)
committerJohn W. Linville <linville@tuxdriver.com>
Wed, 22 Dec 2010 20:44:22 +0000 (15:44 -0500)
It looks like some hardware registers are left into undefined state
after suspend/resume. At minimum, this can cause odd issues related to
key cache and hardware trying to encrypt/decrypt frames unexpectedly.
This seems to happen even when there is no keys configured, i.e., hardware
can end up touching TX frames just based of invalid key cache context
even if the driver is not asking a specific entry to be used. In
addition, RX can likely be affected. This patch fixes this issue.

Signed-off-by: Jouni Malinen <Jouni.Malinen@Atheros.com>
Signed-off-by: Mohammed Shafi Shajakhan <mshajakhan@atheros.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/init.c
drivers/net/wireless/ath/ath9k/pci.c

index d9bda275ec21831afa6a8544b730d3bf2ea923a3..fcc087ce3bc3bbb855bb9fa76da84e9e0cad4bdc 100644 (file)
@@ -670,6 +670,7 @@ extern int ath9k_pm_qos_value;
 extern bool is_ath9k_unloaded;
 
 irqreturn_t ath_isr(int irq, void *dev);
+void ath9k_init_crypto(struct ath_softc *sc);
 int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
                    const struct ath_bus_ops *bus_ops);
 void ath9k_deinit_device(struct ath_softc *sc);
index 9efc77d82563413b3ed1874ceb670e266fce1e22..efb778d4356a4b9875b0bcb7fb4fd78323ac0ab3 100644 (file)
@@ -373,7 +373,7 @@ fail:
 #undef DS2PHYS
 }
 
-static void ath9k_init_crypto(struct ath_softc *sc)
+void ath9k_init_crypto(struct ath_softc *sc)
 {
        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
        int i = 0;
index 545aa1c650cf0993b05ac85ca4bb96ffc3940dfc..78ef1f13386fa6b8c38e3674a53fa869b4b8518c 100644 (file)
@@ -311,6 +311,14 @@ static int ath_pci_resume(struct device *device)
                            AR_GPIO_OUTPUT_MUX_AS_OUTPUT);
        ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
 
+         /*
+          * Reset key cache to sane defaults (all entries cleared) instead of
+          * semi-random values after suspend/resume.
+          */
+       ath9k_ps_wakeup(sc);
+       ath9k_init_crypto(sc);
+       ath9k_ps_restore(sc);
+
        sc->ps_idle = true;
        ath9k_set_wiphy_idle(aphy, true);
        ath_radio_disable(sc, hw);