xref: /linux/drivers/net/wireless/ath/ath9k/common.c (revision fb9987d0f748c983bb795a86f47522313f701a08)
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