/* * Associates the beacon frame buffer with a transmit descriptor. Will set * up all required antenna switch parameters, rate codes, and channel flags. * Beacons are always sent out at the lowest rate, and are not retried. */ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp, struct ath_buf *bf, int rateidx) { struct sk_buff *skb = bf->bf_mpdu; struct ath_hw *ah = sc->sc_ah; struct ath_common *common = ath9k_hw_common(ah); struct ath_desc *ds; struct ath9k_11n_rate_series series[4]; int flags, antenna, ctsrate = 0, ctsduration = 0; struct ieee80211_supported_band *sband; u8 rate = 0; ds = bf->bf_desc; flags = ATH9K_TXDESC_NOACK; ds->ds_link = 0; /* * Switch antenna every beacon. * Should only switch every beacon period, not for every SWBA * XXX assumes two antennae */ antenna = ((sc->beacon.ast_be_xmit / sc->nbcnvifs) & 1 ? 2 : 1); sband = &sc->sbands[common->hw->conf.channel->band]; rate = sband->bitrates[rateidx].hw_value; if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) rate |= sband->bitrates[rateidx].hw_value_short; ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN, ATH9K_PKT_TYPE_BEACON, MAX_RATE_POWER, ATH9K_TXKEYIX_INVALID, ATH9K_KEY_TYPE_CLEAR, flags); /* NB: beacon's BufLen must be a multiple of 4 bytes */ ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4), true, true, ds, bf->bf_buf_addr, sc->beacon.beaconq); memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); series[0].Tries = 1; series[0].Rate = rate; 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); }
/* * Setup the beacon frame for transmit. * * Associates the beacon frame buffer with a transmit descriptor. Will set * up all required antenna switch parameters, rate codes, and channel flags. * Beacons are always sent out at the lowest rate, and are not retried. */ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vap *avp, struct ath_buf *bf) { struct sk_buff *skb = (struct sk_buff *)bf->bf_mpdu; struct ath_hal *ah = sc->sc_ah; struct ath_desc *ds; struct ath9k_11n_rate_series series[4]; const struct ath9k_rate_table *rt; int flags, antenna; u8 rix, rate; int ctsrate = 0; int ctsduration = 0; DPRINTF(sc, ATH_DBG_BEACON, "%s: m %p len %u\n", __func__, skb, skb->len); /* setup descriptors */ ds = bf->bf_desc; flags = ATH9K_TXDESC_NOACK; if (sc->sc_ah->ah_opmode == ATH9K_M_IBSS && (ah->ah_caps.hw_caps & ATH9K_HW_CAP_VEOL)) { ds->ds_link = bf->bf_daddr; /* self-linked */ flags |= ATH9K_TXDESC_VEOL; /* Let hardware handle antenna switching. */ antenna = 0; } else { ds->ds_link = 0; /* * Switch antenna every beacon. * Should only switch every beacon period, not for every * SWBA's * XXX assumes two antenna */ antenna = ((sc->ast_be_xmit / sc->sc_nbcnvaps) & 1 ? 2 : 1); } ds->ds_data = bf->bf_buf_addr; /* * Calculate rate code. * XXX everything at min xmit rate */ rix = 0; rt = sc->sc_currates; rate = rt->info[rix].rateCode; if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) rate |= rt->info[rix].shortPreamble; ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN, /* frame length */ ATH9K_PKT_TYPE_BEACON, /* Atheros packet type */ avp->av_btxctl.txpower, /* txpower XXX */ ATH9K_TXKEYIX_INVALID, /* no encryption */ ATH9K_KEY_TYPE_CLEAR, /* no encryption */ flags /* no ack, veol for beacons */ ); /* NB: beacon's BufLen must be a multiple of 4 bytes */ ath9k_hw_filltxdesc(ah, ds, roundup(skb->len, 4), /* buffer length */ true, /* first segment */ true, /* last segment */ ds /* first descriptor */ ); memset(series, 0, sizeof(struct ath9k_11n_rate_series) * 4); series[0].Tries = 1; series[0].Rate = rate; series[0].ChSel = sc->sc_tx_chainmask; series[0].RateFlags = (ctsrate) ? ATH9K_RATESERIES_RTS_CTS : 0; ath9k_hw_set11n_ratescenario(ah, ds, ds, 0, ctsrate, ctsduration, series, 4, 0); }