Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  * Copyright (c) 2012 Qualcomm Atheros, Inc.
0003  *
0004  * Permission to use, copy, modify, and/or distribute this software for any
0005  * purpose with or without fee is hereby granted, provided that the above
0006  * copyright notice and this permission notice appear in all copies.
0007  *
0008  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
0009  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
0010  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
0011  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
0012  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
0013  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
0014  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0015  */
0016 
0017 #include "ath9k.h"
0018 
0019 /*
0020  * TX polling - checks if the TX engine is stuck somewhere
0021  * and issues a chip reset if so.
0022  */
0023 static bool ath_tx_complete_check(struct ath_softc *sc)
0024 {
0025     struct ath_txq *txq;
0026     int i;
0027 
0028     if (sc->tx99_state)
0029         return true;
0030 
0031     for (i = 0; i < IEEE80211_NUM_ACS; i++) {
0032         txq = sc->tx.txq_map[i];
0033 
0034         ath_txq_lock(sc, txq);
0035         if (txq->axq_depth) {
0036             if (txq->axq_tx_inprogress) {
0037                 ath_txq_unlock(sc, txq);
0038                 goto reset;
0039             }
0040 
0041             txq->axq_tx_inprogress = true;
0042         }
0043         ath_txq_unlock(sc, txq);
0044     }
0045 
0046     return true;
0047 
0048 reset:
0049     ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
0050         "tx hung, resetting the chip\n");
0051     ath9k_queue_reset(sc, RESET_TYPE_TX_HANG);
0052     return false;
0053 
0054 }
0055 
0056 void ath_hw_check_work(struct work_struct *work)
0057 {
0058     struct ath_softc *sc = container_of(work, struct ath_softc,
0059                         hw_check_work.work);
0060 
0061     if (!ath_hw_check(sc) ||
0062         !ath_tx_complete_check(sc))
0063         return;
0064 
0065     ieee80211_queue_delayed_work(sc->hw, &sc->hw_check_work,
0066                      msecs_to_jiffies(ATH_HW_CHECK_POLL_INT));
0067 }
0068 
0069 /*
0070  * Checks if the BB/MAC is hung.
0071  */
0072 bool ath_hw_check(struct ath_softc *sc)
0073 {
0074     struct ath_common *common = ath9k_hw_common(sc->sc_ah);
0075     enum ath_reset_type type;
0076     bool is_alive;
0077 
0078     ath9k_ps_wakeup(sc);
0079 
0080     is_alive = ath9k_hw_check_alive(sc->sc_ah);
0081 
0082     if (!is_alive) {
0083         ath_dbg(common, RESET,
0084             "HW hang detected, schedule chip reset\n");
0085         type = RESET_TYPE_MAC_HANG;
0086         ath9k_queue_reset(sc, type);
0087     }
0088 
0089     ath9k_ps_restore(sc);
0090 
0091     return is_alive;
0092 }
0093 
0094 /*
0095  * PLL-WAR for AR9485/AR9340
0096  */
0097 static bool ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
0098 {
0099     static int count;
0100     struct ath_common *common = ath9k_hw_common(sc->sc_ah);
0101 
0102     if (pll_sqsum >= 0x40000) {
0103         count++;
0104         if (count == 3) {
0105             ath_dbg(common, RESET, "PLL WAR, resetting the chip\n");
0106             ath9k_queue_reset(sc, RESET_TYPE_PLL_HANG);
0107             count = 0;
0108             return true;
0109         }
0110     } else {
0111         count = 0;
0112     }
0113 
0114     return false;
0115 }
0116 
0117 void ath_hw_pll_work(struct work_struct *work)
0118 {
0119     u32 pll_sqsum;
0120     struct ath_softc *sc = container_of(work, struct ath_softc,
0121                         hw_pll_work.work);
0122     struct ath_common *common = ath9k_hw_common(sc->sc_ah);
0123     /*
0124      * ensure that the PLL WAR is executed only
0125      * after the STA is associated (or) if the
0126      * beaconing had started in interfaces that
0127      * uses beacons.
0128      */
0129     if (!test_bit(ATH_OP_BEACONS, &common->op_flags))
0130         return;
0131 
0132     if (sc->tx99_state)
0133         return;
0134 
0135     ath9k_ps_wakeup(sc);
0136     pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
0137     ath9k_ps_restore(sc);
0138     if (ath_hw_pll_rx_hang_check(sc, pll_sqsum))
0139         return;
0140 
0141     ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work,
0142                      msecs_to_jiffies(ATH_PLL_WORK_INTERVAL));
0143 }
0144 
0145 /*
0146  * PA Pre-distortion.
0147  */
0148 static void ath_paprd_activate(struct ath_softc *sc)
0149 {
0150     struct ath_hw *ah = sc->sc_ah;
0151     struct ath_common *common = ath9k_hw_common(ah);
0152     struct ath9k_hw_cal_data *caldata = ah->caldata;
0153     int chain;
0154 
0155     if (!caldata || !test_bit(PAPRD_DONE, &caldata->cal_flags)) {
0156         ath_dbg(common, CALIBRATE, "Failed to activate PAPRD\n");
0157         return;
0158     }
0159 
0160     ar9003_paprd_enable(ah, false);
0161     for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
0162         if (!(ah->txchainmask & BIT(chain)))
0163             continue;
0164 
0165         ar9003_paprd_populate_single_table(ah, caldata, chain);
0166     }
0167 
0168     ath_dbg(common, CALIBRATE, "Activating PAPRD\n");
0169     ar9003_paprd_enable(ah, true);
0170 }
0171 
0172 static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int chain)
0173 {
0174     struct ieee80211_hw *hw = sc->hw;
0175     struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
0176     struct ath_hw *ah = sc->sc_ah;
0177     struct ath_common *common = ath9k_hw_common(ah);
0178     struct ath_tx_control txctl;
0179     unsigned long time_left;
0180 
0181     memset(&txctl, 0, sizeof(txctl));
0182     txctl.txq = sc->tx.txq_map[IEEE80211_AC_BE];
0183 
0184     memset(tx_info, 0, sizeof(*tx_info));
0185     tx_info->band = sc->cur_chandef.chan->band;
0186     tx_info->flags |= IEEE80211_TX_CTL_NO_ACK;
0187     tx_info->control.rates[0].idx = 0;
0188     tx_info->control.rates[0].count = 1;
0189     tx_info->control.rates[0].flags = IEEE80211_TX_RC_MCS;
0190     tx_info->control.rates[1].idx = -1;
0191 
0192     init_completion(&sc->paprd_complete);
0193     txctl.paprd = BIT(chain);
0194 
0195     if (ath_tx_start(hw, skb, &txctl) != 0) {
0196         ath_dbg(common, CALIBRATE, "PAPRD TX failed\n");
0197         dev_kfree_skb_any(skb);
0198         return false;
0199     }
0200 
0201     time_left = wait_for_completion_timeout(&sc->paprd_complete,
0202             msecs_to_jiffies(ATH_PAPRD_TIMEOUT));
0203 
0204     if (!time_left)
0205         ath_dbg(common, CALIBRATE,
0206             "Timeout waiting for paprd training on TX chain %d\n",
0207             chain);
0208 
0209     return !!time_left;
0210 }
0211 
0212 void ath_paprd_calibrate(struct work_struct *work)
0213 {
0214     struct ath_softc *sc = container_of(work, struct ath_softc, paprd_work);
0215     struct ieee80211_hw *hw = sc->hw;
0216     struct ath_hw *ah = sc->sc_ah;
0217     struct ieee80211_hdr *hdr;
0218     struct sk_buff *skb = NULL;
0219     struct ath9k_hw_cal_data *caldata = ah->caldata;
0220     struct ath_common *common = ath9k_hw_common(ah);
0221     int ftype;
0222     int chain_ok = 0;
0223     int chain;
0224     int len = 1800;
0225     int ret;
0226 
0227     if (!caldata ||
0228         !test_bit(PAPRD_PACKET_SENT, &caldata->cal_flags) ||
0229         test_bit(PAPRD_DONE, &caldata->cal_flags)) {
0230         ath_dbg(common, CALIBRATE, "Skipping PAPRD calibration\n");
0231         return;
0232     }
0233 
0234     ath9k_ps_wakeup(sc);
0235 
0236     if (ar9003_paprd_init_table(ah) < 0)
0237         goto fail_paprd;
0238 
0239     skb = alloc_skb(len, GFP_KERNEL);
0240     if (!skb)
0241         goto fail_paprd;
0242 
0243     skb_put(skb, len);
0244     memset(skb->data, 0, len);
0245     hdr = (struct ieee80211_hdr *)skb->data;
0246     ftype = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC;
0247     hdr->frame_control = cpu_to_le16(ftype);
0248     hdr->duration_id = cpu_to_le16(10);
0249     memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN);
0250     memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN);
0251     memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
0252 
0253     for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
0254         if (!(ah->txchainmask & BIT(chain)))
0255             continue;
0256 
0257         chain_ok = 0;
0258         ar9003_paprd_setup_gain_table(ah, chain);
0259 
0260         ath_dbg(common, CALIBRATE,
0261             "Sending PAPRD training frame on chain %d\n", chain);
0262         if (!ath_paprd_send_frame(sc, skb, chain))
0263             goto fail_paprd;
0264 
0265         if (!ar9003_paprd_is_done(ah)) {
0266             ath_dbg(common, CALIBRATE,
0267                 "PAPRD not yet done on chain %d\n", chain);
0268             break;
0269         }
0270 
0271         ret = ar9003_paprd_create_curve(ah, caldata, chain);
0272         if (ret == -EINPROGRESS) {
0273             ath_dbg(common, CALIBRATE,
0274                 "PAPRD curve on chain %d needs to be re-trained\n",
0275                 chain);
0276             break;
0277         } else if (ret) {
0278             ath_dbg(common, CALIBRATE,
0279                 "PAPRD create curve failed on chain %d\n",
0280                 chain);
0281             break;
0282         }
0283 
0284         chain_ok = 1;
0285     }
0286     kfree_skb(skb);
0287 
0288     if (chain_ok) {
0289         set_bit(PAPRD_DONE, &caldata->cal_flags);
0290         ath_paprd_activate(sc);
0291     }
0292 
0293 fail_paprd:
0294     ath9k_ps_restore(sc);
0295 }
0296 
0297 /*
0298  *  ANI performs periodic noise floor calibration
0299  *  that is used to adjust and optimize the chip performance.  This
0300  *  takes environmental changes (location, temperature) into account.
0301  *  When the task is complete, it reschedules itself depending on the
0302  *  appropriate interval that was calculated.
0303  */
0304 void ath_ani_calibrate(struct timer_list *t)
0305 {
0306     struct ath_common *common = from_timer(common, t, ani.timer);
0307     struct ath_softc *sc = (struct ath_softc *)common->priv;
0308     struct ath_hw *ah = sc->sc_ah;
0309     bool longcal = false;
0310     bool shortcal = false;
0311     bool aniflag = false;
0312     unsigned int timestamp = jiffies_to_msecs(jiffies);
0313     u32 cal_interval, short_cal_interval, long_cal_interval;
0314     unsigned long flags;
0315 
0316     if (ah->caldata && test_bit(NFCAL_INTF, &ah->caldata->cal_flags))
0317         long_cal_interval = ATH_LONG_CALINTERVAL_INT;
0318     else
0319         long_cal_interval = ATH_LONG_CALINTERVAL;
0320 
0321     short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ?
0322         ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL;
0323 
0324     /* Only calibrate if awake */
0325     if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) {
0326         if (++ah->ani_skip_count >= ATH_ANI_MAX_SKIP_COUNT) {
0327             spin_lock_irqsave(&sc->sc_pm_lock, flags);
0328             sc->ps_flags |= PS_WAIT_FOR_ANI;
0329             spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
0330         }
0331         goto set_timer;
0332     }
0333     ah->ani_skip_count = 0;
0334     spin_lock_irqsave(&sc->sc_pm_lock, flags);
0335     sc->ps_flags &= ~PS_WAIT_FOR_ANI;
0336     spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
0337 
0338     ath9k_ps_wakeup(sc);
0339 
0340     /* Long calibration runs independently of short calibration. */
0341     if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) {
0342         longcal = true;
0343         common->ani.longcal_timer = timestamp;
0344     }
0345 
0346     /* Short calibration applies only while caldone is false */
0347     if (!common->ani.caldone) {
0348         if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) {
0349             shortcal = true;
0350             common->ani.shortcal_timer = timestamp;
0351             common->ani.resetcal_timer = timestamp;
0352         }
0353     } else {
0354         if ((timestamp - common->ani.resetcal_timer) >=
0355             ATH_RESTART_CALINTERVAL) {
0356             common->ani.caldone = ath9k_hw_reset_calvalid(ah);
0357             if (common->ani.caldone)
0358                 common->ani.resetcal_timer = timestamp;
0359         }
0360     }
0361 
0362     /* Verify whether we must check ANI */
0363     if ((timestamp - common->ani.checkani_timer) >= ah->config.ani_poll_interval) {
0364         aniflag = true;
0365         common->ani.checkani_timer = timestamp;
0366     }
0367 
0368     /* Call ANI routine if necessary */
0369     if (aniflag) {
0370         spin_lock_irqsave(&common->cc_lock, flags);
0371         ath9k_hw_ani_monitor(ah, ah->curchan);
0372         ath_update_survey_stats(sc);
0373         spin_unlock_irqrestore(&common->cc_lock, flags);
0374     }
0375 
0376     /* Perform calibration if necessary */
0377     if (longcal || shortcal) {
0378         int ret = ath9k_hw_calibrate(ah, ah->curchan, ah->rxchainmask,
0379                          longcal);
0380         if (ret < 0) {
0381             common->ani.caldone = 0;
0382             ath9k_queue_reset(sc, RESET_TYPE_CALIBRATION);
0383             return;
0384         }
0385 
0386         common->ani.caldone = ret;
0387     }
0388 
0389     ath_dbg(common, ANI,
0390         "Calibration @%lu finished: %s %s %s, caldone: %s\n",
0391         jiffies,
0392         longcal ? "long" : "", shortcal ? "short" : "",
0393         aniflag ? "ani" : "", common->ani.caldone ? "true" : "false");
0394 
0395     ath9k_ps_restore(sc);
0396 
0397 set_timer:
0398     /*
0399     * Set timer interval based on previous results.
0400     * The interval must be the shortest necessary to satisfy ANI,
0401     * short calibration and long calibration.
0402     */
0403     cal_interval = ATH_LONG_CALINTERVAL;
0404     cal_interval = min(cal_interval, (u32)ah->config.ani_poll_interval);
0405     if (!common->ani.caldone)
0406         cal_interval = min(cal_interval, (u32)short_cal_interval);
0407 
0408     mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval));
0409 
0410     if (ar9003_is_paprd_enabled(ah) && ah->caldata) {
0411         if (!test_bit(PAPRD_DONE, &ah->caldata->cal_flags)) {
0412             ieee80211_queue_work(sc->hw, &sc->paprd_work);
0413         } else if (!ah->paprd_table_write_done) {
0414             ath9k_ps_wakeup(sc);
0415             ath_paprd_activate(sc);
0416             ath9k_ps_restore(sc);
0417         }
0418     }
0419 }
0420 
0421 void ath_start_ani(struct ath_softc *sc)
0422 {
0423     struct ath_hw *ah = sc->sc_ah;
0424     struct ath_common *common = ath9k_hw_common(ah);
0425     unsigned long timestamp = jiffies_to_msecs(jiffies);
0426 
0427     if (common->disable_ani ||
0428         !test_bit(ATH_OP_ANI_RUN, &common->op_flags) ||
0429         sc->cur_chan->offchannel)
0430         return;
0431 
0432     common->ani.longcal_timer = timestamp;
0433     common->ani.shortcal_timer = timestamp;
0434     common->ani.checkani_timer = timestamp;
0435 
0436     ath_dbg(common, ANI, "Starting ANI\n");
0437     mod_timer(&common->ani.timer,
0438           jiffies + msecs_to_jiffies((u32)ah->config.ani_poll_interval));
0439 }
0440 
0441 void ath_stop_ani(struct ath_softc *sc)
0442 {
0443     struct ath_common *common = ath9k_hw_common(sc->sc_ah);
0444 
0445     ath_dbg(common, ANI, "Stopping ANI\n");
0446     del_timer_sync(&common->ani.timer);
0447 }
0448 
0449 void ath_check_ani(struct ath_softc *sc)
0450 {
0451     struct ath_hw *ah = sc->sc_ah;
0452     struct ath_common *common = ath9k_hw_common(sc->sc_ah);
0453     struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
0454 
0455     /*
0456      * Check for the various conditions in which ANI has to
0457      * be stopped.
0458      */
0459     if (ah->opmode == NL80211_IFTYPE_ADHOC) {
0460         if (!cur_conf->enable_beacon)
0461             goto stop_ani;
0462     } else if (ah->opmode == NL80211_IFTYPE_AP) {
0463         if (!cur_conf->enable_beacon) {
0464             /*
0465              * Disable ANI only when there are no
0466              * associated stations.
0467              */
0468             if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags))
0469                 goto stop_ani;
0470         }
0471     } else if (ah->opmode == NL80211_IFTYPE_STATION) {
0472         if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags))
0473             goto stop_ani;
0474     }
0475 
0476     if (!test_bit(ATH_OP_ANI_RUN, &common->op_flags)) {
0477         set_bit(ATH_OP_ANI_RUN, &common->op_flags);
0478         ath_start_ani(sc);
0479     }
0480 
0481     return;
0482 
0483 stop_ani:
0484     clear_bit(ATH_OP_ANI_RUN, &common->op_flags);
0485     ath_stop_ani(sc);
0486 }
0487 
0488 void ath_update_survey_nf(struct ath_softc *sc, int channel)
0489 {
0490     struct ath_hw *ah = sc->sc_ah;
0491     struct ath9k_channel *chan = &ah->channels[channel];
0492     struct survey_info *survey = &sc->survey[channel];
0493 
0494     if (chan->noisefloor) {
0495         survey->filled |= SURVEY_INFO_NOISE_DBM;
0496         survey->noise = ath9k_hw_getchan_noise(ah, chan,
0497                                chan->noisefloor);
0498     }
0499 }
0500 
0501 /*
0502  * Updates the survey statistics and returns the busy time since last
0503  * update in %, if the measurement duration was long enough for the
0504  * result to be useful, -1 otherwise.
0505  */
0506 int ath_update_survey_stats(struct ath_softc *sc)
0507 {
0508     struct ath_hw *ah = sc->sc_ah;
0509     struct ath_common *common = ath9k_hw_common(ah);
0510     int pos = ah->curchan - &ah->channels[0];
0511     struct survey_info *survey = &sc->survey[pos];
0512     struct ath_cycle_counters *cc = &common->cc_survey;
0513     unsigned int div = common->clockrate * 1000;
0514     int ret = 0;
0515 
0516     if (!ah->curchan)
0517         return -1;
0518 
0519     if (ah->power_mode == ATH9K_PM_AWAKE)
0520         ath_hw_cycle_counters_update(common);
0521 
0522     if (cc->cycles > 0) {
0523         survey->filled |= SURVEY_INFO_TIME |
0524             SURVEY_INFO_TIME_BUSY |
0525             SURVEY_INFO_TIME_RX |
0526             SURVEY_INFO_TIME_TX;
0527         survey->time += cc->cycles / div;
0528         survey->time_busy += cc->rx_busy / div;
0529         survey->time_rx += cc->rx_frame / div;
0530         survey->time_tx += cc->tx_frame / div;
0531     }
0532 
0533     if (cc->cycles < div)
0534         return -1;
0535 
0536     if (cc->cycles > 0)
0537         ret = cc->rx_busy * 100 / cc->cycles;
0538 
0539     memset(cc, 0, sizeof(*cc));
0540 
0541     ath_update_survey_nf(sc, pos);
0542 
0543     return ret;
0544 }