]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/net/wireless/ath/ath9k/beacon.c
Merge tag 'v2.6.38' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6
[mv-sheeva.git] / drivers / net / wireless / ath / ath9k / beacon.c
index 19891e7d49aea7e371cfaf43d0228013f03e313e..385ba03134ba1b100ae2c3419f7690d898c74f25 100644 (file)
@@ -28,7 +28,7 @@ int ath_beaconq_config(struct ath_softc *sc)
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
        struct ath9k_tx_queue_info qi, qi_be;
-       int qnum;
+       struct ath_txq *txq;
 
        ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
        if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
@@ -38,16 +38,16 @@ int ath_beaconq_config(struct ath_softc *sc)
                qi.tqi_cwmax = 0;
        } else {
                /* Adhoc mode; important thing is to use 2x cwmin. */
-               qnum = sc->tx.hwq_map[WME_AC_BE];
-               ath9k_hw_get_txq_props(ah, qnum, &qi_be);
+               txq = sc->tx.txq_map[WME_AC_BE];
+               ath9k_hw_get_txq_props(ah, txq->axq_qnum, &qi_be);
                qi.tqi_aifs = qi_be.tqi_aifs;
                qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
                qi.tqi_cwmax = qi_be.tqi_cwmax;
        }
 
        if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) {
-               ath_print(common, ATH_DBG_FATAL,
-                         "Unable to update h/w beacon queue parameters\n");
+               ath_err(common,
+                       "Unable to update h/w beacon queue parameters\n");
                return 0;
        } else {
                ath9k_hw_resettxqueue(ah, sc->beacon.beaconq);
@@ -103,12 +103,32 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
        memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4);
        series[0].Tries = 1;
        series[0].Rate = rate;
-       series[0].ChSel = common->tx_chainmask;
+       series[0].ChSel = ath_txchainmask_reduction(sc,
+                       common->tx_chainmask, series[0].Rate);
        series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0;
        ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration,
                                     series, 4, 0);
 }
 
+static void ath_tx_cabq(struct ieee80211_hw *hw, struct sk_buff *skb)
+{
+       struct ath_wiphy *aphy = hw->priv;
+       struct ath_softc *sc = aphy->sc;
+       struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+       struct ath_tx_control txctl;
+
+       memset(&txctl, 0, sizeof(struct ath_tx_control));
+       txctl.txq = sc->beacon.cabq;
+
+       ath_dbg(common, ATH_DBG_XMIT,
+               "transmitting CABQ packet, skb: %p\n", skb);
+
+       if (ath_tx_start(hw, skb, &txctl) != 0) {
+               ath_dbg(common, ATH_DBG_XMIT, "CABQ TX failed\n");
+               dev_kfree_skb_any(skb);
+       }
+}
+
 static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
                                           struct ieee80211_vif *vif)
 {
@@ -169,8 +189,7 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
                dev_kfree_skb_any(skb);
                bf->bf_mpdu = NULL;
                bf->bf_buf_addr = 0;
-               ath_print(common, ATH_DBG_FATAL,
-                         "dma_mapping_error on beaconing\n");
+               ath_err(common, "dma_mapping_error on beaconing\n");
                return NULL;
        }
 
@@ -190,8 +209,8 @@ static struct ath_buf *ath_beacon_generate(struct ieee80211_hw *hw,
 
        if (skb && cabq_depth) {
                if (sc->nvifs > 1) {
-                       ath_print(common, ATH_DBG_BEACON,
-                                 "Flushing previous cabq traffic\n");
+                       ath_dbg(common, ATH_DBG_BEACON,
+                               "Flushing previous cabq traffic\n");
                        ath_draintxq(sc, cabq, false);
                }
        }
@@ -263,7 +282,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
        /* NB: the beacon data buffer must be 32-bit aligned. */
        skb = ieee80211_beacon_get(sc->hw, vif);
        if (skb == NULL) {
-               ath_print(common, ATH_DBG_BEACON, "cannot get skb\n");
+               ath_dbg(common, ATH_DBG_BEACON, "cannot get skb\n");
                return -ENOMEM;
        }
 
@@ -287,10 +306,9 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
                tsfadjust = intval * avp->av_bslot / ATH_BCBUF;
                avp->tsf_adjust = cpu_to_le64(TU_TO_USEC(tsfadjust));
 
-               ath_print(common, ATH_DBG_BEACON,
-                         "stagger beacons, bslot %d intval "
-                         "%u tsfadjust %llu\n",
-                         avp->av_bslot, intval, (unsigned long long)tsfadjust);
+               ath_dbg(common, ATH_DBG_BEACON,
+                       "stagger beacons, bslot %d intval %u tsfadjust %llu\n",
+                       avp->av_bslot, intval, (unsigned long long)tsfadjust);
 
                ((struct ieee80211_mgmt *)skb->data)->u.beacon.timestamp =
                        avp->tsf_adjust;
@@ -304,8 +322,7 @@ int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif)
                dev_kfree_skb_any(skb);
                bf->bf_mpdu = NULL;
                bf->bf_buf_addr = 0;
