ath9k: Fix antenna diversity for CUS198
authorSujith Manoharan <c_manoha@qca.qualcomm.com>
Sun, 4 Aug 2013 08:51:54 +0000 (14:21 +0530)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 5 Aug 2013 18:52:41 +0000 (14:52 -0400)
CUS198/CUS230 need a few tweaks in the antenna diversity
algorithm to accomodate RSSI variation. Add a couple
of knobs to control low RSSI threshold and fast antenna
diversity bias values.

Signed-off-by: Sujith Manoharan <c_manoha@qca.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/ath/ath9k/antenna.c
drivers/net/wireless/ath/ath9k/ath9k.h
drivers/net/wireless/ath/ath9k/init.c

index 4cd2bcead1e55132052e8f04105227d98ac0c345..8de314cd4aed92733434e48e1dbe9e1b3af984c8 100644 (file)
  * enable_ant_fast_div      ==> bit 7
  */
 
-static inline bool ath_is_alt_ant_ratio_better(int alt_ratio, int maxdelta,
+static inline bool ath_is_alt_ant_ratio_better(struct ath_ant_comb *antcomb,
+                                              int alt_ratio, int maxdelta,
                                               int mindelta, int main_rssi_avg,
                                               int alt_rssi_avg, int pkt_count)
 {
-       return (((alt_ratio >= ATH_ANT_DIV_COMB_ALT_ANT_RATIO2) &&
-                (alt_rssi_avg > main_rssi_avg + maxdelta)) ||
-               (alt_rssi_avg > main_rssi_avg + mindelta)) && (pkt_count > 50);
+       if (pkt_count <= 50)
+               return false;
+
+       if (alt_rssi_avg > main_rssi_avg + mindelta)
+               return true;
+
+       if (alt_ratio >= antcomb->ant_ratio2 &&
+           alt_rssi_avg >= antcomb->low_rssi_thresh &&
+           (alt_rssi_avg > main_rssi_avg + maxdelta))
+               return true;
+
+       return false;
 }
 
 static inline bool ath_ant_div_comb_alt_check(struct ath_hw_antcomb_conf *conf,
+                                             struct ath_ant_comb *antcomb,
                                              int alt_ratio, int alt_rssi_avg,
                                              int main_rssi_avg)
 {
@@ -100,20 +111,22 @@ static inline bool ath_ant_div_comb_alt_check(struct ath_hw_antcomb_conf *conf,
                break;
        case 1:
        case 2:
-               if (alt_rssi_avg < 4)
+               if (alt_rssi_avg < 4 || alt_rssi_avg < antcomb->low_rssi_thresh)
                        break;
 
                if ((set1 && (alt_rssi_avg >= (main_rssi_avg - 5))) ||
-                   (set2 && (alt_rssi_avg >= (main_rssi_avg - 2))))
+                   (set2 && (alt_rssi_avg >= (main_rssi_avg - 2))) ||
+                   (alt_ratio > antcomb->ant_ratio))
                        result = true;
 
                break;
        case 3:
-               if (alt_rssi_avg < 4)
+               if (alt_rssi_avg < 4 || alt_rssi_avg < antcomb->low_rssi_thresh)
                        break;
 
                if ((set1 && (alt_rssi_avg >= (main_rssi_avg - 3))) ||
-                   (set2 && (alt_rssi_avg >= (main_rssi_avg + 3))))
+                   (set2 && (alt_rssi_avg >= (main_rssi_avg + 3))) ||
+                   (alt_ratio > antcomb->ant_ratio))
                        result = true;
 
                break;
@@ -266,7 +279,7 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb,
 
                if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) {
                        /* main is LNA1 */
-                       if (ath_is_alt_ant_ratio_better(alt_ratio,
+                       if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio,
                                                ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
                                                ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
                                                main_rssi_avg, alt_rssi_avg,
@@ -275,7 +288,7 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb,
                        else
                                antcomb->first_ratio = false;
                } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) {
-                       if (ath_is_alt_ant_ratio_better(alt_ratio,
+                       if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio,
                                                ATH_ANT_DIV_COMB_LNA1_DELTA_MID,
                                                ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
                                                main_rssi_avg, alt_rssi_avg,
@@ -284,7 +297,7 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb,
                        else
                                antcomb->first_ratio = false;
                } else {
-                       if (ath_is_alt_ant_ratio_better(alt_ratio,
+                       if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio,
                                                ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
                                                0,
                                                main_rssi_avg, alt_rssi_avg,
@@ -325,7 +338,7 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb,
                        div_ant_conf->main_lna_conf = ATH_ANT_DIV_COMB_LNA1;
 
                if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA1) {
-                       if (ath_is_alt_ant_ratio_better(alt_ratio,
+                       if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio,
                                                ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
                                                ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
                                                main_rssi_avg, alt_rssi_avg,
@@ -334,7 +347,7 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb,
                        else
                                antcomb->second_ratio = false;
                } else if (antcomb->main_conf == ATH_ANT_DIV_COMB_LNA2) {
-                       if (ath_is_alt_ant_ratio_better(alt_ratio,
+                       if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio,
                                                ATH_ANT_DIV_COMB_LNA1_DELTA_MID,
                                                ATH_ANT_DIV_COMB_LNA1_DELTA_LOW,
                                                main_rssi_avg, alt_rssi_avg,
@@ -343,7 +356,7 @@ static void ath_select_ant_div_from_quick_scan(struct ath_ant_comb *antcomb,
                        else
                                antcomb->second_ratio = false;
                } else {
-                       if (ath_is_alt_ant_ratio_better(alt_ratio,
+                       if (ath_is_alt_ant_ratio_better(antcomb, alt_ratio,
                                                ATH_ANT_DIV_COMB_LNA1_DELTA_HI,
                                                0,
                                                main_rssi_avg, alt_rssi_avg,
@@ -484,8 +497,7 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
                        ant_conf->fast_div_bias = 0x1;
                        break;
                case 0x10: /* LNA2 A-B */
-                       if (!(antcomb->scan) &&
-                               (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+                       if (!antcomb->scan && (alt_ratio > antcomb->ant_ratio))
                                ant_conf->fast_div_bias = 0x1;
                        else
                                ant_conf->fast_div_bias = 0x2;
@@ -494,15 +506,13 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
                        ant_conf->fast_div_bias = 0x1;
                        break;
                case 0x13: /* LNA2 A+B */
-                       if (!(antcomb->scan) &&
-                               (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+                       if (!antcomb->scan && (alt_ratio > antcomb->ant_ratio))
                                ant_conf->fast_div_bias = 0x1;
                        else
                                ant_conf->fast_div_bias = 0x2;
                        break;
                case 0x20: /* LNA1 A-B */
-                       if (!(antcomb->scan) &&
-                               (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+                       if (!antcomb->scan && (alt_ratio > antcomb->ant_ratio))
                                ant_conf->fast_div_bias = 0x1;
                        else
                                ant_conf->fast_div_bias = 0x2;
@@ -511,8 +521,7 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
                        ant_conf->fast_div_bias = 0x1;
                        break;
                case 0x23: /* LNA1 A+B */
-                       if (!(antcomb->scan) &&
-                               (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO))
+                       if (!antcomb->scan && (alt_ratio > antcomb->ant_ratio))
                                ant_conf->fast_div_bias = 0x1;
                        else
                                ant_conf->fast_div_bias = 0x2;
@@ -529,6 +538,9 @@ static void ath_ant_div_conf_fast_divbias(struct ath_hw_antcomb_conf *ant_conf,
                default:
                        break;
                }
+
+               if (antcomb->fast_div_bias)
+                       ant_conf->fast_div_bias = antcomb->fast_div_bias;
        } else if (ant_conf->div_group == 3) {
                switch ((ant_conf->main_lna_conf << 4) |
                        ant_conf->alt_lna_conf) {
@@ -668,13 +680,14 @@ static void ath_ant_try_scan(struct ath_ant_comb *antcomb,
 }
 
 static bool ath_ant_try_switch(struct ath_hw_antcomb_conf *div_ant_conf,
+                              struct ath_ant_comb *antcomb,
                               int alt_ratio, int alt_rssi_avg,
                               int main_rssi_avg, int curr_main_set,
                               int curr_alt_set)
 {
        bool ret = false;
 
-       if (ath_ant_div_comb_alt_check(div_ant_conf, alt_ratio,
+       if (ath_ant_div_comb_alt_check(div_ant_conf, antcomb, alt_ratio,
                                       alt_rssi_avg, main_rssi_avg)) {
                if (curr_alt_set == ATH_ANT_DIV_COMB_LNA2) {
                        /*
@@ -718,7 +731,7 @@ static bool ath_ant_short_scan_check(struct ath_ant_comb *antcomb)
        if (antcomb->total_pkt_count == ATH_ANT_DIV_COMB_SHORT_SCAN_PKTCOUNT) {
                alt_ratio = ((antcomb->alt_recv_cnt * 100) /
                             antcomb->total_pkt_count);
-               if (alt_ratio < ATH_ANT_DIV_COMB_ALT_ANT_RATIO)
+               if (alt_ratio < antcomb->ant_ratio)
                        return true;
        }
 
@@ -741,6 +754,14 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs)
        main_ant_conf = (rs->rs_rssi_ctl2 >> ATH_ANT_RX_MAIN_SHIFT) &
                         ATH_ANT_RX_MASK;
 
+       if (alt_rssi >= antcomb->low_rssi_thresh) {
+               antcomb->ant_ratio = ATH_ANT_DIV_COMB_ALT_ANT_RATIO;
+               antcomb->ant_ratio2 = ATH_ANT_DIV_COMB_ALT_ANT_RATIO2;
+       } else {
+               antcomb->ant_ratio = ATH_ANT_DIV_COMB_ALT_ANT_RATIO_LOW_RSSI;
+               antcomb->ant_ratio2 = ATH_ANT_DIV_COMB_ALT_ANT_RATIO2_LOW_RSSI;
+       }
+
        /* Record packet only when both main_rssi and  alt_rssi is positive */
        if (main_rssi > 0 && alt_rssi > 0) {
                antcomb->total_pkt_count++;
@@ -783,7 +804,7 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs)
        antcomb->count++;
 
        if (antcomb->count == ATH_ANT_DIV_COMB_MAX_COUNT) {
-               if (alt_ratio > ATH_ANT_DIV_COMB_ALT_ANT_RATIO) {
+               if (alt_ratio > antcomb->ant_ratio) {
                        ath_lnaconf_alt_good_scan(antcomb, div_ant_conf,
                                                  main_rssi_avg);
                        antcomb->alt_good = true;
@@ -797,7 +818,7 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs)
        }
 
        if (!antcomb->scan) {
-               ret = ath_ant_try_switch(&div_ant_conf, alt_ratio,
+               ret = ath_ant_try_switch(&div_ant_conf, antcomb, alt_ratio,
                                         alt_rssi_avg, main_rssi_avg,
                                         curr_main_set, curr_alt_set);
                if (ret)
index ed8f8efb6ecf37243624e40176bf13e317e318b7..74009f1238a04e4f6b815b339288abac8ffed07f 100644 (file)
@@ -585,6 +585,8 @@ static inline void ath_fill_led_pin(struct ath_softc *sc)
 #define ATH_ANT_DIV_COMB_MAX_COUNT 100
 #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO 30
 #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2 20
+#define ATH_ANT_DIV_COMB_ALT_ANT_RATIO_LOW_RSSI 50
+#define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2_LOW_RSSI 50
 
 #define ATH_ANT_DIV_COMB_LNA1_LNA2_SWITCH_DELTA -1
 #define ATH_ANT_DIV_COMB_LNA1_DELTA_HI -4
@@ -607,6 +609,8 @@ struct ath_ant_comb {
        int rssi_first;
        int rssi_second;
        int rssi_third;
+       int ant_ratio;
+       int ant_ratio2;
        bool alt_good;
        int quick_scan_cnt;
        enum ath9k_ant_div_comb_lna_conf main_conf;
@@ -615,6 +619,12 @@ struct ath_ant_comb {
        bool first_ratio;
        bool second_ratio;
        unsigned long scan_start_time;
+
+       /*
+        * Card-specific config values.
+        */
+       int low_rssi_thresh;
+       int fast_div_bias;
 };
 
 void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs);
index 16f8b201642b71de28ba4920735d0c8a2f5ee8b0..7ded9d607db0090706e2c258554b34cc2b49baa0 100644 (file)
@@ -525,6 +525,8 @@ static void ath9k_init_platform(struct ath_softc *sc)
                               ATH9K_PCI_CUS230)) {
                ah->config.xlna_gpio = 9;
                ah->config.xatten_margin_cfg = true;
+               sc->ant_comb.low_rssi_thresh = 20;
+               sc->ant_comb.fast_div_bias = 3;
 
                ath_info(common, "Set parameters for %s\n",
                         (sc->driver_data & ATH9K_PCI_CUS198) ?