blob: 7028c52fe32e1537b48e2f4ed2000fb7b90da4f6 [file] [log] [blame]
Luis R. Rodriguezdb86f072009-11-05 08:44:39 -08001/*
Sujith Manoharan5b681382011-05-17 13:36:18 +05302 * Copyright (c) 2009-2011 Atheros Communications Inc.
Luis R. Rodriguezdb86f072009-11-05 08:44:39 -08003 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17/*
18 * Module for common driver code between ath9k and ath9k_htc
19 */
20
21#include <linux/kernel.h>
22#include <linux/module.h>
23
24#include "common.h"
25
26MODULE_AUTHOR("Atheros Communications");
27MODULE_DESCRIPTION("Shared library for Atheros wireless 802.11n LAN cards.");
28MODULE_LICENSE("Dual BSD/GPL");
29
Oleksij Rempel32efb0c2014-02-04 10:27:39 +010030void ath9k_cmn_process_rssi(struct ath_common *common,
31 struct ieee80211_hw *hw,
32 struct ath_rx_status *rx_stats,
33 struct ieee80211_rx_status *rxs)
34{
35 struct ath_hw *ah = common->ah;
36 int last_rssi;
37 int rssi = rx_stats->rs_rssi;
38 int i, j;
39
40 /*
41 * RSSI is not available for subframes in an A-MPDU.
42 */
43 if (rx_stats->rs_moreaggr) {
44 rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
45 return;
46 }
47
48 /*
49 * Check if the RSSI for the last subframe in an A-MPDU
50 * or an unaggregated frame is valid.
51 */
52 if (rx_stats->rs_rssi == ATH9K_RSSI_BAD) {
53 rxs->flag |= RX_FLAG_NO_SIGNAL_VAL;
54 return;
55 }
56
57 for (i = 0, j = 0; i < ARRAY_SIZE(rx_stats->rs_rssi_ctl); i++) {
58 s8 rssi;
59
60 if (!(ah->rxchainmask & BIT(i)))
61 continue;
62
63 rssi = rx_stats->rs_rssi_ctl[i];
64 if (rssi != ATH9K_RSSI_BAD) {
65 rxs->chains |= BIT(j);
66 rxs->chain_signal[j] = ah->noise + rssi;
67 }
68 j++;
69 }
70
71 /*
72 * Update Beacon RSSI, this is used by ANI.
73 */
74 if (rx_stats->is_mybeacon &&
75 ((ah->opmode == NL80211_IFTYPE_STATION) ||
76 (ah->opmode == NL80211_IFTYPE_ADHOC))) {
77 ATH_RSSI_LPF(common->last_rssi, rx_stats->rs_rssi);
78 last_rssi = common->last_rssi;
79
80 if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
81 rssi = ATH_EP_RND(last_rssi, ATH_RSSI_EP_MULTIPLIER);
82 if (rssi < 0)
83 rssi = 0;
84
85 ah->stats.avgbrssi = rssi;
86 }
87
88 rxs->signal = ah->noise + rx_stats->rs_rssi;
89}
90EXPORT_SYMBOL(ath9k_cmn_process_rssi);
91
Sujithfb9987d2010-03-17 14:25:25 +053092int ath9k_cmn_get_hw_crypto_keytype(struct sk_buff *skb)
93{
94 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
95
96 if (tx_info->control.hw_key) {
Johannes Berg97359d12010-08-10 09:46:38 +020097 switch (tx_info->control.hw_key->cipher) {
98 case WLAN_CIPHER_SUITE_WEP40:
99 case WLAN_CIPHER_SUITE_WEP104:
Sujithfb9987d2010-03-17 14:25:25 +0530100 return ATH9K_KEY_TYPE_WEP;
Johannes Berg97359d12010-08-10 09:46:38 +0200101 case WLAN_CIPHER_SUITE_TKIP:
Sujithfb9987d2010-03-17 14:25:25 +0530102 return ATH9K_KEY_TYPE_TKIP;
Johannes Berg97359d12010-08-10 09:46:38 +0200103 case WLAN_CIPHER_SUITE_CCMP:
Sujithfb9987d2010-03-17 14:25:25 +0530104 return ATH9K_KEY_TYPE_AES;
Johannes Berg97359d12010-08-10 09:46:38 +0200105 default:
106 break;
107 }
Sujithfb9987d2010-03-17 14:25:25 +0530108 }
109
110 return ATH9K_KEY_TYPE_CLEAR;
111}
112EXPORT_SYMBOL(ath9k_cmn_get_hw_crypto_keytype);
113
Sujithfb9987d2010-03-17 14:25:25 +0530114/*
115 * Update internal channel flags.
116 */
Felix Fietkau2297f1c2013-10-11 23:30:57 +0200117static void ath9k_cmn_update_ichannel(struct ath9k_channel *ichan,
118 struct cfg80211_chan_def *chandef)
Sujithfb9987d2010-03-17 14:25:25 +0530119{
Felix Fietkau6b21fd22013-10-11 23:30:56 +0200120 struct ieee80211_channel *chan = chandef->chan;
121 u16 flags = 0;
Sujithfb9987d2010-03-17 14:25:25 +0530122
Felix Fietkau6b21fd22013-10-11 23:30:56 +0200123 ichan->channel = chan->center_freq;
124 ichan->chan = chan;
125
126 if (chan->band == IEEE80211_BAND_5GHZ)
127 flags |= CHANNEL_5GHZ;
Sujithfb9987d2010-03-17 14:25:25 +0530128
Simon Wunderlich06718942013-08-16 10:46:04 +0200129 switch (chandef->width) {
130 case NL80211_CHAN_WIDTH_5:
Felix Fietkau6b21fd22013-10-11 23:30:56 +0200131 flags |= CHANNEL_QUARTER;
Simon Wunderlich06718942013-08-16 10:46:04 +0200132 break;
133 case NL80211_CHAN_WIDTH_10:
Felix Fietkau6b21fd22013-10-11 23:30:56 +0200134 flags |= CHANNEL_HALF;
Simon Wunderlich06718942013-08-16 10:46:04 +0200135 break;
136 case NL80211_CHAN_WIDTH_20_NOHT:
137 break;
138 case NL80211_CHAN_WIDTH_20:
Felix Fietkau6b21fd22013-10-11 23:30:56 +0200139 flags |= CHANNEL_HT;
140 break;
Simon Wunderlich06718942013-08-16 10:46:04 +0200141 case NL80211_CHAN_WIDTH_40:
Felix Fietkau6b21fd22013-10-11 23:30:56 +0200142 if (chandef->center_freq1 > chandef->chan->center_freq)
143 flags |= CHANNEL_HT40PLUS | CHANNEL_HT;
144 else
145 flags |= CHANNEL_HT40MINUS | CHANNEL_HT;
Simon Wunderlich06718942013-08-16 10:46:04 +0200146 break;
147 default:
148 WARN_ON(1);
149 }
Felix Fietkau6b21fd22013-10-11 23:30:56 +0200150
151 ichan->channelFlags = flags;
Sujithfb9987d2010-03-17 14:25:25 +0530152}
Sujithfb9987d2010-03-17 14:25:25 +0530153
154/*
155 * Get the internal channel reference.
156 */
Felix Fietkau2297f1c2013-10-11 23:30:57 +0200157struct ath9k_channel *ath9k_cmn_get_channel(struct ieee80211_hw *hw,
158 struct ath_hw *ah,
159 struct cfg80211_chan_def *chandef)
Sujithfb9987d2010-03-17 14:25:25 +0530160{
Felix Fietkau2297f1c2013-10-11 23:30:57 +0200161 struct ieee80211_channel *curchan = chandef->chan;
Sujithfb9987d2010-03-17 14:25:25 +0530162 struct ath9k_channel *channel;
Sujithfb9987d2010-03-17 14:25:25 +0530163
Felix Fietkauf40c4602013-12-14 18:03:35 +0100164 channel = &ah->channels[curchan->hw_value];
Felix Fietkau2297f1c2013-10-11 23:30:57 +0200165 ath9k_cmn_update_ichannel(channel, chandef);
Sujithfb9987d2010-03-17 14:25:25 +0530166
167 return channel;
168}
Felix Fietkau2297f1c2013-10-11 23:30:57 +0200169EXPORT_SYMBOL(ath9k_cmn_get_channel);
Sujithfb9987d2010-03-17 14:25:25 +0530170
Sujith61389f32010-06-02 15:53:37 +0530171int ath9k_cmn_count_streams(unsigned int chainmask, int max)
172{
173 int streams = 0;
174
175 do {
176 if (++streams == max)
177 break;
178 } while ((chainmask = chainmask & (chainmask - 1)));
179
180 return streams;
181}
182EXPORT_SYMBOL(ath9k_cmn_count_streams);
183
Rajkumar Manoharan5048e8c2011-01-31 23:47:44 +0530184void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow,
185 u16 new_txpow, u16 *txpower)
186{
Felix Fietkauca2c68c2011-10-08 20:06:20 +0200187 struct ath_regulatory *reg = ath9k_hw_regulatory(ah);
188
189 if (reg->power_limit != new_txpow) {
Rajkumar Manoharan5048e8c2011-01-31 23:47:44 +0530190 ath9k_hw_set_txpowerlimit(ah, new_txpow, false);
191 /* read back in case value is clamped */
Felix Fietkauca2c68c2011-10-08 20:06:20 +0200192 *txpower = reg->max_power_level;
Rajkumar Manoharan5048e8c2011-01-31 23:47:44 +0530193 }
194}
195EXPORT_SYMBOL(ath9k_cmn_update_txpow);
196
Rajkumar Manoharanf82b4bd2011-08-13 10:28:15 +0530197void ath9k_cmn_init_crypto(struct ath_hw *ah)
198{
199 struct ath_common *common = ath9k_hw_common(ah);
200 int i = 0;
201
202 /* Get the hardware key cache size. */
203 common->keymax = AR_KEYTABLE_SIZE;
204
205 /*
206 * Check whether the separate key cache entries
207 * are required to handle both tx+rx MIC keys.
208 * With split mic keys the number of stations is limited
209 * to 27 otherwise 59.
210 */
211 if (ah->misc_mode & AR_PCU_MIC_NEW_LOC_ENA)
212 common->crypt_caps |= ATH_CRYPT_CAP_MIC_COMBINED;
213
214 /*
215 * Reset the key cache since some parts do not
216 * reset the contents on initial power up.
217 */
218 for (i = 0; i < common->keymax; i++)
219 ath_hw_keyreset(common, (u16) i);
220}
221EXPORT_SYMBOL(ath9k_cmn_init_crypto);
222
Luis R. Rodriguezdb86f072009-11-05 08:44:39 -0800223static int __init ath9k_cmn_init(void)
224{
225 return 0;
226}
227module_init(ath9k_cmn_init);
228
229static void __exit ath9k_cmn_exit(void)
230{
231 return;
232}
233module_exit(ath9k_cmn_exit);