162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright (c) 2009-2011 Atheros Communications Inc. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any 562306a36Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above 662306a36Sopenharmony_ci * copyright notice and this permission notice appear in all copies. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 962306a36Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 1062306a36Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 1162306a36Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 1262306a36Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 1362306a36Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 1462306a36Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 1562306a36Sopenharmony_ci */ 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/* 1862306a36Sopenharmony_ci * Module for common driver code between ath9k and ath9k_htc 1962306a36Sopenharmony_ci */ 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include <linux/kernel.h> 2262306a36Sopenharmony_ci#include <linux/module.h> 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include "common.h" 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ciMODULE_AUTHOR("Atheros Communications"); 2762306a36Sopenharmony_ciMODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards."); 2862306a36Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL"); 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_ci/* Assumes you've already done the endian to CPU conversion */ 3162306a36Sopenharmony_cibool ath9k_cmn_rx_accept(struct ath_common *common, 3262306a36Sopenharmony_ci struct ieee80211_hdr *hdr, 3362306a36Sopenharmony_ci struct ieee80211_rx_status *rxs, 3462306a36Sopenharmony_ci struct ath_rx_status *rx_stats, 3562306a36Sopenharmony_ci bool *decrypt_error, 3662306a36Sopenharmony_ci unsigned int rxfilter) 3762306a36Sopenharmony_ci{ 3862306a36Sopenharmony_ci struct ath_hw *ah = common->ah; 3962306a36Sopenharmony_ci bool is_mc, is_valid_tkip, strip_mic, mic_error; 4062306a36Sopenharmony_ci __le16 fc; 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_ci fc = hdr->frame_control; 4362306a36Sopenharmony_ci 4462306a36Sopenharmony_ci is_mc = !!is_multicast_ether_addr(hdr->addr1); 4562306a36Sopenharmony_ci is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && 4662306a36Sopenharmony_ci test_bit(rx_stats->rs_keyix, common->tkip_keymap); 4762306a36Sopenharmony_ci strip_mic = is_valid_tkip && ieee80211_is_data(fc) && 4862306a36Sopenharmony_ci ieee80211_has_protected(fc) && 4962306a36Sopenharmony_ci !(rx_stats->rs_status & 5062306a36Sopenharmony_ci (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC | 5162306a36Sopenharmony_ci ATH9K_RXERR_KEYMISS)); 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci /* 5462306a36Sopenharmony_ci * Key miss events are only relevant for pairwise keys where the 5562306a36Sopenharmony_ci * descriptor does contain a valid key index. This has been observed 5662306a36Sopenharmony_ci * mostly with CCMP encryption. 5762306a36Sopenharmony_ci */ 5862306a36Sopenharmony_ci if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID || 5962306a36Sopenharmony_ci !test_bit(rx_stats->rs_keyix, common->ccmp_keymap)) 6062306a36Sopenharmony_ci rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_ci mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) && 6362306a36Sopenharmony_ci !ieee80211_has_morefrags(fc) && 6462306a36Sopenharmony_ci !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) && 6562306a36Sopenharmony_ci (rx_stats->rs_status & ATH9K_RXERR_MIC); 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci /* 6862306a36Sopenharmony_ci * The rx_stats->rs_status will not be set until the end of the 6962306a36Sopenharmony_ci * chained descriptors so it can be ignored if rs_more is set. The 7062306a36Sopenharmony_ci * rs_more will be false at the last element of the chained 7162306a36Sopenharmony_ci * descriptors. 7262306a36Sopenharmony_ci */ 7362306a36Sopenharmony_ci if (rx_stats->rs_status != 0) { 7462306a36Sopenharmony_ci u8 status_mask; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci if (rx_stats->rs_status & ATH9K_RXERR_CRC) { 7762306a36Sopenharmony_ci rxs->flag |= RX_FLAG_FAILED_FCS_CRC; 7862306a36Sopenharmony_ci mic_error = false; 7962306a36Sopenharmony_ci } 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) || 8262306a36Sopenharmony_ci (!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) { 8362306a36Sopenharmony_ci *decrypt_error = true; 8462306a36Sopenharmony_ci mic_error = false; 8562306a36Sopenharmony_ci } 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci 8862306a36Sopenharmony_ci /* 8962306a36Sopenharmony_ci * Reject error frames with the exception of 9062306a36Sopenharmony_ci * decryption and MIC failures. For monitor mode, 9162306a36Sopenharmony_ci * we also ignore the CRC error. 9262306a36Sopenharmony_ci */ 9362306a36Sopenharmony_ci status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | 9462306a36Sopenharmony_ci ATH9K_RXERR_KEYMISS; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci if (ah->is_monitoring && (rxfilter & FIF_FCSFAIL)) 9762306a36Sopenharmony_ci status_mask |= ATH9K_RXERR_CRC; 9862306a36Sopenharmony_ci 9962306a36Sopenharmony_ci if (rx_stats->rs_status & ~status_mask) 10062306a36Sopenharmony_ci return false; 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci /* 10462306a36Sopenharmony_ci * For unicast frames the MIC error bit can have false positives, 10562306a36Sopenharmony_ci * so all MIC error reports need to be validated in software. 10662306a36Sopenharmony_ci * False negatives are not common, so skip software verification 10762306a36Sopenharmony_ci * if the hardware considers the MIC valid. 10862306a36Sopenharmony_ci */ 10962306a36Sopenharmony_ci if (strip_mic) 11062306a36Sopenharmony_ci rxs->flag |= RX_FLAG_MMIC_STRIPPED; 11162306a36Sopenharmony_ci else if (is_mc && mic_error) 11262306a36Sopenharmony_ci rxs->flag |= RX_FLAG_MMIC_ERROR; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci return true; 11562306a36Sopenharmony_ci} 11662306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_rx_accept); 11762306a36Sopenharmony_ci 11862306a36Sopenharmony_civoid ath9k_cmn_rx_skb_postprocess(struct ath_common *common, 11962306a36Sopenharmony_ci struct sk_buff *skb, 12062306a36Sopenharmony_ci struct ath_rx_status *rx_stats, 12162306a36Sopenharmony_ci struct ieee80211_rx_status *rxs, 12262306a36Sopenharmony_ci bool decrypt_error) 12362306a36Sopenharmony_ci{ 12462306a36Sopenharmony_ci struct ath_hw *ah = common->ah; 12562306a36Sopenharmony_ci struct ieee80211_hdr *hdr; 12662306a36Sopenharmony_ci int hdrlen, padpos, padsize; 12762306a36Sopenharmony_ci u8 keyix; 12862306a36Sopenharmony_ci __le16 fc; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci /* see if any padding is done by the hw and remove it */ 13162306a36Sopenharmony_ci hdr = (struct ieee80211_hdr *) skb->data; 13262306a36Sopenharmony_ci hdrlen = ieee80211_get_hdrlen_from_skb(skb); 13362306a36Sopenharmony_ci fc = hdr->frame_control; 13462306a36Sopenharmony_ci padpos = ieee80211_hdrlen(fc); 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci /* The MAC header is padded to have 32-bit boundary if the 13762306a36Sopenharmony_ci * packet payload is non-zero. The general calculation for 13862306a36Sopenharmony_ci * padsize would take into account odd header lengths: 13962306a36Sopenharmony_ci * padsize = (4 - padpos % 4) % 4; However, since only 14062306a36Sopenharmony_ci * even-length headers are used, padding can only be 0 or 2 14162306a36Sopenharmony_ci * bytes and we can optimize this a bit. In addition, we must 14262306a36Sopenharmony_ci * not try to remove padding from short control frames that do 14362306a36Sopenharmony_ci * not have payload. */ 14462306a36Sopenharmony_ci padsize = padpos & 3; 14562306a36Sopenharmony_ci if (padsize && skb->len>=padpos+padsize+FCS_LEN) { 14662306a36Sopenharmony_ci memmove(skb->data + padsize, skb->data, padpos); 14762306a36Sopenharmony_ci skb_pull(skb, padsize); 14862306a36Sopenharmony_ci } 14962306a36Sopenharmony_ci 15062306a36Sopenharmony_ci keyix = rx_stats->rs_keyix; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error && 15362306a36Sopenharmony_ci ieee80211_has_protected(fc)) { 15462306a36Sopenharmony_ci rxs->flag |= RX_FLAG_DECRYPTED; 15562306a36Sopenharmony_ci } else if (ieee80211_has_protected(fc) 15662306a36Sopenharmony_ci && !decrypt_error && skb->len >= hdrlen + 4) { 15762306a36Sopenharmony_ci keyix = skb->data[hdrlen + 3] >> 6; 15862306a36Sopenharmony_ci 15962306a36Sopenharmony_ci if (test_bit(keyix, common->keymap)) 16062306a36Sopenharmony_ci rxs->flag |= RX_FLAG_DECRYPTED; 16162306a36Sopenharmony_ci } 16262306a36Sopenharmony_ci if (ah->sw_mgmt_crypto_rx && 16362306a36Sopenharmony_ci (rxs->flag & RX_FLAG_DECRYPTED) && 16462306a36Sopenharmony_ci ieee80211_is_mgmt(fc)) 16562306a36Sopenharmony_ci /* Use software decrypt for management frames. */ 16662306a36Sopenharmony_ci rxs->flag &= ~RX_FLAG_DECRYPTED; 16762306a36Sopenharmony_ci} 16862306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess); 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ciint ath9k_cmn_process_rate(struct ath_common *common, 17162306a36Sopenharmony_ci struct ieee80211_hw *hw, 17262306a36Sopenharmony_ci struct ath_rx_status *rx_stats, 17362306a36Sopenharmony_ci struct ieee80211_rx_status *rxs) 17462306a36Sopenharmony_ci{ 17562306a36Sopenharmony_ci struct ieee80211_supported_band *sband; 17662306a36Sopenharmony_ci enum nl80211_band band; 17762306a36Sopenharmony_ci unsigned int i = 0; 17862306a36Sopenharmony_ci struct ath_hw *ah = common->ah; 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci band = ah->curchan->chan->band; 18162306a36Sopenharmony_ci sband = hw->wiphy->bands[band]; 18262306a36Sopenharmony_ci 18362306a36Sopenharmony_ci if (IS_CHAN_QUARTER_RATE(ah->curchan)) 18462306a36Sopenharmony_ci rxs->bw = RATE_INFO_BW_5; 18562306a36Sopenharmony_ci else if (IS_CHAN_HALF_RATE(ah->curchan)) 18662306a36Sopenharmony_ci rxs->bw = RATE_INFO_BW_10; 18762306a36Sopenharmony_ci 18862306a36Sopenharmony_ci if (rx_stats->rs_rate & 0x80) { 18962306a36Sopenharmony_ci /* HT rate */ 19062306a36Sopenharmony_ci rxs->encoding = RX_ENC_HT; 19162306a36Sopenharmony_ci rxs->enc_flags |= rx_stats->enc_flags; 19262306a36Sopenharmony_ci rxs->bw = rx_stats->bw; 19362306a36Sopenharmony_ci rxs->rate_idx = rx_stats->rs_rate & 0x7f; 19462306a36Sopenharmony_ci return 0; 19562306a36Sopenharmony_ci } 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ci for (i = 0; i < sband->n_bitrates; i++) { 19862306a36Sopenharmony_ci if (sband->bitrates[i].hw_value == rx_stats->rs_rate) { 19962306a36Sopenharmony_ci rxs->rate_idx = i; 20062306a36Sopenharmony_ci return 0; 20162306a36Sopenharmony_ci } 20262306a36Sopenharmony_ci if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) { 20362306a36Sopenharmony_ci rxs->enc_flags |= RX_ENC_FLAG_SHORTPRE; 20462306a36Sopenharmony_ci rxs->rate_idx = i; 20562306a36Sopenharmony_ci return 0; 20662306a36Sopenharmony_ci } 20762306a36Sopenharmony_ci } 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci return -EINVAL; 21062306a36Sopenharmony_ci} 21162306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_process_rate); 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_civoid ath9k_cmn_process_rssi(struct ath_common *common, 21462306a36Sopenharmony_ci struct ieee80211_hw *hw, 21562306a36Sopenharmony_ci struct ath_rx_status *rx_stats, 21662306a36Sopenharmony_ci struct ieee80211_rx_status *rxs) 21762306a36Sopenharmony_ci{ 21862306a36Sopenharmony_ci struct ath_hw *ah = common->ah; 21962306a36Sopenharmony_ci int last_rssi; 22062306a36Sopenharmony_ci int rssi = rx_stats->rs_rssi; 22162306a36Sopenharmony_ci int i, j; 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci /* 22462306a36Sopenharmony_ci * RSSI is not available for subframes in an A-MPDU. 22562306a36Sopenharmony_ci */ 22662306a36Sopenharmony_ci if (rx_stats->rs_moreaggr) { 22762306a36Sopenharmony_ci rxs->flag |= RX_FLAG_NO_SIGNAL_VAL; 22862306a36Sopenharmony_ci return; 22962306a36Sopenharmony_ci } 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci /* 23262306a36Sopenharmony_ci * Check if the RSSI for the last subframe in an A-MPDU 23362306a36Sopenharmony_ci * or an unaggregated frame is valid. 23462306a36Sopenharmony_ci */ 23562306a36Sopenharmony_ci if (rx_stats->rs_rssi == ATH9K_RSSI_BAD) { 23662306a36Sopenharmony_ci rxs->flag |= RX_FLAG_NO_SIGNAL_VAL; 23762306a36Sopenharmony_ci return; 23862306a36Sopenharmony_ci } 23962306a36Sopenharmony_ci 24062306a36Sopenharmony_ci for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) { 24162306a36Sopenharmony_ci s8 rssi; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci if (!(ah->rxchainmask & BIT(i))) 24462306a36Sopenharmony_ci continue; 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci rssi = rx_stats->rs_rssi_ctl[i]; 24762306a36Sopenharmony_ci if (rssi != ATH9K_RSSI_BAD) { 24862306a36Sopenharmony_ci rxs->chains |= BIT(j); 24962306a36Sopenharmony_ci rxs->chain_signal[j] = ah->noise + rssi; 25062306a36Sopenharmony_ci } 25162306a36Sopenharmony_ci j++; 25262306a36Sopenharmony_ci } 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci /* 25562306a36Sopenharmony_ci * Update Beacon RSSI, this is used by ANI. 25662306a36Sopenharmony_ci */ 25762306a36Sopenharmony_ci if (rx_stats->is_mybeacon && 25862306a36Sopenharmony_ci ((ah->opmode == NL80211_IFTYPE_STATION) || 25962306a36Sopenharmony_ci (ah->opmode == NL80211_IFTYPE_ADHOC))) { 26062306a36Sopenharmony_ci ATH_RSSI_LPF(common->last_rssi, rx_stats->rs_rssi); 26162306a36Sopenharmony_ci last_rssi = common->last_rssi; 26262306a36Sopenharmony_ci 26362306a36Sopenharmony_ci if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) 26462306a36Sopenharmony_ci rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER); 26562306a36Sopenharmony_ci if (rssi < 0) 26662306a36Sopenharmony_ci rssi = 0; 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci ah->stats.avgbrssi = rssi; 26962306a36Sopenharmony_ci } 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci rxs->signal = ah->noise + rx_stats->rs_rssi; 27262306a36Sopenharmony_ci} 27362306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_process_rssi); 27462306a36Sopenharmony_ci 27562306a36Sopenharmony_ciint ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb) 27662306a36Sopenharmony_ci{ 27762306a36Sopenharmony_ci struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci if (tx_info->control.hw_key) { 28062306a36Sopenharmony_ci switch (tx_info->control.hw_key->cipher) { 28162306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_WEP40: 28262306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_WEP104: 28362306a36Sopenharmony_ci return ATH9K_KEY_TYPE_WEP; 28462306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_TKIP: 28562306a36Sopenharmony_ci return ATH9K_KEY_TYPE_TKIP; 28662306a36Sopenharmony_ci case WLAN_CIPHER_SUITE_CCMP: 28762306a36Sopenharmony_ci return ATH9K_KEY_TYPE_AES; 28862306a36Sopenharmony_ci default: 28962306a36Sopenharmony_ci break; 29062306a36Sopenharmony_ci } 29162306a36Sopenharmony_ci } 29262306a36Sopenharmony_ci 29362306a36Sopenharmony_ci return ATH9K_KEY_TYPE_CLEAR; 29462306a36Sopenharmony_ci} 29562306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype); 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_ci/* 29862306a36Sopenharmony_ci * Update internal channel flags. 29962306a36Sopenharmony_ci */ 30062306a36Sopenharmony_cistatic void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, 30162306a36Sopenharmony_ci struct cfg80211_chan_def *chandef) 30262306a36Sopenharmony_ci{ 30362306a36Sopenharmony_ci struct ieee80211_channel *chan = chandef->chan; 30462306a36Sopenharmony_ci u16 flags = 0; 30562306a36Sopenharmony_ci 30662306a36Sopenharmony_ci ichan->channel = chan->center_freq; 30762306a36Sopenharmony_ci ichan->chan = chan; 30862306a36Sopenharmony_ci 30962306a36Sopenharmony_ci if (chan->band == NL80211_BAND_5GHZ) 31062306a36Sopenharmony_ci flags |= CHANNEL_5GHZ; 31162306a36Sopenharmony_ci 31262306a36Sopenharmony_ci switch (chandef->width) { 31362306a36Sopenharmony_ci case NL80211_CHAN_WIDTH_5: 31462306a36Sopenharmony_ci flags |= CHANNEL_QUARTER; 31562306a36Sopenharmony_ci break; 31662306a36Sopenharmony_ci case NL80211_CHAN_WIDTH_10: 31762306a36Sopenharmony_ci flags |= CHANNEL_HALF; 31862306a36Sopenharmony_ci break; 31962306a36Sopenharmony_ci case NL80211_CHAN_WIDTH_20_NOHT: 32062306a36Sopenharmony_ci break; 32162306a36Sopenharmony_ci case NL80211_CHAN_WIDTH_20: 32262306a36Sopenharmony_ci flags |= CHANNEL_HT; 32362306a36Sopenharmony_ci break; 32462306a36Sopenharmony_ci case NL80211_CHAN_WIDTH_40: 32562306a36Sopenharmony_ci if (chandef->center_freq1 > chandef->chan->center_freq) 32662306a36Sopenharmony_ci flags |= CHANNEL_HT40PLUS | CHANNEL_HT; 32762306a36Sopenharmony_ci else 32862306a36Sopenharmony_ci flags |= CHANNEL_HT40MINUS | CHANNEL_HT; 32962306a36Sopenharmony_ci break; 33062306a36Sopenharmony_ci default: 33162306a36Sopenharmony_ci WARN_ON(1); 33262306a36Sopenharmony_ci } 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci ichan->channelFlags = flags; 33562306a36Sopenharmony_ci} 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci/* 33862306a36Sopenharmony_ci * Get the internal channel reference. 33962306a36Sopenharmony_ci */ 34062306a36Sopenharmony_cistruct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw, 34162306a36Sopenharmony_ci struct ath_hw *ah, 34262306a36Sopenharmony_ci struct cfg80211_chan_def *chandef) 34362306a36Sopenharmony_ci{ 34462306a36Sopenharmony_ci struct ieee80211_channel *curchan = chandef->chan; 34562306a36Sopenharmony_ci struct ath9k_channel *channel; 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci channel = &ah->channels[curchan->hw_value]; 34862306a36Sopenharmony_ci ath9k_cmn_update_ichannel(channel, chandef); 34962306a36Sopenharmony_ci 35062306a36Sopenharmony_ci return channel; 35162306a36Sopenharmony_ci} 35262306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_get_channel); 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ciint ath9k_cmn_count_streams(unsigned int chainmask, int max) 35562306a36Sopenharmony_ci{ 35662306a36Sopenharmony_ci int streams = 0; 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_ci do { 35962306a36Sopenharmony_ci if (++streams == max) 36062306a36Sopenharmony_ci break; 36162306a36Sopenharmony_ci } while ((chainmask = chainmask & (chainmask - 1))); 36262306a36Sopenharmony_ci 36362306a36Sopenharmony_ci return streams; 36462306a36Sopenharmony_ci} 36562306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_count_streams); 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_civoid ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow, 36862306a36Sopenharmony_ci u16 new_txpow, u16 *txpower) 36962306a36Sopenharmony_ci{ 37062306a36Sopenharmony_ci struct ath_regulatory *reg = ath9k_hw_regulatory(ah); 37162306a36Sopenharmony_ci 37262306a36Sopenharmony_ci if (ah->curchan && reg->power_limit != new_txpow) 37362306a36Sopenharmony_ci ath9k_hw_set_txpowerlimit(ah, new_txpow, false); 37462306a36Sopenharmony_ci 37562306a36Sopenharmony_ci /* read back in case value is clamped */ 37662306a36Sopenharmony_ci *txpower = reg->max_power_level; 37762306a36Sopenharmony_ci} 37862306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_update_txpow); 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_civoid ath9k_cmn_init_crypto(struct ath_hw *ah) 38162306a36Sopenharmony_ci{ 38262306a36Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 38362306a36Sopenharmony_ci int i = 0; 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ci /* Get the hardware key cache size. */ 38662306a36Sopenharmony_ci common->keymax = AR_KEYTABLE_SIZE; 38762306a36Sopenharmony_ci 38862306a36Sopenharmony_ci /* 38962306a36Sopenharmony_ci * Check whether the separate key cache entries 39062306a36Sopenharmony_ci * are required to handle both tx+rx MIC keys. 39162306a36Sopenharmony_ci * With split mic keys the number of stations is limited 39262306a36Sopenharmony_ci * to 27 otherwise 59. 39362306a36Sopenharmony_ci */ 39462306a36Sopenharmony_ci if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) 39562306a36Sopenharmony_ci common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; 39662306a36Sopenharmony_ci 39762306a36Sopenharmony_ci /* 39862306a36Sopenharmony_ci * Reset the key cache since some parts do not 39962306a36Sopenharmony_ci * reset the contents on initial power up. 40062306a36Sopenharmony_ci */ 40162306a36Sopenharmony_ci for (i = 0; i < common->keymax; i++) 40262306a36Sopenharmony_ci ath_hw_keyreset(common, (u16) i); 40362306a36Sopenharmony_ci} 40462306a36Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_init_crypto); 40562306a36Sopenharmony_ci 40662306a36Sopenharmony_cistatic int __init ath9k_cmn_init(void) 40762306a36Sopenharmony_ci{ 40862306a36Sopenharmony_ci return 0; 40962306a36Sopenharmony_ci} 41062306a36Sopenharmony_cimodule_init(ath9k_cmn_init); 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_cistatic void __exit ath9k_cmn_exit(void) 41362306a36Sopenharmony_ci{ 41462306a36Sopenharmony_ci return; 41562306a36Sopenharmony_ci} 41662306a36Sopenharmony_cimodule_exit(ath9k_cmn_exit); 417