18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright (c) 2009-2011 Atheros Communications Inc.
38c2ecf20Sopenharmony_ci *
48c2ecf20Sopenharmony_ci * Permission to use, copy, modify, and/or distribute this software for any
58c2ecf20Sopenharmony_ci * purpose with or without fee is hereby granted, provided that the above
68c2ecf20Sopenharmony_ci * copyright notice and this permission notice appear in all copies.
78c2ecf20Sopenharmony_ci *
88c2ecf20Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
98c2ecf20Sopenharmony_ci * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
108c2ecf20Sopenharmony_ci * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
118c2ecf20Sopenharmony_ci * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
128c2ecf20Sopenharmony_ci * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
138c2ecf20Sopenharmony_ci * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
148c2ecf20Sopenharmony_ci * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
158c2ecf20Sopenharmony_ci */
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci/*
188c2ecf20Sopenharmony_ci * Module for common driver code between ath9k and ath9k_htc
198c2ecf20Sopenharmony_ci */
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ci#include <linux/kernel.h>
228c2ecf20Sopenharmony_ci#include <linux/module.h>
238c2ecf20Sopenharmony_ci
248c2ecf20Sopenharmony_ci#include "common.h"
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ciMODULE_AUTHOR("Atheros Communications");
278c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards.");
288c2ecf20Sopenharmony_ciMODULE_LICENSE("Dual BSD/GPL");
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci/* Assumes you've already done the endian to CPU conversion */
318c2ecf20Sopenharmony_cibool ath9k_cmn_rx_accept(struct ath_common *common,
328c2ecf20Sopenharmony_ci			 struct ieee80211_hdr *hdr,
338c2ecf20Sopenharmony_ci			 struct ieee80211_rx_status *rxs,
348c2ecf20Sopenharmony_ci			 struct ath_rx_status *rx_stats,
358c2ecf20Sopenharmony_ci			 bool *decrypt_error,
368c2ecf20Sopenharmony_ci			 unsigned int rxfilter)
378c2ecf20Sopenharmony_ci{
388c2ecf20Sopenharmony_ci	struct ath_hw *ah = common->ah;
398c2ecf20Sopenharmony_ci	bool is_mc, is_valid_tkip, strip_mic, mic_error;
408c2ecf20Sopenharmony_ci	__le16 fc;
418c2ecf20Sopenharmony_ci
428c2ecf20Sopenharmony_ci	fc = hdr->frame_control;
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci	is_mc = !!is_multicast_ether_addr(hdr->addr1);
458c2ecf20Sopenharmony_ci	is_valid_tkip = rx_stats->rs_keyix != ATH9K_RXKEYIX_INVALID &&
468c2ecf20Sopenharmony_ci		test_bit(rx_stats->rs_keyix, common->tkip_keymap);
478c2ecf20Sopenharmony_ci	strip_mic = is_valid_tkip && ieee80211_is_data(fc) &&
488c2ecf20Sopenharmony_ci		ieee80211_has_protected(fc) &&
498c2ecf20Sopenharmony_ci		!(rx_stats->rs_status &
508c2ecf20Sopenharmony_ci		(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_CRC | ATH9K_RXERR_MIC |
518c2ecf20Sopenharmony_ci		 ATH9K_RXERR_KEYMISS));
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	/*
548c2ecf20Sopenharmony_ci	 * Key miss events are only relevant for pairwise keys where the
558c2ecf20Sopenharmony_ci	 * descriptor does contain a valid key index. This has been observed
568c2ecf20Sopenharmony_ci	 * mostly with CCMP encryption.
578c2ecf20Sopenharmony_ci	 */
588c2ecf20Sopenharmony_ci	if (rx_stats->rs_keyix == ATH9K_RXKEYIX_INVALID ||
598c2ecf20Sopenharmony_ci	    !test_bit(rx_stats->rs_keyix, common->ccmp_keymap))
608c2ecf20Sopenharmony_ci		rx_stats->rs_status &= ~ATH9K_RXERR_KEYMISS;
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_ci	mic_error = is_valid_tkip && !ieee80211_is_ctl(fc) &&
638c2ecf20Sopenharmony_ci		!ieee80211_has_morefrags(fc) &&
648c2ecf20Sopenharmony_ci		!(le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_FRAG) &&
658c2ecf20Sopenharmony_ci		(rx_stats->rs_status & ATH9K_RXERR_MIC);
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci	/*
688c2ecf20Sopenharmony_ci	 * The rx_stats->rs_status will not be set until the end of the
698c2ecf20Sopenharmony_ci	 * chained descriptors so it can be ignored if rs_more is set. The
708c2ecf20Sopenharmony_ci	 * rs_more will be false at the last element of the chained
718c2ecf20Sopenharmony_ci	 * descriptors.
728c2ecf20Sopenharmony_ci	 */
738c2ecf20Sopenharmony_ci	if (rx_stats->rs_status != 0) {
748c2ecf20Sopenharmony_ci		u8 status_mask;
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci		if (rx_stats->rs_status & ATH9K_RXERR_CRC) {
778c2ecf20Sopenharmony_ci			rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
788c2ecf20Sopenharmony_ci			mic_error = false;
798c2ecf20Sopenharmony_ci		}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci		if ((rx_stats->rs_status & ATH9K_RXERR_DECRYPT) ||
828c2ecf20Sopenharmony_ci		    (!is_mc && (rx_stats->rs_status & ATH9K_RXERR_KEYMISS))) {
838c2ecf20Sopenharmony_ci			*decrypt_error = true;
848c2ecf20Sopenharmony_ci			mic_error = false;
858c2ecf20Sopenharmony_ci		}
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci
888c2ecf20Sopenharmony_ci		/*
898c2ecf20Sopenharmony_ci		 * Reject error frames with the exception of
908c2ecf20Sopenharmony_ci		 * decryption and MIC failures. For monitor mode,
918c2ecf20Sopenharmony_ci		 * we also ignore the CRC error.
928c2ecf20Sopenharmony_ci		 */
938c2ecf20Sopenharmony_ci		status_mask = ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
948c2ecf20Sopenharmony_ci			      ATH9K_RXERR_KEYMISS;
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_ci		if (ah->is_monitoring && (rxfilter & FIF_FCSFAIL))
978c2ecf20Sopenharmony_ci			status_mask |= ATH9K_RXERR_CRC;
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci		if (rx_stats->rs_status & ~status_mask)
1008c2ecf20Sopenharmony_ci			return false;
1018c2ecf20Sopenharmony_ci	}
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ci	/*
1048c2ecf20Sopenharmony_ci	 * For unicast frames the MIC error bit can have false positives,
1058c2ecf20Sopenharmony_ci	 * so all MIC error reports need to be validated in software.
1068c2ecf20Sopenharmony_ci	 * False negatives are not common, so skip software verification
1078c2ecf20Sopenharmony_ci	 * if the hardware considers the MIC valid.
1088c2ecf20Sopenharmony_ci	 */
1098c2ecf20Sopenharmony_ci	if (strip_mic)
1108c2ecf20Sopenharmony_ci		rxs->flag |= RX_FLAG_MMIC_STRIPPED;
1118c2ecf20Sopenharmony_ci	else if (is_mc && mic_error)
1128c2ecf20Sopenharmony_ci		rxs->flag |= RX_FLAG_MMIC_ERROR;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	return true;
1158c2ecf20Sopenharmony_ci}
1168c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_rx_accept);
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_civoid ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
1198c2ecf20Sopenharmony_ci				  struct sk_buff *skb,
1208c2ecf20Sopenharmony_ci				  struct ath_rx_status *rx_stats,
1218c2ecf20Sopenharmony_ci				  struct ieee80211_rx_status *rxs,
1228c2ecf20Sopenharmony_ci				  bool decrypt_error)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	struct ath_hw *ah = common->ah;
1258c2ecf20Sopenharmony_ci	struct ieee80211_hdr *hdr;
1268c2ecf20Sopenharmony_ci	int hdrlen, padpos, padsize;
1278c2ecf20Sopenharmony_ci	u8 keyix;
1288c2ecf20Sopenharmony_ci	__le16 fc;
1298c2ecf20Sopenharmony_ci
1308c2ecf20Sopenharmony_ci	/* see if any padding is done by the hw and remove it */
1318c2ecf20Sopenharmony_ci	hdr = (struct ieee80211_hdr *) skb->data;
1328c2ecf20Sopenharmony_ci	hdrlen = ieee80211_get_hdrlen_from_skb(skb);
1338c2ecf20Sopenharmony_ci	fc = hdr->frame_control;
1348c2ecf20Sopenharmony_ci	padpos = ieee80211_hdrlen(fc);
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_ci	/* The MAC header is padded to have 32-bit boundary if the
1378c2ecf20Sopenharmony_ci	 * packet payload is non-zero. The general calculation for
1388c2ecf20Sopenharmony_ci	 * padsize would take into account odd header lengths:
1398c2ecf20Sopenharmony_ci	 * padsize = (4 - padpos % 4) % 4; However, since only
1408c2ecf20Sopenharmony_ci	 * even-length headers are used, padding can only be 0 or 2
1418c2ecf20Sopenharmony_ci	 * bytes and we can optimize this a bit. In addition, we must
1428c2ecf20Sopenharmony_ci	 * not try to remove padding from short control frames that do
1438c2ecf20Sopenharmony_ci	 * not have payload. */
1448c2ecf20Sopenharmony_ci	padsize = padpos & 3;
1458c2ecf20Sopenharmony_ci	if (padsize && skb->len>=padpos+padsize+FCS_LEN) {
1468c2ecf20Sopenharmony_ci		memmove(skb->data + padsize, skb->data, padpos);
1478c2ecf20Sopenharmony_ci		skb_pull(skb, padsize);
1488c2ecf20Sopenharmony_ci	}
1498c2ecf20Sopenharmony_ci
1508c2ecf20Sopenharmony_ci	keyix = rx_stats->rs_keyix;
1518c2ecf20Sopenharmony_ci
1528c2ecf20Sopenharmony_ci	if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error &&
1538c2ecf20Sopenharmony_ci	    ieee80211_has_protected(fc)) {
1548c2ecf20Sopenharmony_ci		rxs->flag |= RX_FLAG_DECRYPTED;
1558c2ecf20Sopenharmony_ci	} else if (ieee80211_has_protected(fc)
1568c2ecf20Sopenharmony_ci		   && !decrypt_error && skb->len >= hdrlen + 4) {
1578c2ecf20Sopenharmony_ci		keyix = skb->data[hdrlen + 3] >> 6;
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci		if (test_bit(keyix, common->keymap))
1608c2ecf20Sopenharmony_ci			rxs->flag |= RX_FLAG_DECRYPTED;
1618c2ecf20Sopenharmony_ci	}
1628c2ecf20Sopenharmony_ci	if (ah->sw_mgmt_crypto_rx &&
1638c2ecf20Sopenharmony_ci	    (rxs->flag & RX_FLAG_DECRYPTED) &&
1648c2ecf20Sopenharmony_ci	    ieee80211_is_mgmt(fc))
1658c2ecf20Sopenharmony_ci		/* Use software decrypt for management frames. */
1668c2ecf20Sopenharmony_ci		rxs->flag &= ~RX_FLAG_DECRYPTED;
1678c2ecf20Sopenharmony_ci}
1688c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess);
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ciint ath9k_cmn_process_rate(struct ath_common *common,
1718c2ecf20Sopenharmony_ci			   struct ieee80211_hw *hw,
1728c2ecf20Sopenharmony_ci			   struct ath_rx_status *rx_stats,
1738c2ecf20Sopenharmony_ci			   struct ieee80211_rx_status *rxs)
1748c2ecf20Sopenharmony_ci{
1758c2ecf20Sopenharmony_ci	struct ieee80211_supported_band *sband;
1768c2ecf20Sopenharmony_ci	enum nl80211_band band;
1778c2ecf20Sopenharmony_ci	unsigned int i = 0;
1788c2ecf20Sopenharmony_ci	struct ath_hw *ah = common->ah;
1798c2ecf20Sopenharmony_ci
1808c2ecf20Sopenharmony_ci	band = ah->curchan->chan->band;
1818c2ecf20Sopenharmony_ci	sband = hw->wiphy->bands[band];
1828c2ecf20Sopenharmony_ci
1838c2ecf20Sopenharmony_ci	if (IS_CHAN_QUARTER_RATE(ah->curchan))
1848c2ecf20Sopenharmony_ci		rxs->bw = RATE_INFO_BW_5;
1858c2ecf20Sopenharmony_ci	else if (IS_CHAN_HALF_RATE(ah->curchan))
1868c2ecf20Sopenharmony_ci		rxs->bw = RATE_INFO_BW_10;
1878c2ecf20Sopenharmony_ci
1888c2ecf20Sopenharmony_ci	if (rx_stats->rs_rate & 0x80) {
1898c2ecf20Sopenharmony_ci		/* HT rate */
1908c2ecf20Sopenharmony_ci		rxs->encoding = RX_ENC_HT;
1918c2ecf20Sopenharmony_ci		rxs->enc_flags |= rx_stats->enc_flags;
1928c2ecf20Sopenharmony_ci		rxs->bw = rx_stats->bw;
1938c2ecf20Sopenharmony_ci		rxs->rate_idx = rx_stats->rs_rate & 0x7f;
1948c2ecf20Sopenharmony_ci		return 0;
1958c2ecf20Sopenharmony_ci	}
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	for (i = 0; i < sband->n_bitrates; i++) {
1988c2ecf20Sopenharmony_ci		if (sband->bitrates[i].hw_value == rx_stats->rs_rate) {
1998c2ecf20Sopenharmony_ci			rxs->rate_idx = i;
2008c2ecf20Sopenharmony_ci			return 0;
2018c2ecf20Sopenharmony_ci		}
2028c2ecf20Sopenharmony_ci		if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) {
2038c2ecf20Sopenharmony_ci			rxs->enc_flags |= RX_ENC_FLAG_SHORTPRE;
2048c2ecf20Sopenharmony_ci			rxs->rate_idx = i;
2058c2ecf20Sopenharmony_ci			return 0;
2068c2ecf20Sopenharmony_ci		}
2078c2ecf20Sopenharmony_ci	}
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_ci	return -EINVAL;
2108c2ecf20Sopenharmony_ci}
2118c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_process_rate);
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_civoid ath9k_cmn_process_rssi(struct ath_common *common,
2148c2ecf20Sopenharmony_ci			    struct ieee80211_hw *hw,
2158c2ecf20Sopenharmony_ci			    struct ath_rx_status *rx_stats,
2168c2ecf20Sopenharmony_ci			    struct ieee80211_rx_status *rxs)
2178c2ecf20Sopenharmony_ci{
2188c2ecf20Sopenharmony_ci	struct ath_hw *ah = common->ah;
2198c2ecf20Sopenharmony_ci	int last_rssi;
2208c2ecf20Sopenharmony_ci	int rssi = rx_stats->rs_rssi;
2218c2ecf20Sopenharmony_ci	int i, j;
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	/*
2248c2ecf20Sopenharmony_ci	 * RSSI is not available for subframes in an A-MPDU.
2258c2ecf20Sopenharmony_ci	 */
2268c2ecf20Sopenharmony_ci	if (rx_stats->rs_moreaggr) {
2278c2ecf20Sopenharmony_ci		rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
2288c2ecf20Sopenharmony_ci		return;
2298c2ecf20Sopenharmony_ci	}
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	/*
2328c2ecf20Sopenharmony_ci	 * Check if the RSSI for the last subframe in an A-MPDU
2338c2ecf20Sopenharmony_ci	 * or an unaggregated frame is valid.
2348c2ecf20Sopenharmony_ci	 */
2358c2ecf20Sopenharmony_ci	if (rx_stats->rs_rssi == ATH9K_RSSI_BAD) {
2368c2ecf20Sopenharmony_ci		rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
2378c2ecf20Sopenharmony_ci		return;
2388c2ecf20Sopenharmony_ci	}
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci	for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) {
2418c2ecf20Sopenharmony_ci		s8 rssi;
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci		if (!(ah->rxchainmask & BIT(i)))
2448c2ecf20Sopenharmony_ci			continue;
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_ci		rssi = rx_stats->rs_rssi_ctl[i];
2478c2ecf20Sopenharmony_ci		if (rssi != ATH9K_RSSI_BAD) {
2488c2ecf20Sopenharmony_ci		    rxs->chains |= BIT(j);
2498c2ecf20Sopenharmony_ci		    rxs->chain_signal[j] = ah->noise + rssi;
2508c2ecf20Sopenharmony_ci		}
2518c2ecf20Sopenharmony_ci		j++;
2528c2ecf20Sopenharmony_ci	}
2538c2ecf20Sopenharmony_ci
2548c2ecf20Sopenharmony_ci	/*
2558c2ecf20Sopenharmony_ci	 * Update Beacon RSSI, this is used by ANI.
2568c2ecf20Sopenharmony_ci	 */
2578c2ecf20Sopenharmony_ci	if (rx_stats->is_mybeacon &&
2588c2ecf20Sopenharmony_ci	    ((ah->opmode == NL80211_IFTYPE_STATION) ||
2598c2ecf20Sopenharmony_ci	     (ah->opmode == NL80211_IFTYPE_ADHOC))) {
2608c2ecf20Sopenharmony_ci		ATH_RSSI_LPF(common->last_rssi, rx_stats->rs_rssi);
2618c2ecf20Sopenharmony_ci		last_rssi = common->last_rssi;
2628c2ecf20Sopenharmony_ci
2638c2ecf20Sopenharmony_ci		if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
2648c2ecf20Sopenharmony_ci			rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
2658c2ecf20Sopenharmony_ci		if (rssi < 0)
2668c2ecf20Sopenharmony_ci			rssi = 0;
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_ci		ah->stats.avgbrssi = rssi;
2698c2ecf20Sopenharmony_ci	}
2708c2ecf20Sopenharmony_ci
2718c2ecf20Sopenharmony_ci	rxs->signal = ah->noise + rx_stats->rs_rssi;
2728c2ecf20Sopenharmony_ci}
2738c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_process_rssi);
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_ciint ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb)
2768c2ecf20Sopenharmony_ci{
2778c2ecf20Sopenharmony_ci	struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
2788c2ecf20Sopenharmony_ci
2798c2ecf20Sopenharmony_ci	if (tx_info->control.hw_key) {
2808c2ecf20Sopenharmony_ci		switch (tx_info->control.hw_key->cipher) {
2818c2ecf20Sopenharmony_ci		case WLAN_CIPHER_SUITE_WEP40:
2828c2ecf20Sopenharmony_ci		case WLAN_CIPHER_SUITE_WEP104:
2838c2ecf20Sopenharmony_ci			return ATH9K_KEY_TYPE_WEP;
2848c2ecf20Sopenharmony_ci		case WLAN_CIPHER_SUITE_TKIP:
2858c2ecf20Sopenharmony_ci			return ATH9K_KEY_TYPE_TKIP;
2868c2ecf20Sopenharmony_ci		case WLAN_CIPHER_SUITE_CCMP:
2878c2ecf20Sopenharmony_ci			return ATH9K_KEY_TYPE_AES;
2888c2ecf20Sopenharmony_ci		default:
2898c2ecf20Sopenharmony_ci			break;
2908c2ecf20Sopenharmony_ci		}
2918c2ecf20Sopenharmony_ci	}
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	return ATH9K_KEY_TYPE_CLEAR;
2948c2ecf20Sopenharmony_ci}
2958c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype);
2968c2ecf20Sopenharmony_ci
2978c2ecf20Sopenharmony_ci/*
2988c2ecf20Sopenharmony_ci * Update internal channel flags.
2998c2ecf20Sopenharmony_ci */
3008c2ecf20Sopenharmony_cistatic void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
3018c2ecf20Sopenharmony_ci				      struct cfg80211_chan_def *chandef)
3028c2ecf20Sopenharmony_ci{
3038c2ecf20Sopenharmony_ci	struct ieee80211_channel *chan = chandef->chan;
3048c2ecf20Sopenharmony_ci	u16 flags = 0;
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	ichan->channel = chan->center_freq;
3078c2ecf20Sopenharmony_ci	ichan->chan = chan;
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	if (chan->band == NL80211_BAND_5GHZ)
3108c2ecf20Sopenharmony_ci		flags |= CHANNEL_5GHZ;
3118c2ecf20Sopenharmony_ci
3128c2ecf20Sopenharmony_ci	switch (chandef->width) {
3138c2ecf20Sopenharmony_ci	case NL80211_CHAN_WIDTH_5:
3148c2ecf20Sopenharmony_ci		flags |= CHANNEL_QUARTER;
3158c2ecf20Sopenharmony_ci		break;
3168c2ecf20Sopenharmony_ci	case NL80211_CHAN_WIDTH_10:
3178c2ecf20Sopenharmony_ci		flags |= CHANNEL_HALF;
3188c2ecf20Sopenharmony_ci		break;
3198c2ecf20Sopenharmony_ci	case NL80211_CHAN_WIDTH_20_NOHT:
3208c2ecf20Sopenharmony_ci		break;
3218c2ecf20Sopenharmony_ci	case NL80211_CHAN_WIDTH_20:
3228c2ecf20Sopenharmony_ci		flags |= CHANNEL_HT;
3238c2ecf20Sopenharmony_ci		break;
3248c2ecf20Sopenharmony_ci	case NL80211_CHAN_WIDTH_40:
3258c2ecf20Sopenharmony_ci		if (chandef->center_freq1 > chandef->chan->center_freq)
3268c2ecf20Sopenharmony_ci			flags |= CHANNEL_HT40PLUS | CHANNEL_HT;
3278c2ecf20Sopenharmony_ci		else
3288c2ecf20Sopenharmony_ci			flags |= CHANNEL_HT40MINUS | CHANNEL_HT;
3298c2ecf20Sopenharmony_ci		break;
3308c2ecf20Sopenharmony_ci	default:
3318c2ecf20Sopenharmony_ci		WARN_ON(1);
3328c2ecf20Sopenharmony_ci	}
3338c2ecf20Sopenharmony_ci
3348c2ecf20Sopenharmony_ci	ichan->channelFlags = flags;
3358c2ecf20Sopenharmony_ci}
3368c2ecf20Sopenharmony_ci
3378c2ecf20Sopenharmony_ci/*
3388c2ecf20Sopenharmony_ci * Get the internal channel reference.
3398c2ecf20Sopenharmony_ci */
3408c2ecf20Sopenharmony_cistruct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw,
3418c2ecf20Sopenharmony_ci					    struct ath_hw *ah,
3428c2ecf20Sopenharmony_ci					    struct cfg80211_chan_def *chandef)
3438c2ecf20Sopenharmony_ci{
3448c2ecf20Sopenharmony_ci	struct ieee80211_channel *curchan = chandef->chan;
3458c2ecf20Sopenharmony_ci	struct ath9k_channel *channel;
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	channel = &ah->channels[curchan->hw_value];
3488c2ecf20Sopenharmony_ci	ath9k_cmn_update_ichannel(channel, chandef);
3498c2ecf20Sopenharmony_ci
3508c2ecf20Sopenharmony_ci	return channel;
3518c2ecf20Sopenharmony_ci}
3528c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_get_channel);
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ciint ath9k_cmn_count_streams(unsigned int chainmask, int max)
3558c2ecf20Sopenharmony_ci{
3568c2ecf20Sopenharmony_ci	int streams = 0;
3578c2ecf20Sopenharmony_ci
3588c2ecf20Sopenharmony_ci	do {
3598c2ecf20Sopenharmony_ci		if (++streams == max)
3608c2ecf20Sopenharmony_ci			break;
3618c2ecf20Sopenharmony_ci	} while ((chainmask = chainmask & (chainmask - 1)));
3628c2ecf20Sopenharmony_ci
3638c2ecf20Sopenharmony_ci	return streams;
3648c2ecf20Sopenharmony_ci}
3658c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_count_streams);
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_civoid ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
3688c2ecf20Sopenharmony_ci			    u16 new_txpow, u16 *txpower)
3698c2ecf20Sopenharmony_ci{
3708c2ecf20Sopenharmony_ci	struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_ci	if (ah->curchan && reg->power_limit != new_txpow)
3738c2ecf20Sopenharmony_ci		ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
3748c2ecf20Sopenharmony_ci
3758c2ecf20Sopenharmony_ci	/* read back in case value is clamped */
3768c2ecf20Sopenharmony_ci	*txpower = reg->max_power_level;
3778c2ecf20Sopenharmony_ci}
3788c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_update_txpow);
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_civoid ath9k_cmn_init_crypto(struct ath_hw *ah)
3818c2ecf20Sopenharmony_ci{
3828c2ecf20Sopenharmony_ci	struct ath_common *common = ath9k_hw_common(ah);
3838c2ecf20Sopenharmony_ci	int i = 0;
3848c2ecf20Sopenharmony_ci
3858c2ecf20Sopenharmony_ci	/* Get the hardware key cache size. */
3868c2ecf20Sopenharmony_ci	common->keymax = AR_KEYTABLE_SIZE;
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci	/*
3898c2ecf20Sopenharmony_ci	 * Check whether the separate key cache entries
3908c2ecf20Sopenharmony_ci	 * are required to handle both tx+rx MIC keys.
3918c2ecf20Sopenharmony_ci	 * With split mic keys the number of stations is limited
3928c2ecf20Sopenharmony_ci	 * to 27 otherwise 59.
3938c2ecf20Sopenharmony_ci	 */
3948c2ecf20Sopenharmony_ci	if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
3958c2ecf20Sopenharmony_ci		common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_ci	/*
3988c2ecf20Sopenharmony_ci	 * Reset the key cache since some parts do not
3998c2ecf20Sopenharmony_ci	 * reset the contents on initial power up.
4008c2ecf20Sopenharmony_ci	 */
4018c2ecf20Sopenharmony_ci	for (i = 0; i < common->keymax; i++)
4028c2ecf20Sopenharmony_ci		ath_hw_keyreset(common, (u16) i);
4038c2ecf20Sopenharmony_ci}
4048c2ecf20Sopenharmony_ciEXPORT_SYMBOL(ath9k_cmn_init_crypto);
4058c2ecf20Sopenharmony_ci
4068c2ecf20Sopenharmony_cistatic int __init ath9k_cmn_init(void)
4078c2ecf20Sopenharmony_ci{
4088c2ecf20Sopenharmony_ci	return 0;
4098c2ecf20Sopenharmony_ci}
4108c2ecf20Sopenharmony_cimodule_init(ath9k_cmn_init);
4118c2ecf20Sopenharmony_ci
4128c2ecf20Sopenharmony_cistatic void __exit ath9k_cmn_exit(void)
4138c2ecf20Sopenharmony_ci{
4148c2ecf20Sopenharmony_ci	return;
4158c2ecf20Sopenharmony_ci}
4168c2ecf20Sopenharmony_cimodule_exit(ath9k_cmn_exit);
417