18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Copyright (c) 2009-2011 Atheros Communications Inc. 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any 58c2ecf20Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above 68c2ecf20Sopenharmony_ci * copyright notice and this permission notice appear in all copies. 78c2ecf20Sopenharmony_ci * 88c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 98c2ecf20Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 108c2ecf20Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 118c2ecf20Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 128c2ecf20Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 138c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 148c2ecf20Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 158c2ecf20Sopenharmony_ci */ 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci/* 188c2ecf20Sopenharmony_ci * Module for common driver code between ath9k and ath9k_htc 198c2ecf20Sopenharmony_ci */ 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include <linux/kernel.h> 228c2ecf20Sopenharmony_ci#include <linux/module.h> 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci#include "common.h" 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ciMODULE_AUTHOR("Atheros Communications"); 278c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards."); 288c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL"); 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci/* Assumes you've already done the endian to CPU conversion */ 318c2ecf20Sopenharmony_cibool ath9k_cmn_rx_accept(struct ath_common *common, 328c2ecf20Sopenharmony_ci struct ieee80211_hdr *hdr, 338c2ecf20Sopenharmony_ci struct ieee80211_rx_status *rxs, 348c2ecf20Sopenharmony_ci struct ath_rx_status *rx_stats, 358c2ecf20Sopenharmony_ci bool *decrypt_error, 368c2ecf20Sopenharmony_ci unsigned int rxfilter) 378c2ecf20Sopenharmony_ci{ 388c2ecf20Sopenharmony_ci struct ath_hw *ah = common->ah; 398c2ecf20Sopenharmony_ci bool is_mc, is_valid_tkip, strip_mic, mic_error; 408c2ecf20Sopenharmony_ci __le16 fc; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci fc = hdr->frame_control; 438c2ecf20Sopenharmony_ci 448c2ecf20Sopenharmony_ci is_mc = !!is_multicast_ether_addr(hdr->addr1); 458c2ecf20Sopenharmony_ci is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID && 468c2ecf20Sopenharmony_ci test_bit(rx_stats->rs_keyix, common->tkip_keymap); 478c2ecf20Sopenharmony_ci strip_mic = is_valid_tkip && ieee80211_is_data(fc) && 488c2ecf20Sopenharmony_ci ieee80211_has_protected(fc) && 498c2ecf20Sopenharmony_ci !(rx_stats->rs_status & 508c2ecf20Sopenharmony_ci (ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC | 518c2ecf20Sopenharmony_ci ATH9K_RXERR_KEYMISS)); 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci /* 548c2ecf20Sopenharmony_ci * Key miss events are only relevant for pairwise keys where the 558c2ecf20Sopenharmony_ci * descriptor does contain a valid key index. This has been observed 568c2ecf20Sopenharmony_ci * mostly with CCMP encryption. 578c2ecf20Sopenharmony_ci */ 588c2ecf20Sopenharmony_ci if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID || 598c2ecf20Sopenharmony_ci !test_bit(rx_stats->rs_keyix, common->ccmp_keymap)) 608c2ecf20Sopenharmony_ci rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS; 618c2ecf20Sopenharmony_ci 628c2ecf20Sopenharmony_ci mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) && 638c2ecf20Sopenharmony_ci !ieee80211_has_morefrags(fc) && 648c2ecf20Sopenharmony_ci !(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) && 658c2ecf20Sopenharmony_ci (rx_stats->rs_status & ATH9K_RXERR_MIC); 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_ci /* 688c2ecf20Sopenharmony_ci * The rx_stats->rs_status will not be set until the end of the 698c2ecf20Sopenharmony_ci * chained descriptors so it can be ignored if rs_more is set. The 708c2ecf20Sopenharmony_ci * rs_more will be false at the last element of the chained 718c2ecf20Sopenharmony_ci * descriptors. 728c2ecf20Sopenharmony_ci */ 738c2ecf20Sopenharmony_ci if (rx_stats->rs_status != 0) { 748c2ecf20Sopenharmony_ci u8 status_mask; 758c2ecf20Sopenharmony_ci 768c2ecf20Sopenharmony_ci if (rx_stats->rs_status & ATH9K_RXERR_CRC) { 778c2ecf20Sopenharmony_ci rxs->flag |= RX_FLAG_FAILED_FCS_CRC; 788c2ecf20Sopenharmony_ci mic_error = false; 798c2ecf20Sopenharmony_ci } 808c2ecf20Sopenharmony_ci 818c2ecf20Sopenharmony_ci if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) || 828c2ecf20Sopenharmony_ci (!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) { 838c2ecf20Sopenharmony_ci *decrypt_error = true; 848c2ecf20Sopenharmony_ci mic_error = false; 858c2ecf20Sopenharmony_ci } 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci /* 898c2ecf20Sopenharmony_ci * Reject error frames with the exception of 908c2ecf20Sopenharmony_ci * decryption and MIC failures. For monitor mode, 918c2ecf20Sopenharmony_ci * we also ignore the CRC error. 928c2ecf20Sopenharmony_ci */ 938c2ecf20Sopenharmony_ci status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | 948c2ecf20Sopenharmony_ci ATH9K_RXERR_KEYMISS; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci if (ah->is_monitoring && (rxfilter & FIF_FCSFAIL)) 978c2ecf20Sopenharmony_ci status_mask |= ATH9K_RXERR_CRC; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci if (rx_stats->rs_status & ~status_mask) 1008c2ecf20Sopenharmony_ci return false; 1018c2ecf20Sopenharmony_ci } 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci /* 1048c2ecf20Sopenharmony_ci * For unicast frames the MIC error bit can have false positives, 1058c2ecf20Sopenharmony_ci * so all MIC error reports need to be validated in software. 1068c2ecf20Sopenharmony_ci * False negatives are not common, so skip software verification 1078c2ecf20Sopenharmony_ci * if the hardware considers the MIC valid. 1088c2ecf20Sopenharmony_ci */ 1098c2ecf20Sopenharmony_ci if (strip_mic) 1108c2ecf20Sopenharmony_ci rxs->flag |= RX_FLAG_MMIC_STRIPPED; 1118c2ecf20Sopenharmony_ci else if (is_mc && mic_error) 1128c2ecf20Sopenharmony_ci rxs->flag |= RX_FLAG_MMIC_ERROR; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci return true; 1158c2ecf20Sopenharmony_ci} 1168c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_rx_accept); 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_civoid ath9k_cmn_rx_skb_postprocess(struct ath_common *common, 1198c2ecf20Sopenharmony_ci struct sk_buff *skb, 1208c2ecf20Sopenharmony_ci struct ath_rx_status *rx_stats, 1218c2ecf20Sopenharmony_ci struct ieee80211_rx_status *rxs, 1228c2ecf20Sopenharmony_ci bool decrypt_error) 1238c2ecf20Sopenharmony_ci{ 1248c2ecf20Sopenharmony_ci struct ath_hw *ah = common->ah; 1258c2ecf20Sopenharmony_ci struct ieee80211_hdr *hdr; 1268c2ecf20Sopenharmony_ci int hdrlen, padpos, padsize; 1278c2ecf20Sopenharmony_ci u8 keyix; 1288c2ecf20Sopenharmony_ci __le16 fc; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci /* see if any padding is done by the hw and remove it */ 1318c2ecf20Sopenharmony_ci hdr = (struct ieee80211_hdr *) skb->data; 1328c2ecf20Sopenharmony_ci hdrlen = ieee80211_get_hdrlen_from_skb(skb); 1338c2ecf20Sopenharmony_ci fc = hdr->frame_control; 1348c2ecf20Sopenharmony_ci padpos = ieee80211_hdrlen(fc); 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_ci /* The MAC header is padded to have 32-bit boundary if the 1378c2ecf20Sopenharmony_ci * packet payload is non-zero. The general calculation for 1388c2ecf20Sopenharmony_ci * padsize would take into account odd header lengths: 1398c2ecf20Sopenharmony_ci * padsize = (4 - padpos % 4) % 4; However, since only 1408c2ecf20Sopenharmony_ci * even-length headers are used, padding can only be 0 or 2 1418c2ecf20Sopenharmony_ci * bytes and we can optimize this a bit. In addition, we must 1428c2ecf20Sopenharmony_ci * not try to remove padding from short control frames that do 1438c2ecf20Sopenharmony_ci * not have payload. */ 1448c2ecf20Sopenharmony_ci padsize = padpos & 3; 1458c2ecf20Sopenharmony_ci if (padsize && skb->len>=padpos+padsize+FCS_LEN) { 1468c2ecf20Sopenharmony_ci memmove(skb->data + padsize, skb->data, padpos); 1478c2ecf20Sopenharmony_ci skb_pull(skb, padsize); 1488c2ecf20Sopenharmony_ci } 1498c2ecf20Sopenharmony_ci 1508c2ecf20Sopenharmony_ci keyix = rx_stats->rs_keyix; 1518c2ecf20Sopenharmony_ci 1528c2ecf20Sopenharmony_ci if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error && 1538c2ecf20Sopenharmony_ci ieee80211_has_protected(fc)) { 1548c2ecf20Sopenharmony_ci rxs->flag |= RX_FLAG_DECRYPTED; 1558c2ecf20Sopenharmony_ci } else if (ieee80211_has_protected(fc) 1568c2ecf20Sopenharmony_ci && !decrypt_error && skb->len >= hdrlen + 4) { 1578c2ecf20Sopenharmony_ci keyix = skb->data[hdrlen + 3] >> 6; 1588c2ecf20Sopenharmony_ci 1598c2ecf20Sopenharmony_ci if (test_bit(keyix, common->keymap)) 1608c2ecf20Sopenharmony_ci rxs->flag |= RX_FLAG_DECRYPTED; 1618c2ecf20Sopenharmony_ci } 1628c2ecf20Sopenharmony_ci if (ah->sw_mgmt_crypto_rx && 1638c2ecf20Sopenharmony_ci (rxs->flag & RX_FLAG_DECRYPTED) && 1648c2ecf20Sopenharmony_ci ieee80211_is_mgmt(fc)) 1658c2ecf20Sopenharmony_ci /* Use software decrypt for management frames. */ 1668c2ecf20Sopenharmony_ci rxs->flag &= ~RX_FLAG_DECRYPTED; 1678c2ecf20Sopenharmony_ci} 1688c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess); 1698c2ecf20Sopenharmony_ci 1708c2ecf20Sopenharmony_ciint ath9k_cmn_process_rate(struct ath_common *common, 1718c2ecf20Sopenharmony_ci struct ieee80211_hw *hw, 1728c2ecf20Sopenharmony_ci struct ath_rx_status *rx_stats, 1738c2ecf20Sopenharmony_ci struct ieee80211_rx_status *rxs) 1748c2ecf20Sopenharmony_ci{ 1758c2ecf20Sopenharmony_ci struct ieee80211_supported_band *sband; 1768c2ecf20Sopenharmony_ci enum nl80211_band band; 1778c2ecf20Sopenharmony_ci unsigned int i = 0; 1788c2ecf20Sopenharmony_ci struct ath_hw *ah = common->ah; 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci band = ah->curchan->chan->band; 1818c2ecf20Sopenharmony_ci sband = hw->wiphy->bands[band]; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci if (IS_CHAN_QUARTER_RATE(ah->curchan)) 1848c2ecf20Sopenharmony_ci rxs->bw = RATE_INFO_BW_5; 1858c2ecf20Sopenharmony_ci else if (IS_CHAN_HALF_RATE(ah->curchan)) 1868c2ecf20Sopenharmony_ci rxs->bw = RATE_INFO_BW_10; 1878c2ecf20Sopenharmony_ci 1888c2ecf20Sopenharmony_ci if (rx_stats->rs_rate & 0x80) { 1898c2ecf20Sopenharmony_ci /* HT rate */ 1908c2ecf20Sopenharmony_ci rxs->encoding = RX_ENC_HT; 1918c2ecf20Sopenharmony_ci rxs->enc_flags |= rx_stats->enc_flags; 1928c2ecf20Sopenharmony_ci rxs->bw = rx_stats->bw; 1938c2ecf20Sopenharmony_ci rxs->rate_idx = rx_stats->rs_rate & 0x7f; 1948c2ecf20Sopenharmony_ci return 0; 1958c2ecf20Sopenharmony_ci } 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci for (i = 0; i < sband->n_bitrates; i++) { 1988c2ecf20Sopenharmony_ci if (sband->bitrates[i].hw_value == rx_stats->rs_rate) { 1998c2ecf20Sopenharmony_ci rxs->rate_idx = i; 2008c2ecf20Sopenharmony_ci return 0; 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) { 2038c2ecf20Sopenharmony_ci rxs->enc_flags |= RX_ENC_FLAG_SHORTPRE; 2048c2ecf20Sopenharmony_ci rxs->rate_idx = i; 2058c2ecf20Sopenharmony_ci return 0; 2068c2ecf20Sopenharmony_ci } 2078c2ecf20Sopenharmony_ci } 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci return -EINVAL; 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_process_rate); 2128c2ecf20Sopenharmony_ci 2138c2ecf20Sopenharmony_civoid ath9k_cmn_process_rssi(struct ath_common *common, 2148c2ecf20Sopenharmony_ci struct ieee80211_hw *hw, 2158c2ecf20Sopenharmony_ci struct ath_rx_status *rx_stats, 2168c2ecf20Sopenharmony_ci struct ieee80211_rx_status *rxs) 2178c2ecf20Sopenharmony_ci{ 2188c2ecf20Sopenharmony_ci struct ath_hw *ah = common->ah; 2198c2ecf20Sopenharmony_ci int last_rssi; 2208c2ecf20Sopenharmony_ci int rssi = rx_stats->rs_rssi; 2218c2ecf20Sopenharmony_ci int i, j; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci /* 2248c2ecf20Sopenharmony_ci * RSSI is not available for subframes in an A-MPDU. 2258c2ecf20Sopenharmony_ci */ 2268c2ecf20Sopenharmony_ci if (rx_stats->rs_moreaggr) { 2278c2ecf20Sopenharmony_ci rxs->flag |= RX_FLAG_NO_SIGNAL_VAL; 2288c2ecf20Sopenharmony_ci return; 2298c2ecf20Sopenharmony_ci } 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci /* 2328c2ecf20Sopenharmony_ci * Check if the RSSI for the last subframe in an A-MPDU 2338c2ecf20Sopenharmony_ci * or an unaggregated frame is valid. 2348c2ecf20Sopenharmony_ci */ 2358c2ecf20Sopenharmony_ci if (rx_stats->rs_rssi == ATH9K_RSSI_BAD) { 2368c2ecf20Sopenharmony_ci rxs->flag |= RX_FLAG_NO_SIGNAL_VAL; 2378c2ecf20Sopenharmony_ci return; 2388c2ecf20Sopenharmony_ci } 2398c2ecf20Sopenharmony_ci 2408c2ecf20Sopenharmony_ci for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) { 2418c2ecf20Sopenharmony_ci s8 rssi; 2428c2ecf20Sopenharmony_ci 2438c2ecf20Sopenharmony_ci if (!(ah->rxchainmask & BIT(i))) 2448c2ecf20Sopenharmony_ci continue; 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci rssi = rx_stats->rs_rssi_ctl[i]; 2478c2ecf20Sopenharmony_ci if (rssi != ATH9K_RSSI_BAD) { 2488c2ecf20Sopenharmony_ci rxs->chains |= BIT(j); 2498c2ecf20Sopenharmony_ci rxs->chain_signal[j] = ah->noise + rssi; 2508c2ecf20Sopenharmony_ci } 2518c2ecf20Sopenharmony_ci j++; 2528c2ecf20Sopenharmony_ci } 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci /* 2558c2ecf20Sopenharmony_ci * Update Beacon RSSI, this is used by ANI. 2568c2ecf20Sopenharmony_ci */ 2578c2ecf20Sopenharmony_ci if (rx_stats->is_mybeacon && 2588c2ecf20Sopenharmony_ci ((ah->opmode == NL80211_IFTYPE_STATION) || 2598c2ecf20Sopenharmony_ci (ah->opmode == NL80211_IFTYPE_ADHOC))) { 2608c2ecf20Sopenharmony_ci ATH_RSSI_LPF(common->last_rssi, rx_stats->rs_rssi); 2618c2ecf20Sopenharmony_ci last_rssi = common->last_rssi; 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_ci if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) 2648c2ecf20Sopenharmony_ci rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER); 2658c2ecf20Sopenharmony_ci if (rssi < 0) 2668c2ecf20Sopenharmony_ci rssi = 0; 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci ah->stats.avgbrssi = rssi; 2698c2ecf20Sopenharmony_ci } 2708c2ecf20Sopenharmony_ci 2718c2ecf20Sopenharmony_ci rxs->signal = ah->noise + rx_stats->rs_rssi; 2728c2ecf20Sopenharmony_ci} 2738c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_process_rssi); 2748c2ecf20Sopenharmony_ci 2758c2ecf20Sopenharmony_ciint ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb) 2768c2ecf20Sopenharmony_ci{ 2778c2ecf20Sopenharmony_ci struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci if (tx_info->control.hw_key) { 2808c2ecf20Sopenharmony_ci switch (tx_info->control.hw_key->cipher) { 2818c2ecf20Sopenharmony_ci case WLAN_CIPHER_SUITE_WEP40: 2828c2ecf20Sopenharmony_ci case WLAN_CIPHER_SUITE_WEP104: 2838c2ecf20Sopenharmony_ci return ATH9K_KEY_TYPE_WEP; 2848c2ecf20Sopenharmony_ci case WLAN_CIPHER_SUITE_TKIP: 2858c2ecf20Sopenharmony_ci return ATH9K_KEY_TYPE_TKIP; 2868c2ecf20Sopenharmony_ci case WLAN_CIPHER_SUITE_CCMP: 2878c2ecf20Sopenharmony_ci return ATH9K_KEY_TYPE_AES; 2888c2ecf20Sopenharmony_ci default: 2898c2ecf20Sopenharmony_ci break; 2908c2ecf20Sopenharmony_ci } 2918c2ecf20Sopenharmony_ci } 2928c2ecf20Sopenharmony_ci 2938c2ecf20Sopenharmony_ci return ATH9K_KEY_TYPE_CLEAR; 2948c2ecf20Sopenharmony_ci} 2958c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype); 2968c2ecf20Sopenharmony_ci 2978c2ecf20Sopenharmony_ci/* 2988c2ecf20Sopenharmony_ci * Update internal channel flags. 2998c2ecf20Sopenharmony_ci */ 3008c2ecf20Sopenharmony_cistatic void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, 3018c2ecf20Sopenharmony_ci struct cfg80211_chan_def *chandef) 3028c2ecf20Sopenharmony_ci{ 3038c2ecf20Sopenharmony_ci struct ieee80211_channel *chan = chandef->chan; 3048c2ecf20Sopenharmony_ci u16 flags = 0; 3058c2ecf20Sopenharmony_ci 3068c2ecf20Sopenharmony_ci ichan->channel = chan->center_freq; 3078c2ecf20Sopenharmony_ci ichan->chan = chan; 3088c2ecf20Sopenharmony_ci 3098c2ecf20Sopenharmony_ci if (chan->band == NL80211_BAND_5GHZ) 3108c2ecf20Sopenharmony_ci flags |= CHANNEL_5GHZ; 3118c2ecf20Sopenharmony_ci 3128c2ecf20Sopenharmony_ci switch (chandef->width) { 3138c2ecf20Sopenharmony_ci case NL80211_CHAN_WIDTH_5: 3148c2ecf20Sopenharmony_ci flags |= CHANNEL_QUARTER; 3158c2ecf20Sopenharmony_ci break; 3168c2ecf20Sopenharmony_ci case NL80211_CHAN_WIDTH_10: 3178c2ecf20Sopenharmony_ci flags |= CHANNEL_HALF; 3188c2ecf20Sopenharmony_ci break; 3198c2ecf20Sopenharmony_ci case NL80211_CHAN_WIDTH_20_NOHT: 3208c2ecf20Sopenharmony_ci break; 3218c2ecf20Sopenharmony_ci case NL80211_CHAN_WIDTH_20: 3228c2ecf20Sopenharmony_ci flags |= CHANNEL_HT; 3238c2ecf20Sopenharmony_ci break; 3248c2ecf20Sopenharmony_ci case NL80211_CHAN_WIDTH_40: 3258c2ecf20Sopenharmony_ci if (chandef->center_freq1 > chandef->chan->center_freq) 3268c2ecf20Sopenharmony_ci flags |= CHANNEL_HT40PLUS | CHANNEL_HT; 3278c2ecf20Sopenharmony_ci else 3288c2ecf20Sopenharmony_ci flags |= CHANNEL_HT40MINUS | CHANNEL_HT; 3298c2ecf20Sopenharmony_ci break; 3308c2ecf20Sopenharmony_ci default: 3318c2ecf20Sopenharmony_ci WARN_ON(1); 3328c2ecf20Sopenharmony_ci } 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci ichan->channelFlags = flags; 3358c2ecf20Sopenharmony_ci} 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci/* 3388c2ecf20Sopenharmony_ci * Get the internal channel reference. 3398c2ecf20Sopenharmony_ci */ 3408c2ecf20Sopenharmony_cistruct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw, 3418c2ecf20Sopenharmony_ci struct ath_hw *ah, 3428c2ecf20Sopenharmony_ci struct cfg80211_chan_def *chandef) 3438c2ecf20Sopenharmony_ci{ 3448c2ecf20Sopenharmony_ci struct ieee80211_channel *curchan = chandef->chan; 3458c2ecf20Sopenharmony_ci struct ath9k_channel *channel; 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_ci channel = &ah->channels[curchan->hw_value]; 3488c2ecf20Sopenharmony_ci ath9k_cmn_update_ichannel(channel, chandef); 3498c2ecf20Sopenharmony_ci 3508c2ecf20Sopenharmony_ci return channel; 3518c2ecf20Sopenharmony_ci} 3528c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_get_channel); 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_ciint ath9k_cmn_count_streams(unsigned int chainmask, int max) 3558c2ecf20Sopenharmony_ci{ 3568c2ecf20Sopenharmony_ci int streams = 0; 3578c2ecf20Sopenharmony_ci 3588c2ecf20Sopenharmony_ci do { 3598c2ecf20Sopenharmony_ci if (++streams == max) 3608c2ecf20Sopenharmony_ci break; 3618c2ecf20Sopenharmony_ci } while ((chainmask = chainmask & (chainmask - 1))); 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci return streams; 3648c2ecf20Sopenharmony_ci} 3658c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_count_streams); 3668c2ecf20Sopenharmony_ci 3678c2ecf20Sopenharmony_civoid ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow, 3688c2ecf20Sopenharmony_ci u16 new_txpow, u16 *txpower) 3698c2ecf20Sopenharmony_ci{ 3708c2ecf20Sopenharmony_ci struct ath_regulatory *reg = ath9k_hw_regulatory(ah); 3718c2ecf20Sopenharmony_ci 3728c2ecf20Sopenharmony_ci if (ah->curchan && reg->power_limit != new_txpow) 3738c2ecf20Sopenharmony_ci ath9k_hw_set_txpowerlimit(ah, new_txpow, false); 3748c2ecf20Sopenharmony_ci 3758c2ecf20Sopenharmony_ci /* read back in case value is clamped */ 3768c2ecf20Sopenharmony_ci *txpower = reg->max_power_level; 3778c2ecf20Sopenharmony_ci} 3788c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_update_txpow); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_civoid ath9k_cmn_init_crypto(struct ath_hw *ah) 3818c2ecf20Sopenharmony_ci{ 3828c2ecf20Sopenharmony_ci struct ath_common *common = ath9k_hw_common(ah); 3838c2ecf20Sopenharmony_ci int i = 0; 3848c2ecf20Sopenharmony_ci 3858c2ecf20Sopenharmony_ci /* Get the hardware key cache size. */ 3868c2ecf20Sopenharmony_ci common->keymax = AR_KEYTABLE_SIZE; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci /* 3898c2ecf20Sopenharmony_ci * Check whether the separate key cache entries 3908c2ecf20Sopenharmony_ci * are required to handle both tx+rx MIC keys. 3918c2ecf20Sopenharmony_ci * With split mic keys the number of stations is limited 3928c2ecf20Sopenharmony_ci * to 27 otherwise 59. 3938c2ecf20Sopenharmony_ci */ 3948c2ecf20Sopenharmony_ci if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) 3958c2ecf20Sopenharmony_ci common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; 3968c2ecf20Sopenharmony_ci 3978c2ecf20Sopenharmony_ci /* 3988c2ecf20Sopenharmony_ci * Reset the key cache since some parts do not 3998c2ecf20Sopenharmony_ci * reset the contents on initial power up. 4008c2ecf20Sopenharmony_ci */ 4018c2ecf20Sopenharmony_ci for (i = 0; i < common->keymax; i++) 4028c2ecf20Sopenharmony_ci ath_hw_keyreset(common, (u16) i); 4038c2ecf20Sopenharmony_ci} 4048c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_init_crypto); 4058c2ecf20Sopenharmony_ci 4068c2ecf20Sopenharmony_cistatic int __init ath9k_cmn_init(void) 4078c2ecf20Sopenharmony_ci{ 4088c2ecf20Sopenharmony_ci return 0; 4098c2ecf20Sopenharmony_ci} 4108c2ecf20Sopenharmony_cimodule_init(ath9k_cmn_init); 4118c2ecf20Sopenharmony_ci 4128c2ecf20Sopenharmony_cistatic void __exit ath9k_cmn_exit(void) 4138c2ecf20Sopenharmony_ci{ 4148c2ecf20Sopenharmony_ci return; 4158c2ecf20Sopenharmony_ci} 4168c2ecf20Sopenharmony_cimodule_exit(ath9k_cmn_exit); 417