-               ath_print(common, ATH_DBG_FATAL,
-                         "dma_mapping_error on beacon alloc\n");
+               ath_err(common, "dma_mapping_error on beacon alloc\n");
                return -ENOMEM;
        }
 
@@ -362,13 +379,13 @@ void ath_beacon_tasklet(unsigned long data)
                sc->beacon.bmisscnt++;
 
                if (sc->beacon.bmisscnt < BSTUCK_THRESH) {
-                       ath_print(common, ATH_DBG_BSTUCK,
-                                 "missed %u consecutive beacons\n",
-                                 sc->beacon.bmisscnt);
+                       ath_dbg(common, ATH_DBG_BSTUCK,
+                               "missed %u consecutive beacons\n",
+                               sc->beacon.bmisscnt);
                        ath9k_hw_bstuck_nfcal(ah);
                } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
-                       ath_print(common, ATH_DBG_BSTUCK,
-                                 "beacon is officially stuck\n");
+                       ath_dbg(common, ATH_DBG_BSTUCK,
+                               "beacon is officially stuck\n");
                        sc->sc_flags |= SC_OP_TSF_RESET;
                        ath_reset(sc, true);
                }
@@ -377,9 +394,9 @@ void ath_beacon_tasklet(unsigned long data)
        }
 
        if (sc->beacon.bmisscnt != 0) {
-               ath_print(common, ATH_DBG_BSTUCK,
-                         "resume beacon xmit after %u misses\n",
-                         sc->beacon.bmisscnt);
+               ath_dbg(common, ATH_DBG_BSTUCK,
+                       "resume beacon xmit after %u misses\n",
+                       sc->beacon.bmisscnt);
                sc->beacon.bmisscnt = 0;
        }
 
@@ -405,9 +422,9 @@ void ath_beacon_tasklet(unsigned long data)
        vif = sc->beacon.bslot[slot];
        aphy = sc->beacon.bslot_aphy[slot];
 
-       ath_print(common, ATH_DBG_BEACON,
-                 "slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
-                 slot, tsf, tsftu, intval, vif);
+       ath_dbg(common, ATH_DBG_BEACON,
+               "slot %d [tsf %llu tsftu %u intval %u] vif %p\n",
+               slot, tsf, tsftu, intval, vif);
 
        bfaddr = 0;
        if (vif) {
@@ -449,8 +466,8 @@ void ath_beacon_tasklet(unsigned long data)
                 * are still pending on the queue.
                 */
                if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) {
-                       ath_print(common, ATH_DBG_FATAL,
-                               "beacon queue %u did not stop?\n", sc->beacon.beaconq);
+                       ath_err(common, "beacon queue %u did not stop?\n",
+                               sc->beacon.beaconq);
                }
 
                /* NB: cabq traffic should already be queued and primed */
@@ -503,7 +520,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc,
 
        /* Set the computed AP beacon timers */
 
-       ath9k_hw_set_interrupts(ah, 0);
+       ath9k_hw_disable_interrupts(ah);
        ath9k_beacon_init(sc, nexttbtt, intval);
        sc->beacon.bmisscnt = 0;
        ath9k_hw_set_interrupts(ah, ah->imask);
@@ -536,8 +553,8 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
 
        /* No need to configure beacon if we are not associated */
        if (!common->curaid) {
-               ath_print(common, ATH_DBG_BEACON,
-                        "STA is not yet associated..skipping beacon config\n");
+               ath_dbg(common, ATH_DBG_BEACON,
+                       "STA is not yet associated..skipping beacon config\n");
                return;
        }
 
@@ -549,8 +566,6 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
         * last beacon we received (which may be none).
         */
        dtimperiod = conf->dtim_period;
-       if (dtimperiod <= 0)            /* NB: 0 if not known */
-               dtimperiod = 1;
        dtimcount = conf->dtim_count;
        if (dtimcount >= dtimperiod)    /* NB: sanity check */
                dtimcount = 0;
