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 30db86f07eSLuis R. Rodriguez /* Common RX processing */ 31db86f07eSLuis R. Rodriguez 32db86f07eSLuis R. Rodriguez /* Assumes you've already done the endian to CPU conversion */ 33db86f07eSLuis R. Rodriguez static bool ath9k_rx_accept(struct ath_common *common, 34db86f07eSLuis R. Rodriguez struct sk_buff *skb, 35db86f07eSLuis R. Rodriguez struct ieee80211_rx_status *rxs, 36db86f07eSLuis R. Rodriguez struct ath_rx_status *rx_stats, 37db86f07eSLuis R. Rodriguez bool *decrypt_error) 38db86f07eSLuis R. Rodriguez { 39db86f07eSLuis R. Rodriguez struct ath_hw *ah = common->ah; 40db86f07eSLuis R. Rodriguez struct ieee80211_hdr *hdr; 41db86f07eSLuis R. Rodriguez __le16 fc; 42db86f07eSLuis R. Rodriguez 43db86f07eSLuis R. Rodriguez hdr = (struct ieee80211_hdr *) skb->data; 44db86f07eSLuis R. Rodriguez fc = hdr->frame_control; 45db86f07eSLuis R. Rodriguez 46db86f07eSLuis R. Rodriguez if (!rx_stats->rs_datalen) 47db86f07eSLuis R. Rodriguez return false; 48db86f07eSLuis R. Rodriguez /* 49db86f07eSLuis R. Rodriguez * rs_status follows rs_datalen so if rs_datalen is too large 50db86f07eSLuis R. Rodriguez * we can take a hint that hardware corrupted it, so ignore 51db86f07eSLuis R. Rodriguez * those frames. 52db86f07eSLuis R. Rodriguez */ 53db86f07eSLuis R. Rodriguez if (rx_stats->rs_datalen > common->rx_bufsize) 54db86f07eSLuis R. Rodriguez return false; 55db86f07eSLuis R. Rodriguez 56db86f07eSLuis R. Rodriguez /* 57748d4510SLuis R. Rodriguez * rs_more indicates chained descriptors which can be used 58748d4510SLuis R. Rodriguez * to link buffers together for a sort of scatter-gather 59748d4510SLuis R. Rodriguez * operation. 60748d4510SLuis R. Rodriguez * 61748d4510SLuis R. Rodriguez * The rx_stats->rs_status will not be set until the end of the 62748d4510SLuis R. Rodriguez * chained descriptors so it can be ignored if rs_more is set. The 63748d4510SLuis R. Rodriguez * rs_more will be false at the last element of the chained 64748d4510SLuis R. Rodriguez * descriptors. 65db86f07eSLuis R. Rodriguez */ 66748d4510SLuis R. Rodriguez if (!rx_stats->rs_more && rx_stats->rs_status != 0) { 67db86f07eSLuis R. Rodriguez if (rx_stats->rs_status & ATH9K_RXERR_CRC) 68db86f07eSLuis R. Rodriguez rxs->flag |= RX_FLAG_FAILED_FCS_CRC; 69db86f07eSLuis R. Rodriguez if (rx_stats->rs_status & ATH9K_RXERR_PHY) 70db86f07eSLuis R. Rodriguez return false; 71db86f07eSLuis R. Rodriguez 72db86f07eSLuis R. Rodriguez if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) { 73db86f07eSLuis R. Rodriguez *decrypt_error = true; 74db86f07eSLuis R. Rodriguez } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) { 75db86f07eSLuis R. Rodriguez if (ieee80211_is_ctl(fc)) 76db86f07eSLuis R. Rodriguez /* 77db86f07eSLuis R. Rodriguez * Sometimes, we get invalid 78db86f07eSLuis R. Rodriguez * MIC failures on valid control frames. 79db86f07eSLuis R. Rodriguez * Remove these mic errors. 80db86f07eSLuis R. Rodriguez */ 81db86f07eSLuis R. Rodriguez rx_stats->rs_status &= ~ATH9K_RXERR_MIC; 82db86f07eSLuis R. Rodriguez else 83db86f07eSLuis R. Rodriguez rxs->flag |= RX_FLAG_MMIC_ERROR; 84db86f07eSLuis R. Rodriguez } 85db86f07eSLuis R. Rodriguez /* 86db86f07eSLuis R. Rodriguez * Reject error frames with the exception of 87db86f07eSLuis R. Rodriguez * decryption and MIC failures. For monitor mode, 88db86f07eSLuis R. Rodriguez * we also ignore the CRC error. 89db86f07eSLuis R. Rodriguez */ 90db86f07eSLuis R. Rodriguez if (ah->opmode == NL80211_IFTYPE_MONITOR) { 91db86f07eSLuis R. Rodriguez if (rx_stats->rs_status & 92db86f07eSLuis R. Rodriguez ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | 93db86f07eSLuis R. Rodriguez ATH9K_RXERR_CRC)) 94db86f07eSLuis R. Rodriguez return false; 95db86f07eSLuis R. Rodriguez } else { 96db86f07eSLuis R. Rodriguez if (rx_stats->rs_status & 97db86f07eSLuis R. Rodriguez ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) { 98db86f07eSLuis R. Rodriguez return false; 99db86f07eSLuis R. Rodriguez } 100db86f07eSLuis R. Rodriguez } 101db86f07eSLuis R. Rodriguez } 102db86f07eSLuis R. Rodriguez return true; 103db86f07eSLuis R. Rodriguez } 104db86f07eSLuis R. Rodriguez 105db86f07eSLuis R. Rodriguez static u8 ath9k_process_rate(struct ath_common *common, 106db86f07eSLuis R. Rodriguez struct ieee80211_hw *hw, 107db86f07eSLuis R. Rodriguez struct ath_rx_status *rx_stats, 108db86f07eSLuis R. Rodriguez struct ieee80211_rx_status *rxs, 109db86f07eSLuis R. Rodriguez struct sk_buff *skb) 110db86f07eSLuis R. Rodriguez { 111db86f07eSLuis R. Rodriguez struct ieee80211_supported_band *sband; 112db86f07eSLuis R. Rodriguez enum ieee80211_band band; 113db86f07eSLuis R. Rodriguez unsigned int i = 0; 114db86f07eSLuis R. Rodriguez 115db86f07eSLuis R. Rodriguez band = hw->conf.channel->band; 116db86f07eSLuis R. Rodriguez sband = hw->wiphy->bands[band]; 117db86f07eSLuis R. Rodriguez 118db86f07eSLuis R. Rodriguez if (rx_stats->rs_rate & 0x80) { 119db86f07eSLuis R. Rodriguez /* HT rate */ 120db86f07eSLuis R. Rodriguez rxs->flag |= RX_FLAG_HT; 121db86f07eSLuis R. Rodriguez if (rx_stats->rs_flags & ATH9K_RX_2040) 122db86f07eSLuis R. Rodriguez rxs->flag |= RX_FLAG_40MHZ; 123db86f07eSLuis R. Rodriguez if (rx_stats->rs_flags & ATH9K_RX_GI) 124db86f07eSLuis R. Rodriguez rxs->flag |= RX_FLAG_SHORT_GI; 125db86f07eSLuis R. Rodriguez return rx_stats->rs_rate & 0x7f; 126db86f07eSLuis R. Rodriguez } 127db86f07eSLuis R. Rodriguez 128db86f07eSLuis R. Rodriguez for (i = 0; i < sband->n_bitrates; i++) { 129db86f07eSLuis R. Rodriguez if (sband->bitrates[i].hw_value == rx_stats->rs_rate) 130db86f07eSLuis R. Rodriguez return i; 131db86f07eSLuis R. Rodriguez if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) { 132db86f07eSLuis R. Rodriguez rxs->flag |= RX_FLAG_SHORTPRE; 133db86f07eSLuis R. Rodriguez return i; 134db86f07eSLuis R. Rodriguez } 135db86f07eSLuis R. Rodriguez } 136db86f07eSLuis R. Rodriguez 137db86f07eSLuis R. Rodriguez /* No valid hardware bitrate found -- we should not get here */ 138db86f07eSLuis R. Rodriguez ath_print(common, ATH_DBG_XMIT, "unsupported hw bitrate detected " 139db86f07eSLuis R. Rodriguez "0x%02x using 1 Mbit\n", rx_stats->rs_rate); 140db86f07eSLuis R. Rodriguez if ((common->debug_mask & ATH_DBG_XMIT)) 141db86f07eSLuis R. Rodriguez print_hex_dump_bytes("", DUMP_PREFIX_NONE, skb->data, skb->len); 142db86f07eSLuis R. Rodriguez 143db86f07eSLuis R. Rodriguez return 0; 144db86f07eSLuis R. Rodriguez } 145db86f07eSLuis R. Rodriguez 146db86f07eSLuis R. Rodriguez static void ath9k_process_rssi(struct ath_common *common, 147db86f07eSLuis R. Rodriguez struct ieee80211_hw *hw, 148db86f07eSLuis R. Rodriguez struct sk_buff *skb, 149db86f07eSLuis R. Rodriguez struct ath_rx_status *rx_stats) 150db86f07eSLuis R. Rodriguez { 151db86f07eSLuis R. Rodriguez struct ath_hw *ah = common->ah; 152db86f07eSLuis R. Rodriguez struct ieee80211_sta *sta; 153db86f07eSLuis R. Rodriguez struct ieee80211_hdr *hdr; 154db86f07eSLuis R. Rodriguez struct ath_node *an; 155db86f07eSLuis R. Rodriguez int last_rssi = ATH_RSSI_DUMMY_MARKER; 156db86f07eSLuis R. Rodriguez __le16 fc; 157db86f07eSLuis R. Rodriguez 158db86f07eSLuis R. Rodriguez hdr = (struct ieee80211_hdr *)skb->data; 159db86f07eSLuis R. Rodriguez fc = hdr->frame_control; 160db86f07eSLuis R. Rodriguez 161db86f07eSLuis R. Rodriguez rcu_read_lock(); 162db86f07eSLuis R. Rodriguez /* 163db86f07eSLuis R. Rodriguez * XXX: use ieee80211_find_sta! This requires quite a bit of work 164db86f07eSLuis R. Rodriguez * under the current ath9k virtual wiphy implementation as we have 165db86f07eSLuis R. Rodriguez * no way of tying a vif to wiphy. Typically vifs are attached to 166db86f07eSLuis R. Rodriguez * at least one sdata of a wiphy on mac80211 but with ath9k virtual 167db86f07eSLuis R. Rodriguez * wiphy you'd have to iterate over every wiphy and each sdata. 168db86f07eSLuis R. Rodriguez */ 169db86f07eSLuis R. Rodriguez sta = ieee80211_find_sta_by_hw(hw, hdr->addr2); 170db86f07eSLuis R. Rodriguez if (sta) { 171db86f07eSLuis R. Rodriguez an = (struct ath_node *) sta->drv_priv; 172db86f07eSLuis R. Rodriguez if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && 173db86f07eSLuis R. Rodriguez !rx_stats->rs_moreaggr) 174db86f07eSLuis R. Rodriguez ATH_RSSI_LPF(an->last_rssi, rx_stats->rs_rssi); 175db86f07eSLuis R. Rodriguez last_rssi = an->last_rssi; 176db86f07eSLuis R. Rodriguez } 177db86f07eSLuis R. Rodriguez rcu_read_unlock(); 178db86f07eSLuis R. Rodriguez 179db86f07eSLuis R. Rodriguez if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) 180db86f07eSLuis R. Rodriguez rx_stats->rs_rssi = ATH_EP_RND(last_rssi, 181db86f07eSLuis R. Rodriguez ATH_RSSI_EP_MULTIPLIER); 182db86f07eSLuis R. Rodriguez if (rx_stats->rs_rssi < 0) 183db86f07eSLuis R. Rodriguez rx_stats->rs_rssi = 0; 184db86f07eSLuis R. Rodriguez 185db86f07eSLuis R. Rodriguez /* Update Beacon RSSI, this is used by ANI. */ 186db86f07eSLuis R. Rodriguez if (ieee80211_is_beacon(fc)) 187db86f07eSLuis R. Rodriguez ah->stats.avgbrssi = rx_stats->rs_rssi; 188db86f07eSLuis R. Rodriguez } 189db86f07eSLuis R. Rodriguez 190db86f07eSLuis R. Rodriguez /* 191db86f07eSLuis R. Rodriguez * For Decrypt or Demic errors, we only mark packet status here and always push 192db86f07eSLuis R. Rodriguez * up the frame up to let mac80211 handle the actual error case, be it no 193db86f07eSLuis R. Rodriguez * decryption key or real decryption error. This let us keep statistics there. 194db86f07eSLuis R. Rodriguez */ 195db86f07eSLuis R. Rodriguez int ath9k_cmn_rx_skb_preprocess(struct ath_common *common, 196db86f07eSLuis R. Rodriguez struct ieee80211_hw *hw, 197db86f07eSLuis R. Rodriguez struct sk_buff *skb, 198db86f07eSLuis R. Rodriguez struct ath_rx_status *rx_stats, 199db86f07eSLuis R. Rodriguez struct ieee80211_rx_status *rx_status, 200db86f07eSLuis R. Rodriguez bool *decrypt_error) 201db86f07eSLuis R. Rodriguez { 202db86f07eSLuis R. Rodriguez struct ath_hw *ah = common->ah; 203db86f07eSLuis R. Rodriguez 204dd6ae4f8SFelix Fietkau memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); 205db86f07eSLuis R. Rodriguez if (!ath9k_rx_accept(common, skb, rx_status, rx_stats, decrypt_error)) 206db86f07eSLuis R. Rodriguez return -EINVAL; 207db86f07eSLuis R. Rodriguez 208db86f07eSLuis R. Rodriguez ath9k_process_rssi(common, hw, skb, rx_stats); 209db86f07eSLuis R. Rodriguez 210db86f07eSLuis R. Rodriguez rx_status->rate_idx = ath9k_process_rate(common, hw, 211db86f07eSLuis R. Rodriguez rx_stats, rx_status, skb); 212db86f07eSLuis R. Rodriguez rx_status->mactime = ath9k_hw_extend_tsf(ah, rx_stats->rs_tstamp); 213db86f07eSLuis R. Rodriguez rx_status->band = hw->conf.channel->band; 214db86f07eSLuis R. Rodriguez rx_status->freq = hw->conf.channel->center_freq; 215db86f07eSLuis R. Rodriguez rx_status->noise = common->ani.noise_floor; 216db86f07eSLuis R. Rodriguez rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi; 217db86f07eSLuis R. Rodriguez rx_status->antenna = rx_stats->rs_antenna; 218db86f07eSLuis R. Rodriguez rx_status->flag |= RX_FLAG_TSFT; 219db86f07eSLuis R. Rodriguez 220db86f07eSLuis R. Rodriguez return 0; 221db86f07eSLuis R. Rodriguez } 222db86f07eSLuis R. Rodriguez EXPORT_SYMBOL(ath9k_cmn_rx_skb_preprocess); 223db86f07eSLuis R. Rodriguez 224db86f07eSLuis R. Rodriguez void ath9k_cmn_rx_skb_postprocess(struct ath_common *common, 225db86f07eSLuis R. Rodriguez struct sk_buff *skb, 226db86f07eSLuis R. Rodriguez struct ath_rx_status *rx_stats, 227db86f07eSLuis R. Rodriguez struct ieee80211_rx_status *rxs, 228db86f07eSLuis R. Rodriguez bool decrypt_error) 229db86f07eSLuis R. Rodriguez { 230db86f07eSLuis R. Rodriguez struct ath_hw *ah = common->ah; 231db86f07eSLuis R. Rodriguez struct ieee80211_hdr *hdr; 2328c35024aSBenoit PAPILLAULT int hdrlen, padpos, padsize; 233db86f07eSLuis R. Rodriguez u8 keyix; 234db86f07eSLuis R. Rodriguez __le16 fc; 235db86f07eSLuis R. Rodriguez 236db86f07eSLuis R. Rodriguez /* see if any padding is done by the hw and remove it */ 237db86f07eSLuis R. Rodriguez hdr = (struct ieee80211_hdr *) skb->data; 238db86f07eSLuis R. Rodriguez hdrlen = ieee80211_get_hdrlen_from_skb(skb); 239db86f07eSLuis R. Rodriguez fc = hdr->frame_control; 2401bc14880SBenoit Papillault padpos = ath9k_cmn_padpos(hdr->frame_control); 241db86f07eSLuis R. Rodriguez 242db86f07eSLuis R. Rodriguez /* The MAC header is padded to have 32-bit boundary if the 243db86f07eSLuis R. Rodriguez * packet payload is non-zero. The general calculation for 244db86f07eSLuis R. Rodriguez * padsize would take into account odd header lengths: 2458c35024aSBenoit PAPILLAULT * padsize = (4 - padpos % 4) % 4; However, since only 246db86f07eSLuis R. Rodriguez * even-length headers are used, padding can only be 0 or 2 247db86f07eSLuis R. Rodriguez * bytes and we can optimize this a bit. In addition, we must 248db86f07eSLuis R. Rodriguez * not try to remove padding from short control frames that do 249db86f07eSLuis R. Rodriguez * not have payload. */ 2508c35024aSBenoit PAPILLAULT padsize = padpos & 3; 2518c35024aSBenoit PAPILLAULT if (padsize && skb->len>=padpos+padsize+FCS_LEN) { 2528c35024aSBenoit PAPILLAULT memmove(skb->data + padsize, skb->data, padpos); 253db86f07eSLuis R. Rodriguez skb_pull(skb, padsize); 254db86f07eSLuis R. Rodriguez } 255db86f07eSLuis R. Rodriguez 256db86f07eSLuis R. Rodriguez keyix = rx_stats->rs_keyix; 257db86f07eSLuis R. Rodriguez 258db86f07eSLuis R. Rodriguez if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) { 259db86f07eSLuis R. Rodriguez rxs->flag |= RX_FLAG_DECRYPTED; 260db86f07eSLuis R. Rodriguez } else if (ieee80211_has_protected(fc) 261db86f07eSLuis R. Rodriguez && !decrypt_error && skb->len >= hdrlen + 4) { 262db86f07eSLuis R. Rodriguez keyix = skb->data[hdrlen + 3] >> 6; 263db86f07eSLuis R. Rodriguez 264db86f07eSLuis R. Rodriguez if (test_bit(keyix, common->keymap)) 265db86f07eSLuis R. Rodriguez rxs->flag |= RX_FLAG_DECRYPTED; 266db86f07eSLuis R. Rodriguez } 267db86f07eSLuis R. Rodriguez if (ah->sw_mgmt_crypto && 268db86f07eSLuis R. Rodriguez (rxs->flag & RX_FLAG_DECRYPTED) && 269db86f07eSLuis R. Rodriguez ieee80211_is_mgmt(fc)) 270db86f07eSLuis R. Rodriguez /* Use software decrypt for management frames. */ 271db86f07eSLuis R. Rodriguez rxs->flag &= ~RX_FLAG_DECRYPTED; 272db86f07eSLuis R. Rodriguez } 273db86f07eSLuis R. Rodriguez EXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess); 274db86f07eSLuis R. Rodriguez 2751bc14880SBenoit Papillault int ath9k_cmn_padpos(__le16 frame_control) 2761bc14880SBenoit Papillault { 2771bc14880SBenoit Papillault int padpos = 24; 2781bc14880SBenoit Papillault if (ieee80211_has_a4(frame_control)) { 2791bc14880SBenoit Papillault padpos += ETH_ALEN; 2801bc14880SBenoit Papillault } 2811bc14880SBenoit Papillault if (ieee80211_is_data_qos(frame_control)) { 2821bc14880SBenoit Papillault padpos += IEEE80211_QOS_CTL_LEN; 2831bc14880SBenoit Papillault } 2841bc14880SBenoit Papillault 2851bc14880SBenoit Papillault return padpos; 2861bc14880SBenoit Papillault } 2871bc14880SBenoit Papillault EXPORT_SYMBOL(ath9k_cmn_padpos); 2881bc14880SBenoit Papillault 289*fb9987d0SSujith int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb) 290*fb9987d0SSujith { 291*fb9987d0SSujith struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); 292*fb9987d0SSujith 293*fb9987d0SSujith if (tx_info->control.hw_key) { 294*fb9987d0SSujith if (tx_info->control.hw_key->alg == ALG_WEP) 295*fb9987d0SSujith return ATH9K_KEY_TYPE_WEP; 296*fb9987d0SSujith else if (tx_info->control.hw_key->alg == ALG_TKIP) 297*fb9987d0SSujith return ATH9K_KEY_TYPE_TKIP; 298*fb9987d0SSujith else if (tx_info->control.hw_key->alg == ALG_CCMP) 299*fb9987d0SSujith return ATH9K_KEY_TYPE_AES; 300*fb9987d0SSujith } 301*fb9987d0SSujith 302*fb9987d0SSujith return ATH9K_KEY_TYPE_CLEAR; 303*fb9987d0SSujith } 304*fb9987d0SSujith EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype); 305*fb9987d0SSujith 306*fb9987d0SSujith /* 307*fb9987d0SSujith * Calculate the RX filter to be set in the HW. 308*fb9987d0SSujith */ 309*fb9987d0SSujith u32 ath9k_cmn_calcrxfilter(struct ieee80211_hw *hw, struct ath_hw *ah, 310*fb9987d0SSujith unsigned int rxfilter) 311*fb9987d0SSujith { 312*fb9987d0SSujith #define RX_FILTER_PRESERVE (ATH9K_RX_FILTER_PHYERR | ATH9K_RX_FILTER_PHYRADAR) 313*fb9987d0SSujith 314*fb9987d0SSujith u32 rfilt; 315*fb9987d0SSujith 316*fb9987d0SSujith rfilt = (ath9k_hw_getrxfilter(ah) & RX_FILTER_PRESERVE) 317*fb9987d0SSujith | ATH9K_RX_FILTER_UCAST | ATH9K_RX_FILTER_BCAST 318*fb9987d0SSujith | ATH9K_RX_FILTER_MCAST; 319*fb9987d0SSujith 320*fb9987d0SSujith /* If not a STA, enable processing of Probe Requests */ 321*fb9987d0SSujith if (ah->opmode != NL80211_IFTYPE_STATION) 322*fb9987d0SSujith rfilt |= ATH9K_RX_FILTER_PROBEREQ; 323*fb9987d0SSujith 324*fb9987d0SSujith /* 325*fb9987d0SSujith * Set promiscuous mode when FIF_PROMISC_IN_BSS is enabled for station 326*fb9987d0SSujith * mode interface or when in monitor mode. AP mode does not need this 327*fb9987d0SSujith * since it receives all in-BSS frames anyway. 328*fb9987d0SSujith */ 329*fb9987d0SSujith if (((ah->opmode != NL80211_IFTYPE_AP) && 330*fb9987d0SSujith (rxfilter & FIF_PROMISC_IN_BSS)) || 331*fb9987d0SSujith (ah->opmode == NL80211_IFTYPE_MONITOR)) 332*fb9987d0SSujith rfilt |= ATH9K_RX_FILTER_PROM; 333*fb9987d0SSujith 334*fb9987d0SSujith if (rxfilter & FIF_CONTROL) 335*fb9987d0SSujith rfilt |= ATH9K_RX_FILTER_CONTROL; 336*fb9987d0SSujith 337*fb9987d0SSujith if ((ah->opmode == NL80211_IFTYPE_STATION) && 338*fb9987d0SSujith !(rxfilter & FIF_BCN_PRBRESP_PROMISC)) 339*fb9987d0SSujith rfilt |= ATH9K_RX_FILTER_MYBEACON; 340*fb9987d0SSujith else 341*fb9987d0SSujith rfilt |= ATH9K_RX_FILTER_BEACON; 342*fb9987d0SSujith 343*fb9987d0SSujith if ((AR_SREV_9280_10_OR_LATER(ah) || 344*fb9987d0SSujith AR_SREV_9285_10_OR_LATER(ah)) && 345*fb9987d0SSujith (ah->opmode == NL80211_IFTYPE_AP) && 346*fb9987d0SSujith (rxfilter & FIF_PSPOLL)) 347*fb9987d0SSujith rfilt |= ATH9K_RX_FILTER_PSPOLL; 348*fb9987d0SSujith 349*fb9987d0SSujith if (conf_is_ht(&hw->conf)) 350*fb9987d0SSujith rfilt |= ATH9K_RX_FILTER_COMP_BAR; 351*fb9987d0SSujith 352*fb9987d0SSujith return rfilt; 353*fb9987d0SSujith 354*fb9987d0SSujith #undef RX_FILTER_PRESERVE 355*fb9987d0SSujith } 356*fb9987d0SSujith EXPORT_SYMBOL(ath9k_cmn_calcrxfilter); 357*fb9987d0SSujith 358*fb9987d0SSujith /* 359*fb9987d0SSujith * Recv initialization for opmode change. 360*fb9987d0SSujith */ 361*fb9987d0SSujith void ath9k_cmn_opmode_init(struct ieee80211_hw *hw, struct ath_hw *ah, 362*fb9987d0SSujith unsigned int rxfilter) 363*fb9987d0SSujith { 364*fb9987d0SSujith struct ath_common *common = ath9k_hw_common(ah); 365*fb9987d0SSujith 366*fb9987d0SSujith u32 rfilt, mfilt[2]; 367*fb9987d0SSujith 368*fb9987d0SSujith /* configure rx filter */ 369*fb9987d0SSujith rfilt = ath9k_cmn_calcrxfilter(hw, ah, rxfilter); 370*fb9987d0SSujith ath9k_hw_setrxfilter(ah, rfilt); 371*fb9987d0SSujith 372*fb9987d0SSujith /* configure bssid mask */ 373*fb9987d0SSujith if (ah->caps.hw_caps & ATH9K_HW_CAP_BSSIDMASK) 374*fb9987d0SSujith ath_hw_setbssidmask(common); 375*fb9987d0SSujith 376*fb9987d0SSujith /* configure operational mode */ 377*fb9987d0SSujith ath9k_hw_setopmode(ah); 378*fb9987d0SSujith 379*fb9987d0SSujith /* Handle any link-level address change. */ 380*fb9987d0SSujith ath9k_hw_setmac(ah, common->macaddr); 381*fb9987d0SSujith 382*fb9987d0SSujith /* calculate and install multicast filter */ 383*fb9987d0SSujith mfilt[0] = mfilt[1] = ~0; 384*fb9987d0SSujith ath9k_hw_setmcastfilter(ah, mfilt[0], mfilt[1]); 385*fb9987d0SSujith } 386*fb9987d0SSujith EXPORT_SYMBOL(ath9k_cmn_opmode_init); 387*fb9987d0SSujith 388*fb9987d0SSujith static u32 ath9k_get_extchanmode(struct ieee80211_channel *chan, 389*fb9987d0SSujith enum nl80211_channel_type channel_type) 390*fb9987d0SSujith { 391*fb9987d0SSujith u32 chanmode = 0; 392*fb9987d0SSujith 393*fb9987d0SSujith switch (chan->band) { 394*fb9987d0SSujith case IEEE80211_BAND_2GHZ: 395*fb9987d0SSujith switch (channel_type) { 396*fb9987d0SSujith case NL80211_CHAN_NO_HT: 397*fb9987d0SSujith case NL80211_CHAN_HT20: 398*fb9987d0SSujith chanmode = CHANNEL_G_HT20; 399*fb9987d0SSujith break; 400*fb9987d0SSujith case NL80211_CHAN_HT40PLUS: 401*fb9987d0SSujith chanmode = CHANNEL_G_HT40PLUS; 402*fb9987d0SSujith break; 403*fb9987d0SSujith case NL80211_CHAN_HT40MINUS: 404*fb9987d0SSujith chanmode = CHANNEL_G_HT40MINUS; 405*fb9987d0SSujith break; 406*fb9987d0SSujith } 407*fb9987d0SSujith break; 408*fb9987d0SSujith case IEEE80211_BAND_5GHZ: 409*fb9987d0SSujith switch (channel_type) { 410*fb9987d0SSujith case NL80211_CHAN_NO_HT: 411*fb9987d0SSujith case NL80211_CHAN_HT20: 412*fb9987d0SSujith chanmode = CHANNEL_A_HT20; 413*fb9987d0SSujith break; 414*fb9987d0SSujith case NL80211_CHAN_HT40PLUS: 415*fb9987d0SSujith chanmode = CHANNEL_A_HT40PLUS; 416*fb9987d0SSujith break; 417*fb9987d0SSujith case NL80211_CHAN_HT40MINUS: 418*fb9987d0SSujith chanmode = CHANNEL_A_HT40MINUS; 419*fb9987d0SSujith break; 420*fb9987d0SSujith } 421*fb9987d0SSujith break; 422*fb9987d0SSujith default: 423*fb9987d0SSujith break; 424*fb9987d0SSujith } 425*fb9987d0SSujith 426*fb9987d0SSujith return chanmode; 427*fb9987d0SSujith } 428*fb9987d0SSujith 429*fb9987d0SSujith /* 430*fb9987d0SSujith * Update internal channel flags. 431*fb9987d0SSujith */ 432*fb9987d0SSujith void ath9k_cmn_update_ichannel(struct ieee80211_hw *hw, 433*fb9987d0SSujith struct ath9k_channel *ichan) 434*fb9987d0SSujith { 435*fb9987d0SSujith struct ieee80211_channel *chan = hw->conf.channel; 436*fb9987d0SSujith struct ieee80211_conf *conf = &hw->conf; 437*fb9987d0SSujith 438*fb9987d0SSujith ichan->channel = chan->center_freq; 439*fb9987d0SSujith ichan->chan = chan; 440*fb9987d0SSujith 441*fb9987d0SSujith if (chan->band == IEEE80211_BAND_2GHZ) { 442*fb9987d0SSujith ichan->chanmode = CHANNEL_G; 443*fb9987d0SSujith ichan->channelFlags = CHANNEL_2GHZ | CHANNEL_OFDM | CHANNEL_G; 444*fb9987d0SSujith } else { 445*fb9987d0SSujith ichan->chanmode = CHANNEL_A; 446*fb9987d0SSujith ichan->channelFlags = CHANNEL_5GHZ | CHANNEL_OFDM; 447*fb9987d0SSujith } 448*fb9987d0SSujith 449*fb9987d0SSujith if (conf_is_ht(conf)) 450*fb9987d0SSujith ichan->chanmode = ath9k_get_extchanmode(chan, 451*fb9987d0SSujith conf->channel_type); 452*fb9987d0SSujith } 453*fb9987d0SSujith EXPORT_SYMBOL(ath9k_cmn_update_ichannel); 454*fb9987d0SSujith 455*fb9987d0SSujith /* 456*fb9987d0SSujith * Get the internal channel reference. 457*fb9987d0SSujith */ 458*fb9987d0SSujith struct ath9k_channel *ath9k_cmn_get_curchannel(struct ieee80211_hw *hw, 459*fb9987d0SSujith struct ath_hw *ah) 460*fb9987d0SSujith { 461*fb9987d0SSujith struct ieee80211_channel *curchan = hw->conf.channel; 462*fb9987d0SSujith struct ath9k_channel *channel; 463*fb9987d0SSujith u8 chan_idx; 464*fb9987d0SSujith 465*fb9987d0SSujith chan_idx = curchan->hw_value; 466*fb9987d0SSujith channel = &ah->channels[chan_idx]; 467*fb9987d0SSujith ath9k_cmn_update_ichannel(hw, channel); 468*fb9987d0SSujith 469*fb9987d0SSujith return channel; 470*fb9987d0SSujith } 471*fb9987d0SSujith EXPORT_SYMBOL(ath9k_cmn_get_curchannel); 472*fb9987d0SSujith 473*fb9987d0SSujith static int ath_setkey_tkip(struct ath_common *common, u16 keyix, const u8 *key, 474*fb9987d0SSujith struct ath9k_keyval *hk, const u8 *addr, 475*fb9987d0SSujith bool authenticator) 476*fb9987d0SSujith { 477*fb9987d0SSujith struct ath_hw *ah = common->ah; 478*fb9987d0SSujith const u8 *key_rxmic; 479*fb9987d0SSujith const u8 *key_txmic; 480*fb9987d0SSujith 481*fb9987d0SSujith key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; 482*fb9987d0SSujith key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; 483*fb9987d0SSujith 484*fb9987d0SSujith if (addr == NULL) { 485*fb9987d0SSujith /* 486*fb9987d0SSujith * Group key installation - only two key cache entries are used 487*fb9987d0SSujith * regardless of splitmic capability since group key is only 488*fb9987d0SSujith * used either for TX or RX. 489*fb9987d0SSujith */ 490*fb9987d0SSujith if (authenticator) { 491*fb9987d0SSujith memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); 492*fb9987d0SSujith memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_mic)); 493*fb9987d0SSujith } else { 494*fb9987d0SSujith memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); 495*fb9987d0SSujith memcpy(hk->kv_txmic, key_rxmic, sizeof(hk->kv_mic)); 496*fb9987d0SSujith } 497*fb9987d0SSujith return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr); 498*fb9987d0SSujith } 499*fb9987d0SSujith if (!common->splitmic) { 500*fb9987d0SSujith /* TX and RX keys share the same key cache entry. */ 501*fb9987d0SSujith memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); 502*fb9987d0SSujith memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic)); 503*fb9987d0SSujith return ath9k_hw_set_keycache_entry(ah, keyix, hk, addr); 504*fb9987d0SSujith } 505*fb9987d0SSujith 506*fb9987d0SSujith /* Separate key cache entries for TX and RX */ 507*fb9987d0SSujith 508*fb9987d0SSujith /* TX key goes at first index, RX key at +32. */ 509*fb9987d0SSujith memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); 510*fb9987d0SSujith if (!ath9k_hw_set_keycache_entry(ah, keyix, hk, NULL)) { 511*fb9987d0SSujith /* TX MIC entry failed. No need to proceed further */ 512*fb9987d0SSujith ath_print(common, ATH_DBG_FATAL, 513*fb9987d0SSujith "Setting TX MIC Key Failed\n"); 514*fb9987d0SSujith return 0; 515*fb9987d0SSujith } 516*fb9987d0SSujith 517*fb9987d0SSujith memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); 518*fb9987d0SSujith /* XXX delete tx key on failure? */ 519*fb9987d0SSujith return ath9k_hw_set_keycache_entry(ah, keyix + 32, hk, addr); 520*fb9987d0SSujith } 521*fb9987d0SSujith 522*fb9987d0SSujith static int ath_reserve_key_cache_slot_tkip(struct ath_common *common) 523*fb9987d0SSujith { 524*fb9987d0SSujith int i; 525*fb9987d0SSujith 526*fb9987d0SSujith for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { 527*fb9987d0SSujith if (test_bit(i, common->keymap) || 528*fb9987d0SSujith test_bit(i + 64, common->keymap)) 529*fb9987d0SSujith continue; /* At least one part of TKIP key allocated */ 530*fb9987d0SSujith if (common->splitmic && 531*fb9987d0SSujith (test_bit(i + 32, common->keymap) || 532*fb9987d0SSujith test_bit(i + 64 + 32, common->keymap))) 533*fb9987d0SSujith continue; /* At least one part of TKIP key allocated */ 534*fb9987d0SSujith 535*fb9987d0SSujith /* Found a free slot for a TKIP key */ 536*fb9987d0SSujith return i; 537*fb9987d0SSujith } 538*fb9987d0SSujith return -1; 539*fb9987d0SSujith } 540*fb9987d0SSujith 541*fb9987d0SSujith static int ath_reserve_key_cache_slot(struct ath_common *common) 542*fb9987d0SSujith { 543*fb9987d0SSujith int i; 544*fb9987d0SSujith 545*fb9987d0SSujith /* First, try to find slots that would not be available for TKIP. */ 546*fb9987d0SSujith if (common->splitmic) { 547*fb9987d0SSujith for (i = IEEE80211_WEP_NKID; i < common->keymax / 4; i++) { 548*fb9987d0SSujith if (!test_bit(i, common->keymap) && 549*fb9987d0SSujith (test_bit(i + 32, common->keymap) || 550*fb9987d0SSujith test_bit(i + 64, common->keymap) || 551*fb9987d0SSujith test_bit(i + 64 + 32, common->keymap))) 552*fb9987d0SSujith return i; 553*fb9987d0SSujith if (!test_bit(i + 32, common->keymap) && 554*fb9987d0SSujith (test_bit(i, common->keymap) || 555*fb9987d0SSujith test_bit(i + 64, common->keymap) || 556*fb9987d0SSujith test_bit(i + 64 + 32, common->keymap))) 557*fb9987d0SSujith return i + 32; 558*fb9987d0SSujith if (!test_bit(i + 64, common->keymap) && 559*fb9987d0SSujith (test_bit(i , common->keymap) || 560*fb9987d0SSujith test_bit(i + 32, common->keymap) || 561*fb9987d0SSujith test_bit(i + 64 + 32, common->keymap))) 562*fb9987d0SSujith return i + 64; 563*fb9987d0SSujith if (!test_bit(i + 64 + 32, common->keymap) && 564*fb9987d0SSujith (test_bit(i, common->keymap) || 565*fb9987d0SSujith test_bit(i + 32, common->keymap) || 566*fb9987d0SSujith test_bit(i + 64, common->keymap))) 567*fb9987d0SSujith return i + 64 + 32; 568*fb9987d0SSujith } 569*fb9987d0SSujith } else { 570*fb9987d0SSujith for (i = IEEE80211_WEP_NKID; i < common->keymax / 2; i++) { 571*fb9987d0SSujith if (!test_bit(i, common->keymap) && 572*fb9987d0SSujith test_bit(i + 64, common->keymap)) 573*fb9987d0SSujith return i; 574*fb9987d0SSujith if (test_bit(i, common->keymap) && 575*fb9987d0SSujith !test_bit(i + 64, common->keymap)) 576*fb9987d0SSujith return i + 64; 577*fb9987d0SSujith } 578*fb9987d0SSujith } 579*fb9987d0SSujith 580*fb9987d0SSujith /* No partially used TKIP slots, pick any available slot */ 581*fb9987d0SSujith for (i = IEEE80211_WEP_NKID; i < common->keymax; i++) { 582*fb9987d0SSujith /* Do not allow slots that could be needed for TKIP group keys 583*fb9987d0SSujith * to be used. This limitation could be removed if we know that 584*fb9987d0SSujith * TKIP will not be used. */ 585*fb9987d0SSujith if (i >= 64 && i < 64 + IEEE80211_WEP_NKID) 586*fb9987d0SSujith continue; 587*fb9987d0SSujith if (common->splitmic) { 588*fb9987d0SSujith if (i >= 32 && i < 32 + IEEE80211_WEP_NKID) 589*fb9987d0SSujith continue; 590*fb9987d0SSujith if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID) 591*fb9987d0SSujith continue; 592*fb9987d0SSujith } 593*fb9987d0SSujith 594*fb9987d0SSujith if (!test_bit(i, common->keymap)) 595*fb9987d0SSujith return i; /* Found a free slot for a key */ 596*fb9987d0SSujith } 597*fb9987d0SSujith 598*fb9987d0SSujith /* No free slot found */ 599*fb9987d0SSujith return -1; 600*fb9987d0SSujith } 601*fb9987d0SSujith 602*fb9987d0SSujith /* 603*fb9987d0SSujith * Configure encryption in the HW. 604*fb9987d0SSujith */ 605*fb9987d0SSujith int ath9k_cmn_key_config(struct ath_common *common, 606*fb9987d0SSujith struct ieee80211_vif *vif, 607*fb9987d0SSujith struct ieee80211_sta *sta, 608*fb9987d0SSujith struct ieee80211_key_conf *key) 609*fb9987d0SSujith { 610*fb9987d0SSujith struct ath_hw *ah = common->ah; 611*fb9987d0SSujith struct ath9k_keyval hk; 612*fb9987d0SSujith const u8 *mac = NULL; 613*fb9987d0SSujith int ret = 0; 614*fb9987d0SSujith int idx; 615*fb9987d0SSujith 616*fb9987d0SSujith memset(&hk, 0, sizeof(hk)); 617*fb9987d0SSujith 618*fb9987d0SSujith switch (key->alg) { 619*fb9987d0SSujith case ALG_WEP: 620*fb9987d0SSujith hk.kv_type = ATH9K_CIPHER_WEP; 621*fb9987d0SSujith break; 622*fb9987d0SSujith case ALG_TKIP: 623*fb9987d0SSujith hk.kv_type = ATH9K_CIPHER_TKIP; 624*fb9987d0SSujith break; 625*fb9987d0SSujith case ALG_CCMP: 626*fb9987d0SSujith hk.kv_type = ATH9K_CIPHER_AES_CCM; 627*fb9987d0SSujith break; 628*fb9987d0SSujith default: 629*fb9987d0SSujith return -EOPNOTSUPP; 630*fb9987d0SSujith } 631*fb9987d0SSujith 632*fb9987d0SSujith hk.kv_len = key->keylen; 633*fb9987d0SSujith memcpy(hk.kv_val, key->key, key->keylen); 634*fb9987d0SSujith 635*fb9987d0SSujith if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { 636*fb9987d0SSujith /* For now, use the default keys for broadcast keys. This may 637*fb9987d0SSujith * need to change with virtual interfaces. */ 638*fb9987d0SSujith idx = key->keyidx; 639*fb9987d0SSujith } else if (key->keyidx) { 640*fb9987d0SSujith if (WARN_ON(!sta)) 641*fb9987d0SSujith return -EOPNOTSUPP; 642*fb9987d0SSujith mac = sta->addr; 643*fb9987d0SSujith 644*fb9987d0SSujith if (vif->type != NL80211_IFTYPE_AP) { 645*fb9987d0SSujith /* Only keyidx 0 should be used with unicast key, but 646*fb9987d0SSujith * allow this for client mode for now. */ 647*fb9987d0SSujith idx = key->keyidx; 648*fb9987d0SSujith } else 649*fb9987d0SSujith return -EIO; 650*fb9987d0SSujith } else { 651*fb9987d0SSujith if (WARN_ON(!sta)) 652*fb9987d0SSujith return -EOPNOTSUPP; 653*fb9987d0SSujith mac = sta->addr; 654*fb9987d0SSujith 655*fb9987d0SSujith if (key->alg == ALG_TKIP) 656*fb9987d0SSujith idx = ath_reserve_key_cache_slot_tkip(common); 657*fb9987d0SSujith else 658*fb9987d0SSujith idx = ath_reserve_key_cache_slot(common); 659*fb9987d0SSujith if (idx < 0) 660*fb9987d0SSujith return -ENOSPC; /* no free key cache entries */ 661*fb9987d0SSujith } 662*fb9987d0SSujith 663*fb9987d0SSujith if (key->alg == ALG_TKIP) 664*fb9987d0SSujith ret = ath_setkey_tkip(common, idx, key->key, &hk, mac, 665*fb9987d0SSujith vif->type == NL80211_IFTYPE_AP); 666*fb9987d0SSujith else 667*fb9987d0SSujith ret = ath9k_hw_set_keycache_entry(ah, idx, &hk, mac); 668*fb9987d0SSujith 669*fb9987d0SSujith if (!ret) 670*fb9987d0SSujith return -EIO; 671*fb9987d0SSujith 672*fb9987d0SSujith set_bit(idx, common->keymap); 673*fb9987d0SSujith if (key->alg == ALG_TKIP) { 674*fb9987d0SSujith set_bit(idx + 64, common->keymap); 675*fb9987d0SSujith if (common->splitmic) { 676*fb9987d0SSujith set_bit(idx + 32, common->keymap); 677*fb9987d0SSujith set_bit(idx + 64 + 32, common->keymap); 678*fb9987d0SSujith } 679*fb9987d0SSujith } 680*fb9987d0SSujith 681*fb9987d0SSujith return idx; 682*fb9987d0SSujith } 683*fb9987d0SSujith EXPORT_SYMBOL(ath9k_cmn_key_config); 684*fb9987d0SSujith 685*fb9987d0SSujith /* 686*fb9987d0SSujith * Delete Key. 687*fb9987d0SSujith */ 688*fb9987d0SSujith void ath9k_cmn_key_delete(struct ath_common *common, 689*fb9987d0SSujith struct ieee80211_key_conf *key) 690*fb9987d0SSujith { 691*fb9987d0SSujith struct ath_hw *ah = common->ah; 692*fb9987d0SSujith 693*fb9987d0SSujith ath9k_hw_keyreset(ah, key->hw_key_idx); 694*fb9987d0SSujith if (key->hw_key_idx < IEEE80211_WEP_NKID) 695*fb9987d0SSujith return; 696*fb9987d0SSujith 697*fb9987d0SSujith clear_bit(key->hw_key_idx, common->keymap); 698*fb9987d0SSujith if (key->alg != ALG_TKIP) 699*fb9987d0SSujith return; 700*fb9987d0SSujith 701*fb9987d0SSujith clear_bit(key->hw_key_idx + 64, common->keymap); 702*fb9987d0SSujith if (common->splitmic) { 703*fb9987d0SSujith ath9k_hw_keyreset(ah, key->hw_key_idx + 32); 704*fb9987d0SSujith clear_bit(key->hw_key_idx + 32, common->keymap); 705*fb9987d0SSujith clear_bit(key->hw_key_idx + 64 + 32, common->keymap); 706*fb9987d0SSujith } 707*fb9987d0SSujith } 708*fb9987d0SSujith EXPORT_SYMBOL(ath9k_cmn_key_delete); 709*fb9987d0SSujith 710db86f07eSLuis R. Rodriguez static int __init ath9k_cmn_init(void) 711db86f07eSLuis R. Rodriguez { 712db86f07eSLuis R. Rodriguez return 0; 713db86f07eSLuis R. Rodriguez } 714db86f07eSLuis R. Rodriguez module_init(ath9k_cmn_init); 715db86f07eSLuis R. Rodriguez 716db86f07eSLuis R. Rodriguez static void __exit ath9k_cmn_exit(void) 717db86f07eSLuis R. Rodriguez { 718db86f07eSLuis R. Rodriguez return; 719db86f07eSLuis R. Rodriguez } 720db86f07eSLuis R. Rodriguez module_exit(ath9k_cmn_exit); 721