Browse Source

mac80211: replace the regd revert patch with a proper fix, add some more pending patches

SVN-Revision: 26761
Felix Fietkau 15 years ago
parent
commit
359e667fd5

+ 567 - 0
package/mac80211/patches/300-pending_work.patch

@@ -0,0 +1,567 @@
+--- 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(&reg_timeout, msecs_to_jiffies(3142));
+ }
+ 
+--- 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;
+ }
+ 
+-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;
++		}
++	}
+ 
+-	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;
+ }
+ 
+ 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);
++		}
+ 
+-			/*
+-			 * 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 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;
+ }
+ 
+ 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++;
+ 	}
+ 
+-	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;
++			}
+ 
+-				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]);
++			}
+ 
+-				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 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);
++	}
+ 
+ 	/* Calibrate the AGC */
+ 	REG_WRITE(ah, AR_PHY_AGC_CONTROL,
+@@ -979,7 +885,7 @@ static bool ar9003_hw_init_cal(struct at
+ 		return false;
+ 	}
+ 
+-	if (AR_SREV_9485(ah))
++	if (txiqcal_done)
+ 		ar9003_hw_tx_iq_cal_post_proc(ah);
+ 
+ 	/* 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 @@
+ 
+ #define AR_PHY_TXGAIN_TABLE      (AR_SM_BASE + 0x300)
+ 
+-#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)
+-
+-#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:
+ 
+ 		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);

+ 0 - 63
package/mac80211/patches/300-revert_regd_breakage.patch

@@ -1,63 +0,0 @@
---- a/net/wireless/reg.c
-+++ b/net/wireless/reg.c
-@@ -107,9 +107,6 @@ struct reg_beacon {
- static void reg_todo(struct work_struct *work);
- static DECLARE_WORK(reg_work, reg_todo);
- 
--static void reg_timeout_work(struct work_struct *work);
--static DECLARE_DELAYED_WORK(reg_timeout, reg_timeout_work);
--
- /* We keep a static world regulatory domain in case of the absence of CRDA */
- static const struct ieee80211_regdomain world_regdom = {
- 	.n_reg_rules = 5,
-@@ -1334,9 +1331,6 @@ static void reg_set_request_processed(vo
- 		need_more_processing = true;
- 	spin_unlock(&reg_requests_lock);
- 
--	if (last_request->initiator == NL80211_REGDOM_SET_BY_USER)
--		cancel_delayed_work_sync(&reg_timeout);
--
- 	if (need_more_processing)
- 		schedule_work(&reg_work);
- }
-@@ -1447,17 +1441,8 @@ static void reg_process_hint(struct regu
- 	r = __regulatory_hint(wiphy, reg_request);
- 	/* This is required so that the orig_* parameters are saved */
- 	if (r == -EALREADY && wiphy &&
--	    wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY) {
-+	    wiphy->flags & WIPHY_FLAG_STRICT_REGULATORY)
- 		wiphy_update_regulatory(wiphy, initiator);
--		return;
--	}
--
--	/*
--	 * 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)
--		schedule_delayed_work(&reg_timeout, msecs_to_jiffies(3142));
- }
- 
- /*
-@@ -2185,13 +2170,6 @@ out:
- 	mutex_unlock(&reg_mutex);
- }
- 
--static void reg_timeout_work(struct work_struct *work)
--{
--	REG_DBG_PRINT("Timeout while waiting for CRDA to reply, "
--		      "restoring regulatory settings");
--	restore_regulatory_settings(true);
--}
--
- int __init regulatory_init(void)
- {
- 	int err = 0;
-@@ -2245,7 +2223,6 @@ void /* __init_or_exit */ regulatory_exi
- 	struct reg_beacon *reg_beacon, *btmp;
- 
- 	cancel_work_sync(&reg_work);
--	cancel_delayed_work_sync(&reg_timeout);
- 
- 	mutex_lock(&cfg80211_mutex);
- 	mutex_lock(&reg_mutex);