fix noise floor calibration by applying AR5K_PHY_NF_AVAL after
AR5K_PHY_NF_RVAL.  that way the XORed mask and value have the same length and
we get a reasonable noise value in -dBm.

move duplicate noise floor calibration code from two different places into one
function ath5k_hw_noise_floor_calibration().

the check for accepted noise_floor values (<= AR5K_TUNE_NOISE_FLOOR) should
only happen when we have an active reading and a converted value, so move it up
into the first if.

Changes-licensed-under: ISC
Signed-off-by: Bruno Randolf <[EMAIL PROTECTED]>
Acked-by: Nick Kossifidis <[EMAIL PROTECTED]>
---
 drivers/net/wireless/ath5k/ath5k.h |    1 +
 drivers/net/wireless/ath5k/hw.c    |   36 +------------
 drivers/net/wireless/ath5k/phy.c   |  100 ++++++++++++++++++++++++-----------
 3 files changed, 72 insertions(+), 65 deletions(-)

diff --git a/drivers/net/wireless/ath5k/ath5k.h 
b/drivers/net/wireless/ath5k/ath5k.h
index 1b8ddd9..5bcbbf9 100644
--- a/drivers/net/wireless/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath5k/ath5k.h
@@ -1127,6 +1127,7 @@ extern int ath5k_hw_phy_disable(struct ath5k_hw *ah);
 extern u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan);
 extern void ath5k_hw_set_def_antenna(struct ath5k_hw *ah, unsigned int ant);
 extern unsigned int ath5k_hw_get_def_antenna(struct ath5k_hw *ah);
+extern int ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq);
 /* TX power setup */
 extern int ath5k_hw_txpower(struct ath5k_hw *ah, struct ieee80211_channel 
*channel, unsigned int txpower);
 extern int ath5k_hw_set_txpower_limit(struct ath5k_hw *ah, unsigned int power);
diff --git a/drivers/net/wireless/ath5k/hw.c b/drivers/net/wireless/ath5k/hw.c
index 752bd6a..83fd241 100644
--- a/drivers/net/wireless/ath5k/hw.c
+++ b/drivers/net/wireless/ath5k/hw.c
@@ -591,7 +591,6 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum 
ieee80211_if_types op_mode,
 {
        struct ath5k_eeprom_info *ee = &ah->ah_capabilities.cap_eeprom;
        u32 data, s_seq, s_ant, s_led[3];
-       s32 noise_floor;
        unsigned int i, mode, freq, ee_mode, ant[2], driver_mode = -1;
        int ret;
 
@@ -914,38 +913,9 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum 
ieee80211_if_types op_mode,
                return -EAGAIN;
        }
 
-       /*
-        * Enable noise floor calibration and wait until completion
-        */
-       AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
-                               AR5K_PHY_AGCCTL_NF);
-
-       if (ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
-                       AR5K_PHY_AGCCTL_NF, 0, false)) {
-               ATH5K_ERR(ah->ah_sc,
-                       "noise floor calibration timeout (%uMHz)\n",
-                       channel->freq);
-               return -EAGAIN;
-       }
-
-       /* Wait until the noise floor is calibrated and read the value */
-       for (i = 20; i > 0; i--) {
-               mdelay(1);
-               noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
-
-               if (AR5K_PHY_NF_RVAL(noise_floor) & AR5K_PHY_NF_ACTIVE)
-                       noise_floor = AR5K_PHY_NF_AVAL(noise_floor);
-
-               if (noise_floor <= AR5K_TUNE_NOISE_FLOOR)
-                       break;
-       }
-
-       if (noise_floor > AR5K_TUNE_NOISE_FLOOR) {
-               ATH5K_ERR(ah->ah_sc,
-                       "noise floor calibration failed (%uMHz)\n",
-                       channel->freq);
-               return -EIO;
-       }
+       ret = ath5k_hw_noise_floor_calibration(ah, channel->freq);
+       if (ret)
+               return ret;
 
        ah->ah_calibration = false;
 
diff --git a/drivers/net/wireless/ath5k/phy.c b/drivers/net/wireless/ath5k/phy.c
index 3c2a67c..7dba325 100644
--- a/drivers/net/wireless/ath5k/phy.c
+++ b/drivers/net/wireless/ath5k/phy.c
@@ -1520,6 +1520,72 @@ int ath5k_hw_channel(struct ath5k_hw *ah, struct 
ieee80211_channel *channel)
   PHY calibration
 \*****************/
 
