linux/drivers/net/wireless/ath/ath9k/beacon.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2008-2009 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 "ath9k.h"
  18
  19#define FUDGE 2
  20
  21/*
  22 *  This function will modify certain transmit queue properties depending on
  23 *  the operating mode of the station (AP or AdHoc).  Parameters are AIFS
  24 *  settings and channel width min/max
  25*/
  26static int ath_beaconq_config(struct ath_softc *sc)
  27{
  28        struct ath_hw *ah = sc->sc_ah;
  29        struct ath9k_tx_queue_info qi;
  30
  31        ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
  32        if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
  33                /* Always burst out beacon and CAB traffic. */
  34                qi.tqi_aifs = 1;
  35                qi.tqi_cwmin = 0;
  36                qi.tqi_cwmax = 0;
  37        } else {
  38                /* Adhoc mode; important thing is to use 2x cwmin. */
  39                qi.tqi_aifs = sc->beacon.beacon_qi.tqi_aifs;
  40                qi.tqi_cwmin = 2*sc->beacon.beacon_qi.tqi_cwmin;
  41                qi.tqi_cwmax = sc->beacon.beacon_qi.tqi_cwmax;
  42        }
  43
  44        if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) {
  45                DPRINTF(sc, ATH_DBG_FATAL,
  46                        "Unable to update h/w beacon queue parameters\n");
  47                return 0;
  48        } else {
  49                ath9k_hw_resettxqueue(ah, sc->beacon.beaconq);
  50                return 1;
  51        }
  52}
  53
  54/*
  55 *  Associates the beacon frame buffer with a transmit descriptor.  Will set
  56 *  up all required antenna switch parameters, rate codes, and channel flags.
  57 *  Beacons are always sent out at the lowest rate, and are not retried.
  58*/
  59static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
  60                             struct ath_buf *bf)
  61{
  62        struct sk_buff *skb = bf->bf_mpdu;
  63        struct ath_hw *ah = sc->sc_ah;
  64        struct ath_desc *ds;
  65        struct ath9k_11n_rate_series series[4];
  66        const struct ath_rate_table *rt;
  67        int flags, antenna, ctsrate = 0, ctsduration = 0;
  68        u8 rate;
  69
  70        ds = bf->bf_desc;
  71        flags = ATH9K_TXDESC_NOACK;
  72
  73        if (((sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC) ||
  74             (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT)) &&
  75            (ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) {
  76                ds->ds_link = bf->bf_daddr; /* self-linked */
  77                flags |= ATH9K_TXDESC_VEOL;
  78                /* Let hardware handle antenna switching. */
  79                antenna = 0;
  80        } else {
  81                ds->ds_link = 0;
  82                /*
  83                 * Switch antenna every beacon.
  84                 * Should only switch every beacon period, not for every SWBA
  85                 * XXX assumes two antennae
  86                 */
  87                antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1);
  88        }
  89
  90        ds->ds_data = bf->bf_buf_addr;
  91
  92        rt = sc->cur_rate_table;
  93        rate = rt->info[0].ratecode;
  94        if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
  95                rate |= rt->info[0].short_preamble;
  96
  97        ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN,
  98                               ATH9K_PKT_TYPE_BEACON,
  99                               MAX_RATE_POWER,
 100                               ATH9K_TXKEYIX_INVALID,
 101                               ATH9K_KEY_TYPE_CLEAR,
 102                               flags);
 103
 104        /* NB: beacon's BufLen must be a multiple of 4 bytes */
 105        ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4),
 106                            true, true, ds);
 107
 108        memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
 109        series[0].Tries = 1;
 110        series[0].Rate = rate;
 111        series[0].ChSel = sc->tx_chainmask;
 112        series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0;
 113        ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration,
 114                                     series, 4, 0);
 115}
 116
 117static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
 118                                           struct ieee80211_vif *vif)
 119{
 120        struct ath_wiphy *aphy = hw->priv;
 121        struct ath_softc *sc = aphy->sc;
 122        struct ath_buf *bf;
 123        struct ath_vif *avp;
 124        struct sk_buff *skb;
 125        struct ath_txq *cabq;
 126        struct ieee80211_tx_info *info;
 127        int cabq_depth;
 128
 129        if (aphy->state != ATH_WIPHY_ACTIVE)
 130                return NULL;
 131
 132        avp = (void *)vif->drv_priv;
 133        cabq = sc->beacon.cabq;
 134
 135        if (avp->av_bcbuf == NULL)
 136                return NULL;
 137
 138        /* Release the old beacon first */
 139
 140        bf = avp->av_bcbuf;
 141        skb = bf->bf_mpdu;
 142        if (skb) {
 143                dma_unmap_single(sc->dev, bf->bf_dmacontext,
 144                                 skb->len, DMA_TO_DEVICE);
 145                dev_kfree_skb_any(skb);
 146        }
 147
 148        /* Get a new beacon from mac80211 */
 149
 150        skb = ieee80211_beacon_get(hw, vif);
 151        bf->bf_mpdu = skb;
 152        if (skb == NULL)
 153                return NULL;
 154        ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
 155                avp->tsf_adjust;
 156
 157        info = IEEE80211_SKB_CB(skb);
 158        if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
 159                /*
 160                 * TODO: make sure the seq# gets assigned properly (vs. other
 161                 * TX frames)
 162                 */
 163                struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
 164                sc->tx.seq_no += 0x10;
 165                hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
 166                hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no);
 167        }
 168
 169        bf->bf_buf_addr = bf->bf_dmacontext =
 170                dma_map_single(sc->dev, skb->data,
 171                               skb->len, DMA_TO_DEVICE);
 172        if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
 173                dev_kfree_skb_any(skb);
 174                bf->bf_mpdu = NULL;
 175                DPRINTF(sc, ATH_DBG_FATAL, "dma_mapping_error on beaconing\n");
 176                return NULL;
 177        }
 178
 179        skb = ieee80211_get_buffered_bc(hw, vif);
 180
 181        /*
 182         * if the CABQ traffic from previous DTIM is pending and the current
 183         *  beacon is also a DTIM.
 184         *  1) if there is only one vif let the cab traffic continue.
 185         *  2) if there are more than one vif and we are using staggered
 186         *     beacons, then drain the cabq by dropping all the frames in
 187         *     the cabq so that the current vifs cab traffic can be scheduled.
 188         */
 189        spin_lock_bh(&cabq->axq_lock);
 190        cabq_depth = cabq->axq_depth;
 191        spin_unlock_bh(&cabq->axq_lock);
 192
 193        if (skb && cabq_depth) {
 194                if (sc->nvifs > 1) {
 195                        DPRINTF(sc, ATH_DBG_BEACON,
 196                                "Flushing previous cabq traffic\n");
 197                        ath_draintxq(sc, cabq, false);
 198                }
 199        }
 200
 201        ath_beacon_setup(sc, avp, bf);
 202
 203        while (skb) {
 204                ath_tx_cabq(hw, skb);
 205                skb = ieee80211_get_buffered_bc(hw, vif);
 206        }
 207
 208        return bf;
 209}
 210
 211/*
 212 * Startup beacon transmission for adhoc mode when they are sent entirely
 213 * by the hardware using the self-linked descriptor + veol trick.
 214*/
 215static void ath_beacon_start_adhoc(struct ath_softc *sc,
 216                                   struct ieee80211_vif *vif)
 217{
 218        struct ath_hw *ah = sc->sc_ah;
 219        struct ath_buf *bf;
 220        struct ath_vif *avp;
 221        struct sk_buff *skb;
 222
 223        avp = (void *)vif->drv_priv;
 224
 225        if (avp->av_bcbuf == NULL)
 226                return;
 227
 228        bf = avp->av_bcbuf;
 229        skb = bf->bf_mpdu;
 230
 231        ath_beacon_setup(sc, avp, bf);
 232
 233        /* NB: caller is known to have already stopped tx dma */
 234        ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bf->bf_daddr);
 235        ath9k_hw_txstart(ah, sc->beacon.beaconq);
 236        DPRINTF(sc, ATH_DBG_BEACON, "TXDP%u = %llx (%p)\n",
 237                sc->beacon.beaconq, ito64(bf->bf_daddr), bf->bf_desc);
 238}
 239
 240int ath_beaconq_setup(struct ath_hw *ah)
 241{
 242        struct ath9k_tx_queue_info qi;
 243
 244        memset(&qi, 0, sizeof(qi));
 245        qi.tqi_aifs = 1;
 246        qi.tqi_cwmin = 0;
 247        qi.tqi_cwmax = 0;
 248        /* NB: don't enable any interrupts */
 249        return ath9k_hw_setuptxqueue(ah, ATH9K_TX_QUEUE_BEACON, &qi);
 250}
 251
 252int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
 253{
 254        struct ath_softc *sc = aphy->sc;
 255        struct ath_vif *avp;
 256        struct ath_buf *bf;
 257        struct sk_buff *skb;
 258        __le64 tstamp;
 259
 260        avp = (void *)vif->drv_priv;
 261
 262        /* Allocate a beacon descriptor if we haven't done so. */
 263        if (!avp->av_bcbuf) {
 264                /* Allocate beacon state for hostap/ibss.  We know
 265                 * a buffer is available. */
 266                avp->av_bcbuf = list_first_entry(&sc->beacon.bbuf,
 267                                                 struct ath_buf, list);
 268                list_del(&avp->av_bcbuf->list);
 269
 270                if (sc->sc_ah->opmode == NL80211_IFTYPE_AP ||
 271                    !(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)) {
 272                        int slot;
 273                        /*
 274                         * Assign the vif to a beacon xmit slot. As
 275                         * above, this cannot fail to find one.
 276                         */
 277                        avp->av_bslot = 0;
 278                        for (slot = 0; slot < ATH_BCBUF; slot++)
 279                                if (sc->beacon.bslot[slot] == NULL) {
 280                                        /*
 281                                         * XXX hack, space out slots to better
 282                                         * deal with misses
 283                                         */
 284                                        if (slot+1 < ATH_BCBUF &&
 285                                            sc->beacon.bslot[slot+1] == NULL) {
 286                                                avp->av_bslot = slot+1;
 287                                                break;
 288                                        }
 289                                        avp->av_bslot = slot;
 290                                        /* NB: keep looking for a double slot */
 291                                }
 292                        BUG_ON(sc->beacon.bslot[avp->av_bslot] != NULL);
 293                        sc->beacon.bslot[avp->av_bslot] = vif;
 294                        sc->beacon.bslot_aphy[avp->av_bslot] = aphy;
 295                        sc->nbcnvifs++;
 296                }
 297        }
 298
 299        /* release the previous beacon frame, if it already exists. */
 300        bf = avp->av_bcbuf;
 301        if (bf->bf_mpdu != NULL) {
 302                skb = bf->bf_mpdu;
 303                dma_unmap_single(sc->dev, bf->bf_dmacontext,
 304                                 skb->len, DMA_TO_DEVICE);
 305                dev_kfree_skb_any(skb);
 306                bf->bf_mpdu = NULL;
 307        }
 308
 309        /* NB: the beacon data buffer must be 32-bit aligned. */
 310        skb = ieee80211_beacon_get(sc->hw, vif);
 311        if (skb == NULL) {
 312                DPRINTF(sc, ATH_DBG_BEACON, "cannot get skb\n");
 313                return -ENOMEM;
 314        }
 315
 316        tstamp = ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp;
 317        sc->beacon.bc_tstamp = le64_to_cpu(tstamp);
 318        /* Calculate a TSF adjustment factor required for staggered beacons. */
 319        if (avp->av_bslot > 0) {
 320                u64 tsfadjust;
 321                int intval;
 322
 323                intval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL;
 324
 325                /*
 326                 * Calculate the TSF offset for this beacon slot, i.e., the
 327                 * number of usecs that need to be added to the timestamp field
 328                 * in Beacon and Probe Response frames. Beacon slot 0 is
 329                 * processed at the correct offset, so it does not require TSF
 330                 * adjustment. Other slots are adjusted to get the timestamp
 331                 * close to the TBTT for the BSS.
 332                 */
 333                tsfadjust = intval * avp->av_bslot / ATH_BCBUF;
 334                avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
 335
 336                DPRINTF(sc, ATH_DBG_BEACON,
 337                        "stagger beacons, bslot %d intval %u tsfadjust %llu\n",
 338                        avp->av_bslot, intval, (unsigned long long)tsfadjust);
 339
 340                ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
 341                        avp->tsf_adjust;
 342        } else
 343                avp->tsf_adjust = cpu_to_le64(0);
 344
 345        bf->bf_mpdu = skb;
 346        bf->bf_buf_addr = bf->bf_dmacontext =
 347                dma_map_single(sc->dev, skb->data,
 348                               skb->len, DMA_TO_DEVICE);
 349        if (unlikely(dma_mapping_error(sc->dev, bf->bf_buf_addr))) {
 350                dev_kfree_skb_any(skb);
 351                bf->bf_mpdu = NULL;
 352                DPRINTF(sc, ATH_DBG_FATAL,
 353                        "dma_mapping_error on beacon alloc\n");
 354                return -ENOMEM;
 355        }
 356
 357        return 0;
 358}
 359
 360void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp)
 361{
 362        if (avp->av_bcbuf != NULL) {
 363                struct ath_buf *bf;
 364
 365                if (avp->av_bslot != -1) {
 366                        sc->beacon.bslot[avp->av_bslot] = NULL;
 367                        sc->beacon.bslot_aphy[avp->av_bslot] = NULL;
 368                        sc->nbcnvifs--;
 369                }
 370
 371                bf = avp->av_bcbuf;
 372                if (bf->bf_mpdu != NULL) {
 373                        struct sk_buff *skb = bf->bf_mpdu;
 374                        dma_unmap_single(sc->dev, bf->bf_dmacontext,
 375                                         skb->len, DMA_TO_DEVICE);
 376                        dev_kfree_skb_any(skb);
 377                        bf->bf_mpdu = NULL;
 378                }
 379                list_add_tail(&bf->list, &sc->beacon.bbuf);
 380
 381                avp->av_bcbuf = NULL;
 382        }
 383}
 384
 385void ath_beacon_tasklet(unsigned long data)
 386{
 387        struct ath_softc *sc = (struct ath_softc *)data;
 388        struct ath_hw *ah = sc->sc_ah;
 389        struct ath_buf *bf = NULL;
 390        struct ieee80211_vif *vif;
 391        struct ath_wiphy *aphy;
 392        int slot;
 393        u32 bfaddr, bc = 0, tsftu;
 394        u64 tsf;
 395        u16 intval;
 396
 397        /*
 398         * Check if the previous beacon has gone out.  If
 399         * not don't try to post another, skip this period
 400         * and wait for the next.  Missed beacons indicate
 401         * a problem and should not occur.  If we miss too
 402         * many consecutive beacons reset the device.
 403         */
 404        if (ath9k_hw_numtxpending(ah, sc->beacon.beaconq) != 0) {
 405                sc->beacon.bmisscnt++;
 406
 407                if (sc->beacon.bmisscnt < BSTUCK_THRESH) {
 408                        DPRINTF(sc, ATH_DBG_BEACON,
 409                                "missed %u consecutive beacons\n",
 410                                sc->beacon.bmisscnt);
 411                } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
 412                        DPRINTF(sc, ATH_DBG_BEACON,
 413                                "beacon is officially stuck\n");
 414                        sc->sc_flags |= SC_OP_TSF_RESET;
 415                        ath_reset(sc, false);
 416                }
 417
 418                return;
 419        }
 420
 421        if (sc->beacon.bmisscnt != 0) {
 422                DPRINTF(sc, ATH_DBG_BEACON,
 423                        "resume beacon xmit after %u misses\n",
 424                        sc->beacon.bmisscnt);
 425                sc->beacon.bmisscnt = 0;
 426        }
 427
 428        /*
 429         * Generate beacon frames. we are sending frames
 430         * staggered so calculate the slot for this frame based
 431         * on the tsf to safeguard against missing an swba.
 432         */
 433
 434        intval = sc->beacon_interval ? : ATH_DEFAULT_BINTVAL;
 435
 436        tsf = ath9k_hw_gettsf64(ah);
 437        tsftu = TSF_TO_TU(tsf>>32, tsf);
 438        slot = ((tsftu % intval) * ATH_BCBUF) / intval;
 439        /*
 440         * Reverse the slot order to get slot 0 on the TBTT offset that does
 441         * not require TSF adjustment and other slots adding
 442         * slot/ATH_BCBUF * beacon_int to timestamp. For example, with
 443         * ATH_BCBUF = 4, we process beacon slots as follows: 3 2 1 0 3 2 1 ..
 444         * and slot 0 is at correct offset to TBTT.
 445         */
 446        slot = ATH_BCBUF - slot - 1;
 447        vif = sc->beacon.bslot[slot];
 448        aphy = sc->beacon.bslot_aphy[slot];
 449
 450        DPRINTF(sc, ATH_DBG_BEACON,
 451                "slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
 452                slot, tsf, tsftu, intval, vif);
 453
 454        bfaddr = 0;
 455        if (vif) {
 456                bf = ath_beacon_generate(aphy->hw, vif);
 457                if (bf != NULL) {
 458                        bfaddr = bf->bf_daddr;
 459                        bc = 1;
 460                }
 461        }
 462
 463        /*
 464         * Handle slot time change when a non-ERP station joins/leaves
 465         * an 11g network.  The 802.11 layer notifies us via callback,
 466         * we mark updateslot, then wait one beacon before effecting
 467         * the change.  This gives associated stations at least one
 468         * beacon interval to note the state change.
 469         *
 470         * NB: The slot time change state machine is clocked according
 471         *     to whether we are bursting or staggering beacons.  We
 472         *     recognize the request to update and record the current
 473         *     slot then don't transition until that slot is reached
 474         *     again.  If we miss a beacon for that slot then we'll be
 475         *     slow to transition but we'll be sure at least one beacon
 476         *     interval has passed.  When bursting slot is always left
 477         *     set to ATH_BCBUF so this check is a noop.
 478         */
 479        if (sc->beacon.updateslot == UPDATE) {
 480                sc->beacon.updateslot = COMMIT; /* commit next beacon */
 481                sc->beacon.slotupdate = slot;
 482        } else if (sc->beacon.updateslot == COMMIT && sc->beacon.slotupdate == slot) {
 483                ath9k_hw_setslottime(sc->sc_ah, sc->beacon.slottime);
 484                sc->beacon.updateslot = OK;
 485        }
 486        if (bfaddr != 0) {
 487                /*
 488                 * Stop any current dma and put the new frame(s) on the queue.
 489                 * This should never fail since we check above that no frames
 490                 * are still pending on the queue.
 491                 */
 492                if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) {
 493                        DPRINTF(sc, ATH_DBG_FATAL,
 494                                "beacon queue %u did not stop?\n", sc->beacon.beaconq);
 495                }
 496
 497                /* NB: cabq traffic should already be queued and primed */
 498                ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr);
 499                ath9k_hw_txstart(ah, sc->beacon.beaconq);
 500
 501                sc->beacon.ast_be_xmit += bc;     /* XXX per-vif? */
 502        }
 503}
 504
 505/*
 506 * For multi-bss ap support beacons are either staggered evenly over N slots or
 507 * burst together.  For the former arrange for the SWBA to be delivered for each
 508 * slot. Slots that are not occupied will generate nothing.
 509 */
 510static void ath_beacon_config_ap(struct ath_softc *sc,
 511                                 struct ath_beacon_config *conf)
 512{
 513        u32 nexttbtt, intval;
 514
 515        /* Configure the timers only when the TSF has to be reset */
 516
 517        if (!(sc->sc_flags & SC_OP_TSF_RESET))
 518                return;
 519
 520        /* NB: the beacon interval is kept internally in TU's */
 521        intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
 522        intval /= ATH_BCBUF;    /* for staggered beacons */
 523        nexttbtt = intval;
 524        intval |= ATH9K_BEACON_RESET_TSF;
 525
 526        /*
 527         * In AP mode we enable the beacon timers and SWBA interrupts to
 528         * prepare beacon frames.
 529         */
 530        intval |= ATH9K_BEACON_ENA;
 531        sc->imask |= ATH9K_INT_SWBA;
 532        ath_beaconq_config(sc);
 533
 534        /* Set the computed AP beacon timers */
 535
 536        ath9k_hw_set_interrupts(sc->sc_ah, 0);
 537        ath9k_hw_beaconinit(sc->sc_ah, nexttbtt, intval);
 538        sc->beacon.bmisscnt = 0;
 539        ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
 540
 541        /* Clear the reset TSF flag, so that subsequent beacon updation
 542           will not reset the HW TSF. */
 543
 544        sc->sc_flags &= ~SC_OP_TSF_RESET;
 545}
 546
 547/*
 548 * This sets up the beacon timers according to the timestamp of the last
 549 * received beacon and the current TSF, configures PCF and DTIM
 550 * handling, programs the sleep registers so the hardware will wakeup in
 551 * time to receive beacons, and configures the beacon miss handling so
 552 * we'll receive a BMISS interrupt when we stop seeing beacons from the AP
 553 * we've associated with.
 554 */
 555static void ath_beacon_config_sta(struct ath_softc *sc,
 556                                  struct ath_beacon_config *conf)
 557{
 558        struct ath9k_beacon_state bs;
 559        int dtimperiod, dtimcount, sleepduration;
 560        int cfpperiod, cfpcount;
 561        u32 nexttbtt = 0, intval, tsftu;
 562        u64 tsf;
 563        int num_beacons, offset, dtim_dec_count, cfp_dec_count;
 564
 565        memset(&bs, 0, sizeof(bs));
 566        intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
 567
 568        /*
 569         * Setup dtim and cfp parameters according to
 570         * last beacon we received (which may be none).
 571         */
 572        dtimperiod = conf->dtim_period;
 573        if (dtimperiod <= 0)            /* NB: 0 if not known */
 574                dtimperiod = 1;
 575        dtimcount = conf->dtim_count;
 576        if (dtimcount >= dtimperiod)    /* NB: sanity check */
 577                dtimcount = 0;
 578        cfpperiod = 1;                  /* NB: no PCF support yet */
 579        cfpcount = 0;
 580
 581        sleepduration = conf->listen_interval * intval;
 582        if (sleepduration <= 0)
 583                sleepduration = intval;
 584
 585        /*
 586         * Pull nexttbtt forward to reflect the current
 587         * TSF and calculate dtim+cfp state for the result.
 588         */
 589        tsf = ath9k_hw_gettsf64(sc->sc_ah);
 590        tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
 591
 592        num_beacons = tsftu / intval + 1;
 593        offset = tsftu % intval;
 594        nexttbtt = tsftu - offset;
 595        if (offset)
 596                nexttbtt += intval;
 597
 598        /* DTIM Beacon every dtimperiod Beacon */
 599        dtim_dec_count = num_beacons % dtimperiod;
 600        /* CFP every cfpperiod DTIM Beacon */
 601        cfp_dec_count = (num_beacons / dtimperiod) % cfpperiod;
 602        if (dtim_dec_count)
 603                cfp_dec_count++;
 604
 605        dtimcount -= dtim_dec_count;
 606        if (dtimcount < 0)
 607                dtimcount += dtimperiod;
 608
 609        cfpcount -= cfp_dec_count;
 610        if (cfpcount < 0)
 611                cfpcount += cfpperiod;
 612
 613        bs.bs_intval = intval;
 614        bs.bs_nexttbtt = nexttbtt;
 615        bs.bs_dtimperiod = dtimperiod*intval;
 616        bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval;
 617        bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod;
 618        bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod;
 619        bs.bs_cfpmaxduration = 0;
 620
 621        /*
 622         * Calculate the number of consecutive beacons to miss* before taking
 623         * a BMISS interrupt. The configuration is specified in TU so we only
 624         * need calculate based on the beacon interval.  Note that we clamp the
 625         * result to at most 15 beacons.
 626         */
 627        if (sleepduration > intval) {
 628                bs.bs_bmissthreshold = conf->listen_interval *
 629                        ATH_DEFAULT_BMISS_LIMIT / 2;
 630        } else {
 631                bs.bs_bmissthreshold = DIV_ROUND_UP(conf->bmiss_timeout, intval);
 632                if (bs.bs_bmissthreshold > 15)
 633                        bs.bs_bmissthreshold = 15;
 634                else if (bs.bs_bmissthreshold <= 0)
 635                        bs.bs_bmissthreshold = 1;
 636        }
 637
 638        /*
 639         * Calculate sleep duration. The configuration is given in ms.
 640         * We ensure a multiple of the beacon period is used. Also, if the sleep
 641         * duration is greater than the DTIM period then it makes senses
 642         * to make it a multiple of that.
 643         *
 644         * XXX fixed at 100ms
 645         */
 646
 647        bs.bs_sleepduration = roundup(IEEE80211_MS_TO_TU(100), sleepduration);
 648        if (bs.bs_sleepduration > bs.bs_dtimperiod)
 649                bs.bs_sleepduration = bs.bs_dtimperiod;
 650
 651        /* TSF out of range threshold fixed at 1 second */
 652        bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
 653
 654        DPRINTF(sc, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
 655        DPRINTF(sc, ATH_DBG_BEACON,
 656                "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
 657                bs.bs_bmissthreshold, bs.bs_sleepduration,
 658                bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
 659
 660        /* Set the computed STA beacon timers */
 661
 662        ath9k_hw_set_interrupts(sc->sc_ah, 0);
 663        ath9k_hw_set_sta_beacon_timers(sc->sc_ah, &bs);
 664        sc->imask |= ATH9K_INT_BMISS;
 665        ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
 666}
 667
 668static void ath_beacon_config_adhoc(struct ath_softc *sc,
 669                                    struct ath_beacon_config *conf,
 670                                    struct ieee80211_vif *vif)
 671{
 672        u64 tsf;
 673        u32 tsftu, intval, nexttbtt;
 674
 675        intval = conf->beacon_interval & ATH9K_BEACON_PERIOD;
 676
 677
 678        /* Pull nexttbtt forward to reflect the current TSF */
 679
 680        nexttbtt = TSF_TO_TU(sc->beacon.bc_tstamp >> 32, sc->beacon.bc_tstamp);
 681        if (nexttbtt == 0)
 682                nexttbtt = intval;
 683        else if (intval)
 684                nexttbtt = roundup(nexttbtt, intval);
 685
 686        tsf = ath9k_hw_gettsf64(sc->sc_ah);
 687        tsftu = TSF_TO_TU((u32)(tsf>>32), (u32)tsf) + FUDGE;
 688        do {
 689                nexttbtt += intval;
 690        } while (nexttbtt < tsftu);
 691
 692        DPRINTF(sc, ATH_DBG_BEACON,
 693                "IBSS nexttbtt %u intval %u (%u)\n",
 694                nexttbtt, intval, conf->beacon_interval);
 695
 696        /*
 697         * In IBSS mode enable the beacon timers but only enable SWBA interrupts
 698         * if we need to manually prepare beacon frames.  Otherwise we use a
 699         * self-linked tx descriptor and let the hardware deal with things.
 700         */
 701        intval |= ATH9K_BEACON_ENA;
 702        if (!(sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL))
 703                sc->imask |= ATH9K_INT_SWBA;
 704
 705        ath_beaconq_config(sc);
 706
 707        /* Set the computed ADHOC beacon timers */
 708
 709        ath9k_hw_set_interrupts(sc->sc_ah, 0);
 710        ath9k_hw_beaconinit(sc->sc_ah, nexttbtt, intval);
 711        sc->beacon.bmisscnt = 0;
 712        ath9k_hw_set_interrupts(sc->sc_ah, sc->imask);
 713
 714        /* FIXME: Handle properly when vif is NULL */
 715        if (vif && sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_VEOL)
 716                ath_beacon_start_adhoc(sc, vif);
 717}
 718
 719void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
 720{
 721        struct ath_beacon_config *cur_conf = &sc->cur_beacon_conf;
 722        enum nl80211_iftype iftype;
 723
 724        /* Setup the beacon configuration parameters */
 725
 726        if (vif) {
 727                struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
 728
 729                iftype = vif->type;
 730
 731                cur_conf->beacon_interval = bss_conf->beacon_int;
 732                cur_conf->dtim_period = bss_conf->dtim_period;
 733                cur_conf->listen_interval = 1;
 734                cur_conf->dtim_count = 1;
 735                cur_conf->bmiss_timeout =
 736                        ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
 737        } else {
 738                iftype = sc->sc_ah->opmode;
 739        }
 740
 741        /*
 742         * It looks like mac80211 may end up using beacon interval of zero in
 743         * some cases (at least for mesh point). Avoid getting into an
 744         * infinite loop by using a bit safer value instead. To be safe,
 745         * do sanity check on beacon interval for all operating modes.
 746         */
 747        if (cur_conf->beacon_interval == 0)
 748                cur_conf->beacon_interval = 100;
 749
 750        switch (iftype) {
 751        case NL80211_IFTYPE_AP:
 752                ath_beacon_config_ap(sc, cur_conf);
 753                break;
 754        case NL80211_IFTYPE_ADHOC:
 755        case NL80211_IFTYPE_MESH_POINT:
 756                ath_beacon_config_adhoc(sc, cur_conf, vif);
 757                break;
 758        case NL80211_IFTYPE_STATION:
 759                ath_beacon_config_sta(sc, cur_conf);
 760                break;
 761        default:
 762                DPRINTF(sc, ATH_DBG_CONFIG,
 763                        "Unsupported beaconing mode\n");
 764                return;
 765        }
 766
 767        sc->sc_flags |= SC_OP_BEACONS;
 768}
 769