]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/net/wireless/ath5k/base.c
Merge git://git.infradead.org/mtd-2.6
[linux-2.6-omap-h63xx.git] / drivers / net / wireless / ath5k / base.c
index 9b95c4049b313492055198077de7d3f6458c2fbc..9e47d727e2206ff28c647f648bb29caf4888057d 100644 (file)
@@ -340,9 +340,9 @@ static inline u64 ath5k_extend_tsf(struct ath5k_hw *ah, u32 rstamp)
 }
 
 /* Interrupt handling */
-static int     ath5k_init(struct ath5k_softc *sc);
+static int     ath5k_init(struct ath5k_softc *sc, bool is_resume);
 static int     ath5k_stop_locked(struct ath5k_softc *sc);
-static int     ath5k_stop_hw(struct ath5k_softc *sc);
+static int     ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend);
 static irqreturn_t ath5k_intr(int irq, void *dev_id);
 static void    ath5k_tasklet_reset(unsigned long data);
 
@@ -646,7 +646,7 @@ ath5k_pci_suspend(struct pci_dev *pdev, pm_message_t state)
 
        ath5k_led_off(sc);
 
-       ath5k_stop_hw(sc);
+       ath5k_stop_hw(sc, true);
 
        free_irq(pdev->irq, sc);
        pci_save_state(pdev);
@@ -661,8 +661,7 @@ ath5k_pci_resume(struct pci_dev *pdev)
 {
        struct ieee80211_hw *hw = pci_get_drvdata(pdev);
        struct ath5k_softc *sc = hw->priv;
-       struct ath5k_hw *ah = sc->ah;
-       int i, err;
+       int err;
 
        pci_restore_state(pdev);
 
@@ -683,21 +682,11 @@ ath5k_pci_resume(struct pci_dev *pdev)
                goto err_no_irq;
        }
 
-       err = ath5k_init(sc);
+       err = ath5k_init(sc, true);
        if (err)
                goto err_irq;
        ath5k_led_enable(sc);
 
-       /*
-        * Reset the key cache since some parts do not
-        * reset the contents on initial power up or resume.
-        *
-        * FIXME: This may need to be revisited when mac80211 becomes
-        *        aware of suspend/resume.
-        */
-       for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
-               ath5k_hw_reset_key(ah, i);
-
        return 0;
 err_irq:
        free_irq(pdev->irq, sc);
@@ -718,7 +707,6 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
        struct ath5k_softc *sc = hw->priv;
        struct ath5k_hw *ah = sc->ah;
        u8 mac[ETH_ALEN];
-       unsigned int i;
        int ret;
 
        ATH5K_DBG(sc, ATH5K_DEBUG_ANY, "devid 0x%x\n", pdev->device);
@@ -736,13 +724,6 @@ ath5k_attach(struct pci_dev *pdev, struct ieee80211_hw *hw)
        if (ret > 0)
                __set_bit(ATH_STAT_MRRETRY, sc->status);
 
-       /*
-        * Reset the key cache since some parts do not
-        * reset the contents on initial power up.
-        */
-       for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
-               ath5k_hw_reset_key(ah, i);
-
        /*
         * Collect the channel list.  The 802.11 layer
         * is resposible for filtering this list based
@@ -2200,12 +2181,18 @@ ath5k_beacon_config(struct ath5k_softc *sc)
 \********************/
 
 static int
-ath5k_init(struct ath5k_softc *sc)
+ath5k_init(struct ath5k_softc *sc, bool is_resume)
 {
-       int ret;
+       struct ath5k_hw *ah = sc->ah;
+       int ret, i;
 
        mutex_lock(&sc->lock);
 
+       if (is_resume && !test_bit(ATH_STAT_STARTED, sc->status))
+               goto out_ok;
+
+       __clear_bit(ATH_STAT_STARTED, sc->status);
+
        ATH5K_DBG(sc, ATH5K_DEBUG_RESET, "mode %d\n", sc->opmode);
 
        /*
@@ -2230,12 +2217,22 @@ ath5k_init(struct ath5k_softc *sc)
        if (ret)
                goto done;
 
+       /*
+        * Reset the key cache since some parts do not reset the
+        * contents on initial power up or resume from suspend.
+        */
+       for (i = 0; i < AR5K_KEYTABLE_SIZE; i++)
+               ath5k_hw_reset_key(ah, i);
+
+       __set_bit(ATH_STAT_STARTED, sc->status);
+
        /* Set ack to be sent at low bit-rates */
-       ath5k_hw_set_ack_bitrate_high(sc->ah, false);
+       ath5k_hw_set_ack_bitrate_high(ah, false);
 
        mod_timer(&sc->calib_tim, round_jiffies(jiffies +
                        msecs_to_jiffies(ath5k_calinterval * 1000)));
 
+out_ok:
        ret = 0;
 done:
        mmiowb();
@@ -2290,7 +2287,7 @@ ath5k_stop_locked(struct ath5k_softc *sc)
  * stop is preempted).
  */
 static int
-ath5k_stop_hw(struct ath5k_softc *sc)
+ath5k_stop_hw(struct ath5k_softc *sc, bool is_suspend)
 {
        int ret;
 
@@ -2321,6 +2318,9 @@ ath5k_stop_hw(struct ath5k_softc *sc)
                }
        }
        ath5k_txbuf_free(sc, sc->bbuf);
+       if (!is_suspend)
+               __clear_bit(ATH_STAT_STARTED, sc->status);
+
        mmiowb();
        mutex_unlock(&sc->lock);
 
@@ -2718,12 +2718,12 @@ ath5k_reset_wake(struct ath5k_softc *sc)
 
 static int ath5k_start(struct ieee80211_hw *hw)
 {
-       return ath5k_init(hw->priv);
+       return ath5k_init(hw->priv, false);
 }
 
 static void ath5k_stop(struct ieee80211_hw *hw)
 {
-       ath5k_stop_hw(hw->priv);
+       ath5k_stop_hw(hw->priv, false);
 }
 
 static int ath5k_add_interface(struct ieee80211_hw *hw,
@@ -2942,10 +2942,8 @@ static void ath5k_configure_filter(struct ieee80211_hw *hw,
                sc->opmode != NL80211_IFTYPE_MESH_POINT &&
                test_bit(ATH_STAT_PROMISC, sc->status))
                rfilt |= AR5K_RX_FILTER_PROM;
-       if (sc->opmode == NL80211_IFTYPE_STATION ||
-               sc->opmode == NL80211_IFTYPE_ADHOC) {
+       if (sc->opmode == NL80211_IFTYPE_ADHOC)
                rfilt |= AR5K_RX_FILTER_BEACON;
-       }
 
        /* Set filters */
        ath5k_hw_set_rx_filter(ah,rfilt);