+commit a63caf0a357ad5c1f08d6b7827dc76c451445017
+Author: Stanislaw Gruszka <sgruszka@redhat.com>
+Date: Wed Feb 19 13:15:17 2014 +0100
+
+ ath9k: protect tid->sched check
+
+ We check tid->sched without a lock taken on ath_tx_aggr_sleep(). That
+ is race condition which can result of doing list_del(&tid->list) twice
+ (second time with poisoned list node) and cause crash like shown below:
+
+ [424271.637220] BUG: unable to handle kernel paging request at 00100104
+ [424271.637328] IP: [<f90fc072>] ath_tx_aggr_sleep+0x62/0xe0 [ath9k]
+ ...
+ [424271.639953] Call Trace:
+ [424271.639998] [<f90f6900>] ? ath9k_get_survey+0x110/0x110 [ath9k]
+ [424271.640083] [<f90f6942>] ath9k_sta_notify+0x42/0x50 [ath9k]
+ [424271.640177] [<f809cfef>] sta_ps_start+0x8f/0x1c0 [mac80211]
+ [424271.640258] [<c10f730e>] ? free_compound_page+0x2e/0x40
+ [424271.640346] [<f809e915>] ieee80211_rx_handlers+0x9d5/0x2340 [mac80211]
+ [424271.640437] [<c112f048>] ? kmem_cache_free+0x1d8/0x1f0
+ [424271.640510] [<c1345a84>] ? kfree_skbmem+0x34/0x90
+ [424271.640578] [<c10fc23c>] ? put_page+0x2c/0x40
+ [424271.640640] [<c1345a84>] ? kfree_skbmem+0x34/0x90
+ [424271.640706] [<c1345a84>] ? kfree_skbmem+0x34/0x90
+ [424271.640787] [<f809dde3>] ? ieee80211_rx_handlers_result+0x73/0x1d0 [mac80211]
+ [424271.640897] [<f80a07a0>] ieee80211_prepare_and_rx_handle+0x520/0xad0 [mac80211]
+ [424271.641009] [<f809e22d>] ? ieee80211_rx_handlers+0x2ed/0x2340 [mac80211]
+ [424271.641104] [<c13846ce>] ? ip_output+0x7e/0xd0
+ [424271.641182] [<f80a1057>] ieee80211_rx+0x307/0x7c0 [mac80211]
+ [424271.641266] [<f90fa6ee>] ath_rx_tasklet+0x88e/0xf70 [ath9k]
+ [424271.641358] [<f80a0f2c>] ? ieee80211_rx+0x1dc/0x7c0 [mac80211]
+ [424271.641445] [<f90f82db>] ath9k_tasklet+0xcb/0x130 [ath9k]
+
+ Bug report:
+ https://bugzilla.kernel.org/show_bug.cgi?id=70551
+
+ Reported-and-tested-by: Max Sydorenko <maxim.stargazer@gmail.com>
+ Cc: stable@vger.kernel.org
+ Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com>
+
+commit 82ed9e3ccc02797df2ffe4b78127c4cd5f799a41
+Author: Felix Fietkau <nbd@openwrt.org>
+Date: Tue Feb 11 15:54:13 2014 +0100
+
+ mac80211: send control port protocol frames to the VO queue
+
+ Improves reliability of wifi connections with WPA, since authentication
+ frames are prioritized over normal traffic and also typically exempt
+ from aggregation.
+
+ Cc: stable@vger.kernel.org
+ Signed-off-by: Felix Fietkau <nbd@openwrt.org>
+
+commit d4426800f71e972feaa33e04c5801fc730627bdd
+Author: Stanislaw Gruszka <stf_xl@wp.pl>
+Date: Mon Feb 10 22:38:28 2014 +0100
+
+ rtl8187: fix regression on MIPS without coherent DMA
+
+ This patch fixes regression caused by commit a16dad77634 "MIPS: Fix
+ potencial corruption". That commit fixes one corruption scenario in
+ cost of adding another one, which actually start to cause crashes
+ on Yeeloong laptop when rtl8187 driver is used.
+
+ For correct DMA read operation on machines without DMA coherence, kernel
+ have to invalidate cache, such it will refill later with new data that
+ device wrote to memory, when that data is needed to process. We can only
+ invalidate full cache line. Hence when cache line includes both dma
+ buffer and some other data (written in cache, but not yet in main
+ memory), the other data can not hit memory due to invalidation. That
+ happen on rtl8187 where struct rtl8187_priv fields are located just
+ before and after small buffers that are passed to USB layer and DMA
+ is performed on them.
+
+ To fix the problem we align buffers and reserve space after them to make
+ them match cache line.
+
+ This patch does not resolve all possible MIPS problems entirely, for
+ that we have to assure that we always map cache aligned buffers for DMA,
+ what can be complex or even not possible. But patch fixes visible and
+ reproducible regression and seems other possible corruptions do not
+ happen in practice, since Yeeloong laptop works stable without rtl8187
+ driver.
+
+ Bug report:
+ https://bugzilla.kernel.org/show_bug.cgi?id=54391
+
+ Reported-by: Petr Pisar <petr.pisar@atlas.cz>
+ Bisected-by: Tom Li <biergaizi2009@gmail.com>
+ Reported-and-tested-by: Tom Li <biergaizi2009@gmail.com>
+ Cc: stable@vger.kernel.org
+ Signed-off-by: Stanislaw Gruszka <stf_xl@wp.pl>
+
+commit e2f141d67ad1e7fe10aaab61811e8a409dfb2442
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date: Fri Feb 7 10:29:55 2014 +0530
+
+ ath9k: Calculate IQ-CAL median
+
+ This patch adds a routine to calculate the median IQ correction
+ values for AR955x, which is used for outlier detection.
+ The normal method which is used for all other chips is
+ bypassed for AR955x.
+
+ Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+
+commit c52a6fce0820c8d0687443ab86058ae03b478c8f
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date: Fri Feb 7 10:29:54 2014 +0530
+
+ ath9k: Expand the IQ coefficient array
+
+ This will be used for storing data for mutiple
+ IQ calibration runs, for AR955x.
+
+ Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+
+commit 034969ff5c2b6431d10e07c1938f0b916da85cc3
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date: Fri Feb 7 10:29:53 2014 +0530
+
+ ath9k: Modify IQ calibration for AR955x
+
+ IQ calibration post-processing for AR955x is different
+ from other chips - instead of just doing it as part
+ of AGC calibration once, it is triggered 3 times and
+ a median is determined. This patch adds initial support
+ for changing the calibration behavior for AR955x.
+
+ Also, to simplify things, a helper routine to issue/poll
+ AGC calibration is used.
+
+ For non-AR955x chips, the iqcal_idx (which will be used
+ in subsequent patches) is set to zero.
+
+ Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+
+commit 9b1ed6454e6f3511f24266be99b4e403f243f6a8
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date: Fri Feb 7 10:29:52 2014 +0530
+
+ ath9k: Fix magnitude/phase calculation
+
+ Incorrect values are programmed in the registers
+ containing the IQ correction coefficients by the IQ-CAL
+ post-processing code. Fix this.
+
+ Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+
+commit 36f93484f96f79171dcecb67c5ef0c3de22531a6
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date: Fri Feb 7 10:29:51 2014 +0530
+
+ ath9k: Rename ar9003_hw_tx_iqcal_load_avg_2_passes
+
+ Use ar9003_hw_tx_iq_cal_outlier_detection instead.
+
+ Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+
+commit 3af09a7f5d21dd5fd15b973ce6a91a575da30417
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date: Fri Feb 7 10:29:50 2014 +0530
+
+ ath9k: Check explicitly for IQ calibration
+
+ In chips like AR955x, the initvals contain the information
+ whether IQ calibration is to be done in the HW when an
+ AGC calibration is triggered. Check if IQ-CAL is enabled
+ in the initvals before flagging 'txiqcal_done' as true.
+
+ Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+
+commit cb4969634b93c4643a32cc3fbd27d2b288b25771
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date: Fri Feb 7 10:29:49 2014 +0530
+
+ ath9k: Fix IQ cal post processing for SoC
+
+ Calibration data is not reused for SoC chips, so
+ call ar9003_hw_tx_iq_cal_post_proc() with the correct
+ argument. The 'is_reusable' flag is currently used
+ only for PC-OEM chips, but it makes things clearer to
+ specify it explicity.
+
+ Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+
+commit e138e0ef9560c46ce93dbb22a728a57888e94d1c
+Author: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+Date: Mon Feb 3 13:31:37 2014 +0530
+
+ ath9k: Fix TX power calculation
+
+ The commit, "ath9k_hw: Fix incorrect Tx control power in AR9003 template"
+ fixed the incorrect values in the eeprom templates, but if
+ boards have already been calibrated with incorrect values,
+ they would still be using the wrong TX power. Fix this by assigning
+ a default value in such cases.
+
+ Cc: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
+ Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
+
commit b9f268b5b01331c3c82179abca551429450e9417
Author: Michal Kazior <michal.kazior@tieto.com>
Date: Wed Jan 29 14:22:27 2014 +0100
return;
switch (event) {
+--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+@@ -5065,6 +5065,10 @@ static u16 ar9003_hw_get_max_edge_power(
+ break;
+ }
+ }
++
++ if (is2GHz && !twiceMaxEdgePower)
++ twiceMaxEdgePower = 60;
++
+ return twiceMaxEdgePower;
+ }
+
+--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
++++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+@@ -23,10 +23,11 @@
+ #define MAX_MEASUREMENT MAX_IQCAL_MEASUREMENT
+ #define MAX_MAG_DELTA 11
+ #define MAX_PHS_DELTA 10
++#define MAXIQCAL 3
+
+ struct coeff {
+- int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
+- int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT];
++ int mag_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL];
++ int phs_coeff[AR9300_MAX_CHAINS][MAX_MEASUREMENT][MAXIQCAL];
+ int iqc_coeff[2];
+ };
+
+@@ -800,7 +801,7 @@ static bool ar9003_hw_calc_iq_corr(struc
+ if (q_q_coff > 63)
+ q_q_coff = 63;
+
+- iqc_coeff[0] = (q_q_coff * 128) + q_i_coff;
++ iqc_coeff[0] = (q_q_coff * 128) + (0x7f & q_i_coff);
+
+ ath_dbg(common, CALIBRATE, "tx chain %d: iq corr coeff=%x\n",
+ chain_idx, iqc_coeff[0]);
+@@ -831,7 +832,7 @@ static bool ar9003_hw_calc_iq_corr(struc
+ if (q_q_coff > 63)
+ q_q_coff = 63;
+
+- iqc_coeff[1] = (q_q_coff * 128) + q_i_coff;
++ iqc_coeff[1] = (q_q_coff * 128) + (0x7f & q_i_coff);
+
+ ath_dbg(common, CALIBRATE, "rx chain %d: iq corr coeff=%x\n",
+ chain_idx, iqc_coeff[1]);
+@@ -839,7 +840,8 @@ static bool ar9003_hw_calc_iq_corr(struc
+ return true;
+ }
+
+-static void ar9003_hw_detect_outlier(int *mp_coeff, int nmeasurement,
++static void ar9003_hw_detect_outlier(int mp_coeff[][MAXIQCAL],
++ int nmeasurement,
+ int max_delta)
+ {
+ int mp_max = -64, max_idx = 0;
+@@ -848,20 +850,20 @@ static void ar9003_hw_detect_outlier(int
+
+ /* find min/max mismatch across all calibrated gains */
+ for (i = 0; i < nmeasurement; i++) {
+- if (mp_coeff[i] > mp_max) {
+- mp_max = mp_coeff[i];
++ if (mp_coeff[i][0] > mp_max) {
++ mp_max = mp_coeff[i][0];
+ max_idx = i;
+- } else if (mp_coeff[i] < mp_min) {
+- mp_min = mp_coeff[i];
++ } else if (mp_coeff[i][0] < mp_min) {
++ mp_min = mp_coeff[i][0];
+ min_idx = i;
+ }
+ }
+
+ /* 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];
++ if ((abs(mp_coeff[i][0]) < abs(mp_max)) ||
++ (abs(mp_coeff[i][0]) < abs(mp_min))) {
++ mp_avg += mp_coeff[i][0];
+ mp_count++;
+ }
+ }
+@@ -873,7 +875,7 @@ static void ar9003_hw_detect_outlier(int
+ if (mp_count)
+ mp_avg /= mp_count;
+ else
+- mp_avg = mp_coeff[nmeasurement - 1];
++ mp_avg = mp_coeff[nmeasurement - 1][0];
+
+ /* detect outlier */
+ if (abs(mp_max - mp_min) > max_delta) {
+@@ -882,15 +884,16 @@ static void ar9003_hw_detect_outlier(int
+ else
+ outlier_idx = min_idx;
+
+- mp_coeff[outlier_idx] = mp_avg;
++ mp_coeff[outlier_idx][0] = mp_avg;
+ }
+ }
+
+-static void ar9003_hw_tx_iqcal_load_avg_2_passes(struct ath_hw *ah,
+- struct coeff *coeff,
+- bool is_reusable)
++static void ar9003_hw_tx_iq_cal_outlier_detection(struct ath_hw *ah,
++ struct coeff *coeff,
++ bool is_reusable)
+ {
+ int i, im, nmeasurement;
++ int magnitude, phase;
+ u32 tx_corr_coeff[MAX_MEASUREMENT][AR9300_MAX_CHAINS];
+ struct ath9k_hw_cal_data *caldata = ah->caldata;
+
+@@ -920,21 +923,30 @@ static void ar9003_hw_tx_iqcal_load_avg_
+ if (nmeasurement > MAX_MEASUREMENT)
+ nmeasurement = MAX_MEASUREMENT;
+
+- /* 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);
++ /*
++ * Skip normal outlier detection for AR9550.
++ */
++ if (!AR_SREV_9550(ah)) {
++ /* 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);
++ }
+ }
+
+ for (im = 0; im < nmeasurement; im++) {
++ magnitude = coeff->mag_coeff[i][im][0];
++ phase = coeff->phs_coeff[i][im][0];
+
+- coeff->iqc_coeff[0] = (coeff->mag_coeff[i][im] & 0x7f) |
+- ((coeff->phs_coeff[i][im] & 0x7f) << 7);
++ coeff->iqc_coeff[0] =
++ (phase & 0x7f) | ((magnitude & 0x7f) << 7);
+
+ if ((im % 2) == 0)
+ REG_RMW_FIELD(ah, tx_corr_coeff[im][i],
+@@ -991,7 +1003,63 @@ static bool ar9003_hw_tx_iq_cal_run(stru
+ return true;
+ }
+
+-static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah, bool is_reusable)
++static void __ar955x_tx_iq_cal_sort(struct ath_hw *ah,
++ struct coeff *coeff,
++ int i, int nmeasurement)
++{
++ struct ath_common *common = ath9k_hw_common(ah);
++ int im, ix, iy, temp;
++
++ for (im = 0; im < nmeasurement; im++) {
++ for (ix = 0; ix < MAXIQCAL - 1; ix++) {
++ for (iy = ix + 1; iy <= MAXIQCAL - 1; iy++) {
++ if (coeff->mag_coeff[i][im][iy] <
++ coeff->mag_coeff[i][im][ix]) {
++ temp = coeff->mag_coeff[i][im][ix];
++ coeff->mag_coeff[i][im][ix] =
++ coeff->mag_coeff[i][im][iy];
++ coeff->mag_coeff[i][im][iy] = temp;
++ }
++ if (coeff->phs_coeff[i][im][iy] <
++ coeff->phs_coeff[i][im][ix]) {
++ temp = coeff->phs_coeff[i][im][ix];
++ coeff->phs_coeff[i][im][ix] =
++ coeff->phs_coeff[i][im][iy];
++ coeff->phs_coeff[i][im][iy] = temp;
++ }
++ }
++ }
++ coeff->mag_coeff[i][im][0] = coeff->mag_coeff[i][im][MAXIQCAL / 2];
++ coeff->phs_coeff[i][im][0] = coeff->phs_coeff[i][im][MAXIQCAL / 2];
++
++ ath_dbg(common, CALIBRATE,
++ "IQCAL: Median [ch%d][gain%d]: mag = %d phase = %d\n",
++ i, im,
++ coeff->mag_coeff[i][im][0],
++ coeff->phs_coeff[i][im][0]);
++ }
++}
++
++static bool ar955x_tx_iq_cal_median(struct ath_hw *ah,
++ struct coeff *coeff,
++ int iqcal_idx,
++ int nmeasurement)
++{
++ int i;
++
++ if ((iqcal_idx + 1) != MAXIQCAL)
++ return false;
++
++ for (i = 0; i < AR9300_MAX_CHAINS; i++) {
++ __ar955x_tx_iq_cal_sort(ah, coeff, i, nmeasurement);
++ }
++
++ return true;
++}
++
++static void ar9003_hw_tx_iq_cal_post_proc(struct ath_hw *ah,
++ int iqcal_idx,
++ bool is_reusable)
+ {
+ struct ath_common *common = ath9k_hw_common(ah);
+ const u32 txiqcal_status[AR9300_MAX_CHAINS] = {
+@@ -1004,10 +1072,11 @@ static void ar9003_hw_tx_iq_cal_post_pro
+ AR_PHY_CHAN_INFO_TAB_1,
+ AR_PHY_CHAN_INFO_TAB_2,
+ };
+- struct coeff coeff;
++ static struct coeff coeff;
+ s32 iq_res[6];
+ int i, im, j;
+- int nmeasurement;
++ int nmeasurement = 0;
++ bool outlier_detect = true;
+
+ for (i = 0; i < AR9300_MAX_CHAINS; i++) {
+ if (!(ah->txchainmask & (1 << i)))
+@@ -1065,17 +1134,23 @@ static void ar9003_hw_tx_iq_cal_post_pro
+ goto tx_iqcal_fail;
+ }
+
+- coeff.mag_coeff[i][im] = coeff.iqc_coeff[0] & 0x7f;
+- coeff.phs_coeff[i][im] =
++ coeff.phs_coeff[i][im][iqcal_idx] =
++ coeff.iqc_coeff[0] & 0x7f;
++ coeff.mag_coeff[i][im][iqcal_idx] =
+ (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;
++ if (coeff.mag_coeff[i][im][iqcal_idx] > 63)
++ coeff.mag_coeff[i][im][iqcal_idx] -= 128;
++ if (coeff.phs_coeff[i][im][iqcal_idx] > 63)
++ coeff.phs_coeff[i][im][iqcal_idx] -= 128;
+ }
+ }
+- ar9003_hw_tx_iqcal_load_avg_2_passes(ah, &coeff, is_reusable);
++
++ if (AR_SREV_9550(ah))
++ outlier_detect = ar955x_tx_iq_cal_median(ah, &coeff,
++ iqcal_idx, nmeasurement);
++ if (outlier_detect)
++ ar9003_hw_tx_iq_cal_outlier_detection(ah, &coeff, is_reusable);
+
+ return;
+
+@@ -1409,7 +1484,7 @@ skip_tx_iqcal:
+ }
+
+ if (txiqcal_done)
+- ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable);
++ ar9003_hw_tx_iq_cal_post_proc(ah, 0, is_reusable);
+ else if (caldata && test_bit(TXIQCAL_DONE, &caldata->cal_flags))
+ ar9003_hw_tx_iq_cal_reload(ah);
+
+@@ -1455,14 +1530,38 @@ skip_tx_iqcal:
+ return true;
+ }
+
++static bool do_ar9003_agc_cal(struct ath_hw *ah)
++{
++ struct ath_common *common = ath9k_hw_common(ah);
++ bool status;
++
++ REG_WRITE(ah, AR_PHY_AGC_CONTROL,
++ REG_READ(ah, AR_PHY_AGC_CONTROL) |
++ AR_PHY_AGC_CONTROL_CAL);
++
++ status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
++ AR_PHY_AGC_CONTROL_CAL,
++ 0, AH_WAIT_TIMEOUT);
++ if (!status) {
++ ath_dbg(common, CALIBRATE,
++ "offset calibration failed to complete in %d ms,"
++ "noisy environment?\n",
++ AH_WAIT_TIMEOUT / 1000);
++ return false;
++ }
++
++ return true;
++}
++
+ static bool ar9003_hw_init_cal_soc(struct ath_hw *ah,
+ struct ath9k_channel *chan)
+ {
+ struct ath_common *common = ath9k_hw_common(ah);
+ struct ath9k_hw_cal_data *caldata = ah->caldata;
+ bool txiqcal_done = false;
+- bool is_reusable = true, status = true;
++ bool status = true;
+ bool run_agc_cal = false, sep_iq_cal = false;
++ int i = 0;
+
+ /* Use chip chainmask only for calibration */
+ ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
+@@ -1485,7 +1584,12 @@ static bool ar9003_hw_init_cal_soc(struc
+ * AGC calibration. Specifically, AR9550 in SoC chips.
+ */
+ if (ah->enabled_cals & TX_IQ_ON_AGC_CAL) {
+- txiqcal_done = true;
++ if (REG_READ_FIELD(ah, AR_PHY_TX_IQCAL_CONTROL_0,
++ AR_PHY_TX_IQCAL_CONTROL_0_ENABLE_TXIQ_CAL)) {
++ txiqcal_done = true;
++ } else {
++ txiqcal_done = false;
++ }
+ run_agc_cal = true;
+ } else {
+ sep_iq_cal = true;
+@@ -1512,27 +1616,37 @@ skip_tx_iqcal:
+ if (AR_SREV_9330_11(ah))
+ ar9003_hw_manual_peak_cal(ah, 0, IS_CHAN_2GHZ(chan));
+
+- /* Calibrate the AGC */
+- REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+- REG_READ(ah, AR_PHY_AGC_CONTROL) |
+- AR_PHY_AGC_CONTROL_CAL);
+-
+- /* Poll for offset calibration complete */
+- status = ath9k_hw_wait(ah, AR_PHY_AGC_CONTROL,
+- AR_PHY_AGC_CONTROL_CAL,
+- 0, AH_WAIT_TIMEOUT);
+- }
++ /*
++ * For non-AR9550 chips, we just trigger AGC calibration
++ * in the HW, poll for completion and then process
++ * the results.
++ *
++ * For AR955x, we run it multiple times and use
++ * median IQ correction.
++ */
++ if (!AR_SREV_9550(ah)) {
++ status = do_ar9003_agc_cal(ah);
++ if (!status)
++ return false;
+
+- if (!status) {
+- ath_dbg(common, CALIBRATE,
+- "offset calibration failed to complete in %d ms; noisy environment?\n",
+- AH_WAIT_TIMEOUT / 1000);
+- return false;
++ if (txiqcal_done)
++ ar9003_hw_tx_iq_cal_post_proc(ah, 0, false);
++ } else {
++ if (!txiqcal_done) {
++ status = do_ar9003_agc_cal(ah);
++ if (!status)
++ return false;
++ } else {
++ for (i = 0; i < MAXIQCAL; i++) {
++ status = do_ar9003_agc_cal(ah);
++ if (!status)
++ return false;
++ ar9003_hw_tx_iq_cal_post_proc(ah, i, false);
++ }
++ }
++ }
+ }
+
+- if (txiqcal_done)
+- ar9003_hw_tx_iq_cal_post_proc(ah, is_reusable);
+-
+ /* Revert chainmask to runtime parameters */
+ ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask);
+
+--- a/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
++++ b/drivers/net/wireless/rtl818x/rtl8187/rtl8187.h
+@@ -15,6 +15,8 @@
+ #ifndef RTL8187_H
+ #define RTL8187_H
+
++#include <linux/cache.h>
++
+ #include "rtl818x.h"
+ #include "leds.h"
+
+@@ -139,7 +141,10 @@ struct rtl8187_priv {
+ u8 aifsn[4];
+ u8 rfkill_mask;
+ struct {
+- __le64 buf;
++ union {
++ __le64 buf;
++ u8 dummy1[L1_CACHE_BYTES];
++ } ____cacheline_aligned;
+ struct sk_buff_head queue;
+ } b_tx_status; /* This queue is used by both -b and non-b devices */
+ struct mutex io_mutex;
+@@ -147,7 +152,8 @@ struct rtl8187_priv {
+ u8 bits8;
+ __le16 bits16;
+ __le32 bits32;
+- } *io_dmabuf;
++ u8 dummy2[L1_CACHE_BYTES];
++ } *io_dmabuf ____cacheline_aligned;
+ bool rfkill_off;
+ u16 seqno;
+ };
+--- a/net/mac80211/wme.c
++++ b/net/mac80211/wme.c
+@@ -154,6 +154,11 @@ u16 ieee80211_select_queue(struct ieee80
+ return IEEE80211_AC_BE;
+ }
+
++ if (skb->protocol == sdata->control_port_protocol) {
++ skb->priority = 7;
++ return ieee80211_downgrade_queue(sdata, skb);
++ }
++
+ /* use the data classifier to determine what 802.1d tag the
+ * data frame has */
+ rcu_read_lock();
+--- a/drivers/net/wireless/ath/ath9k/xmit.c
++++ b/drivers/net/wireless/ath/ath9k/xmit.c
+@@ -1444,14 +1444,16 @@ void ath_tx_aggr_sleep(struct ieee80211_
+ for (tidno = 0, tid = &an->tid[tidno];
+ tidno < IEEE80211_NUM_TIDS; tidno++, tid++) {
+
+- if (!tid->sched)
+- continue;
+-
+ ac = tid->ac;
+ txq = ac->txq;
+
+ ath_txq_lock(sc, txq);
+
++ if (!tid->sched) {
++ ath_txq_unlock(sc, txq);
++ continue;
++ }
++
+ buffered = ath_tid_has_buffered(tid);
+
+ tid->sched = false;