source: trunk/package/ath9k/src/drivers/net/wireless/ath9k/beacon.c @ 11884

Last change on this file since 11884 was 11884, checked in by nbd, 8 years ago

add the new ath9k driver (loads successfully on an AR9160 card, but still seems to have some rf issues)

File size: 29.9 KB
Line 
1/*
2 * Copyright (c) 2008 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 /* Implementation of beacon processing. */
18
19#include "core.h"
20
21/*
22 *  Configure parameters for the beacon queue
23 *
24 *  This function will modify certain transmit queue properties depending on
25 *  the operating mode of the station (AP or AdHoc).  Parameters are AIFS
26 *  settings and channel width min/max
27*/
28
29static int ath_beaconq_config(struct ath_softc *sc)
30{
31        struct ath_hal *ah = sc->sc_ah;
32        struct hal_txq_info qi;
33
34        ath9k_hw_gettxqueueprops(ah, sc->sc_bhalq, &qi);
35        if (sc->sc_opmode == HAL_M_HOSTAP) {
36                /* Always burst out beacon and CAB traffic. */
37                qi.tqi_aifs = 1;
38                qi.tqi_cwmin = 0;
39                qi.tqi_cwmax = 0;
40        } else {
41                /* Adhoc mode; important thing is to use 2x cwmin. */
42                qi.tqi_aifs = sc->sc_beacon_qi.tqi_aifs;
43                qi.tqi_cwmin = 2*sc->sc_beacon_qi.tqi_cwmin;
44                qi.tqi_cwmax = sc->sc_beacon_qi.tqi_cwmax;
45        }
46
47        if (!ath9k_hw_settxqueueprops(ah, sc->sc_bhalq, &qi)) {
48                DPRINTF(sc, ATH_DEBUG_FATAL,
49                        "%s: unable to update h/w beacon queue parameters\n",
50                        __func__);
51                return 0;
52        } else {
53                ath9k_hw_resettxqueue(ah, sc->sc_bhalq); /* push to h/w */
54                return 1;
55        }
56}
57
58/*
59 *  Setup the beacon frame for transmit.
60 *
61 *  Associates the beacon frame buffer with a transmit descriptor.  Will set
62 *  up all required antenna switch parameters, rate codes, and channel flags.
63 *  Beacons are always sent out at the lowest rate, and are not retried.
64*/
65
66static void ath_beacon_setup(struct ath_softc *sc,
67        struct ath_vap *avp, struct ath_buf *bf)
68{
69        struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu;
70        struct ath_hal *ah = sc->sc_ah;
71        struct ath_desc *ds;
72        int flags, antenna;
73        const struct hal_rate_table *rt;
74        u_int8_t rix, rate;
75        int ctsrate = 0;
76        int ctsduration = 0;
77        struct hal_11n_rate_series  series[4];
78
79        DPRINTF(sc, ATH_DEBUG_BEACON, "%s: m %p len %u\n",
80                __func__, skb, skb->len);
81
82        /* setup descriptors */
83        ds = bf->bf_desc;
84
85        flags = HAL_TXDESC_NOACK;
86
87        if (sc->sc_opmode == HAL_M_IBSS && sc->sc_hasveol) {
88                ds->ds_link = bf->bf_daddr; /* self-linked */
89                flags |= HAL_TXDESC_VEOL;
90                /* Let hardware handle antenna switching. */
91                antenna = 0;
92        } else {
93                ds->ds_link = 0;
94                /*
95                 * Switch antenna every beacon.
96                 * Should only switch every beacon period, not for every
97                 * SWBA's
98                 * XXX assumes two antenna
99                 */
100                if (sc->sc_stagbeacons)
101                        antenna = ((sc->ast_be_xmit /
102                                        sc->sc_nbcnvaps) & 1 ? 2 : 1);
103                else
104                        antenna = (sc->ast_be_xmit & 1 ? 2 : 1);
105        }
106
107        ds->ds_data = bf->bf_buf_addr;
108
109        /*
110         * Calculate rate code.
111         * XXX everything at min xmit rate
112         */
113        rix = sc->sc_minrateix;
114        rt = sc->sc_currates;
115        rate = rt->info[rix].rateCode;
116        if (sc->sc_flags & ATH_PREAMBLE_SHORT)
117                rate |= rt->info[rix].shortPreamble;
118
119        ath9k_hw_set11n_txdesc(ah, ds
120                              , skb->len + FCS_LEN /* frame length */
121                              , HAL_PKT_TYPE_BEACON /* Atheros packet type */
122                              , avp->av_btxctl.txpower /* txpower XXX */
123                              , HAL_TXKEYIX_INVALID /* no encryption */
124                              , HAL_KEY_TYPE_CLEAR /* no encryption */
125                              , flags /* no ack, veol for beacons */
126                );
127
128        /* NB: beacon's BufLen must be a multiple of 4 bytes */
129        ath9k_hw_filltxdesc(ah, ds
130                           , roundup(skb->len, 4) /* buffer length */
131                           , AH_TRUE /* first segment */
132                           , AH_TRUE /* last segment */
133                           , ds /* first descriptor */
134                );
135
136        memzero(series, sizeof(struct hal_11n_rate_series) * 4);
137        series[0].Tries = 1;
138        series[0].Rate = rate;
139        series[0].ChSel = sc->sc_tx_chainmask;
140        series[0].RateFlags = (ctsrate) ? HAL_RATESERIES_RTS_CTS : 0;
141        ath9k_hw_set11n_ratescenario(ah, ds, ds, 0,
142                ctsrate, ctsduration, series, 4, 0);
143
144        /* NB: The desc swap function becomes void,
145         * if descriptor swapping is not enabled
146         */
147        ath_desc_swap(ds);
148}
149
150/* Move everything from the vap's mcast queue to the hardware cab queue.
151 * Caller must hold mcasq lock and cabq lock
152 * XXX MORE_DATA bit?
153 */
154static void empty_mcastq_into_cabq(struct ath_hal *ah,
155        struct ath_txq *mcastq, struct ath_txq *cabq)
156{
157        struct ath_buf *bfmcast;
158
159        BUG_ON(list_empty(&mcastq->axq_q));
160
161        bfmcast = list_first_entry(&mcastq->axq_q, struct ath_buf, list);
162
163        /* link the descriptors */
164        if (!cabq->axq_link)
165                ath9k_hw_puttxbuf(ah, cabq->axq_qnum, bfmcast->bf_daddr);
166        else
167                *cabq->axq_link = cpu_to_le32(bfmcast->bf_daddr);
168
169        /* append the private vap mcast list to  the cabq */
170
171        cabq->axq_depth += mcastq->axq_depth;
172        cabq->axq_totalqueued += mcastq->axq_totalqueued;
173        cabq->axq_linkbuf = mcastq->axq_linkbuf;
174        cabq->axq_link = mcastq->axq_link;
175        list_splice_tail_init(&mcastq->axq_q, &cabq->axq_q);
176        mcastq->axq_depth = 0;
177        mcastq->axq_totalqueued = 0;
178        mcastq->axq_linkbuf = NULL;
179        mcastq->axq_link = NULL;
180}
181
182/* This is only run at DTIM. We move everything from the vap's mcast queue
183 * to the hardware cab queue. Caller must hold the mcastq lock. */
184static void trigger_mcastq(struct ath_hal *ah,
185        struct ath_txq *mcastq, struct ath_txq *cabq)
186{
187        spin_lock_bh(&cabq->axq_lock);
188
189        if (!list_empty(&mcastq->axq_q))
190                empty_mcastq_into_cabq(ah, mcastq, cabq);
191
192        /* cabq is gated by beacon so it is safe to start here */
193        if (!list_empty(&cabq->axq_q))
194                ath9k_hw_txstart(ah, cabq->axq_qnum);
195
196        spin_unlock_bh(&cabq->axq_lock);
197}
198
199/*
200 *  Generate beacon frame and queue cab data for a vap.
201 *
202 *  Updates the contents of the beacon frame.  It is assumed that the buffer for
203 *  the beacon frame has been allocated in the ATH object, and simply needs to
204 *  be filled for this cycle.  Also, any CAB (crap after beacon?) traffic will
205 *  be added to the beacon frame at this point.
206*/
207static struct ath_buf *ath_beacon_generate(struct ath_softc *sc, int if_id)
208{
209        struct ath_hal *ah = sc->sc_ah;
210        struct ath_buf *bf;
211        struct ath_vap *avp;
212        struct sk_buff *skb;
213        int cabq_depth;
214        int mcastq_depth;
215        int is_beacon_dtim = 0;
216        unsigned int curlen;
217        struct ath_txq *cabq;
218        struct ath_txq *mcastq;
219        avp = sc->sc_vaps[if_id];
220
221        mcastq = &avp->av_mcastq;
222        cabq = sc->sc_cabq;
223
224        ASSERT(avp);
225
226        if (avp->av_bcbuf == NULL) {
227                DPRINTF(sc, ATH_DEBUG_BEACON, "%s: avp=%p av_bcbuf=%p\n",
228                        __func__, avp, avp->av_bcbuf);
229                return NULL;
230        }
231        bf = avp->av_bcbuf;
232        skb = (struct sk_buff *) bf->bf_mpdu;
233
234        /*
235         * Update dynamic beacon contents.  If this returns
236         * non-zero then we need to remap the memory because
237         * the beacon frame changed size (probably because
238         * of the TIM bitmap).
239         */
240        curlen = skb->len;
241
242        /* XXX: spin_lock_bh should not be used here, but sparse bitches
243         * otherwise. We should fix sparse :) */
244        spin_lock_bh(&mcastq->axq_lock);
245        mcastq_depth = avp->av_mcastq.axq_depth;
246
247        if (ath_update_beacon(sc, if_id, &avp->av_boff, skb, mcastq_depth) ==
248            1) {
249                ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE,
250                                     get_dma_mem_context(bf, bf_dmacontext));
251                bf->bf_buf_addr = ath_skb_map_single(sc, skb, PCI_DMA_TODEVICE,
252                        get_dma_mem_context(bf, bf_dmacontext));
253        } else {
254                pci_dma_sync_single_for_cpu(sc->pdev,
255                                            bf->bf_buf_addr,
256                                            skb_tailroom(skb),
257                                            PCI_DMA_TODEVICE);
258        }
259
260        /*
261         * if the CABQ traffic from previous DTIM is pending and the current
262         *  beacon is also a DTIM.
263         *  1) if there is only one vap let the cab traffic continue.
264         *  2) if there are more than one vap and we are using staggered
265         *     beacons, then drain the cabq by dropping all the frames in
266         *     the cabq so that the current vaps cab traffic can be scheduled.
267         */
268        spin_lock_bh(&cabq->axq_lock);
269        cabq_depth = cabq->axq_depth;
270        spin_unlock_bh(&cabq->axq_lock);
271
272        is_beacon_dtim = avp->av_boff.bo_tim[4] & 1;
273
274        if (mcastq_depth && is_beacon_dtim && cabq_depth) {
275                /*
276                 * Unlock the cabq lock as ath_tx_draintxq acquires
277                 * the lock again which is a common function and that
278                 * acquires txq lock inside.
279                 */
280                if (sc->sc_nvaps > 1 && sc->sc_stagbeacons) {
281                        ath_tx_draintxq(sc, cabq, AH_FALSE);
282                        DPRINTF(sc, ATH_DEBUG_BEACON,
283                                "%s: flush previous cabq traffic\n", __func__);
284                }
285        }
286
287        /* Construct tx descriptor. */
288        ath_beacon_setup(sc, avp, bf);
289
290        /*
291         * Enable the CAB queue before the beacon queue to
292         * insure cab frames are triggered by this beacon.
293         */
294        if (is_beacon_dtim)
295                trigger_mcastq(ah, mcastq, cabq);
296
297        spin_unlock_bh(&mcastq->axq_lock);
298        return bf;
299}
300
301/*
302 * Startup beacon transmission for adhoc mode when they are sent entirely
303 * by the hardware using the self-linked descriptor + veol trick.
304*/
305
306static void ath_beacon_start_adhoc(struct ath_softc *sc, int if_id)
307{
308        struct ath_hal *ah = sc->sc_ah;
309        struct ath_buf *bf;
310        struct ath_vap *avp;
311        struct sk_buff *skb;
312
313        avp = sc->sc_vaps[if_id];
314        ASSERT(avp);
315
316        if (avp->av_bcbuf == NULL) {
317                DPRINTF(sc, ATH_DEBUG_BEACON, "%s: avp=%p av_bcbuf=%p\n",
318                        __func__, avp, avp != NULL ? avp->av_bcbuf : NULL);
319                return;
320        }
321        bf = avp->av_bcbuf;
322        skb = (struct sk_buff *) bf->bf_mpdu;
323
324        /* Construct tx descriptor. */
325        ath_beacon_setup(sc, avp, bf);
326
327        /* NB: caller is known to have already stopped tx dma */
328        ath9k_hw_puttxbuf(ah, sc->sc_bhalq, bf->bf_daddr);
329        ath9k_hw_txstart(ah, sc->sc_bhalq);
330        DPRINTF(sc, ATH_DEBUG_BEACON, "%s: TXDP%u = %llx (%p)\n", __func__,
331                sc->sc_bhalq, ito64(bf->bf_daddr), bf->bf_desc);
332}
333
334/*
335 *  Setup a h/w transmit queue for beacons.
336 *
337 *  This function allocates an information structure (struct hal_txq_info)
338 *  on the stack, sets some specific parameters (zero out channel width
339 *  min/max, and enable aifs). The info structure does not need to be
340 *  persistant.
341*/
342
343int ath_beaconq_setup(struct ath_hal *ah)
344{
345        struct hal_txq_info qi;
346
347        memzero(&qi, sizeof(qi));
348        qi.tqi_aifs = 1;
349        qi.tqi_cwmin = 0;
350        qi.tqi_cwmax = 0;
351        /* NB: don't enable any interrupts */
352        return ath9k_hw_setuptxqueue(ah, HAL_TX_QUEUE_BEACON, &qi);
353}
354
355
356/*
357 *  Allocate and setup an initial beacon frame.
358 *
359 *  Allocate a beacon state variable for a specific VAP instance created on
360 *  the ATH interface.  This routine also calculates the beacon "slot" for
361 *  staggared beacons in the mBSSID case.
362*/
363
364int ath_beacon_alloc(struct ath_softc *sc, int if_id)
365{
366        struct ath_vap *avp;
367        struct ieee80211_hdr *wh;
368        struct ath_buf *bf;
369        struct sk_buff *skb;
370
371        avp = sc->sc_vaps[if_id];
372        ASSERT(avp);
373
374        /* Allocate a beacon descriptor if we haven't done so. */
375        if (!avp->av_bcbuf) {
376                /*
377                 * Allocate beacon state for hostap/ibss.  We know
378                 * a buffer is available.
379                 */
380
381                avp->av_bcbuf = list_first_entry(&sc->sc_bbuf,
382                                struct ath_buf, list);
383                list_del(&avp->av_bcbuf->list);
384
385                if (sc->sc_opmode == HAL_M_HOSTAP || !sc->sc_hasveol) {
386                        int slot;
387                        /*
388                         * Assign the vap to a beacon xmit slot. As
389                         * above, this cannot fail to find one.
390                         */
391                        avp->av_bslot = 0;
392                        for (slot = 0; slot < ATH_BCBUF; slot++)
393                                if (sc->sc_bslot[slot] == ATH_IF_ID_ANY) {
394                                        /*
395                                         * XXX hack, space out slots to better
396                                         * deal with misses
397                                         */
398                                        if (slot+1 < ATH_BCBUF &&
399                                            sc->sc_bslot[slot+1] ==
400                                                ATH_IF_ID_ANY) {
401                                                avp->av_bslot = slot+1;
402                                                break;
403                                        }
404                                        avp->av_bslot = slot;
405                                        /* NB: keep looking for a double slot */
406                                }
407                        KASSERT(sc->sc_bslot[avp->av_bslot] == ATH_IF_ID_ANY,
408                                ("beacon slot %u not empty?", avp->av_bslot));
409                        sc->sc_bslot[avp->av_bslot] = if_id;
410                        sc->sc_nbcnvaps++;
411                }
412        }
413
414        /* release the previous beacon frame , if it already exists. */
415        bf = avp->av_bcbuf;
416        if (bf->bf_mpdu != NULL) {
417                struct ath_xmit_status tx_status;
418
419                skb = (struct sk_buff *) bf->bf_mpdu;
420                ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE,
421                                     get_dma_mem_context(bf, bf_dmacontext));
422                tx_status.flags = 0;
423                tx_status.retries = 0;
424                ath_tx_complete(sc, skb, &tx_status, NULL);
425                bf->bf_mpdu = NULL;
426        }
427
428        /*
429         * NB: the beacon data buffer must be 32-bit aligned;
430         * we assume the wbuf routines will return us something
431         * with this alignment (perhaps should assert).
432         */
433        skb = ath_get_beacon(sc, if_id, &avp->av_boff, &avp->av_btxctl);
434        if (skb == NULL) {
435                DPRINTF(sc, ATH_DEBUG_BEACON, "%s: cannot get skb\n",
436                        __func__);
437                return -ENOMEM;
438        }
439
440        /*
441         * Calculate a TSF adjustment factor required for
442         * staggered beacons.  Note that we assume the format
443         * of the beacon frame leaves the tstamp field immediately
444         * following the header.
445         */
446        if (sc->sc_stagbeacons && avp->av_bslot > 0) {
447                u_int64_t tsfadjust;
448                int intval;
449
450                /* FIXME: Use default value for now: Sujith */
451
452                intval = ATH_DEFAULT_BINTVAL;
453
454                /*
455                 * The beacon interval is in TU's; the TSF in usecs.
456                 * We figure out how many TU's to add to align the
457                 * timestamp then convert to TSF units and handle
458                 * byte swapping before writing it in the frame.
459                 * The hardware will then add this each time a beacon
460                 * frame is sent.  Note that we align vap's 1..N
461                 * and leave vap 0 untouched.  This means vap 0
462                 * has a timestamp in one beacon interval while the
463                 * others get a timestamp aligned to the next interval.
464                 */
465                tsfadjust = (intval * (ATH_BCBUF - avp->av_bslot)) / ATH_BCBUF;
466                tsfadjust = cpu_to_le64(tsfadjust<<10);     /* TU->TSF */
467
468                DPRINTF(sc, ATH_DEBUG_BEACON,
469                        "%s: %s beacons, bslot %d intval %u tsfadjust %llu\n",
470                        __func__, sc->sc_stagbeacons ? "stagger" : "burst",
471                        avp->av_bslot, intval, (unsigned long long)tsfadjust);
472
473                wh = (struct ieee80211_hdr *)skb->data;
474                memcpy(&wh[1], &tsfadjust, sizeof(tsfadjust));
475        }
476
477        bf->bf_buf_addr = ath_skb_map_single(sc, skb, PCI_DMA_TODEVICE,
478                get_dma_mem_context(bf, bf_dmacontext));
479        bf->bf_mpdu = skb;
480
481        return 0;
482}
483
484/*
485 *  Reclaim beacon resources and return buffer to the pool.
486 *
487 *  Checks the VAP to put the beacon frame buffer back to the ATH object
488 *  queue, and de-allocates any wbuf frames that were sent as CAB traffic.
489*/
490
491void ath_beacon_return(struct ath_softc *sc, struct ath_vap *avp)
492{
493        if (avp->av_bcbuf != NULL) {
494                struct ath_buf *bf;
495
496                if (avp->av_bslot != -1) {
497                        sc->sc_bslot[avp->av_bslot] = ATH_IF_ID_ANY;
498                        sc->sc_nbcnvaps--;
499                }
500
501                bf = avp->av_bcbuf;
502                if (bf->bf_mpdu != NULL) {
503                        struct sk_buff *skb = (struct sk_buff *) bf->bf_mpdu;
504                        struct ath_xmit_status tx_status;
505
506                        ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE,
507                                get_dma_mem_context(bf, bf_dmacontext));
508                        tx_status.flags = 0;
509                        tx_status.retries = 0;
510                        ath_tx_complete(sc, skb, &tx_status, NULL);
511                        bf->bf_mpdu = NULL;
512                }
513                list_add_tail(&bf->list, &sc->sc_bbuf);
514
515                avp->av_bcbuf = NULL;
516        }
517}
518
519/*
520 *  Reclaim beacon resources and return buffer to the pool.
521 *
522 *  This function will free any wbuf frames that are still attached to the
523 *  beacon buffers in the ATH object.  Note that this does not de-allocate
524 *  any wbuf objects that are in the transmit queue and have not yet returned
525 *  to the ATH object.
526*/
527
528void ath_beacon_free(struct ath_softc *sc)
529{
530        struct ath_buf *bf;
531
532        list_for_each_entry(bf, &sc->sc_bbuf, list) {
533                if (bf->bf_mpdu != NULL) {
534                        struct sk_buff *skb = (struct sk_buff *) bf->bf_mpdu;
535                        struct ath_xmit_status tx_status;
536
537                        ath_skb_unmap_single(sc, skb, PCI_DMA_TODEVICE,
538                                get_dma_mem_context(bf, bf_dmacontext));
539                        tx_status.flags = 0;
540                        tx_status.retries = 0;
541                        ath_tx_complete(sc, skb, &tx_status, NULL);
542                        bf->bf_mpdu = NULL;
543                }
544        }
545}
546
547/*
548 * Tasklet for Sending Beacons
549 *
550 * Transmit one or more beacon frames at SWBA.  Dynamic updates to the frame
551 * contents are done as needed and the slot time is also adjusted based on
552 * current state.
553 *
554 * This tasklet is not scheduled, it's called in ISR context.
555*/
556
557void ath9k_beacon_tasklet(unsigned long data)
558{
559#define TSF_TO_TU(_h,_l)                                        \
560        ((((u_int32_t)(_h)) << 22) | (((u_int32_t)(_l)) >> 10))
561
562        struct ath_softc *sc = (struct ath_softc *)data;
563        struct ath_hal *ah = sc->sc_ah;
564        struct ath_buf *bf = NULL;
565        int slot, if_id;
566        u_int32_t bfaddr;
567        u_int32_t rx_clear = 0, rx_frame = 0, tx_frame = 0;
568        u_int32_t show_cycles = 0;
569        u_int32_t bc = 0; /* beacon count */
570
571        if (sc->sc_noreset) {
572                show_cycles = ath9k_hw_GetMibCycleCountsPct(ah,
573                                                            &rx_clear,
574                                                            &rx_frame,
575                                                            &tx_frame);
576        }
577
578        /*
579         * Check if the previous beacon has gone out.  If
580         * not don't try to post another, skip this period
581         * and wait for the next.  Missed beacons indicate
582         * a problem and should not occur.  If we miss too
583         * many consecutive beacons reset the device.
584         */
585        if (ath9k_hw_numtxpending(ah, sc->sc_bhalq) != 0) {
586                sc->sc_bmisscount++;
587                /* XXX: doth needs the chanchange IE countdown decremented.
588                 *      We should consider adding a mac80211 call to indicate
589                 *      a beacon miss so appropriate action could be taken
590                 *      (in that layer).
591                 */
592                if (sc->sc_bmisscount < BSTUCK_THRESH) {
593                        if (sc->sc_noreset) {
594                                DPRINTF(sc, ATH_DEBUG_BEACON,
595                                        "%s: missed %u consecutive beacons\n",
596                                        __func__, sc->sc_bmisscount);
597                                if (show_cycles) {
598                                        /*
599                                         * Display cycle counter stats
600                                         * from HW to aide in debug of
601                                         * stickiness.
602                                         */
603                                        DPRINTF(sc,
604                                                ATH_DEBUG_BEACON,
605                                                "%s: busy times: rx_clear=%d, "
606                                                "rx_frame=%d, tx_frame=%d\n",
607                                                __func__, rx_clear, rx_frame,
608                                                tx_frame);
609                                } else {
610                                        DPRINTF(sc,
611                                                ATH_DEBUG_BEACON,
612                                                "%s: unable to obtain "
613                                                "busy times\n", __func__);
614                                }
615                        } else {
616                                DPRINTF(sc, ATH_DEBUG_BEACON,
617                                        "%s: missed %u consecutive beacons\n",
618                                        __func__, sc->sc_bmisscount);
619                        }
620                } else if (sc->sc_bmisscount >= BSTUCK_THRESH) {
621                        if (sc->sc_noreset) {
622                                if (sc->sc_bmisscount == BSTUCK_THRESH) {
623                                        DPRINTF(sc,
624                                                ATH_DEBUG_BEACON,
625                                                "%s: beacon is officially "
626                                                "stuck\n", __func__);
627                                        ath9k_hw_dmaRegDump(ah);
628                                }
629                        } else {
630                                DPRINTF(sc, ATH_DEBUG_BEACON,
631                                        "%s: beacon is officially stuck\n",
632                                        __func__);
633                                ath_bstuck_process(sc);
634                        }
635                }
636
637                return;
638        }
639        if (sc->sc_bmisscount != 0) {
640                if (sc->sc_noreset) {
641                        DPRINTF(sc,
642                                ATH_DEBUG_BEACON,
643                                "%s: resume beacon xmit after %u misses\n",
644                                __func__, sc->sc_bmisscount);
645                } else {
646                        DPRINTF(sc, ATH_DEBUG_BEACON,
647                                "%s: resume beacon xmit after %u misses\n",
648                                __func__, sc->sc_bmisscount);
649                }
650                sc->sc_bmisscount = 0;
651        }
652
653        /*
654         * Generate beacon frames.  If we are sending frames
655         * staggered then calculate the slot for this frame based
656         * on the tsf to safeguard against missing an swba.
657         * Otherwise we are bursting all frames together and need
658         * to generate a frame for each vap that is up and running.
659         */
660        if (sc->sc_stagbeacons) {
661                /* staggered beacons */
662                u_int64_t tsf;
663                u_int32_t tsftu;
664                u_int16_t intval;
665
666                /* FIXME: Use default value for now - Sujith */
667                intval = ATH_DEFAULT_BINTVAL;
668
669                tsf = ath9k_hw_gettsf64(ah);
670                tsftu = TSF_TO_TU(tsf>>32, tsf);
671                slot = ((tsftu % intval) * ATH_BCBUF) / intval;
672                if_id = sc->sc_bslot[(slot + 1) % ATH_BCBUF];
673                DPRINTF(sc, ATH_DEBUG_BEACON,
674                        "%s: slot %d [tsf %llu tsftu %u intval %u] if_id %d\n",
675                        __func__, slot, (unsigned long long) tsf, tsftu,
676                        intval, if_id);
677                bfaddr = 0;
678                if (if_id != ATH_IF_ID_ANY) {
679                        bf = ath_beacon_generate(sc, if_id);
680                        if (bf != NULL) {
681                                bfaddr = bf->bf_daddr;
682                                bc = 1;
683                        }
684                }
685        } else {
686                /* XXX: Clean this up, move work to a helper */
687                /* burst'd beacons */
688                u_int32_t *bflink;
689                bflink = &bfaddr;
690                /* XXX rotate/randomize order? */
691                for (slot = 0; slot < ATH_BCBUF; slot++) {
692                        if_id = sc->sc_bslot[slot];
693                        if (if_id != ATH_IF_ID_ANY) {
694                                bf = ath_beacon_generate(sc, if_id);
695                                if (bf != NULL) {
696                                        if (bflink != &bfaddr)
697                                                *bflink = cpu_to_le32(
698                                                        bf->bf_daddr);
699                                        else
700                                                *bflink = bf->bf_daddr;
701                                        bflink = &bf->bf_desc->ds_link;
702                                        bc++;
703                                }
704                        }
705                }
706                *bflink = 0;    /* link of last frame */
707        }
708        /*
709         * Handle slot time change when a non-ERP station joins/leaves
710         * an 11g network.  The 802.11 layer notifies us via callback,
711         * we mark updateslot, then wait one beacon before effecting
712         * the change.  This gives associated stations at least one
713         * beacon interval to note the state change.
714         *
715         * NB: The slot time change state machine is clocked according
716         *     to whether we are bursting or staggering beacons.  We
717         *     recognize the request to update and record the current
718         *     slot then don't transition until that slot is reached
719         *     again.  If we miss a beacon for that slot then we'll be
720         *     slow to transition but we'll be sure at least one beacon
721         *     interval has passed.  When bursting slot is always left
722         *     set to ATH_BCBUF so this check is a noop.
723         */
724        /* XXX locking */
725        if (sc->sc_updateslot == UPDATE) {
726                sc->sc_updateslot = COMMIT; /* commit next beacon */
727                sc->sc_slotupdate = slot;
728        } else if (sc->sc_updateslot == COMMIT && sc->sc_slotupdate == slot)
729                ath_setslottime(sc);        /* commit change to hardware */
730
731        if ((!sc->sc_stagbeacons || slot == 0) && (!sc->sc_diversity)) {
732                int otherant;
733                /*
734                 * Check recent per-antenna transmit statistics and flip
735                 * the default rx antenna if noticeably more frames went out
736                 * on the non-default antenna.  Only do this if rx diversity
737                 * is off.
738                 * XXX assumes 2 anntenae
739                 */
740                otherant = sc->sc_defant & 1 ? 2 : 1;
741                if (sc->sc_ant_tx[otherant] > sc->sc_ant_tx[sc->sc_defant] +
742                        ATH_ANTENNA_DIFF) {
743                        DPRINTF(sc, ATH_DEBUG_BEACON,
744                                "%s: flip defant to %u, %u > %u\n",
745                                __func__, otherant, sc->sc_ant_tx[otherant],
746                                sc->sc_ant_tx[sc->sc_defant]);
747                        ath_setdefantenna(sc, otherant);
748                }
749                sc->sc_ant_tx[1] = sc->sc_ant_tx[2] = 0;
750        }
751
752        if (bfaddr != 0) {
753                /*
754                 * Stop any current dma and put the new frame(s) on the queue.
755                 * This should never fail since we check above that no frames
756                 * are still pending on the queue.
757                 */
758                if (!ath9k_hw_stoptxdma(ah, sc->sc_bhalq)) {
759                        DPRINTF(sc, ATH_DEBUG_FATAL,
760                                "%s: beacon queue %u did not stop?\n",
761                                __func__, sc->sc_bhalq);
762                        /* NB: the HAL still stops DMA, so proceed */
763                }
764
765                /* NB: cabq traffic should already be queued and primed */
766                ath9k_hw_puttxbuf(ah, sc->sc_bhalq, bfaddr);
767                ath9k_hw_txstart(ah, sc->sc_bhalq);
768
769                sc->ast_be_xmit += bc;     /* XXX per-vap? */
770        }
771#undef TSF_TO_TU
772}
773
774/*
775 *  Tasklet for Beacon Stuck processing
776 *
777 *  Processing for Beacon Stuck.
778 *  Basically calls the ath_internal_reset function to reset the chip.
779*/
780
781void ath_bstuck_process(struct ath_softc *sc)
782{
783        DPRINTF(sc, ATH_DEBUG_BEACON,
784                "%s: stuck beacon; resetting (bmiss count %u)\n",
785                __func__, sc->sc_bmisscount);
786        ath_internal_reset(sc);
787}
788
789/*
790 * Configure the beacon and sleep timers.
791 *
792 * When operating as an AP this resets the TSF and sets
793 * up the hardware to notify us when we need to issue beacons.
794 *
795 * When operating in station mode this sets up the beacon
796 * timers according to the timestamp of the last received
797 * beacon and the current TSF, configures PCF and DTIM
798 * handling, programs the sleep registers so the hardware
799 * will wakeup in time to receive beacons, and configures
800 * the beacon miss handling so we'll receive a BMISS
801 * interrupt when we stop seeing beacons from the AP
802 * we've associated with.
803 */
804
805void ath_beacon_config(struct ath_softc *sc, int if_id)
806{
807#define TSF_TO_TU(_h,_l)                                        \
808        ((((u_int32_t)(_h)) << 22) | (((u_int32_t)(_l)) >> 10))
809        struct ath_hal *ah = sc->sc_ah;
810        u_int32_t nexttbtt, intval;
811        struct ath_beacon_config conf;
812        enum hal_opmode av_opmode;
813
814        if (if_id != ATH_IF_ID_ANY)
815                av_opmode = sc->sc_vaps[if_id]->av_opmode;
816        else
817                av_opmode = sc->sc_opmode;
818
819        memzero(&conf, sizeof(struct ath_beacon_config));
820
821        /* FIXME: Use default values for now - Sujith */
822        /* Query beacon configuration first */
823        /*
824         * Protocol stack doesn't support dynamic beacon configuration,
825         * use default configurations.
826         */
827        conf.beacon_interval = ATH_DEFAULT_BINTVAL;
828        conf.listen_interval = 1;
829        conf.dtim_period = conf.beacon_interval;
830        conf.dtim_count = 1;
831        conf.bmiss_timeout = ATH_DEFAULT_BMISS_LIMIT * conf.beacon_interval;
832
833        /* extract tstamp from last beacon and convert to TU */
834        nexttbtt = TSF_TO_TU(LE_READ_4(conf.u.last_tstamp + 4),
835                             LE_READ_4(conf.u.last_tstamp));
836        /* XXX conditionalize multi-bss support? */
837        if (sc->sc_opmode == HAL_M_HOSTAP) {
838                /*
839                 * For multi-bss ap support beacons are either staggered
840                 * evenly over N slots or burst together.  For the former
841                 * arrange for the SWBA to be delivered for each slot.
842                 * Slots that are not occupied will generate nothing.
843                 */
844                /* NB: the beacon interval is kept internally in TU's */
845                intval = conf.beacon_interval & HAL_BEACON_PERIOD;
846                if (sc->sc_stagbeacons)
847                        intval /= ATH_BCBUF;    /* for staggered beacons */
848                if ((sc->sc_nostabeacons) &&
849                    (av_opmode == HAL_M_HOSTAP))
850                        nexttbtt = 0;
851        } else {
852                intval = conf.beacon_interval & HAL_BEACON_PERIOD;
853        }
854
855        if (nexttbtt == 0)      /* e.g. for ap mode */
856                nexttbtt = intval;
857        else if (intval)        /* NB: can be 0 for monitor mode */
858                nexttbtt = roundup(nexttbtt, intval);
859        DPRINTF(sc, ATH_DEBUG_BEACON, "%s: nexttbtt %u intval %u (%u)\n",
860                __func__, nexttbtt, intval, conf.beacon_interval);
861        /* Check for HAL_M_HOSTAP and sc_nostabeacons for WDS client */
862        if ((sc->sc_opmode == HAL_M_STA) ||
863             ((sc->sc_opmode == HAL_M_HOSTAP) &&
864              (av_opmode == HAL_M_STA) &&
865              (sc->sc_nostabeacons))) {
866                struct hal_beacon_state bs;
867                u_int64_t tsf;
868                u_int32_t tsftu;
869                int dtimperiod, dtimcount, sleepduration;
870                int cfpperiod, cfpcount;
871
872                /*
873                 * Setup dtim and cfp parameters according to
874                 * last beacon we received (which may be none).
875                 */
876                dtimperiod = conf.dtim_period;
877                if (dtimperiod <= 0)        /* NB: 0 if not known */
878                        dtimperiod = 1;
879                dtimcount = conf.dtim_count;
880                if (dtimcount >= dtimperiod)    /* NB: sanity check */
881                        dtimcount = 0;      /* XXX? */
882                cfpperiod = 1;          /* NB: no PCF support yet */
883                cfpcount = 0;
884
885                sleepduration = conf.listen_interval * intval;
886                if (sleepduration <= 0)
887                        sleepduration = intval;
888
889#define FUDGE   2
890                /*
891                 * Pull nexttbtt forward to reflect the current
892                 * TSF and calculate dtim+cfp state for the result.
893                 */
894                tsf = ath9k_hw_gettsf64(ah);
895                tsftu = TSF_TO_TU(tsf>>32, tsf) + FUDGE;
896                do {
897                        nexttbtt += intval;
898                        if (--dtimcount < 0) {
899                                dtimcount = dtimperiod - 1;
900                                if (--cfpcount < 0)
901                                        cfpcount = cfpperiod - 1;
902                        }
903                } while (nexttbtt < tsftu);
904#undef FUDGE
905                memzero(&bs, sizeof(bs));
906                bs.bs_intval = intval;
907                bs.bs_nexttbtt = nexttbtt;
908                bs.bs_dtimperiod = dtimperiod*intval;
909                bs.bs_nextdtim = bs.bs_nexttbtt + dtimcount*intval;
910                bs.bs_cfpperiod = cfpperiod*bs.bs_dtimperiod;
911                bs.bs_cfpnext = bs.bs_nextdtim + cfpcount*bs.bs_dtimperiod;
912                bs.bs_cfpmaxduration = 0;
913                /*
914                 * Calculate the number of consecutive beacons to miss
915                 * before taking a BMISS interrupt.  The configuration
916                 * is specified in TU so we only need calculate based
917                 * on the beacon interval.  Note that we clamp the
918                 * result to at most 15 beacons.
919                 */
920                if (sleepduration > intval) {
921                        bs.bs_bmissthreshold =
922                                conf.listen_interval *
923                                        ATH_DEFAULT_BMISS_LIMIT / 2;
924                } else {
925                        bs.bs_bmissthreshold =
926                                howmany(conf.bmiss_timeout, intval);
927                        if (bs.bs_bmissthreshold > 15)
928                                bs.bs_bmissthreshold = 15;
929                        else if (bs.bs_bmissthreshold <= 0)
930                                bs.bs_bmissthreshold = 1;
931                }
932
933                /*
934                 * Calculate sleep duration.  The configuration is
935                 * given in ms.  We insure a multiple of the beacon
936                 * period is used.  Also, if the sleep duration is
937                 * greater than the DTIM period then it makes senses
938                 * to make it a multiple of that.
939                 *
940                 * XXX fixed at 100ms
941                 */
942
943                bs.bs_sleepduration =
944                        roundup(IEEE80211_MS_TO_TU(100), sleepduration);
945                if (bs.bs_sleepduration > bs.bs_dtimperiod)
946                        bs.bs_sleepduration = bs.bs_dtimperiod;
947
948                DPRINTF(sc, ATH_DEBUG_BEACON,
949                        "%s: tsf %llu "
950                        "tsf:tu %u "
951                        "intval %u "
952                        "nexttbtt %u "
953                        "dtim %u "
954                        "nextdtim %u "
955                        "bmiss %u "
956                        "sleep %u "
957                        "cfp:period %u "
958                        "maxdur %u "
959                        "next %u "
960                        "timoffset %u\n"
961                        , __func__
962                        , (unsigned long long)tsf, tsftu
963                        , bs.bs_intval
964                        , bs.bs_nexttbtt
965                        , bs.bs_dtimperiod
966                        , bs.bs_nextdtim
967                        , bs.bs_bmissthreshold
968                        , bs.bs_sleepduration
969                        , bs.bs_cfpperiod
970                        , bs.bs_cfpmaxduration
971                        , bs.bs_cfpnext
972                        , bs.bs_timoffset
973                        );
974
975                if (!(sc->sc_nostabeacons)) {
976                        ath9k_hw_set_interrupts(ah, 0);
977                        ath9k_hw_set_sta_beacon_timers(ah, &bs);
978                        sc->sc_imask |= HAL_INT_BMISS;
979                        ath9k_hw_set_interrupts(ah, sc->sc_imask);
980                }
981        } else {
982                u_int64_t tsf;
983                u_int32_t tsftu;
984                ath9k_hw_set_interrupts(ah, 0);
985                if (nexttbtt == intval)
986                        intval |= HAL_BEACON_RESET_TSF;
987                if (sc->sc_opmode == HAL_M_IBSS) {
988                        /*
989                         * Pull nexttbtt forward to reflect the current
990                         * TSF .
991                         */
992#define FUDGE   2
993                        if (!(intval & HAL_BEACON_RESET_TSF)) {
994                                tsf = ath9k_hw_gettsf64(ah);
995                                tsftu = TSF_TO_TU((u_int32_t)(tsf>>32),
996                                        (u_int32_t)tsf) + FUDGE;
997                                do {
998                                        nexttbtt += intval;
999                                } while (nexttbtt < tsftu);
1000                        }
1001#undef FUDGE
1002                        DPRINTF(sc, ATH_DEBUG_BEACON,
1003                                "%s: IBSS nexttbtt %u intval %u (%u)\n",
1004                                __func__, nexttbtt,
1005                                intval & ~HAL_BEACON_RESET_TSF,
1006                                conf.beacon_interval);
1007
1008                        /*
1009                         * In IBSS mode enable the beacon timers but only
1010                         * enable SWBA interrupts if we need to manually
1011                         * prepare beacon frames.  Otherwise we use a
1012                         * self-linked tx descriptor and let the hardware
1013                         * deal with things.
1014                         */
1015                        intval |= HAL_BEACON_ENA;
1016                        if (!sc->sc_hasveol)
1017                                sc->sc_imask |= HAL_INT_SWBA;
1018                        ath_beaconq_config(sc);
1019                } else if (sc->sc_opmode == HAL_M_HOSTAP) {
1020                        /*
1021                         * In AP mode we enable the beacon timers and
1022                         * SWBA interrupts to prepare beacon frames.
1023                         */
1024                        intval |= HAL_BEACON_ENA;
1025                        sc->sc_imask |= HAL_INT_SWBA;   /* beacon prepare */
1026                        ath_beaconq_config(sc);
1027                }
1028                ath9k_hw_beaconinit(ah, nexttbtt, intval);
1029                sc->sc_bmisscount = 0;
1030                ath9k_hw_set_interrupts(ah, sc->sc_imask);
1031                /*
1032                 * When using a self-linked beacon descriptor in
1033                 * ibss mode load it once here.
1034                 */
1035                if (sc->sc_opmode == HAL_M_IBSS && sc->sc_hasveol)
1036                        ath_beacon_start_adhoc(sc, 0);
1037        }
1038#undef TSF_TO_TU
1039}
1040
1041/* Function to collect beacon rssi data and resync beacon if necessary */
1042
1043void ath_beacon_sync(struct ath_softc *sc, int if_id)
1044{
1045        /*
1046         * Resync beacon timers using the tsf of the
1047         * beacon frame we just received.
1048         */
1049        ath_beacon_config(sc, if_id);
1050        sc->sc_beacons = 1;
1051}
Note: See TracBrowser for help on using the repository browser.