+/**
+ * ath5k_hw_noise_floor_calibration - perform PHY noise floor calibration
+ *
+ * @ah: struct ath5k_hw pointer we are operating on
+ * @freq: the channel frequency, just used for error logging
+ *
+ * This function performs a noise floor calibration of the PHY and waits for
+ * it to complete. Then the noise floor value is compared to some maximum
+ * noise floor we consider valid.
+ *
+ * Note that this is different from what the madwifi HAL does: it reads the
+ * noise floor and afterwards initiates the calibration. Since the noise floor
+ * calibration can take some time to finish, depending on the current channel
+ * use, that avoids the occasional timeout warnings we are seeing now.
+ *
+ * See the following link for an Atheros patent on noise floor calibration:
+ * http://patft.uspto.gov/netacgi/nph-Parser?Sect1=PTO1&Sect2=HITOFF&d=PALL \
+ * &p=1&u=%2Fnetahtml%2FPTO%2Fsrchnum.htm&r=1&f=G&l=50&s1=7245893.PN.&OS=PN/7
+ *
+ */
+int
+ath5k_hw_noise_floor_calibration(struct ath5k_hw *ah, short freq)
+{
+       int ret;
+       unsigned int i;
+       s32 noise_floor;
+
+       /*
+        * Enable noise floor calibration and wait until completion
+        */
+       AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL,
+                               AR5K_PHY_AGCCTL_NF);
+
+       ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
+                       AR5K_PHY_AGCCTL_NF, 0, false);
+       if (ret) {
+               ATH5K_ERR(ah->ah_sc,
+                       "noise floor calibration timeout (%uMHz)\n", freq);
+               return ret;
+       }
+
+       /* Wait until the noise floor is calibrated and read the value */
+       for (i = 20; i > 0; i--) {
+               mdelay(1);
+               noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
+               noise_floor = AR5K_PHY_NF_RVAL(noise_floor);
+               if (noise_floor & AR5K_PHY_NF_ACTIVE) {
+                       noise_floor = AR5K_PHY_NF_AVAL(noise_floor);
+
+                       if (noise_floor <= AR5K_TUNE_NOISE_FLOOR)
+                               break;
+               }
+       }
+
+       ATH5K_DBG_UNLIMIT(ah->ah_sc, ATH5K_DEBUG_CALIBRATE,
+               "noise floor %d\n", noise_floor);
+
+       if (noise_floor > AR5K_TUNE_NOISE_FLOOR) {
+               ATH5K_ERR(ah->ah_sc,
+                       "noise floor calibration failed (%uMHz)\n", freq);
+               return -EIO;
+       }
+
+       return 0;
+}
+
 /*
  * Perform a PHY calibration on RF5110
  * -Fix BPSK/QAM Constellation (I/Q correction)
@@ -1529,8 +1595,6 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
                struct ieee80211_channel *channel)
 {
        u32 phy_sig, phy_agc, phy_sat, beacon;
-       s32 noise_floor;
-       unsigned int i;
        int ret;
 
        /*
@@ -1612,37 +1676,9 @@ static int ath5k_hw_rf5110_calibrate(struct ath5k_hw *ah,
                return ret;
        }
 
-       /*
-        * Enable noise floor calibration and wait until completion
-        */
-       AR5K_REG_ENABLE_BITS(ah, AR5K_PHY_AGCCTL, AR5K_PHY_AGCCTL_NF);
-
-       ret = ath5k_hw_register_timeout(ah, AR5K_PHY_AGCCTL,
-                       AR5K_PHY_AGCCTL_NF, 0, false);
-       if (ret) {
-               ATH5K_ERR(ah->ah_sc,
-                       "noise floor calibration timeout (%uMHz)\n",
-                       channel->freq);
+       ret = ath5k_hw_noise_floor_calibration(ah, channel->freq);
+       if (ret)
                return ret;
-       }
-
-       /* Wait until the noise floor is calibrated */
-       for (i = 20; i > 0; i--) {
-               mdelay(1);
-               noise_floor = ath5k_hw_reg_read(ah, AR5K_PHY_NF);
-
-               if (AR5K_PHY_NF_RVAL(noise_floor) & AR5K_PHY_NF_ACTIVE)
-                       noise_floor = AR5K_PHY_NF_AVAL(noise_floor);
-
-               if (noise_floor <= AR5K_TUNE_NOISE_FLOOR)
-                       break;
-       }
-
-       if (noise_floor > AR5K_TUNE_NOISE_FLOOR) {
-               ATH5K_ERR(ah->ah_sc, "noise floor calibration failed (%uMHz)\n",
-                       channel->freq);
-               return -EIO;
-       }
 
        /*
         * Re-enable RX/TX and beacons
-- 
1.5.3.4

_______________________________________________
ath5k-devel mailing list
ath5k-devel@lists.ath5k.org
https://lists.ath5k.org/mailman/listinfo/ath5k-devel

Reply via email to