ath9k: fix various calibration related bugs and clean up the code
[openwrt.git] / package / mac80211 / patches / 523-ath9k_nfcal_timeout_handling.patch
1 --- a/drivers/net/wireless/ath/ath9k/hw.h
2 +++ b/drivers/net/wireless/ath/ath9k/hw.h
3 @@ -354,6 +354,7 @@ struct ath9k_hw_cal_data {
4         int8_t qCoff;
5         int16_t rawNoiseFloor;
6         bool paprd_done;
7 +       bool nfcal_pending;
8         u16 small_signal_gain[AR9300_MAX_CHAINS];
9         u32 pa_table[AR9300_MAX_CHAINS][PAPRD_TABLE_SZ];
10         struct ath9k_nfcal_hist nfCalHist[NUM_NF_READINGS];
11 --- a/drivers/net/wireless/ath/ath9k/calib.c
12 +++ b/drivers/net/wireless/ath/ath9k/calib.c
13 @@ -156,6 +156,9 @@ EXPORT_SYMBOL(ath9k_hw_reset_calvalid);
14  
15  void ath9k_hw_start_nfcal(struct ath_hw *ah)
16  {
17 +       if (ah->caldata)
18 +               ah->caldata->nfcal_pending = true;
19 +
20         REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
21                     AR_PHY_AGC_CONTROL_ENABLE_NF);
22         REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
23 @@ -282,8 +285,7 @@ static void ath9k_hw_nf_sanitize(struct 
24         }
25  }
26  
27 -int16_t ath9k_hw_getnf(struct ath_hw *ah,
28 -                      struct ath9k_channel *chan)
29 +bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
30  {
31         struct ath_common *common = ath9k_hw_common(ah);
32         int16_t nf, nfThresh;
33 @@ -293,7 +295,7 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah
34         struct ath9k_hw_cal_data *caldata = ah->caldata;
35  
36         if (!caldata)
37 -               return ath9k_hw_get_default_nf(ah, chan);
38 +               return false;
39  
40         chan->channelFlags &= (~CHANNEL_CW_INT);
41         if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
42 @@ -301,7 +303,7 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah
43                           "NF did not complete in calibration window\n");
44                 nf = 0;
45                 caldata->rawNoiseFloor = nf;
46 -               return caldata->rawNoiseFloor;
47 +               return false;
48         } else {
49                 ath9k_hw_do_getnf(ah, nfarray);
50                 ath9k_hw_nf_sanitize(ah, nfarray);
51 @@ -317,11 +319,10 @@ int16_t ath9k_hw_getnf(struct ath_hw *ah
52         }
53  
54         h = caldata->nfCalHist;
55 -
56 +       caldata->nfcal_pending = false;
57         ath9k_hw_update_nfcal_hist_buffer(h, nfarray);
58         caldata->rawNoiseFloor = h[0].privNF;
59 -
60 -       return ah->caldata->rawNoiseFloor;
61 +       return true;
62  }
63  
64  void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
65 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c
66 +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c
67 @@ -687,8 +687,13 @@ static bool ar9002_hw_calibrate(struct a
68  {
69         bool iscaldone = true;
70         struct ath9k_cal_list *currCal = ah->cal_list_curr;
71 +       bool nfcal, nfcal_pending = false;
72  
73 -       if (currCal &&
74 +       nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF);
75 +       if (ah->caldata)
76 +               nfcal_pending = ah->caldata->nfcal_pending;
77 +
78 +       if (currCal && !nfcal &&
79             (currCal->calState == CAL_RUNNING ||
80              currCal->calState == CAL_WAITING)) {
81                 iscaldone = ar9002_hw_per_calibration(ah, chan,
82 @@ -704,7 +709,7 @@ static bool ar9002_hw_calibrate(struct a
83         }
84  
85         /* Do NF cal only at longer intervals */
86 -       if (longcal) {
87 +       if (longcal || nfcal_pending) {
88                 /* Do periodic PAOffset Cal */
89                 ar9002_hw_pa_cal(ah, false);
90                 ar9002_hw_olc_temp_compensation(ah);
91 @@ -713,16 +718,18 @@ static bool ar9002_hw_calibrate(struct a
92                  * Get the value from the previous NF cal and update
93                  * history buffer.
94                  */
95 -               ath9k_hw_getnf(ah, chan);
96 -
97 -               /*
98 -                * Load the NF from history buffer of the current channel.
99 -                * NF is slow time-variant, so it is OK to use a historical
100 -                * value.
101 -                */
102 -               ath9k_hw_loadnf(ah, ah->curchan);
103 +               if (ath9k_hw_getnf(ah, chan)) {
104 +                       /*
105 +                        * Load the NF from history buffer of the current
106 +                        * channel.
107 +                        * NF is slow time-variant, so it is OK to use a
108 +                        * historical value.
109 +                        */
110 +                       ath9k_hw_loadnf(ah, ah->curchan);
111 +               }
112  
113 -               ath9k_hw_start_nfcal(ah);
114 +               if (longcal)
115 +                       ath9k_hw_start_nfcal(ah);
116         }
117  
118         return iscaldone;
119 @@ -873,6 +880,9 @@ static bool ar9002_hw_init_cal(struct at
120         REG_WRITE(ah, AR_PHY_AGC_CONTROL,
121                   REG_READ(ah, AR_PHY_AGC_CONTROL) | AR_PHY_AGC_CONTROL_NF);
122  
123 +       if (ah->caldata)
124 +               ah->caldata->nfcal_pending = true;
125 +
126         ah->cal_list = ah->cal_list_last = ah->cal_list_curr = NULL;
127  
128         /* Enable IQ, ADC Gain and ADC DC offset CALs */
129 --- a/drivers/net/wireless/ath/ath9k/calib.h
130 +++ b/drivers/net/wireless/ath/ath9k/calib.h
131 @@ -110,8 +110,7 @@ struct ath9k_pacal_info{
132  bool ath9k_hw_reset_calvalid(struct ath_hw *ah);
133  void ath9k_hw_start_nfcal(struct ath_hw *ah);
134  void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan);
135 -int16_t ath9k_hw_getnf(struct ath_hw *ah,
136 -                      struct ath9k_channel *chan);
137 +bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan);
138  void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
139                                   struct ath9k_channel *chan);
140  s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan);