From 76061abbbb39ba4bdf42fe28aa3157df8bb03d38 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Dec 2008 15:58:41 -0800 Subject: ath9k: make request to get the noisefloor threshold band specific Lets make the request to get the current noise floor threshold from the EEPROM band specific as it is band specific, not mode specific. This also adds a backpointer on the private channel structure back to the ieee80211_channel structure as this is now needed during ath9k_hw_getnf(). Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/calib.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) (limited to 'drivers/net/wireless/ath9k/calib.c') diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c index 3c7454fc51b..2a6b8a4d6e9 100644 --- a/drivers/net/wireless/ath9k/calib.c +++ b/drivers/net/wireless/ath9k/calib.c @@ -168,26 +168,18 @@ static void ath9k_hw_do_getnf(struct ath_hal *ah, } static bool getNoiseFloorThresh(struct ath_hal *ah, - const struct ath9k_channel *chan, + enum ieee80211_band band, int16_t *nft) { - switch (chan->chanmode) { - case CHANNEL_A: - case CHANNEL_A_HT20: - case CHANNEL_A_HT40PLUS: - case CHANNEL_A_HT40MINUS: + switch (band) { + case IEEE80211_BAND_5GHZ: *nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_5); break; - case CHANNEL_B: - case CHANNEL_G: - case CHANNEL_G_HT20: - case CHANNEL_G_HT40PLUS: - case CHANNEL_G_HT40MINUS: + case IEEE80211_BAND_2GHZ: *nft = (int8_t)ath9k_hw_get_eeprom(ah, EEP_NFTHRESH_2); break; default: - DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, - "invalid channel flags 0x%x\n", chan->channelFlags); + BUG_ON(1); return false; } @@ -692,6 +684,7 @@ int16_t ath9k_hw_getnf(struct ath_hal *ah, int16_t nf, nfThresh; int16_t nfarray[NUM_NF_READINGS] = { 0 }; struct ath9k_nfcal_hist *h; + struct ieee80211_channel *c = chan->chan; u8 chainmask; if (AR_SREV_9280(ah)) @@ -709,7 +702,7 @@ int16_t ath9k_hw_getnf(struct ath_hal *ah, } else { ath9k_hw_do_getnf(ah, nfarray); nf = nfarray[0]; - if (getNoiseFloorThresh(ah, chan, &nfThresh) + if (getNoiseFloorThresh(ah, c->band, &nfThresh) && nf > nfThresh) { DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "noise floor failed detected; " -- cgit v1.2.3 From c9e27d94f5fc726f88897914025619fbfc18b23c Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Dec 2008 15:58:42 -0800 Subject: ath9k: use ieee80211_conf on ath9k_hw_iscal_supported() ath9k_hw_iscal_supported() just needs to be aware of your band and if HT20 is being used so lets abandon our internal channel, HT appended values and internal mode values and use ieee80211_conf which already carries this information. This works as calibration is being done for the currently configured channel. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/calib.c | 63 +++++++++++++++----------------------- 1 file changed, 25 insertions(+), 38 deletions(-) (limited to 'drivers/net/wireless/ath9k/calib.c') diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c index 2a6b8a4d6e9..707289685b4 100644 --- a/drivers/net/wireless/ath9k/calib.c +++ b/drivers/net/wireless/ath9k/calib.c @@ -277,27 +277,24 @@ static void ath9k_hw_per_calibration(struct ath_hal *ah, } } +/* Assumes you are talking about the currently configured channel */ static bool ath9k_hw_iscal_supported(struct ath_hal *ah, - struct ath9k_channel *chan, enum hal_cal_types calType) { struct ath_hal_5416 *ahp = AH5416(ah); - bool retval = false; + struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; switch (calType & ahp->ah_suppCals) { - case IQ_MISMATCH_CAL: - if (!IS_CHAN_B(chan)) - retval = true; - break; + case IQ_MISMATCH_CAL: /* Both 2 GHz and 5 GHz support OFDM */ + return true; case ADC_GAIN_CAL: case ADC_DC_CAL: - if (!IS_CHAN_B(chan) - && !(IS_CHAN_2GHZ(chan) && IS_CHAN_HT20(chan))) - retval = true; + if (conf->channel->band == IEEE80211_BAND_5GHZ && + conf_is_ht20(conf)) + return true; break; } - - return retval; + return false; } static void ath9k_hw_iqcal_collect(struct ath_hal *ah) @@ -565,50 +562,40 @@ static void ath9k_hw_adc_dccal_calibrate(struct ath_hal *ah, u8 numChains) AR_PHY_NEW_ADC_DC_OFFSET_CORR_ENABLE); } -void ath9k_hw_reset_calvalid(struct ath_hal *ah, struct ath9k_channel *chan, - bool *isCalDone) +/* This is done for the currently configured channel */ +bool ath9k_hw_reset_calvalid(struct ath_hal *ah) { struct ath_hal_5416 *ahp = AH5416(ah); - struct ath9k_channel *ichan = - ath9k_regd_check_channel(ah, chan); + struct ieee80211_conf *conf = &ah->ah_sc->hw->conf; struct hal_cal_list *currCal = ahp->ah_cal_list_curr; - *isCalDone = true; + if (!ah->ah_curchan) + return true; if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah)) - return; + return true; if (currCal == NULL) - return; - - if (ichan == NULL) { - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "invalid channel %u/0x%x; no mapping\n", - chan->channel, chan->channelFlags); - return; - } - + return true; if (currCal->calState != CAL_DONE) { DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "Calibration state incorrect, %d\n", currCal->calState); - return; + return true; } - - if (!ath9k_hw_iscal_supported(ah, chan, currCal->calData->calType)) - return; + if (!ath9k_hw_iscal_supported(ah, currCal->calData->calType)) + return true; DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "Resetting Cal %d state for channel %u/0x%x\n", - currCal->calData->calType, chan->channel, - chan->channelFlags); + "Resetting Cal %d state for channel %u\n", + currCal->calData->calType, conf->channel->center_freq); - ichan->CalValid &= ~currCal->calData->calType; + ah->ah_curchan->CalValid &= ~currCal->calData->calType; currCal->calState = CAL_WAITING; - *isCalDone = false; + return false; } void ath9k_hw_start_nfcal(struct ath_hal *ah) @@ -933,19 +920,19 @@ bool ath9k_hw_init_cal(struct ath_hal *ah, ahp->ah_cal_list = ahp->ah_cal_list_last = ahp->ah_cal_list_curr = NULL; if (AR_SREV_9100(ah) || AR_SREV_9160_10_OR_LATER(ah)) { - if (ath9k_hw_iscal_supported(ah, chan, ADC_GAIN_CAL)) { + if (ath9k_hw_iscal_supported(ah, ADC_GAIN_CAL)) { INIT_CAL(&ahp->ah_adcGainCalData); INSERT_CAL(ahp, &ahp->ah_adcGainCalData); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "enabling ADC Gain Calibration.\n"); } - if (ath9k_hw_iscal_supported(ah, chan, ADC_DC_CAL)) { + if (ath9k_hw_iscal_supported(ah, ADC_DC_CAL)) { INIT_CAL(&ahp->ah_adcDcCalData); INSERT_CAL(ahp, &ahp->ah_adcDcCalData); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, "enabling ADC DC Calibration.\n"); } - if (ath9k_hw_iscal_supported(ah, chan, IQ_MISMATCH_CAL)) { + if (ath9k_hw_iscal_supported(ah, IQ_MISMATCH_CAL)) { INIT_CAL(&ahp->ah_iqCalData); INSERT_CAL(ahp, &ahp->ah_iqCalData); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, -- cgit v1.2.3 From e56db718468416ce5ff1ba05e7fa5026424befd5 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Tue, 23 Dec 2008 15:58:47 -0800 Subject: ath9k: remove mode specific default noise floor values The NOISE_FLOOR array we have is mode specific, and the only possible indexed values are A, B and G. The mode routine only can return G or A, so this is band specific. Then since the values for A and G (5ghz or 2ghz) are the same (-96) we simply remove the array and use a static value. If we later determine we want to use special values for HT configurations we can use the new mac80211 conf_is_ht*() helpers. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/calib.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'drivers/net/wireless/ath9k/calib.c') diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c index 707289685b4..8e073d6513d 100644 --- a/drivers/net/wireless/ath9k/calib.c +++ b/drivers/net/wireless/ath9k/calib.c @@ -19,8 +19,6 @@ #include "reg.h" #include "phy.h" -static const int16_t NOISE_FLOOR[] = { -96, -93, -98, -96, -93, -96 }; - /* We can tune this as we go by monitoring really low values */ #define ATH9K_NF_TOO_LOW -60 @@ -740,10 +738,9 @@ s16 ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan) chan->channel, chan->channelFlags); return ATH_DEFAULT_NOISE_FLOOR; } - if (ichan->rawNoiseFloor == 0) { - enum wireless_mode mode = ath9k_hw_chan2wmode(ah, chan); - nf = NOISE_FLOOR[mode]; - } else + if (ichan->rawNoiseFloor == 0) + nf = -96; + else nf = ichan->rawNoiseFloor; if (!ath9k_hw_nf_in_range(ah, nf)) -- cgit v1.2.3 From 5f8e077c0adc0dc7cfad64cdc05276e1961a1394 Mon Sep 17 00:00:00 2001 From: "Luis R. Rodriguez" Date: Thu, 22 Jan 2009 15:16:48 -0800 Subject: ath9k: simplify regulatory code Now that cfg80211 has its own regulatory infrastructure we can condense ath9k's regulatory code considerably. We only keep data we need to provide our own regulatory_hint(), reg_notifier() and information necessary for calibration. Atheros hardware supports 12 world regulatory domains, since these are custom we apply them through the the new wiphy_apply_custom_regulatory(). Although we have 12 we can consolidate these into 5 structures based on frequency and apply a different set of flags that differentiate them on a case by case basis through the reg_notifier(). If CRDA is not found our own custom world regulatory domain is applied, this is identical to cfg80211's except we enable passive scan on most frequencies. Signed-off-by: Luis R. Rodriguez Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/calib.c | 41 +++++++------------------------------- 1 file changed, 7 insertions(+), 34 deletions(-) (limited to 'drivers/net/wireless/ath9k/calib.c') diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c index 8e073d6513d..d16f9fe48a9 100644 --- a/drivers/net/wireless/ath9k/calib.c +++ b/drivers/net/wireless/ath9k/calib.c @@ -625,11 +625,7 @@ void ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan) else chainmask = 0x3F; -#ifdef ATH_NF_PER_CHAN - h = chan->nfCalHist; -#else h = ah->nfCalHist; -#endif for (i = 0; i < NUM_NF_READINGS; i++) { if (chainmask & (1 << i)) { @@ -697,11 +693,7 @@ int16_t ath9k_hw_getnf(struct ath_hal *ah, } } -#ifdef ATH_NF_PER_CHAN - h = chan->nfCalHist; -#else h = ah->nfCalHist; -#endif ath9k_hw_update_nfcal_hist_buffer(h, nfarray); chan->rawNoiseFloor = h[0].privNF; @@ -728,20 +720,12 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hal *ah) s16 ath9k_hw_getchan_noise(struct ath_hal *ah, struct ath9k_channel *chan) { - struct ath9k_channel *ichan; s16 nf; - ichan = ath9k_regd_check_channel(ah, chan); - if (ichan == NULL) { - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "invalid channel %u/0x%x; no mapping\n", - chan->channel, chan->channelFlags); - return ATH_DEFAULT_NOISE_FLOOR; - } - if (ichan->rawNoiseFloor == 0) + if (chan->rawNoiseFloor == 0) nf = -96; else - nf = ichan->rawNoiseFloor; + nf = chan->rawNoiseFloor; if (!ath9k_hw_nf_in_range(ah, nf)) nf = ATH_DEFAULT_NOISE_FLOOR; @@ -755,21 +739,13 @@ bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan, { struct ath_hal_5416 *ahp = AH5416(ah); struct hal_cal_list *currCal = ahp->ah_cal_list_curr; - struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan); *isCalDone = true; - if (ichan == NULL) { - DPRINTF(ah->ah_sc, ATH_DBG_CHANNEL, - "invalid channel %u/0x%x; no mapping\n", - chan->channel, chan->channelFlags); - return false; - } - if (currCal && (currCal->calState == CAL_RUNNING || currCal->calState == CAL_WAITING)) { - ath9k_hw_per_calibration(ah, ichan, rxchainmask, currCal, + ath9k_hw_per_calibration(ah, chan, rxchainmask, currCal, isCalDone); if (*isCalDone) { ahp->ah_cal_list_curr = currCal = currCal->calNext; @@ -782,14 +758,12 @@ bool ath9k_hw_calibrate(struct ath_hal *ah, struct ath9k_channel *chan, } if (longcal) { - ath9k_hw_getnf(ah, ichan); + ath9k_hw_getnf(ah, chan); ath9k_hw_loadnf(ah, ah->ah_curchan); ath9k_hw_start_nfcal(ah); - if ((ichan->channelFlags & CHANNEL_CW_INT) != 0) { - chan->channelFlags |= CHANNEL_CW_INT; - ichan->channelFlags &= ~CHANNEL_CW_INT; - } + if (chan->channelFlags & CHANNEL_CW_INT) + chan->channelFlags &= ~CHANNEL_CW_INT; } return true; @@ -894,7 +868,6 @@ bool ath9k_hw_init_cal(struct ath_hal *ah, struct ath9k_channel *chan) { struct ath_hal_5416 *ahp = AH5416(ah); - struct ath9k_channel *ichan = ath9k_regd_check_channel(ah, chan); REG_WRITE(ah, AR_PHY_AGC_CONTROL, REG_READ(ah, AR_PHY_AGC_CONTROL) | @@ -942,7 +915,7 @@ bool ath9k_hw_init_cal(struct ath_hal *ah, ath9k_hw_reset_calibration(ah, ahp->ah_cal_list_curr); } - ichan->CalValid = 0; + chan->CalValid = 0; return true; } -- cgit v1.2.3 From 5dad40c13e7753e7b62eb7c2fca9b4034679882a Mon Sep 17 00:00:00 2001 From: Sujith Date: Fri, 23 Jan 2009 11:20:55 +0530 Subject: ath9k: Fix bug in NF calibration The number of chainmasks for AR9285 weren't being setup when running NF calibration. Signed-off-by: Sujith Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/calib.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'drivers/net/wireless/ath9k/calib.c') diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c index d16f9fe48a9..c6d1de0f1e2 100644 --- a/drivers/net/wireless/ath9k/calib.c +++ b/drivers/net/wireless/ath9k/calib.c @@ -620,7 +620,9 @@ void ath9k_hw_loadnf(struct ath_hal *ah, struct ath9k_channel *chan) }; u8 chainmask; - if (AR_SREV_9280(ah)) + if (AR_SREV_9285(ah)) + chainmask = 0x9; + else if (AR_SREV_9280(ah)) chainmask = 0x1B; else chainmask = 0x3F; -- cgit v1.2.3 From 793c592995b841667fa6d1a36a98880430dcc8f4 Mon Sep 17 00:00:00 2001 From: Senthil Balasubramanian Date: Mon, 26 Jan 2009 20:28:14 +0530 Subject: ath9k: Fix AR9285 specific noise floor eeprom reads. Fix AR9285 specific noise floor reads and initialize tx and rx chainmask during reset. This along with the following earlier patches of ath9k fixes an issue with association noticed in noisy environment. ath9k: Fix typo in chip version check ath9k: Remove unnecessary gpio configuration in ath9k_hw_reset() ath9k: Fix bug in NF calibration Signed-off-by: Senthil Balasubramanian Signed-off-by: John W. Linville --- drivers/net/wireless/ath9k/calib.c | 78 +++++++++++++++++++------------------- 1 file changed, 38 insertions(+), 40 deletions(-) (limited to 'drivers/net/wireless/ath9k/calib.c') diff --git a/drivers/net/wireless/ath9k/calib.c b/drivers/net/wireless/ath9k/calib.c index c6d1de0f1e2..69ff01ce968 100644 --- a/drivers/net/wireless/ath9k/calib.c +++ b/drivers/net/wireless/ath9k/calib.c @@ -105,27 +105,29 @@ static void ath9k_hw_do_getnf(struct ath_hal *ah, "NF calibrated [ctl] [chain 0] is %d\n", nf); nfarray[0] = nf; - if (AR_SREV_9280_10_OR_LATER(ah)) - nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), - AR9280_PHY_CH1_MINCCA_PWR); - else - nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), - AR_PHY_CH1_MINCCA_PWR); - - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "NF calibrated [ctl] [chain 1] is %d\n", nf); - nfarray[1] = nf; + if (!AR_SREV_9285(ah)) { + if (AR_SREV_9280_10_OR_LATER(ah)) + nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), + AR9280_PHY_CH1_MINCCA_PWR); + else + nf = MS(REG_READ(ah, AR_PHY_CH1_CCA), + AR_PHY_CH1_MINCCA_PWR); - if (!AR_SREV_9280(ah)) { - nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), - AR_PHY_CH2_MINCCA_PWR); if (nf & 0x100) nf = 0 - ((nf ^ 0x1ff) + 1); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "NF calibrated [ctl] [chain 2] is %d\n", nf); - nfarray[2] = nf; + "NF calibrated [ctl] [chain 1] is %d\n", nf); + nfarray[1] = nf; + + if (!AR_SREV_9280(ah)) { + nf = MS(REG_READ(ah, AR_PHY_CH2_CCA), + AR_PHY_CH2_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "NF calibrated [ctl] [chain 2] is %d\n", nf); + nfarray[2] = nf; + } } if (AR_SREV_9280_10_OR_LATER(ah)) @@ -141,27 +143,29 @@ static void ath9k_hw_do_getnf(struct ath_hal *ah, "NF calibrated [ext] [chain 0] is %d\n", nf); nfarray[3] = nf; - if (AR_SREV_9280_10_OR_LATER(ah)) - nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), - AR9280_PHY_CH1_EXT_MINCCA_PWR); - else - nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), - AR_PHY_CH1_EXT_MINCCA_PWR); + if (!AR_SREV_9285(ah)) { + if (AR_SREV_9280_10_OR_LATER(ah)) + nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), + AR9280_PHY_CH1_EXT_MINCCA_PWR); + else + nf = MS(REG_READ(ah, AR_PHY_CH1_EXT_CCA), + AR_PHY_CH1_EXT_MINCCA_PWR); - if (nf & 0x100) - nf = 0 - ((nf ^ 0x1ff) + 1); - DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "NF calibrated [ext] [chain 1] is %d\n", nf); - nfarray[4] = nf; - - if (!AR_SREV_9280(ah)) { - nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), - AR_PHY_CH2_EXT_MINCCA_PWR); if (nf & 0x100) nf = 0 - ((nf ^ 0x1ff) + 1); DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, - "NF calibrated [ext] [chain 2] is %d\n", nf); - nfarray[5] = nf; + "NF calibrated [ext] [chain 1] is %d\n", nf); + nfarray[4] = nf; + + if (!AR_SREV_9280(ah)) { + nf = MS(REG_READ(ah, AR_PHY_CH2_EXT_CCA), + AR_PHY_CH2_EXT_MINCCA_PWR); + if (nf & 0x100) + nf = 0 - ((nf ^ 0x1ff) + 1); + DPRINTF(ah->ah_sc, ATH_DBG_CALIBRATE, + "NF calibrated [ext] [chain 2] is %d\n", nf); + nfarray[5] = nf; + } } } @@ -668,12 +672,6 @@ int16_t ath9k_hw_getnf(struct ath_hal *ah, int16_t nfarray[NUM_NF_READINGS] = { 0 }; struct ath9k_nfcal_hist *h; struct ieee80211_channel *c = chan->chan; - u8 chainmask; - - if (AR_SREV_9280(ah)) - chainmask = 0x1B; - else - chainmask = 0x3F; chan->channelFlags &= (~CHANNEL_CW_INT); if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) { -- cgit v1.2.3