1*db86f07eSLuis R. Rodriguez /* 2*db86f07eSLuis R. Rodriguez * Copyright (c) 2009 Atheros Communications Inc. 3*db86f07eSLuis R. Rodriguez * 4*db86f07eSLuis R. Rodriguez * Permission to use, copy, modify, and/or distribute this software for any 5*db86f07eSLuis R. Rodriguez * purpose with or without fee is hereby granted, provided that the above 6*db86f07eSLuis R. Rodriguez * copyright notice and this permission notice appear in all copies. 7*db86f07eSLuis R. Rodriguez * 8*db86f07eSLuis R. Rodriguez * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9*db86f07eSLuis R. Rodriguez * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10*db86f07eSLuis R. Rodriguez * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11*db86f07eSLuis R. Rodriguez * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12*db86f07eSLuis R. Rodriguez * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13*db86f07eSLuis R. Rodriguez * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14*db86f07eSLuis R. Rodriguez * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15*db86f07eSLuis R. Rodriguez */ 16*db86f07eSLuis R. Rodriguez 17*db86f07eSLuis R. Rodriguez /* 18*db86f07eSLuis R. Rodriguez * Module for common driver code between ath9k and ath9k_htc 19*db86f07eSLuis R. Rodriguez */ 20*db86f07eSLuis R. Rodriguez 21*db86f07eSLuis R. Rodriguez #include <linux/kernel.h> 22*db86f07eSLuis R. Rodriguez #include <linux/module.h> 23*db86f07eSLuis R. Rodriguez 24*db86f07eSLuis R. Rodriguez #include "common.h" 25*db86f07eSLuis R. Rodriguez 26*db86f07eSLuis R. Rodriguez MODULE_AUTHOR("Atheros Communications"); 27*db86f07eSLuis R. Rodriguez MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards."); 28*db86f07eSLuis R. Rodriguez MODULE_LICENSE("Dual BSD/GPL"); 29*db86f07eSLuis R. Rodriguez 30*db86f07eSLuis R. Rodriguez /* Common RX processing */ 31*db86f07eSLuis R. Rodriguez 32*db86f07eSLuis R. Rodriguez /* Assumes you've already done the endian to CPU conversion */ 33*db86f07eSLuis R. Rodriguez static bool ath9k_rx_accept(struct ath_common *common, 34*db86f07eSLuis R. Rodriguez struct sk_buff *skb, 35*db86f07eSLuis R. Rodriguez struct ieee80211_rx_status *rxs, 36*db86f07eSLuis R. Rodriguez struct ath_rx_status *rx_stats, 37*db86f07eSLuis R. Rodriguez bool *decrypt_error) 38*db86f07eSLuis R. Rodriguez { 39*db86f07eSLuis R. Rodriguez struct ath_hw *ah = common->ah; 40*db86f07eSLuis R. Rodriguez struct ieee80211_hdr *hdr; 41*db86f07eSLuis R. Rodriguez __le16 fc; 42*db86f07eSLuis R. Rodriguez 43*db86f07eSLuis R. Rodriguez hdr = (struct ieee80211_hdr *) skb->data; 44*db86f07eSLuis R. Rodriguez fc = hdr->frame_control; 45*db86f07eSLuis R. Rodriguez 46*db86f07eSLuis R. Rodriguez if (!rx_stats->rs_datalen) 47*db86f07eSLuis R. Rodriguez return false; 48*db86f07eSLuis R. Rodriguez /* 49*db86f07eSLuis R. Rodriguez * rs_status follows rs_datalen so if rs_datalen is too large 50*db86f07eSLuis R. Rodriguez * we can take a hint that hardware corrupted it, so ignore 51*db86f07eSLuis R. Rodriguez * those frames. 52*db86f07eSLuis R. Rodriguez */ 53*db86f07eSLuis R. Rodriguez if (rx_stats->rs_datalen > common->rx_bufsize) 54*db86f07eSLuis R. Rodriguez return false; 55*db86f07eSLuis R. Rodriguez 56*db86f07eSLuis R. Rodriguez if (rx_stats->rs_more) { 57*db86f07eSLuis R. Rodriguez /* 58*db86f07eSLuis R. Rodriguez * Frame spans multiple descriptors; this cannot happen yet 59*db86f07eSLuis R. Rodriguez * as we don't support jumbograms. If not in monitor mode, 60*db86f07eSLuis R. Rodriguez * discard the frame. Enable this if you want to see 61*db86f07eSLuis R. Rodriguez * error frames in Monitor mode. 62*db86f07eSLuis R. Rodriguez */ 63*db86f07eSLuis R. Rodriguez if (ah->opmode != NL80211_IFTYPE_MONITOR) 64*db86f07eSLuis R. Rodriguez return false; 65*db86f07eSLuis R. Rodriguez } else if (rx_stats->rs_status != 0) { 66*db86f07eSLuis R. Rodriguez if (rx_stats->rs_status & ATH9K_RXERR_CRC) 67*db86f07eSLuis R. Rodriguez rxs->flag |= RX_FLAG_FAILED_FCS_CRC; 68*db86f07eSLuis R. Rodriguez if (rx_stats->rs_status & ATH9K_RXERR_PHY) 69*db86f07eSLuis R. Rodriguez return false; 70*db86f07eSLuis R. Rodriguez 71*db86f07eSLuis R. Rodriguez if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) { 72*db86f07eSLuis R. Rodriguez *decrypt_error = true; 73*db86f07eSLuis R. Rodriguez } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) { 74*db86f07eSLuis R. Rodriguez if (ieee80211_is_ctl(fc)) 75*db86f07eSLuis R. Rodriguez /* 76*db86f07eSLuis R. Rodriguez * Sometimes, we get invalid 77*db86f07eSLuis R. Rodriguez * MIC failures on valid control frames. 78*db86f07eSLuis R. Rodriguez * Remove these mic errors. 79*db86f07eSLuis R. Rodriguez */ 80*db86f07eSLuis R. Rodriguez rx_stats->rs_status &= ~ATH9K_RXERR_MIC; 81*db86f07eSLuis R. Rodriguez else 82*db86f07eSLuis R. Rodriguez rxs->flag |= RX_FLAG_MMIC_ERROR; 83*db86f07eSLuis R. Rodriguez } 84*db86f07eSLuis R. Rodriguez /* 85*db86f07eSLuis R. Rodriguez * Reject error frames with the exception of 86*db86f07eSLuis R. Rodriguez * decryption and MIC failures. For monitor mode, 87*db86f07eSLuis R. Rodriguez * we also ignore the CRC error. 88*db86f07eSLuis R. Rodriguez */ 89*db86f07eSLuis R. Rodriguez if (ah->opmode == NL80211_IFTYPE_MONITOR) { 90*db86f07eSLuis R. Rodriguez if (rx_stats->rs_status & 91*db86f07eSLuis R. Rodriguez ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC | 92*db86f07eSLuis R. Rodriguez ATH9K_RXERR_CRC)) 93*db86f07eSLuis R. Rodriguez return false; 94*db86f07eSLuis R. Rodriguez } else { 95*db86f07eSLuis R. Rodriguez if (rx_stats->rs_status & 96*db86f07eSLuis R. Rodriguez ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) { 97*db86f07eSLuis R. Rodriguez return false; 98*db86f07eSLuis R. Rodriguez } 99*db86f07eSLuis R. Rodriguez } 100*db86f07eSLuis R. Rodriguez } 101*db86f07eSLuis R. Rodriguez return true; 102*db86f07eSLuis R. Rodriguez } 103*db86f07eSLuis R. Rodriguez 104*db86f07eSLuis R. Rodriguez static u8 ath9k_process_rate(struct ath_common *common, 105*db86f07eSLuis R. Rodriguez struct ieee80211_hw *hw, 106*db86f07eSLuis R. Rodriguez struct ath_rx_status *rx_stats, 107*db86f07eSLuis R. Rodriguez struct ieee80211_rx_status *rxs, 108*db86f07eSLuis R. Rodriguez struct sk_buff *skb) 109*db86f07eSLuis R. Rodriguez { 110*db86f07eSLuis R. Rodriguez struct ieee80211_supported_band *sband; 111*db86f07eSLuis R. Rodriguez enum ieee80211_band band; 112*db86f07eSLuis R. Rodriguez unsigned int i = 0; 113*db86f07eSLuis R. Rodriguez 114*db86f07eSLuis R. Rodriguez band = hw->conf.channel->band; 115*db86f07eSLuis R. Rodriguez sband = hw->wiphy->bands[band]; 116*db86f07eSLuis R. Rodriguez 117*db86f07eSLuis R. Rodriguez if (rx_stats->rs_rate & 0x80) { 118*db86f07eSLuis R. Rodriguez /* HT rate */ 119*db86f07eSLuis R. Rodriguez rxs->flag |= RX_FLAG_HT; 120*db86f07eSLuis R. Rodriguez if (rx_stats->rs_flags & ATH9K_RX_2040) 121*db86f07eSLuis R. Rodriguez rxs->flag |= RX_FLAG_40MHZ; 122*db86f07eSLuis R. Rodriguez if (rx_stats->rs_flags & ATH9K_RX_GI) 123*db86f07eSLuis R. Rodriguez rxs->flag |= RX_FLAG_SHORT_GI; 124*db86f07eSLuis R. Rodriguez return rx_stats->rs_rate & 0x7f; 125*db86f07eSLuis R. Rodriguez } 126*db86f07eSLuis R. Rodriguez 127*db86f07eSLuis R. Rodriguez for (i = 0; i < sband->n_bitrates; i++) { 128*db86f07eSLuis R. Rodriguez if (sband->bitrates[i].hw_value == rx_stats->rs_rate) 129*db86f07eSLuis R. Rodriguez return i; 130*db86f07eSLuis R. Rodriguez if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) { 131*db86f07eSLuis R. Rodriguez rxs->flag |= RX_FLAG_SHORTPRE; 132*db86f07eSLuis R. Rodriguez return i; 133*db86f07eSLuis R. Rodriguez } 134*db86f07eSLuis R. Rodriguez } 135*db86f07eSLuis R. Rodriguez 136*db86f07eSLuis R. Rodriguez /* No valid hardware bitrate found -- we should not get here */ 137*db86f07eSLuis R. Rodriguez ath_print(common, ATH_DBG_XMIT, "unsupported hw bitrate detected " 138*db86f07eSLuis R. Rodriguez "0x%02x using 1 Mbit\n", rx_stats->rs_rate); 139*db86f07eSLuis R. Rodriguez if ((common->debug_mask & ATH_DBG_XMIT)) 140*db86f07eSLuis R. Rodriguez print_hex_dump_bytes("", DUMP_PREFIX_NONE, skb->data, skb->len); 141*db86f07eSLuis R. Rodriguez 142*db86f07eSLuis R. Rodriguez return 0; 143*db86f07eSLuis R. Rodriguez } 144*db86f07eSLuis R. Rodriguez 145*db86f07eSLuis R. Rodriguez /* 146*db86f07eSLuis R. Rodriguez * Theory for reporting quality: 147*db86f07eSLuis R. Rodriguez * 148*db86f07eSLuis R. Rodriguez * At a hardware RSSI of 45 you will be able to use MCS 7 reliably. 149*db86f07eSLuis R. Rodriguez * At a hardware RSSI of 45 you will be able to use MCS 15 reliably. 150*db86f07eSLuis R. Rodriguez * At a hardware RSSI of 35 you should be able use 54 Mbps reliably. 151*db86f07eSLuis R. Rodriguez * 152*db86f07eSLuis R. Rodriguez * MCS 7 is the highets MCS index usable by a 1-stream device. 153*db86f07eSLuis R. Rodriguez * MCS 15 is the highest MCS index usable by a 2-stream device. 154*db86f07eSLuis R. Rodriguez * 155*db86f07eSLuis R. Rodriguez * All ath9k devices are either 1-stream or 2-stream. 156*db86f07eSLuis R. Rodriguez * 157*db86f07eSLuis R. Rodriguez * How many bars you see is derived from the qual reporting. 158*db86f07eSLuis R. Rodriguez * 159*db86f07eSLuis R. Rodriguez * A more elaborate scheme can be used here but it requires tables 160*db86f07eSLuis R. Rodriguez * of SNR/throughput for each possible mode used. For the MCS table 161*db86f07eSLuis R. Rodriguez * you can refer to the wireless wiki: 162*db86f07eSLuis R. Rodriguez * 163*db86f07eSLuis R. Rodriguez * http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n 164*db86f07eSLuis R. Rodriguez * 165*db86f07eSLuis R. Rodriguez */ 166*db86f07eSLuis R. Rodriguez static int ath9k_compute_qual(struct ieee80211_hw *hw, 167*db86f07eSLuis R. Rodriguez struct ath_rx_status *rx_stats) 168*db86f07eSLuis R. Rodriguez { 169*db86f07eSLuis R. Rodriguez int qual; 170*db86f07eSLuis R. Rodriguez 171*db86f07eSLuis R. Rodriguez if (conf_is_ht(&hw->conf)) 172*db86f07eSLuis R. Rodriguez qual = rx_stats->rs_rssi * 100 / 45; 173*db86f07eSLuis R. Rodriguez else 174*db86f07eSLuis R. Rodriguez qual = rx_stats->rs_rssi * 100 / 35; 175*db86f07eSLuis R. Rodriguez 176*db86f07eSLuis R. Rodriguez /* 177*db86f07eSLuis R. Rodriguez * rssi can be more than 45 though, anything above that 178*db86f07eSLuis R. Rodriguez * should be considered at 100% 179*db86f07eSLuis R. Rodriguez */ 180*db86f07eSLuis R. Rodriguez if (qual > 100) 181*db86f07eSLuis R. Rodriguez qual = 100; 182*db86f07eSLuis R. Rodriguez 183*db86f07eSLuis R. Rodriguez return qual; 184*db86f07eSLuis R. Rodriguez } 185*db86f07eSLuis R. Rodriguez 186*db86f07eSLuis R. Rodriguez static void ath9k_process_rssi(struct ath_common *common, 187*db86f07eSLuis R. Rodriguez struct ieee80211_hw *hw, 188*db86f07eSLuis R. Rodriguez struct sk_buff *skb, 189*db86f07eSLuis R. Rodriguez struct ath_rx_status *rx_stats) 190*db86f07eSLuis R. Rodriguez { 191*db86f07eSLuis R. Rodriguez struct ath_hw *ah = common->ah; 192*db86f07eSLuis R. Rodriguez struct ieee80211_sta *sta; 193*db86f07eSLuis R. Rodriguez struct ieee80211_hdr *hdr; 194*db86f07eSLuis R. Rodriguez struct ath_node *an; 195*db86f07eSLuis R. Rodriguez int last_rssi = ATH_RSSI_DUMMY_MARKER; 196*db86f07eSLuis R. Rodriguez __le16 fc; 197*db86f07eSLuis R. Rodriguez 198*db86f07eSLuis R. Rodriguez hdr = (struct ieee80211_hdr *)skb->data; 199*db86f07eSLuis R. Rodriguez fc = hdr->frame_control; 200*db86f07eSLuis R. Rodriguez 201*db86f07eSLuis R. Rodriguez rcu_read_lock(); 202*db86f07eSLuis R. Rodriguez /* 203*db86f07eSLuis R. Rodriguez * XXX: use ieee80211_find_sta! This requires quite a bit of work 204*db86f07eSLuis R. Rodriguez * under the current ath9k virtual wiphy implementation as we have 205*db86f07eSLuis R. Rodriguez * no way of tying a vif to wiphy. Typically vifs are attached to 206*db86f07eSLuis R. Rodriguez * at least one sdata of a wiphy on mac80211 but with ath9k virtual 207*db86f07eSLuis R. Rodriguez * wiphy you'd have to iterate over every wiphy and each sdata. 208*db86f07eSLuis R. Rodriguez */ 209*db86f07eSLuis R. Rodriguez sta = ieee80211_find_sta_by_hw(hw, hdr->addr2); 210*db86f07eSLuis R. Rodriguez if (sta) { 211*db86f07eSLuis R. Rodriguez an = (struct ath_node *) sta->drv_priv; 212*db86f07eSLuis R. Rodriguez if (rx_stats->rs_rssi != ATH9K_RSSI_BAD && 213*db86f07eSLuis R. Rodriguez !rx_stats->rs_moreaggr) 214*db86f07eSLuis R. Rodriguez ATH_RSSI_LPF(an->last_rssi, rx_stats->rs_rssi); 215*db86f07eSLuis R. Rodriguez last_rssi = an->last_rssi; 216*db86f07eSLuis R. Rodriguez } 217*db86f07eSLuis R. Rodriguez rcu_read_unlock(); 218*db86f07eSLuis R. Rodriguez 219*db86f07eSLuis R. Rodriguez if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER)) 220*db86f07eSLuis R. Rodriguez rx_stats->rs_rssi = ATH_EP_RND(last_rssi, 221*db86f07eSLuis R. Rodriguez ATH_RSSI_EP_MULTIPLIER); 222*db86f07eSLuis R. Rodriguez if (rx_stats->rs_rssi < 0) 223*db86f07eSLuis R. Rodriguez rx_stats->rs_rssi = 0; 224*db86f07eSLuis R. Rodriguez else if (rx_stats->rs_rssi > 127) 225*db86f07eSLuis R. Rodriguez rx_stats->rs_rssi = 127; 226*db86f07eSLuis R. Rodriguez 227*db86f07eSLuis R. Rodriguez /* Update Beacon RSSI, this is used by ANI. */ 228*db86f07eSLuis R. Rodriguez if (ieee80211_is_beacon(fc)) 229*db86f07eSLuis R. Rodriguez ah->stats.avgbrssi = rx_stats->rs_rssi; 230*db86f07eSLuis R. Rodriguez } 231*db86f07eSLuis R. Rodriguez 232*db86f07eSLuis R. Rodriguez /* 233*db86f07eSLuis R. Rodriguez * For Decrypt or Demic errors, we only mark packet status here and always push 234*db86f07eSLuis R. Rodriguez * up the frame up to let mac80211 handle the actual error case, be it no 235*db86f07eSLuis R. Rodriguez * decryption key or real decryption error. This let us keep statistics there. 236*db86f07eSLuis R. Rodriguez */ 237*db86f07eSLuis R. Rodriguez int ath9k_cmn_rx_skb_preprocess(struct ath_common *common, 238*db86f07eSLuis R. Rodriguez struct ieee80211_hw *hw, 239*db86f07eSLuis R. Rodriguez struct sk_buff *skb, 240*db86f07eSLuis R. Rodriguez struct ath_rx_status *rx_stats, 241*db86f07eSLuis R. Rodriguez struct ieee80211_rx_status *rx_status, 242*db86f07eSLuis R. Rodriguez bool *decrypt_error) 243*db86f07eSLuis R. Rodriguez { 244*db86f07eSLuis R. Rodriguez struct ath_hw *ah = common->ah; 245*db86f07eSLuis R. Rodriguez 246*db86f07eSLuis R. Rodriguez if (!ath9k_rx_accept(common, skb, rx_status, rx_stats, decrypt_error)) 247*db86f07eSLuis R. Rodriguez return -EINVAL; 248*db86f07eSLuis R. Rodriguez 249*db86f07eSLuis R. Rodriguez ath9k_process_rssi(common, hw, skb, rx_stats); 250*db86f07eSLuis R. Rodriguez 251*db86f07eSLuis R. Rodriguez rx_status->rate_idx = ath9k_process_rate(common, hw, 252*db86f07eSLuis R. Rodriguez rx_stats, rx_status, skb); 253*db86f07eSLuis R. Rodriguez rx_status->mactime = ath9k_hw_extend_tsf(ah, rx_stats->rs_tstamp); 254*db86f07eSLuis R. Rodriguez rx_status->band = hw->conf.channel->band; 255*db86f07eSLuis R. Rodriguez rx_status->freq = hw->conf.channel->center_freq; 256*db86f07eSLuis R. Rodriguez rx_status->noise = common->ani.noise_floor; 257*db86f07eSLuis R. Rodriguez rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi; 258*db86f07eSLuis R. Rodriguez rx_status->antenna = rx_stats->rs_antenna; 259*db86f07eSLuis R. Rodriguez rx_status->qual = ath9k_compute_qual(hw, rx_stats); 260*db86f07eSLuis R. Rodriguez rx_status->flag |= RX_FLAG_TSFT; 261*db86f07eSLuis R. Rodriguez 262*db86f07eSLuis R. Rodriguez return 0; 263*db86f07eSLuis R. Rodriguez } 264*db86f07eSLuis R. Rodriguez EXPORT_SYMBOL(ath9k_cmn_rx_skb_preprocess); 265*db86f07eSLuis R. Rodriguez 266*db86f07eSLuis R. Rodriguez void ath9k_cmn_rx_skb_postprocess(struct ath_common *common, 267*db86f07eSLuis R. Rodriguez struct sk_buff *skb, 268*db86f07eSLuis R. Rodriguez struct ath_rx_status *rx_stats, 269*db86f07eSLuis R. Rodriguez struct ieee80211_rx_status *rxs, 270*db86f07eSLuis R. Rodriguez bool decrypt_error) 271*db86f07eSLuis R. Rodriguez { 272*db86f07eSLuis R. Rodriguez struct ath_hw *ah = common->ah; 273*db86f07eSLuis R. Rodriguez struct ieee80211_hdr *hdr; 274*db86f07eSLuis R. Rodriguez int hdrlen, padsize; 275*db86f07eSLuis R. Rodriguez u8 keyix; 276*db86f07eSLuis R. Rodriguez __le16 fc; 277*db86f07eSLuis R. Rodriguez 278*db86f07eSLuis R. Rodriguez /* see if any padding is done by the hw and remove it */ 279*db86f07eSLuis R. Rodriguez hdr = (struct ieee80211_hdr *) skb->data; 280*db86f07eSLuis R. Rodriguez hdrlen = ieee80211_get_hdrlen_from_skb(skb); 281*db86f07eSLuis R. Rodriguez fc = hdr->frame_control; 282*db86f07eSLuis R. Rodriguez 283*db86f07eSLuis R. Rodriguez /* The MAC header is padded to have 32-bit boundary if the 284*db86f07eSLuis R. Rodriguez * packet payload is non-zero. The general calculation for 285*db86f07eSLuis R. Rodriguez * padsize would take into account odd header lengths: 286*db86f07eSLuis R. Rodriguez * padsize = (4 - hdrlen % 4) % 4; However, since only 287*db86f07eSLuis R. Rodriguez * even-length headers are used, padding can only be 0 or 2 288*db86f07eSLuis R. Rodriguez * bytes and we can optimize this a bit. In addition, we must 289*db86f07eSLuis R. Rodriguez * not try to remove padding from short control frames that do 290*db86f07eSLuis R. Rodriguez * not have payload. */ 291*db86f07eSLuis R. Rodriguez padsize = hdrlen & 3; 292*db86f07eSLuis R. Rodriguez if (padsize && hdrlen >= 24) { 293*db86f07eSLuis R. Rodriguez memmove(skb->data + padsize, skb->data, hdrlen); 294*db86f07eSLuis R. Rodriguez skb_pull(skb, padsize); 295*db86f07eSLuis R. Rodriguez } 296*db86f07eSLuis R. Rodriguez 297*db86f07eSLuis R. Rodriguez keyix = rx_stats->rs_keyix; 298*db86f07eSLuis R. Rodriguez 299*db86f07eSLuis R. Rodriguez if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) { 300*db86f07eSLuis R. Rodriguez rxs->flag |= RX_FLAG_DECRYPTED; 301*db86f07eSLuis R. Rodriguez } else if (ieee80211_has_protected(fc) 302*db86f07eSLuis R. Rodriguez && !decrypt_error && skb->len >= hdrlen + 4) { 303*db86f07eSLuis R. Rodriguez keyix = skb->data[hdrlen + 3] >> 6; 304*db86f07eSLuis R. Rodriguez 305*db86f07eSLuis R. Rodriguez if (test_bit(keyix, common->keymap)) 306*db86f07eSLuis R. Rodriguez rxs->flag |= RX_FLAG_DECRYPTED; 307*db86f07eSLuis R. Rodriguez } 308*db86f07eSLuis R. Rodriguez if (ah->sw_mgmt_crypto && 309*db86f07eSLuis R. Rodriguez (rxs->flag & RX_FLAG_DECRYPTED) && 310*db86f07eSLuis R. Rodriguez ieee80211_is_mgmt(fc)) 311*db86f07eSLuis R. Rodriguez /* Use software decrypt for management frames. */ 312*db86f07eSLuis R. Rodriguez rxs->flag &= ~RX_FLAG_DECRYPTED; 313*db86f07eSLuis R. Rodriguez } 314*db86f07eSLuis R. Rodriguez EXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess); 315*db86f07eSLuis R. Rodriguez 316*db86f07eSLuis R. Rodriguez static int __init ath9k_cmn_init(void) 317*db86f07eSLuis R. Rodriguez { 318*db86f07eSLuis R. Rodriguez return 0; 319*db86f07eSLuis R. Rodriguez } 320*db86f07eSLuis R. Rodriguez module_init(ath9k_cmn_init); 321*db86f07eSLuis R. Rodriguez 322*db86f07eSLuis R. Rodriguez static void __exit ath9k_cmn_exit(void) 323*db86f07eSLuis R. Rodriguez { 324*db86f07eSLuis R. Rodriguez return; 325*db86f07eSLuis R. Rodriguez } 326*db86f07eSLuis R. Rodriguez module_exit(ath9k_cmn_exit); 327