1db86f07eSLuis R. Rodriguez /* 2db86f07eSLuis R. Rodriguez * Copyright (c) 2009 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) { 49fb9987d0SSujith if (tx_info->control.hw_key->alg == ALG_WEP) 50fb9987d0SSujith return ATH9K_KEY_TYPE_WEP; 51fb9987d0SSujith else if (tx_info->control.hw_key->alg == ALG_TKIP) 52fb9987d0SSujith return ATH9K_KEY_TYPE_TKIP; 53fb9987d0SSujith else if (tx_info->control.hw_key->alg == ALG_CCMP) 54fb9987d0SSujith return ATH9K_KEY_TYPE_AES; 55fb9987d0SSujith } 56fb9987d0SSujith 57fb9987d0SSujith return ATH9K_KEY_TYPE_CLEAR; 58fb9987d0SSujith } 59fb9987d0SSujith EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype); 60fb9987d0SSujith 61fb9987d0SSujith static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan, 62fb9987d0SSujith enum nl80211_channel_type channel_type) 63fb9987d0SSujith { 64fb9987d0SSujith u32 chanmode = 0; 65fb9987d0SSujith 66fb9987d0SSujith switch (chan->band) { 67fb9987d0SSujith case IEEE80211_BAND_2GHZ: 68fb9987d0SSujith switch (channel_type) { 69fb9987d0SSujith case NL80211_CHAN_NO_HT: 70fb9987d0SSujith case NL80211_CHAN_HT20: 71fb9987d0SSujith chanmode = CHANNEL_G_HT20; 72fb9987d0SSujith break; 73fb9987d0SSujith case NL80211_CHAN_HT40PLUS: 74fb9987d0SSujith chanmode = CHANNEL_G_HT40PLUS; 75fb9987d0SSujith break; 76fb9987d0SSujith case NL80211_CHAN_HT40MINUS: 77fb9987d0SSujith chanmode = CHANNEL_G_HT40MINUS; 78fb9987d0SSujith break; 79fb9987d0SSujith } 80fb9987d0SSujith break; 81fb9987d0SSujith case IEEE80211_BAND_5GHZ: 82fb9987d0SSujith switch (channel_type) { 83fb9987d0SSujith case NL80211_CHAN_NO_HT: 84fb9987d0SSujith case NL80211_CHAN_HT20: 85fb9987d0SSujith chanmode = CHANNEL_A_HT20; 86fb9987d0SSujith break; 87fb9987d0SSujith case NL80211_CHAN_HT40PLUS: 88fb9987d0SSujith chanmode = CHANNEL_A_HT40PLUS; 89fb9987d0SSujith break; 90fb9987d0SSujith case NL80211_CHAN_HT40MINUS: 91fb9987d0SSujith chanmode = CHANNEL_A_HT40MINUS; 92fb9987d0SSujith break; 93fb9987d0SSujith } 94fb9987d0SSujith break; 95fb9987d0SSujith default: 96fb9987d0SSujith break; 97fb9987d0SSujith } 98fb9987d0SSujith 99fb9987d0SSujith return chanmode; 100fb9987d0SSujith } 101fb9987d0SSujith 102fb9987d0SSujith /* 103fb9987d0SSujith * Update internal channel flags. 104fb9987d0SSujith */ 105fb9987d0SSujith void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, 106fb9987d0SSujith struct ath9k_channel *ichan) 107fb9987d0SSujith { 108fb9987d0SSujith struct ieee80211_channel *chan = hw->conf.channel; 109fb9987d0SSujith struct ieee80211_conf *conf = &hw->conf; 110fb9987d0SSujith 111fb9987d0SSujith ichan->channel = chan->center_freq; 112fb9987d0SSujith ichan->chan = chan; 113fb9987d0SSujith 114fb9987d0SSujith if (chan->band == IEEE80211_BAND_2GHZ) { 115fb9987d0SSujith ichan->chanmode = CHANNEL_G; 116fb9987d0SSujith ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM | CHANNEL_G; 117fb9987d0SSujith } else { 118fb9987d0SSujith ichan->chanmode = CHANNEL_A; 119fb9987d0SSujith ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; 120fb9987d0SSujith } 121fb9987d0SSujith 122fb9987d0SSujith if (conf_is_ht(conf)) 123fb9987d0SSujith ichan->chanmode = ath9k_get_extchanmode(chan, 124fb9987d0SSujith conf->channel_type); 125fb9987d0SSujith } 126fb9987d0SSujith EXPORT_SYMBOL(ath9k_cmn_update_ichannel); 127fb9987d0SSujith 128fb9987d0SSujith /* 129fb9987d0SSujith * Get the internal channel reference. 130fb9987d0SSujith */ 131fb9987d0SSujith struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, 132fb9987d0SSujith struct ath_hw *ah) 133fb9987d0SSujith { 134fb9987d0SSujith struct ieee80211_channel *curchan = hw->conf.channel; 135fb9987d0SSujith struct ath9k_channel *channel; 136fb9987d0SSujith u8 chan_idx; 137fb9987d0SSujith 138fb9987d0SSujith chan_idx = curchan->hw_value; 139fb9987d0SSujith channel = &ah->channels[chan_idx]; 140fb9987d0SSujith ath9k_cmn_update_ichannel(hw, channel); 141fb9987d0SSujith 142fb9987d0SSujith return channel; 143fb9987d0SSujith } 144fb9987d0SSujith EXPORT_SYMBOL(ath9k_cmn_get_curchannel); 145fb9987d0SSujith 146fb9987d0SSujith static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key, 147fb9987d0SSujith struct ath9k_keyval *hk, const u8 *addr, 148fb9987d0SSujith bool authenticator) 149fb9987d0SSujith { 150fb9987d0SSujith struct ath_hw *ah = common->ah; 151fb9987d0SSujith const u8 *key_rxmic; 152fb9987d0SSujith const u8 *key_txmic; 153fb9987d0SSujith 154fb9987d0SSujith key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; 155fb9987d0SSujith key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; 156fb9987d0SSujith 157fb9987d0SSujith if (addr == NULL) { 158fb9987d0SSujith /* 159fb9987d0SSujith * Group key installation - only two key cache entries are used 160fb9987d0SSujith * regardless of splitmic capability since group key is only 161fb9987d0SSujith * used either for TX or RX. 162fb9987d0SSujith */ 163fb9987d0SSujith if (authenticator) { 164fb9987d0SSujith memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); 165fb9987d0SSujith memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic)); 166fb9987d0SSujith } else { 167fb9987d0SSujith memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); 168fb9987d0SSujith memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic)); 169fb9987d0SSujith } 170fb9987d0SSujith return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr); 171fb9987d0SSujith } 172fb9987d0SSujith if (!common->splitmic) { 173fb9987d0SSujith /* TX and RX keys share the same key cache entry. */ 174fb9987d0SSujith memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); 175fb9987d0SSujith memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic)); 176fb9987d0SSujith return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr); 177fb9987d0SSujith } 178fb9987d0SSujith 179fb9987d0SSujith /* Separate key cache entries for TX and RX */ 180fb9987d0SSujith 181fb9987d0SSujith /* TX key goes at first index, RX key at +32. */ 182fb9987d0SSujith memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); 183fb9987d0SSujith if (!ath9k_hw_set_keycache_entry(ah, keyix, hk, NULL)) { 184fb9987d0SSujith /* TX MIC entry failed. No need to proceed further */ 185fb9987d0SSujith ath_print(common, ATH_DBG_FATAL, 186fb9987d0SSujith "Setting TX MIC Key Failed\n"); 187fb9987d0SSujith return 0; 188fb9987d0SSujith } 189fb9987d0SSujith 190fb9987d0SSujith memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); 191fb9987d0SSujith /* XXX delete tx key on failure? */ 192fb9987d0SSujith return ath9k_hw_set_keycache_entry(ah, keyix + 32, hk, addr); 193fb9987d0SSujith } 194fb9987d0SSujith 195fb9987d0SSujith static int ath_reserve_key_cache_slot_tkip(struct ath_common *common) 196fb9987d0SSujith { 197fb9987d0SSujith int i; 198fb9987d0SSujith 199fb9987d0SSujith for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { 200fb9987d0SSujith if (test_bit(i, common->keymap) || 201fb9987d0SSujith test_bit(i + 64, common->keymap)) 202fb9987d0SSujith continue; /* At least one part of TKIP key allocated */ 203fb9987d0SSujith if (common->splitmic && 204fb9987d0SSujith (test_bit(i + 32, common->keymap) || 205fb9987d0SSujith test_bit(i + 64 + 32, common->keymap))) 206fb9987d0SSujith continue; /* At least one part of TKIP key allocated */ 207fb9987d0SSujith 208fb9987d0SSujith /* Found a free slot for a TKIP key */ 209fb9987d0SSujith return i; 210fb9987d0SSujith } 211fb9987d0SSujith return -1; 212fb9987d0SSujith } 213fb9987d0SSujith 214eed8e22fSFelix Fietkau static int ath_reserve_key_cache_slot(struct ath_common *common, 215eed8e22fSFelix Fietkau enum ieee80211_key_alg alg) 216fb9987d0SSujith { 217fb9987d0SSujith int i; 218fb9987d0SSujith 219eed8e22fSFelix Fietkau if (alg == ALG_TKIP) 220eed8e22fSFelix Fietkau return ath_reserve_key_cache_slot_tkip(common); 221eed8e22fSFelix Fietkau 222fb9987d0SSujith /* First, try to find slots that would not be available for TKIP. */ 223fb9987d0SSujith if (common->splitmic) { 224fb9987d0SSujith for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) { 225fb9987d0SSujith if (!test_bit(i, common->keymap) && 226fb9987d0SSujith (test_bit(i + 32, common->keymap) || 227fb9987d0SSujith test_bit(i + 64, common->keymap) || 228fb9987d0SSujith test_bit(i + 64 + 32, common->keymap))) 229fb9987d0SSujith return i; 230fb9987d0SSujith if (!test_bit(i + 32, common->keymap) && 231fb9987d0SSujith (test_bit(i, common->keymap) || 232fb9987d0SSujith test_bit(i + 64, common->keymap) || 233fb9987d0SSujith test_bit(i + 64 + 32, common->keymap))) 234fb9987d0SSujith return i + 32; 235fb9987d0SSujith if (!test_bit(i + 64, common->keymap) && 236fb9987d0SSujith (test_bit(i , common->keymap) || 237fb9987d0SSujith test_bit(i + 32, common->keymap) || 238fb9987d0SSujith test_bit(i + 64 + 32, common->keymap))) 239fb9987d0SSujith return i + 64; 240fb9987d0SSujith if (!test_bit(i + 64 + 32, common->keymap) && 241fb9987d0SSujith (test_bit(i, common->keymap) || 242fb9987d0SSujith test_bit(i + 32, common->keymap) || 243fb9987d0SSujith test_bit(i + 64, common->keymap))) 244fb9987d0SSujith return i + 64 + 32; 245fb9987d0SSujith } 246fb9987d0SSujith } else { 247fb9987d0SSujith for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { 248fb9987d0SSujith if (!test_bit(i, common->keymap) && 249fb9987d0SSujith test_bit(i + 64, common->keymap)) 250fb9987d0SSujith return i; 251fb9987d0SSujith if (test_bit(i, common->keymap) && 252fb9987d0SSujith !test_bit(i + 64, common->keymap)) 253fb9987d0SSujith return i + 64; 254fb9987d0SSujith } 255fb9987d0SSujith } 256fb9987d0SSujith 257fb9987d0SSujith /* No partially used TKIP slots, pick any available slot */ 258fb9987d0SSujith for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) { 259fb9987d0SSujith /* Do not allow slots that could be needed for TKIP group keys 260fb9987d0SSujith * to be used. This limitation could be removed if we know that 261fb9987d0SSujith * TKIP will not be used. */ 262fb9987d0SSujith if (i >= 64 && i < 64 + IEEE80211_WEP_NKID) 263fb9987d0SSujith continue; 264fb9987d0SSujith if (common->splitmic) { 265fb9987d0SSujith if (i >= 32 && i < 32 + IEEE80211_WEP_NKID) 266fb9987d0SSujith continue; 267fb9987d0SSujith if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID) 268fb9987d0SSujith continue; 269fb9987d0SSujith } 270fb9987d0SSujith 271fb9987d0SSujith if (!test_bit(i, common->keymap)) 272fb9987d0SSujith return i; /* Found a free slot for a key */ 273fb9987d0SSujith } 274fb9987d0SSujith 275fb9987d0SSujith /* No free slot found */ 276fb9987d0SSujith return -1; 277fb9987d0SSujith } 278fb9987d0SSujith 279fb9987d0SSujith /* 280fb9987d0SSujith * Configure encryption in the HW. 281fb9987d0SSujith */ 282fb9987d0SSujith int ath9k_cmn_key_config(struct ath_common *common, 283fb9987d0SSujith struct ieee80211_vif *vif, 284fb9987d0SSujith struct ieee80211_sta *sta, 285fb9987d0SSujith struct ieee80211_key_conf *key) 286fb9987d0SSujith { 287fb9987d0SSujith struct ath_hw *ah = common->ah; 288fb9987d0SSujith struct ath9k_keyval hk; 289fb9987d0SSujith const u8 *mac = NULL; 290eed8e22fSFelix Fietkau u8 gmac[ETH_ALEN]; 291fb9987d0SSujith int ret = 0; 292fb9987d0SSujith int idx; 293fb9987d0SSujith 294fb9987d0SSujith memset(&hk, 0, sizeof(hk)); 295fb9987d0SSujith 296fb9987d0SSujith switch (key->alg) { 297fb9987d0SSujith case ALG_WEP: 298fb9987d0SSujith hk.kv_type = ATH9K_CIPHER_WEP; 299fb9987d0SSujith break; 300fb9987d0SSujith case ALG_TKIP: 301fb9987d0SSujith hk.kv_type = ATH9K_CIPHER_TKIP; 302fb9987d0SSujith break; 303fb9987d0SSujith case ALG_CCMP: 304fb9987d0SSujith hk.kv_type = ATH9K_CIPHER_AES_CCM; 305fb9987d0SSujith break; 306fb9987d0SSujith default: 307fb9987d0SSujith return -EOPNOTSUPP; 308fb9987d0SSujith } 309fb9987d0SSujith 310fb9987d0SSujith hk.kv_len = key->keylen; 311fb9987d0SSujith memcpy(hk.kv_val, key->key, key->keylen); 312fb9987d0SSujith 313fb9987d0SSujith if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { 314eed8e22fSFelix Fietkau switch (vif->type) { 315eed8e22fSFelix Fietkau case NL80211_IFTYPE_AP: 316eed8e22fSFelix Fietkau memcpy(gmac, vif->addr, ETH_ALEN); 317eed8e22fSFelix Fietkau gmac[0] |= 0x01; 318eed8e22fSFelix Fietkau mac = gmac; 319eed8e22fSFelix Fietkau idx = ath_reserve_key_cache_slot(common, key->alg); 320eed8e22fSFelix Fietkau break; 321eed8e22fSFelix Fietkau case NL80211_IFTYPE_ADHOC: 322eed8e22fSFelix Fietkau memcpy(gmac, sta->addr, ETH_ALEN); 323eed8e22fSFelix Fietkau gmac[0] |= 0x01; 324eed8e22fSFelix Fietkau mac = gmac; 325eed8e22fSFelix Fietkau idx = ath_reserve_key_cache_slot(common, key->alg); 326eed8e22fSFelix Fietkau break; 327eed8e22fSFelix Fietkau default: 328fb9987d0SSujith idx = key->keyidx; 329eed8e22fSFelix Fietkau break; 330eed8e22fSFelix Fietkau } 331fb9987d0SSujith } else if (key->keyidx) { 332fb9987d0SSujith if (WARN_ON(!sta)) 333fb9987d0SSujith return -EOPNOTSUPP; 334fb9987d0SSujith mac = sta->addr; 335fb9987d0SSujith 336fb9987d0SSujith if (vif->type != NL80211_IFTYPE_AP) { 337fb9987d0SSujith /* Only keyidx 0 should be used with unicast key, but 338fb9987d0SSujith * allow this for client mode for now. */ 339fb9987d0SSujith idx = key->keyidx; 340fb9987d0SSujith } else 341fb9987d0SSujith return -EIO; 342fb9987d0SSujith } else { 343fb9987d0SSujith if (WARN_ON(!sta)) 344fb9987d0SSujith return -EOPNOTSUPP; 345fb9987d0SSujith mac = sta->addr; 346fb9987d0SSujith 347eed8e22fSFelix Fietkau idx = ath_reserve_key_cache_slot(common, key->alg); 348eed8e22fSFelix Fietkau } 349eed8e22fSFelix Fietkau 350fb9987d0SSujith if (idx < 0) 351fb9987d0SSujith return -ENOSPC; /* no free key cache entries */ 352fb9987d0SSujith 353fb9987d0SSujith if (key->alg == ALG_TKIP) 354fb9987d0SSujith ret = ath_setkey_tkip(common, idx, key->key, &hk, mac, 355fb9987d0SSujith vif->type == NL80211_IFTYPE_AP); 356fb9987d0SSujith else 357fb9987d0SSujith ret = ath9k_hw_set_keycache_entry(ah, idx, &hk, mac); 358fb9987d0SSujith 359fb9987d0SSujith if (!ret) 360fb9987d0SSujith return -EIO; 361fb9987d0SSujith 362fb9987d0SSujith set_bit(idx, common->keymap); 363fb9987d0SSujith if (key->alg == ALG_TKIP) { 364fb9987d0SSujith set_bit(idx + 64, common->keymap); 365fb9987d0SSujith if (common->splitmic) { 366fb9987d0SSujith set_bit(idx + 32, common->keymap); 367fb9987d0SSujith set_bit(idx + 64 + 32, common->keymap); 368fb9987d0SSujith } 369fb9987d0SSujith } 370fb9987d0SSujith 371fb9987d0SSujith return idx; 372fb9987d0SSujith } 373fb9987d0SSujith EXPORT_SYMBOL(ath9k_cmn_key_config); 374fb9987d0SSujith 375fb9987d0SSujith /* 376fb9987d0SSujith * Delete Key. 377fb9987d0SSujith */ 378fb9987d0SSujith void ath9k_cmn_key_delete(struct ath_common *common, 379fb9987d0SSujith struct ieee80211_key_conf *key) 380fb9987d0SSujith { 381fb9987d0SSujith struct ath_hw *ah = common->ah; 382fb9987d0SSujith 383fb9987d0SSujith ath9k_hw_keyreset(ah, key->hw_key_idx); 384fb9987d0SSujith if (key->hw_key_idx < IEEE80211_WEP_NKID) 385fb9987d0SSujith return; 386fb9987d0SSujith 387fb9987d0SSujith clear_bit(key->hw_key_idx, common->keymap); 388fb9987d0SSujith if (key->alg != ALG_TKIP) 389fb9987d0SSujith return; 390fb9987d0SSujith 391fb9987d0SSujith clear_bit(key->hw_key_idx + 64, common->keymap); 392fb9987d0SSujith if (common->splitmic) { 393fb9987d0SSujith ath9k_hw_keyreset(ah, key->hw_key_idx + 32); 394fb9987d0SSujith clear_bit(key->hw_key_idx + 32, common->keymap); 395fb9987d0SSujith clear_bit(key->hw_key_idx + 64 + 32, common->keymap); 396fb9987d0SSujith } 397fb9987d0SSujith } 398fb9987d0SSujith EXPORT_SYMBOL(ath9k_cmn_key_delete); 399fb9987d0SSujith 400*61389f3eSSujith int ath9k_cmn_count_streams(unsigned int chainmask, int max) 401*61389f3eSSujith { 402*61389f3eSSujith int streams = 0; 403*61389f3eSSujith 404*61389f3eSSujith do { 405*61389f3eSSujith if (++streams == max) 406*61389f3eSSujith break; 407*61389f3eSSujith } while ((chainmask = chainmask & (chainmask - 1))); 408*61389f3eSSujith 409*61389f3eSSujith return streams; 410*61389f3eSSujith } 411*61389f3eSSujith EXPORT_SYMBOL(ath9k_cmn_count_streams); 412*61389f3eSSujith 413db86f07eSLuis R. Rodriguez static int __init ath9k_cmn_init(void) 414db86f07eSLuis R. Rodriguez { 415db86f07eSLuis R. Rodriguez return 0; 416db86f07eSLuis R. Rodriguez } 417db86f07eSLuis R. Rodriguez module_init(ath9k_cmn_init); 418db86f07eSLuis R. Rodriguez 419db86f07eSLuis R. Rodriguez static void __exit ath9k_cmn_exit(void) 420db86f07eSLuis R. Rodriguez { 421db86f07eSLuis R. Rodriguez return; 422db86f07eSLuis R. Rodriguez } 423db86f07eSLuis R. Rodriguez module_exit(ath9k_cmn_exit); 424