| .. | .. |
|---|
| 19 | 19 | #include "ath9k.h" |
|---|
| 20 | 20 | #include "btcoex.h" |
|---|
| 21 | 21 | |
|---|
| 22 | +static void ath9k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
|---|
| 23 | + u32 queues, bool drop); |
|---|
| 24 | + |
|---|
| 22 | 25 | u8 ath9k_parse_mpdudensity(u8 mpdudensity) |
|---|
| 23 | 26 | { |
|---|
| 24 | 27 | /* |
|---|
| .. | .. |
|---|
| 200 | 203 | void ath_restart_work(struct ath_softc *sc) |
|---|
| 201 | 204 | { |
|---|
| 202 | 205 | ieee80211_queue_delayed_work(sc->hw, &sc->hw_check_work, |
|---|
| 203 | | - ATH_HW_CHECK_POLL_INT); |
|---|
| 206 | + msecs_to_jiffies(ATH_HW_CHECK_POLL_INT)); |
|---|
| 204 | 207 | |
|---|
| 205 | 208 | if (AR_SREV_9340(sc->sc_ah) || AR_SREV_9330(sc->sc_ah)) |
|---|
| 206 | 209 | ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, |
|---|
| .. | .. |
|---|
| 373 | 376 | ath_dynack_node_deinit(sc->sc_ah, an); |
|---|
| 374 | 377 | } |
|---|
| 375 | 378 | |
|---|
| 376 | | -void ath9k_tasklet(unsigned long data) |
|---|
| 379 | +void ath9k_tasklet(struct tasklet_struct *t) |
|---|
| 377 | 380 | { |
|---|
| 378 | | - struct ath_softc *sc = (struct ath_softc *)data; |
|---|
| 381 | + struct ath_softc *sc = from_tasklet(sc, t, intr_tq); |
|---|
| 379 | 382 | struct ath_hw *ah = sc->sc_ah; |
|---|
| 380 | 383 | struct ath_common *common = ath9k_hw_common(ah); |
|---|
| 381 | 384 | enum ath_reset_type type; |
|---|
| .. | .. |
|---|
| 816 | 819 | |
|---|
| 817 | 820 | if (ath_tx_start(hw, skb, &txctl) != 0) { |
|---|
| 818 | 821 | ath_dbg(common, XMIT, "TX failed\n"); |
|---|
| 819 | | - TX_STAT_INC(txctl.txq->axq_qnum, txfailed); |
|---|
| 822 | + TX_STAT_INC(sc, txctl.txq->axq_qnum, txfailed); |
|---|
| 820 | 823 | goto exit; |
|---|
| 821 | 824 | } |
|---|
| 822 | 825 | |
|---|
| .. | .. |
|---|
| 836 | 839 | continue; |
|---|
| 837 | 840 | |
|---|
| 838 | 841 | txinfo = IEEE80211_SKB_CB(bf->bf_mpdu); |
|---|
| 839 | | - fi = (struct ath_frame_info *)&txinfo->rate_driver_data[0]; |
|---|
| 842 | + fi = (struct ath_frame_info *)&txinfo->status.status_driver_data[0]; |
|---|
| 840 | 843 | if (fi->keyix == keyix) |
|---|
| 841 | 844 | return true; |
|---|
| 842 | 845 | } |
|---|
| .. | .. |
|---|
| 847 | 850 | static bool ath9k_txq_has_key(struct ath_softc *sc, u32 keyix) |
|---|
| 848 | 851 | { |
|---|
| 849 | 852 | struct ath_hw *ah = sc->sc_ah; |
|---|
| 850 | | - int i; |
|---|
| 853 | + int i, j; |
|---|
| 851 | 854 | struct ath_txq *txq; |
|---|
| 852 | 855 | bool key_in_use = false; |
|---|
| 853 | 856 | |
|---|
| .. | .. |
|---|
| 865 | 868 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) { |
|---|
| 866 | 869 | int idx = txq->txq_tailidx; |
|---|
| 867 | 870 | |
|---|
| 868 | | - while (!key_in_use && |
|---|
| 869 | | - !list_empty(&txq->txq_fifo[idx])) { |
|---|
| 871 | + for (j = 0; !key_in_use && |
|---|
| 872 | + !list_empty(&txq->txq_fifo[idx]) && |
|---|
| 873 | + j < ATH_TXFIFO_DEPTH; j++) { |
|---|
| 870 | 874 | key_in_use = ath9k_txq_list_has_key( |
|---|
| 871 | 875 | &txq->txq_fifo[idx], keyix); |
|---|
| 872 | 876 | INCR(idx, ATH_TXFIFO_DEPTH); |
|---|
| .. | .. |
|---|
| 1279 | 1283 | { |
|---|
| 1280 | 1284 | int *power = data; |
|---|
| 1281 | 1285 | |
|---|
| 1286 | + if (vif->bss_conf.txpower == INT_MIN) |
|---|
| 1287 | + return; |
|---|
| 1288 | + |
|---|
| 1282 | 1289 | if (*power < vif->bss_conf.txpower) |
|---|
| 1283 | 1290 | *power = vif->bss_conf.txpower; |
|---|
| 1284 | 1291 | } |
|---|
| .. | .. |
|---|
| 1556 | 1563 | FIF_OTHER_BSS | \ |
|---|
| 1557 | 1564 | FIF_BCN_PRBRESP_PROMISC | \ |
|---|
| 1558 | 1565 | FIF_PROBE_REQ | \ |
|---|
| 1566 | + FIF_MCAST_ACTION | \ |
|---|
| 1559 | 1567 | FIF_FCSFAIL) |
|---|
| 1560 | 1568 | |
|---|
| 1561 | 1569 | /* FIXME: sc->sc_full_reset ? */ |
|---|
| .. | .. |
|---|
| 1777 | 1785 | * frames is a acceptable to allow RSN IBSS to be used. |
|---|
| 1778 | 1786 | */ |
|---|
| 1779 | 1787 | return -EOPNOTSUPP; |
|---|
| 1788 | + } |
|---|
| 1789 | + |
|---|
| 1790 | + /* There may be MPDUs queued for the outgoing PTK key. Flush queues to |
|---|
| 1791 | + * make sure these are not send unencrypted or with a wrong (new) key |
|---|
| 1792 | + */ |
|---|
| 1793 | + if (cmd == DISABLE_KEY && key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { |
|---|
| 1794 | + ieee80211_stop_queues(hw); |
|---|
| 1795 | + ath9k_flush(hw, vif, 0, true); |
|---|
| 1796 | + ieee80211_wake_queues(hw); |
|---|
| 1780 | 1797 | } |
|---|
| 1781 | 1798 | |
|---|
| 1782 | 1799 | mutex_lock(&sc->mutex); |
|---|
| .. | .. |
|---|
| 2020 | 2037 | ath9k_ps_wakeup(sc); |
|---|
| 2021 | 2038 | ret = ath_tx_aggr_start(sc, sta, tid, ssn); |
|---|
| 2022 | 2039 | if (!ret) |
|---|
| 2023 | | - ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); |
|---|
| 2040 | + ret = IEEE80211_AMPDU_TX_START_IMMEDIATE; |
|---|
| 2024 | 2041 | ath9k_ps_restore(sc); |
|---|
| 2025 | 2042 | break; |
|---|
| 2026 | 2043 | case IEEE80211_AMPDU_TX_STOP_FLUSH: |
|---|
| 2027 | 2044 | case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: |
|---|
| 2028 | 2045 | flush = true; |
|---|
| 2029 | | - /* fall through */ |
|---|
| 2046 | + fallthrough; |
|---|
| 2030 | 2047 | case IEEE80211_AMPDU_TX_STOP_CONT: |
|---|
| 2031 | 2048 | ath9k_ps_wakeup(sc); |
|---|
| 2032 | 2049 | ath_tx_aggr_stop(sc, sta, tid); |
|---|
| .. | .. |
|---|
| 2227 | 2244 | } |
|---|
| 2228 | 2245 | |
|---|
| 2229 | 2246 | ieee80211_queue_delayed_work(hw, &sc->hw_check_work, |
|---|
| 2230 | | - ATH_HW_CHECK_POLL_INT); |
|---|
| 2247 | + msecs_to_jiffies(ATH_HW_CHECK_POLL_INT)); |
|---|
| 2231 | 2248 | } |
|---|
| 2232 | 2249 | |
|---|
| 2233 | 2250 | static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw) |
|---|
| .. | .. |
|---|
| 2491 | 2508 | return ret; |
|---|
| 2492 | 2509 | } |
|---|
| 2493 | 2510 | |
|---|
| 2494 | | -static int ath9k_cancel_remain_on_channel(struct ieee80211_hw *hw) |
|---|
| 2511 | +static int ath9k_cancel_remain_on_channel(struct ieee80211_hw *hw, |
|---|
| 2512 | + struct ieee80211_vif *vif) |
|---|
| 2495 | 2513 | { |
|---|
| 2496 | 2514 | struct ath_softc *sc = hw->priv; |
|---|
| 2497 | 2515 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
|---|