Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f2552e28 authored by Felix Fietkau's avatar Felix Fietkau Committed by John W. Linville
Browse files

ath9k_hw: sanitize noise floor values properly on all chips



This refactors the noise floor range checks to make them generic,
and adds proper ranges for each supported chip type.

Signed-off-by: default avatarFelix Fietkau <nbd@openwrt.org>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent ba17bc5e
Loading
Loading
Loading
Loading
+11 −0
Original line number Diff line number Diff line
@@ -1676,6 +1676,15 @@ static void ar5008_hw_ani_cache_ini_regs(struct ath_hw *ah)
	aniState->cycleCount = 0;
}

static void ar5008_hw_set_nf_limits(struct ath_hw *ah)
{
	ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ;
	ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ;
	ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_5416_2GHZ;
	ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ;
	ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ;
	ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_5416_5GHZ;
}

void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
{
@@ -1713,4 +1722,6 @@ void ar5008_hw_attach_phy_ops(struct ath_hw *ah)
		priv_ops->compute_pll_control = ar9160_hw_compute_pll_control;
	else
		priv_ops->compute_pll_control = ar5008_hw_compute_pll_control;

	ar5008_hw_set_nf_limits(ah);
}
+26 −6
Original line number Diff line number Diff line
@@ -481,9 +481,6 @@ static void ar9002_hw_do_getnf(struct ath_hw *ah,
	ath_print(common, ATH_DBG_CALIBRATE,
		  "NF calibrated [ctl] [chain 0] is %d\n", nf);

	if (AR_SREV_9271(ah) && (nf >= -114))
		nf = -116;

	nfarray[0] = nf;

	if (!AR_SREV_9285(ah) && !AR_SREV_9271(ah)) {
@@ -503,9 +500,6 @@ static void ar9002_hw_do_getnf(struct ath_hw *ah,
	ath_print(common, ATH_DBG_CALIBRATE,
		  "NF calibrated [ext] [chain 0] is %d\n", nf);

	if (AR_SREV_9271(ah) && (nf >= -114))
		nf = -116;

	nfarray[3] = nf;

	if (!AR_SREV_9285(ah) && !AR_SREV_9271(ah)) {
@@ -520,6 +514,30 @@ static void ar9002_hw_do_getnf(struct ath_hw *ah,
	}
}

static void ar9002_hw_set_nf_limits(struct ath_hw *ah)
{
	if (AR_SREV_9285(ah)) {
		ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9285_2GHZ;
		ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9285_2GHZ;
		ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9285_2GHZ;
	} else if (AR_SREV_9287(ah)) {
		ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ;
		ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ;
		ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9287_2GHZ;
	} else if (AR_SREV_9271(ah)) {
		ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9271_2GHZ;
		ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9271_2GHZ;
		ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9271_2GHZ;
	} else {
		ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_2GHZ;
		ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_2GHZ;
		ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9280_2GHZ;
		ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9280_5GHZ;
		ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9280_5GHZ;
		ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9280_5GHZ;
	}
}

void ar9002_hw_attach_phy_ops(struct ath_hw *ah)
{
	struct ath_hw_private_ops *priv_ops = ath9k_hw_private_ops(ah);
@@ -532,4 +550,6 @@ void ar9002_hw_attach_phy_ops(struct ath_hw *ah)
	priv_ops->olc_init = ar9002_olc_init;
	priv_ops->compute_pll_control = ar9002_hw_compute_pll_control;
	priv_ops->do_getnf = ar9002_hw_do_getnf;

	ar9002_hw_set_nf_limits(ah);
}
+26 −0
Original line number Diff line number Diff line
@@ -576,4 +576,30 @@
#define AR_PHY_CH2_EXT_MINCCA_PWR   0xFF800000
#define AR_PHY_CH2_EXT_MINCCA_PWR_S 23

#define AR_PHY_CCA_NOM_VAL_5416_2GHZ            -90
#define AR_PHY_CCA_NOM_VAL_5416_5GHZ            -100
#define AR_PHY_CCA_MIN_GOOD_VAL_5416_2GHZ     -100
#define AR_PHY_CCA_MIN_GOOD_VAL_5416_5GHZ     -110
#define AR_PHY_CCA_MAX_GOOD_VAL_5416_2GHZ     -80
#define AR_PHY_CCA_MAX_GOOD_VAL_5416_5GHZ     -90

#define AR_PHY_CCA_NOM_VAL_9280_2GHZ         -112
#define AR_PHY_CCA_NOM_VAL_9280_5GHZ         -112
#define AR_PHY_CCA_MIN_GOOD_VAL_9280_2GHZ  -127
#define AR_PHY_CCA_MIN_GOOD_VAL_9280_5GHZ  -122
#define AR_PHY_CCA_MAX_GOOD_VAL_9280_2GHZ  -97
#define AR_PHY_CCA_MAX_GOOD_VAL_9280_5GHZ  -102

#define AR_PHY_CCA_NOM_VAL_9285_2GHZ           -118
#define AR_PHY_CCA_MIN_GOOD_VAL_9285_2GHZ    -127
#define AR_PHY_CCA_MAX_GOOD_VAL_9285_2GHZ    -108

#define AR_PHY_CCA_NOM_VAL_9271_2GHZ             -118
#define AR_PHY_CCA_MIN_GOOD_VAL_9271_2GHZ      -127
#define AR_PHY_CCA_MAX_GOOD_VAL_9271_2GHZ      -116

#define AR_PHY_CCA_NOM_VAL_9287_2GHZ           -120
#define AR_PHY_CCA_MIN_GOOD_VAL_9287_2GHZ    -127
#define AR_PHY_CCA_MAX_GOOD_VAL_9287_2GHZ    -110

#endif
+9 −57
Original line number Diff line number Diff line
@@ -1015,52 +1015,6 @@ static bool ar9003_hw_ani_control(struct ath_hw *ah,
	return true;
}

static void ar9003_hw_nf_sanitize_2g(struct ath_hw *ah, s16 *nf)
{
	struct ath_common *common = ath9k_hw_common(ah);

	if (*nf > ah->nf_2g_max) {
		ath_print(common, ATH_DBG_CALIBRATE,
			  "2 GHz NF (%d) > MAX (%d), "
			  "correcting to MAX",
			  *nf, ah->nf_2g_max);
		*nf = ah->nf_2g_max;
	} else if (*nf < ah->nf_2g_min) {
		ath_print(common, ATH_DBG_CALIBRATE,
			  "2 GHz NF (%d) < MIN (%d), "
			  "correcting to MIN",
			  *nf, ah->nf_2g_min);
		*nf = ah->nf_2g_min;
	}
}

static void ar9003_hw_nf_sanitize_5g(struct ath_hw *ah, s16 *nf)
{
	struct ath_common *common = ath9k_hw_common(ah);

	if (*nf > ah->nf_5g_max) {
		ath_print(common, ATH_DBG_CALIBRATE,
			  "5 GHz NF (%d) > MAX (%d), "
			  "correcting to MAX",
			  *nf, ah->nf_5g_max);
		*nf = ah->nf_5g_max;
	} else if (*nf < ah->nf_5g_min) {
		ath_print(common, ATH_DBG_CALIBRATE,
			  "5 GHz NF (%d) < MIN (%d), "
			  "correcting to MIN",
			  *nf, ah->nf_5g_min);
		*nf = ah->nf_5g_min;
	}
}

static void ar9003_hw_nf_sanitize(struct ath_hw *ah, s16 *nf)
{
	if (IS_CHAN_2GHZ(ah->curchan))
		ar9003_hw_nf_sanitize_2g(ah, nf);
	else
		ar9003_hw_nf_sanitize_5g(ah, nf);
}

static void ar9003_hw_do_getnf(struct ath_hw *ah,
			      int16_t nfarray[NUM_NF_READINGS])
{
@@ -1070,7 +1024,6 @@ static void ar9003_hw_do_getnf(struct ath_hw *ah,
	nf = MS(REG_READ(ah, AR_PHY_CCA_0), AR_PHY_MINCCA_PWR);
	if (nf & 0x100)
		nf = 0 - ((nf ^ 0x1ff) + 1);
	ar9003_hw_nf_sanitize(ah, &nf);
	ath_print(common, ATH_DBG_CALIBRATE,
		  "NF calibrated [ctl] [chain 0] is %d\n", nf);
	nfarray[0] = nf;
@@ -1078,7 +1031,6 @@ static void ar9003_hw_do_getnf(struct ath_hw *ah,
	nf = MS(REG_READ(ah, AR_PHY_CCA_1), AR_PHY_CH1_MINCCA_PWR);
	if (nf & 0x100)
		nf = 0 - ((nf ^ 0x1ff) + 1);
	ar9003_hw_nf_sanitize(ah, &nf);
	ath_print(common, ATH_DBG_CALIBRATE,
		  "NF calibrated [ctl] [chain 1] is %d\n", nf);
	nfarray[1] = nf;
@@ -1086,7 +1038,6 @@ static void ar9003_hw_do_getnf(struct ath_hw *ah,
	nf = MS(REG_READ(ah, AR_PHY_CCA_2), AR_PHY_CH2_MINCCA_PWR);
	if (nf & 0x100)
		nf = 0 - ((nf ^ 0x1ff) + 1);
	ar9003_hw_nf_sanitize(ah, &nf);
	ath_print(common, ATH_DBG_CALIBRATE,
		  "NF calibrated [ctl] [chain 2] is %d\n", nf);
	nfarray[2] = nf;
@@ -1094,7 +1045,6 @@ static void ar9003_hw_do_getnf(struct ath_hw *ah,
	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA), AR_PHY_EXT_MINCCA_PWR);
	if (nf & 0x100)
		nf = 0 - ((nf ^ 0x1ff) + 1);
	ar9003_hw_nf_sanitize(ah, &nf);
	ath_print(common, ATH_DBG_CALIBRATE,
		  "NF calibrated [ext] [chain 0] is %d\n", nf);
	nfarray[3] = nf;
@@ -1102,7 +1052,6 @@ static void ar9003_hw_do_getnf(struct ath_hw *ah,
	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_1), AR_PHY_CH1_EXT_MINCCA_PWR);
	if (nf & 0x100)
		nf = 0 - ((nf ^ 0x1ff) + 1);
	ar9003_hw_nf_sanitize(ah, &nf);
	ath_print(common, ATH_DBG_CALIBRATE,
		  "NF calibrated [ext] [chain 1] is %d\n", nf);
	nfarray[4] = nf;
@@ -1110,18 +1059,19 @@ static void ar9003_hw_do_getnf(struct ath_hw *ah,
	nf = MS(REG_READ(ah, AR_PHY_EXT_CCA_2), AR_PHY_CH2_EXT_MINCCA_PWR);
	if (nf & 0x100)
		nf = 0 - ((nf ^ 0x1ff) + 1);
	ar9003_hw_nf_sanitize(ah, &nf);
	ath_print(common, ATH_DBG_CALIBRATE,
		  "NF calibrated [ext] [chain 2] is %d\n", nf);
	nfarray[5] = nf;
}

void ar9003_hw_set_nf_limits(struct ath_hw *ah)
static void ar9003_hw_set_nf_limits(struct ath_hw *ah)
{
	ah->nf_2g_max = AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ;
	ah->nf_2g_min = AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ;
	ah->nf_5g_max = AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ;
	ah->nf_5g_min = AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ;
	ah->nf_2g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_2GHZ;
	ah->nf_2g.min = AR_PHY_CCA_MIN_GOOD_VAL_9300_2GHZ;
	ah->nf_2g.nominal = AR_PHY_CCA_NOM_VAL_9300_2GHZ;
	ah->nf_5g.max = AR_PHY_CCA_MAX_GOOD_VAL_9300_5GHZ;
	ah->nf_5g.min = AR_PHY_CCA_MIN_GOOD_VAL_9300_5GHZ;
	ah->nf_5g.nominal = AR_PHY_CCA_NOM_VAL_9300_5GHZ;
}

/*
@@ -1309,6 +1259,8 @@ void ar9003_hw_attach_phy_ops(struct ath_hw *ah)
	priv_ops->do_getnf = ar9003_hw_do_getnf;
	priv_ops->loadnf = ar9003_hw_loadnf;
	priv_ops->ani_cache_ini_regs = ar9003_hw_ani_cache_ini_regs;

	ar9003_hw_set_nf_limits(ah);
}

void ar9003_hw_bb_watchdog_config(struct ath_hw *ah)
+39 −18
Original line number Diff line number Diff line
@@ -74,13 +74,8 @@ static void ath9k_hw_update_nfcal_hist_buffer(struct ath9k_nfcal_hist *h,
			h[i].currIndex = 0;

		if (h[i].invalidNFcount > 0) {
			if (nfarray[i] < AR_PHY_CCA_MIN_BAD_VALUE ||
			    nfarray[i] > AR_PHY_CCA_MAX_HIGH_VALUE) {
				h[i].invalidNFcount = ATH9K_NF_CAL_HIST_MAX;
			} else {
			h[i].invalidNFcount--;
			h[i].privNF = nfarray[i];
			}
		} else {
			h[i].privNF =
				ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
@@ -172,6 +167,35 @@ void ath9k_hw_start_nfcal(struct ath_hw *ah)
	REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
}

static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf)
{
	struct ath_common *common = ath9k_hw_common(ah);
	struct ath_nf_limits *limit;
	int i;

	if (IS_CHAN_2GHZ(ah->curchan))
		limit = &ah->nf_2g;
	else
		limit = &ah->nf_5g;

	for (i = 0; i < NUM_NF_READINGS; i++) {
		if (!nf[i])
			continue;

		if (nf[i] > limit->max) {
			ath_print(common, ATH_DBG_CALIBRATE,
				  "NF[%d] (%d) > MAX (%d), correcting to MAX",
				  i, nf[i], limit->max);
			nf[i] = limit->max;
		} else if (nf[i] < limit->min) {
			ath_print(common, ATH_DBG_CALIBRATE,
				  "NF[%d] (%d) < MIN (%d), correcting to NOM",
				  i, nf[i], limit->min);
			nf[i] = limit->nominal;
		}
	}
}

int16_t ath9k_hw_getnf(struct ath_hw *ah,
		       struct ath9k_channel *chan)
{
@@ -190,6 +214,7 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah,
		return chan->rawNoiseFloor;
	} else {
		ath9k_hw_do_getnf(ah, nfarray);
		ath9k_hw_nf_sanitize(ah, nfarray);
		nf = nfarray[0];
		if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh)
		    && nf > nfThresh) {
@@ -211,25 +236,21 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah,

void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah)
{
	struct ath_nf_limits *limit;
	int i, j;
	s16 noise_floor;

	if (AR_SREV_9280(ah))
		noise_floor = AR_PHY_CCA_MAX_AR9280_GOOD_VALUE;
	else if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
		noise_floor = AR_PHY_CCA_MAX_AR9285_GOOD_VALUE;
	else if (AR_SREV_9287(ah))
		noise_floor = AR_PHY_CCA_MAX_AR9287_GOOD_VALUE;

	if (!ah->curchan || IS_CHAN_2GHZ(ah->curchan))
		limit = &ah->nf_2g;
	else
		noise_floor = AR_PHY_CCA_MAX_AR5416_GOOD_VALUE;
		limit = &ah->nf_5g;

	for (i = 0; i < NUM_NF_READINGS; i++) {
		ah->nfCalHist[i].currIndex = 0;
		ah->nfCalHist[i].privNF = noise_floor;
		ah->nfCalHist[i].privNF = limit->nominal;
		ah->nfCalHist[i].invalidNFcount =
			AR_PHY_CCA_FILTERWINDOW_LENGTH;
		for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++) {
			ah->nfCalHist[i].nfCalBuffer[j] = noise_floor;
			ah->nfCalHist[i].nfCalBuffer[j] = limit->nominal;
		}
	}
}
Loading