linux/drivers/net/wireless/ath/ath9k/link.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2012 Qualcomm Atheros, 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 "ath9k.h"
  18
  19/*
  20 * TX polling - checks if the TX engine is stuck somewhere
  21 * and issues a chip reset if so.
  22 */
  23void ath_tx_complete_poll_work(struct work_struct *work)
  24{
  25        struct ath_softc *sc = container_of(work, struct ath_softc,
  26                                            tx_complete_work.work);
  27        struct ath_txq *txq;
  28        int i;
  29        bool needreset = false;
  30
  31
  32        if (sc->tx99_state) {
  33                ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
  34                        "skip tx hung detection on tx99\n");
  35                return;
  36        }
  37
  38        for (i = 0; i < IEEE80211_NUM_ACS; i++) {
  39                txq = sc->tx.txq_map[i];
  40
  41                ath_txq_lock(sc, txq);
  42                if (txq->axq_depth) {
  43                        if (txq->axq_tx_inprogress) {
  44                                needreset = true;
  45                                ath_txq_unlock(sc, txq);
  46                                break;
  47                        } else {
  48                                txq->axq_tx_inprogress = true;
  49                        }
  50                }
  51                ath_txq_unlock(sc, txq);
  52        }
  53
  54        if (needreset) {
  55                ath_dbg(ath9k_hw_common(sc->sc_ah), RESET,
  56                        "tx hung, resetting the chip\n");
  57                ath9k_queue_reset(sc, RESET_TYPE_TX_HANG);
  58                return;
  59        }
  60
  61        ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work,
  62                                     msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT));
  63}
  64
  65/*
  66 * Checks if the BB/MAC is hung.
  67 */
  68bool ath_hw_check(struct ath_softc *sc)
  69{
  70        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
  71        enum ath_reset_type type;
  72        bool is_alive;
  73
  74        ath9k_ps_wakeup(sc);
  75
  76        is_alive = ath9k_hw_check_alive(sc->sc_ah);
  77
  78        if (!is_alive) {
  79                ath_dbg(common, RESET,
  80                        "HW hang detected, schedule chip reset\n");
  81                type = RESET_TYPE_MAC_HANG;
  82                ath9k_queue_reset(sc, type);
  83        }
  84
  85        ath9k_ps_restore(sc);
  86
  87        return is_alive;
  88}
  89
  90/*
  91 * PLL-WAR for AR9485/AR9340
  92 */
  93static bool ath_hw_pll_rx_hang_check(struct ath_softc *sc, u32 pll_sqsum)
  94{
  95        static int count;
  96        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
  97
  98        if (pll_sqsum >= 0x40000) {
  99                count++;
 100                if (count == 3) {
 101                        ath_dbg(common, RESET, "PLL WAR, resetting the chip\n");
 102                        ath9k_queue_reset(sc, RESET_TYPE_PLL_HANG);
 103                        count = 0;
 104                        return true;
 105                }
 106        } else {
 107                count = 0;
 108        }
 109
 110        return false;
 111}
 112
 113void ath_hw_pll_work(struct work_struct *work)
 114{
 115        u32 pll_sqsum;
 116        struct ath_softc *sc = container_of(work, struct ath_softc,
 117                                            hw_pll_work.work);
 118        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 119        /*
 120         * ensure that the PLL WAR is executed only
 121         * after the STA is associated (or) if the
 122         * beaconing had started in interfaces that
 123         * uses beacons.
 124         */
 125        if (!test_bit(ATH_OP_BEACONS, &common->op_flags))
 126                return;
 127
 128        if (sc->tx99_state)
 129                return;
 130
 131        ath9k_ps_wakeup(sc);
 132        pll_sqsum = ar9003_get_pll_sqsum_dvc(sc->sc_ah);
 133        ath9k_ps_restore(sc);
 134        if (ath_hw_pll_rx_hang_check(sc, pll_sqsum))
 135                return;
 136
 137        ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work,
 138                                     msecs_to_jiffies(ATH_PLL_WORK_INTERVAL));
 139}
 140
 141/*
 142 * PA Pre-distortion.
 143 */
 144static void ath_paprd_activate(struct ath_softc *sc)
 145{
 146        struct ath_hw *ah = sc->sc_ah;
 147        struct ath_common *common = ath9k_hw_common(ah);
 148        struct ath9k_hw_cal_data *caldata = ah->caldata;
 149        int chain;
 150
 151        if (!caldata || !test_bit(PAPRD_DONE, &caldata->cal_flags)) {
 152                ath_dbg(common, CALIBRATE, "Failed to activate PAPRD\n");
 153                return;
 154        }
 155
 156        ar9003_paprd_enable(ah, false);
 157        for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
 158                if (!(ah->txchainmask & BIT(chain)))
 159                        continue;
 160
 161                ar9003_paprd_populate_single_table(ah, caldata, chain);
 162        }
 163
 164        ath_dbg(common, CALIBRATE, "Activating PAPRD\n");
 165        ar9003_paprd_enable(ah, true);
 166}
 167
 168static bool ath_paprd_send_frame(struct ath_softc *sc, struct sk_buff *skb, int chain)
 169{
 170        struct ieee80211_hw *hw = sc->hw;
 171        struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
 172        struct ath_hw *ah = sc->sc_ah;
 173        struct ath_common *common = ath9k_hw_common(ah);
 174        struct ath_tx_control txctl;
 175        unsigned long time_left;
 176
 177        memset(&txctl, 0, sizeof(txctl));
 178        txctl.txq = sc->tx.txq_map[IEEE80211_AC_BE];
 179
 180        memset(tx_info, 0, sizeof(*tx_info));
 181        tx_info->band = sc->cur_chandef.chan->band;
 182        tx_info->flags |= IEEE80211_TX_CTL_NO_ACK;
 183        tx_info->control.rates[0].idx = 0;
 184        tx_info->control.rates[0].count = 1;
 185        tx_info->control.rates[0].flags = IEEE80211_TX_RC_MCS;
 186        tx_info->control.rates[1].idx = -1;
 187
 188        init_completion(&sc->paprd_complete);
 189        txctl.paprd = BIT(chain);
 190
 191        if (ath_tx_start(hw, skb, &txctl) != 0) {
 192                ath_dbg(common, CALIBRATE, "PAPRD TX failed\n");
 193                dev_kfree_skb_any(skb);
 194                return false;
 195        }
 196
 197        time_left = wait_for_completion_timeout(&sc->paprd_complete,
 198                        msecs_to_jiffies(ATH_PAPRD_TIMEOUT));
 199
 200        if (!time_left)
 201                ath_dbg(common, CALIBRATE,
 202                        "Timeout waiting for paprd training on TX chain %d\n",
 203                        chain);
 204
 205        return !!time_left;
 206}
 207
 208void ath_paprd_calibrate(struct work_struct *work)
 209{
 210        struct ath_softc *sc = container_of(work, struct ath_softc, paprd_work);
 211        struct ieee80211_hw *hw = sc->hw;
 212        struct ath_hw *ah = sc->sc_ah;
 213        struct ieee80211_hdr *hdr;
 214        struct sk_buff *skb = NULL;
 215        struct ath9k_hw_cal_data *caldata = ah->caldata;
 216        struct ath_common *common = ath9k_hw_common(ah);
 217        int ftype;
 218        int chain_ok = 0;
 219        int chain;
 220        int len = 1800;
 221        int ret;
 222
 223        if (!caldata ||
 224            !test_bit(PAPRD_PACKET_SENT, &caldata->cal_flags) ||
 225            test_bit(PAPRD_DONE, &caldata->cal_flags)) {
 226                ath_dbg(common, CALIBRATE, "Skipping PAPRD calibration\n");
 227                return;
 228        }
 229
 230        ath9k_ps_wakeup(sc);
 231
 232        if (ar9003_paprd_init_table(ah) < 0)
 233                goto fail_paprd;
 234
 235        skb = alloc_skb(len, GFP_KERNEL);
 236        if (!skb)
 237                goto fail_paprd;
 238
 239        skb_put(skb, len);
 240        memset(skb->data, 0, len);
 241        hdr = (struct ieee80211_hdr *)skb->data;
 242        ftype = IEEE80211_FTYPE_DATA | IEEE80211_STYPE_NULLFUNC;
 243        hdr->frame_control = cpu_to_le16(ftype);
 244        hdr->duration_id = cpu_to_le16(10);
 245        memcpy(hdr->addr1, hw->wiphy->perm_addr, ETH_ALEN);
 246        memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN);
 247        memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN);
 248
 249        for (chain = 0; chain < AR9300_MAX_CHAINS; chain++) {
 250                if (!(ah->txchainmask & BIT(chain)))
 251                        continue;
 252
 253                chain_ok = 0;
 254                ar9003_paprd_setup_gain_table(ah, chain);
 255
 256                ath_dbg(common, CALIBRATE,
 257                        "Sending PAPRD training frame on chain %d\n", chain);
 258                if (!ath_paprd_send_frame(sc, skb, chain))
 259                        goto fail_paprd;
 260
 261                if (!ar9003_paprd_is_done(ah)) {
 262                        ath_dbg(common, CALIBRATE,
 263                                "PAPRD not yet done on chain %d\n", chain);
 264                        break;
 265                }
 266
 267                ret = ar9003_paprd_create_curve(ah, caldata, chain);
 268                if (ret == -EINPROGRESS) {
 269                        ath_dbg(common, CALIBRATE,
 270                                "PAPRD curve on chain %d needs to be re-trained\n",
 271                                chain);
 272                        break;
 273                } else if (ret) {
 274                        ath_dbg(common, CALIBRATE,
 275                                "PAPRD create curve failed on chain %d\n",
 276                                chain);
 277                        break;
 278                }
 279
 280                chain_ok = 1;
 281        }
 282        kfree_skb(skb);
 283
 284        if (chain_ok) {
 285                set_bit(PAPRD_DONE, &caldata->cal_flags);
 286                ath_paprd_activate(sc);
 287        }
 288
 289fail_paprd:
 290        ath9k_ps_restore(sc);
 291}
 292
 293/*
 294 *  ANI performs periodic noise floor calibration
 295 *  that is used to adjust and optimize the chip performance.  This
 296 *  takes environmental changes (location, temperature) into account.
 297 *  When the task is complete, it reschedules itself depending on the
 298 *  appropriate interval that was calculated.
 299 */
 300void ath_ani_calibrate(unsigned long data)
 301{
 302        struct ath_softc *sc = (struct ath_softc *)data;
 303        struct ath_hw *ah = sc->sc_ah;
 304        struct ath_common *common = ath9k_hw_common(ah);
 305        bool longcal = false;
 306        bool shortcal = false;
 307        bool aniflag = false;
 308        unsigned int timestamp = jiffies_to_msecs(jiffies);
 309        u32 cal_interval, short_cal_interval, long_cal_interval;
 310        unsigned long flags;
 311
 312        if (ah->caldata && test_bit(NFCAL_INTF, &ah->caldata->cal_flags))
 313                long_cal_interval = ATH_LONG_CALINTERVAL_INT;
 314        else
 315                long_cal_interval = ATH_LONG_CALINTERVAL;
 316
 317        short_cal_interval = (ah->opmode == NL80211_IFTYPE_AP) ?
 318                ATH_AP_SHORT_CALINTERVAL : ATH_STA_SHORT_CALINTERVAL;
 319
 320        /* Only calibrate if awake */
 321        if (sc->sc_ah->power_mode != ATH9K_PM_AWAKE) {
 322                if (++ah->ani_skip_count >= ATH_ANI_MAX_SKIP_COUNT) {
 323                        spin_lock_irqsave(&sc->sc_pm_lock, flags);
 324                        sc->ps_flags |= PS_WAIT_FOR_ANI;
 325                        spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
 326                }
 327                goto set_timer;
 328        }
 329        ah->ani_skip_count = 0;
 330        spin_lock_irqsave(&sc->sc_pm_lock, flags);
 331        sc->ps_flags &= ~PS_WAIT_FOR_ANI;
 332        spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
 333
 334        ath9k_ps_wakeup(sc);
 335
 336        /* Long calibration runs independently of short calibration. */
 337        if ((timestamp - common->ani.longcal_timer) >= long_cal_interval) {
 338                longcal = true;
 339                common->ani.longcal_timer = timestamp;
 340        }
 341
 342        /* Short calibration applies only while caldone is false */
 343        if (!common->ani.caldone) {
 344                if ((timestamp - common->ani.shortcal_timer) >= short_cal_interval) {
 345                        shortcal = true;
 346                        common->ani.shortcal_timer = timestamp;
 347                        common->ani.resetcal_timer = timestamp;
 348                }
 349        } else {
 350                if ((timestamp - common->ani.resetcal_timer) >=
 351                    ATH_RESTART_CALINTERVAL) {
 352                        common->ani.caldone = ath9k_hw_reset_calvalid(ah);
 353                        if (common->ani.caldone)
 354                                common->ani.resetcal_timer = timestamp;
 355                }
 356        }
 357
 358        /* Verify whether we must check ANI */
 359        if ((timestamp - common->ani.checkani_timer) >= ah->config.ani_poll_interval) {
 360                aniflag = true;
 361                common->ani.checkani_timer = timestamp;
 362        }
 363
 364        /* Call ANI routine if necessary */
 365        if (aniflag) {
 366                spin_lock(&common->cc_lock);
 367                ath9k_hw_ani_monitor(ah, ah->curchan);
 368                ath_update_survey_stats(sc);
 369                spin_unlock(&common->cc_lock);
 370        }
 371
 372        /* Perform calibration if necessary */
 373        if (longcal || shortcal) {
 374                int ret = ath9k_hw_calibrate(ah, ah->curchan, ah->rxchainmask,
 375                                             longcal);
 376                if (ret < 0) {
 377                        common->ani.caldone = 0;
 378                        ath9k_queue_reset(sc, RESET_TYPE_CALIBRATION);
 379                        return;
 380                }
 381
 382                common->ani.caldone = ret;
 383        }
 384
 385        ath_dbg(common, ANI,
 386                "Calibration @%lu finished: %s %s %s, caldone: %s\n",
 387                jiffies,
 388                longcal ? "long" : "", shortcal ? "short" : "",
 389                aniflag ? "ani" : "", common->ani.caldone ? "true" : "false");
 390
 391        ath9k_ps_restore(sc);
 392
 393set_timer:
 394        /*
 395        * Set timer interval based on previous results.
 396        * The interval must be the shortest necessary to satisfy ANI,
 397        * short calibration and long calibration.
 398        */
 399        cal_interval = ATH_LONG_CALINTERVAL;
 400        cal_interval = min(cal_interval, (u32)ah->config.ani_poll_interval);
 401        if (!common->ani.caldone)
 402                cal_interval = min(cal_interval, (u32)short_cal_interval);
 403
 404        mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval));
 405
 406        if (ar9003_is_paprd_enabled(ah) && ah->caldata) {
 407                if (!test_bit(PAPRD_DONE, &ah->caldata->cal_flags)) {
 408                        ieee80211_queue_work(sc->hw, &sc->paprd_work);
 409                } else if (!ah->paprd_table_write_done) {
 410                        ath9k_ps_wakeup(sc);
 411                        ath_paprd_activate(sc);
 412                        ath9k_ps_restore(sc);
 413                }
 414        }
 415}
 416
 417void ath_start_ani(struct ath_softc *sc)
 418{
 419        struct ath_hw *ah = sc->sc_ah;
 420        struct ath_common *common = ath9k_hw_common(ah);
 421        unsigned long timestamp = jiffies_to_msecs(jiffies);
 422
 423        if (common->disable_ani ||
 424            !test_bit(ATH_OP_ANI_RUN, &common->op_flags) ||
 425            sc->cur_chan->offchannel)
 426                return;
 427
 428        common->ani.longcal_timer = timestamp;
 429        common->ani.shortcal_timer = timestamp;
 430        common->ani.checkani_timer = timestamp;
 431
 432        ath_dbg(common, ANI, "Starting ANI\n");
 433        mod_timer(&common->ani.timer,
 434                  jiffies + msecs_to_jiffies((u32)ah->config.ani_poll_interval));
 435}
 436
 437void ath_stop_ani(struct ath_softc *sc)
 438{
 439        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 440
 441        ath_dbg(common, ANI, "Stopping ANI\n");
 442        del_timer_sync(&common->ani.timer);
 443}
 444
 445void ath_check_ani(struct ath_softc *sc)
 446{
 447        struct ath_hw *ah = sc->sc_ah;
 448        struct ath_common *common = ath9k_hw_common(sc->sc_ah);
 449        struct ath_beacon_config *cur_conf = &sc->cur_chan->beacon;
 450
 451        /*
 452         * Check for the various conditions in which ANI has to
 453         * be stopped.
 454         */
 455        if (ah->opmode == NL80211_IFTYPE_ADHOC) {
 456                if (!cur_conf->enable_beacon)
 457                        goto stop_ani;
 458        } else if (ah->opmode == NL80211_IFTYPE_AP) {
 459                if (!cur_conf->enable_beacon) {
 460                        /*
 461                         * Disable ANI only when there are no
 462                         * associated stations.
 463                         */
 464                        if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags))
 465                                goto stop_ani;
 466                }
 467        } else if (ah->opmode == NL80211_IFTYPE_STATION) {
 468                if (!test_bit(ATH_OP_PRIM_STA_VIF, &common->op_flags))
 469                        goto stop_ani;
 470        }
 471
 472        if (!test_bit(ATH_OP_ANI_RUN, &common->op_flags)) {
 473                set_bit(ATH_OP_ANI_RUN, &common->op_flags);
 474                ath_start_ani(sc);
 475        }
 476
 477        return;
 478
 479stop_ani:
 480        clear_bit(ATH_OP_ANI_RUN, &common->op_flags);
 481        ath_stop_ani(sc);
 482}
 483
 484void ath_update_survey_nf(struct ath_softc *sc, int channel)
 485{
 486        struct ath_hw *ah = sc->sc_ah;
 487        struct ath9k_channel *chan = &ah->channels[channel];
 488        struct survey_info *survey = &sc->survey[channel];
 489
 490        if (chan->noisefloor) {
 491                survey->filled |= SURVEY_INFO_NOISE_DBM;
 492                survey->noise = ath9k_hw_getchan_noise(ah, chan,
 493                                                       chan->noisefloor);
 494        }
 495}
 496
 497/*
 498 * Updates the survey statistics and returns the busy time since last
 499 * update in %, if the measurement duration was long enough for the
 500 * result to be useful, -1 otherwise.
 501 */
 502int ath_update_survey_stats(struct ath_softc *sc)
 503{
 504        struct ath_hw *ah = sc->sc_ah;
 505        struct ath_common *common = ath9k_hw_common(ah);
 506        int pos = ah->curchan - &ah->channels[0];
 507        struct survey_info *survey = &sc->survey[pos];
 508        struct ath_cycle_counters *cc = &common->cc_survey;
 509        unsigned int div = common->clockrate * 1000;
 510        int ret = 0;
 511
 512        if (!ah->curchan)
 513                return -1;
 514
 515        if (ah->power_mode == ATH9K_PM_AWAKE)
 516                ath_hw_cycle_counters_update(common);
 517
 518        if (cc->cycles > 0) {
 519                survey->filled |= SURVEY_INFO_TIME |
 520                        SURVEY_INFO_TIME_BUSY |
 521                        SURVEY_INFO_TIME_RX |
 522                        SURVEY_INFO_TIME_TX;
 523                survey->time += cc->cycles / div;
 524                survey->time_busy += cc->rx_busy / div;
 525                survey->time_rx += cc->rx_frame / div;
 526                survey->time_tx += cc->tx_frame / div;
 527        }
 528
 529        if (cc->cycles < div)
 530                return -1;
 531
 532        if (cc->cycles > 0)
 533                ret = cc->rx_busy * 100 / cc->cycles;
 534
 535        memset(cc, 0, sizeof(*cc));
 536
 537        ath_update_survey_nf(sc, pos);
 538
 539        return ret;
 540}
 541