diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath9k')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | 133 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ar9003_eeprom.h | 10 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/calib.c | 38 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/hw.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/recv.c | 4 |
5 files changed, 162 insertions, 25 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index c2e210c0a770..f019a20e5a1f 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c @@ -3310,6 +3310,12 @@ static int ar9300_eeprom_restore_internal(struct ath_hw *ah, if (ar9300_check_eeprom_header(ah, read, cptr)) goto found; + cptr = AR9300_BASE_ADDR_4K; + ath_dbg(common, EEPROM, "Trying EEPROM access at Address 0x%04x\n", + cptr); + if (ar9300_check_eeprom_header(ah, read, cptr)) + goto found; + cptr = AR9300_BASE_ADDR_512; ath_dbg(common, EEPROM, "Trying EEPROM access at Address 0x%04x\n", cptr); @@ -3430,6 +3436,60 @@ static u32 ar9003_dump_modal_eeprom(char *buf, u32 len, u32 size, return len; } +static u32 ar9003_dump_cal_data(struct ath_hw *ah, char *buf, u32 len, u32 size, + bool is_2g) +{ + struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep; + struct ar9300_base_eep_hdr *pBase; + struct ar9300_cal_data_per_freq_op_loop *cal_pier; + int cal_pier_nr; + int freq; + int i, j; + + pBase = &eep->baseEepHeader; + + if (is_2g) + cal_pier_nr = AR9300_NUM_2G_CAL_PIERS; + else + cal_pier_nr = AR9300_NUM_5G_CAL_PIERS; + + for (i = 0; i < AR9300_MAX_CHAINS; i++) { + if (!((pBase->txrxMask >> i) & 1)) + continue; + + len += snprintf(buf + len, size - len, "Chain %d\n", i); + + len += snprintf(buf + len, size - len, + "Freq\t ref\tvolt\ttemp\tnf_cal\tnf_pow\trx_temp\n"); + + for (j = 0; j < cal_pier_nr; j++) { + if (is_2g) { + cal_pier = &eep->calPierData2G[i][j]; + freq = 2300 + eep->calFreqPier2G[j]; + } else { + cal_pier = &eep->calPierData5G[i][j]; + freq = 4800 + eep->calFreqPier5G[j] * 5; + } + + len += snprintf(buf + len, size - len, + "%d\t", freq); + + len += snprintf(buf + len, size - len, + "%d\t%d\t%d\t%d\t%d\t%d\n", + cal_pier->refPower, + cal_pier->voltMeas, + cal_pier->tempMeas, + cal_pier->rxTempMeas ? + N2DBM(cal_pier->rxNoisefloorCal) : 0, + cal_pier->rxTempMeas ? + N2DBM(cal_pier->rxNoisefloorPower) : 0, + cal_pier->rxTempMeas); + } + } + + return len; +} + static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, u8 *buf, u32 len, u32 size) { @@ -3441,10 +3501,18 @@ static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, "%20s :\n", "2GHz modal Header"); len = ar9003_dump_modal_eeprom(buf, len, size, &eep->modalHeader2G); - len += scnprintf(buf + len, size - len, + + len += scnprintf(buf + len, size - len, "Calibration data\n"); + len = ar9003_dump_cal_data(ah, buf, len, size, true); + + len += snprintf(buf + len, size - len, "%20s :\n", "5GHz modal Header"); len = ar9003_dump_modal_eeprom(buf, len, size, &eep->modalHeader5G); + + len += snprintf(buf + len, size - len, "Calibration data\n"); + len = ar9003_dump_cal_data(ah, buf, len, size, false); + goto out; } @@ -4683,7 +4751,8 @@ static int ar9003_hw_cal_pier_get(struct ath_hw *ah, int ichain, int *pfrequency, int *pcorrection, - int *ptemperature, int *pvoltage) + int *ptemperature, int *pvoltage, + int *pnf_cal, int *pnf_power) { u8 *pCalPier; struct ar9300_cal_data_per_freq_op_loop *pCalPierStruct; @@ -4725,6 +4794,10 @@ static int ar9003_hw_cal_pier_get(struct ath_hw *ah, *pcorrection = pCalPierStruct->refPower; *ptemperature = pCalPierStruct->tempMeas; *pvoltage = pCalPierStruct->voltMeas; + *pnf_cal = pCalPierStruct->rxTempMeas ? + N2DBM(pCalPierStruct->rxNoisefloorCal) : 0; + *pnf_power = pCalPierStruct->rxTempMeas ? + N2DBM(pCalPierStruct->rxNoisefloorPower) : 0; return 0; } @@ -4889,14 +4962,18 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) int mode; int lfrequency[AR9300_MAX_CHAINS], lcorrection[AR9300_MAX_CHAINS], - ltemperature[AR9300_MAX_CHAINS], lvoltage[AR9300_MAX_CHAINS]; + ltemperature[AR9300_MAX_CHAINS], lvoltage[AR9300_MAX_CHAINS], + lnf_cal[AR9300_MAX_CHAINS], lnf_pwr[AR9300_MAX_CHAINS]; int hfrequency[AR9300_MAX_CHAINS], hcorrection[AR9300_MAX_CHAINS], - htemperature[AR9300_MAX_CHAINS], hvoltage[AR9300_MAX_CHAINS]; + htemperature[AR9300_MAX_CHAINS], hvoltage[AR9300_MAX_CHAINS], + hnf_cal[AR9300_MAX_CHAINS], hnf_pwr[AR9300_MAX_CHAINS]; int fdiff; int correction[AR9300_MAX_CHAINS], - voltage[AR9300_MAX_CHAINS], temperature[AR9300_MAX_CHAINS]; - int pfrequency, pcorrection, ptemperature, pvoltage; + voltage[AR9300_MAX_CHAINS], temperature[AR9300_MAX_CHAINS], + nf_cal[AR9300_MAX_CHAINS], nf_pwr[AR9300_MAX_CHAINS]; + int pfrequency, pcorrection, ptemperature, pvoltage, + pnf_cal, pnf_pwr; struct ath_common *common = ath9k_hw_common(ah); mode = (frequency >= 4000); @@ -4914,7 +4991,8 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) for (ipier = 0; ipier < npier; ipier++) { if (!ar9003_hw_cal_pier_get(ah, mode, ipier, ichain, &pfrequency, &pcorrection, - &ptemperature, &pvoltage)) { + &ptemperature, &pvoltage, + &pnf_cal, &pnf_pwr)) { fdiff = frequency - pfrequency; /* @@ -4936,6 +5014,8 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) htemperature[ichain] = ptemperature; hvoltage[ichain] = pvoltage; + hnf_cal[ichain] = pnf_cal; + hnf_pwr[ichain] = pnf_pwr; } } if (fdiff >= 0) { @@ -4952,6 +5032,8 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) ltemperature[ichain] = ptemperature; lvoltage[ichain] = pvoltage; + lnf_cal[ichain] = pnf_cal; + lnf_pwr[ichain] = pnf_pwr; } } } @@ -4960,15 +5042,20 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) /* interpolate */ for (ichain = 0; ichain < AR9300_MAX_CHAINS; ichain++) { - ath_dbg(common, EEPROM, "ch=%d f=%d low=%d %d h=%d %d\n", + ath_dbg(common, EEPROM, + "ch=%d f=%d low=%d %d h=%d %d n=%d %d p=%d %d\n", ichain, frequency, lfrequency[ichain], lcorrection[ichain], hfrequency[ichain], - hcorrection[ichain]); + hcorrection[ichain], lnf_cal[ichain], + hnf_cal[ichain], lnf_pwr[ichain], + hnf_pwr[ichain]); /* they're the same, so just pick one */ if (hfrequency[ichain] == lfrequency[ichain]) { correction[ichain] = lcorrection[ichain]; voltage[ichain] = lvoltage[ichain]; temperature[ichain] = ltemperature[ichain]; + nf_cal[ichain] = lnf_cal[ichain]; + nf_pwr[ichain] = lnf_pwr[ichain]; } /* the low frequency is good */ else if (frequency - lfrequency[ichain] < 1000) { @@ -4992,12 +5079,26 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) hfrequency[ichain], lvoltage[ichain], hvoltage[ichain]); + + nf_cal[ichain] = interpolate(frequency, + lfrequency[ichain], + hfrequency[ichain], + lnf_cal[ichain], + hnf_cal[ichain]); + + nf_pwr[ichain] = interpolate(frequency, + lfrequency[ichain], + hfrequency[ichain], + lnf_pwr[ichain], + hnf_pwr[ichain]); } /* only low is good, use it */ else { correction[ichain] = lcorrection[ichain]; temperature[ichain] = ltemperature[ichain]; voltage[ichain] = lvoltage[ichain]; + nf_cal[ichain] = lnf_cal[ichain]; + nf_pwr[ichain] = lnf_pwr[ichain]; } } /* only high is good, use it */ @@ -5005,10 +5106,14 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) correction[ichain] = hcorrection[ichain]; temperature[ichain] = htemperature[ichain]; voltage[ichain] = hvoltage[ichain]; + nf_cal[ichain] = hnf_cal[ichain]; + nf_pwr[ichain] = hnf_pwr[ichain]; } else { /* nothing is good, presume 0???? */ correction[ichain] = 0; temperature[ichain] = 0; voltage[ichain] = 0; + nf_cal[ichain] = 0; + nf_pwr[ichain] = 0; } } @@ -5019,6 +5124,16 @@ static int ar9003_hw_calibration_apply(struct ath_hw *ah, int frequency) "for frequency=%d, calibration correction = %d %d %d\n", frequency, correction[0], correction[1], correction[2]); + /* Store calibrated noise floor values */ + for (ichain = 0; ichain < AR5416_MAX_CHAINS; ichain++) + if (mode) { + ah->nf_5g.cal[ichain] = nf_cal[ichain]; + ah->nf_5g.pwr[ichain] = nf_pwr[ichain]; + } else { + ah->nf_2g.cal[ichain] = nf_cal[ichain]; + ah->nf_2g.pwr[ichain] = nf_pwr[ichain]; + } + return 0; } diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h index bd2269c7de6b..e8fda54acfe3 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.h @@ -62,6 +62,16 @@ */ #define AR9300_PWR_TABLE_OFFSET 0 +/* Noise power data definitions + * units are: 4 x dBm - NOISE_PWR_DATA_OFFSET + * (e.g. -25 = (-25/4 - 90) = -96.25 dBm) + * range (for 6 signed bits) is (-32 to 31) + offset => -122dBm to -59dBm + * resolution (2 bits) is 0.25dBm + */ +#define NOISE_PWR_DATA_OFFSET -90 +#define NOISE_PWR_DBM_2_INT(_p) ((((_p) + 3) >> 2) + NOISE_PWR_DATA_OFFSET) +#define N2DBM(_p) NOISE_PWR_DBM_2_INT(_p) + /* byte addressable */ #define AR9300_EEPROM_SIZE (16*1024) diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 13ab6bc46775..3d9447e21025 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c @@ -58,19 +58,25 @@ static struct ath_nf_limits *ath9k_hw_get_nf_limits(struct ath_hw *ah, } static s16 ath9k_hw_get_default_nf(struct ath_hw *ah, - struct ath9k_channel *chan) + struct ath9k_channel *chan, + int chain) { - return ath9k_hw_get_nf_limits(ah, chan)->nominal; + s16 calib_nf = ath9k_hw_get_nf_limits(ah, chan)->cal[chain]; + + if (calib_nf) + return calib_nf; + else + return ath9k_hw_get_nf_limits(ah, chan)->nominal; } s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan, s16 nf) { - s8 noise = ATH_DEFAULT_NOISE_FLOOR; + s8 noise = ath9k_hw_get_default_nf(ah, chan, 0); if (nf) { s8 delta = nf - ATH9K_NF_CAL_NOISE_THRESH - - ath9k_hw_get_default_nf(ah, chan); + ath9k_hw_get_default_nf(ah, chan, 0); if (delta > 0) noise += delta; } @@ -240,7 +246,7 @@ int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) unsigned i, j; u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask; struct ath_common *common = ath9k_hw_common(ah); - s16 default_nf = ath9k_hw_get_default_nf(ah, chan); + s16 default_nf = ath9k_hw_get_nf_limits(ah, chan)->nominal; u32 bb_agc_ctl = REG_READ(ah, AR_PHY_AGC_CONTROL); if (ah->caldata) @@ -258,8 +264,13 @@ int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) nfval = ah->nf_override; else if (h) nfval = h[i].privNF; - else - nfval = default_nf; + else { + /* Try to get calibrated noise floor value */ + nfval = + ath9k_hw_get_nf_limits(ah, chan)->cal[i]; + if (nfval > -60 || nfval < -127) + nfval = default_nf; + } REG_RMW(ah, ah->nf_regs[i], (((u32) nfval << 1) & 0x1ff), 0x1ff); @@ -429,20 +440,19 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, struct ath9k_channel *chan) { struct ath9k_nfcal_hist *h; - s16 default_nf; - int i, j; + int i, j, k = 0; ah->caldata->channel = chan->channel; ah->caldata->channelFlags = chan->channelFlags; h = ah->caldata->nfCalHist; - default_nf = ath9k_hw_get_default_nf(ah, chan); for (i = 0; i < NUM_NF_READINGS; i++) { h[i].currIndex = 0; - h[i].privNF = default_nf; + h[i].privNF = ath9k_hw_get_default_nf(ah, chan, k); h[i].invalidNFcount = AR_PHY_CCA_FILTERWINDOW_LENGTH; - for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) { - h[i].nfCalBuffer[j] = default_nf; - } + for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) + h[i].nfCalBuffer[j] = h[i].privNF; + if (++k >= AR5416_MAX_CHAINS) + k = 0; } } diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 0d6c07c77372..9804a24a2dc0 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h @@ -754,6 +754,8 @@ struct ath_nf_limits { s16 max; s16 min; s16 nominal; + s16 cal[AR5416_MAX_CHAINS]; + s16 pwr[AR5416_MAX_CHAINS]; }; enum ath_cal_list { diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 2197aee2bb72..a8ac42c96d71 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c @@ -826,9 +826,9 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc, sc->rx.discard_next = false; /* - * Discard zero-length packets. + * Discard zero-length packets and packets smaller than an ACK */ - if (!rx_stats->rs_datalen) { + if (rx_stats->rs_datalen < 10) { RX_STAT_INC(rx_len_err); goto corrupt; } |