X-Git-Url: https://git.rohieb.name/openwrt.git/blobdiff_plain/bc3305d88ecd77f0812383a5e771824a014444b6..5e10b16d95550d4656d8b594f3cbb6a3892db688:/package/mac80211/patches/300-pending_work.patch diff --git a/package/mac80211/patches/300-pending_work.patch b/package/mac80211/patches/300-pending_work.patch index 74acba566..f06e9df99 100644 --- a/package/mac80211/patches/300-pending_work.patch +++ b/package/mac80211/patches/300-pending_work.patch @@ -1,353 +1,619 @@ ---- a/drivers/net/wireless/ath/ath9k/main.c -+++ b/drivers/net/wireless/ath/ath9k/main.c -@@ -324,7 +324,6 @@ static void ath_paprd_activate(struct at - if (!caldata || !caldata->paprd_done) - return; - -- ath9k_ps_wakeup(sc); - ar9003_paprd_enable(ah, false); - for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { - if (!(common->tx_chainmask & BIT(chain))) -@@ -334,7 +333,6 @@ static void ath_paprd_activate(struct at - } - - ar9003_paprd_enable(ah, true); -- ath9k_ps_restore(sc); +--- a/net/wireless/reg.c ++++ b/net/wireless/reg.c +@@ -1456,7 +1456,8 @@ static void reg_process_hint(struct regu + * We only time out user hints, given that they should be the only + * source of bogus requests. + */ +- if (reg_request->initiator == NL80211_REGDOM_SET_BY_USER) ++ if (r != -EALREADY && ++ reg_request->initiator == NL80211_REGDOM_SET_BY_USER) + schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); } - static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int chain) -@@ -554,8 +552,11 @@ set_timer: - if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) { - if (!ah->caldata->paprd_done) - ieee80211_queue_work(sc->hw, &sc->paprd_work); -- else if (!ah->paprd_table_write_done) -+ else if (!ah->paprd_table_write_done) { -+ ath9k_ps_wakeup(sc); - ath_paprd_activate(sc); -+ ath9k_ps_restore(sc); -+ } - } +--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c ++++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c +@@ -18,13 +18,13 @@ + #include "hw-ops.h" + #include "ar9003_phy.h" + +-#define MPASS 3 + #define MAX_MEASUREMENT 8 +-#define MAX_DIFFERENCE 10 ++#define MAX_MAG_DELTA 11 ++#define MAX_PHS_DELTA 10 + + struct coeff { +- int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS]; +- int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MPASS]; ++ int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]; ++ int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT]; + int iqc_coeff[2]; + }; + +@@ -608,36 +608,48 @@ static bool ar9003_hw_calc_iq_corr(struc + return true; } -@@ -1376,7 +1377,6 @@ static void ath9k_calculate_summary_stat - - ath9k_calculate_iter_data(hw, vif, &iter_data); - -- ath9k_ps_wakeup(sc); - /* Set BSSID mask. */ - memcpy(common->bssidmask, iter_data.mask, ETH_ALEN); - ath_hw_setbssidmask(common); -@@ -1411,7 +1411,6 @@ static void ath9k_calculate_summary_stat - } - - ath9k_hw_set_interrupts(ah, ah->imask); -- ath9k_ps_restore(sc); - - /* Set up ANI */ - if ((iter_data.naps + iter_data.nadhocs) > 0) { -@@ -1457,6 +1456,7 @@ static int ath9k_add_interface(struct ie - struct ath_vif *avp = (void *)vif->drv_priv; - int ret = 0; - -+ ath9k_ps_wakeup(sc); - mutex_lock(&sc->mutex); - - switch (vif->type) { -@@ -1503,6 +1503,7 @@ static int ath9k_add_interface(struct ie - ath9k_do_vif_add_setup(hw, vif); - out: - mutex_unlock(&sc->mutex); -+ ath9k_ps_restore(sc); - return ret; - } - -@@ -1517,6 +1518,7 @@ static int ath9k_change_interface(struct - - ath_dbg(common, ATH_DBG_CONFIG, "Change Interface\n"); - mutex_lock(&sc->mutex); -+ ath9k_ps_wakeup(sc); - - /* See if new interface type is valid. */ - if ((new_type == NL80211_IFTYPE_ADHOC) && -@@ -1546,6 +1548,7 @@ static int ath9k_change_interface(struct +-static bool ar9003_hw_compute_closest_pass_and_avg(int *mp_coeff, int *mp_avg) ++static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement, ++ int max_delta) + { +- int diff[MPASS]; +- +- diff[0] = abs(mp_coeff[0] - mp_coeff[1]); +- diff[1] = abs(mp_coeff[1] - mp_coeff[2]); +- diff[2] = abs(mp_coeff[2] - mp_coeff[0]); +- +- if (diff[0] > MAX_DIFFERENCE && +- diff[1] > MAX_DIFFERENCE && +- diff[2] > MAX_DIFFERENCE) +- return false; +- +- if (diff[0] <= diff[1] && diff[0] <= diff[2]) +- *mp_avg = (mp_coeff[0] + mp_coeff[1]) / 2; +- else if (diff[1] <= diff[2]) +- *mp_avg = (mp_coeff[1] + mp_coeff[2]) / 2; +- else +- *mp_avg = (mp_coeff[2] + mp_coeff[0]) / 2; ++ int mp_max = -64, max_idx = 0; ++ int mp_min = 63, min_idx = 0; ++ int mp_avg = 0, i, outlier_idx = 0; ++ ++ /* find min/max mismatch across all calibrated gains */ ++ for (i = 0; i < nmeasurement; i++) { ++ mp_avg += mp_coeff[i]; ++ if (mp_coeff[i] > mp_max) { ++ mp_max = mp_coeff[i]; ++ max_idx = i; ++ } else if (mp_coeff[i] < mp_min) { ++ mp_min = mp_coeff[i]; ++ min_idx = i; ++ } ++ } - ath9k_do_vif_add_setup(hw, vif); - out: -+ ath9k_ps_restore(sc); - mutex_unlock(&sc->mutex); - return ret; +- return true; ++ /* find average (exclude max abs value) */ ++ for (i = 0; i < nmeasurement; i++) { ++ if ((abs(mp_coeff[i]) < abs(mp_max)) || ++ (abs(mp_coeff[i]) < abs(mp_min))) ++ mp_avg += mp_coeff[i]; ++ } ++ mp_avg /= (nmeasurement - 1); ++ ++ /* detect outlier */ ++ if (abs(mp_max - mp_min) > max_delta) { ++ if (abs(mp_max - mp_avg) > abs(mp_min - mp_avg)) ++ outlier_idx = max_idx; ++ else ++ outlier_idx = min_idx; ++ } ++ mp_coeff[outlier_idx] = mp_avg; } -@@ -1558,6 +1561,7 @@ static void ath9k_remove_interface(struc - - ath_dbg(common, ATH_DBG_CONFIG, "Detach Interface\n"); -+ ath9k_ps_wakeup(sc); - mutex_lock(&sc->mutex); - - sc->nvifs--; -@@ -1569,6 +1573,7 @@ static void ath9k_remove_interface(struc - ath9k_calculate_summary_state(hw, NULL); + static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah, + u8 num_chains, + struct coeff *coeff) + { +- struct ath_common *common = ath9k_hw_common(ah); + int i, im, nmeasurement; +- int magnitude, phase; + u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS]; + + memset(tx_corr_coeff, 0, sizeof(tx_corr_coeff)); +@@ -657,37 +669,28 @@ static void ar9003_hw_tx_iqcal_load_avg_ + + /* Load the average of 2 passes */ + for (i = 0; i < num_chains; i++) { +- if (AR_SREV_9485(ah)) +- nmeasurement = REG_READ_FIELD(ah, +- AR_PHY_TX_IQCAL_STATUS_B0_9485, +- AR_PHY_CALIBRATED_GAINS_0); +- else +- nmeasurement = REG_READ_FIELD(ah, +- AR_PHY_TX_IQCAL_STATUS_B0, +- AR_PHY_CALIBRATED_GAINS_0); ++ nmeasurement = REG_READ_FIELD(ah, ++ AR_PHY_TX_IQCAL_STATUS_B0, ++ AR_PHY_CALIBRATED_GAINS_0); + + if (nmeasurement > MAX_MEASUREMENT) + nmeasurement = MAX_MEASUREMENT; + +- for (im = 0; im < nmeasurement; im++) { +- /* +- * Determine which 2 passes are closest and compute avg +- * magnitude +- */ +- if (!ar9003_hw_compute_closest_pass_and_avg(coeff->mag_coeff[i][im], +- &magnitude)) +- goto disable_txiqcal; ++ /* detect outlier only if nmeasurement > 1 */ ++ if (nmeasurement > 1) { ++ /* Detect magnitude outlier */ ++ ar9003_hw_detect_outlier(coeff->mag_coeff[i], ++ nmeasurement, MAX_MAG_DELTA); ++ ++ /* Detect phase outlier */ ++ ar9003_hw_detect_outlier(coeff->phs_coeff[i], ++ nmeasurement, MAX_PHS_DELTA); ++ } - mutex_unlock(&sc->mutex); -+ ath9k_ps_restore(sc); +- /* +- * Determine which 2 passes are closest and compute avg +- * phase +- */ +- if (!ar9003_hw_compute_closest_pass_and_avg(coeff->phs_coeff[i][im], +- &phase)) +- goto disable_txiqcal; ++ for (im = 0; im < nmeasurement; im++) { + +- coeff->iqc_coeff[0] = (magnitude & 0x7f) | +- ((phase & 0x7f) << 7); ++ coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) | ++ ((coeff->phs_coeff[i][im] & 0x7f) << 7); + + if ((im % 2) == 0) + REG_RMW_FIELD(ah, tx_corr_coeff[im][i], +@@ -707,141 +710,37 @@ static void ar9003_hw_tx_iqcal_load_avg_ + + return; + +-disable_txiqcal: +- REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_3, +- AR_PHY_TX_IQCAL_CONTROL_3_IQCORR_EN, 0x0); +- REG_RMW_FIELD(ah, AR_PHY_RX_IQCAL_CORR_B0, +- AR_PHY_RX_IQCAL_CORR_B0_LOOPBACK_IQCORR_EN, 0x0); +- +- ath_dbg(common, ATH_DBG_CALIBRATE, "TX IQ Cal disabled\n"); } - static void ath9k_enable_ps(struct ath_softc *sc) -@@ -1809,6 +1814,7 @@ static int ath9k_conf_tx(struct ieee8021 - - txq = sc->tx.txq_map[queue]; - -+ ath9k_ps_wakeup(sc); - mutex_lock(&sc->mutex); - - memset(&qi, 0, sizeof(struct ath9k_tx_queue_info)); -@@ -1832,6 +1838,7 @@ static int ath9k_conf_tx(struct ieee8021 - ath_beaconq_config(sc); - - mutex_unlock(&sc->mutex); -+ ath9k_ps_restore(sc); - - return ret; +-static void ar9003_hw_tx_iq_cal(struct ath_hw *ah) ++static bool ar9003_hw_tx_iq_cal_run(struct ath_hw *ah) + { + struct ath_common *common = ath9k_hw_common(ah); +- static const u32 txiqcal_status[AR9300_MAX_CHAINS] = { +- AR_PHY_TX_IQCAL_STATUS_B0, +- AR_PHY_TX_IQCAL_STATUS_B1, +- AR_PHY_TX_IQCAL_STATUS_B2, +- }; +- static const u32 chan_info_tab[] = { +- AR_PHY_CHAN_INFO_TAB_0, +- AR_PHY_CHAN_INFO_TAB_1, +- AR_PHY_CHAN_INFO_TAB_2, +- }; +- struct coeff coeff; +- s32 iq_res[6]; +- s32 i, j, ip, im, nmeasurement; +- u8 nchains = get_streams(common->tx_chainmask); +- +- for (ip = 0; ip < MPASS; ip++) { +- REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, +- AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, +- DELPT); +- REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START, +- AR_PHY_TX_IQCAL_START_DO_CAL, +- AR_PHY_TX_IQCAL_START_DO_CAL); +- +- if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START, +- AR_PHY_TX_IQCAL_START_DO_CAL, +- 0, AH_WAIT_TIMEOUT)) { +- ath_dbg(common, ATH_DBG_CALIBRATE, +- "Tx IQ Cal not complete.\n"); +- goto TX_IQ_CAL_FAILED; +- } +- +- nmeasurement = REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_STATUS_B0, +- AR_PHY_CALIBRATED_GAINS_0); +- if (nmeasurement > MAX_MEASUREMENT) +- nmeasurement = MAX_MEASUREMENT; +- +- for (i = 0; i < nchains; i++) { +- ath_dbg(common, ATH_DBG_CALIBRATE, +- "Doing Tx IQ Cal for chain %d.\n", i); +- for (im = 0; im < nmeasurement; im++) { +- if (REG_READ(ah, txiqcal_status[i]) & +- AR_PHY_TX_IQCAL_STATUS_FAILED) { +- ath_dbg(common, ATH_DBG_CALIBRATE, +- "Tx IQ Cal failed for chain %d.\n", i); +- goto TX_IQ_CAL_FAILED; +- } +- +- for (j = 0; j < 3; j++) { +- u8 idx = 2 * j, +- offset = 4 * (3 * im + j); +- +- REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, +- AR_PHY_CHAN_INFO_TAB_S2_READ, +- 0); +- +- /* 32 bits */ +- iq_res[idx] = REG_READ(ah, +- chan_info_tab[i] + +- offset); +- +- REG_RMW_FIELD(ah, AR_PHY_CHAN_INFO_MEMORY, +- AR_PHY_CHAN_INFO_TAB_S2_READ, +- 1); +- +- /* 16 bits */ +- iq_res[idx+1] = 0xffff & REG_READ(ah, +- chan_info_tab[i] + +- offset); +- +- ath_dbg(common, ATH_DBG_CALIBRATE, +- "IQ RES[%d]=0x%x IQ_RES[%d]=0x%x\n", +- idx, iq_res[idx], idx+1, iq_res[idx+1]); +- } +- +- if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, +- coeff.iqc_coeff)) { +- ath_dbg(common, ATH_DBG_CALIBRATE, +- "Failed in calculation of IQ correction.\n"); +- goto TX_IQ_CAL_FAILED; +- } +- coeff.mag_coeff[i][im][ip] = +- coeff.iqc_coeff[0] & 0x7f; +- coeff.phs_coeff[i][im][ip] = +- (coeff.iqc_coeff[0] >> 7) & 0x7f; +- +- if (coeff.mag_coeff[i][im][ip] > 63) +- coeff.mag_coeff[i][im][ip] -= 128; +- if (coeff.phs_coeff[i][im][ip] > 63) +- coeff.phs_coeff[i][im][ip] -= 128; +- +- } +- } +- } +- +- ar9003_hw_tx_iqcal_load_avg_2_passes(ah, nchains, &coeff); +- +- return; +- +-TX_IQ_CAL_FAILED: +- ath_dbg(common, ATH_DBG_CALIBRATE, "Tx IQ Cal failed\n"); +-} +- +-static void ar9003_hw_tx_iq_cal_run(struct ath_hw *ah) +-{ + u8 tx_gain_forced; + +- REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1_9485, +- AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, DELPT); + tx_gain_forced = REG_READ_FIELD(ah, AR_PHY_TX_FORCED_GAIN, + AR_PHY_TXGAIN_FORCE); + if (tx_gain_forced) + REG_RMW_FIELD(ah, AR_PHY_TX_FORCED_GAIN, + AR_PHY_TXGAIN_FORCE, 0); + +- REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START_9485, +- AR_PHY_TX_IQCAL_START_DO_CAL_9485, 1); ++ REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_START, ++ AR_PHY_TX_IQCAL_START_DO_CAL, 1); ++ ++ if (!ath9k_hw_wait(ah, AR_PHY_TX_IQCAL_START, ++ AR_PHY_TX_IQCAL_START_DO_CAL, 0, ++ AH_WAIT_TIMEOUT)) { ++ ath_dbg(common, ATH_DBG_CALIBRATE, ++ "Tx IQ Cal is not completed.\n"); ++ return false; ++ } ++ return true; } -@@ -1908,6 +1915,7 @@ static void ath9k_bss_info_changed(struc - int slottime; - int error; - -+ ath9k_ps_wakeup(sc); - mutex_lock(&sc->mutex); - if (changed & BSS_CHANGED_BSSID) { -@@ -2008,6 +2016,7 @@ static void ath9k_bss_info_changed(struc + static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah) + { + struct ath_common *common = ath9k_hw_common(ah); + const u32 txiqcal_status[AR9300_MAX_CHAINS] = { +- AR_PHY_TX_IQCAL_STATUS_B0_9485, ++ AR_PHY_TX_IQCAL_STATUS_B0, + AR_PHY_TX_IQCAL_STATUS_B1, + AR_PHY_TX_IQCAL_STATUS_B2, + }; +@@ -853,7 +752,7 @@ static void ar9003_hw_tx_iq_cal_post_pro + struct coeff coeff; + s32 iq_res[6]; + u8 num_chains = 0; +- int i, ip, im, j; ++ int i, im, j; + int nmeasurement; + + for (i = 0; i < AR9300_MAX_CHAINS; i++) { +@@ -861,71 +760,69 @@ static void ar9003_hw_tx_iq_cal_post_pro + num_chains++; } - mutex_unlock(&sc->mutex); -+ ath9k_ps_restore(sc); - } +- for (ip = 0; ip < MPASS; ip++) { +- for (i = 0; i < num_chains; i++) { +- nmeasurement = REG_READ_FIELD(ah, +- AR_PHY_TX_IQCAL_STATUS_B0_9485, +- AR_PHY_CALIBRATED_GAINS_0); +- if (nmeasurement > MAX_MEASUREMENT) +- nmeasurement = MAX_MEASUREMENT; ++ for (i = 0; i < num_chains; i++) { ++ nmeasurement = REG_READ_FIELD(ah, ++ AR_PHY_TX_IQCAL_STATUS_B0, ++ AR_PHY_CALIBRATED_GAINS_0); ++ if (nmeasurement > MAX_MEASUREMENT) ++ nmeasurement = MAX_MEASUREMENT; ++ ++ for (im = 0; im < nmeasurement; im++) { ++ ath_dbg(common, ATH_DBG_CALIBRATE, ++ "Doing Tx IQ Cal for chain %d.\n", i); + +- for (im = 0; im < nmeasurement; im++) { ++ if (REG_READ(ah, txiqcal_status[i]) & ++ AR_PHY_TX_IQCAL_STATUS_FAILED) { + ath_dbg(common, ATH_DBG_CALIBRATE, +- "Doing Tx IQ Cal for chain %d.\n", i); +- +- if (REG_READ(ah, txiqcal_status[i]) & +- AR_PHY_TX_IQCAL_STATUS_FAILED) { +- ath_dbg(common, ATH_DBG_CALIBRATE, + "Tx IQ Cal failed for chain %d.\n", i); +- goto tx_iqcal_fail; +- } ++ goto tx_iqcal_fail; ++ } - static u64 ath9k_get_tsf(struct ieee80211_hw *hw) ---- a/drivers/net/wireless/ath/ath9k/beacon.c -+++ b/drivers/net/wireless/ath/ath9k/beacon.c -@@ -392,14 +392,6 @@ void ath_beacon_tasklet(unsigned long da - tsf += TU_TO_USEC(ah->config.sw_beacon_response_time); - tsftu = TSF_TO_TU((tsf * ATH_BCBUF) >>32, tsf * ATH_BCBUF); - slot = (tsftu % (intval * ATH_BCBUF)) / intval; -- /* -- * Reverse the slot order to get slot 0 on the TBTT offset that does -- * not require TSF adjustment and other slots adding -- * slot/ATH_BCBUF * beacon_int to timestamp. For example, with -- * ATH_BCBUF = 4, we process beacon slots as follows: 3 2 1 0 3 2 1 .. -- * and slot 0 is at correct offset to TBTT. -- */ -- slot = ATH_BCBUF - slot - 1; - vif = sc->beacon.bslot[slot]; - - ath_dbg(common, ATH_DBG_BEACON, -@@ -708,7 +700,7 @@ void ath_beacon_config(struct ath_softc - if (cur_conf->dtim_period == 0) - cur_conf->dtim_period = 1; - -- switch (iftype) { -+ switch (sc->sc_ah->opmode) { - case NL80211_IFTYPE_AP: - ath_beacon_config_ap(sc, cur_conf); - break; ---- a/net/mac80211/rx.c -+++ b/net/mac80211/rx.c -@@ -1585,7 +1585,7 @@ ieee80211_drop_unencrypted_mgmt(struct i - } +- for (j = 0; j < 3; j++) { +- u32 idx = 2 * j, offset = 4 * (3 * im + j); ++ for (j = 0; j < 3; j++) { ++ u32 idx = 2 * j, offset = 4 * (3 * im + j); + +- REG_RMW_FIELD(ah, ++ REG_RMW_FIELD(ah, + AR_PHY_CHAN_INFO_MEMORY, + AR_PHY_CHAN_INFO_TAB_S2_READ, + 0); + +- /* 32 bits */ +- iq_res[idx] = REG_READ(ah, +- chan_info_tab[i] + +- offset); ++ /* 32 bits */ ++ iq_res[idx] = REG_READ(ah, ++ chan_info_tab[i] + ++ offset); + +- REG_RMW_FIELD(ah, ++ REG_RMW_FIELD(ah, + AR_PHY_CHAN_INFO_MEMORY, + AR_PHY_CHAN_INFO_TAB_S2_READ, + 1); + +- /* 16 bits */ +- iq_res[idx + 1] = 0xffff & REG_READ(ah, +- chan_info_tab[i] + offset); +- +- ath_dbg(common, ATH_DBG_CALIBRATE, +- "IQ RES[%d]=0x%x" +- "IQ_RES[%d]=0x%x\n", +- idx, iq_res[idx], idx + 1, +- iq_res[idx + 1]); +- } ++ /* 16 bits */ ++ iq_res[idx + 1] = 0xffff & REG_READ(ah, ++ chan_info_tab[i] + offset); + +- if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, +- coeff.iqc_coeff)) { +- ath_dbg(common, ATH_DBG_CALIBRATE, +- "Failed in calculation of IQ correction.\n"); +- goto tx_iqcal_fail; +- } ++ ath_dbg(common, ATH_DBG_CALIBRATE, ++ "IQ RES[%d]=0x%x" ++ "IQ_RES[%d]=0x%x\n", ++ idx, iq_res[idx], idx + 1, ++ iq_res[idx + 1]); ++ } - static int --__ieee80211_data_to_8023(struct ieee80211_rx_data *rx) -+__ieee80211_data_to_8023(struct ieee80211_rx_data *rx, bool *port_control) +- coeff.mag_coeff[i][im][ip] = +- coeff.iqc_coeff[0] & 0x7f; +- coeff.phs_coeff[i][im][ip] = +- (coeff.iqc_coeff[0] >> 7) & 0x7f; +- +- if (coeff.mag_coeff[i][im][ip] > 63) +- coeff.mag_coeff[i][im][ip] -= 128; +- if (coeff.phs_coeff[i][im][ip] > 63) +- coeff.phs_coeff[i][im][ip] -= 128; ++ if (!ar9003_hw_calc_iq_corr(ah, i, iq_res, ++ coeff.iqc_coeff)) { ++ ath_dbg(common, ATH_DBG_CALIBRATE, ++ "Failed in calculation of \ ++ IQ correction.\n"); ++ goto tx_iqcal_fail; + } ++ ++ coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f; ++ coeff.phs_coeff[i][im] = ++ (coeff.iqc_coeff[0] >> 7) & 0x7f; ++ ++ if (coeff.mag_coeff[i][im] > 63) ++ coeff.mag_coeff[i][im] -= 128; ++ if (coeff.phs_coeff[i][im] > 63) ++ coeff.phs_coeff[i][im] -= 128; + } + } + ar9003_hw_tx_iqcal_load_avg_2_passes(ah, num_chains, &coeff); +@@ -941,6 +838,7 @@ static bool ar9003_hw_init_cal(struct at { - struct ieee80211_sub_if_data *sdata = rx->sdata; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; -@@ -1593,6 +1593,7 @@ __ieee80211_data_to_8023(struct ieee8021 - struct ethhdr *ehdr; - int ret; - -+ *port_control = false; - if (ieee80211_has_a4(hdr->frame_control) && - sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta) - return -1; -@@ -1611,11 +1612,13 @@ __ieee80211_data_to_8023(struct ieee8021 - return -1; - - ret = ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type); -- if (ret < 0 || !check_port_control) -+ if (ret < 0) - return ret; - - ehdr = (struct ethhdr *) rx->skb->data; -- if (ehdr->h_proto != rx->sdata->control_port_protocol) -+ if (ehdr->h_proto == rx->sdata->control_port_protocol) -+ *port_control = true; -+ else if (check_port_control) - return -1; - - return 0; -@@ -1916,6 +1919,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_ - struct net_device *dev = sdata->dev; - struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data; - __le16 fc = hdr->frame_control; -+ bool port_control; - int err; - - if (unlikely(!ieee80211_is_data(hdr->frame_control))) -@@ -1932,13 +1936,21 @@ ieee80211_rx_h_data(struct ieee80211_rx_ - sdata->vif.type == NL80211_IFTYPE_AP) - return RX_DROP_MONITOR; - -- err = __ieee80211_data_to_8023(rx); -+ err = __ieee80211_data_to_8023(rx, &port_control); - if (unlikely(err)) - return RX_DROP_UNUSABLE; - - if (!ieee80211_frame_allowed(rx, fc)) - return RX_DROP_MONITOR; - -+ if (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && -+ unlikely(port_control) && sdata->bss) { -+ sdata = container_of(sdata->bss, struct ieee80211_sub_if_data, -+ u.ap); -+ dev = sdata->dev; -+ rx->sdata = sdata; + struct ath_common *common = ath9k_hw_common(ah); + int val; ++ bool txiqcal_done = false; + + val = REG_READ(ah, AR_ENT_OTP); + ath_dbg(common, ATH_DBG_CALIBRATE, "ath9k: AR_ENT_OTP 0x%x\n", val); +@@ -957,14 +855,22 @@ static bool ar9003_hw_init_cal(struct at + ar9003_hw_set_chain_masks(ah, 0x7, 0x7); + + /* Do Tx IQ Calibration */ +- if (AR_SREV_9485(ah)) +- ar9003_hw_tx_iq_cal_run(ah); +- else +- ar9003_hw_tx_iq_cal(ah); ++ REG_RMW_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_1, ++ AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT, ++ DELPT); + +- REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); +- udelay(5); +- REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); ++ /* ++ * For AR9485 or later chips, TxIQ cal runs as part of ++ * AGC calibration ++ */ ++ if (AR_SREV_9485_OR_LATER(ah)) ++ txiqcal_done = true; ++ else { ++ txiqcal_done = ar9003_hw_tx_iq_cal_run(ah); ++ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_DIS); ++ udelay(5); ++ REG_WRITE(ah, AR_PHY_ACTIVE, AR_PHY_ACTIVE_EN); + } -+ - rx->skb->dev = dev; - - dev->stats.rx_packets++; ---- a/drivers/net/wireless/ath/ath9k/recv.c -+++ b/drivers/net/wireless/ath/ath9k/recv.c -@@ -75,7 +75,6 @@ static void ath_rx_buf_link(struct ath_s - *sc->rx.rxlink = bf->bf_daddr; - sc->rx.rxlink = &ds->ds_link; -- ath9k_hw_rxena(ah); - } + /* Calibrate the AGC */ + REG_WRITE(ah, AR_PHY_AGC_CONTROL, +@@ -979,7 +885,7 @@ static bool ar9003_hw_init_cal(struct at + return false; + } - static void ath_setdefantenna(struct ath_softc *sc, u32 antenna) -@@ -426,9 +425,7 @@ u32 ath_calcrxfilter(struct ath_softc *s - else - rfilt |= ATH9K_RX_FILTER_BEACON; +- if (AR_SREV_9485(ah)) ++ if (txiqcal_done) + ar9003_hw_tx_iq_cal_post_proc(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) && -+ if ((sc->sc_ah->opmode == NL80211_IFTYPE_AP) || - (sc->rx.rxfilter & FIF_PSPOLL)) - rfilt |= ATH9K_RX_FILTER_PSPOLL; + /* Revert chainmasks to their original values before NF cal */ +--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.h ++++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.h +@@ -548,15 +548,12 @@ -@@ -486,12 +483,12 @@ start_recv: - bool ath_stoprecv(struct ath_softc *sc) - { - struct ath_hw *ah = sc->sc_ah; -- bool stopped; -+ bool stopped, reset = false; - - spin_lock_bh(&sc->rx.rxbuflock); - ath9k_hw_abortpcurecv(ah); - ath9k_hw_setrxfilter(ah, 0); -- stopped = ath9k_hw_stopdmarecv(ah); -+ stopped = ath9k_hw_stopdmarecv(ah, &reset); - - if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) - ath_edma_stop_recv(sc); -@@ -506,7 +503,7 @@ bool ath_stoprecv(struct ath_softc *sc) - "confusing the DMA engine when we start RX up\n"); - ATH_DBG_WARN_ON_ONCE(!stopped); - } -- return stopped; -+ return stopped || reset; - } + #define AR_PHY_TXGAIN_TABLE (AR_SM_BASE + 0x300) - void ath_flushrecv(struct ath_softc *sc) -@@ -1767,6 +1764,7 @@ requeue: - } else { - list_move_tail(&bf->list, &sc->rx.rxbuf); - ath_rx_buf_link(sc, bf); -+ ath9k_hw_rxena(ah); - } - } while (1); - ---- a/drivers/net/wireless/ath/ath9k/hw.c -+++ b/drivers/net/wireless/ath/ath9k/hw.c -@@ -1249,15 +1249,6 @@ int ath9k_hw_reset(struct ath_hw *ah, st - ah->txchainmask = common->tx_chainmask; - ah->rxchainmask = common->rx_chainmask; - -- if ((common->bus_ops->ath_bus_type != ATH_USB) && !ah->chip_fullsleep) { -- ath9k_hw_abortpcurecv(ah); -- if (!ath9k_hw_stopdmarecv(ah)) { -- ath_dbg(common, ATH_DBG_XMIT, -- "Failed to stop receive dma\n"); -- bChannelChange = false; -- } -- } +-#define AR_PHY_TX_IQCAL_START_9485 (AR_SM_BASE + 0x3c4) +-#define AR_PHY_TX_IQCAL_START_DO_CAL_9485 0x80000000 +-#define AR_PHY_TX_IQCAL_START_DO_CAL_9485_S 31 +-#define AR_PHY_TX_IQCAL_CONTROL_1_9485 (AR_SM_BASE + 0x3c8) +-#define AR_PHY_TX_IQCAL_STATUS_B0_9485 (AR_SM_BASE + 0x3f0) - - if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) - return -EIO; - ---- a/drivers/net/wireless/ath/ath9k/mac.c -+++ b/drivers/net/wireless/ath/ath9k/mac.c -@@ -710,27 +710,46 @@ void ath9k_hw_abortpcurecv(struct ath_hw - } - EXPORT_SYMBOL(ath9k_hw_abortpcurecv); +-#define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + 0x448) +-#define AR_PHY_TX_IQCAL_START (AR_SM_BASE + 0x440) +-#define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + 0x48c) ++#define AR_PHY_TX_IQCAL_CONTROL_1 (AR_SM_BASE + AR_SREV_9485(ah) ? \ ++ 0x3c8 : 0x448) ++#define AR_PHY_TX_IQCAL_START (AR_SM_BASE + AR_SREV_9485(ah) ? \ ++ 0x3c4 : 0x440) ++#define AR_PHY_TX_IQCAL_STATUS_B0 (AR_SM_BASE + AR_SREV_9485(ah) ? \ ++ 0x3f0 : 0x48c) + #define AR_PHY_TX_IQCAL_CORR_COEFF_B0(_i) (AR_SM_BASE + \ + (AR_SREV_9485(ah) ? \ + 0x3d0 : 0x450) + ((_i) << 2)) +@@ -758,10 +755,10 @@ + #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT 0x01000000 + #define AR_PHY_SPECTRAL_SCAN_SHORT_REPEAT_S 24 + #define AR_PHY_CHANNEL_STATUS_RX_CLEAR 0x00000004 +-#define AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT 0x01fc0000 +-#define AR_PHY_TX_IQCAQL_CONTROL_1_IQCORR_I_Q_COFF_DELPT_S 18 +-#define AR_PHY_TX_IQCAL_START_DO_CAL 0x00000001 +-#define AR_PHY_TX_IQCAL_START_DO_CAL_S 0 ++#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT 0x01fc0000 ++#define AR_PHY_TX_IQCAL_CONTROL_1_IQCORR_I_Q_COFF_DELPT_S 18 ++#define AR_PHY_TX_IQCAL_START_DO_CAL 0x00000001 ++#define AR_PHY_TX_IQCAL_START_DO_CAL_S 0 + + #define AR_PHY_TX_IQCAL_STATUS_FAILED 0x00000001 + #define AR_PHY_CALIBRATED_GAINS_0 0x3e +--- a/drivers/net/wireless/ath/ath9k/ath9k.h ++++ b/drivers/net/wireless/ath/ath9k/ath9k.h +@@ -453,6 +453,7 @@ void ath9k_btcoex_timer_pause(struct ath + + #define ATH_LED_PIN_DEF 1 + #define ATH_LED_PIN_9287 8 ++#define ATH_LED_PIN_9300 10 + #define ATH_LED_PIN_9485 6 + + #ifdef CONFIG_MAC80211_LEDS +--- a/drivers/net/wireless/ath/ath9k/gpio.c ++++ b/drivers/net/wireless/ath/ath9k/gpio.c +@@ -46,6 +46,8 @@ void ath_init_leds(struct ath_softc *sc) + sc->sc_ah->led_pin = ATH_LED_PIN_9287; + else if (AR_SREV_9485(sc->sc_ah)) + sc->sc_ah->led_pin = ATH_LED_PIN_9485; ++ else if (AR_SREV_9300(sc->sc_ah)) ++ sc->sc_ah->led_pin = ATH_LED_PIN_9300; + else + sc->sc_ah->led_pin = ATH_LED_PIN_DEF; + } +--- a/drivers/net/wireless/ath/ath9k/reg.h ++++ b/drivers/net/wireless/ath/ath9k/reg.h +@@ -868,6 +868,8 @@ + #define AR_SREV_9485_11(_ah) \ + (AR_SREV_9485(_ah) && \ + ((_ah)->hw_version.macRev == AR_SREV_REVISION_9485_11)) ++#define AR_SREV_9485_OR_LATER(_ah) \ ++ (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9485)) + + #define AR_SREV_9285E_20(_ah) \ + (AR_SREV_9285_12_OR_LATER(_ah) && \ +--- a/net/mac80211/rx.c ++++ b/net/mac80211/rx.c +@@ -652,7 +652,7 @@ static void ieee80211_sta_reorder_releas + set_release_timer: --bool ath9k_hw_stopdmarecv(struct ath_hw *ah) -+bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset) + mod_timer(&tid_agg_rx->reorder_timer, +- tid_agg_rx->reorder_time[j] + ++ tid_agg_rx->reorder_time[j] + 1 + + HT_RX_REORDER_BUF_TIMEOUT); + } else { + del_timer(&tid_agg_rx->reorder_timer); +--- a/drivers/net/wireless/ath/ath9k/calib.c ++++ b/drivers/net/wireless/ath/ath9k/calib.c +@@ -69,15 +69,21 @@ static void ath9k_hw_update_nfcal_hist_b + int16_t *nfarray) { - #define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */ struct ath_common *common = ath9k_hw_common(ah); -+ u32 mac_status, last_mac_status = 0; ++ struct ieee80211_conf *conf = &common->hw->conf; + struct ath_nf_limits *limit; + struct ath9k_nfcal_hist *h; + bool high_nf_mid = false; ++ u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; int i; -+ /* Enable access to the DMA observation bus */ -+ REG_WRITE(ah, AR_MACMISC, -+ ((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) | -+ (AR_MACMISC_MISC_OBS_BUS_1 << -+ AR_MACMISC_MISC_OBS_BUS_MSB_S))); -+ - REG_WRITE(ah, AR_CR, AR_CR_RXD); + h = cal->nfCalHist; + limit = ath9k_hw_get_nf_limits(ah, ah->curchan); - /* Wait for rx enable bit to go low */ - for (i = AH_RX_STOP_DMA_TIMEOUT / AH_TIME_QUANTUM; i != 0; i--) { - if ((REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) - break; + for (i = 0; i < NUM_NF_READINGS; i++) { ++ if (!(chainmask & (1 << i)) || ++ ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf))) ++ continue; + -+ if (!AR_SREV_9300_20_OR_LATER(ah)) { -+ mac_status = REG_READ(ah, AR_DMADBG_7) & 0x7f0; -+ if (mac_status == 0x1c0 && mac_status == last_mac_status) { -+ *reset = true; -+ break; -+ } + h[i].nfCalBuffer[h[i].currIndex] = nfarray[i]; + + if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX) +@@ -225,6 +231,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, + int32_t val; + u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; + struct ath_common *common = ath9k_hw_common(ah); ++ struct ieee80211_conf *conf = &common->hw->conf; + s16 default_nf = ath9k_hw_get_default_nf(ah, chan); + + if (ah->caldata) +@@ -234,6 +241,9 @@ void ath9k_hw_loadnf(struct ath_hw *ah, + if (chainmask & (1 << i)) { + s16 nfval; + ++ if ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)) ++ continue; + -+ last_mac_status = mac_status; -+ } + if (h) + nfval = h[i].privNF; + else +@@ -293,6 +303,9 @@ void ath9k_hw_loadnf(struct ath_hw *ah, + ENABLE_REGWRITE_BUFFER(ah); + for (i = 0; i < NUM_NF_READINGS; i++) { + if (chainmask & (1 << i)) { ++ if ((i >= AR5416_MAX_CHAINS) && !conf_is_ht40(conf)) ++ continue; + - udelay(AH_TIME_QUANTUM); - } - - if (i == 0) { - ath_err(common, -- "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x\n", -+ "DMA failed to stop in %d ms AR_CR=0x%08x AR_DIAG_SW=0x%08x DMADBG_7=0x%08x\n", - AH_RX_STOP_DMA_TIMEOUT / 1000, - REG_READ(ah, AR_CR), -- REG_READ(ah, AR_DIAG_SW)); -+ REG_READ(ah, AR_DIAG_SW), -+ REG_READ(ah, AR_DMADBG_7)); - return false; - } else { - return true; ---- a/drivers/net/wireless/ath/ath9k/mac.h -+++ b/drivers/net/wireless/ath/ath9k/mac.h -@@ -695,7 +695,7 @@ bool ath9k_hw_setrxabort(struct ath_hw * - void ath9k_hw_putrxbuf(struct ath_hw *ah, u32 rxdp); - void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning); - void ath9k_hw_abortpcurecv(struct ath_hw *ah); --bool ath9k_hw_stopdmarecv(struct ath_hw *ah); -+bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset); - int ath9k_hw_beaconq_setup(struct ath_hw *ah); - - /* Interrupt Handling */ + val = REG_READ(ah, ah->nf_regs[i]); + val &= 0xFFFFFE00; + val |= (((u32) (-50) << 1) & 0x1ff);