diff options
39 files changed, 299 insertions, 203 deletions
diff --git a/drivers/bcma/scan.c b/drivers/bcma/scan.c index bca9c80056fe..8bffa5c9818c 100644 --- a/drivers/bcma/scan.c +++ b/drivers/bcma/scan.c @@ -84,6 +84,8 @@ static const struct bcma_device_id_name bcma_bcm_device_names[] = { { BCMA_CORE_I2S, "I2S" }, { BCMA_CORE_SDR_DDR1_MEM_CTL, "SDR/DDR1 Memory Controller" }, { BCMA_CORE_SHIM, "SHIM" }, + { BCMA_CORE_PCIE2, "PCIe Gen2" }, + { BCMA_CORE_ARM_CR4, "ARM CR4" }, { BCMA_CORE_DEFAULT, "Default" }, }; diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 17507dc8a1e7..f3dc124c60c7 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig @@ -17,7 +17,7 @@ config ATH9K_BTCOEX_SUPPORT config ATH9K tristate "Atheros 802.11n wireless cards support" - depends on MAC80211 + depends on MAC80211 && HAS_DMA select ATH9K_HW select MAC80211_LEDS select LEDS_CLASS diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index 639ba7d18ea4..6988e1d081f2 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c @@ -965,7 +965,7 @@ static void ar9003_hw_do_manual_peak_cal(struct ath_hw *ah, { int i; - if (!AR_SREV_9462(ah) && !AR_SREV_9565(ah)) + if (!AR_SREV_9462(ah) && !AR_SREV_9565(ah) && !AR_SREV_9485(ah)) return; for (i = 0; i < AR9300_MAX_CHAINS; i++) { diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 2bf6548dd143..e1714d7c9eeb 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c @@ -334,7 +334,8 @@ static void ar9003_hw_spur_ofdm(struct ath_hw *ah, REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_EN_VIT_SPUR_RSSI, 1); - if (REG_READ_FIELD(ah, AR_PHY_MODE, + if (!AR_SREV_9340(ah) && + REG_READ_FIELD(ah, AR_PHY_MODE, AR_PHY_MODE_DYNAMIC) == 0x1) REG_RMW_FIELD(ah, AR_PHY_SPUR_REG, AR_PHY_SPUR_REG_ENABLE_NF_RSSI_SPUR_MIT, 1); diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h index 712f415b8c08..88ff1d7b53ab 100644 --- a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h @@ -1020,7 +1020,7 @@ static const u32 ar9485_1_1_baseband_postamble[][5] = { {0x0000a284, 0x00000000, 0x00000000, 0x000002a0, 0x000002a0}, {0x0000a288, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, {0x0000a28c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, - {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00158d18, 0x00158d18}, + {0x0000a2c4, 0x00158d18, 0x00158d18, 0x00058d18, 0x00058d18}, {0x0000a2d0, 0x00071981, 0x00071981, 0x00071982, 0x00071982}, {0x0000a2d8, 0xf999a83a, 0xf999a83a, 0xf999a83a, 0xf999a83a}, {0x0000a358, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index 8a1888d02070..42b03dc39d14 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h @@ -251,9 +251,9 @@ struct ath_atx_tid { int tidno; int baw_head; /* first un-acked tx buffer */ int baw_tail; /* next unused tx buffer slot */ - int sched; - int paused; - u8 state; + bool sched; + bool paused; + bool active; }; struct ath_node { @@ -274,10 +274,6 @@ struct ath_node { #endif }; -#define AGGR_CLEANUP BIT(1) -#define AGGR_ADDBA_COMPLETE BIT(2) -#define AGGR_ADDBA_PROGRESS BIT(3) - struct ath_tx_control { struct ath_txq *txq; struct ath_node *an; diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index e6307b86363a..b37eb8d38811 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c @@ -2008,6 +2008,14 @@ void ath9k_get_et_stats(struct ieee80211_hw *hw, WARN_ON(i != ATH9K_SSTATS_LEN); } +void ath9k_deinit_debug(struct ath_softc *sc) +{ + if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) { + relay_close(sc->rfs_chan_spec_scan); + sc->rfs_chan_spec_scan = NULL; + } +} + int ath9k_init_debug(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 794a7ec83a24..9d49aab8b989 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h @@ -304,6 +304,7 @@ struct ath9k_debug { }; int ath9k_init_debug(struct ath_hw *ah); +void ath9k_deinit_debug(struct ath_softc *sc); void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); void ath_debug_stat_tx(struct ath_softc *sc, struct ath_buf *bf, @@ -339,6 +340,10 @@ static inline int ath9k_init_debug(struct ath_hw *ah) return 0; } +static inline void ath9k_deinit_debug(struct ath_softc *sc) +{ +} + static inline void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status) { diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 7f25da8444fe..15dfefcf2d0f 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c @@ -1172,6 +1172,7 @@ u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan) static inline void ath9k_hw_set_dma(struct ath_hw *ah) { struct ath_common *common = ath9k_hw_common(ah); + int txbuf_size; ENABLE_REGWRITE_BUFFER(ah); @@ -1225,13 +1226,17 @@ static inline void ath9k_hw_set_dma(struct ath_hw *ah) * So set the usable tx buf size also to half to * avoid data/delimiter underruns */ - REG_WRITE(ah, AR_PCU_TXBUF_CTRL, - AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE); - } else if (!AR_SREV_9271(ah)) { - REG_WRITE(ah, AR_PCU_TXBUF_CTRL, - AR_PCU_TXBUF_CTRL_USABLE_SIZE); + txbuf_size = AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE; + } else if (AR_SREV_9340_13_OR_LATER(ah)) { + /* Uses fewer entries for AR934x v1.3+ to prevent rx overruns */ + txbuf_size = AR_9340_PCU_TXBUF_CTRL_USABLE_SIZE; + } else { + txbuf_size = AR_PCU_TXBUF_CTRL_USABLE_SIZE; } + if (!AR_SREV_9271(ah)) + REG_WRITE(ah, AR_PCU_TXBUF_CTRL, txbuf_size); + REGWRITE_BUFFER_FLUSH(ah); if (AR_SREV_9300_20_OR_LATER(ah)) @@ -1306,9 +1311,13 @@ static bool ath9k_hw_set_reset(struct ath_hw *ah, int type) AR_RTC_RC_COLD_RESET | AR_RTC_RC_WARM_RESET; } else { tmpReg = REG_READ(ah, AR_INTR_SYNC_CAUSE); - if (tmpReg & - (AR_INTR_SYNC_LOCAL_TIMEOUT | - AR_INTR_SYNC_RADM_CPL_TIMEOUT)) { + if (AR_SREV_9340(ah)) + tmpReg &= AR9340_INTR_SYNC_LOCAL_TIMEOUT; + else + tmpReg &= AR_INTR_SYNC_LOCAL_TIMEOUT | + AR_INTR_SYNC_RADM_CPL_TIMEOUT; + + if (tmpReg) { u32 val; REG_WRITE(ah, AR_INTR_SYNC_ENABLE, 0); diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 0237b2868961..aba415103f94 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c @@ -906,7 +906,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, if (!ath_is_world_regd(reg)) { error = regulatory_hint(hw->wiphy, reg->alpha2); if (error) - goto unregister; + goto debug_cleanup; } ath_init_leds(sc); @@ -914,6 +914,8 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, return 0; +debug_cleanup: + ath9k_deinit_debug(sc); unregister: ieee80211_unregister_hw(hw); rx_cleanup: @@ -942,11 +944,6 @@ static void ath9k_deinit_softc(struct ath_softc *sc) sc->dfs_detector->exit(sc->dfs_detector); ath9k_eeprom_release(sc); - - if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) { - relay_close(sc->rfs_chan_spec_scan); - sc->rfs_chan_spec_scan = NULL; - } } void ath9k_deinit_device(struct ath_softc *sc) @@ -960,6 +957,7 @@ void ath9k_deinit_device(struct ath_softc *sc) ath9k_ps_restore(sc); + ath9k_deinit_debug(sc); ieee80211_unregister_hw(hw); ath_rx_cleanup(sc); ath9k_deinit_softc(sc); diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c index 498fee04afa0..566109a40fb3 100644 --- a/drivers/net/wireless/ath/ath9k/mac.c +++ b/drivers/net/wireless/ath/ath9k/mac.c @@ -410,7 +410,7 @@ bool ath9k_hw_resettxqueue(struct ath_hw *ah, u32 q) REG_WRITE(ah, AR_QMISC(q), AR_Q_MISC_DCU_EARLY_TERM_REQ); - if (AR_SREV_9340(ah)) + if (AR_SREV_9340(ah) && !AR_SREV_9340_13_OR_LATER(ah)) REG_WRITE(ah, AR_DMISC(q), AR_D_MISC_CW_BKOFF_EN | AR_D_MISC_FRAG_WAIT_EN | 0x1); else diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index a18414b5948b..5092ecae7706 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c @@ -1687,6 +1687,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, u16 tid, u16 *ssn, u8 buf_size) { struct ath_softc *sc = hw->priv; + bool flush = false; int ret = 0; local_bh_disable(); @@ -1703,12 +1704,14 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); ath9k_ps_restore(sc); break; - case IEEE80211_AMPDU_TX_STOP_CONT: case IEEE80211_AMPDU_TX_STOP_FLUSH: case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: + flush = true; + case IEEE80211_AMPDU_TX_STOP_CONT: ath9k_ps_wakeup(sc); ath_tx_aggr_stop(sc, sta, tid); - ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); + if (!flush) + ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); ath9k_ps_restore(sc); break; case IEEE80211_AMPDU_TX_OPERATIONAL: diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c index aa4d368d8d3d..7eb1f4b458e4 100644 --- a/drivers/net/wireless/ath/ath9k/rc.c +++ b/drivers/net/wireless/ath/ath9k/rc.c @@ -1227,10 +1227,7 @@ static bool ath_tx_aggr_check(struct ath_softc *sc, struct ieee80211_sta *sta, return false; txtid = ATH_AN_2_TID(an, tidno); - - if (!(txtid->state & (AGGR_ADDBA_COMPLETE | AGGR_ADDBA_PROGRESS))) - return true; - return false; + return !txtid->active; } diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 5c4ab5026dca..f7c90cc58d56 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h @@ -798,6 +798,10 @@ #define AR_SREV_REVISION_9485_10 0 #define AR_SREV_REVISION_9485_11 1 #define AR_SREV_VERSION_9340 0x300 +#define AR_SREV_REVISION_9340_10 0 +#define AR_SREV_REVISION_9340_11 1 +#define AR_SREV_REVISION_9340_12 2 +#define AR_SREV_REVISION_9340_13 3 #define AR_SREV_VERSION_9580 0x1C0 #define AR_SREV_REVISION_9580_10 4 /* AR9580 1.0 */ #define AR_SREV_VERSION_9462 0x280 @@ -897,6 +901,10 @@ #define AR_SREV_9340(_ah) \ (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9340)) +#define AR_SREV_9340_13_OR_LATER(_ah) \ + (AR_SREV_9340((_ah)) && \ + ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9340_13)) + #define AR_SREV_9285E_20(_ah) \ (AR_SREV_9285_12_OR_LATER(_ah) && \ ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1)) @@ -1007,6 +1015,8 @@ enum { AR_INTR_SYNC_LOCAL_TIMEOUT | AR_INTR_SYNC_MAC_SLEEP_ACCESS), + AR9340_INTR_SYNC_LOCAL_TIMEOUT = 0x00000010, + AR_INTR_SYNC_SPURIOUS = 0xFFFFFFFF, }; @@ -1881,6 +1891,7 @@ enum { #define AR_PCU_TXBUF_CTRL_SIZE_MASK 0x7FF #define AR_PCU_TXBUF_CTRL_USABLE_SIZE 0x700 #define AR_9285_PCU_TXBUF_CTRL_USABLE_SIZE 0x380 +#define AR_9340_PCU_TXBUF_CTRL_USABLE_SIZE 0x500 #define AR_PCU_MISC_MODE2 0x8344 #define AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE 0x00000002 diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index eab0fcb7ded6..1c9b1bac8b0d 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c @@ -125,24 +125,6 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid) list_add_tail(&ac->list, &txq->axq_acq); } -static void ath_tx_resume_tid(struct ath_softc *sc, struct ath_atx_tid *tid) -{ - struct ath_txq *txq = tid->ac->txq; - - WARN_ON(!tid->paused); - - ath_txq_lock(sc, txq); - tid->paused = false; - - if (skb_queue_empty(&tid->buf_q)) - goto unlock; - - ath_tx_queue_tid(txq, tid); - ath_txq_schedule(sc, txq); -unlock: - ath_txq_unlock_complete(sc, txq); -} - static struct ath_frame_info *get_frame_info(struct sk_buff *skb) { struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); @@ -201,11 +183,6 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid) } } - if (tid->baw_head == tid->baw_tail) { - tid->state &= ~AGGR_ADDBA_COMPLETE; - tid->state &= ~AGGR_CLEANUP; - } - if (sendbar) { ath_txq_unlock(sc, txq); ath_send_bar(tid, tid->seq_start); @@ -277,9 +254,7 @@ static void ath_tid_drain(struct ath_softc *sc, struct ath_txq *txq, list_add_tail(&bf->list, &bf_head); - if (fi->retries) - ath_tx_update_baw(sc, tid, bf->bf_state.seqno); - + ath_tx_update_baw(sc, tid, bf->bf_state.seqno); ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0); } @@ -491,19 +466,19 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, tx_info = IEEE80211_SKB_CB(skb); fi = get_frame_info(skb); - if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, seqno))) { + if (!BAW_WITHIN(tid->seq_start, tid->baw_size, seqno)) { + /* + * Outside of the current BlockAck window, + * maybe part of a previous session + */ + txfail = 1; + } else if (ATH_BA_ISSET(ba, ATH_BA_INDEX(seq_st, seqno))) { /* transmit completion, subframe is * acked by block ack */ acked_cnt++; } else if (!isaggr && txok) { /* transmit completion */ acked_cnt++; - } else if (tid->state & AGGR_CLEANUP) { - /* - * cleanup in progress, just fail - * the un-acked sub-frames - */ - txfail = 1; } else if (flush) { txpending = 1; } else if (fi->retries < ATH_MAX_SW_RETRIES) { @@ -527,7 +502,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, if (bf_next != NULL || !bf_last->bf_stale) list_move_tail(&bf->list, &bf_head); - if (!txpending || (tid->state & AGGR_CLEANUP)) { + if (!txpending) { /* * complete the acked-ones/xretried ones; update * block-ack window @@ -601,9 +576,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, ath_txq_lock(sc, txq); } - if (tid->state & AGGR_CLEANUP) - ath_tx_flush_tid(sc, tid); - rcu_read_unlock(); if (needreset) @@ -620,6 +592,7 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, struct ath_tx_status *ts, struct ath_buf *bf, struct list_head *bf_head) { + struct ieee80211_tx_info *info; bool txok, flush; txok = !(ts->ts_status & ATH9K_TXERR_MASK); @@ -631,8 +604,12 @@ static void ath_tx_process_buffer(struct ath_softc *sc, struct ath_txq *txq, txq->axq_ampdu_depth--; if (!bf_isampdu(bf)) { - if (!flush) + if (!flush) { + info = IEEE80211_SKB_CB(bf->bf_mpdu); + memcpy(info->control.rates, bf->rates, + sizeof(info->control.rates)); ath_tx_rc_status(sc, bf, ts, 1, txok ? 0 : 1, txok); + } ath_tx_complete_buf(sc, bf, txq, bf_head, ts, txok); } else ath_tx_complete_aggr(sc, txq, bf, bf_head, ts, txok); @@ -676,7 +653,7 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, skb = bf->bf_mpdu; tx_info = IEEE80211_SKB_CB(skb); - rates = tx_info->control.rates; + rates = bf->rates; /* * Find the lowest frame length among the rate series that will have a @@ -1231,9 +1208,6 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, an = (struct ath_node *)sta->drv_priv; txtid = ATH_AN_2_TID(an, tid); - if (txtid->state & (AGGR_CLEANUP | AGGR_ADDBA_COMPLETE)) - return -EAGAIN; - /* update ampdu factor/density, they may have changed. This may happen * in HT IBSS when a beacon with HT-info is received after the station * has already been added. @@ -1245,7 +1219,7 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, an->mpdudensity = density; } - txtid->state |= AGGR_ADDBA_PROGRESS; + txtid->active = true; txtid->paused = true; *ssn = txtid->seq_start = txtid->seq_next; txtid->bar_index = -1; @@ -1262,28 +1236,9 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); struct ath_txq *txq = txtid->ac->txq; - if (txtid->state & AGGR_CLEANUP) - return; - - if (!(txtid->state & AGGR_ADDBA_COMPLETE)) { - txtid->state &= ~AGGR_ADDBA_PROGRESS; - return; - } - ath_txq_lock(sc, txq); + txtid->active = false; txtid->paused = true; - - /* - * If frames are still being transmitted for this TID, they will be - * cleaned up during tx completion. To prevent race conditions, this - * TID can only be reused after all in-progress subframes have been - * completed. - */ - if (txtid->baw_head != txtid->baw_tail) - txtid->state |= AGGR_CLEANUP; - else - txtid->state &= ~AGGR_ADDBA_COMPLETE; - ath_tx_flush_tid(sc, txtid); ath_txq_unlock_complete(sc, txq); } @@ -1349,18 +1304,28 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) } } -void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) +void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, + u16 tidno) { - struct ath_atx_tid *txtid; + struct ath_atx_tid *tid; struct ath_node *an; + struct ath_txq *txq; an = (struct ath_node *)sta->drv_priv; + tid = ATH_AN_2_TID(an, tidno); + txq = tid->ac->txq; - txtid = ATH_AN_2_TID(an, tid); - txtid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor; - txtid->state |= AGGR_ADDBA_COMPLETE; - txtid->state &= ~AGGR_ADDBA_PROGRESS; - ath_tx_resume_tid(sc, txtid); + ath_txq_lock(sc, txq); + + tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor; + tid->paused = false; + + if (!skb_queue_empty(&tid->buf_q)) { + ath_tx_queue_tid(txq, tid); + ath_txq_schedule(sc, txq); + } + + ath_txq_unlock_complete(sc, txq); } /********************/ @@ -2409,12 +2374,10 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an) tid->baw_head = tid->baw_tail = 0; tid->sched = false; tid->paused = false; - tid->state &= ~AGGR_CLEANUP; + tid->active = false; __skb_queue_head_init(&tid->buf_q); acno = TID_TO_WME_AC(tidno); tid->ac = &an->ac[acno]; - tid->state &= ~AGGR_ADDBA_COMPLETE; - tid->state &= ~AGGR_ADDBA_PROGRESS; } for (acno = 0, ac = &an->ac[acno]; @@ -2451,8 +2414,7 @@ void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an) } ath_tid_drain(sc, txq, tid); - tid->state &= ~AGGR_ADDBA_COMPLETE; - tid->state &= ~AGGR_CLEANUP; + tid->active = false; ath_txq_unlock(sc, txq); } diff --git a/drivers/net/wireless/atmel.c b/drivers/net/wireless/atmel.c index 830bb1d1f957..b827d51c30a3 100644 --- a/drivers/net/wireless/atmel.c +++ b/drivers/net/wireless/atmel.c @@ -1624,7 +1624,7 @@ struct net_device *init_atmel_card(unsigned short irq, unsigned long port, netif_carrier_off(dev); - if (!proc_create_data("driver/atmel", 0, NULL, &atmel_proc_fops, priv)); + if (!proc_create_data("driver/atmel", 0, NULL, &atmel_proc_fops, priv)) printk(KERN_WARNING "atmel: unable to create /proc entry.\n"); printk(KERN_INFO "%s: Atmel at76c50x. Version %d.%d. MAC %pM\n", diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 6d758f285352..761f501959a9 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -4140,6 +4140,10 @@ static const struct ieee80211_iface_limit brcmf_iface_limits[] = { .types = BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO) }, + { + .max = 1, + .types = BIT(NL80211_IFTYPE_P2P_DEVICE) + } }; static const struct ieee80211_iface_combination brcmf_iface_combos[] = { { @@ -4197,7 +4201,8 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev) BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_P2P_GO); + BIT(NL80211_IFTYPE_P2P_GO) | + BIT(NL80211_IFTYPE_P2P_DEVICE); wiphy->iface_combinations = brcmf_iface_combos; wiphy->n_iface_combinations = ARRAY_SIZE(brcmf_iface_combos); wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c index 592d0aa634a8..e9a3cbc409ae 100644 --- a/drivers/net/wireless/iwlegacy/common.c +++ b/drivers/net/wireless/iwlegacy/common.c @@ -1423,7 +1423,7 @@ il_setup_rx_scan_handlers(struct il_priv *il) } EXPORT_SYMBOL(il_setup_rx_scan_handlers); -inline u16 +u16 il_get_active_dwell_time(struct il_priv *il, enum ieee80211_band band, u8 n_probes) { diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index b878a32e7a98..cb34c7895f2a 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c @@ -1723,11 +1723,11 @@ static void mac80211_hwsim_free(void) class_destroy(hwsim_class); } - -static struct device_driver mac80211_hwsim_driver = { - .name = "mac80211_hwsim", - .bus = &platform_bus_type, - .owner = THIS_MODULE, +static struct platform_driver mac80211_hwsim_driver = { + .driver = { + .name = "mac80211_hwsim", + .owner = THIS_MODULE, + }, }; static const struct net_device_ops hwsim_netdev_ops = { @@ -2219,7 +2219,7 @@ static int __init init_mac80211_hwsim(void) spin_lock_init(&hwsim_radio_lock); INIT_LIST_HEAD(&hwsim_radios); - err = driver_register(&mac80211_hwsim_driver); + err = platform_driver_register(&mac80211_hwsim_driver); if (err) return err; @@ -2254,7 +2254,7 @@ static int __init init_mac80211_hwsim(void) err = -ENOMEM; goto failed_drvdata; } - data->dev->driver = &mac80211_hwsim_driver; + data->dev->driver = &mac80211_hwsim_driver.driver; err = device_bind_driver(data->dev); if (err != 0) { printk(KERN_DEBUG @@ -2564,7 +2564,7 @@ failed_drvdata: failed: mac80211_hwsim_free(); failed_unregister_driver: - driver_unregister(&mac80211_hwsim_driver); + platform_driver_unregister(&mac80211_hwsim_driver); return err; } module_init(init_mac80211_hwsim); @@ -2577,6 +2577,6 @@ static void __exit exit_mac80211_hwsim(void) mac80211_hwsim_free(); unregister_netdev(hwsim_mon); - driver_unregister(&mac80211_hwsim_driver); + platform_driver_unregister(&mac80211_hwsim_driver); } module_exit(exit_mac80211_hwsim); diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h index d3a02e73f53a..21ca33a7c770 100644 --- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h +++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.h @@ -550,7 +550,7 @@ do { \ rxmcs == DESC92C_RATE11M) struct phy_rx_agc_info_t { - #if __LITTLE_ENDIAN + #ifdef __LITTLE_ENDIAN u8 gain:7, trsw:1; #else u8 trsw:1, gain:7; @@ -574,7 +574,7 @@ struct phy_status_rpt { u8 stream_target_csi[2]; u8 sig_evm; u8 rsvd_3; -#if __LITTLE_ENDIAN +#ifdef __LITTLE_ENDIAN u8 antsel_rx_keep_2:1; /*ex_intf_flg:1;*/ u8 sgi_en:1; u8 rxsc:2; diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 23d640a4debd..938b1e670b93 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c @@ -349,6 +349,7 @@ static struct usb_device_id rtl8192c_usb_ids[] = { {RTL_USB_DEVICE(0x07aa, 0x0056, rtl92cu_hal_cfg)}, /*ATKK-Gemtek*/ {RTL_USB_DEVICE(0x07b8, 0x8178, rtl92cu_hal_cfg)}, /*Funai -Abocom*/ {RTL_USB_DEVICE(0x0846, 0x9021, rtl92cu_hal_cfg)}, /*Netgear-Sercomm*/ + {RTL_USB_DEVICE(0x0846, 0xf001, rtl92cu_hal_cfg)}, /*On Netwrks N300MA*/ {RTL_USB_DEVICE(0x0b05, 0x17ab, rtl92cu_hal_cfg)}, /*ASUS-Edimax*/ {RTL_USB_DEVICE(0x0bda, 0x8186, rtl92cu_hal_cfg)}, /*Realtek 92CE-VAU*/ {RTL_USB_DEVICE(0x0df6, 0x0061, rtl92cu_hal_cfg)}, /*Sitecom-Edimax*/ diff --git a/drivers/nfc/Kconfig b/drivers/nfc/Kconfig index 4775d4e61b88..74a852e4e41f 100644 --- a/drivers/nfc/Kconfig +++ b/drivers/nfc/Kconfig @@ -28,7 +28,7 @@ config NFC_WILINK config NFC_MEI_PHY tristate "MEI bus NFC device support" - depends on INTEL_MEI_BUS_NFC && NFC_HCI + depends on INTEL_MEI && NFC_HCI help This adds support to use an mei bus nfc device. Select this if you will use an HCI NFC driver for an NFC chip connected behind an diff --git a/drivers/nfc/mei_phy.c b/drivers/nfc/mei_phy.c index b8f8abc422f0..1201bdbfb791 100644 --- a/drivers/nfc/mei_phy.c +++ b/drivers/nfc/mei_phy.c @@ -64,6 +64,15 @@ int nfc_mei_phy_enable(void *phy_id) return r; } + r = mei_cl_register_event_cb(phy->device, nfc_mei_event_cb, phy); + if (r) { + pr_err("MEY_PHY: Event cb registration failed\n"); + mei_cl_disable_device(phy->device); + phy->powered = 0; + + return r; + } + phy->powered = 1; return 0; diff --git a/drivers/nfc/microread/mei.c b/drivers/nfc/microread/mei.c index 1ad044dce7b6..cdf1bc53b257 100644 --- a/drivers/nfc/microread/mei.c +++ b/drivers/nfc/microread/mei.c @@ -43,24 +43,16 @@ static int microread_mei_probe(struct mei_cl_device *device, return -ENOMEM; } - r = mei_cl_register_event_cb(device, nfc_mei_event_cb, phy); - if (r) { - pr_err(MICROREAD_DRIVER_NAME ": event cb registration failed\n"); - goto err_out; - } - r = microread_probe(phy, &mei_phy_ops, LLC_NOP_NAME, MEI_NFC_HEADER_SIZE, 0, MEI_NFC_MAX_HCI_PAYLOAD, &phy->hdev); - if (r < 0) - goto err_out; - - return 0; + if (r < 0) { + nfc_mei_phy_free(phy); -err_out: - nfc_mei_phy_free(phy); + return r; + } - return r; + return 0; } static int microread_mei_remove(struct mei_cl_device *device) @@ -71,8 +63,6 @@ static int microread_mei_remove(struct mei_cl_device *device) microread_remove(phy->hdev); - nfc_mei_phy_disable(phy); - nfc_mei_phy_free(phy); return 0; diff --git a/drivers/nfc/pn544/mei.c b/drivers/nfc/pn544/mei.c index 1eb48848a35a..b5d3d18179eb 100644 --- a/drivers/nfc/pn544/mei.c +++ b/drivers/nfc/pn544/mei.c @@ -43,24 +43,16 @@ static int pn544_mei_probe(struct mei_cl_device *device, return -ENOMEM; } - r = mei_cl_register_event_cb(device, nfc_mei_event_cb, phy); - if (r) { - pr_err(PN544_DRIVER_NAME ": event cb registration failed\n"); - goto err_out; - } - r = pn544_hci_probe(phy, &mei_phy_ops, LLC_NOP_NAME, MEI_NFC_HEADER_SIZE, 0, MEI_NFC_MAX_HCI_PAYLOAD, &phy->hdev); - if (r < 0) - goto err_out; - - return 0; + if (r < 0) { + nfc_mei_phy_free(phy); -err_out: - nfc_mei_phy_free(phy); + return r; + } - return r; + return 0; } static int pn544_mei_remove(struct mei_cl_device *device) @@ -71,8 +63,6 @@ static int pn544_mei_remove(struct mei_cl_device *device) pn544_hci_remove(phy->hdev); - nfc_mei_phy_disable(phy); - nfc_mei_phy_free(phy); return 0; diff --git a/include/linux/bcma/bcma.h b/include/linux/bcma/bcma.h index f14a98a79c9d..2e34db82a643 100644 --- a/include/linux/bcma/bcma.h +++ b/include/linux/bcma/bcma.h @@ -134,7 +134,10 @@ struct bcma_host_ops { #define BCMA_CORE_I2S 0x834 #define BCMA_CORE_SDR_DDR1_MEM_CTL 0x835 /* SDR/DDR1 memory controller core */ #define BCMA_CORE_SHIM 0x837 /* SHIM component in ubus/6362 */ -#define BCMA_CORE_ARM_CR4 0x83e +#define BCMA_CORE_PHY_AC 0x83B +#define BCMA_CORE_PCIE2 0x83C /* PCI Express Gen2 */ +#define BCMA_CORE_USB30_DEV 0x83D +#define BCMA_CORE_ARM_CR4 0x83E #define BCMA_CORE_DEFAULT 0xFFF #define BCMA_MAX_NR_CORES 16 diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 04c2d4670dc6..885898a40d13 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h @@ -3043,7 +3043,8 @@ void ieee80211_napi_complete(struct ieee80211_hw *hw); * This function may not be called in IRQ context. Calls to this function * for a single hardware must be synchronized against each other. Calls to * this function, ieee80211_rx_ni() and ieee80211_rx_irqsafe() may not be - * mixed for a single hardware. + * mixed for a single hardware. Must not run concurrently with + * ieee80211_tx_status() or ieee80211_tx_status_ni(). * * In process context use instead ieee80211_rx_ni(). * @@ -3059,7 +3060,8 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb); * (internally defers to a tasklet.) * * Calls to this function, ieee80211_rx() or ieee80211_rx_ni() may not - * be mixed for a single hardware. + * be mixed for a single hardware.Must not run concurrently with + * ieee80211_tx_status() or ieee80211_tx_status_ni(). * * @hw: the hardware this frame came in on * @skb: the buffer to receive, owned by mac80211 after this call @@ -3073,7 +3075,8 @@ void ieee80211_rx_irqsafe(struct ieee80211_hw *hw, struct sk_buff *skb); * (internally disables bottom halves). * * Calls to this function, ieee80211_rx() and ieee80211_rx_irqsafe() may - * not be mixed for a single hardware. + * not be mixed for a single hardware. Must not run concurrently with + * ieee80211_tx_status() or ieee80211_tx_status_ni(). * * @hw: the hardware this frame came in on * @skb: the buffer to receive, owned by mac80211 after this call @@ -3196,7 +3199,8 @@ void ieee80211_get_tx_rates(struct ieee80211_vif *vif, * This function may not be called in IRQ context. Calls to this function * for a single hardware must be synchronized against each other. Calls * to this function, ieee80211_tx_status_ni() and ieee80211_tx_status_irqsafe() - * may not be mixed for a single hardware. + * may not be mixed for a single hardware. Must not run concurrently with + * ieee80211_rx() or ieee80211_rx_ni(). * * @hw: the hardware the frame was transmitted by * @skb: the frame that was transmitted, owned by mac80211 after this call diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 158e6eb188d3..44be28cfc6c4 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -1267,6 +1267,7 @@ void ieee80211_sta_reset_conn_monitor(struct ieee80211_sub_if_data *sdata); void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata); void ieee80211_mgd_conn_tx_status(struct ieee80211_sub_if_data *sdata, __le16 fc, bool acked); +void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata); /* IBSS code */ void ieee80211_ibss_notify_scan_completed(struct ieee80211_local *local); diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index 60f1ce5e5e52..98d20c0f6fed 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -159,9 +159,10 @@ static int ieee80211_change_mtu(struct net_device *dev, int new_mtu) return 0; } -static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr) +static int ieee80211_verify_mac(struct ieee80211_sub_if_data *sdata, u8 *addr) { - struct ieee80211_sub_if_data *sdata; + struct ieee80211_local *local = sdata->local; + struct ieee80211_sub_if_data *iter; u64 new, mask, tmp; u8 *m; int ret = 0; @@ -181,11 +182,14 @@ static int ieee80211_verify_mac(struct ieee80211_local *local, u8 *addr) mutex_lock(&local->iflist_mtx); - list_for_each_entry(sdata, &local->interfaces, list) { - if (sdata->vif.type == NL80211_IFTYPE_MONITOR) + list_for_each_entry(iter, &local->interfaces, list) { + if (iter == sdata) + continue; + + if (iter->vif.type == NL80211_IFTYPE_MONITOR) continue; - m = sdata->vif.addr; + m = iter->vif.addr; tmp = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); @@ -209,7 +213,7 @@ static int ieee80211_change_mac(struct net_device *dev, void *addr) if (ieee80211_sdata_running(sdata)) return -EBUSY; - ret = ieee80211_verify_mac(sdata->local, sa->sa_data); + ret = ieee80211_verify_mac(sdata, sa->sa_data); if (ret) return ret; @@ -474,6 +478,9 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) master->control_port_protocol; sdata->control_port_no_encrypt = master->control_port_no_encrypt; + sdata->vif.cab_queue = master->vif.cab_queue; + memcpy(sdata->vif.hw_queue, master->vif.hw_queue, + sizeof(sdata->vif.hw_queue)); break; } case NL80211_IFTYPE_AP: @@ -653,7 +660,11 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up) ieee80211_recalc_ps(local, -1); - if (dev) { + if (sdata->vif.type == NL80211_IFTYPE_MONITOR || + sdata->vif.type == NL80211_IFTYPE_AP_VLAN) { + /* XXX: for AP_VLAN, actually track AP queues */ + netif_tx_start_all_queues(dev); + } else if (dev) { unsigned long flags; int n_acs = IEEE80211_NUM_ACS; int ac; @@ -1479,7 +1490,17 @@ static void ieee80211_assign_perm_addr(struct ieee80211_local *local, break; } + /* + * Pick address of existing interface in case user changed + * MAC address manually, default to perm_addr. + */ m = local->hw.wiphy->perm_addr; + list_for_each_entry(sdata, &local->interfaces, list) { + if (sdata->vif.type == NL80211_IFTYPE_MONITOR) + continue; + m = sdata->vif.addr; + break; + } start = ((u64)m[0] << 5*8) | ((u64)m[1] << 4*8) | ((u64)m[2] << 3*8) | ((u64)m[3] << 2*8) | ((u64)m[4] << 1*8) | ((u64)m[5] << 0*8); @@ -1696,6 +1717,15 @@ void ieee80211_remove_interfaces(struct ieee80211_local *local) ASSERT_RTNL(); + /* + * Close all AP_VLAN interfaces first, as otherwise they + * might be closed while the AP interface they belong to + * is closed, causing unregister_netdevice_many() to crash. + */ + list_for_each_entry(sdata, &local->interfaces, list) + if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) + dev_close(sdata->dev); + mutex_lock(&local->iflist_mtx); list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { list_del(&sdata->list); diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 29620bfc7a69..a8c2130c8ba4 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -1015,7 +1015,8 @@ static void ieee80211_chswitch_timer(unsigned long data) static void ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, - u64 timestamp, struct ieee802_11_elems *elems) + u64 timestamp, struct ieee802_11_elems *elems, + bool beacon) { struct ieee80211_local *local = sdata->local; struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; @@ -1032,6 +1033,7 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, struct cfg80211_chan_def new_vht_chandef = {}; const struct ieee80211_sec_chan_offs_ie *sec_chan_offs; const struct ieee80211_wide_bw_chansw_ie *wide_bw_chansw_ie; + const struct ieee80211_ht_operation *ht_oper; int secondary_channel_offset = -1; ASSERT_MGD_MTX(ifmgd); @@ -1048,11 +1050,14 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, sec_chan_offs = elems->sec_chan_offs; wide_bw_chansw_ie = elems->wide_bw_chansw_ie; + ht_oper = elems->ht_operation; if (ifmgd->flags & (IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_40MHZ)) { sec_chan_offs = NULL; wide_bw_chansw_ie = NULL; + /* only used for bandwidth here */ + ht_oper = NULL; } if (ifmgd->flags & IEEE80211_STA_DISABLE_VHT) @@ -1094,10 +1099,20 @@ ieee80211_sta_process_chanswitch(struct ieee80211_sub_if_data *sdata, return; } - if (sec_chan_offs) { + if (!beacon && sec_chan_offs) { secondary_channel_offset = sec_chan_offs->sec_chan_offs; + } else if (beacon && ht_oper) { + secondary_channel_offset = + ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; } else if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT)) { - /* if HT is enabled and the IE not present, it's still HT */ + /* + * If it's not a beacon, HT is enabled and the IE not present, + * it's 20 MHz, 802.11-2012 8.5.2.6: + * This element [the Secondary Channel Offset Element] is + * present when switching to a 40 MHz channel. It may be + * present when switching to a 20 MHz channel (in which + * case the secondary channel offset is set to SCN). + */ secondary_channel_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; } @@ -2796,7 +2811,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, mutex_unlock(&local->iflist_mtx); } - ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, elems); + ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, + elems, true); } @@ -3210,7 +3226,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, - &elems); + &elems, false); } else if (mgmt->u.action.category == WLAN_CATEGORY_PUBLIC) { ies_len = skb->len - offsetof(struct ieee80211_mgmt, @@ -3232,7 +3248,7 @@ void ieee80211_sta_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata, ieee80211_sta_process_chanswitch(sdata, rx_status->mactime, - &elems); + &elems, false); } break; } @@ -3305,10 +3321,6 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) if (WARN_ON_ONCE(!auth_data)) return -EINVAL; - if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) - tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS | - IEEE80211_TX_INTFL_MLME_CONN_TX; - auth_data->tries++; if (auth_data->tries > IEEE80211_AUTH_MAX_TRIES) { @@ -3342,6 +3354,10 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) auth_data->expected_transaction = trans; } + if (local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS) + tx_flags = IEEE80211_TX_CTL_REQ_TX_STATUS | + IEEE80211_TX_INTFL_MLME_CONN_TX; + ieee80211_send_auth(sdata, trans, auth_data->algorithm, status, auth_data->data, auth_data->data_len, auth_data->bss->bssid, @@ -3365,12 +3381,12 @@ static int ieee80211_probe_auth(struct ieee80211_sub_if_data *sdata) * will not answer to direct packet in unassociated state. */ ieee80211_send_probe_req(sdata, NULL, ssidie + 2, ssidie[1], - NULL, 0, (u32) -1, true, tx_flags, + NULL, 0, (u32) -1, true, 0, auth_data->bss->channel, false); rcu_read_unlock(); } - if (!(local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)) { + if (tx_flags == 0) { auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT; ifmgd->auth_data->timeout_started = true; run_again(ifmgd, auth_data->timeout); @@ -3623,6 +3639,31 @@ static void ieee80211_restart_sta_timer(struct ieee80211_sub_if_data *sdata) } } +#ifdef CONFIG_PM +void ieee80211_sta_restart(struct ieee80211_sub_if_data *sdata) +{ + struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; + + mutex_lock(&ifmgd->mtx); + if (!ifmgd->associated) { + mutex_unlock(&ifmgd->mtx); + return; + } + + if (sdata->flags & IEEE80211_SDATA_DISCONNECT_RESUME) { + sdata->flags &= ~IEEE80211_SDATA_DISCONNECT_RESUME; + mlme_dbg(sdata, "driver requested disconnect after resume\n"); + ieee80211_sta_connection_lost(sdata, + ifmgd->associated->bssid, + WLAN_REASON_UNSPECIFIED, + true); + mutex_unlock(&ifmgd->mtx); + return; + } + mutex_unlock(&ifmgd->mtx); +} +#endif + /* interface setup */ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) { @@ -4329,7 +4370,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; u8 frame_buf[IEEE80211_DEAUTH_FRAME_LEN]; bool tx = !req->local_state_change; - bool sent_frame = false; + bool report_frame = false; mutex_lock(&ifmgd->mtx); @@ -4346,7 +4387,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, ieee80211_destroy_auth_data(sdata, false); mutex_unlock(&ifmgd->mtx); - sent_frame = tx; + report_frame = true; goto out; } @@ -4354,12 +4395,12 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata, ether_addr_equal(ifmgd->associated->bssid, req->bssid)) { ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH, req->reason_code, tx, frame_buf); - sent_frame = tx; + report_frame = true; } mutex_unlock(&ifmgd->mtx); out: - if (sent_frame) + if (report_frame) __cfg80211_send_deauth(sdata->dev, frame_buf, IEEE80211_DEAUTH_FRAME_LEN); diff --git a/net/mac80211/rate.c b/net/mac80211/rate.c index 0d51877efdb7..d3f414fe67e0 100644 --- a/net/mac80211/rate.c +++ b/net/mac80211/rate.c @@ -688,8 +688,15 @@ int rate_control_set_rates(struct ieee80211_hw *hw, struct ieee80211_sta *pubsta, struct ieee80211_sta_rates *rates) { - struct ieee80211_sta_rates *old = rcu_dereference(pubsta->rates); + struct ieee80211_sta_rates *old; + /* + * mac80211 guarantees that this function will not be called + * concurrently, so the following RCU access is safe, even without + * extra locking. This can not be checked easily, so we just set + * the condition to true. + */ + old = rcu_dereference_protected(pubsta->rates, true); rcu_assign_pointer(pubsta->rates, rates); if (old) kfree_rcu(old, rcu_head); diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index c8447af76ead..8e2952620256 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c @@ -3036,6 +3036,9 @@ static int prepare_for_handlers(struct ieee80211_rx_data *rx, * and location updates. Note that mac80211 * itself never looks at these frames. */ + if (!multicast && + !ether_addr_equal(sdata->vif.addr, hdr->addr1)) + return 0; if (ieee80211_is_public_action(hdr, skb->len)) return 1; if (!ieee80211_is_beacon(hdr->frame_control)) diff --git a/net/mac80211/tkip.c b/net/mac80211/tkip.c index 3ed801d90f1e..124b1fdc20d0 100644 --- a/net/mac80211/tkip.c +++ b/net/mac80211/tkip.c @@ -208,10 +208,10 @@ void ieee80211_get_tkip_p2k(struct ieee80211_key_conf *keyconf, u32 iv32 = get_unaligned_le32(&data[4]); u16 iv16 = data[2] | (data[0] << 8); - spin_lock_bh(&key->u.tkip.txlock); + spin_lock(&key->u.tkip.txlock); ieee80211_compute_tkip_p1k(key, iv32); tkip_mixing_phase2(tk, ctx, iv16, p2k); - spin_unlock_bh(&key->u.tkip.txlock); + spin_unlock(&key->u.tkip.txlock); } EXPORT_SYMBOL(ieee80211_get_tkip_p2k); diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 3f87fa468b1f..27e07150eb46 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -1740,6 +1740,13 @@ int ieee80211_reconfig(struct ieee80211_local *local) mb(); local->resuming = false; + list_for_each_entry(sdata, &local->interfaces, list) { + if (!ieee80211_sdata_running(sdata)) + continue; + if (sdata->vif.type == NL80211_IFTYPE_STATION) + ieee80211_sta_restart(sdata); + } + mod_timer(&local->sta_cleanup, jiffies + 1); #else WARN_ON(1); diff --git a/net/nfc/Makefile b/net/nfc/Makefile index fb799deaed4f..a76f4533cb6c 100644 --- a/net/nfc/Makefile +++ b/net/nfc/Makefile @@ -5,7 +5,6 @@ obj-$(CONFIG_NFC) += nfc.o obj-$(CONFIG_NFC_NCI) += nci/ obj-$(CONFIG_NFC_HCI) += hci/ -#obj-$(CONFIG_NFC_LLCP) += llcp/ nfc-objs := core.o netlink.o af_nfc.o rawsock.o llcp_core.o llcp_commands.o \ llcp_sock.o diff --git a/net/wireless/core.c b/net/wireless/core.c index 84c9ad7e1dca..73405e00c800 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c @@ -638,17 +638,21 @@ int wiphy_register(struct wiphy *wiphy) * cfg80211_mutex lock */ res = rfkill_register(rdev->rfkill); - if (res) - goto out_rm_dev; + if (res) { + device_del(&rdev->wiphy.dev); + + mutex_lock(&cfg80211_mutex); + debugfs_remove_recursive(rdev->wiphy.debugfsdir); + list_del_rcu(&rdev->list); + wiphy_regulatory_deregister(wiphy); + mutex_unlock(&cfg80211_mutex); + return res; + } rtnl_lock(); rdev->wiphy.registered = true; rtnl_unlock(); return 0; - -out_rm_dev: - device_del(&rdev->wiphy.dev); - return res; } EXPORT_SYMBOL(wiphy_register); @@ -866,7 +870,6 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, #endif __cfg80211_disconnect(rdev, dev, WLAN_REASON_DEAUTH_LEAVING, true); - cfg80211_mlme_down(rdev, dev); wdev_unlock(wdev); break; case NL80211_IFTYPE_MESH_POINT: diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index afa283841e8c..d5aed3bb3945 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -3411,7 +3411,7 @@ static int nl80211_send_station(struct sk_buff *msg, u32 portid, u32 seq, (u32)sinfo->rx_bytes)) goto nla_put_failure; if ((sinfo->filled & (STATION_INFO_TX_BYTES | - NL80211_STA_INFO_TX_BYTES64)) && + STATION_INFO_TX_BYTES64)) && nla_put_u32(msg, NL80211_STA_INFO_TX_BYTES, (u32)sinfo->tx_bytes)) goto nla_put_failure; @@ -7577,6 +7577,8 @@ static int nl80211_send_wowlan_tcp(struct sk_buff *msg, &tcp->payload_tok)) return -ENOBUFS; + nla_nest_end(msg, nl_tcp); + return 0; } @@ -9970,6 +9972,7 @@ int nl80211_send_mgmt(struct cfg80211_registered_device *rdev, if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) || + nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) || nla_put_u32(msg, NL80211_ATTR_WIPHY_FREQ, freq) || (sig_dbm && nla_put_u32(msg, NL80211_ATTR_RX_SIGNAL_DBM, sig_dbm)) || @@ -10010,6 +10013,7 @@ void cfg80211_mgmt_tx_status(struct wireless_dev *wdev, u64 cookie, if (nla_put_u32(msg, NL80211_ATTR_WIPHY, rdev->wiphy_idx) || (netdev && nla_put_u32(msg, NL80211_ATTR_IFINDEX, netdev->ifindex)) || + nla_put_u64(msg, NL80211_ATTR_WDEV, wdev_id(wdev)) || nla_put(msg, NL80211_ATTR_FRAME, len, buf) || nla_put_u64(msg, NL80211_ATTR_COOKIE, cookie) || (ack && nla_put_flag(msg, NL80211_ATTR_ACK))) diff --git a/net/wireless/sme.c b/net/wireless/sme.c index a9dc5c736df0..3ed35c345cae 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -231,6 +231,9 @@ void cfg80211_conn_work(struct work_struct *work) mutex_lock(&rdev->sched_scan_mtx); list_for_each_entry(wdev, &rdev->wdev_list, list) { + if (!wdev->netdev) + continue; + wdev_lock(wdev); if (!netif_running(wdev->netdev)) { wdev_unlock(wdev); @@ -961,7 +964,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, /* was it connected by userspace SME? */ if (!wdev->conn) { cfg80211_mlme_down(rdev, dev); - return 0; + goto disconnect; } if (wdev->sme_state == CFG80211_SME_CONNECTING && @@ -987,6 +990,7 @@ int __cfg80211_disconnect(struct cfg80211_registered_device *rdev, return err; } + disconnect: if (wdev->sme_state == CFG80211_SME_CONNECTED) __cfg80211_disconnected(dev, NULL, 0, 0, false); else if (wdev->sme_state == CFG80211_SME_CONNECTING) diff --git a/net/wireless/trace.h b/net/wireless/trace.h index ecd4fcec3c94..5755bc14abbd 100644 --- a/net/wireless/trace.h +++ b/net/wireless/trace.h @@ -2441,6 +2441,7 @@ TRACE_EVENT(cfg80211_report_wowlan_wakeup, TP_STRUCT__entry( WIPHY_ENTRY WDEV_ENTRY + __field(bool, non_wireless) __field(bool, disconnect) __field(bool, magic_pkt) __field(bool, gtk_rekey_failure) @@ -2449,20 +2450,22 @@ TRACE_EVENT(cfg80211_report_wowlan_wakeup, __field(bool, rfkill_release) __field(s32, pattern_idx) __field(u32, packet_len) - __dynamic_array(u8, packet, wakeup->packet_present_len) + __dynamic_array(u8, packet, + wakeup ? wakeup->packet_present_len : 0) ), TP_fast_assign( WIPHY_ASSIGN; WDEV_ASSIGN; - __entry->disconnect = wakeup->disconnect; - __entry->magic_pkt = wakeup->magic_pkt; - __entry->gtk_rekey_failure = wakeup->gtk_rekey_failure; - __entry->eap_identity_req = wakeup->eap_identity_req; - __entry->four_way_handshake = wakeup->four_way_handshake; - __entry->rfkill_release = wakeup->rfkill_release; - __entry->pattern_idx = wakeup->pattern_idx; - __entry->packet_len = wakeup->packet_len; - if (wakeup->packet && wakeup->packet_present_len) + __entry->non_wireless = !wakeup; + __entry->disconnect = wakeup ? wakeup->disconnect : false; + __entry->magic_pkt = wakeup ? wakeup->magic_pkt : false; + __entry->gtk_rekey_failure = wakeup ? wakeup->gtk_rekey_failure : false; + __entry->eap_identity_req = wakeup ? wakeup->eap_identity_req : false; + __entry->four_way_handshake = wakeup ? wakeup->four_way_handshake : false; + __entry->rfkill_release = wakeup ? wakeup->rfkill_release : false; + __entry->pattern_idx = wakeup ? wakeup->pattern_idx : false; + __entry->packet_len = wakeup ? wakeup->packet_len : false; + if (wakeup && wakeup->packet && wakeup->packet_present_len) memcpy(__get_dynamic_array(packet), wakeup->packet, wakeup->packet_present_len); ), |