]> git.karo-electronics.de Git - linux-beck.git/blobdiff - drivers/net/wireless/ath/ath9k/recv.c
ath9k: lock reset and PCU start/stopping
[linux-beck.git] / drivers / net / wireless / ath / ath9k / recv.c
index 9eceeae28e7eed9ed23c442d97b7d1b45b5027da..fddb0129bb57c43efa1148401a3ebf1e80f38239 100644 (file)
@@ -268,6 +268,7 @@ static int ath_rx_edma_init(struct ath_softc *sc, int nbufs)
                                                bf->bf_buf_addr))) {
                                dev_kfree_skb_any(skb);
                                bf->bf_mpdu = NULL;
+                               bf->bf_buf_addr = 0;
                                ath_print(common, ATH_DBG_FATAL,
                                        "dma_mapping_error() on RX init\n");
                                error = -ENOMEM;
@@ -296,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_SCANNING));
+       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)
@@ -318,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->rx.pcu_lock);
        sc->sc_flags &= ~SC_OP_RXFLUSH;
        spin_lock_init(&sc->rx.rxbuflock);
 
@@ -358,12 +357,12 @@ int ath_rx_init(struct ath_softc *sc, int nbufs)
                                                        bf->bf_buf_addr))) {
                                dev_kfree_skb_any(skb);
                                bf->bf_mpdu = NULL;
+                               bf->bf_buf_addr = 0;
                                ath_print(common, ATH_DBG_FATAL,
                                          "dma_mapping_error() on RX init\n");
                                error = -ENOMEM;
                                goto err;
                        }
-                       bf->bf_dmacontext = bf->bf_buf_addr;
                }
                sc->rx.rxlink = NULL;
        }
@@ -393,6 +392,8 @@ void ath_rx_cleanup(struct ath_softc *sc)
                                                common->rx_bufsize,
                                                DMA_FROM_DEVICE);
                                dev_kfree_skb(skb);
+                               bf->bf_buf_addr = 0;
+                               bf->bf_mpdu = NULL;
                        }
                }
 
@@ -430,8 +431,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
                | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST
                | ATH9K_RX_FILTER_MCAST;
 
-       /* If not a STA, enable processing of Probe Requests */
-       if (sc->sc_ah->opmode != NL80211_IFTYPE_STATION)
+       if (sc->rx.rxfilter & FIF_PROBE_REQ)
                rfilt |= ATH9K_RX_FILTER_PROBEREQ;
 
        /*
@@ -454,8 +454,8 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
        else
                rfilt |= ATH9K_RX_FILTER_BEACON;
 
-       if ((AR_SREV_9280_10_OR_LATER(sc->sc_ah) ||
-           AR_SREV_9285_10_OR_LATER(sc->sc_ah)) &&
+       if ((AR_SREV_9280_20_OR_LATER(sc->sc_ah) ||
+           AR_SREV_9285_12_OR_LATER(sc->sc_ah)) &&
            (sc->sc_ah->opmode == NL80211_IFTYPE_AP) &&
            (sc->rx.rxfilter & FIF_PSPOLL))
                rfilt |= ATH9K_RX_FILTER_PSPOLL;
@@ -504,9 +504,10 @@ 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_SCANNING));
+       ath9k_hw_startpcureceive(ah, (sc->sc_flags & SC_OP_OFFCHANNEL));
+
+       spin_unlock_bh(&sc->rx.rxbuflock);
 
        return 0;
 }
@@ -516,6 +517,7 @@ bool ath_stoprecv(struct ath_softc *sc)
        struct ath_hw *ah = sc->sc_ah;
        bool stopped;
 
+       spin_lock_bh(&sc->rx.rxbuflock);
        ath9k_hw_stoppcurecv(ah);
        ath9k_hw_setrxfilter(ah, 0);
        stopped = ath9k_hw_stopdmarecv(ah);
@@ -524,19 +526,18 @@ bool ath_stoprecv(struct ath_softc *sc)
                ath_edma_stop_recv(sc);
        else
                sc->rx.rxlink = NULL;
+       spin_unlock_bh(&sc->rx.rxbuflock);
 
        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)
@@ -639,7 +640,7 @@ static void ath_rx_ps(struct ath_softc *sc, struct sk_buff *skb)
                 * No more broadcast/multicast frames to be received at this
                 * point.
                 */
-               sc->ps_flags &= ~PS_WAIT_FOR_CAB;
+               sc->ps_flags &= ~(PS_WAIT_FOR_CAB | PS_WAIT_FOR_BEACON);
                ath_print(common, ATH_DBG_PS,
                          "All PS CAB frames received, back to sleep\n");
        } else if ((sc->ps_flags & PS_WAIT_FOR_PSPOLL_DATA) &&
@@ -977,7 +978,11 @@ static void ath9k_process_rssi(struct ath_common *common,
         * 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.
         */
-       sta = ieee80211_find_sta_by_hw(hw, hdr->addr2);
+       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 &&
@@ -1338,7 +1343,7 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb,
        }
 }
 
-void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf)
+static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf)
 {
        /* Adjust the fast_div_bias based on main and alt lna conf */
        switch ((ant_conf->main_lna_conf << 4) | ant_conf->alt_lna_conf) {
@@ -1640,6 +1645,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
        u8 rx_status_len = ah->caps.rx_status_len;
        u64 tsf = 0;
        u32 tsf_lower = 0;
+       unsigned long flags;
 
        if (edma)
                dma_type = DMA_BIDIRECTIONAL;
@@ -1730,12 +1736,12 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
                          bf->bf_buf_addr))) {
                        dev_kfree_skb_any(requeue_skb);
                        bf->bf_mpdu = NULL;
+                       bf->bf_buf_addr = 0;
                        ath_print(common, ATH_DBG_FATAL,
                                  "dma_mapping_error() on RX\n");
                        ath_rx_send_to_mac80211(hw, sc, skb, rxs);
                        break;
                }
-               bf->bf_dmacontext = bf->bf_buf_addr;
 
                /*
                 * change the default rx antenna if rx diversity chooses the
@@ -1748,11 +1754,13 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
                        sc->rx.rxotherant = 0;
                }
 
+               spin_lock_irqsave(&sc->sc_pm_lock, flags);
                if (unlikely(ath9k_check_auto_sleep(sc) ||
                             (sc->ps_flags & (PS_WAIT_FOR_BEACON |
                                              PS_WAIT_FOR_CAB |
                                              PS_WAIT_FOR_PSPOLL_DATA))))
                        ath_rx_ps(sc, skb);
+               spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
 
                if (ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB)
                        ath_ant_comb_scan(sc, &rs);