Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[cascardo/linux.git] / drivers / net / wireless / ath / ath9k / recv.c
index fe73fc5..262c815 100644 (file)
@@ -297,19 +297,17 @@ static void ath_edma_start_recv(struct ath_softc *sc)
        ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_LP,
                              sc->rx.rx_edma[ATH9K_RX_QUEUE_LP].rx_fifo_hwsize);
 
-       spin_unlock_bh(&sc->rx.rxbuflock);
-
        ath_opmode_init(sc);
 
        ath9k_hw_startpcureceive(sc->sc_ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
+
+       spin_unlock_bh(&sc->rx.rxbuflock);
 }
 
 static void ath_edma_stop_recv(struct ath_softc *sc)
 {
-       spin_lock_bh(&sc->rx.rxbuflock);
        ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_HP);
        ath_rx_remove_buffer(sc, ATH9K_RX_QUEUE_LP);
-       spin_unlock_bh(&sc->rx.rxbuflock);
 }
 
 int ath_rx_init(struct ath_softc *sc, int nbufs)
@@ -319,7 +317,7 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
        struct ath_buf *bf;
        int error = 0;
 
-       spin_lock_init(&sc->rx.rxflushlock);
+       spin_lock_init(&sc->sc_pcu_lock);
        sc->sc_flags &= ~SC_OP_RXFLUSH;
        spin_lock_init(&sc->rx.rxbuflock);
 
@@ -443,7 +441,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
         */
        if (((sc->sc_ah->opmode != NL80211_IFTYPE_AP) &&
             (sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) ||
-           (sc->sc_ah->opmode == NL80211_IFTYPE_MONITOR))
+           (sc->sc_ah->is_monitoring))
                rfilt |= ATH9K_RX_FILTER_PROM;
 
        if (sc->rx.rxfilter & FIF_CONTROL)
@@ -506,10 +504,11 @@ int ath_startrecv(struct ath_softc *sc)
        ath9k_hw_rxena(ah);
 
 start_recv:
-       spin_unlock_bh(&sc->rx.rxbuflock);
        ath_opmode_init(sc);
        ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
 
+       spin_unlock_bh(&sc->rx.rxbuflock);
+
        return 0;
 }
 
@@ -518,7 +517,8 @@ bool ath_stoprecv(struct ath_softc *sc)
        struct ath_hw *ah = sc->sc_ah;
        bool stopped;
 
-       ath9k_hw_stoppcurecv(ah);
+       spin_lock_bh(&sc->rx.rxbuflock);
+       ath9k_hw_abortpcurecv(ah);
        ath9k_hw_setrxfilter(ah, 0);
        stopped = ath9k_hw_stopdmarecv(ah);
 
@@ -526,19 +526,20 @@ bool ath_stoprecv(struct ath_softc *sc)
                ath_edma_stop_recv(sc);
        else
                sc->rx.rxlink = NULL;
+       spin_unlock_bh(&sc->rx.rxbuflock);
 
+       ATH_DBG_WARN(!stopped, "Could not stop RX, we could be "
+                    "confusing the DMA engine when we start RX up\n");
        return stopped;
 }
 
 void ath_flushrecv(struct ath_softc *sc)
 {
-       spin_lock_bh(&sc->rx.rxflushlock);
        sc->sc_flags |= SC_OP_RXFLUSH;
        if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
                ath_rx_tasklet(sc, 1, true);
        ath_rx_tasklet(sc, 1, false);
        sc->sc_flags &= ~SC_OP_RXFLUSH;
-       spin_unlock_bh(&sc->rx.rxflushlock);
 }
 
 static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb)
@@ -898,7 +899,7 @@ static bool ath9k_rx_accept(struct ath_common *common,
                 * decryption and MIC failures. For monitor mode,
                 * we also ignore the CRC error.
                 */
-               if (ah->opmode == NL80211_IFTYPE_MONITOR) {
+               if (ah->is_monitoring) {
                        if (rx_stats->rs_status &
                            ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
                              ATH9K_RXERR_CRC))
@@ -963,36 +964,23 @@ static void ath9k_process_rssi(struct ath_common *common,
                               struct ieee80211_hdr *hdr,
                               struct ath_rx_status *rx_stats)
 {
+       struct ath_wiphy *aphy = hw->priv;
        struct ath_hw *ah = common->ah;
-       struct ieee80211_sta *sta;
-       struct ath_node *an;
-       int last_rssi = ATH_RSSI_DUMMY_MARKER;
+       int last_rssi;
        __le16 fc;
 
+       if (ah->opmode != NL80211_IFTYPE_STATION)
+               return;
+
        fc = hdr->frame_control;
+       if (!ieee80211_is_beacon(fc) ||
+           compare_ether_addr(hdr->addr3, common->curbssid))
+               return;
 
-       rcu_read_lock();
-       /*
-        * XXX: use ieee80211_find_sta! This requires quite a bit of work
-        * under the current ath9k virtual wiphy implementation as we have
-        * no way of tying a vif to wiphy. Typically vifs are attached to
-        * at least one sdata of a wiphy on mac80211 but with ath9k virtual
-        * wiphy you'd have to iterate over every wiphy and each sdata.
-        */
-       if (is_multicast_ether_addr(hdr->addr1))
-               sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, NULL);
-       else
-               sta = ieee80211_find_sta_by_ifaddr(hw, hdr->addr2, hdr->addr1);
-
-       if (sta) {
-               an = (struct ath_node *) sta->drv_priv;
-               if (rx_stats->rs_rssi != ATH9K_RSSI_BAD &&
-                  !rx_stats->rs_moreaggr)
-                       ATH_RSSI_LPF(an->last_rssi, rx_stats->rs_rssi);
-               last_rssi = an->last_rssi;
-       }
-       rcu_read_unlock();
+       if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && !rx_stats->rs_moreaggr)
+               ATH_RSSI_LPF(aphy->last_rssi, rx_stats->rs_rssi);
 
+       last_rssi = aphy->last_rssi;
        if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
                rx_stats->rs_rssi = ATH_EP_RND(last_rssi,
                                              ATH_RSSI_EP_MULTIPLIER);
@@ -1000,8 +988,7 @@ static void ath9k_process_rssi(struct ath_common *common,
                rx_stats->rs_rssi = 0;
 
        /* Update Beacon RSSI, this is used by ANI. */
-       if (ieee80211_is_beacon(fc))
-               ah->stats.avgbrssi = rx_stats->rs_rssi;
+       ah->stats.avgbrssi = rx_stats->rs_rssi;
 }
 
 /*