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 */ 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 118*5a078fcbSOleksij Rempel void ath9k_cmn_rx_skb_postprocess(struct ath_common *common, 119*5a078fcbSOleksij Rempel struct sk_buff *skb, 120*5a078fcbSOleksij Rempel struct ath_rx_status *rx_stats, 121*5a078fcbSOleksij Rempel struct ieee80211_rx_status *rxs, 122*5a078fcbSOleksij Rempel bool decrypt_error) 123*5a078fcbSOleksij Rempel { 124*5a078fcbSOleksij Rempel struct ath_hw *ah = common->ah; 125*5a078fcbSOleksij Rempel struct ieee80211_hdr *hdr; 126*5a078fcbSOleksij Rempel int hdrlen, padpos, padsize; 127*5a078fcbSOleksij Rempel u8 keyix; 128*5a078fcbSOleksij Rempel __le16 fc; 129*5a078fcbSOleksij Rempel 130*5a078fcbSOleksij Rempel /* see if any padding is done by the hw and remove it */ 131*5a078fcbSOleksij Rempel hdr = (struct ieee80211_hdr *) skb->data; 132*5a078fcbSOleksij Rempel hdrlen = ieee80211_get_hdrlen_from_skb(skb); 133*5a078fcbSOleksij Rempel fc = hdr->frame_control; 134*5a078fcbSOleksij Rempel padpos = ieee80211_hdrlen(fc); 135*5a078fcbSOleksij Rempel 136*5a078fcbSOleksij Rempel /* The MAC header is padded to have 32-bit boundary if the 137*5a078fcbSOleksij Rempel * packet payload is non-zero. The general calculation for 138*5a078fcbSOleksij Rempel * padsize would take into account odd header lengths: 139*5a078fcbSOleksij Rempel * padsize = (4 - padpos % 4) % 4; However, since only 140*5a078fcbSOleksij Rempel * even-length headers are used, padding can only be 0 or 2 141*5a078fcbSOleksij Rempel * bytes and we can optimize this a bit. In addition, we must 142*5a078fcbSOleksij Rempel * not try to remove padding from short control frames that do 143*5a078fcbSOleksij Rempel * not have payload. */ 144*5a078fcbSOleksij Rempel padsize = padpos & 3; 145*5a078fcbSOleksij Rempel if (padsize && skb->len>=padpos+padsize+FCS_LEN) { 146*5a078fcbSOleksij Rempel memmove(skb->data + padsize, skb->data, padpos); 147*5a078fcbSOleksij Rempel skb_pull(skb, padsize); 148*5a078fcbSOleksij Rempel } 149*5a078fcbSOleksij Rempel 150*5a078fcbSOleksij Rempel keyix = rx_stats->rs_keyix; 151*5a078fcbSOleksij Rempel 152*5a078fcbSOleksij Rempel if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error && 153*5a078fcbSOleksij Rempel ieee80211_has_protected(fc)) { 154*5a078fcbSOleksij Rempel rxs->flag |= RX_FLAG_DECRYPTED; 155*5a078fcbSOleksij Rempel } else if (ieee80211_has_protected(fc) 156*5a078fcbSOleksij Rempel && !decrypt_error && skb->len >= hdrlen + 4) { 157*5a078fcbSOleksij Rempel keyix = skb->data[hdrlen + 3] >> 6; 158*5a078fcbSOleksij Rempel 159*5a078fcbSOleksij Rempel if (test_bit(keyix, common->keymap)) 160*5a078fcbSOleksij Rempel rxs->flag |= RX_FLAG_DECRYPTED; 161*5a078fcbSOleksij Rempel } 162*5a078fcbSOleksij Rempel if (ah->sw_mgmt_crypto && 163*5a078fcbSOleksij Rempel (rxs->flag & RX_FLAG_DECRYPTED) && 164*5a078fcbSOleksij Rempel ieee80211_is_mgmt(fc)) 165*5a078fcbSOleksij Rempel /* Use software decrypt for management frames. */ 166*5a078fcbSOleksij Rempel rxs->flag &= ~RX_FLAG_DECRYPTED; 167*5a078fcbSOleksij Rempel } 168*5a078fcbSOleksij Rempel EXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess); 169*5a078fcbSOleksij Rempel 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; 17612746036SOleksij Rempel enum ieee80211_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)) 18412746036SOleksij Rempel rxs->flag |= RX_FLAG_5MHZ; 18512746036SOleksij Rempel else if (IS_CHAN_HALF_RATE(ah->curchan)) 18612746036SOleksij Rempel rxs->flag |= RX_FLAG_10MHZ; 18712746036SOleksij Rempel 18812746036SOleksij Rempel if (rx_stats->rs_rate & 0x80) { 18912746036SOleksij Rempel /* HT rate */ 19012746036SOleksij Rempel rxs->flag |= RX_FLAG_HT; 19112746036SOleksij Rempel rxs->flag |= rx_stats->flag; 19212746036SOleksij Rempel rxs->rate_idx = rx_stats->rs_rate & 0x7f; 19312746036SOleksij Rempel return 0; 19412746036SOleksij Rempel } 19512746036SOleksij Rempel 19612746036SOleksij Rempel for (i = 0; i < sband->n_bitrates; i++) { 19712746036SOleksij Rempel if (sband->bitrates[i].hw_value == rx_stats->rs_rate) { 19812746036SOleksij Rempel rxs->rate_idx = i; 19912746036SOleksij Rempel return 0; 20012746036SOleksij Rempel } 20112746036SOleksij Rempel if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) { 20212746036SOleksij Rempel rxs->flag |= RX_FLAG_SHORTPRE; 20312746036SOleksij Rempel rxs->rate_idx = i; 20412746036SOleksij Rempel return 0; 20512746036SOleksij Rempel } 20612746036SOleksij Rempel } 20712746036SOleksij Rempel 20812746036SOleksij Rempel return -EINVAL; 20912746036SOleksij Rempel } 21012746036SOleksij Rempel EXPORT_SYMBOL(ath9k_cmn_process_rate); 21112746036SOleksij Rempel 21232efb0ccSOleksij Rempel void ath9k_cmn_process_rssi(struct ath_common *common, 21332efb0ccSOleksij Rempel struct ieee80211_hw *hw, 21432efb0ccSOleksij Rempel struct ath_rx_status *rx_stats, 21532efb0ccSOleksij Rempel struct ieee80211_rx_status *rxs) 21632efb0ccSOleksij Rempel { 21732efb0ccSOleksij Rempel struct ath_hw *ah = common->ah; 21832efb0ccSOleksij Rempel int last_rssi; 21932efb0ccSOleksij Rempel int rssi = rx_stats->rs_rssi; 22032efb0ccSOleksij Rempel int i, j; 22132efb0ccSOleksij Rempel 22232efb0ccSOleksij Rempel /* 22332efb0ccSOleksij Rempel * RSSI is not available for subframes in an A-MPDU. 22432efb0ccSOleksij Rempel */ 22532efb0ccSOleksij Rempel if (rx_stats->rs_moreaggr) { 22632efb0ccSOleksij Rempel rxs->flag |= RX_FLAG_NO_SIGNAL_VAL; 22732efb0ccSOleksij Rempel return; 22832efb0ccSOleksij Rempel } 22932efb0ccSOleksij Rempel 23032efb0ccSOleksij Rempel /* 23132efb0ccSOleksij Rempel * Check if the RSSI for the last subframe in an A-MPDU 23232efb0ccSOleksij Rempel * or an unaggregated frame is valid. 23332efb0ccSOleksij Rempel */ 23432efb0ccSOleksij Rempel if (rx_stats->rs_rssi == ATH9K_RSSI_BAD) { 23532efb0ccSOleksij Rempel rxs->flag |= RX_FLAG_NO_SIGNAL_VAL; 23632efb0ccSOleksij Rempel return; 23732efb0ccSOleksij Rempel } 23832efb0ccSOleksij Rempel 23932efb0ccSOleksij Rempel for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) { 24032efb0ccSOleksij Rempel s8 rssi; 24132efb0ccSOleksij Rempel 24232efb0ccSOleksij Rempel if (!(ah->rxchainmask & BIT(i))) 24332efb0ccSOleksij Rempel continue; 24432efb0ccSOleksij Rempel 24532efb0ccSOleksij Rempel rssi = rx_stats->rs_rssi_ctl[i]; 24632efb0ccSOleksij Rempel if (rssi != ATH9K_RSSI_BAD) { 24732efb0ccSOleksij Rempel rxs->chains |= BIT(j); 24832efb0ccSOleksij Rempel rxs->chain_signal[j] = ah->noise + rssi; 24932efb0ccSOleksij Rempel } 25032efb0ccSOleksij Rempel j++; 25132efb0ccSOleksij Rempel } 25232efb0ccSOleksij Rempel 25332efb0ccSOleksij Rempel /* 25432efb0ccSOleksij Rempel * Update Beacon RSSI, this is used by ANI. 25532efb0ccSOleksij Rempel */ 25632efb0ccSOleksij Rempel if (rx_stats->is_mybeacon && 25732efb0ccSOleksij Rempel ((ah->opmode == NL80211_IFTYPE_STATION) || 25832efb0ccSOleksij Rempel (ah->opmode == NL80211_IFTYPE_ADHOC))) { 25932efb0ccSOleksij Rempel ATH_RSSI_LPF(common->last_rssi, rx_stats->rs_rssi); 26032efb0ccSOleksij Rempel last_rssi = common->last_rssi; 26132efb0ccSOleksij Rempel 26232efb0ccSOleksij Rempel if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) 26332efb0ccSOleksij Rempel rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER); 26432efb0ccSOleksij Rempel if (rssi < 0) 26532efb0ccSOleksij Rempel rssi = 0; 26632efb0ccSOleksij Rempel 26732efb0ccSOleksij Rempel ah->stats.avgbrssi = rssi; 26832efb0ccSOleksij Rempel } 26932efb0ccSOleksij Rempel 27032efb0ccSOleksij Rempel rxs->signal = ah->noise + rx_stats->rs_rssi; 27132efb0ccSOleksij Rempel } 27232efb0ccSOleksij Rempel EXPORT_SYMBOL(ath9k_cmn_process_rssi); 27332efb0ccSOleksij Rempel 274fb9987d0SSujith int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb) 275fb9987d0SSujith { 276fb9987d0SSujith struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); 277fb9987d0SSujith 278fb9987d0SSujith if (tx_info->control.hw_key) { 27997359d12SJohannes Berg switch (tx_info->control.hw_key->cipher) { 28097359d12SJohannes Berg case WLAN_CIPHER_SUITE_WEP40: 28197359d12SJohannes Berg case WLAN_CIPHER_SUITE_WEP104: 282fb9987d0SSujith return ATH9K_KEY_TYPE_WEP; 28397359d12SJohannes Berg case WLAN_CIPHER_SUITE_TKIP: 284fb9987d0SSujith return ATH9K_KEY_TYPE_TKIP; 28597359d12SJohannes Berg case WLAN_CIPHER_SUITE_CCMP: 286fb9987d0SSujith return ATH9K_KEY_TYPE_AES; 28797359d12SJohannes Berg default: 28897359d12SJohannes Berg break; 28997359d12SJohannes Berg } 290fb9987d0SSujith } 291fb9987d0SSujith 292fb9987d0SSujith return ATH9K_KEY_TYPE_CLEAR; 293fb9987d0SSujith } 294fb9987d0SSujith EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype); 295fb9987d0SSujith 296fb9987d0SSujith /* 297fb9987d0SSujith * Update internal channel flags. 298fb9987d0SSujith */ 2992297f1c7SFelix Fietkau static void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, 3000671894fSSimon Wunderlich struct cfg80211_chan_def *chandef) 301fb9987d0SSujith { 3026b21fd20SFelix Fietkau struct ieee80211_channel *chan = chandef->chan; 3036b21fd20SFelix Fietkau u16 flags = 0; 304fb9987d0SSujith 3056b21fd20SFelix Fietkau ichan->channel = chan->center_freq; 3066b21fd20SFelix Fietkau ichan->chan = chan; 3076b21fd20SFelix Fietkau 3086b21fd20SFelix Fietkau if (chan->band == IEEE80211_BAND_5GHZ) 3096b21fd20SFelix Fietkau flags |= CHANNEL_5GHZ; 310fb9987d0SSujith 3110671894fSSimon Wunderlich switch (chandef->width) { 3120671894fSSimon Wunderlich case NL80211_CHAN_WIDTH_5: 3136b21fd20SFelix Fietkau flags |= CHANNEL_QUARTER; 3140671894fSSimon Wunderlich break; 3150671894fSSimon Wunderlich case NL80211_CHAN_WIDTH_10: 3166b21fd20SFelix Fietkau flags |= CHANNEL_HALF; 3170671894fSSimon Wunderlich break; 3180671894fSSimon Wunderlich case NL80211_CHAN_WIDTH_20_NOHT: 3190671894fSSimon Wunderlich break; 3200671894fSSimon Wunderlich case NL80211_CHAN_WIDTH_20: 3216b21fd20SFelix Fietkau flags |= CHANNEL_HT; 3226b21fd20SFelix Fietkau break; 3230671894fSSimon Wunderlich case NL80211_CHAN_WIDTH_40: 3246b21fd20SFelix Fietkau if (chandef->center_freq1 > chandef->chan->center_freq) 3256b21fd20SFelix Fietkau flags |= CHANNEL_HT40PLUS | CHANNEL_HT; 3266b21fd20SFelix Fietkau else 3276b21fd20SFelix Fietkau flags |= CHANNEL_HT40MINUS | CHANNEL_HT; 3280671894fSSimon Wunderlich break; 3290671894fSSimon Wunderlich default: 3300671894fSSimon Wunderlich WARN_ON(1); 3310671894fSSimon Wunderlich } 3326b21fd20SFelix Fietkau 3336b21fd20SFelix Fietkau ichan->channelFlags = flags; 334fb9987d0SSujith } 335fb9987d0SSujith 336fb9987d0SSujith /* 337fb9987d0SSujith * Get the internal channel reference. 338fb9987d0SSujith */ 3392297f1c7SFelix Fietkau struct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw, 3402297f1c7SFelix Fietkau struct ath_hw *ah, 3412297f1c7SFelix Fietkau struct cfg80211_chan_def *chandef) 342fb9987d0SSujith { 3432297f1c7SFelix Fietkau struct ieee80211_channel *curchan = chandef->chan; 344fb9987d0SSujith struct ath9k_channel *channel; 345fb9987d0SSujith 346f40c4608SFelix Fietkau channel = &ah->channels[curchan->hw_value]; 3472297f1c7SFelix Fietkau ath9k_cmn_update_ichannel(channel, chandef); 348fb9987d0SSujith 349fb9987d0SSujith return channel; 350fb9987d0SSujith } 3512297f1c7SFelix Fietkau EXPORT_SYMBOL(ath9k_cmn_get_channel); 352fb9987d0SSujith 35361389f3eSSujith int ath9k_cmn_count_streams(unsigned int chainmask, int max) 35461389f3eSSujith { 35561389f3eSSujith int streams = 0; 35661389f3eSSujith 35761389f3eSSujith do { 35861389f3eSSujith if (++streams == max) 35961389f3eSSujith break; 36061389f3eSSujith } while ((chainmask = chainmask & (chainmask - 1))); 36161389f3eSSujith 36261389f3eSSujith return streams; 36361389f3eSSujith } 36461389f3eSSujith EXPORT_SYMBOL(ath9k_cmn_count_streams); 36561389f3eSSujith 3665048e8c3SRajkumar Manoharan void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow, 3675048e8c3SRajkumar Manoharan u16 new_txpow, u16 *txpower) 3685048e8c3SRajkumar Manoharan { 369ca2c68ccSFelix Fietkau struct ath_regulatory *reg = ath9k_hw_regulatory(ah); 370ca2c68ccSFelix Fietkau 371ca2c68ccSFelix Fietkau if (reg->power_limit != new_txpow) { 3725048e8c3SRajkumar Manoharan ath9k_hw_set_txpowerlimit(ah, new_txpow, false); 3735048e8c3SRajkumar Manoharan /* read back in case value is clamped */ 374ca2c68ccSFelix Fietkau *txpower = reg->max_power_level; 3755048e8c3SRajkumar Manoharan } 3765048e8c3SRajkumar Manoharan } 3775048e8c3SRajkumar Manoharan EXPORT_SYMBOL(ath9k_cmn_update_txpow); 3785048e8c3SRajkumar Manoharan 379f82b4bdeSRajkumar Manoharan void ath9k_cmn_init_crypto(struct ath_hw *ah) 380f82b4bdeSRajkumar Manoharan { 381f82b4bdeSRajkumar Manoharan struct ath_common *common = ath9k_hw_common(ah); 382f82b4bdeSRajkumar Manoharan int i = 0; 383f82b4bdeSRajkumar Manoharan 384f82b4bdeSRajkumar Manoharan /* Get the hardware key cache size. */ 385f82b4bdeSRajkumar Manoharan common->keymax = AR_KEYTABLE_SIZE; 386f82b4bdeSRajkumar Manoharan 387f82b4bdeSRajkumar Manoharan /* 388f82b4bdeSRajkumar Manoharan * Check whether the separate key cache entries 389f82b4bdeSRajkumar Manoharan * are required to handle both tx+rx MIC keys. 390f82b4bdeSRajkumar Manoharan * With split mic keys the number of stations is limited 391f82b4bdeSRajkumar Manoharan * to 27 otherwise 59. 392f82b4bdeSRajkumar Manoharan */ 393f82b4bdeSRajkumar Manoharan if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) 394f82b4bdeSRajkumar Manoharan common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; 395f82b4bdeSRajkumar Manoharan 396f82b4bdeSRajkumar Manoharan /* 397f82b4bdeSRajkumar Manoharan * Reset the key cache since some parts do not 398f82b4bdeSRajkumar Manoharan * reset the contents on initial power up. 399f82b4bdeSRajkumar Manoharan */ 400f82b4bdeSRajkumar Manoharan for (i = 0; i < common->keymax; i++) 401f82b4bdeSRajkumar Manoharan ath_hw_keyreset(common, (u16) i); 402f82b4bdeSRajkumar Manoharan } 403f82b4bdeSRajkumar Manoharan EXPORT_SYMBOL(ath9k_cmn_init_crypto); 404f82b4bdeSRajkumar Manoharan 405db86f07eSLuis R. Rodriguez static int __init ath9k_cmn_init(void) 406db86f07eSLuis R. Rodriguez { 407db86f07eSLuis R. Rodriguez return 0; 408db86f07eSLuis R. Rodriguez } 409db86f07eSLuis R. Rodriguez module_init(ath9k_cmn_init); 410db86f07eSLuis R. Rodriguez 411db86f07eSLuis R. Rodriguez static void __exit ath9k_cmn_exit(void) 412db86f07eSLuis R. Rodriguez { 413db86f07eSLuis R. Rodriguez return; 414db86f07eSLuis R. Rodriguez } 415db86f07eSLuis R. Rodriguez module_exit(ath9k_cmn_exit); 416