1db86f07eSLuis R. Rodriguez /*
25b68138eSSujith Manoharan * Copyright (c) 2009-2011 Atheros Communications Inc.
3db86f07eSLuis R. Rodriguez *
4db86f07eSLuis R. Rodriguez * Permission to use, copy, modify, and/or distribute this software for any
5db86f07eSLuis R. Rodriguez * purpose with or without fee is hereby granted, provided that the above
6db86f07eSLuis R. Rodriguez * copyright notice and this permission notice appear in all copies.
7db86f07eSLuis R. Rodriguez *
8db86f07eSLuis R. Rodriguez * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9db86f07eSLuis R. Rodriguez * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10db86f07eSLuis R. Rodriguez * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11db86f07eSLuis R. Rodriguez * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12db86f07eSLuis R. Rodriguez * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13db86f07eSLuis R. Rodriguez * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14db86f07eSLuis R. Rodriguez * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15db86f07eSLuis R. Rodriguez */
16db86f07eSLuis R. Rodriguez
17db86f07eSLuis R. Rodriguez /*
18db86f07eSLuis R. Rodriguez * Module for common driver code between ath9k and ath9k_htc
19db86f07eSLuis R. Rodriguez */
20db86f07eSLuis R. Rodriguez
21db86f07eSLuis R. Rodriguez #include <linux/kernel.h>
22db86f07eSLuis R. Rodriguez #include <linux/module.h>
23db86f07eSLuis R. Rodriguez
24db86f07eSLuis R. Rodriguez #include "common.h"
25db86f07eSLuis R. Rodriguez
26db86f07eSLuis R. Rodriguez MODULE_AUTHOR("Atheros Communications");
27db86f07eSLuis R. Rodriguez MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards.");
28db86f07eSLuis R. Rodriguez MODULE_LICENSE("Dual BSD/GPL");
29db86f07eSLuis R. Rodriguez
306438696eSOleksij Rempel /* Assumes you've already done the endian to CPU conversion */
ath9k_cmn_rx_accept(struct ath_common * common,struct ieee80211_hdr * hdr,struct ieee80211_rx_status * rxs,struct ath_rx_status * rx_stats,bool * decrypt_error,unsigned int rxfilter)316438696eSOleksij Rempel bool ath9k_cmn_rx_accept(struct ath_common *common,
326438696eSOleksij Rempel struct ieee80211_hdr *hdr,
336438696eSOleksij Rempel struct ieee80211_rx_status *rxs,
346438696eSOleksij Rempel struct ath_rx_status *rx_stats,
356438696eSOleksij Rempel bool *decrypt_error,
366438696eSOleksij Rempel unsigned int rxfilter)
376438696eSOleksij Rempel {
386438696eSOleksij Rempel struct ath_hw *ah = common->ah;
396438696eSOleksij Rempel bool is_mc, is_valid_tkip, strip_mic, mic_error;
406438696eSOleksij Rempel __le16 fc;
416438696eSOleksij Rempel
426438696eSOleksij Rempel fc = hdr->frame_control;
436438696eSOleksij Rempel
446438696eSOleksij Rempel is_mc = !!is_multicast_ether_addr(hdr->addr1);
456438696eSOleksij Rempel is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&
466438696eSOleksij Rempel test_bit(rx_stats->rs_keyix, common->tkip_keymap);
476438696eSOleksij Rempel strip_mic = is_valid_tkip && ieee80211_is_data(fc) &&
486438696eSOleksij Rempel ieee80211_has_protected(fc) &&
496438696eSOleksij Rempel !(rx_stats->rs_status &
506438696eSOleksij Rempel (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |
516438696eSOleksij Rempel ATH9K_RXERR_KEYMISS));
526438696eSOleksij Rempel
536438696eSOleksij Rempel /*
546438696eSOleksij Rempel * Key miss events are only relevant for pairwise keys where the
556438696eSOleksij Rempel * descriptor does contain a valid key index. This has been observed
566438696eSOleksij Rempel * mostly with CCMP encryption.
576438696eSOleksij Rempel */
586438696eSOleksij Rempel if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID ||
596438696eSOleksij Rempel !test_bit(rx_stats->rs_keyix, common->ccmp_keymap))
606438696eSOleksij Rempel rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;
616438696eSOleksij Rempel
626438696eSOleksij Rempel mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) &&
636438696eSOleksij Rempel !ieee80211_has_morefrags(fc) &&
646438696eSOleksij Rempel !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
656438696eSOleksij Rempel (rx_stats->rs_status & ATH9K_RXERR_MIC);
666438696eSOleksij Rempel
676438696eSOleksij Rempel /*
686438696eSOleksij Rempel * The rx_stats->rs_status will not be set until the end of the
696438696eSOleksij Rempel * chained descriptors so it can be ignored if rs_more is set. The
706438696eSOleksij Rempel * rs_more will be false at the last element of the chained
716438696eSOleksij Rempel * descriptors.
726438696eSOleksij Rempel */
736438696eSOleksij Rempel if (rx_stats->rs_status != 0) {
746438696eSOleksij Rempel u8 status_mask;
756438696eSOleksij Rempel
766438696eSOleksij Rempel if (rx_stats->rs_status & ATH9K_RXERR_CRC) {
776438696eSOleksij Rempel rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
786438696eSOleksij Rempel mic_error = false;
796438696eSOleksij Rempel }
806438696eSOleksij Rempel
816438696eSOleksij Rempel if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) ||
826438696eSOleksij Rempel (!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) {
836438696eSOleksij Rempel *decrypt_error = true;
846438696eSOleksij Rempel mic_error = false;
856438696eSOleksij Rempel }
866438696eSOleksij Rempel
876438696eSOleksij Rempel
886438696eSOleksij Rempel /*
896438696eSOleksij Rempel * Reject error frames with the exception of
906438696eSOleksij Rempel * decryption and MIC failures. For monitor mode,
916438696eSOleksij Rempel * we also ignore the CRC error.
926438696eSOleksij Rempel */
936438696eSOleksij Rempel status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
946438696eSOleksij Rempel ATH9K_RXERR_KEYMISS;
956438696eSOleksij Rempel
966438696eSOleksij Rempel if (ah->is_monitoring && (rxfilter & FIF_FCSFAIL))
976438696eSOleksij Rempel status_mask |= ATH9K_RXERR_CRC;
986438696eSOleksij Rempel
996438696eSOleksij Rempel if (rx_stats->rs_status & ~status_mask)
1006438696eSOleksij Rempel return false;
1016438696eSOleksij Rempel }
1026438696eSOleksij Rempel
1036438696eSOleksij Rempel /*
1046438696eSOleksij Rempel * For unicast frames the MIC error bit can have false positives,
1056438696eSOleksij Rempel * so all MIC error reports need to be validated in software.
1066438696eSOleksij Rempel * False negatives are not common, so skip software verification
1076438696eSOleksij Rempel * if the hardware considers the MIC valid.
1086438696eSOleksij Rempel */
1096438696eSOleksij Rempel if (strip_mic)
1106438696eSOleksij Rempel rxs->flag |= RX_FLAG_MMIC_STRIPPED;
1116438696eSOleksij Rempel else if (is_mc && mic_error)
1126438696eSOleksij Rempel rxs->flag |= RX_FLAG_MMIC_ERROR;
1136438696eSOleksij Rempel
1146438696eSOleksij Rempel return true;
1156438696eSOleksij Rempel }
1166438696eSOleksij Rempel EXPORT_SYMBOL(ath9k_cmn_rx_accept);
1176438696eSOleksij Rempel
ath9k_cmn_rx_skb_postprocess(struct ath_common * common,struct sk_buff * skb,struct ath_rx_status * rx_stats,struct ieee80211_rx_status * rxs,bool decrypt_error)1185a078fcbSOleksij Rempel void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
1195a078fcbSOleksij Rempel struct sk_buff *skb,
1205a078fcbSOleksij Rempel struct ath_rx_status *rx_stats,
1215a078fcbSOleksij Rempel struct ieee80211_rx_status *rxs,
1225a078fcbSOleksij Rempel bool decrypt_error)
1235a078fcbSOleksij Rempel {
1245a078fcbSOleksij Rempel struct ath_hw *ah = common->ah;
1255a078fcbSOleksij Rempel struct ieee80211_hdr *hdr;
1265a078fcbSOleksij Rempel int hdrlen, padpos, padsize;
1275a078fcbSOleksij Rempel u8 keyix;
1285a078fcbSOleksij Rempel __le16 fc;
1295a078fcbSOleksij Rempel
1305a078fcbSOleksij Rempel /* see if any padding is done by the hw and remove it */
1315a078fcbSOleksij Rempel hdr = (struct ieee80211_hdr *) skb->data;
1325a078fcbSOleksij Rempel hdrlen = ieee80211_get_hdrlen_from_skb(skb);
1335a078fcbSOleksij Rempel fc = hdr->frame_control;
1345a078fcbSOleksij Rempel padpos = ieee80211_hdrlen(fc);
1355a078fcbSOleksij Rempel
1365a078fcbSOleksij Rempel /* The MAC header is padded to have 32-bit boundary if the
1375a078fcbSOleksij Rempel * packet payload is non-zero. The general calculation for
1385a078fcbSOleksij Rempel * padsize would take into account odd header lengths:
1395a078fcbSOleksij Rempel * padsize = (4 - padpos % 4) % 4; However, since only
1405a078fcbSOleksij Rempel * even-length headers are used, padding can only be 0 or 2
1415a078fcbSOleksij Rempel * bytes and we can optimize this a bit. In addition, we must
1425a078fcbSOleksij Rempel * not try to remove padding from short control frames that do
1435a078fcbSOleksij Rempel * not have payload. */
1445a078fcbSOleksij Rempel padsize = padpos & 3;
1455a078fcbSOleksij Rempel if (padsize && skb->len>=padpos+padsize+FCS_LEN) {
1465a078fcbSOleksij Rempel memmove(skb->data + padsize, skb->data, padpos);
1475a078fcbSOleksij Rempel skb_pull(skb, padsize);
1485a078fcbSOleksij Rempel }
1495a078fcbSOleksij Rempel
1505a078fcbSOleksij Rempel keyix = rx_stats->rs_keyix;
1515a078fcbSOleksij Rempel
1525a078fcbSOleksij Rempel if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error &&
1535a078fcbSOleksij Rempel ieee80211_has_protected(fc)) {
1545a078fcbSOleksij Rempel rxs->flag |= RX_FLAG_DECRYPTED;
1555a078fcbSOleksij Rempel } else if (ieee80211_has_protected(fc)
1565a078fcbSOleksij Rempel && !decrypt_error && skb->len >= hdrlen + 4) {
1575a078fcbSOleksij Rempel keyix = skb->data[hdrlen + 3] >> 6;
1585a078fcbSOleksij Rempel
1595a078fcbSOleksij Rempel if (test_bit(keyix, common->keymap))
1605a078fcbSOleksij Rempel rxs->flag |= RX_FLAG_DECRYPTED;
1615a078fcbSOleksij Rempel }
162e6510b11SChun-Yeow Yeoh if (ah->sw_mgmt_crypto_rx &&
1635a078fcbSOleksij Rempel (rxs->flag & RX_FLAG_DECRYPTED) &&
1645a078fcbSOleksij Rempel ieee80211_is_mgmt(fc))
1655a078fcbSOleksij Rempel /* Use software decrypt for management frames. */
1665a078fcbSOleksij Rempel rxs->flag &= ~RX_FLAG_DECRYPTED;
1675a078fcbSOleksij Rempel }
1685a078fcbSOleksij Rempel EXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess);
1695a078fcbSOleksij Rempel
ath9k_cmn_process_rate(struct ath_common * common,struct ieee80211_hw * hw,struct ath_rx_status * rx_stats,struct ieee80211_rx_status * rxs)17012746036SOleksij Rempel int ath9k_cmn_process_rate(struct ath_common *common,
17112746036SOleksij Rempel struct ieee80211_hw *hw,
17212746036SOleksij Rempel struct ath_rx_status *rx_stats,
17312746036SOleksij Rempel struct ieee80211_rx_status *rxs)
17412746036SOleksij Rempel {
17512746036SOleksij Rempel struct ieee80211_supported_band *sband;
17657fbcce3SJohannes Berg enum nl80211_band band;
17712746036SOleksij Rempel unsigned int i = 0;
17812746036SOleksij Rempel struct ath_hw *ah = common->ah;
17912746036SOleksij Rempel
18012746036SOleksij Rempel band = ah->curchan->chan->band;
18112746036SOleksij Rempel sband = hw->wiphy->bands[band];
18212746036SOleksij Rempel
18312746036SOleksij Rempel if (IS_CHAN_QUARTER_RATE(ah->curchan))
184da6a4352SJohannes Berg rxs->bw = RATE_INFO_BW_5;
18512746036SOleksij Rempel else if (IS_CHAN_HALF_RATE(ah->curchan))
186da6a4352SJohannes Berg rxs->bw = RATE_INFO_BW_10;
18712746036SOleksij Rempel
18812746036SOleksij Rempel if (rx_stats->rs_rate & 0x80) {
18912746036SOleksij Rempel /* HT rate */
190da6a4352SJohannes Berg rxs->encoding = RX_ENC_HT;
191da6a4352SJohannes Berg rxs->enc_flags |= rx_stats->enc_flags;
192da6a4352SJohannes Berg rxs->bw = rx_stats->bw;
19312746036SOleksij Rempel rxs->rate_idx = rx_stats->rs_rate & 0x7f;
19412746036SOleksij Rempel return 0;
19512746036SOleksij Rempel }
19612746036SOleksij Rempel
19712746036SOleksij Rempel for (i = 0; i < sband->n_bitrates; i++) {
19812746036SOleksij Rempel if (sband->bitrates[i].hw_value == rx_stats->rs_rate) {
19912746036SOleksij Rempel rxs->rate_idx = i;
20012746036SOleksij Rempel return 0;
20112746036SOleksij Rempel }
20212746036SOleksij Rempel if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) {
2037fdd69c5SJohannes Berg rxs->enc_flags |= RX_ENC_FLAG_SHORTPRE;
20412746036SOleksij Rempel rxs->rate_idx = i;
20512746036SOleksij Rempel return 0;
20612746036SOleksij Rempel }
20712746036SOleksij Rempel }
20812746036SOleksij Rempel
20912746036SOleksij Rempel return -EINVAL;
21012746036SOleksij Rempel }
21112746036SOleksij Rempel EXPORT_SYMBOL(ath9k_cmn_process_rate);
21212746036SOleksij Rempel
ath9k_cmn_process_rssi(struct ath_common * common,struct ieee80211_hw * hw,struct ath_rx_status * rx_stats,struct ieee80211_rx_status * rxs)21332efb0ccSOleksij Rempel void ath9k_cmn_process_rssi(struct ath_common *common,
21432efb0ccSOleksij Rempel struct ieee80211_hw *hw,
21532efb0ccSOleksij Rempel struct ath_rx_status *rx_stats,
21632efb0ccSOleksij Rempel struct ieee80211_rx_status *rxs)
21732efb0ccSOleksij Rempel {
21832efb0ccSOleksij Rempel struct ath_hw *ah = common->ah;
21932efb0ccSOleksij Rempel int last_rssi;
22032efb0ccSOleksij Rempel int rssi = rx_stats->rs_rssi;
22132efb0ccSOleksij Rempel int i, j;
22232efb0ccSOleksij Rempel
22332efb0ccSOleksij Rempel /*
22432efb0ccSOleksij Rempel * RSSI is not available for subframes in an A-MPDU.
22532efb0ccSOleksij Rempel */
22632efb0ccSOleksij Rempel if (rx_stats->rs_moreaggr) {
22732efb0ccSOleksij Rempel rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
22832efb0ccSOleksij Rempel return;
22932efb0ccSOleksij Rempel }
23032efb0ccSOleksij Rempel
23132efb0ccSOleksij Rempel /*
23232efb0ccSOleksij Rempel * Check if the RSSI for the last subframe in an A-MPDU
23332efb0ccSOleksij Rempel * or an unaggregated frame is valid.
23432efb0ccSOleksij Rempel */
23532efb0ccSOleksij Rempel if (rx_stats->rs_rssi == ATH9K_RSSI_BAD) {
23632efb0ccSOleksij Rempel rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
23732efb0ccSOleksij Rempel return;
23832efb0ccSOleksij Rempel }
23932efb0ccSOleksij Rempel
24032efb0ccSOleksij Rempel for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) {
24132efb0ccSOleksij Rempel s8 rssi;
24232efb0ccSOleksij Rempel
24332efb0ccSOleksij Rempel if (!(ah->rxchainmask & BIT(i)))
24432efb0ccSOleksij Rempel continue;
24532efb0ccSOleksij Rempel
24632efb0ccSOleksij Rempel rssi = rx_stats->rs_rssi_ctl[i];
24732efb0ccSOleksij Rempel if (rssi != ATH9K_RSSI_BAD) {
24832efb0ccSOleksij Rempel rxs->chains |= BIT(j);
24932efb0ccSOleksij Rempel rxs->chain_signal[j] = ah->noise + rssi;
25032efb0ccSOleksij Rempel }
25132efb0ccSOleksij Rempel j++;
25232efb0ccSOleksij Rempel }
25332efb0ccSOleksij Rempel
25432efb0ccSOleksij Rempel /*
25532efb0ccSOleksij Rempel * Update Beacon RSSI, this is used by ANI.
25632efb0ccSOleksij Rempel */
25732efb0ccSOleksij Rempel if (rx_stats->is_mybeacon &&
25832efb0ccSOleksij Rempel ((ah->opmode == NL80211_IFTYPE_STATION) ||
25932efb0ccSOleksij Rempel (ah->opmode == NL80211_IFTYPE_ADHOC))) {
26032efb0ccSOleksij Rempel ATH_RSSI_LPF(common->last_rssi, rx_stats->rs_rssi);
26132efb0ccSOleksij Rempel last_rssi = common->last_rssi;
26232efb0ccSOleksij Rempel
26332efb0ccSOleksij Rempel if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
26432efb0ccSOleksij Rempel rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
26532efb0ccSOleksij Rempel if (rssi < 0)
26632efb0ccSOleksij Rempel rssi = 0;
26732efb0ccSOleksij Rempel
26832efb0ccSOleksij Rempel ah->stats.avgbrssi = rssi;
26932efb0ccSOleksij Rempel }
27032efb0ccSOleksij Rempel
27132efb0ccSOleksij Rempel rxs->signal = ah->noise + rx_stats->rs_rssi;
27232efb0ccSOleksij Rempel }
27332efb0ccSOleksij Rempel EXPORT_SYMBOL(ath9k_cmn_process_rssi);
27432efb0ccSOleksij Rempel
ath9k_cmn_get_hw_crypto_keytype(struct sk_buff * skb)275fb9987d0SSujith int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb)
276fb9987d0SSujith {
277fb9987d0SSujith struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
278fb9987d0SSujith
279fb9987d0SSujith if (tx_info->control.hw_key) {
28097359d12SJohannes Berg switch (tx_info->control.hw_key->cipher) {
28197359d12SJohannes Berg case WLAN_CIPHER_SUITE_WEP40:
28297359d12SJohannes Berg case WLAN_CIPHER_SUITE_WEP104:
283fb9987d0SSujith return ATH9K_KEY_TYPE_WEP;
28497359d12SJohannes Berg case WLAN_CIPHER_SUITE_TKIP:
285fb9987d0SSujith return ATH9K_KEY_TYPE_TKIP;
28697359d12SJohannes Berg case WLAN_CIPHER_SUITE_CCMP:
287fb9987d0SSujith return ATH9K_KEY_TYPE_AES;
28897359d12SJohannes Berg default:
28997359d12SJohannes Berg break;
29097359d12SJohannes Berg }
291fb9987d0SSujith }
292fb9987d0SSujith
293fb9987d0SSujith return ATH9K_KEY_TYPE_CLEAR;
294fb9987d0SSujith }
295fb9987d0SSujith EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype);
296fb9987d0SSujith
297fb9987d0SSujith /*
298fb9987d0SSujith * Update internal channel flags.
299fb9987d0SSujith */
ath9k_cmn_update_ichannel(struct ath9k_channel * ichan,struct cfg80211_chan_def * chandef)3002297f1c7SFelix Fietkau static void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
3010671894fSSimon Wunderlich struct cfg80211_chan_def *chandef)
302fb9987d0SSujith {
3036b21fd20SFelix Fietkau struct ieee80211_channel *chan = chandef->chan;
3046b21fd20SFelix Fietkau u16 flags = 0;
305fb9987d0SSujith
3066b21fd20SFelix Fietkau ichan->channel = chan->center_freq;
3076b21fd20SFelix Fietkau ichan->chan = chan;
3086b21fd20SFelix Fietkau
30957fbcce3SJohannes Berg if (chan->band == NL80211_BAND_5GHZ)
3106b21fd20SFelix Fietkau flags |= CHANNEL_5GHZ;
311fb9987d0SSujith
3120671894fSSimon Wunderlich switch (chandef->width) {
3130671894fSSimon Wunderlich case NL80211_CHAN_WIDTH_5:
3146b21fd20SFelix Fietkau flags |= CHANNEL_QUARTER;
3150671894fSSimon Wunderlich break;
3160671894fSSimon Wunderlich case NL80211_CHAN_WIDTH_10:
3176b21fd20SFelix Fietkau flags |= CHANNEL_HALF;
3180671894fSSimon Wunderlich break;
3190671894fSSimon Wunderlich case NL80211_CHAN_WIDTH_20_NOHT:
3200671894fSSimon Wunderlich break;
3210671894fSSimon Wunderlich case NL80211_CHAN_WIDTH_20:
3226b21fd20SFelix Fietkau flags |= CHANNEL_HT;
3236b21fd20SFelix Fietkau break;
3240671894fSSimon Wunderlich case NL80211_CHAN_WIDTH_40:
3256b21fd20SFelix Fietkau if (chandef->center_freq1 > chandef->chan->center_freq)
3266b21fd20SFelix Fietkau flags |= CHANNEL_HT40PLUS | CHANNEL_HT;
3276b21fd20SFelix Fietkau else
3286b21fd20SFelix Fietkau flags |= CHANNEL_HT40MINUS | CHANNEL_HT;
3290671894fSSimon Wunderlich break;
3300671894fSSimon Wunderlich default:
3310671894fSSimon Wunderlich WARN_ON(1);
3320671894fSSimon Wunderlich }
3336b21fd20SFelix Fietkau
3346b21fd20SFelix Fietkau ichan->channelFlags = flags;
335fb9987d0SSujith }
336fb9987d0SSujith
337fb9987d0SSujith /*
338fb9987d0SSujith * Get the internal channel reference.
339fb9987d0SSujith */
ath9k_cmn_get_channel(struct ieee80211_hw * hw,struct ath_hw * ah,struct cfg80211_chan_def * chandef)3402297f1c7SFelix Fietkau struct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw,
3412297f1c7SFelix Fietkau struct ath_hw *ah,
3422297f1c7SFelix Fietkau struct cfg80211_chan_def *chandef)
343fb9987d0SSujith {
3442297f1c7SFelix Fietkau struct ieee80211_channel *curchan = chandef->chan;
345fb9987d0SSujith struct ath9k_channel *channel;
346fb9987d0SSujith
347f40c4608SFelix Fietkau channel = &ah->channels[curchan->hw_value];
3482297f1c7SFelix Fietkau ath9k_cmn_update_ichannel(channel, chandef);
349fb9987d0SSujith
350fb9987d0SSujith return channel;
351fb9987d0SSujith }
3522297f1c7SFelix Fietkau EXPORT_SYMBOL(ath9k_cmn_get_channel);
353fb9987d0SSujith
ath9k_cmn_count_streams(unsigned int chainmask,int max)35461389f3eSSujith int ath9k_cmn_count_streams(unsigned int chainmask, int max)
35561389f3eSSujith {
35661389f3eSSujith int streams = 0;
35761389f3eSSujith
35861389f3eSSujith do {
35961389f3eSSujith if (++streams == max)
36061389f3eSSujith break;
36161389f3eSSujith } while ((chainmask = chainmask & (chainmask - 1)));
36261389f3eSSujith
36361389f3eSSujith return streams;
36461389f3eSSujith }
36561389f3eSSujith EXPORT_SYMBOL(ath9k_cmn_count_streams);
36661389f3eSSujith
ath9k_cmn_update_txpow(struct ath_hw * ah,u16 cur_txpow,u16 new_txpow,u16 * txpower)3675048e8c3SRajkumar Manoharan void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
3685048e8c3SRajkumar Manoharan u16 new_txpow, u16 *txpower)
3695048e8c3SRajkumar Manoharan {
370ca2c68ccSFelix Fietkau struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
371ca2c68ccSFelix Fietkau
372*b01c9e32SStanislaw Gruszka if (ah->curchan && reg->power_limit != new_txpow)
3735048e8c3SRajkumar Manoharan ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
37476325451SFelix Fietkau
3755048e8c3SRajkumar Manoharan /* read back in case value is clamped */
376ca2c68ccSFelix Fietkau *txpower = reg->max_power_level;
3775048e8c3SRajkumar Manoharan }
3785048e8c3SRajkumar Manoharan EXPORT_SYMBOL(ath9k_cmn_update_txpow);
3795048e8c3SRajkumar Manoharan
ath9k_cmn_init_crypto(struct ath_hw * ah)380f82b4bdeSRajkumar Manoharan void ath9k_cmn_init_crypto(struct ath_hw *ah)
381f82b4bdeSRajkumar Manoharan {
382f82b4bdeSRajkumar Manoharan struct ath_common *common = ath9k_hw_common(ah);
383f82b4bdeSRajkumar Manoharan int i = 0;
384f82b4bdeSRajkumar Manoharan
385f82b4bdeSRajkumar Manoharan /* Get the hardware key cache size. */
386f82b4bdeSRajkumar Manoharan common->keymax = AR_KEYTABLE_SIZE;
387f82b4bdeSRajkumar Manoharan
388f82b4bdeSRajkumar Manoharan /*
389f82b4bdeSRajkumar Manoharan * Check whether the separate key cache entries
390f82b4bdeSRajkumar Manoharan * are required to handle both tx+rx MIC keys.
391f82b4bdeSRajkumar Manoharan * With split mic keys the number of stations is limited
392f82b4bdeSRajkumar Manoharan * to 27 otherwise 59.
393f82b4bdeSRajkumar Manoharan */
394f82b4bdeSRajkumar Manoharan if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
395f82b4bdeSRajkumar Manoharan common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
396f82b4bdeSRajkumar Manoharan
397f82b4bdeSRajkumar Manoharan /*
398f82b4bdeSRajkumar Manoharan * Reset the key cache since some parts do not
399f82b4bdeSRajkumar Manoharan * reset the contents on initial power up.
400f82b4bdeSRajkumar Manoharan */
401f82b4bdeSRajkumar Manoharan for (i = 0; i < common->keymax; i++)
402f82b4bdeSRajkumar Manoharan ath_hw_keyreset(common, (u16) i);
403f82b4bdeSRajkumar Manoharan }
404f82b4bdeSRajkumar Manoharan EXPORT_SYMBOL(ath9k_cmn_init_crypto);
405f82b4bdeSRajkumar Manoharan
ath9k_cmn_init(void)406db86f07eSLuis R. Rodriguez static int __init ath9k_cmn_init(void)
407db86f07eSLuis R. Rodriguez {
408db86f07eSLuis R. Rodriguez return 0;
409db86f07eSLuis R. Rodriguez }
410db86f07eSLuis R. Rodriguez module_init(ath9k_cmn_init);
411db86f07eSLuis R. Rodriguez
ath9k_cmn_exit(void)412db86f07eSLuis R. Rodriguez static void __exit ath9k_cmn_exit(void)
413db86f07eSLuis R. Rodriguez {
414db86f07eSLuis R. Rodriguez return;
415db86f07eSLuis R. Rodriguez }
416db86f07eSLuis R. Rodriguez module_exit(ath9k_cmn_exit);
417