| 1 | --- a/net/mac80211/main.c |
| 2 | +++ b/net/mac80211/main.c |
| 3 | @@ -103,11 +103,13 @@ int ieee80211_hw_config(struct ieee80211 |
| 4 | int ret = 0; |
| 5 | int power; |
| 6 | enum nl80211_channel_type channel_type; |
| 7 | + u32 offchannel_flag; |
| 8 | |
| 9 | might_sleep(); |
| 10 | |
| 11 | scan_chan = local->scan_channel; |
| 12 | |
| 13 | + offchannel_flag = local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; |
| 14 | if (scan_chan) { |
| 15 | chan = scan_chan; |
| 16 | channel_type = NL80211_CHAN_NO_HT; |
| 17 | @@ -121,8 +123,9 @@ int ieee80211_hw_config(struct ieee80211 |
| 18 | channel_type = local->_oper_channel_type; |
| 19 | local->hw.conf.flags &= ~IEEE80211_CONF_OFFCHANNEL; |
| 20 | } |
| 21 | + offchannel_flag ^= local->hw.conf.flags & IEEE80211_CONF_OFFCHANNEL; |
| 22 | |
| 23 | - if (chan != local->hw.conf.channel || |
| 24 | + if (offchannel_flag || chan != local->hw.conf.channel || |
| 25 | channel_type != local->hw.conf.channel_type) { |
| 26 | local->hw.conf.channel = chan; |
| 27 | local->hw.conf.channel_type = channel_type; |
| 28 | --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c |
| 29 | +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c |
| 30 | @@ -63,6 +63,7 @@ static bool ar9002_hw_per_calibration(st |
| 31 | u8 rxchainmask, |
| 32 | struct ath9k_cal_list *currCal) |
| 33 | { |
| 34 | + struct ath9k_hw_cal_data *caldata = ah->caldata; |
| 35 | bool iscaldone = false; |
| 36 | |
| 37 | if (currCal->calState == CAL_RUNNING) { |
| 38 | @@ -81,14 +82,14 @@ static bool ar9002_hw_per_calibration(st |
| 39 | } |
| 40 | |
| 41 | currCal->calData->calPostProc(ah, numChains); |
| 42 | - ichan->CalValid |= currCal->calData->calType; |
| 43 | + caldata->CalValid |= currCal->calData->calType; |
| 44 | currCal->calState = CAL_DONE; |
| 45 | iscaldone = true; |
| 46 | } else { |
| 47 | ar9002_hw_setup_calibration(ah, currCal); |
| 48 | } |
| 49 | } |
| 50 | - } else if (!(ichan->CalValid & currCal->calData->calType)) { |
| 51 | + } else if (!(caldata->CalValid & currCal->calData->calType)) { |
| 52 | ath9k_hw_reset_calibration(ah, currCal); |
| 53 | } |
| 54 | |
| 55 | @@ -686,8 +687,13 @@ static bool ar9002_hw_calibrate(struct a |
| 56 | { |
| 57 | bool iscaldone = true; |
| 58 | struct ath9k_cal_list *currCal = ah->cal_list_curr; |
| 59 | + bool nfcal, nfcal_pending = false; |
| 60 | |
| 61 | - if (currCal && |
| 62 | + nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF); |
| 63 | + if (ah->caldata) |
| 64 | + nfcal_pending = ah->caldata->nfcal_pending; |
| 65 | + |
| 66 | + if (currCal && !nfcal && |
| 67 | (currCal->calState == CAL_RUNNING || |
| 68 | currCal->calState == CAL_WAITING)) { |
| 69 | iscaldone = ar9002_hw_per_calibration(ah, chan, |
| 70 | @@ -703,7 +709,7 @@ static bool ar9002_hw_calibrate(struct a |
| 71 | } |
| 72 | |
| 73 | /* Do NF cal only at longer intervals */ |
| 74 | - if (longcal) { |
| 75 | + if (longcal || nfcal_pending) { |
| 76 | /* Do periodic PAOffset Cal */ |
| 77 | ar9002_hw_pa_cal(ah, false); |
| 78 | ar9002_hw_olc_temp_compensation(ah); |
| 79 | @@ -712,16 +718,18 @@ static bool ar9002_hw_calibrate(struct a |
| 80 | * Get the value from the previous NF cal and update |
| 81 | * history buffer. |
| 82 | */ |
| 83 | - ath9k_hw_getnf(ah, chan); |
| 84 | - |
| 85 | - /* |
| 86 | - * Load the NF from history buffer of the current channel. |
| 87 | - * NF is slow time-variant, so it is OK to use a historical |
| 88 | - * value. |
| 89 | - */ |
| 90 | - ath9k_hw_loadnf(ah, ah->curchan); |
| 91 | + if (ath9k_hw_getnf(ah, chan)) { |
| 92 | + /* |
| 93 | + * Load the NF from history buffer of the current |
| 94 | + * channel. |
| 95 | + * NF is slow time-variant, so it is OK to use a |
| 96 | + * historical value. |
| 97 | + */ |
| 98 | + ath9k_hw_loadnf(ah, ah->curchan); |
| 99 | + } |
| 100 | |
| 101 | - ath9k_hw_start_nfcal(ah); |
| 102 | + if (longcal) |
| 103 | + ath9k_hw_start_nfcal(ah, false); |
| 104 | } |
| 105 | |
| 106 | return iscaldone; |
| 107 | @@ -869,8 +877,10 @@ static bool ar9002_hw_init_cal(struct at |
| 108 | ar9002_hw_pa_cal(ah, true); |
| 109 | |
| 110 | /* Do NF Calibration after DC offset and other calibrations */ |
| 111 | - REG_WRITE(ah, AR_PHY_AGC_CONTROL, |
| 112 | - REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF); |
| 113 | + ath9k_hw_start_nfcal(ah, true); |
| 114 | + |
| 115 | + if (ah->caldata) |
| 116 | + ah->caldata->nfcal_pending = true; |
| 117 | |
| 118 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; |
| 119 | |
| 120 | @@ -901,7 +911,8 @@ static bool ar9002_hw_init_cal(struct at |
| 121 | ath9k_hw_reset_calibration(ah, ah->cal_list_curr); |
| 122 | } |
| 123 | |
| 124 | - chan->CalValid = 0; |
| 125 | + if (ah->caldata) |
| 126 | + ah->caldata->CalValid = 0; |
| 127 | |
| 128 | return true; |
| 129 | } |
| 130 | --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c |
| 131 | +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c |
| 132 | @@ -68,6 +68,7 @@ static bool ar9003_hw_per_calibration(st |
| 133 | u8 rxchainmask, |
| 134 | struct ath9k_cal_list *currCal) |
| 135 | { |
| 136 | + struct ath9k_hw_cal_data *caldata = ah->caldata; |
| 137 | /* Cal is assumed not done until explicitly set below */ |
| 138 | bool iscaldone = false; |
| 139 | |
| 140 | @@ -95,7 +96,7 @@ static bool ar9003_hw_per_calibration(st |
| 141 | currCal->calData->calPostProc(ah, numChains); |
| 142 | |
| 143 | /* Calibration has finished. */ |
| 144 | - ichan->CalValid |= currCal->calData->calType; |
| 145 | + caldata->CalValid |= currCal->calData->calType; |
| 146 | currCal->calState = CAL_DONE; |
| 147 | iscaldone = true; |
| 148 | } else { |
| 149 | @@ -106,7 +107,7 @@ static bool ar9003_hw_per_calibration(st |
| 150 | ar9003_hw_setup_calibration(ah, currCal); |
| 151 | } |
| 152 | } |
| 153 | - } else if (!(ichan->CalValid & currCal->calData->calType)) { |
| 154 | + } else if (!(caldata->CalValid & currCal->calData->calType)) { |
| 155 | /* If current cal is marked invalid in channel, kick it off */ |
| 156 | ath9k_hw_reset_calibration(ah, currCal); |
| 157 | } |
| 158 | @@ -149,6 +150,12 @@ static bool ar9003_hw_calibrate(struct a |
| 159 | /* Do NF cal only at longer intervals */ |
| 160 | if (longcal) { |
| 161 | /* |
| 162 | + * Get the value from the previous NF cal and update |
| 163 | + * history buffer. |
| 164 | + */ |
| 165 | + ath9k_hw_getnf(ah, chan); |
| 166 | + |
| 167 | + /* |
| 168 | * Load the NF from history buffer of the current channel. |
| 169 | * NF is slow time-variant, so it is OK to use a historical |
| 170 | * value. |
| 171 | @@ -156,7 +163,7 @@ static bool ar9003_hw_calibrate(struct a |
| 172 | ath9k_hw_loadnf(ah, ah->curchan); |
| 173 | |
| 174 | /* start NF calibration, without updating BB NF register */ |
| 175 | - ath9k_hw_start_nfcal(ah); |
| 176 | + ath9k_hw_start_nfcal(ah, false); |
| 177 | } |
| 178 | |
| 179 | return iscaldone; |
| 180 | @@ -762,6 +769,8 @@ static bool ar9003_hw_init_cal(struct at |
| 181 | /* Revert chainmasks to their original values before NF cal */ |
| 182 | ar9003_hw_set_chain_masks(ah, ah->rxchainmask, ah->txchainmask); |
| 183 | |
| 184 | + ath9k_hw_start_nfcal(ah, true); |
| 185 | + |
| 186 | /* Initialize list pointers */ |
| 187 | ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL; |
| 188 | |
| 189 | @@ -785,7 +794,8 @@ static bool ar9003_hw_init_cal(struct at |
| 190 | if (ah->cal_list_curr) |
| 191 | ath9k_hw_reset_calibration(ah, ah->cal_list_curr); |
| 192 | |
| 193 | - chan->CalValid = 0; |
| 194 | + if (ah->caldata) |
| 195 | + ah->caldata->CalValid = 0; |
| 196 | |
| 197 | return true; |
| 198 | } |
| 199 | --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c |
| 200 | +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c |
| 201 | @@ -542,7 +542,11 @@ static void ar9003_hw_prog_ini(struct at |
| 202 | u32 reg = INI_RA(iniArr, i, 0); |
| 203 | u32 val = INI_RA(iniArr, i, column); |
| 204 | |
| 205 | - REG_WRITE(ah, reg, val); |
| 206 | + if (reg >= 0x16000 && reg < 0x17000) |
| 207 | + ath9k_hw_analog_shift_regwrite(ah, reg, val); |
| 208 | + else |
| 209 | + REG_WRITE(ah, reg, val); |
| 210 | + |
| 211 | DO_DELAY(regWrites); |
| 212 | } |
| 213 | } |
| 214 | --- a/drivers/net/wireless/ath/ath9k/calib.c |
| 215 | +++ b/drivers/net/wireless/ath/ath9k/calib.c |
| 216 | @@ -22,23 +22,6 @@ |
| 217 | /* We can tune this as we go by monitoring really low values */ |
| 218 | #define ATH9K_NF_TOO_LOW -60 |
| 219 | |
| 220 | -/* AR5416 may return very high value (like -31 dBm), in those cases the nf |
| 221 | - * is incorrect and we should use the static NF value. Later we can try to |
| 222 | - * find out why they are reporting these values */ |
| 223 | - |
| 224 | -static bool ath9k_hw_nf_in_range(struct ath_hw *ah, s16 nf) |
| 225 | -{ |
| 226 | - if (nf > ATH9K_NF_TOO_LOW) { |
| 227 | - ath_print(ath9k_hw_common(ah), ATH_DBG_CALIBRATE, |
| 228 | - "noise floor value detected (%d) is " |
| 229 | - "lower than what we think is a " |
| 230 | - "reasonable value (%d)\n", |
| 231 | - nf, ATH9K_NF_TOO_LOW); |
| 232 | - return false; |
| 233 | - } |
| 234 | - return true; |
| 235 | -} |
| 236 | - |
| 237 | static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer) |
| 238 | { |
| 239 | int16_t nfval; |
| 240 | @@ -121,6 +104,19 @@ void ath9k_hw_reset_calibration(struct a |
| 241 | ah->cal_samples = 0; |
| 242 | } |
| 243 | |
| 244 | +static s16 ath9k_hw_get_default_nf(struct ath_hw *ah, |
| 245 | + struct ath9k_channel *chan) |
| 246 | +{ |
| 247 | + struct ath_nf_limits *limit; |
| 248 | + |
| 249 | + if (!chan || IS_CHAN_2GHZ(chan)) |
| 250 | + limit = &ah->nf_2g; |
| 251 | + else |
| 252 | + limit = &ah->nf_5g; |
| 253 | + |
| 254 | + return limit->nominal; |
| 255 | +} |
| 256 | + |
| 257 | /* This is done for the currently configured channel */ |
| 258 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah) |
| 259 | { |
| 260 | @@ -128,7 +124,7 @@ bool ath9k_hw_reset_calvalid(struct ath_ |
| 261 | struct ieee80211_conf *conf = &common->hw->conf; |
| 262 | struct ath9k_cal_list *currCal = ah->cal_list_curr; |
| 263 | |
| 264 | - if (!ah->curchan) |
| 265 | + if (!ah->caldata) |
| 266 | return true; |
| 267 | |
| 268 | if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah)) |
| 269 | @@ -151,37 +147,55 @@ bool ath9k_hw_reset_calvalid(struct ath_ |
| 270 | "Resetting Cal %d state for channel %u\n", |
| 271 | currCal->calData->calType, conf->channel->center_freq); |
| 272 | |
| 273 | - ah->curchan->CalValid &= ~currCal->calData->calType; |
| 274 | + ah->caldata->CalValid &= ~currCal->calData->calType; |
| 275 | currCal->calState = CAL_WAITING; |
| 276 | |
| 277 | return false; |
| 278 | } |
| 279 | EXPORT_SYMBOL(ath9k_hw_reset_calvalid); |
| 280 | |
| 281 | -void ath9k_hw_start_nfcal(struct ath_hw *ah) |
| 282 | +void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update) |
| 283 | { |
| 284 | + if (ah->caldata) |
| 285 | + ah->caldata->nfcal_pending = true; |
| 286 | + |
| 287 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, |
| 288 | AR_PHY_AGC_CONTROL_ENABLE_NF); |
| 289 | - REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, |
| 290 | + |
| 291 | + if (update) |
| 292 | + REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, |
| 293 | + AR_PHY_AGC_CONTROL_NO_UPDATE_NF); |
| 294 | + else |
| 295 | + REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, |
| 296 | AR_PHY_AGC_CONTROL_NO_UPDATE_NF); |
| 297 | + |
| 298 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); |
| 299 | } |
| 300 | |
| 301 | void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) |
| 302 | { |
| 303 | - struct ath9k_nfcal_hist *h; |
| 304 | + struct ath9k_nfcal_hist *h = NULL; |
| 305 | unsigned i, j; |
| 306 | int32_t val; |
| 307 | u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; |
| 308 | struct ath_common *common = ath9k_hw_common(ah); |
| 309 | + s16 default_nf = ath9k_hw_get_default_nf(ah, chan); |
| 310 | |
| 311 | - h = ah->nfCalHist; |
| 312 | + if (ah->caldata) |
| 313 | + h = ah->caldata->nfCalHist; |
| 314 | |
| 315 | for (i = 0; i < NUM_NF_READINGS; i++) { |
| 316 | if (chainmask & (1 << i)) { |
| 317 | + s16 nfval; |
| 318 | + |
| 319 | + if (h) |
| 320 | + nfval = h[i].privNF; |
| 321 | + else |
| 322 | + nfval = default_nf; |
| 323 | + |
| 324 | val = REG_READ(ah, ah->nf_regs[i]); |
| 325 | val &= 0xFFFFFE00; |
| 326 | - val |= (((u32) (h[i].privNF) << 1) & 0x1ff); |
| 327 | + val |= (((u32) nfval << 1) & 0x1ff); |
| 328 | REG_WRITE(ah, ah->nf_regs[i], val); |
| 329 | } |
| 330 | } |
| 331 | @@ -277,22 +291,25 @@ static void ath9k_hw_nf_sanitize(struct |
| 332 | } |
| 333 | } |
| 334 | |
| 335 | -int16_t ath9k_hw_getnf(struct ath_hw *ah, |
| 336 | - struct ath9k_channel *chan) |
| 337 | +bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan) |
| 338 | { |
| 339 | struct ath_common *common = ath9k_hw_common(ah); |
| 340 | int16_t nf, nfThresh; |
| 341 | int16_t nfarray[NUM_NF_READINGS] = { 0 }; |
| 342 | struct ath9k_nfcal_hist *h; |
| 343 | struct ieee80211_channel *c = chan->chan; |
| 344 | + struct ath9k_hw_cal_data *caldata = ah->caldata; |
| 345 | + |
| 346 | + if (!caldata) |
| 347 | + return false; |
| 348 | |
| 349 | chan->channelFlags &= (~CHANNEL_CW_INT); |
| 350 | if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { |
| 351 | ath_print(common, ATH_DBG_CALIBRATE, |
| 352 | "NF did not complete in calibration window\n"); |
| 353 | nf = 0; |
| 354 | - chan->rawNoiseFloor = nf; |
| 355 | - return chan->rawNoiseFloor; |
| 356 | + caldata->rawNoiseFloor = nf; |
| 357 | + return false; |
| 358 | } else { |
| 359 | ath9k_hw_do_getnf(ah, nfarray); |
| 360 | ath9k_hw_nf_sanitize(ah, nfarray); |
| 361 | @@ -307,47 +324,40 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah |
| 362 | } |
| 363 | } |
| 364 | |
| 365 | - h = ah->nfCalHist; |
| 366 | - |
| 367 | + h = caldata->nfCalHist; |
| 368 | + caldata->nfcal_pending = false; |
| 369 | ath9k_hw_update_nfcal_hist_buffer(h, nfarray); |
| 370 | - chan->rawNoiseFloor = h[0].privNF; |
| 371 | - |
| 372 | - return chan->rawNoiseFloor; |
| 373 | + caldata->rawNoiseFloor = h[0].privNF; |
| 374 | + return true; |
| 375 | } |
| 376 | |
| 377 | -void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah) |
| 378 | +void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, |
| 379 | + struct ath9k_channel *chan) |
| 380 | { |
| 381 | - struct ath_nf_limits *limit; |
| 382 | + struct ath9k_nfcal_hist *h; |
| 383 | + s16 default_nf; |
| 384 | int i, j; |
| 385 | |
| 386 | - if (!ah->curchan || IS_CHAN_2GHZ(ah->curchan)) |
| 387 | - limit = &ah->nf_2g; |
| 388 | - else |
| 389 | - limit = &ah->nf_5g; |
| 390 | + if (!ah->caldata) |
| 391 | + return; |
| 392 | |
| 393 | + h = ah->caldata->nfCalHist; |
| 394 | + default_nf = ath9k_hw_get_default_nf(ah, chan); |
| 395 | for (i = 0; i < NUM_NF_READINGS; i++) { |
| 396 | - ah->nfCalHist[i].currIndex = 0; |
| 397 | - ah->nfCalHist[i].privNF = limit->nominal; |
| 398 | - ah->nfCalHist[i].invalidNFcount = |
| 399 | - AR_PHY_CCA_FILTERWINDOW_LENGTH; |
| 400 | + h[i].currIndex = 0; |
| 401 | + h[i].privNF = default_nf; |
| 402 | + h[i].invalidNFcount = AR_PHY_CCA_FILTERWINDOW_LENGTH; |
| 403 | for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) { |
| 404 | - ah->nfCalHist[i].nfCalBuffer[j] = limit->nominal; |
| 405 | + h[i].nfCalBuffer[j] = default_nf; |
| 406 | } |
| 407 | } |
| 408 | } |
| 409 | |
| 410 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan) |
| 411 | { |
| 412 | - s16 nf; |
| 413 | - |
| 414 | - if (chan->rawNoiseFloor == 0) |
| 415 | - nf = -96; |
| 416 | - else |
| 417 | - nf = chan->rawNoiseFloor; |
| 418 | - |
| 419 | - if (!ath9k_hw_nf_in_range(ah, nf)) |
| 420 | - nf = ATH_DEFAULT_NOISE_FLOOR; |
| 421 | + if (!ah->caldata || !ah->caldata->rawNoiseFloor) |
| 422 | + return ath9k_hw_get_default_nf(ah, chan); |
| 423 | |
| 424 | - return nf; |
| 425 | + return ah->caldata->rawNoiseFloor; |
| 426 | } |
| 427 | EXPORT_SYMBOL(ath9k_hw_getchan_noise); |
| 428 | --- a/drivers/net/wireless/ath/ath9k/calib.h |
| 429 | +++ b/drivers/net/wireless/ath/ath9k/calib.h |
| 430 | @@ -108,11 +108,11 @@ struct ath9k_pacal_info{ |
| 431 | }; |
| 432 | |
| 433 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah); |
| 434 | -void ath9k_hw_start_nfcal(struct ath_hw *ah); |
| 435 | +void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update); |
| 436 | void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan); |
| 437 | -int16_t ath9k_hw_getnf(struct ath_hw *ah, |
| 438 | - struct ath9k_channel *chan); |
| 439 | -void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah); |
| 440 | +bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan); |
| 441 | +void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, |
| 442 | + struct ath9k_channel *chan); |
| 443 | s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan); |
| 444 | void ath9k_hw_reset_calibration(struct ath_hw *ah, |
| 445 | struct ath9k_cal_list *currCal); |
| 446 | --- a/drivers/net/wireless/ath/ath9k/hw.c |
| 447 | +++ b/drivers/net/wireless/ath/ath9k/hw.c |
| 448 | @@ -622,7 +622,6 @@ static int __ath9k_hw_init(struct ath_hw |
| 449 | else |
| 450 | ah->tx_trig_level = (AR_FTRIG_512B >> AR_FTRIG_S); |
| 451 | |
| 452 | - ath9k_init_nfcal_hist_buffer(ah); |
| 453 | ah->bb_watchdog_timeout_ms = 25; |
| 454 | |
| 455 | common->state = ATH_HW_INITIALIZED; |
| 456 | @@ -1195,9 +1194,6 @@ static bool ath9k_hw_channel_change(stru |
| 457 | |
| 458 | ath9k_hw_spur_mitigate_freq(ah, chan); |
| 459 | |
| 460 | - if (!chan->oneTimeCalsDone) |
| 461 | - chan->oneTimeCalsDone = true; |
| 462 | - |
| 463 | return true; |
| 464 | } |
| 465 | |
| 466 | @@ -1230,7 +1226,7 @@ bool ath9k_hw_check_alive(struct ath_hw |
| 467 | EXPORT_SYMBOL(ath9k_hw_check_alive); |
| 468 | |
| 469 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, |
| 470 | - bool bChannelChange) |
| 471 | + struct ath9k_hw_cal_data *caldata, bool bChannelChange) |
| 472 | { |
| 473 | struct ath_common *common = ath9k_hw_common(ah); |
| 474 | u32 saveLedState; |
| 475 | @@ -1255,9 +1251,19 @@ int ath9k_hw_reset(struct ath_hw *ah, st |
| 476 | if (!ath9k_hw_setpower(ah, ATH9K_PM_AWAKE)) |
| 477 | return -EIO; |
| 478 | |
| 479 | - if (curchan && !ah->chip_fullsleep) |
| 480 | + if (curchan && !ah->chip_fullsleep && ah->caldata) |
| 481 | ath9k_hw_getnf(ah, curchan); |
| 482 | |
| 483 | + ah->caldata = caldata; |
| 484 | + if (caldata && |
| 485 | + (chan->channel != caldata->channel || |
| 486 | + (chan->channelFlags & ~CHANNEL_CW_INT) != |
| 487 | + (caldata->channelFlags & ~CHANNEL_CW_INT))) { |
| 488 | + /* Operating channel changed, reset channel calibration data */ |
| 489 | + memset(caldata, 0, sizeof(*caldata)); |
| 490 | + ath9k_init_nfcal_hist_buffer(ah, chan); |
| 491 | + } |
| 492 | + |
| 493 | if (bChannelChange && |
| 494 | (ah->chip_fullsleep != true) && |
| 495 | (ah->curchan != NULL) && |
| 496 | @@ -1268,7 +1274,7 @@ int ath9k_hw_reset(struct ath_hw *ah, st |
| 497 | |
| 498 | if (ath9k_hw_channel_change(ah, chan)) { |
| 499 | ath9k_hw_loadnf(ah, ah->curchan); |
| 500 | - ath9k_hw_start_nfcal(ah); |
| 501 | + ath9k_hw_start_nfcal(ah, true); |
| 502 | return 0; |
| 503 | } |
| 504 | } |
| 505 | @@ -1473,11 +1479,8 @@ int ath9k_hw_reset(struct ath_hw *ah, st |
| 506 | if (ah->btcoex_hw.enabled) |
| 507 | ath9k_hw_btcoex_enable(ah); |
| 508 | |
| 509 | - if (AR_SREV_9300_20_OR_LATER(ah)) { |
| 510 | - ath9k_hw_loadnf(ah, curchan); |
| 511 | - ath9k_hw_start_nfcal(ah); |
| 512 | + if (AR_SREV_9300_20_OR_LATER(ah)) |
| 513 | ar9003_hw_bb_watchdog_config(ah); |
| 514 | - } |
| 515 | |
| 516 | return 0; |
| 517 | } |
| 518 | --- a/drivers/net/wireless/ath/ath9k/main.c |
| 519 | +++ b/drivers/net/wireless/ath/ath9k/main.c |
| 520 | @@ -155,6 +155,27 @@ void ath9k_ps_restore(struct ath_softc * |
| 521 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
| 522 | } |
| 523 | |
| 524 | +static void ath_start_ani(struct ath_common *common) |
| 525 | +{ |
| 526 | + struct ath_hw *ah = common->ah; |
| 527 | + unsigned long timestamp = jiffies_to_msecs(jiffies); |
| 528 | + struct ath_softc *sc = (struct ath_softc *) common->priv; |
| 529 | + |
| 530 | + if (!(sc->sc_flags & SC_OP_ANI_RUN)) |
| 531 | + return; |
| 532 | + |
| 533 | + if (sc->sc_flags & SC_OP_OFFCHANNEL) |
| 534 | + return; |
| 535 | + |
| 536 | + common->ani.longcal_timer = timestamp; |
| 537 | + common->ani.shortcal_timer = timestamp; |
| 538 | + common->ani.checkani_timer = timestamp; |
| 539 | + |
| 540 | + mod_timer(&common->ani.timer, |
| 541 | + jiffies + |
| 542 | + msecs_to_jiffies((u32)ah->config.ani_poll_interval)); |
| 543 | +} |
| 544 | + |
| 545 | /* |
| 546 | * Set/change channels. If the channel is really being changed, it's done |
| 547 | * by reseting the chip. To accomplish this we must first cleanup any pending |
| 548 | @@ -163,16 +184,23 @@ void ath9k_ps_restore(struct ath_softc * |
| 549 | int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw, |
| 550 | struct ath9k_channel *hchan) |
| 551 | { |
| 552 | + struct ath_wiphy *aphy = hw->priv; |
| 553 | struct ath_hw *ah = sc->sc_ah; |
| 554 | struct ath_common *common = ath9k_hw_common(ah); |
| 555 | struct ieee80211_conf *conf = &common->hw->conf; |
| 556 | bool fastcc = true, stopped; |
| 557 | struct ieee80211_channel *channel = hw->conf.channel; |
| 558 | + struct ath9k_hw_cal_data *caldata = NULL; |
| 559 | int r; |
| 560 | |
| 561 | if (sc->sc_flags & SC_OP_INVALID) |
| 562 | return -EIO; |
| 563 | |
| 564 | + del_timer_sync(&common->ani.timer); |
| 565 | + cancel_work_sync(&sc->paprd_work); |
| 566 | + cancel_work_sync(&sc->hw_check_work); |
| 567 | + cancel_delayed_work_sync(&sc->tx_complete_work); |
| 568 | + |
| 569 | ath9k_ps_wakeup(sc); |
| 570 | |
| 571 | /* |
| 572 | @@ -192,9 +220,12 @@ int ath_set_channel(struct ath_softc *sc |
| 573 | * to flush data frames already in queue because of |
| 574 | * changing channel. */ |
| 575 | |
| 576 | - if (!stopped || (sc->sc_flags & SC_OP_FULL_RESET)) |
| 577 | + if (!stopped || !(sc->sc_flags & SC_OP_OFFCHANNEL)) |
| 578 | fastcc = false; |
| 579 | |
| 580 | + if (!(sc->sc_flags & SC_OP_OFFCHANNEL)) |
| 581 | + caldata = &aphy->caldata; |
| 582 | + |
| 583 | ath_print(common, ATH_DBG_CONFIG, |
| 584 | "(%u MHz) -> (%u MHz), conf_is_ht40: %d\n", |
| 585 | sc->sc_ah->curchan->channel, |
| 586 | @@ -202,7 +233,7 @@ int ath_set_channel(struct ath_softc *sc |
| 587 | |
| 588 | spin_lock_bh(&sc->sc_resetlock); |
| 589 | |
| 590 | - r = ath9k_hw_reset(ah, hchan, fastcc); |
| 591 | + r = ath9k_hw_reset(ah, hchan, caldata, fastcc); |
| 592 | if (r) { |
| 593 | ath_print(common, ATH_DBG_FATAL, |
| 594 | "Unable to reset channel (%u MHz), " |
| 595 | @@ -213,8 +244,6 @@ int ath_set_channel(struct ath_softc *sc |
| 596 | } |
| 597 | spin_unlock_bh(&sc->sc_resetlock); |
| 598 | |
| 599 | - sc->sc_flags &= ~SC_OP_FULL_RESET; |
| 600 | - |
| 601 | if (ath_startrecv(sc) != 0) { |
| 602 | ath_print(common, ATH_DBG_FATAL, |
| 603 | "Unable to restart recv logic\n"); |
| 604 | @@ -226,6 +255,12 @@ int ath_set_channel(struct ath_softc *sc |
| 605 | ath_update_txpow(sc); |
| 606 | ath9k_hw_set_interrupts(ah, ah->imask); |
| 607 | |
| 608 | + if (!(sc->sc_flags & (SC_OP_OFFCHANNEL | SC_OP_SCANNING))) { |
| 609 | + ath_start_ani(common); |
| 610 | + ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); |
| 611 | + ath_beacon_config(sc, NULL); |
| 612 | + } |
| 613 | + |
| 614 | ps_restore: |
| 615 | ath9k_ps_restore(sc); |
| 616 | return r; |
| 617 | @@ -234,17 +269,19 @@ int ath_set_channel(struct ath_softc *sc |
| 618 | static void ath_paprd_activate(struct ath_softc *sc) |
| 619 | { |
| 620 | struct ath_hw *ah = sc->sc_ah; |
| 621 | + struct ath9k_hw_cal_data *caldata = ah->caldata; |
| 622 | int chain; |
| 623 | |
| 624 | - if (!ah->curchan->paprd_done) |
| 625 | + if (!caldata || !caldata->paprd_done) |
| 626 | return; |
| 627 | |
| 628 | ath9k_ps_wakeup(sc); |
| 629 | + ar9003_paprd_enable(ah, false); |
| 630 | for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) { |
| 631 | if (!(ah->caps.tx_chainmask & BIT(chain))) |
| 632 | continue; |
| 633 | |
| 634 | - ar9003_paprd_populate_single_table(ah, ah->curchan, chain); |
| 635 | + ar9003_paprd_populate_single_table(ah, caldata, chain); |
| 636 | } |
| 637 | |
| 638 | ar9003_paprd_enable(ah, true); |
| 639 | @@ -262,6 +299,7 @@ void ath_paprd_calibrate(struct work_str |
| 640 | int band = hw->conf.channel->band; |
| 641 | struct ieee80211_supported_band *sband = &sc->sbands[band]; |
| 642 | struct ath_tx_control txctl; |
| 643 | + struct ath9k_hw_cal_data *caldata = ah->caldata; |
| 644 | int qnum, ftype; |
| 645 | int chain_ok = 0; |
| 646 | int chain; |
| 647 | @@ -269,6 +307,9 @@ void ath_paprd_calibrate(struct work_str |
| 648 | int time_left; |
| 649 | int i; |
| 650 | |
| 651 | + if (!caldata) |
| 652 | + return; |
| 653 | + |
| 654 | skb = alloc_skb(len, GFP_KERNEL); |
| 655 | if (!skb) |
| 656 | return; |
| 657 | @@ -323,7 +364,7 @@ void ath_paprd_calibrate(struct work_str |
| 658 | if (!ar9003_paprd_is_done(ah)) |
| 659 | break; |
| 660 | |
| 661 | - if (ar9003_paprd_create_curve(ah, ah->curchan, chain) != 0) |
| 662 | + if (ar9003_paprd_create_curve(ah, caldata, chain) != 0) |
| 663 | break; |
| 664 | |
| 665 | chain_ok = 1; |
| 666 | @@ -331,7 +372,7 @@ void ath_paprd_calibrate(struct work_str |
| 667 | kfree_skb(skb); |
| 668 | |
| 669 | if (chain_ok) { |
| 670 | - ah->curchan->paprd_done = true; |
| 671 | + caldata->paprd_done = true; |
| 672 | ath_paprd_activate(sc); |
| 673 | } |
| 674 | |
| 675 | @@ -440,33 +481,14 @@ set_timer: |
| 676 | cal_interval = min(cal_interval, (u32)short_cal_interval); |
| 677 | |
| 678 | mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval)); |
| 679 | - if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && |
| 680 | - !(sc->sc_flags & SC_OP_SCANNING)) { |
| 681 | - if (!sc->sc_ah->curchan->paprd_done) |
| 682 | + if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) { |
| 683 | + if (!ah->caldata->paprd_done) |
| 684 | ieee80211_queue_work(sc->hw, &sc->paprd_work); |
| 685 | else |
| 686 | ath_paprd_activate(sc); |
| 687 | } |
| 688 | } |
| 689 | |
| 690 | -static void ath_start_ani(struct ath_common *common) |
| 691 | -{ |
| 692 | - struct ath_hw *ah = common->ah; |
| 693 | - unsigned long timestamp = jiffies_to_msecs(jiffies); |
| 694 | - struct ath_softc *sc = (struct ath_softc *) common->priv; |
| 695 | - |
| 696 | - if (!(sc->sc_flags & SC_OP_ANI_RUN)) |
| 697 | - return; |
| 698 | - |
| 699 | - common->ani.longcal_timer = timestamp; |
| 700 | - common->ani.shortcal_timer = timestamp; |
| 701 | - common->ani.checkani_timer = timestamp; |
| 702 | - |
| 703 | - mod_timer(&common->ani.timer, |
| 704 | - jiffies + |
| 705 | - msecs_to_jiffies((u32)ah->config.ani_poll_interval)); |
| 706 | -} |
| 707 | - |
| 708 | /* |
| 709 | * Update tx/rx chainmask. For legacy association, |
| 710 | * hard code chainmask to 1x1, for 11n association, use |
| 711 | @@ -478,7 +500,7 @@ void ath_update_chainmask(struct ath_sof |
| 712 | struct ath_hw *ah = sc->sc_ah; |
| 713 | struct ath_common *common = ath9k_hw_common(ah); |
| 714 | |
| 715 | - if ((sc->sc_flags & SC_OP_SCANNING) || is_ht || |
| 716 | + if ((sc->sc_flags & SC_OP_OFFCHANNEL) || is_ht || |
| 717 | (ah->btcoex_hw.scheme != ATH_BTCOEX_CFG_NONE)) { |
| 718 | common->tx_chainmask = ah->caps.tx_chainmask; |
| 719 | common->rx_chainmask = ah->caps.rx_chainmask; |
| 720 | @@ -818,7 +840,7 @@ void ath_radio_enable(struct ath_softc * |
| 721 | ah->curchan = ath_get_curchannel(sc, sc->hw); |
| 722 | |
| 723 | spin_lock_bh(&sc->sc_resetlock); |
| 724 | - r = ath9k_hw_reset(ah, ah->curchan, false); |
| 725 | + r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); |
| 726 | if (r) { |
| 727 | ath_print(common, ATH_DBG_FATAL, |
| 728 | "Unable to reset channel (%u MHz), " |
| 729 | @@ -878,7 +900,7 @@ void ath_radio_disable(struct ath_softc |
| 730 | ah->curchan = ath_get_curchannel(sc, hw); |
| 731 | |
| 732 | spin_lock_bh(&sc->sc_resetlock); |
| 733 | - r = ath9k_hw_reset(ah, ah->curchan, false); |
| 734 | + r = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); |
| 735 | if (r) { |
| 736 | ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_FATAL, |
| 737 | "Unable to reset channel (%u MHz), " |
| 738 | @@ -911,7 +933,7 @@ int ath_reset(struct ath_softc *sc, bool |
| 739 | ath_flushrecv(sc); |
| 740 | |
| 741 | spin_lock_bh(&sc->sc_resetlock); |
| 742 | - r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false); |
| 743 | + r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false); |
| 744 | if (r) |
| 745 | ath_print(common, ATH_DBG_FATAL, |
| 746 | "Unable to reset hardware; reset status %d\n", r); |
| 747 | @@ -1086,7 +1108,7 @@ static int ath9k_start(struct ieee80211_ |
| 748 | * and then setup of the interrupt mask. |
| 749 | */ |
| 750 | spin_lock_bh(&sc->sc_resetlock); |
| 751 | - r = ath9k_hw_reset(ah, init_channel, false); |
| 752 | + r = ath9k_hw_reset(ah, init_channel, ah->caldata, false); |
| 753 | if (r) { |
| 754 | ath_print(common, ATH_DBG_FATAL, |
| 755 | "Unable to reset hardware; reset status %d " |
| 756 | @@ -1580,6 +1602,10 @@ static int ath9k_config(struct ieee80211 |
| 757 | |
| 758 | aphy->chan_idx = pos; |
| 759 | aphy->chan_is_ht = conf_is_ht(conf); |
| 760 | + if (hw->conf.flags & IEEE80211_CONF_OFFCHANNEL) |
| 761 | + sc->sc_flags |= SC_OP_OFFCHANNEL; |
| 762 | + else |
| 763 | + sc->sc_flags &= ~SC_OP_OFFCHANNEL; |
| 764 | |
| 765 | if (aphy->state == ATH_WIPHY_SCAN || |
| 766 | aphy->state == ATH_WIPHY_ACTIVE) |
| 767 | @@ -1991,7 +2017,6 @@ static void ath9k_sw_scan_start(struct i |
| 768 | { |
| 769 | struct ath_wiphy *aphy = hw->priv; |
| 770 | struct ath_softc *sc = aphy->sc; |
| 771 | - struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
| 772 | |
| 773 | mutex_lock(&sc->mutex); |
| 774 | if (ath9k_wiphy_scanning(sc)) { |
| 775 | @@ -2009,10 +2034,6 @@ static void ath9k_sw_scan_start(struct i |
| 776 | aphy->state = ATH_WIPHY_SCAN; |
| 777 | ath9k_wiphy_pause_all_forced(sc, aphy); |
| 778 | sc->sc_flags |= SC_OP_SCANNING; |
| 779 | - del_timer_sync(&common->ani.timer); |
| 780 | - cancel_work_sync(&sc->paprd_work); |
| 781 | - cancel_work_sync(&sc->hw_check_work); |
| 782 | - cancel_delayed_work_sync(&sc->tx_complete_work); |
| 783 | mutex_unlock(&sc->mutex); |
| 784 | } |
| 785 | |
| 786 | @@ -2024,15 +2045,10 @@ static void ath9k_sw_scan_complete(struc |
| 787 | { |
| 788 | struct ath_wiphy *aphy = hw->priv; |
| 789 | struct ath_softc *sc = aphy->sc; |
| 790 | - struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
| 791 | |
| 792 | mutex_lock(&sc->mutex); |
| 793 | aphy->state = ATH_WIPHY_ACTIVE; |
| 794 | sc->sc_flags &= ~SC_OP_SCANNING; |
| 795 | - sc->sc_flags |= SC_OP_FULL_RESET; |
| 796 | - ath_start_ani(common); |
| 797 | - ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); |
| 798 | - ath_beacon_config(sc, NULL); |
| 799 | mutex_unlock(&sc->mutex); |
| 800 | } |
| 801 | |
| 802 | --- a/drivers/net/wireless/ath/ath9k/ar9003_paprd.c |
| 803 | +++ b/drivers/net/wireless/ath/ath9k/ar9003_paprd.c |
| 804 | @@ -577,10 +577,11 @@ static bool create_pa_curve(u32 *data_L, |
| 805 | } |
| 806 | |
| 807 | void ar9003_paprd_populate_single_table(struct ath_hw *ah, |
| 808 | - struct ath9k_channel *chan, int chain) |
| 809 | + struct ath9k_hw_cal_data *caldata, |
| 810 | + int chain) |
| 811 | { |
| 812 | - u32 *paprd_table_val = chan->pa_table[chain]; |
| 813 | - u32 small_signal_gain = chan->small_signal_gain[chain]; |
| 814 | + u32 *paprd_table_val = caldata->pa_table[chain]; |
| 815 | + u32 small_signal_gain = caldata->small_signal_gain[chain]; |
| 816 | u32 training_power; |
| 817 | u32 reg = 0; |
| 818 | int i; |
| 819 | @@ -654,17 +655,17 @@ int ar9003_paprd_setup_gain_table(struct |
| 820 | } |
| 821 | EXPORT_SYMBOL(ar9003_paprd_setup_gain_table); |
| 822 | |
| 823 | -int ar9003_paprd_create_curve(struct ath_hw *ah, struct ath9k_channel *chan, |
| 824 | - int chain) |
| 825 | +int ar9003_paprd_create_curve(struct ath_hw *ah, |
| 826 | + struct ath9k_hw_cal_data *caldata, int chain) |
| 827 | { |
| 828 | - u16 *small_signal_gain = &chan->small_signal_gain[chain]; |
| 829 | - u32 *pa_table = chan->pa_table[chain]; |
| 830 | + u16 *small_signal_gain = &caldata->small_signal_gain[chain]; |
| 831 | + u32 *pa_table = caldata->pa_table[chain]; |
| 832 | u32 *data_L, *data_U; |
| 833 | int i, status = 0; |
| 834 | u32 *buf; |
| 835 | u32 reg; |
| 836 | |
| 837 | - memset(chan->pa_table[chain], 0, sizeof(chan->pa_table[chain])); |
| 838 | + memset(caldata->pa_table[chain], 0, sizeof(caldata->pa_table[chain])); |
| 839 | |
| 840 | buf = kmalloc(2 * 48 * sizeof(u32), GFP_ATOMIC); |
| 841 | if (!buf) |
| 842 | --- a/drivers/net/wireless/ath/ath9k/ath9k.h |
| 843 | +++ b/drivers/net/wireless/ath/ath9k/ath9k.h |
| 844 | @@ -511,7 +511,7 @@ void ath_deinit_leds(struct ath_softc *s |
| 845 | #define SC_OP_BEACONS BIT(1) |
| 846 | #define SC_OP_RXAGGR BIT(2) |
| 847 | #define SC_OP_TXAGGR BIT(3) |
| 848 | -#define SC_OP_FULL_RESET BIT(4) |
| 849 | +#define SC_OP_OFFCHANNEL BIT(4) |
| 850 | #define SC_OP_PREAMBLE_SHORT BIT(5) |
| 851 | #define SC_OP_PROTECT_ENABLE BIT(6) |
| 852 | #define SC_OP_RXFLUSH BIT(7) |
| 853 | @@ -612,6 +612,7 @@ struct ath_softc { |
| 854 | struct ath_wiphy { |
| 855 | struct ath_softc *sc; /* shared for all virtual wiphys */ |
| 856 | struct ieee80211_hw *hw; |
| 857 | + struct ath9k_hw_cal_data caldata; |
| 858 | enum ath_wiphy_state { |
| 859 | ATH_WIPHY_INACTIVE, |
| 860 | ATH_WIPHY_ACTIVE, |
| 861 | --- a/drivers/net/wireless/ath/ath9k/htc.h |
| 862 | +++ b/drivers/net/wireless/ath/ath9k/htc.h |
| 863 | @@ -353,6 +353,8 @@ struct ath9k_htc_priv { |
| 864 | u16 seq_no; |
| 865 | u32 bmiss_cnt; |
| 866 | |
| 867 | + struct ath9k_hw_cal_data caldata[38]; |
| 868 | + |
| 869 | spinlock_t beacon_lock; |
| 870 | |
| 871 | bool tx_queues_stop; |
| 872 | --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c |
| 873 | +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c |
| 874 | @@ -125,6 +125,7 @@ static int ath9k_htc_set_channel(struct |
| 875 | struct ieee80211_conf *conf = &common->hw->conf; |
| 876 | bool fastcc = true; |
| 877 | struct ieee80211_channel *channel = hw->conf.channel; |
| 878 | + struct ath9k_hw_cal_data *caldata; |
| 879 | enum htc_phymode mode; |
| 880 | __be16 htc_mode; |
| 881 | u8 cmd_rsp; |
| 882 | @@ -149,7 +150,8 @@ static int ath9k_htc_set_channel(struct |
| 883 | priv->ah->curchan->channel, |
| 884 | channel->center_freq, conf_is_ht(conf), conf_is_ht40(conf)); |
| 885 | |
| 886 | - ret = ath9k_hw_reset(ah, hchan, fastcc); |
| 887 | + caldata = &priv->caldata[channel->hw_value]; |
| 888 | + ret = ath9k_hw_reset(ah, hchan, caldata, fastcc); |
| 889 | if (ret) { |
| 890 | ath_print(common, ATH_DBG_FATAL, |
| 891 | "Unable to reset channel (%u Mhz) " |
| 892 | @@ -1028,7 +1030,7 @@ static void ath9k_htc_radio_enable(struc |
| 893 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); |
| 894 | |
| 895 | /* Reset the HW */ |
| 896 | - ret = ath9k_hw_reset(ah, ah->curchan, false); |
| 897 | + ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); |
| 898 | if (ret) { |
| 899 | ath_print(common, ATH_DBG_FATAL, |
| 900 | "Unable to reset hardware; reset status %d " |
| 901 | @@ -1091,7 +1093,7 @@ static void ath9k_htc_radio_disable(stru |
| 902 | ah->curchan = ath9k_cmn_get_curchannel(hw, ah); |
| 903 | |
| 904 | /* Reset the HW */ |
| 905 | - ret = ath9k_hw_reset(ah, ah->curchan, false); |
| 906 | + ret = ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); |
| 907 | if (ret) { |
| 908 | ath_print(common, ATH_DBG_FATAL, |
| 909 | "Unable to reset hardware; reset status %d " |
| 910 | @@ -1179,7 +1181,7 @@ static int ath9k_htc_start(struct ieee80 |
| 911 | ath9k_hw_configpcipowersave(ah, 0, 0); |
| 912 | |
| 913 | ath9k_hw_htc_resetinit(ah); |
| 914 | - ret = ath9k_hw_reset(ah, init_channel, false); |
| 915 | + ret = ath9k_hw_reset(ah, init_channel, ah->caldata, false); |
| 916 | if (ret) { |
| 917 | ath_print(common, ATH_DBG_FATAL, |
| 918 | "Unable to reset hardware; reset status %d " |
| 919 | --- a/drivers/net/wireless/ath/ath9k/hw.h |
| 920 | +++ b/drivers/net/wireless/ath/ath9k/hw.h |
| 921 | @@ -346,19 +346,25 @@ enum ath9k_int { |
| 922 | CHANNEL_HT40PLUS | \ |
| 923 | CHANNEL_HT40MINUS) |
| 924 | |
| 925 | -struct ath9k_channel { |
| 926 | - struct ieee80211_channel *chan; |
| 927 | +struct ath9k_hw_cal_data { |
| 928 | u16 channel; |
| 929 | u32 channelFlags; |
| 930 | - u32 chanmode; |
| 931 | int32_t CalValid; |
| 932 | - bool oneTimeCalsDone; |
| 933 | int8_t iCoff; |
| 934 | int8_t qCoff; |
| 935 | int16_t rawNoiseFloor; |
| 936 | bool paprd_done; |
| 937 | + bool nfcal_pending; |
| 938 | u16 small_signal_gain[AR9300_MAX_CHAINS]; |
| 939 | u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ]; |
| 940 | + struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; |
| 941 | +}; |
| 942 | + |
| 943 | +struct ath9k_channel { |
| 944 | + struct ieee80211_channel *chan; |
| 945 | + u16 channel; |
| 946 | + u32 channelFlags; |
| 947 | + u32 chanmode; |
| 948 | }; |
| 949 | |
| 950 | #define IS_CHAN_G(_c) ((((_c)->channelFlags & (CHANNEL_G)) == CHANNEL_G) || \ |
| 951 | @@ -669,7 +675,7 @@ struct ath_hw { |
| 952 | enum nl80211_iftype opmode; |
| 953 | enum ath9k_power_mode power_mode; |
| 954 | |
| 955 | - struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS]; |
| 956 | + struct ath9k_hw_cal_data *caldata; |
| 957 | struct ath9k_pacal_info pacal_info; |
| 958 | struct ar5416Stats stats; |
| 959 | struct ath9k_tx_queue_info txq[ATH9K_NUM_TX_QUEUES]; |
| 960 | @@ -863,7 +869,7 @@ const char *ath9k_hw_probe(u16 vendorid, |
| 961 | void ath9k_hw_deinit(struct ath_hw *ah); |
| 962 | int ath9k_hw_init(struct ath_hw *ah); |
| 963 | int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, |
| 964 | - bool bChannelChange); |
| 965 | + struct ath9k_hw_cal_data *caldata, bool bChannelChange); |
| 966 | int ath9k_hw_fill_cap_info(struct ath_hw *ah); |
| 967 | u32 ath9k_regd_get_ctl(struct ath_regulatory *reg, struct ath9k_channel *chan); |
| 968 | |
| 969 | @@ -958,9 +964,10 @@ void ar9003_hw_bb_watchdog_read(struct a |
| 970 | void ar9003_hw_bb_watchdog_dbg_info(struct ath_hw *ah); |
| 971 | void ar9003_paprd_enable(struct ath_hw *ah, bool val); |
| 972 | void ar9003_paprd_populate_single_table(struct ath_hw *ah, |
| 973 | - struct ath9k_channel *chan, int chain); |
| 974 | -int ar9003_paprd_create_curve(struct ath_hw *ah, struct ath9k_channel *chan, |
| 975 | - int chain); |
| 976 | + struct ath9k_hw_cal_data *caldata, |
| 977 | + int chain); |
| 978 | +int ar9003_paprd_create_curve(struct ath_hw *ah, |
| 979 | + struct ath9k_hw_cal_data *caldata, int chain); |
| 980 | int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain); |
| 981 | int ar9003_paprd_init_table(struct ath_hw *ah); |
| 982 | bool ar9003_paprd_is_done(struct ath_hw *ah); |
| 983 | --- a/drivers/net/wireless/ath/ath9k/xmit.c |
| 984 | +++ b/drivers/net/wireless/ath/ath9k/xmit.c |
| 985 | @@ -1181,7 +1181,7 @@ void ath_drain_all_txq(struct ath_softc |
| 986 | "Failed to stop TX DMA. Resetting hardware!\n"); |
| 987 | |
| 988 | spin_lock_bh(&sc->sc_resetlock); |
| 989 | - r = ath9k_hw_reset(ah, sc->sc_ah->curchan, false); |
| 990 | + r = ath9k_hw_reset(ah, sc->sc_ah->curchan, ah->caldata, false); |
| 991 | if (r) |
| 992 | ath_print(common, ATH_DBG_FATAL, |
| 993 | "Unable to reset hardware; reset status %d\n", |
| 994 | |