aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2010-07-30 18:12:00 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-08-04 15:27:37 -0400
commit20bd2a0952d01ba82a99b3f22d46e3832c255529 (patch)
treed875681269e087e6a148593bb1d436849e642b7f /drivers/net/wireless/ath
parent5ee0865615f65f84e6ee9174771a6716c29e08e1 (diff)
ath9k_hw: clean up per-channel calibration data
The noise floor history buffer is currently not kept per channel, which can lead to problems when changing channels from a clean channel to a noisy one. Also when switching from HT20 to HT40, the noise floor history buffer is full of measurements, but none of them contain data for the extension channel, which it needs quite a bit of time to recover from. This patch puts all the per-channel calibration data into a single data structure, and gives the the driver control over whether that is used per-channel or even not used for some channels. For ath9k_htc, I decided to keep this per-channel in order to avoid creating regressions. For ath9k, the data is kept only for the operating channel, which saves some space. ath9k_hw takes care of wiping old data when the operating channel or its channel flags change. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9002_calib.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_calib.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_paprd.c17
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.c99
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/htc.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c18
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h24
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c32
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c2
12 files changed, 130 insertions, 94 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
index 2387ad1a23a0..d28a8d37f01f 100644
--- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
@@ -63,6 +63,7 @@ static bool ar9002_hw_per_calibration(struct ath_hw *ah,
63 u8 rxchainmask, 63 u8 rxchainmask,
64 struct ath9k_cal_list *currCal) 64 struct ath9k_cal_list *currCal)
65{ 65{
66 struct ath9k_hw_cal_data *caldata = ah->caldata;
66 bool iscaldone = false; 67 bool iscaldone = false;
67 68
68 if (currCal->calState == CAL_RUNNING) { 69 if (currCal->calState == CAL_RUNNING) {
@@ -81,14 +82,14 @@ static bool ar9002_hw_per_calibration(struct ath_hw *ah,
81 } 82 }
82 83
83 currCal->calData->calPostProc(ah, numChains); 84 currCal->calData->calPostProc(ah, numChains);
84 ichan->CalValid |= currCal->calData->calType; 85 caldata->CalValid |= currCal->calData->calType;
85 currCal->calState = CAL_DONE; 86 currCal->calState = CAL_DONE;
86 iscaldone = true; 87 iscaldone = true;
87 } else { 88 } else {
88 ar9002_hw_setup_calibration(ah, currCal); 89 ar9002_hw_setup_calibration(ah, currCal);
89 } 90 }
90 } 91 }
91 } else if (!(ichan->CalValid & currCal->calData->calType)) { 92 } else if (!(caldata->CalValid & currCal->calData->calType)) {
92 ath9k_hw_reset_calibration(ah, currCal); 93 ath9k_hw_reset_calibration(ah, currCal);
93 } 94 }
94 95
@@ -900,7 +901,8 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan)
900 ath9k_hw_reset_calibration(ah, ah->cal_list_curr); 901 ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
901 } 902 }
902 903
903 chan->CalValid = 0; 904 if (ah->caldata)
905 ah->caldata->CalValid = 0;
904 906
905 return true; 907 return true;
906} 908}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index f51ab89c989d..4674ea8c9c99 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -68,6 +68,7 @@ static bool ar9003_hw_per_calibration(struct ath_hw *ah,
68 u8 rxchainmask, 68 u8 rxchainmask,
69 struct ath9k_cal_list *currCal) 69 struct ath9k_cal_list *currCal)
70{ 70{
71 struct ath9k_hw_cal_data *caldata = ah->caldata;
71 /* Cal is assumed not done until explicitly set below */ 72 /* Cal is assumed not done until explicitly set below */
72 bool iscaldone = false; 73 bool iscaldone = false;
73 74
@@ -95,7 +96,7 @@ static bool ar9003_hw_per_calibration(struct ath_hw *ah,
95 currCal->calData->calPostProc(ah, numChains); 96 currCal->calData->calPostProc(ah, numChains);
96 97
97 /* Calibration has finished. */ 98 /* Calibration has finished. */
98 ichan->CalValid |= currCal->calData->calType; 99 caldata->CalValid |= currCal->calData->calType;
99 currCal->calState = CAL_DONE; 100 currCal->calState = CAL_DONE;
100 iscaldone = true; 101 iscaldone = true;
101 } else { 102 } else {
@@ -106,7 +107,7 @@ static bool ar9003_hw_per_calibration(struct ath_hw *ah,
106 ar9003_hw_setup_calibration(ah, currCal); 107 ar9003_hw_setup_calibration(ah, currCal);
107 } 108 }
108 } 109 }
109 } else if (!(ichan->CalValid & currCal->calData->calType)) { 110 } else if (!(caldata->CalValid & currCal->calData->calType)) {
110 /* If current cal is marked invalid in channel, kick it off */ 111 /* If current cal is marked invalid in channel, kick it off */
111 ath9k_hw_reset_calibration(ah, currCal); 112 ath9k_hw_reset_calibration(ah, currCal);
112 } 113 }
@@ -793,7 +794,8 @@ static bool ar9003_hw_init_cal(struct ath_hw *ah,
793 if (ah->cal_list_curr) 794 if (ah->cal_list_curr)
794 ath9k_hw_reset_calibration(ah, ah->cal_list_curr); 795 ath9k_hw_reset_calibration(ah, ah->cal_list_curr);
795 796
796 chan->CalValid = 0; 797 if (ah->caldata)
798 ah->caldata->CalValid = 0;
797 799
798 return true; 800 return true;
799} 801}
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
index 49e0c865ce5c..7c38229ba670 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c
@@ -577,10 +577,11 @@ static bool create_pa_curve(u32 *data_L, u32 *data_U, u32 *pa_table, u16 *gain)
577} 577}
578 578
579void ar9003_paprd_populate_single_table(struct ath_hw *ah, 579void ar9003_paprd_populate_single_table(struct ath_hw *ah,
580 struct ath9k_channel *chan, int chain) 580 struct ath9k_hw_cal_data *caldata,
581 int chain)
581{ 582{
582 u32 *paprd_table_val = chan->pa_table[chain]; 583 u32 *paprd_table_val = caldata->pa_table[chain];
583 u32 small_signal_gain = chan->small_signal_gain[chain]; 584 u32 small_signal_gain = caldata->small_signal_gain[chain];
584 u32 training_power; 585 u32 training_power;
585 u32 reg = 0; 586 u32 reg = 0;
586 int i; 587 int i;
@@ -654,17 +655,17 @@ int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain)
654} 655}
655EXPORT_SYMBOL(ar9003_paprd_setup_gain_table); 656EXPORT_SYMBOL(ar9003_paprd_setup_gain_table);
656 657
657int ar9003_paprd_create_curve(struct ath_hw *ah, struct ath9k_channel *chan, 658int ar9003_paprd_create_curve(struct ath_hw *ah,
658 int chain) 659 struct ath9k_hw_cal_data *caldata, int chain)
659{ 660{
660 u16 *small_signal_gain = &chan->small_signal_gain[chain]; 661 u16 *small_signal_gain = &caldata->small_signal_gain[chain];
661 u32 *pa_table = chan->pa_table[chain]; 662 u32 *pa_table = caldata->pa_table[chain];
662 u32 *data_L, *data_U; 663 u32 *data_L, *data_U;
663 int i, status = 0; 664 int i, status = 0;
664 u32 *buf; 665 u32 *buf;
665 u32 reg; 666 u32 reg;
666 667
667 memset(chan->pa_table[chain], 0, sizeof(chan->pa_table[chain])); 668 memset(caldata->pa_table[chain], 0, sizeof(caldata->pa_table[chain]));
668 669
669 buf = kmalloc(2 * 48 * sizeof(u32), GFP_ATOMIC); 670 buf = kmalloc(2 * 48 * sizeof(u32), GFP_ATOMIC);
670 if (!buf) 671 if (!buf)
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 11fc69bee58f..07f26ee7a723 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -609,6 +609,7 @@ struct ath_softc {
609struct ath_wiphy { 609struct ath_wiphy {
610 struct ath_softc *sc; /* shared for all virtual wiphys */ 610 struct ath_softc *sc; /* shared for all virtual wiphys */
611 struct ieee80211_hw *hw; 611 struct ieee80211_hw *hw;
612 struct ath9k_hw_cal_data caldata;
612 enum ath_wiphy_state { 613 enum ath_wiphy_state {
613 ATH_WIPHY_INACTIVE, 614 ATH_WIPHY_INACTIVE,
614 ATH_WIPHY_ACTIVE, 615 ATH_WIPHY_ACTIVE,
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index 294016f9ce7d..18b5c0dcc1fc 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -22,23 +22,6 @@
22/* We can tune this as we go by monitoring really low values */ 22/* We can tune this as we go by monitoring really low values */
23#define ATH9K_NF_TOO_LOW -60 23#define ATH9K_NF_TOO_LOW -60
24 24
25/* AR5416 may return very high value (like -31 dBm), in those cases the nf
26 * is incorrect and we should use the static NF value. Later we can try to
27 * find out why they are reporting these values */
28
29static bool ath9k_hw_nf_in_range(struct ath_hw *ah, s16 nf)
30{
31 if (nf > ATH9K_NF_TOO_LOW) {
32 ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE,
33 "noise floor value detected (%d) is "
34 "lower than what we think is a "
35 "reasonable value (%d)\n",
36 nf, ATH9K_NF_TOO_LOW);
37 return false;
38 }
39 return true;
40}
41
42static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) 25static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
43{ 26{
44 int16_t nfval; 27 int16_t nfval;
@@ -121,6 +104,19 @@ void ath9k_hw_reset_calibration(struct ath_hw *ah,
121 ah->cal_samples = 0; 104 ah->cal_samples = 0;
122} 105}
123 106
107static s16 ath9k_hw_get_default_nf(struct ath_hw *ah,
108 struct ath9k_channel *chan)
109{
110 struct ath_nf_limits *limit;
111
112 if (!chan || IS_CHAN_2GHZ(chan))
113 limit = &ah->nf_2g;
114 else
115 limit = &ah->nf_5g;
116
117 return limit->nominal;
118}
119
124/* This is done for the currently configured channel */ 120/* This is done for the currently configured channel */
125bool ath9k_hw_reset_calvalid(struct ath_hw *ah) 121bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
126{ 122{
@@ -128,7 +124,7 @@ bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
128 struct ieee80211_conf *conf = &common->hw->conf; 124 struct ieee80211_conf *conf = &common->hw->conf;
129 struct ath9k_cal_list *currCal = ah->cal_list_curr; 125 struct ath9k_cal_list *currCal = ah->cal_list_curr;
130 126
131 if (!ah->curchan) 127 if (!ah->caldata)
132 return true; 128 return true;
133 129
134 if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah)) 130 if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
@@ -151,7 +147,7 @@ bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
151 "Resetting Cal %d state for channel %u\n", 147 "Resetting Cal %d state for channel %u\n",
152 currCal->calData->calType, conf->channel->center_freq); 148 currCal->calData->calType, conf->channel->center_freq);
153 149
154 ah->curchan->CalValid &= ~currCal->calData->calType; 150 ah->caldata->CalValid &= ~currCal->calData->calType;
155 currCal->calState = CAL_WAITING; 151 currCal->calState = CAL_WAITING;
156 152
157 return false; 153 return false;
@@ -175,19 +171,28 @@ void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update)
175 171
176void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) 172void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
177{ 173{
178 struct ath9k_nfcal_hist *h; 174 struct ath9k_nfcal_hist *h = NULL;
179 unsigned i, j; 175 unsigned i, j;
180 int32_t val; 176 int32_t val;
181 u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; 177 u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
182 struct ath_common *common = ath9k_hw_common(ah); 178 struct ath_common *common = ath9k_hw_common(ah);
179 s16 default_nf = ath9k_hw_get_default_nf(ah, chan);
183 180
184 h = ah->nfCalHist; 181 if (ah->caldata)
182 h = ah->caldata->nfCalHist;
185 183
186 for (i = 0; i < NUM_NF_READINGS; i++) { 184 for (i = 0; i < NUM_NF_READINGS; i++) {
187 if (chainmask & (1 << i)) { 185 if (chainmask & (1 << i)) {
186 s16 nfval;
187
188 if (h)
189 nfval = h[i].privNF;
190 else
191 nfval = default_nf;
192
188 val = REG_READ(ah, ah->nf_regs[i]); 193 val = REG_READ(ah, ah->nf_regs[i]);
189 val &= 0xFFFFFE00; 194 val &= 0xFFFFFE00;
190 val |= (((u32) (h[i].privNF) << 1) & 0x1ff); 195 val |= (((u32) nfval << 1) & 0x1ff);
191 REG_WRITE(ah, ah->nf_regs[i], val); 196 REG_WRITE(ah, ah->nf_regs[i], val);
192 } 197 }
193 } 198 }
@@ -291,14 +296,18 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah,
291 int16_t nfarray[NUM_NF_READINGS] = { 0 }; 296 int16_t nfarray[NUM_NF_READINGS] = { 0 };
292 struct ath9k_nfcal_hist *h; 297 struct ath9k_nfcal_hist *h;
293 struct ieee80211_channel *c = chan->chan; 298 struct ieee80211_channel *c = chan->chan;
299 struct ath9k_hw_cal_data *caldata = ah->caldata;
300
301 if (!caldata)
302 return ath9k_hw_get_default_nf(ah, chan);
294 303
295 chan->channelFlags &= (~CHANNEL_CW_INT); 304 chan->channelFlags &= (~CHANNEL_CW_INT);
296 if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { 305 if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
297 ath_print(common, ATH_DBG_CALIBRATE, 306 ath_print(common, ATH_DBG_CALIBRATE,
298 "NF did not complete in calibration window\n"); 307 "NF did not complete in calibration window\n");
299 nf = 0; 308 nf = 0;
300 chan->rawNoiseFloor = nf; 309 caldata->rawNoiseFloor = nf;
301 return chan->rawNoiseFloor; 310 return caldata->rawNoiseFloor;
302 } else { 311 } else {
303 ath9k_hw_do_getnf(ah, nfarray); 312 ath9k_hw_do_getnf(ah, nfarray);
304 ath9k_hw_nf_sanitize(ah, nfarray); 313 ath9k_hw_nf_sanitize(ah, nfarray);
@@ -313,47 +322,41 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah,
313 } 322 }
314 } 323 }
315 324
316 h = ah->nfCalHist; 325 h = caldata->nfCalHist;
317 326
318 ath9k_hw_update_nfcal_hist_buffer(h, nfarray); 327 ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
319 chan->rawNoiseFloor = h[0].privNF; 328 caldata->rawNoiseFloor = h[0].privNF;
320 329
321 return chan->rawNoiseFloor; 330 return ah->caldata->rawNoiseFloor;
322} 331}
323 332
324void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah) 333void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
334 struct ath9k_channel *chan)
325{ 335{
326 struct ath_nf_limits *limit; 336 struct ath9k_nfcal_hist *h;
337 s16 default_nf;
327 int i, j; 338 int i, j;
328 339
329 if (!ah->curchan || IS_CHAN_2GHZ(ah->curchan)) 340 if (!ah->caldata)
330 limit = &ah->nf_2g; 341 return;
331 else
332 limit = &ah->nf_5g;
333 342
343 h = ah->caldata->nfCalHist;
344 default_nf = ath9k_hw_get_default_nf(ah, chan);
334 for (i = 0; i < NUM_NF_READINGS; i++) { 345 for (i = 0; i < NUM_NF_READINGS; i++) {
335 ah->nfCalHist[i].currIndex = 0; 346 h[i].currIndex = 0;
336 ah->nfCalHist[i].privNF = limit->nominal; 347 h[i].privNF = default_nf;
337 ah->nfCalHist[i].invalidNFcount = 348 h[i].invalidNFcount = AR_PHY_CCA_FILTERWINDOW_LENGTH;
338 AR_PHY_CCA_FILTERWINDOW_LENGTH;
339 for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) { 349 for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
340 ah->nfCalHist[i].nfCalBuffer[j] = limit->nominal; 350 h[i].nfCalBuffer[j] = default_nf;
341 } 351 }
342 } 352 }
343} 353}
344 354
345s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) 355s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
346{ 356{
347 s16 nf; 357 if (!ah->caldata || !ah->caldata->rawNoiseFloor)
348 358 return ath9k_hw_get_default_nf(ah, chan);
349 if (chan->rawNoiseFloor == 0)
350 nf = -96;
351 else
352 nf = chan->rawNoiseFloor;
353
354 if (!ath9k_hw_nf_in_range(ah, nf))
355 nf = ATH_DEFAULT_NOISE_FLOOR;
356 359
357 return nf; 360 return ah->caldata->rawNoiseFloor;
358} 361}
359EXPORT_SYMBOL(ath9k_hw_getchan_noise); 362EXPORT_SYMBOL(ath9k_hw_getchan_noise);
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h
index bf4474220d1d..ca2e6b39c1d4 100644
--- a/drivers/net/wireless/ath/ath9k/calib.h
+++ b/drivers/net/wireless/ath/ath9k/calib.h
@@ -112,7 +112,8 @@ void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update);
112void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan); 112void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan);
113int16_t ath9k_hw_getnf(struct ath_hw *ah, 113int16_t ath9k_hw_getnf(struct ath_hw *ah,
114 struct ath9k_channel *chan); 114 struct ath9k_channel *chan);
115void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah); 115void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
116 struct ath9k_channel *chan);
116s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); 117s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan);
117void ath9k_hw_reset_calibration(struct ath_hw *ah, 118void ath9k_hw_reset_calibration(struct ath_hw *ah,
118 struct ath9k_cal_list *currCal); 119 struct ath9k_cal_list *currCal);
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 3756400e6bf9..43b9e21bc562 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -353,6 +353,8 @@ struct ath9k_htc_priv {
353 u16 seq_no; 353 u16 seq_no;
354 u32 bmiss_cnt; 354 u32 bmiss_cnt;
355 355
356 struct ath9k_hw_cal_data caldata[38];
357
356 spinlock_t beacon_lock; 358 spinlock_t beacon_lock;
357 359
358 bool tx_queues_stop; 360 bool tx_queues_stop;
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index cf9bcc67ade2..ebed9d1691a5 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -125,6 +125,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
125 struct ieee80211_conf *conf = &common->hw->conf; 125 struct ieee80211_conf *conf = &common->hw->conf;
126 bool fastcc = true; 126 bool fastcc = true;
127 struct ieee80211_channel *channel = hw->conf.channel; 127 struct ieee80211_channel *channel = hw->conf.channel;
128 struct ath9k_hw_cal_data *caldata;
128 enum htc_phymode mode; 129 enum htc_phymode mode;
129 __be16 htc_mode; 130 __be16 htc_mode;
130 u8 cmd_rsp; 131 u8 cmd_rsp;
@@ -149,7 +150,8 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
149 priv->ah->curchan->channel, 150 priv->ah->curchan->channel,
150 channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf)); 151 channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf));
151 152
152 ret = ath9k_hw_reset(ah, hchan, fastcc); 153 caldata = &priv->caldata[channel->hw_value];
154 ret = ath9k_hw_reset(ah, hchan, caldata, fastcc);
153 if (ret) { 155 if (ret) {
154 ath_print(common, ATH_DBG_FATAL, 156 ath_print(common, ATH_DBG_FATAL,
155 "Unable to reset channel (%u Mhz) " 157 "Unable to reset channel (%u Mhz) "
@@ -1028,7 +1030,7 @@ static void ath9k_htc_radio_enable(struct ieee80211_hw *hw)
1028 ah->curchan = ath9k_cmn_get_curchannel(hw, ah); 1030 ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
1029 1031
1030 /* Reset the HW */ 1032 /* Reset the HW */
1031 ret = ath9k_hw_reset(ah, ah->curchan, false); 1033 ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
1032 if (ret) { 1034 if (ret) {
1033 ath_print(common, ATH_DBG_FATAL, 1035 ath_print(common, ATH_DBG_FATAL,
1034 "Unable to reset hardware; reset status %d " 1036 "Unable to reset hardware; reset status %d "
@@ -1091,7 +1093,7 @@ static void ath9k_htc_radio_disable(struct ieee80211_hw *hw)
1091 ah->curchan = ath9k_cmn_get_curchannel(hw, ah); 1093 ah->curchan = ath9k_cmn_get_curchannel(hw, ah);
1092 1094
1093 /* Reset the HW */ 1095 /* Reset the HW */
1094 ret = ath9k_hw_reset(ah, ah->curchan, false); 1096 ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
1095 if (ret) { 1097 if (ret) {
1096 ath_print(common, ATH_DBG_FATAL, 1098 ath_print(common, ATH_DBG_FATAL,
1097 "Unable to reset hardware; reset status %d " 1099 "Unable to reset hardware; reset status %d "
@@ -1179,7 +1181,7 @@ static int ath9k_htc_start(struct ieee80211_hw *hw)
1179 ath9k_hw_configpcipowersave(ah, 0, 0); 1181 ath9k_hw_configpcipowersave(ah, 0, 0);
1180 1182
1181 ath9k_hw_htc_resetinit(ah); 1183 ath9k_hw_htc_resetinit(ah);
1182 ret = ath9k_hw_reset(ah, init_channel, false); 1184 ret = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
1183 if (ret) { 1185 if (ret) {
1184 ath_print(common, ATH_DBG_FATAL, 1186 ath_print(common, ATH_DBG_FATAL,
1185 "Unable to reset hardware; reset status %d " 1187 "Unable to reset hardware; reset status %d "
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 257b623185cd..3384ca164562 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -610,7 +610,6 @@ static int __ath9k_hw_init(struct ath_hw *ah)
610 else 610 else
611 ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S); 611 ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S);
612 612
613 ath9k_init_nfcal_hist_buffer(ah);
614 ah->bb_watchdog_timeout_ms = 25; 613 ah->bb_watchdog_timeout_ms = 25;
615 614
616 common->state = ATH_HW_INITIALIZED; 615 common->state = ATH_HW_INITIALIZED;
@@ -1183,9 +1182,6 @@ static bool ath9k_hw_channel_change(struct ath_hw *ah,
1183 1182
1184 ath9k_hw_spur_mitigate_freq(ah, chan); 1183 ath9k_hw_spur_mitigate_freq(ah, chan);
1185 1184
1186 if (!chan->oneTimeCalsDone)
1187 chan->oneTimeCalsDone = true;
1188
1189 return true; 1185 return true;
1190} 1186}
1191 1187
@@ -1218,7 +1214,7 @@ bool ath9k_hw_check_alive(struct ath_hw *ah)
1218EXPORT_SYMBOL(ath9k_hw_check_alive); 1214EXPORT_SYMBOL(ath9k_hw_check_alive);
1219 1215
1220int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, 1216int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
1221 bool bChannelChange) 1217 struct ath9k_hw_cal_data *caldata, bool bChannelChange)
1222{ 1218{
1223 struct ath_common *common = ath9k_hw_common(ah); 1219 struct ath_common *common = ath9k_hw_common(ah);
1224 u32 saveLedState; 1220 u32 saveLedState;
@@ -1243,9 +1239,19 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
1243 if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) 1239 if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE))
1244 return -EIO; 1240 return -EIO;
1245 1241
1246 if (curchan && !ah->chip_fullsleep) 1242 if (curchan && !ah->chip_fullsleep && ah->caldata)
1247 ath9k_hw_getnf(ah, curchan); 1243 ath9k_hw_getnf(ah, curchan);
1248 1244
1245 ah->caldata = caldata;
1246 if (caldata &&
1247 (chan->channel != caldata->channel ||
1248 (chan->channelFlags & ~CHANNEL_CW_INT) !=
1249 (caldata->channelFlags & ~CHANNEL_CW_INT))) {
1250 /* Operating channel changed, reset channel calibration data */
1251 memset(caldata, 0, sizeof(*caldata));
1252 ath9k_init_nfcal_hist_buffer(ah, chan);
1253 }
1254
1249 if (bChannelChange && 1255 if (bChannelChange &&
1250 (ah->chip_fullsleep != true) && 1256 (ah->chip_fullsleep != true) &&
1251 (ah->curchan != NULL) && 1257 (ah->curchan != NULL) &&
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 2d30efc0b94f..c1b701119d88 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -346,19 +346,24 @@ enum ath9k_int {
346 CHANNEL_HT40PLUS | \ 346 CHANNEL_HT40PLUS | \
347 CHANNEL_HT40MINUS) 347 CHANNEL_HT40MINUS)
348 348
349struct ath9k_channel { 349struct ath9k_hw_cal_data {
350 struct ieee80211_channel *chan;
351 u16 channel; 350 u16 channel;
352 u32 channelFlags; 351 u32 channelFlags;
353 u32 chanmode;
354 int32_t CalValid; 352 int32_t CalValid;
355 bool oneTimeCalsDone;
356 int8_t iCoff; 353 int8_t iCoff;
357 int8_t qCoff; 354 int8_t qCoff;
358 int16_t rawNoiseFloor; 355 int16_t rawNoiseFloor;
359 bool paprd_done; 356 bool paprd_done;
360 u16 small_signal_gain[AR9300_MAX_CHAINS]; 357 u16 small_signal_gain[AR9300_MAX_CHAINS];
361 u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ]; 358 u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ];
359 struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
360};
361
362struct ath9k_channel {
363 struct ieee80211_channel *chan;
364 u16 channel;
365 u32 channelFlags;
366 u32 chanmode;
362}; 367};
363 368
364#define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ 369#define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \
@@ -669,7 +674,7 @@ struct ath_hw {
669 enum nl80211_iftype opmode; 674 enum nl80211_iftype opmode;
670 enum ath9k_power_mode power_mode; 675 enum ath9k_power_mode power_mode;
671 676
672 struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; 677 struct ath9k_hw_cal_data *caldata;
673 struct ath9k_pacal_info pacal_info; 678 struct ath9k_pacal_info pacal_info;
674 struct ar5416Stats stats; 679 struct ar5416Stats stats;
675 struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES]; 680 struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES];
@@ -863,7 +868,7 @@ const char *ath9k_hw_probe(u16 vendorid, u16 devid);
863void ath9k_hw_deinit(struct ath_hw *ah); 868void ath9k_hw_deinit(struct ath_hw *ah);
864int ath9k_hw_init(struct ath_hw *ah); 869int ath9k_hw_init(struct ath_hw *ah);
865int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, 870int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
866 bool bChannelChange); 871 struct ath9k_hw_cal_data *caldata, bool bChannelChange);
867int ath9k_hw_fill_cap_info(struct ath_hw *ah); 872int ath9k_hw_fill_cap_info(struct ath_hw *ah);
868u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan); 873u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan);
869 874
@@ -958,9 +963,10 @@ void ar9003_hw_bb_watchdog_read(struct ath_hw *ah);
958void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah); 963void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah);
959void ar9003_paprd_enable(struct ath_hw *ah, bool val); 964void ar9003_paprd_enable(struct ath_hw *ah, bool val);
960void ar9003_paprd_populate_single_table(struct ath_hw *ah, 965void ar9003_paprd_populate_single_table(struct ath_hw *ah,
961 struct ath9k_channel *chan, int chain); 966 struct ath9k_hw_cal_data *caldata,
962int ar9003_paprd_create_curve(struct ath_hw *ah, struct ath9k_channel *chan, 967 int chain);
963 int chain); 968int ar9003_paprd_create_curve(struct ath_hw *ah,
969 struct ath9k_hw_cal_data *caldata, int chain);
964int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain); 970int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain);
965int ar9003_paprd_init_table(struct ath_hw *ah); 971int ar9003_paprd_init_table(struct ath_hw *ah);
966bool ar9003_paprd_is_done(struct ath_hw *ah); 972bool ar9003_paprd_is_done(struct ath_hw *ah);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 8387ad5b4897..3caa32316e7b 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -183,11 +183,13 @@ static void ath_start_ani(struct ath_common *common)
183int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, 183int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
184 struct ath9k_channel *hchan) 184 struct ath9k_channel *hchan)
185{ 185{
186 struct ath_wiphy *aphy = hw->priv;
186 struct ath_hw *ah = sc->sc_ah; 187 struct ath_hw *ah = sc->sc_ah;
187 struct ath_common *common = ath9k_hw_common(ah); 188 struct ath_common *common = ath9k_hw_common(ah);
188 struct ieee80211_conf *conf = &common->hw->conf; 189 struct ieee80211_conf *conf = &common->hw->conf;
189 bool fastcc = true, stopped; 190 bool fastcc = true, stopped;
190 struct ieee80211_channel *channel = hw->conf.channel; 191 struct ieee80211_channel *channel = hw->conf.channel;
192 struct ath9k_hw_cal_data *caldata = NULL;
191 int r; 193 int r;
192 194
193 if (sc->sc_flags & SC_OP_INVALID) 195 if (sc->sc_flags & SC_OP_INVALID)
@@ -220,6 +222,9 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
220 if (!stopped || !(sc->sc_flags & SC_OP_OFFCHANNEL)) 222 if (!stopped || !(sc->sc_flags & SC_OP_OFFCHANNEL))
221 fastcc = false; 223 fastcc = false;
222 224
225 if (!(sc->sc_flags & SC_OP_OFFCHANNEL))
226 caldata = &aphy->caldata;
227
223 ath_print(common, ATH_DBG_CONFIG, 228 ath_print(common, ATH_DBG_CONFIG,
224 "(%u MHz) -> (%u MHz), conf_is_ht40: %d\n", 229 "(%u MHz) -> (%u MHz), conf_is_ht40: %d\n",
225 sc->sc_ah->curchan->channel, 230 sc->sc_ah->curchan->channel,
@@ -227,7 +232,7 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
227 232
228 spin_lock_bh(&sc->sc_resetlock); 233 spin_lock_bh(&sc->sc_resetlock);
229 234
230 r = ath9k_hw_reset(ah, hchan, fastcc); 235 r = ath9k_hw_reset(ah, hchan, caldata, fastcc);
231 if (r) { 236 if (r) {
232 ath_print(common, ATH_DBG_FATAL, 237 ath_print(common, ATH_DBG_FATAL,
233 "Unable to reset channel (%u MHz), " 238 "Unable to reset channel (%u MHz), "
@@ -263,9 +268,10 @@ int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
263static void ath_paprd_activate(struct ath_softc *sc) 268static void ath_paprd_activate(struct ath_softc *sc)
264{ 269{
265 struct ath_hw *ah = sc->sc_ah; 270 struct ath_hw *ah = sc->sc_ah;
271 struct ath9k_hw_cal_data *caldata = ah->caldata;
266 int chain; 272 int chain;
267 273
268 if (!ah->curchan->paprd_done) 274 if (!caldata || !caldata->paprd_done)
269 return; 275 return;
270 276
271 ath9k_ps_wakeup(sc); 277 ath9k_ps_wakeup(sc);
@@ -274,7 +280,7 @@ static void ath_paprd_activate(struct ath_softc *sc)
274 if (!(ah->caps.tx_chainmask & BIT(chain))) 280 if (!(ah->caps.tx_chainmask & BIT(chain)))
275 continue; 281 continue;
276 282
277 ar9003_paprd_populate_single_table(ah, ah->curchan, chain); 283 ar9003_paprd_populate_single_table(ah, caldata, chain);
278 } 284 }
279 285
280 ar9003_paprd_enable(ah, true); 286 ar9003_paprd_enable(ah, true);
@@ -292,6 +298,7 @@ void ath_paprd_calibrate(struct work_struct *work)
292 int band = hw->conf.channel->band; 298 int band = hw->conf.channel->band;
293 struct ieee80211_supported_band *sband = &sc->sbands[band]; 299 struct ieee80211_supported_band *sband = &sc->sbands[band];
294 struct ath_tx_control txctl; 300 struct ath_tx_control txctl;
301 struct ath9k_hw_cal_data *caldata = ah->caldata;
295 int qnum, ftype; 302 int qnum, ftype;
296 int chain_ok = 0; 303 int chain_ok = 0;
297 int chain; 304 int chain;
@@ -299,6 +306,9 @@ void ath_paprd_calibrate(struct work_struct *work)
299 int time_left; 306 int time_left;
300 int i; 307 int i;
301 308
309 if (!caldata)
310 return;
311
302 skb = alloc_skb(len, GFP_KERNEL); 312 skb = alloc_skb(len, GFP_KERNEL);
303 if (!skb) 313 if (!skb)
304 return; 314 return;
@@ -353,7 +363,7 @@ void ath_paprd_calibrate(struct work_struct *work)
353 if (!ar9003_paprd_is_done(ah)) 363 if (!ar9003_paprd_is_done(ah))
354 break; 364 break;
355 365
356 if (ar9003_paprd_create_curve(ah, ah->curchan, chain) != 0) 366 if (ar9003_paprd_create_curve(ah, caldata, chain) != 0)
357 break; 367 break;
358 368
359 chain_ok = 1; 369 chain_ok = 1;
@@ -361,7 +371,7 @@ void ath_paprd_calibrate(struct work_struct *work)
361 kfree_skb(skb); 371 kfree_skb(skb);
362 372
363 if (chain_ok) { 373 if (chain_ok) {
364 ah->curchan->paprd_done = true; 374 caldata->paprd_done = true;
365 ath_paprd_activate(sc); 375 ath_paprd_activate(sc);
366 } 376 }
367 377
@@ -470,8 +480,8 @@ set_timer:
470 cal_interval = min(cal_interval, (u32)short_cal_interval); 480 cal_interval = min(cal_interval, (u32)short_cal_interval);
471 481
472 mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); 482 mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval));
473 if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) { 483 if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) {
474 if (!sc->sc_ah->curchan->paprd_done) 484 if (!ah->caldata->paprd_done)
475 ieee80211_queue_work(sc->hw, &sc->paprd_work); 485 ieee80211_queue_work(sc->hw, &sc->paprd_work);
476 else 486 else
477 ath_paprd_activate(sc); 487 ath_paprd_activate(sc);
@@ -829,7 +839,7 @@ void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
829 ah->curchan = ath_get_curchannel(sc, sc->hw); 839 ah->curchan = ath_get_curchannel(sc, sc->hw);
830 840
831 spin_lock_bh(&sc->sc_resetlock); 841 spin_lock_bh(&sc->sc_resetlock);
832 r = ath9k_hw_reset(ah, ah->curchan, false); 842 r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
833 if (r) { 843 if (r) {
834 ath_print(common, ATH_DBG_FATAL, 844 ath_print(common, ATH_DBG_FATAL,
835 "Unable to reset channel (%u MHz), " 845 "Unable to reset channel (%u MHz), "
@@ -889,7 +899,7 @@ void ath_radio_disable(struct ath_softc *sc, struct ieee80211_hw *hw)
889 ah->curchan = ath_get_curchannel(sc, hw); 899 ah->curchan = ath_get_curchannel(sc, hw);
890 900
891 spin_lock_bh(&sc->sc_resetlock); 901 spin_lock_bh(&sc->sc_resetlock);
892 r = ath9k_hw_reset(ah, ah->curchan, false); 902 r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
893 if (r) { 903 if (r) {
894 ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, 904 ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL,
895 "Unable to reset channel (%u MHz), " 905 "Unable to reset channel (%u MHz), "
@@ -922,7 +932,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
922 ath_flushrecv(sc); 932 ath_flushrecv(sc);
923 933
924 spin_lock_bh(&sc->sc_resetlock); 934 spin_lock_bh(&sc->sc_resetlock);
925 r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false); 935 r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
926 if (r) 936 if (r)
927 ath_print(common, ATH_DBG_FATAL, 937 ath_print(common, ATH_DBG_FATAL,
928 "Unable to reset hardware; reset status %d\n", r); 938 "Unable to reset hardware; reset status %d\n", r);
@@ -1097,7 +1107,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
1097 * and then setup of the interrupt mask. 1107 * and then setup of the interrupt mask.
1098 */ 1108 */
1099 spin_lock_bh(&sc->sc_resetlock); 1109 spin_lock_bh(&sc->sc_resetlock);
1100 r = ath9k_hw_reset(ah, init_channel, false); 1110 r = ath9k_hw_reset(ah, init_channel, ah->caldata, false);
1101 if (r) { 1111 if (r) {
1102 ath_print(common, ATH_DBG_FATAL, 1112 ath_print(common, ATH_DBG_FATAL,
1103 "Unable to reset hardware; reset status %d " 1113 "Unable to reset hardware; reset status %d "
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 501b72821b4d..700ba8dee5a5 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -1181,7 +1181,7 @@ void ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
1181 "Failed to stop TX DMA. Resetting hardware!\n"); 1181 "Failed to stop TX DMA. Resetting hardware!\n");
1182 1182
1183 spin_lock_bh(&sc->sc_resetlock); 1183 spin_lock_bh(&sc->sc_resetlock);
1184 r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false); 1184 r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false);
1185 if (r) 1185 if (r)
1186 ath_print(common, ATH_DBG_FATAL, 1186 ath_print(common, ATH_DBG_FATAL,
1187 "Unable to reset hardware; reset status %d\n", 1187 "Unable to reset hardware; reset status %d\n",