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 301bc14880SBenoit Papillault int ath9k_cmn_padpos(__le16 frame_control) 311bc14880SBenoit Papillault { 321bc14880SBenoit Papillault int padpos = 24; 331bc14880SBenoit Papillault if (ieee80211_has_a4(frame_control)) { 341bc14880SBenoit Papillault padpos += ETH_ALEN; 351bc14880SBenoit Papillault } 361bc14880SBenoit Papillault if (ieee80211_is_data_qos(frame_control)) { 371bc14880SBenoit Papillault padpos += IEEE80211_QOS_CTL_LEN; 381bc14880SBenoit Papillault } 391bc14880SBenoit Papillault 401bc14880SBenoit Papillault return padpos; 411bc14880SBenoit Papillault } 421bc14880SBenoit Papillault EXPORT_SYMBOL(ath9k_cmn_padpos); 431bc14880SBenoit Papillault 44fb9987d0SSujith int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb) 45fb9987d0SSujith { 46fb9987d0SSujith struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); 47fb9987d0SSujith 48fb9987d0SSujith if (tx_info->control.hw_key) { 4997359d12SJohannes Berg switch (tx_info->control.hw_key->cipher) { 5097359d12SJohannes Berg case WLAN_CIPHER_SUITE_WEP40: 5197359d12SJohannes Berg case WLAN_CIPHER_SUITE_WEP104: 52fb9987d0SSujith return ATH9K_KEY_TYPE_WEP; 5397359d12SJohannes Berg case WLAN_CIPHER_SUITE_TKIP: 54fb9987d0SSujith return ATH9K_KEY_TYPE_TKIP; 5597359d12SJohannes Berg case WLAN_CIPHER_SUITE_CCMP: 56fb9987d0SSujith return ATH9K_KEY_TYPE_AES; 5797359d12SJohannes Berg default: 5897359d12SJohannes Berg break; 5997359d12SJohannes Berg } 60fb9987d0SSujith } 61fb9987d0SSujith 62fb9987d0SSujith return ATH9K_KEY_TYPE_CLEAR; 63fb9987d0SSujith } 64fb9987d0SSujith EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype); 65fb9987d0SSujith 66fb9987d0SSujith static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan, 67fb9987d0SSujith enum nl80211_channel_type channel_type) 68fb9987d0SSujith { 69fb9987d0SSujith u32 chanmode = 0; 70fb9987d0SSujith 71fb9987d0SSujith switch (chan->band) { 72fb9987d0SSujith case IEEE80211_BAND_2GHZ: 73fb9987d0SSujith switch (channel_type) { 74fb9987d0SSujith case NL80211_CHAN_NO_HT: 75fb9987d0SSujith case NL80211_CHAN_HT20: 76fb9987d0SSujith chanmode = CHANNEL_G_HT20; 77fb9987d0SSujith break; 78fb9987d0SSujith case NL80211_CHAN_HT40PLUS: 79fb9987d0SSujith chanmode = CHANNEL_G_HT40PLUS; 80fb9987d0SSujith break; 81fb9987d0SSujith case NL80211_CHAN_HT40MINUS: 82fb9987d0SSujith chanmode = CHANNEL_G_HT40MINUS; 83fb9987d0SSujith break; 84fb9987d0SSujith } 85fb9987d0SSujith break; 86fb9987d0SSujith case IEEE80211_BAND_5GHZ: 87fb9987d0SSujith switch (channel_type) { 88fb9987d0SSujith case NL80211_CHAN_NO_HT: 89fb9987d0SSujith case NL80211_CHAN_HT20: 90fb9987d0SSujith chanmode = CHANNEL_A_HT20; 91fb9987d0SSujith break; 92fb9987d0SSujith case NL80211_CHAN_HT40PLUS: 93fb9987d0SSujith chanmode = CHANNEL_A_HT40PLUS; 94fb9987d0SSujith break; 95fb9987d0SSujith case NL80211_CHAN_HT40MINUS: 96fb9987d0SSujith chanmode = CHANNEL_A_HT40MINUS; 97fb9987d0SSujith break; 98fb9987d0SSujith } 99fb9987d0SSujith break; 100fb9987d0SSujith default: 101fb9987d0SSujith break; 102fb9987d0SSujith } 103fb9987d0SSujith 104fb9987d0SSujith return chanmode; 105fb9987d0SSujith } 106fb9987d0SSujith 107fb9987d0SSujith /* 108fb9987d0SSujith * Update internal channel flags. 109fb9987d0SSujith */ 110babcbc29SFelix Fietkau void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan, 111babcbc29SFelix Fietkau struct ieee80211_channel *chan, 112babcbc29SFelix Fietkau enum nl80211_channel_type channel_type) 113fb9987d0SSujith { 114fb9987d0SSujith ichan->channel = chan->center_freq; 115fb9987d0SSujith ichan->chan = chan; 116fb9987d0SSujith 117fb9987d0SSujith if (chan->band == IEEE80211_BAND_2GHZ) { 118fb9987d0SSujith ichan->chanmode = CHANNEL_G; 119b64c6a3dSMohammed Shafi Shajakhan ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM; 120fb9987d0SSujith } else { 121fb9987d0SSujith ichan->chanmode = CHANNEL_A; 122fb9987d0SSujith ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; 123fb9987d0SSujith } 124fb9987d0SSujith 125babcbc29SFelix Fietkau if (channel_type != NL80211_CHAN_NO_HT) 126babcbc29SFelix Fietkau ichan->chanmode = ath9k_get_extchanmode(chan, channel_type); 127fb9987d0SSujith } 128fb9987d0SSujith EXPORT_SYMBOL(ath9k_cmn_update_ichannel); 129fb9987d0SSujith 130fb9987d0SSujith /* 131fb9987d0SSujith * Get the internal channel reference. 132fb9987d0SSujith */ 133fb9987d0SSujith struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, 134fb9987d0SSujith struct ath_hw *ah) 135fb9987d0SSujith { 136fb9987d0SSujith struct ieee80211_channel *curchan = hw->conf.channel; 137fb9987d0SSujith struct ath9k_channel *channel; 138fb9987d0SSujith u8 chan_idx; 139fb9987d0SSujith 140fb9987d0SSujith chan_idx = curchan->hw_value; 141fb9987d0SSujith channel = &ah->channels[chan_idx]; 142babcbc29SFelix Fietkau ath9k_cmn_update_ichannel(channel, curchan, hw->conf.channel_type); 143fb9987d0SSujith 144fb9987d0SSujith return channel; 145fb9987d0SSujith } 146fb9987d0SSujith EXPORT_SYMBOL(ath9k_cmn_get_curchannel); 147fb9987d0SSujith 14861389f3eSSujith int ath9k_cmn_count_streams(unsigned int chainmask, int max) 14961389f3eSSujith { 15061389f3eSSujith int streams = 0; 15161389f3eSSujith 15261389f3eSSujith do { 15361389f3eSSujith if (++streams == max) 15461389f3eSSujith break; 15561389f3eSSujith } while ((chainmask = chainmask & (chainmask - 1))); 15661389f3eSSujith 15761389f3eSSujith return streams; 15861389f3eSSujith } 15961389f3eSSujith EXPORT_SYMBOL(ath9k_cmn_count_streams); 16061389f3eSSujith 1615048e8c3SRajkumar Manoharan void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow, 1625048e8c3SRajkumar Manoharan u16 new_txpow, u16 *txpower) 1635048e8c3SRajkumar Manoharan { 164*ca2c68ccSFelix Fietkau struct ath_regulatory *reg = ath9k_hw_regulatory(ah); 165*ca2c68ccSFelix Fietkau 166*ca2c68ccSFelix Fietkau if (reg->power_limit != new_txpow) { 1675048e8c3SRajkumar Manoharan ath9k_hw_set_txpowerlimit(ah, new_txpow, false); 1685048e8c3SRajkumar Manoharan /* read back in case value is clamped */ 169*ca2c68ccSFelix Fietkau *txpower = reg->max_power_level; 1705048e8c3SRajkumar Manoharan } 1715048e8c3SRajkumar Manoharan } 1725048e8c3SRajkumar Manoharan EXPORT_SYMBOL(ath9k_cmn_update_txpow); 1735048e8c3SRajkumar Manoharan 174f82b4bdeSRajkumar Manoharan void ath9k_cmn_init_crypto(struct ath_hw *ah) 175f82b4bdeSRajkumar Manoharan { 176f82b4bdeSRajkumar Manoharan struct ath_common *common = ath9k_hw_common(ah); 177f82b4bdeSRajkumar Manoharan int i = 0; 178f82b4bdeSRajkumar Manoharan 179f82b4bdeSRajkumar Manoharan /* Get the hardware key cache size. */ 180f82b4bdeSRajkumar Manoharan common->keymax = AR_KEYTABLE_SIZE; 181f82b4bdeSRajkumar Manoharan 182f82b4bdeSRajkumar Manoharan /* 183f82b4bdeSRajkumar Manoharan * Check whether the separate key cache entries 184f82b4bdeSRajkumar Manoharan * are required to handle both tx+rx MIC keys. 185f82b4bdeSRajkumar Manoharan * With split mic keys the number of stations is limited 186f82b4bdeSRajkumar Manoharan * to 27 otherwise 59. 187f82b4bdeSRajkumar Manoharan */ 188f82b4bdeSRajkumar Manoharan if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA) 189f82b4bdeSRajkumar Manoharan common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED; 190f82b4bdeSRajkumar Manoharan 191f82b4bdeSRajkumar Manoharan /* 192f82b4bdeSRajkumar Manoharan * Reset the key cache since some parts do not 193f82b4bdeSRajkumar Manoharan * reset the contents on initial power up. 194f82b4bdeSRajkumar Manoharan */ 195f82b4bdeSRajkumar Manoharan for (i = 0; i < common->keymax; i++) 196f82b4bdeSRajkumar Manoharan ath_hw_keyreset(common, (u16) i); 197f82b4bdeSRajkumar Manoharan } 198f82b4bdeSRajkumar Manoharan EXPORT_SYMBOL(ath9k_cmn_init_crypto); 199f82b4bdeSRajkumar Manoharan 200db86f07eSLuis R. Rodriguez static int __init ath9k_cmn_init(void) 201db86f07eSLuis R. Rodriguez { 202db86f07eSLuis R. Rodriguez return 0; 203db86f07eSLuis R. Rodriguez } 204db86f07eSLuis R. Rodriguez module_init(ath9k_cmn_init); 205db86f07eSLuis R. Rodriguez 206db86f07eSLuis R. Rodriguez static void __exit ath9k_cmn_exit(void) 207db86f07eSLuis R. Rodriguez { 208db86f07eSLuis R. Rodriguez return; 209db86f07eSLuis R. Rodriguez } 210db86f07eSLuis R. Rodriguez module_exit(ath9k_cmn_exit); 211