LCOV - code coverage report
Current view: top level - drivers/net/wireless/ath/ath9k - calib.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 170 223 76.2 %
Date: 2022-03-28 13:20:08 Functions: 9 12 75.0 %
Branches: 135 233 57.9 %

           Branch data     Line data    Source code
       1                 :            : /*
       2                 :            :  * Copyright (c) 2008-2011 Atheros Communications Inc.
       3                 :            :  *
       4                 :            :  * Permission to use, copy, modify, and/or distribute this software for any
       5                 :            :  * purpose with or without fee is hereby granted, provided that the above
       6                 :            :  * copyright notice and this permission notice appear in all copies.
       7                 :            :  *
       8                 :            :  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
       9                 :            :  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
      10                 :            :  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
      11                 :            :  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      12                 :            :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
      13                 :            :  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
      14                 :            :  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      15                 :            :  */
      16                 :            : 
      17                 :            : #include "hw.h"
      18                 :            : #include "hw-ops.h"
      19                 :            : #include <linux/export.h>
      20                 :            : 
      21                 :            : /* Common calibration code */
      22                 :            : 
      23                 :            : 
      24                 :          0 : static int16_t ath9k_hw_get_nf_hist_mid(int16_t *nfCalBuffer)
      25                 :            : {
      26                 :          0 :         int16_t nfval;
      27                 :          0 :         int16_t sort[ATH9K_NF_CAL_HIST_MAX];
      28                 :          0 :         int i, j;
      29                 :            : 
      30         [ #  # ]:          0 :         for (i = 0; i < ATH9K_NF_CAL_HIST_MAX; i++)
      31                 :          0 :                 sort[i] = nfCalBuffer[i];
      32                 :            : 
      33         [ #  # ]:          0 :         for (i = 0; i < ATH9K_NF_CAL_HIST_MAX - 1; i++) {
      34         [ #  # ]:          0 :                 for (j = 1; j < ATH9K_NF_CAL_HIST_MAX - i; j++) {
      35         [ #  # ]:          0 :                         if (sort[j] > sort[j - 1]) {
      36                 :          0 :                                 nfval = sort[j];
      37                 :          0 :                                 sort[j] = sort[j - 1];
      38                 :          0 :                                 sort[j - 1] = nfval;
      39                 :            :                         }
      40                 :            :                 }
      41                 :            :         }
      42                 :          0 :         nfval = sort[(ATH9K_NF_CAL_HIST_MAX - 1) >> 1];
      43                 :            : 
      44                 :          0 :         return nfval;
      45                 :            : }
      46                 :            : 
      47                 :        381 : static struct ath_nf_limits *ath9k_hw_get_nf_limits(struct ath_hw *ah,
      48                 :            :                                                     struct ath9k_channel *chan)
      49                 :            : {
      50                 :        381 :         struct ath_nf_limits *limit;
      51                 :            : 
      52   [ +  -  +  -  :        381 :         if (!chan || IS_CHAN_2GHZ(chan))
          +  -  +  -  +  
             -  +  -  +  
                      - ]
      53                 :        381 :                 limit = &ah->nf_2g;
      54                 :            :         else
      55                 :          0 :                 limit = &ah->nf_5g;
      56                 :            : 
      57                 :        381 :         return limit;
      58                 :            : }
      59                 :            : 
      60                 :        141 : static s16 ath9k_hw_get_default_nf(struct ath_hw *ah,
      61                 :            :                                    struct ath9k_channel *chan,
      62                 :            :                                    int chain)
      63                 :            : {
      64                 :        282 :         s16 calib_nf = ath9k_hw_get_nf_limits(ah, chan)->cal[chain];
      65                 :            : 
      66   [ +  -  +  - ]:        141 :         if (calib_nf)
      67                 :            :                 return calib_nf;
      68                 :            :         else
      69   [ +  -  +  - ]:        282 :                 return ath9k_hw_get_nf_limits(ah, chan)->nominal;
      70                 :            : }
      71                 :            : 
      72                 :         93 : s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan,
      73                 :            :                            s16 nf)
      74                 :            : {
      75                 :         93 :         s8 noise = ATH_DEFAULT_NOISE_FLOOR;
      76                 :            : 
      77         [ +  + ]:         93 :         if (nf) {
      78         [ +  - ]:         75 :                 s8 delta = nf - ATH9K_NF_CAL_NOISE_THRESH -
      79                 :            :                            ath9k_hw_get_default_nf(ah, chan, 0);
      80         [ +  + ]:         75 :                 if (delta > 0)
      81                 :         45 :                         noise += delta;
      82                 :            :         }
      83                 :         93 :         return noise;
      84                 :            : }
      85                 :            : EXPORT_SYMBOL(ath9k_hw_getchan_noise);
      86                 :            : 
      87                 :         23 : static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
      88                 :            :                                               struct ath9k_hw_cal_data *cal,
      89                 :            :                                               int16_t *nfarray)
      90                 :            : {
      91         [ +  - ]:         23 :         struct ath_common *common = ath9k_hw_common(ah);
      92                 :         23 :         struct ath_nf_limits *limit;
      93                 :         23 :         struct ath9k_nfcal_hist *h;
      94                 :         23 :         bool high_nf_mid = false;
      95                 :         23 :         u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
      96                 :         23 :         int i;
      97                 :            : 
      98                 :         23 :         h = cal->nfCalHist;
      99         [ +  - ]:         23 :         limit = ath9k_hw_get_nf_limits(ah, ah->curchan);
     100                 :            : 
     101         [ +  + ]:        161 :         for (i = 0; i < NUM_NF_READINGS; i++) {
     102   [ +  +  +  + ]:        138 :                 if (!(chainmask & (1 << i)) ||
     103         [ +  - ]:         61 :                     ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(ah->curchan)))
     104                 :         77 :                         continue;
     105                 :            : 
     106                 :         61 :                 h[i].nfCalBuffer[h[i].currIndex] = nfarray[i];
     107                 :            : 
     108         [ -  + ]:         61 :                 if (++h[i].currIndex >= ATH9K_NF_CAL_HIST_MAX)
     109                 :          0 :                         h[i].currIndex = 0;
     110                 :            : 
     111         [ +  - ]:         61 :                 if (h[i].invalidNFcount > 0) {
     112                 :         61 :                         h[i].invalidNFcount--;
     113                 :         61 :                         h[i].privNF = nfarray[i];
     114                 :            :                 } else {
     115                 :          0 :                         h[i].privNF =
     116                 :          0 :                                 ath9k_hw_get_nf_hist_mid(h[i].nfCalBuffer);
     117                 :            :                 }
     118                 :            : 
     119         [ +  + ]:         61 :                 if (!h[i].privNF)
     120                 :          7 :                         continue;
     121                 :            : 
     122         [ -  + ]:         54 :                 if (h[i].privNF > limit->max) {
     123                 :          0 :                         high_nf_mid = true;
     124                 :            : 
     125   [ #  #  #  # ]:          0 :                         ath_dbg(common, CALIBRATE,
     126                 :            :                                 "NFmid[%d] (%d) > MAX (%d), %s\n",
     127                 :            :                                 i, h[i].privNF, limit->max,
     128                 :            :                                 (test_bit(NFCAL_INTF, &cal->cal_flags) ?
     129                 :            :                                  "not corrected (due to interference)" :
     130                 :            :                                  "correcting to MAX"));
     131                 :            : 
     132                 :            :                         /*
     133                 :            :                          * Normally we limit the average noise floor by the
     134                 :            :                          * hardware specific maximum here. However if we have
     135                 :            :                          * encountered stuck beacons because of interference,
     136                 :            :                          * we bypass this limit here in order to better deal
     137                 :            :                          * with our environment.
     138                 :            :                          */
     139         [ #  # ]:          0 :                         if (!test_bit(NFCAL_INTF, &cal->cal_flags))
     140                 :          0 :                                 h[i].privNF = limit->max;
     141                 :            :                 }
     142                 :            :         }
     143                 :            : 
     144                 :            :         /*
     145                 :            :          * If the noise floor seems normal for all chains, assume that
     146                 :            :          * there is no significant interference in the environment anymore.
     147                 :            :          * Re-enable the enforcement of the NF maximum again.
     148                 :            :          */
     149         [ +  - ]:         23 :         if (!high_nf_mid)
     150                 :         23 :                 clear_bit(NFCAL_INTF, &cal->cal_flags);
     151                 :         23 : }
     152                 :            : 
     153                 :         28 : static bool ath9k_hw_get_nf_thresh(struct ath_hw *ah,
     154                 :            :                                    enum nl80211_band band,
     155                 :            :                                    int16_t *nft)
     156                 :            : {
     157      [ -  +  - ]:         28 :         switch (band) {
     158                 :          0 :         case NL80211_BAND_5GHZ:
     159                 :          0 :                 *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_5);
     160                 :          0 :                 break;
     161                 :         28 :         case NL80211_BAND_2GHZ:
     162                 :         28 :                 *nft = (int8_t)ah->eep_ops->get_eeprom(ah, EEP_NFTHRESH_2);
     163                 :         28 :                 break;
     164                 :            :         default:
     165                 :          0 :                 BUG_ON(1);
     166                 :            :                 return false;
     167                 :            :         }
     168                 :            : 
     169                 :         28 :         return true;
     170                 :            : }
     171                 :            : 
     172                 :         40 : void ath9k_hw_reset_calibration(struct ath_hw *ah,
     173                 :            :                                 struct ath9k_cal_list *currCal)
     174                 :            : {
     175                 :         40 :         int i;
     176                 :            : 
     177                 :         40 :         ath9k_hw_setup_calibration(ah, currCal);
     178                 :            : 
     179                 :         40 :         currCal->calState = CAL_RUNNING;
     180                 :            : 
     181         [ +  + ]:        160 :         for (i = 0; i < AR5416_MAX_CHAINS; i++) {
     182                 :        120 :                 ah->meas0.sign[i] = 0;
     183                 :        120 :                 ah->meas1.sign[i] = 0;
     184                 :        120 :                 ah->meas2.sign[i] = 0;
     185                 :        120 :                 ah->meas3.sign[i] = 0;
     186                 :            :         }
     187                 :            : 
     188                 :         40 :         ah->cal_samples = 0;
     189                 :         40 : }
     190                 :            : 
     191                 :            : /* This is done for the currently configured channel */
     192                 :          0 : bool ath9k_hw_reset_calvalid(struct ath_hw *ah)
     193                 :            : {
     194         [ #  # ]:          0 :         struct ath_common *common = ath9k_hw_common(ah);
     195                 :          0 :         struct ath9k_cal_list *currCal = ah->cal_list_curr;
     196                 :            : 
     197         [ #  # ]:          0 :         if (!ah->caldata)
     198                 :            :                 return true;
     199                 :            : 
     200   [ #  #  #  # ]:          0 :         if (!AR_SREV_9100(ah) && !AR_SREV_9160_10_OR_LATER(ah))
     201                 :            :                 return true;
     202                 :            : 
     203         [ #  # ]:          0 :         if (currCal == NULL)
     204                 :            :                 return true;
     205                 :            : 
     206         [ #  # ]:          0 :         if (currCal->calState != CAL_DONE) {
     207         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE, "Calibration state incorrect, %d\n",
     208                 :            :                         currCal->calState);
     209                 :          0 :                 return true;
     210                 :            :         }
     211                 :            : 
     212         [ #  # ]:          0 :         if (!(ah->supp_cals & currCal->calData->calType))
     213                 :            :                 return true;
     214                 :            : 
     215         [ #  # ]:          0 :         ath_dbg(common, CALIBRATE, "Resetting Cal %d state for channel %u\n",
     216                 :            :                 currCal->calData->calType, ah->curchan->chan->center_freq);
     217                 :            : 
     218                 :          0 :         ah->caldata->CalValid &= ~currCal->calData->calType;
     219                 :          0 :         currCal->calState = CAL_WAITING;
     220                 :            : 
     221                 :          0 :         return false;
     222                 :            : }
     223                 :            : EXPORT_SYMBOL(ath9k_hw_reset_calvalid);
     224                 :            : 
     225                 :         60 : void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update)
     226                 :            : {
     227         [ +  + ]:         60 :         if (ah->caldata)
     228                 :         54 :                 set_bit(NFCAL_PENDING, &ah->caldata->cal_flags);
     229                 :            : 
     230         [ +  + ]:         80 :         REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
     231                 :            :                     AR_PHY_AGC_CONTROL_ENABLE_NF);
     232                 :            : 
     233         [ +  - ]:         60 :         if (update)
     234         [ +  + ]:         80 :                 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
     235                 :            :                     AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
     236                 :            :         else
     237         [ #  # ]:          0 :                 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
     238                 :            :                     AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
     239                 :            : 
     240         [ +  + ]:         80 :         REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
     241                 :         60 : }
     242                 :            : 
     243                 :         60 : int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
     244                 :            : {
     245                 :         60 :         struct ath9k_nfcal_hist *h = NULL;
     246                 :         60 :         unsigned i, j;
     247                 :         60 :         u8 chainmask = (ah->rxchainmask << 3) | ah->rxchainmask;
     248         [ +  - ]:         60 :         struct ath_common *common = ath9k_hw_common(ah);
     249         [ +  - ]:         60 :         s16 default_nf = ath9k_hw_get_nf_limits(ah, chan)->nominal;
     250         [ +  + ]:         80 :         u32 bb_agc_ctl = REG_READ(ah, AR_PHY_AGC_CONTROL);
     251                 :            : 
     252         [ +  + ]:         60 :         if (ah->caldata)
     253                 :         54 :                 h = ah->caldata->nfCalHist;
     254                 :            : 
     255         [ -  + ]:         60 :         ENABLE_REG_RMW_BUFFER(ah);
     256         [ +  + ]:        420 :         for (i = 0; i < NUM_NF_READINGS; i++) {
     257         [ +  + ]:        360 :                 if (chainmask & (1 << i)) {
     258                 :        316 :                         s16 nfval;
     259                 :            : 
     260   [ +  +  +  - ]:        316 :                         if ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(chan))
     261                 :        158 :                                 continue;
     262                 :            : 
     263         [ +  - ]:        158 :                         if (ah->nf_override)
     264                 :            :                                 nfval = ah->nf_override;
     265         [ +  + ]:        158 :                         else if (h)
     266                 :        142 :                                 nfval = h[i].privNF;
     267                 :            :                         else {
     268                 :            :                                 /* Try to get calibrated noise floor value */
     269         [ +  - ]:         16 :                                 nfval =
     270                 :            :                                     ath9k_hw_get_nf_limits(ah, chan)->cal[i];
     271         [ +  - ]:         16 :                                 if (nfval > -60 || nfval < -127)
     272                 :         16 :                                         nfval = default_nf;
     273                 :            :                         }
     274                 :            : 
     275                 :        158 :                         REG_RMW(ah, ah->nf_regs[i],
     276                 :            :                                 (((u32) nfval << 1) & 0x1ff), 0x1ff);
     277                 :            :                 }
     278                 :            :         }
     279                 :            : 
     280                 :            :         /*
     281                 :            :          * stop NF cal if ongoing to ensure NF load completes immediately
     282                 :            :          * (or after end rx/tx frame if ongoing)
     283                 :            :          */
     284         [ +  + ]:         60 :         if (bb_agc_ctl & AR_PHY_AGC_CONTROL_NF) {
     285         [ +  + ]:         26 :                 REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
     286         [ -  + ]:         16 :                 REG_RMW_BUFFER_FLUSH(ah);
     287         [ -  + ]:         16 :                 ENABLE_REG_RMW_BUFFER(ah);
     288                 :            :         }
     289                 :            : 
     290                 :            :         /*
     291                 :            :          * Load software filtered NF value into baseband internal minCCApwr
     292                 :            :          * variable.
     293                 :            :          */
     294         [ +  + ]:         80 :         REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
     295                 :            :                     AR_PHY_AGC_CONTROL_ENABLE_NF);
     296         [ +  + ]:         80 :         REG_CLR_BIT(ah, AR_PHY_AGC_CONTROL,
     297                 :            :                     AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
     298         [ +  + ]:         80 :         REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
     299         [ -  + ]:         60 :         REG_RMW_BUFFER_FLUSH(ah);
     300                 :            : 
     301                 :            :         /*
     302                 :            :          * Wait for load to complete, should be fast, a few 10s of us.
     303                 :            :          * The max delay was changed from an original 250us to 22.2 msec.
     304                 :            :          * This would increase timeout to the longest possible frame
     305                 :            :          * (11n max length 22.1 msec)
     306                 :            :          */
     307         [ +  - ]:         83 :         for (j = 0; j < 22200; j++) {
     308   [ +  +  +  + ]:        113 :                 if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
     309                 :            :                               AR_PHY_AGC_CONTROL_NF) == 0)
     310                 :            :                         break;
     311                 :         23 :                 udelay(10);
     312                 :            :         }
     313                 :            : 
     314                 :            :         /*
     315                 :            :          * Restart NF so it can continue.
     316                 :            :          */
     317         [ +  + ]:         60 :         if (bb_agc_ctl & AR_PHY_AGC_CONTROL_NF) {
     318         [ -  + ]:         16 :                 ENABLE_REG_RMW_BUFFER(ah);
     319         [ +  + ]:         16 :                 if (bb_agc_ctl & AR_PHY_AGC_CONTROL_ENABLE_NF)
     320         [ +  + ]:         15 :                         REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
     321                 :            :                                     AR_PHY_AGC_CONTROL_ENABLE_NF);
     322         [ +  + ]:         16 :                 if (bb_agc_ctl & AR_PHY_AGC_CONTROL_NO_UPDATE_NF)
     323         [ +  + ]:         16 :                         REG_SET_BIT(ah, AR_PHY_AGC_CONTROL,
     324                 :            :                                     AR_PHY_AGC_CONTROL_NO_UPDATE_NF);
     325         [ +  + ]:         26 :                 REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF);
     326         [ -  + ]:         16 :                 REG_RMW_BUFFER_FLUSH(ah);
     327                 :            :         }
     328                 :            : 
     329                 :            :         /*
     330                 :            :          * We timed out waiting for the noisefloor to load, probably due to an
     331                 :            :          * in-progress rx. Simply return here and allow the load plenty of time
     332                 :            :          * to complete before the next calibration interval.  We need to avoid
     333                 :            :          * trying to load -50 (which happens below) while the previous load is
     334                 :            :          * still in progress as this can cause rx deafness. Instead by returning
     335                 :            :          * here, the baseband nf cal will just be capped by our present
     336                 :            :          * noisefloor until the next calibration timer.
     337                 :            :          */
     338         [ -  + ]:         60 :         if (j == 22200) {
     339   [ #  #  #  # ]:          0 :                 ath_dbg(common, ANY,
     340                 :            :                         "Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n",
     341                 :            :                         REG_READ(ah, AR_PHY_AGC_CONTROL));
     342                 :          0 :                 return -ETIMEDOUT;
     343                 :            :         }
     344                 :            : 
     345                 :            :         /*
     346                 :            :          * Restore maxCCAPower register parameter again so that we're not capped
     347                 :            :          * by the median we just loaded.  This will be initial (and max) value
     348                 :            :          * of next noise floor calibration the baseband does.
     349                 :            :          */
     350         [ -  + ]:         60 :         ENABLE_REG_RMW_BUFFER(ah);
     351         [ +  + ]:        420 :         for (i = 0; i < NUM_NF_READINGS; i++) {
     352         [ +  + ]:        360 :                 if (chainmask & (1 << i)) {
     353   [ +  +  +  - ]:        316 :                         if ((i >= AR5416_MAX_CHAINS) && !IS_CHAN_HT40(chan))
     354                 :        158 :                                 continue;
     355                 :            : 
     356                 :        158 :                         REG_RMW(ah, ah->nf_regs[i],
     357                 :            :                                         (((u32) (-50) << 1) & 0x1ff), 0x1ff);
     358                 :            :                 }
     359                 :            :         }
     360         [ -  + ]:         60 :         REG_RMW_BUFFER_FLUSH(ah);
     361                 :            : 
     362                 :            :         return 0;
     363                 :            : }
     364                 :            : EXPORT_SYMBOL(ath9k_hw_loadnf);
     365                 :            : 
     366                 :            : 
     367                 :         28 : static void ath9k_hw_nf_sanitize(struct ath_hw *ah, s16 *nf)
     368                 :            : {
     369         [ +  - ]:         28 :         struct ath_common *common = ath9k_hw_common(ah);
     370                 :         28 :         struct ath_nf_limits *limit;
     371                 :         28 :         int i;
     372                 :            : 
     373         [ +  - ]:         28 :         if (IS_CHAN_2GHZ(ah->curchan))
     374                 :         28 :                 limit = &ah->nf_2g;
     375                 :            :         else
     376                 :          0 :                 limit = &ah->nf_5g;
     377                 :            : 
     378         [ +  + ]:        196 :         for (i = 0; i < NUM_NF_READINGS; i++) {
     379         [ +  + ]:        168 :                 if (!nf[i])
     380                 :        101 :                         continue;
     381                 :            : 
     382   [ -  +  -  - ]:         67 :                 ath_dbg(common, CALIBRATE,
     383                 :            :                         "NF calibrated [%s] [chain %d] is %d\n",
     384                 :            :                         (i >= 3 ? "ext" : "ctl"), i % 3, nf[i]);
     385                 :            : 
     386         [ +  + ]:         67 :                 if (nf[i] > limit->max) {
     387         [ -  + ]:         43 :                         ath_dbg(common, CALIBRATE,
     388                 :            :                                 "NF[%d] (%d) > MAX (%d), correcting to MAX\n",
     389                 :            :                                 i, nf[i], limit->max);
     390                 :         43 :                         nf[i] = limit->max;
     391         [ +  + ]:         24 :                 } else if (nf[i] < limit->min) {
     392         [ -  + ]:         16 :                         ath_dbg(common, CALIBRATE,
     393                 :            :                                 "NF[%d] (%d) < MIN (%d), correcting to NOM\n",
     394                 :            :                                 i, nf[i], limit->min);
     395                 :         16 :                         nf[i] = limit->nominal;
     396                 :            :                 }
     397                 :            :         }
     398                 :         28 : }
     399                 :            : 
     400                 :         33 : bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
     401                 :            : {
     402         [ +  + ]:         33 :         struct ath_common *common = ath9k_hw_common(ah);
     403                 :         33 :         int16_t nf, nfThresh;
     404                 :         33 :         int16_t nfarray[NUM_NF_READINGS] = { 0 };
     405                 :         33 :         struct ath9k_nfcal_hist *h;
     406                 :         33 :         struct ieee80211_channel *c = chan->chan;
     407                 :         33 :         struct ath9k_hw_cal_data *caldata = ah->caldata;
     408                 :            : 
     409   [ +  +  +  + ]:         45 :         if (REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF) {
     410         [ -  + ]:          5 :                 ath_dbg(common, CALIBRATE,
     411                 :            :                         "NF did not complete in calibration window\n");
     412                 :          5 :                 return false;
     413                 :            :         }
     414                 :            : 
     415                 :         28 :         ath9k_hw_do_getnf(ah, nfarray);
     416                 :         28 :         ath9k_hw_nf_sanitize(ah, nfarray);
     417                 :         28 :         nf = nfarray[0];
     418         [ +  - ]:         28 :         if (ath9k_hw_get_nf_thresh(ah, c->band, &nfThresh)
     419         [ -  + ]:         28 :             && nf > nfThresh) {
     420         [ #  # ]:          0 :                 ath_dbg(common, CALIBRATE,
     421                 :            :                         "noise floor failed detected; detected %d, threshold %d\n",
     422                 :            :                         nf, nfThresh);
     423                 :            :         }
     424                 :            : 
     425         [ +  + ]:         28 :         if (!caldata) {
     426                 :          5 :                 chan->noisefloor = nf;
     427                 :          5 :                 return false;
     428                 :            :         }
     429                 :            : 
     430                 :         23 :         h = caldata->nfCalHist;
     431                 :         23 :         clear_bit(NFCAL_PENDING, &caldata->cal_flags);
     432                 :         23 :         ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray);
     433                 :         23 :         chan->noisefloor = h[0].privNF;
     434                 :         23 :         ah->noise = ath9k_hw_getchan_noise(ah, chan, chan->noisefloor);
     435                 :         23 :         return true;
     436                 :            : }
     437                 :            : EXPORT_SYMBOL(ath9k_hw_getnf);
     438                 :            : 
     439                 :         11 : void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
     440                 :            :                                   struct ath9k_channel *chan)
     441                 :            : {
     442                 :         11 :         struct ath9k_nfcal_hist *h;
     443                 :         11 :         int i, j, k = 0;
     444                 :            : 
     445                 :         11 :         ah->caldata->channel = chan->channel;
     446                 :         11 :         ah->caldata->channelFlags = chan->channelFlags;
     447                 :         11 :         h = ah->caldata->nfCalHist;
     448         [ +  + ]:         77 :         for (i = 0; i < NUM_NF_READINGS; i++) {
     449                 :         66 :                 h[i].currIndex = 0;
     450         [ +  - ]:         66 :                 h[i].privNF = ath9k_hw_get_default_nf(ah, chan, k);
     451                 :         66 :                 h[i].invalidNFcount = AR_PHY_CCA_FILTERWINDOW_LENGTH;
     452         [ +  + ]:        396 :                 for (j = 0; j < ATH9K_NF_CAL_HIST_MAX; j++)
     453                 :        330 :                         h[i].nfCalBuffer[j] = h[i].privNF;
     454         [ +  + ]:         66 :                 if (++k >= AR5416_MAX_CHAINS)
     455                 :         22 :                         k = 0;
     456                 :            :         }
     457                 :         11 : }
     458                 :            : 
     459                 :            : 
     460                 :          0 : void ath9k_hw_bstuck_nfcal(struct ath_hw *ah)
     461                 :            : {
     462                 :          0 :         struct ath9k_hw_cal_data *caldata = ah->caldata;
     463                 :            : 
     464         [ #  # ]:          0 :         if (unlikely(!caldata))
     465                 :            :                 return;
     466                 :            : 
     467                 :            :         /*
     468                 :            :          * If beacons are stuck, the most likely cause is interference.
     469                 :            :          * Triggering a noise floor calibration at this point helps the
     470                 :            :          * hardware adapt to a noisy environment much faster.
     471                 :            :          * To ensure that we recover from stuck beacons quickly, let
     472                 :            :          * the baseband update the internal NF value itself, similar to
     473                 :            :          * what is being done after a full reset.
     474                 :            :          */
     475         [ #  # ]:          0 :         if (!test_bit(NFCAL_PENDING, &caldata->cal_flags))
     476                 :          0 :                 ath9k_hw_start_nfcal(ah, true);
     477   [ #  #  #  # ]:          0 :         else if (!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF))
     478                 :          0 :                 ath9k_hw_getnf(ah, ah->curchan);
     479                 :            : 
     480                 :          0 :         set_bit(NFCAL_INTF, &caldata->cal_flags);
     481                 :            : }
     482                 :            : EXPORT_SYMBOL(ath9k_hw_bstuck_nfcal);
     483                 :            : 

Generated by: LCOV version 1.14