xref: /linux/drivers/net/wireless/ath/ath9k/common.c (revision 5a078fcbdedf88cc3a76ed1b3b4a55a5c61a2e7f)
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 
306438696eSOleksij Rempel /* Assumes you've already done the endian to CPU conversion */
316438696eSOleksij Rempel bool ath9k_cmn_rx_accept(struct ath_common *common,
326438696eSOleksij Rempel 			 struct ieee80211_hdr *hdr,
336438696eSOleksij Rempel 			 struct ieee80211_rx_status *rxs,
346438696eSOleksij Rempel 			 struct ath_rx_status *rx_stats,
356438696eSOleksij Rempel 			 bool *decrypt_error,
366438696eSOleksij Rempel 			 unsigned int rxfilter)
376438696eSOleksij Rempel {
386438696eSOleksij Rempel 	struct ath_hw *ah = common->ah;
396438696eSOleksij Rempel 	bool is_mc, is_valid_tkip, strip_mic, mic_error;
406438696eSOleksij Rempel 	__le16 fc;
416438696eSOleksij Rempel 
426438696eSOleksij Rempel 	fc = hdr->frame_control;
436438696eSOleksij Rempel 
446438696eSOleksij Rempel 	is_mc = !!is_multicast_ether_addr(hdr->addr1);
456438696eSOleksij Rempel 	is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&
466438696eSOleksij Rempel 		test_bit(rx_stats->rs_keyix, common->tkip_keymap);
476438696eSOleksij Rempel 	strip_mic = is_valid_tkip && ieee80211_is_data(fc) &&
486438696eSOleksij Rempel 		ieee80211_has_protected(fc) &&
496438696eSOleksij Rempel 		!(rx_stats->rs_status &
506438696eSOleksij Rempel 		(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |
516438696eSOleksij Rempel 		 ATH9K_RXERR_KEYMISS));
526438696eSOleksij Rempel 
536438696eSOleksij Rempel 	/*
546438696eSOleksij Rempel 	 * Key miss events are only relevant for pairwise keys where the
556438696eSOleksij Rempel 	 * descriptor does contain a valid key index. This has been observed
566438696eSOleksij Rempel 	 * mostly with CCMP encryption.
576438696eSOleksij Rempel 	 */
586438696eSOleksij Rempel 	if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID ||
596438696eSOleksij Rempel 	    !test_bit(rx_stats->rs_keyix, common->ccmp_keymap))
606438696eSOleksij Rempel 		rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;
616438696eSOleksij Rempel 
626438696eSOleksij Rempel 	mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) &&
636438696eSOleksij Rempel 		!ieee80211_has_morefrags(fc) &&
646438696eSOleksij Rempel 		!(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
656438696eSOleksij Rempel 		(rx_stats->rs_status & ATH9K_RXERR_MIC);
666438696eSOleksij Rempel 
676438696eSOleksij Rempel 	/*
686438696eSOleksij Rempel 	 * The rx_stats->rs_status will not be set until the end of the
696438696eSOleksij Rempel 	 * chained descriptors so it can be ignored if rs_more is set. The
706438696eSOleksij Rempel 	 * rs_more will be false at the last element of the chained
716438696eSOleksij Rempel 	 * descriptors.
726438696eSOleksij Rempel 	 */
736438696eSOleksij Rempel 	if (rx_stats->rs_status != 0) {
746438696eSOleksij Rempel 		u8 status_mask;
756438696eSOleksij Rempel 
766438696eSOleksij Rempel 		if (rx_stats->rs_status & ATH9K_RXERR_CRC) {
776438696eSOleksij Rempel 			rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
786438696eSOleksij Rempel 			mic_error = false;
796438696eSOleksij Rempel 		}
806438696eSOleksij Rempel 
816438696eSOleksij Rempel 		if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) ||
826438696eSOleksij Rempel 		    (!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) {
836438696eSOleksij Rempel 			*decrypt_error = true;
846438696eSOleksij Rempel 			mic_error = false;
856438696eSOleksij Rempel 		}
866438696eSOleksij Rempel 
876438696eSOleksij Rempel 
886438696eSOleksij Rempel 		/*
896438696eSOleksij Rempel 		 * Reject error frames with the exception of
906438696eSOleksij Rempel 		 * decryption and MIC failures. For monitor mode,
916438696eSOleksij Rempel 		 * we also ignore the CRC error.
926438696eSOleksij Rempel 		 */
936438696eSOleksij Rempel 		status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
946438696eSOleksij Rempel 			      ATH9K_RXERR_KEYMISS;
956438696eSOleksij Rempel 
966438696eSOleksij Rempel 		if (ah->is_monitoring && (rxfilter & FIF_FCSFAIL))
976438696eSOleksij Rempel 			status_mask |= ATH9K_RXERR_CRC;
986438696eSOleksij Rempel 
996438696eSOleksij Rempel 		if (rx_stats->rs_status & ~status_mask)
1006438696eSOleksij Rempel 			return false;
1016438696eSOleksij Rempel 	}
1026438696eSOleksij Rempel 
1036438696eSOleksij Rempel 	/*
1046438696eSOleksij Rempel 	 * For unicast frames the MIC error bit can have false positives,
1056438696eSOleksij Rempel 	 * so all MIC error reports need to be validated in software.
1066438696eSOleksij Rempel 	 * False negatives are not common, so skip software verification
1076438696eSOleksij Rempel 	 * if the hardware considers the MIC valid.
1086438696eSOleksij Rempel 	 */
1096438696eSOleksij Rempel 	if (strip_mic)
1106438696eSOleksij Rempel 		rxs->flag |= RX_FLAG_MMIC_STRIPPED;
1116438696eSOleksij Rempel 	else if (is_mc && mic_error)
1126438696eSOleksij Rempel 		rxs->flag |= RX_FLAG_MMIC_ERROR;
1136438696eSOleksij Rempel 
1146438696eSOleksij Rempel 	return true;
1156438696eSOleksij Rempel }
1166438696eSOleksij Rempel EXPORT_SYMBOL(ath9k_cmn_rx_accept);
1176438696eSOleksij Rempel 
118*5a078fcbSOleksij Rempel void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
119*5a078fcbSOleksij Rempel 				  struct sk_buff *skb,
120*5a078fcbSOleksij Rempel 				  struct ath_rx_status *rx_stats,
121*5a078fcbSOleksij Rempel 				  struct ieee80211_rx_status *rxs,
122*5a078fcbSOleksij Rempel 				  bool decrypt_error)
123*5a078fcbSOleksij Rempel {
124*5a078fcbSOleksij Rempel 	struct ath_hw *ah = common->ah;
125*5a078fcbSOleksij Rempel 	struct ieee80211_hdr *hdr;
126*5a078fcbSOleksij Rempel 	int hdrlen, padpos, padsize;
127*5a078fcbSOleksij Rempel 	u8 keyix;
128*5a078fcbSOleksij Rempel 	__le16 fc;
129*5a078fcbSOleksij Rempel 
130*5a078fcbSOleksij Rempel 	/* see if any padding is done by the hw and remove it */
131*5a078fcbSOleksij Rempel 	hdr = (struct ieee80211_hdr *) skb->data;
132*5a078fcbSOleksij Rempel 	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
133*5a078fcbSOleksij Rempel 	fc = hdr->frame_control;
134*5a078fcbSOleksij Rempel 	padpos = ieee80211_hdrlen(fc);
135*5a078fcbSOleksij Rempel 
136*5a078fcbSOleksij Rempel 	/* The MAC header is padded to have 32-bit boundary if the
137*5a078fcbSOleksij Rempel 	 * packet payload is non-zero. The general calculation for
138*5a078fcbSOleksij Rempel 	 * padsize would take into account odd header lengths:
139*5a078fcbSOleksij Rempel 	 * padsize = (4 - padpos % 4) % 4; However, since only
140*5a078fcbSOleksij Rempel 	 * even-length headers are used, padding can only be 0 or 2
141*5a078fcbSOleksij Rempel 	 * bytes and we can optimize this a bit. In addition, we must
142*5a078fcbSOleksij Rempel 	 * not try to remove padding from short control frames that do
143*5a078fcbSOleksij Rempel 	 * not have payload. */
144*5a078fcbSOleksij Rempel 	padsize = padpos & 3;
145*5a078fcbSOleksij Rempel 	if (padsize && skb->len>=padpos+padsize+FCS_LEN) {
146*5a078fcbSOleksij Rempel 		memmove(skb->data + padsize, skb->data, padpos);
147*5a078fcbSOleksij Rempel 		skb_pull(skb, padsize);
148*5a078fcbSOleksij Rempel 	}
149*5a078fcbSOleksij Rempel 
150*5a078fcbSOleksij Rempel 	keyix = rx_stats->rs_keyix;
151*5a078fcbSOleksij Rempel 
152*5a078fcbSOleksij Rempel 	if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error &&
153*5a078fcbSOleksij Rempel 	    ieee80211_has_protected(fc)) {
154*5a078fcbSOleksij Rempel 		rxs->flag |= RX_FLAG_DECRYPTED;
155*5a078fcbSOleksij Rempel 	} else if (ieee80211_has_protected(fc)
156*5a078fcbSOleksij Rempel 		   && !decrypt_error && skb->len >= hdrlen + 4) {
157*5a078fcbSOleksij Rempel 		keyix = skb->data[hdrlen + 3] >> 6;
158*5a078fcbSOleksij Rempel 
159*5a078fcbSOleksij Rempel 		if (test_bit(keyix, common->keymap))
160*5a078fcbSOleksij Rempel 			rxs->flag |= RX_FLAG_DECRYPTED;
161*5a078fcbSOleksij Rempel 	}
162*5a078fcbSOleksij Rempel 	if (ah->sw_mgmt_crypto &&
163*5a078fcbSOleksij Rempel 	    (rxs->flag & RX_FLAG_DECRYPTED) &&
164*5a078fcbSOleksij Rempel 	    ieee80211_is_mgmt(fc))
165*5a078fcbSOleksij Rempel 		/* Use software decrypt for management frames. */
166*5a078fcbSOleksij Rempel 		rxs->flag &= ~RX_FLAG_DECRYPTED;
167*5a078fcbSOleksij Rempel }
168*5a078fcbSOleksij Rempel EXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess);
169*5a078fcbSOleksij Rempel 
17012746036SOleksij Rempel int ath9k_cmn_process_rate(struct ath_common *common,
17112746036SOleksij Rempel 			   struct ieee80211_hw *hw,
17212746036SOleksij Rempel 			   struct ath_rx_status *rx_stats,
17312746036SOleksij Rempel 			   struct ieee80211_rx_status *rxs)
17412746036SOleksij Rempel {
17512746036SOleksij Rempel 	struct ieee80211_supported_band *sband;
17612746036SOleksij Rempel 	enum ieee80211_band band;
17712746036SOleksij Rempel 	unsigned int i = 0;
17812746036SOleksij Rempel 	struct ath_hw *ah = common->ah;
17912746036SOleksij Rempel 
18012746036SOleksij Rempel 	band = ah->curchan->chan->band;
18112746036SOleksij Rempel 	sband = hw->wiphy->bands[band];
18212746036SOleksij Rempel 
18312746036SOleksij Rempel 	if (IS_CHAN_QUARTER_RATE(ah->curchan))
18412746036SOleksij Rempel 		rxs->flag |= RX_FLAG_5MHZ;
18512746036SOleksij Rempel 	else if (IS_CHAN_HALF_RATE(ah->curchan))
18612746036SOleksij Rempel 		rxs->flag |= RX_FLAG_10MHZ;
18712746036SOleksij Rempel 
18812746036SOleksij Rempel 	if (rx_stats->rs_rate & 0x80) {
18912746036SOleksij Rempel 		/* HT rate */
19012746036SOleksij Rempel 		rxs->flag |= RX_FLAG_HT;
19112746036SOleksij Rempel 		rxs->flag |= rx_stats->flag;
19212746036SOleksij Rempel 		rxs->rate_idx = rx_stats->rs_rate & 0x7f;
19312746036SOleksij Rempel 		return 0;
19412746036SOleksij Rempel 	}
19512746036SOleksij Rempel 
19612746036SOleksij Rempel 	for (i = 0; i < sband->n_bitrates; i++) {
19712746036SOleksij Rempel 		if (sband->bitrates[i].hw_value == rx_stats->rs_rate) {
19812746036SOleksij Rempel 			rxs->rate_idx = i;
19912746036SOleksij Rempel 			return 0;
20012746036SOleksij Rempel 		}
20112746036SOleksij Rempel 		if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) {
20212746036SOleksij Rempel 			rxs->flag |= RX_FLAG_SHORTPRE;
20312746036SOleksij Rempel 			rxs->rate_idx = i;
20412746036SOleksij Rempel 			return 0;
20512746036SOleksij Rempel 		}
20612746036SOleksij Rempel 	}
20712746036SOleksij Rempel 
20812746036SOleksij Rempel 	return -EINVAL;
20912746036SOleksij Rempel }
21012746036SOleksij Rempel EXPORT_SYMBOL(ath9k_cmn_process_rate);
21112746036SOleksij Rempel 
21232efb0ccSOleksij Rempel void ath9k_cmn_process_rssi(struct ath_common *common,
21332efb0ccSOleksij Rempel 			    struct ieee80211_hw *hw,
21432efb0ccSOleksij Rempel 			    struct ath_rx_status *rx_stats,
21532efb0ccSOleksij Rempel 			    struct ieee80211_rx_status *rxs)
21632efb0ccSOleksij Rempel {
21732efb0ccSOleksij Rempel 	struct ath_hw *ah = common->ah;
21832efb0ccSOleksij Rempel 	int last_rssi;
21932efb0ccSOleksij Rempel 	int rssi = rx_stats->rs_rssi;
22032efb0ccSOleksij Rempel 	int i, j;
22132efb0ccSOleksij Rempel 
22232efb0ccSOleksij Rempel 	/*
22332efb0ccSOleksij Rempel 	 * RSSI is not available for subframes in an A-MPDU.
22432efb0ccSOleksij Rempel 	 */
22532efb0ccSOleksij Rempel 	if (rx_stats->rs_moreaggr) {
22632efb0ccSOleksij Rempel 		rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
22732efb0ccSOleksij Rempel 		return;
22832efb0ccSOleksij Rempel 	}
22932efb0ccSOleksij Rempel 
23032efb0ccSOleksij Rempel 	/*
23132efb0ccSOleksij Rempel 	 * Check if the RSSI for the last subframe in an A-MPDU
23232efb0ccSOleksij Rempel 	 * or an unaggregated frame is valid.
23332efb0ccSOleksij Rempel 	 */
23432efb0ccSOleksij Rempel 	if (rx_stats->rs_rssi == ATH9K_RSSI_BAD) {
23532efb0ccSOleksij Rempel 		rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
23632efb0ccSOleksij Rempel 		return;
23732efb0ccSOleksij Rempel 	}
23832efb0ccSOleksij Rempel 
23932efb0ccSOleksij Rempel 	for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) {
24032efb0ccSOleksij Rempel 		s8 rssi;
24132efb0ccSOleksij Rempel 
24232efb0ccSOleksij Rempel 		if (!(ah->rxchainmask & BIT(i)))
24332efb0ccSOleksij Rempel 			continue;
24432efb0ccSOleksij Rempel 
24532efb0ccSOleksij Rempel 		rssi = rx_stats->rs_rssi_ctl[i];
24632efb0ccSOleksij Rempel 		if (rssi != ATH9K_RSSI_BAD) {
24732efb0ccSOleksij Rempel 		    rxs->chains |= BIT(j);
24832efb0ccSOleksij Rempel 		    rxs->chain_signal[j] = ah->noise + rssi;
24932efb0ccSOleksij Rempel 		}
25032efb0ccSOleksij Rempel 		j++;
25132efb0ccSOleksij Rempel 	}
25232efb0ccSOleksij Rempel 
25332efb0ccSOleksij Rempel 	/*
25432efb0ccSOleksij Rempel 	 * Update Beacon RSSI, this is used by ANI.
25532efb0ccSOleksij Rempel 	 */
25632efb0ccSOleksij Rempel 	if (rx_stats->is_mybeacon &&
25732efb0ccSOleksij Rempel 	    ((ah->opmode == NL80211_IFTYPE_STATION) ||
25832efb0ccSOleksij Rempel 	     (ah->opmode == NL80211_IFTYPE_ADHOC))) {
25932efb0ccSOleksij Rempel 		ATH_RSSI_LPF(common->last_rssi, rx_stats->rs_rssi);
26032efb0ccSOleksij Rempel 		last_rssi = common->last_rssi;
26132efb0ccSOleksij Rempel 
26232efb0ccSOleksij Rempel 		if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
26332efb0ccSOleksij Rempel 			rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
26432efb0ccSOleksij Rempel 		if (rssi < 0)
26532efb0ccSOleksij Rempel 			rssi = 0;
26632efb0ccSOleksij Rempel 
26732efb0ccSOleksij Rempel 		ah->stats.avgbrssi = rssi;
26832efb0ccSOleksij Rempel 	}
26932efb0ccSOleksij Rempel 
27032efb0ccSOleksij Rempel 	rxs->signal = ah->noise + rx_stats->rs_rssi;
27132efb0ccSOleksij Rempel }
27232efb0ccSOleksij Rempel EXPORT_SYMBOL(ath9k_cmn_process_rssi);
27332efb0ccSOleksij Rempel 
274fb9987d0SSujith int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb)
275fb9987d0SSujith {
276fb9987d0SSujith 	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
277fb9987d0SSujith 
278fb9987d0SSujith 	if (tx_info->control.hw_key) {
27997359d12SJohannes Berg 		switch (tx_info->control.hw_key->cipher) {
28097359d12SJohannes Berg 		case WLAN_CIPHER_SUITE_WEP40:
28197359d12SJohannes Berg 		case WLAN_CIPHER_SUITE_WEP104:
282fb9987d0SSujith 			return ATH9K_KEY_TYPE_WEP;
28397359d12SJohannes Berg 		case WLAN_CIPHER_SUITE_TKIP:
284fb9987d0SSujith 			return ATH9K_KEY_TYPE_TKIP;
28597359d12SJohannes Berg 		case WLAN_CIPHER_SUITE_CCMP:
286fb9987d0SSujith 			return ATH9K_KEY_TYPE_AES;
28797359d12SJohannes Berg 		default:
28897359d12SJohannes Berg 			break;
28997359d12SJohannes Berg 		}
290fb9987d0SSujith 	}
291fb9987d0SSujith 
292fb9987d0SSujith 	return ATH9K_KEY_TYPE_CLEAR;
293fb9987d0SSujith }
294fb9987d0SSujith EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype);
295fb9987d0SSujith 
296fb9987d0SSujith /*
297fb9987d0SSujith  * Update internal channel flags.
298fb9987d0SSujith  */
2992297f1c7SFelix Fietkau static void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
3000671894fSSimon Wunderlich 				      struct cfg80211_chan_def *chandef)
301fb9987d0SSujith {
3026b21fd20SFelix Fietkau 	struct ieee80211_channel *chan = chandef->chan;
3036b21fd20SFelix Fietkau 	u16 flags = 0;
304fb9987d0SSujith 
3056b21fd20SFelix Fietkau 	ichan->channel = chan->center_freq;
3066b21fd20SFelix Fietkau 	ichan->chan = chan;
3076b21fd20SFelix Fietkau 
3086b21fd20SFelix Fietkau 	if (chan->band == IEEE80211_BAND_5GHZ)
3096b21fd20SFelix Fietkau 		flags |= CHANNEL_5GHZ;
310fb9987d0SSujith 
3110671894fSSimon Wunderlich 	switch (chandef->width) {
3120671894fSSimon Wunderlich 	case NL80211_CHAN_WIDTH_5:
3136b21fd20SFelix Fietkau 		flags |= CHANNEL_QUARTER;
3140671894fSSimon Wunderlich 		break;
3150671894fSSimon Wunderlich 	case NL80211_CHAN_WIDTH_10:
3166b21fd20SFelix Fietkau 		flags |= CHANNEL_HALF;
3170671894fSSimon Wunderlich 		break;
3180671894fSSimon Wunderlich 	case NL80211_CHAN_WIDTH_20_NOHT:
3190671894fSSimon Wunderlich 		break;
3200671894fSSimon Wunderlich 	case NL80211_CHAN_WIDTH_20:
3216b21fd20SFelix Fietkau 		flags |= CHANNEL_HT;
3226b21fd20SFelix Fietkau 		break;
3230671894fSSimon Wunderlich 	case NL80211_CHAN_WIDTH_40:
3246b21fd20SFelix Fietkau 		if (chandef->center_freq1 > chandef->chan->center_freq)
3256b21fd20SFelix Fietkau 			flags |= CHANNEL_HT40PLUS | CHANNEL_HT;
3266b21fd20SFelix Fietkau 		else
3276b21fd20SFelix Fietkau 			flags |= CHANNEL_HT40MINUS | CHANNEL_HT;
3280671894fSSimon Wunderlich 		break;
3290671894fSSimon Wunderlich 	default:
3300671894fSSimon Wunderlich 		WARN_ON(1);
3310671894fSSimon Wunderlich 	}
3326b21fd20SFelix Fietkau 
3336b21fd20SFelix Fietkau 	ichan->channelFlags = flags;
334fb9987d0SSujith }
335fb9987d0SSujith 
336fb9987d0SSujith /*
337fb9987d0SSujith  * Get the internal channel reference.
338fb9987d0SSujith  */
3392297f1c7SFelix Fietkau struct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw,
3402297f1c7SFelix Fietkau 					    struct ath_hw *ah,
3412297f1c7SFelix Fietkau 					    struct cfg80211_chan_def *chandef)
342fb9987d0SSujith {
3432297f1c7SFelix Fietkau 	struct ieee80211_channel *curchan = chandef->chan;
344fb9987d0SSujith 	struct ath9k_channel *channel;
345fb9987d0SSujith 
346f40c4608SFelix Fietkau 	channel = &ah->channels[curchan->hw_value];
3472297f1c7SFelix Fietkau 	ath9k_cmn_update_ichannel(channel, chandef);
348fb9987d0SSujith 
349fb9987d0SSujith 	return channel;
350fb9987d0SSujith }
3512297f1c7SFelix Fietkau EXPORT_SYMBOL(ath9k_cmn_get_channel);
352fb9987d0SSujith 
35361389f3eSSujith int ath9k_cmn_count_streams(unsigned int chainmask, int max)
35461389f3eSSujith {
35561389f3eSSujith 	int streams = 0;
35661389f3eSSujith 
35761389f3eSSujith 	do {
35861389f3eSSujith 		if (++streams == max)
35961389f3eSSujith 			break;
36061389f3eSSujith 	} while ((chainmask = chainmask & (chainmask - 1)));
36161389f3eSSujith 
36261389f3eSSujith 	return streams;
36361389f3eSSujith }
36461389f3eSSujith EXPORT_SYMBOL(ath9k_cmn_count_streams);
36561389f3eSSujith 
3665048e8c3SRajkumar Manoharan void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
3675048e8c3SRajkumar Manoharan 			    u16 new_txpow, u16 *txpower)
3685048e8c3SRajkumar Manoharan {
369ca2c68ccSFelix Fietkau 	struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
370ca2c68ccSFelix Fietkau 
371ca2c68ccSFelix Fietkau 	if (reg->power_limit != new_txpow) {
3725048e8c3SRajkumar Manoharan 		ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
3735048e8c3SRajkumar Manoharan 		/* read back in case value is clamped */
374ca2c68ccSFelix Fietkau 		*txpower = reg->max_power_level;
3755048e8c3SRajkumar Manoharan 	}
3765048e8c3SRajkumar Manoharan }
3775048e8c3SRajkumar Manoharan EXPORT_SYMBOL(ath9k_cmn_update_txpow);
3785048e8c3SRajkumar Manoharan 
379f82b4bdeSRajkumar Manoharan void ath9k_cmn_init_crypto(struct ath_hw *ah)
380f82b4bdeSRajkumar Manoharan {
381f82b4bdeSRajkumar Manoharan 	struct ath_common *common = ath9k_hw_common(ah);
382f82b4bdeSRajkumar Manoharan 	int i = 0;
383f82b4bdeSRajkumar Manoharan 
384f82b4bdeSRajkumar Manoharan 	/* Get the hardware key cache size. */
385f82b4bdeSRajkumar Manoharan 	common->keymax = AR_KEYTABLE_SIZE;
386f82b4bdeSRajkumar Manoharan 
387f82b4bdeSRajkumar Manoharan 	/*
388f82b4bdeSRajkumar Manoharan 	 * Check whether the separate key cache entries
389f82b4bdeSRajkumar Manoharan 	 * are required to handle both tx+rx MIC keys.
390f82b4bdeSRajkumar Manoharan 	 * With split mic keys the number of stations is limited
391f82b4bdeSRajkumar Manoharan 	 * to 27 otherwise 59.
392f82b4bdeSRajkumar Manoharan 	 */
393f82b4bdeSRajkumar Manoharan 	if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
394f82b4bdeSRajkumar Manoharan 		common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
395f82b4bdeSRajkumar Manoharan 
396f82b4bdeSRajkumar Manoharan 	/*
397f82b4bdeSRajkumar Manoharan 	 * Reset the key cache since some parts do not
398f82b4bdeSRajkumar Manoharan 	 * reset the contents on initial power up.
399f82b4bdeSRajkumar Manoharan 	 */
400f82b4bdeSRajkumar Manoharan 	for (i = 0; i < common->keymax; i++)
401f82b4bdeSRajkumar Manoharan 		ath_hw_keyreset(common, (u16) i);
402f82b4bdeSRajkumar Manoharan }
403f82b4bdeSRajkumar Manoharan EXPORT_SYMBOL(ath9k_cmn_init_crypto);
404f82b4bdeSRajkumar Manoharan 
405db86f07eSLuis R. Rodriguez static int __init ath9k_cmn_init(void)
406db86f07eSLuis R. Rodriguez {
407db86f07eSLuis R. Rodriguez 	return 0;
408db86f07eSLuis R. Rodriguez }
409db86f07eSLuis R. Rodriguez module_init(ath9k_cmn_init);
410db86f07eSLuis R. Rodriguez 
411db86f07eSLuis R. Rodriguez static void __exit ath9k_cmn_exit(void)
412db86f07eSLuis R. Rodriguez {
413db86f07eSLuis R. Rodriguez 	return;
414db86f07eSLuis R. Rodriguez }
415db86f07eSLuis R. Rodriguez module_exit(ath9k_cmn_exit);
416