@@ -558,8 +573,6 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
        cfpcount = 0;
 
        sleepduration = conf->listen_interval * intval;
-       if (sleepduration <= 0)
-               sleepduration = intval;
 
        /*
         * Pull nexttbtt forward to reflect the current
@@ -630,23 +643,22 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
        /* TSF out of range threshold fixed at 1 second */
        bs.bs_tsfoor_threshold = ATH9K_TSFOOR_THRESHOLD;
 
-       ath_print(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
-       ath_print(common, ATH_DBG_BEACON,
-                 "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
-                 bs.bs_bmissthreshold, bs.bs_sleepduration,
-                 bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
+       ath_dbg(common, ATH_DBG_BEACON, "tsf: %llu tsftu: %u\n", tsf, tsftu);
+       ath_dbg(common, ATH_DBG_BEACON,
+               "bmiss: %u sleep: %u cfp-period: %u maxdur: %u next: %u\n",
+               bs.bs_bmissthreshold, bs.bs_sleepduration,
+               bs.bs_cfpperiod, bs.bs_cfpmaxduration, bs.bs_cfpnext);
 
        /* Set the computed STA beacon timers */
 
-       ath9k_hw_set_interrupts(ah, 0);
+       ath9k_hw_disable_interrupts(ah);
        ath9k_hw_set_sta_beacon_timers(ah, &bs);
        ah->imask |= ATH9K_INT_BMISS;
        ath9k_hw_set_interrupts(ah, ah->imask);
 }
 
 static void ath_beacon_config_adhoc(struct ath_softc *sc,
-                                   struct ath_beacon_config *conf,
-                                   struct ieee80211_vif *vif)
+                                   struct ath_beacon_config *conf)
 {
        struct ath_hw *ah = sc->sc_ah;
        struct ath_common *common = ath9k_hw_common(ah);
@@ -670,9 +682,9 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
                nexttbtt += intval;
        } while (nexttbtt < tsftu);
 
-       ath_print(common, ATH_DBG_BEACON,
-                 "IBSS nexttbtt %u intval %u (%u)\n",
-                 nexttbtt, intval, conf->beacon_interval);
+       ath_dbg(common, ATH_DBG_BEACON,
+               "IBSS nexttbtt %u intval %u (%u)\n",
+               nexttbtt, intval, conf->beacon_interval);
 
        /*
         * In IBSS mode enable the beacon timers but only enable SWBA interrupts
@@ -686,7 +698,7 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
 
        /* Set the computed ADHOC beacon timers */
 
-       ath9k_hw_set_interrupts(ah, 0);
+       ath9k_hw_disable_interrupts(ah);
        ath9k_beacon_init(sc, nexttbtt, intval);
        sc->beacon.bmisscnt = 0;
        ath9k_hw_set_interrupts(ah, ah->imask);
@@ -701,18 +713,17 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
        /* Setup the beacon configuration parameters */
        if (vif) {
                struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
-
                iftype = vif->type;
-
                cur_conf->beacon_interval = bss_conf->beacon_int;
                cur_conf->dtim_period = bss_conf->dtim_period;
+       } else {
+               iftype = sc->sc_ah->opmode;
+       }
+
                cur_conf->listen_interval = 1;
                cur_conf->dtim_count = 1;
                cur_conf->bmiss_timeout =
                        ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
-       } else {
-               iftype = sc->sc_ah->opmode;
-       }
 
        /*
         * It looks like mac80211 may end up using beacon interval of zero in
@@ -723,20 +734,27 @@ void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif)
        if (cur_conf->beacon_interval == 0)
                cur_conf->beacon_interval = 100;
 
+       /*
+        * Some times we dont parse dtim period from mac80211, in that case
+        * use a default value
+        */
+       if (cur_conf->dtim_period == 0)
+               cur_conf->dtim_period = 1;
+
        switch (iftype) {
        case NL80211_IFTYPE_AP:
                ath_beacon_config_ap(sc, cur_conf);
                break;
        case NL80211_IFTYPE_ADHOC:
        case NL80211_IFTYPE_MESH_POINT:
-               ath_beacon_config_adhoc(sc, cur_conf, vif);
+               ath_beacon_config_adhoc(sc, cur_conf);
                break;
        case NL80211_IFTYPE_STATION:
                ath_beacon_config_sta(sc, cur_conf);
                break;
        default:
-               ath_print(common, ATH_DBG_CONFIG,
-                         "Unsupported beaconing mode\n");
+               ath_dbg(common, ATH_DBG_CONFIG,
+                       "Unsupported beaconing mode\n");
                return;
        }