aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/common.c
diff options
context:
space:
mode:
authorLuis R. Rodriguez <lrodriguez@atheros.com>2009-11-05 11:44:39 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-11-11 17:09:11 -0500
commitdb86f07ec6cdea9670a0928bd1289109d2a989dc (patch)
treeaf3484cd4d43c4d89fb1d597369f0df36478bfb2 /drivers/net/wireless/ath/ath9k/common.c
parentc9b1417055cd2518e8a3b4b27e1f8e4b72821dff (diff)
ath9k_common: add new module to share 802.11n driver helpers
ath9k and ath9k_htc share a lot of common hardware characteristics. They only differ in that ath9k_htc works with a target CPU and ath9k works directly with the hardware. ath9k_htc will do *some* things in the firmware, but a lot of others on the host. The common 802.11n hardware code is already shared through the ath9k_hw module. Common helpers amongst all Atheros drivers can use the ath module, this includes ath5k and ar9170 as users. But there is some common driver specific helpers which are not exactly hardware code which ath9k and ath9k_htc can share. We'll be using ath9k_common for this to avoid bloating the ath module and the common 802.11n hardware module ath9k_hw. We start by sharing skb pre and post processing in preparation for a hand off to mac80211. Signed-off-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/common.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/common.c326
1 files changed, 326 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
new file mode 100644
index 000000000000..5fb164e294de
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -0,0 +1,326 @@
1/*
2 * Copyright (c) 2009 Atheros Communications Inc.
3 *
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
30/* Common RX processing */
31
32/* Assumes you've already done the endian to CPU conversion */
33static bool ath9k_rx_accept(struct ath_common *common,
34 struct sk_buff *skb,
35 struct ieee80211_rx_status *rxs,
36 struct ath_rx_status *rx_stats,
37 bool *decrypt_error)
38{
39 struct ath_hw *ah = common->ah;
40 struct ieee80211_hdr *hdr;
41 __le16 fc;
42
43 hdr = (struct ieee80211_hdr *) skb->data;
44 fc = hdr->frame_control;
45
46 if (!rx_stats->rs_datalen)
47 return false;
48 /*
49 * rs_status follows rs_datalen so if rs_datalen is too large
50 * we can take a hint that hardware corrupted it, so ignore
51 * those frames.
52 */
53 if (rx_stats->rs_datalen > common->rx_bufsize)
54 return false;
55
56 if (rx_stats->rs_more) {
57 /*
58 * Frame spans multiple descriptors; this cannot happen yet
59 * as we don't support jumbograms. If not in monitor mode,
60 * discard the frame. Enable this if you want to see
61 * error frames in Monitor mode.
62 */
63 if (ah->opmode != NL80211_IFTYPE_MONITOR)
64 return false;
65 } else if (rx_stats->rs_status != 0) {
66 if (rx_stats->rs_status & ATH9K_RXERR_CRC)
67 rxs->flag |= RX_FLAG_FAILED_FCS_CRC;
68 if (rx_stats->rs_status & ATH9K_RXERR_PHY)
69 return false;
70
71 if (rx_stats->rs_status & ATH9K_RXERR_DECRYPT) {
72 *decrypt_error = true;
73 } else if (rx_stats->rs_status & ATH9K_RXERR_MIC) {
74 if (ieee80211_is_ctl(fc))
75 /*
76 * Sometimes, we get invalid
77 * MIC failures on valid control frames.
78 * Remove these mic errors.
79 */
80 rx_stats->rs_status &= ~ATH9K_RXERR_MIC;
81 else
82 rxs->flag |= RX_FLAG_MMIC_ERROR;
83 }
84 /*
85 * Reject error frames with the exception of
86 * decryption and MIC failures. For monitor mode,
87 * we also ignore the CRC error.
88 */
89 if (ah->opmode == NL80211_IFTYPE_MONITOR) {
90 if (rx_stats->rs_status &
91 ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC |
92 ATH9K_RXERR_CRC))
93 return false;
94 } else {
95 if (rx_stats->rs_status &
96 ~(ATH9K_RXERR_DECRYPT | ATH9K_RXERR_MIC)) {
97 return false;
98 }
99 }
100 }
101 return true;
102}
103
104static u8 ath9k_process_rate(struct ath_common *common,
105 struct ieee80211_hw *hw,
106 struct ath_rx_status *rx_stats,
107 struct ieee80211_rx_status *rxs,
108 struct sk_buff *skb)
109{
110 struct ieee80211_supported_band *sband;
111 enum ieee80211_band band;
112 unsigned int i = 0;
113
114 band = hw->conf.channel->band;
115 sband = hw->wiphy->bands[band];
116
117 if (rx_stats->rs_rate & 0x80) {
118 /* HT rate */
119 rxs->flag |= RX_FLAG_HT;
120 if (rx_stats->rs_flags & ATH9K_RX_2040)
121 rxs->flag |= RX_FLAG_40MHZ;
122 if (rx_stats->rs_flags & ATH9K_RX_GI)
123 rxs->flag |= RX_FLAG_SHORT_GI;
124 return rx_stats->rs_rate & 0x7f;
125 }
126
127 for (i = 0; i < sband->n_bitrates; i++) {
128 if (sband->bitrates[i].hw_value == rx_stats->rs_rate)
129 return i;
130 if (sband->bitrates[i].hw_value_short == rx_stats->rs_rate) {
131 rxs->flag |= RX_FLAG_SHORTPRE;
132 return i;
133 }
134 }
135
136 /* No valid hardware bitrate found -- we should not get here */
137 ath_print(common, ATH_DBG_XMIT, "unsupported hw bitrate detected "
138 "0x%02x using 1 Mbit\n", rx_stats->rs_rate);
139 if ((common->debug_mask & ATH_DBG_XMIT))
140 print_hex_dump_bytes("", DUMP_PREFIX_NONE, skb->data, skb->len);
141
142 return 0;
143}
144
145/*
146 * Theory for reporting quality:
147 *
148 * At a hardware RSSI of 45 you will be able to use MCS 7 reliably.
149 * At a hardware RSSI of 45 you will be able to use MCS 15 reliably.
150 * At a hardware RSSI of 35 you should be able use 54 Mbps reliably.
151 *
152 * MCS 7 is the highets MCS index usable by a 1-stream device.
153 * MCS 15 is the highest MCS index usable by a 2-stream device.
154 *
155 * All ath9k devices are either 1-stream or 2-stream.
156 *
157 * How many bars you see is derived from the qual reporting.
158 *
159 * A more elaborate scheme can be used here but it requires tables
160 * of SNR/throughput for each possible mode used. For the MCS table
161 * you can refer to the wireless wiki:
162 *
163 * http://wireless.kernel.org/en/developers/Documentation/ieee80211/802.11n
164 *
165 */
166static int ath9k_compute_qual(struct ieee80211_hw *hw,
167 struct ath_rx_status *rx_stats)
168{
169 int qual;
170
171 if (conf_is_ht(&hw->conf))
172 qual = rx_stats->rs_rssi * 100 / 45;
173 else
174 qual = rx_stats->rs_rssi * 100 / 35;
175
176 /*
177 * rssi can be more than 45 though, anything above that
178 * should be considered at 100%
179 */
180 if (qual > 100)
181 qual = 100;
182
183 return qual;
184}
185
186static void ath9k_process_rssi(struct ath_common *common,
187 struct ieee80211_hw *hw,
188 struct sk_buff *skb,
189 struct ath_rx_status *rx_stats)
190{
191 struct ath_hw *ah = common->ah;
192 struct ieee80211_sta *sta;
193 struct ieee80211_hdr *hdr;
194 struct ath_node *an;
195 int last_rssi = ATH_RSSI_DUMMY_MARKER;
196 __le16 fc;
197
198 hdr = (struct ieee80211_hdr *)skb->data;
199 fc = hdr->frame_control;
200
201 rcu_read_lock();
202 /*
203 * XXX: use ieee80211_find_sta! This requires quite a bit of work
204 * under the current ath9k virtual wiphy implementation as we have
205 * no way of tying a vif to wiphy. Typically vifs are attached to
206 * at least one sdata of a wiphy on mac80211 but with ath9k virtual
207 * wiphy you'd have to iterate over every wiphy and each sdata.
208 */
209 sta = ieee80211_find_sta_by_hw(hw, hdr->addr2);
210 if (sta) {
211 an = (struct ath_node *) sta->drv_priv;
212 if (rx_stats->rs_rssi != ATH9K_RSSI_BAD &&
213 !rx_stats->rs_moreaggr)
214 ATH_RSSI_LPF(an->last_rssi, rx_stats->rs_rssi);
215 last_rssi = an->last_rssi;
216 }
217 rcu_read_unlock();
218
219 if (likely(last_rssi != ATH_RSSI_DUMMY_MARKER))
220 rx_stats->rs_rssi = ATH_EP_RND(last_rssi,
221 ATH_RSSI_EP_MULTIPLIER);
222 if (rx_stats->rs_rssi < 0)
223 rx_stats->rs_rssi = 0;
224 else if (rx_stats->rs_rssi > 127)
225 rx_stats->rs_rssi = 127;
226
227 /* Update Beacon RSSI, this is used by ANI. */
228 if (ieee80211_is_beacon(fc))
229 ah->stats.avgbrssi = rx_stats->rs_rssi;
230}
231
232/*
233 * For Decrypt or Demic errors, we only mark packet status here and always push
234 * up the frame up to let mac80211 handle the actual error case, be it no
235 * decryption key or real decryption error. This let us keep statistics there.
236 */
237int ath9k_cmn_rx_skb_preprocess(struct ath_common *common,
238 struct ieee80211_hw *hw,
239 struct sk_buff *skb,
240 struct ath_rx_status *rx_stats,
241 struct ieee80211_rx_status *rx_status,
242 bool *decrypt_error)
243{
244 struct ath_hw *ah = common->ah;
245
246 if (!ath9k_rx_accept(common, skb, rx_status, rx_stats, decrypt_error))
247 return -EINVAL;
248
249 ath9k_process_rssi(common, hw, skb, rx_stats);
250
251 rx_status->rate_idx = ath9k_process_rate(common, hw,
252 rx_stats, rx_status, skb);
253 rx_status->mactime = ath9k_hw_extend_tsf(ah, rx_stats->rs_tstamp);
254 rx_status->band = hw->conf.channel->band;
255 rx_status->freq = hw->conf.channel->center_freq;
256 rx_status->noise = common->ani.noise_floor;
257 rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi;
258 rx_status->antenna = rx_stats->rs_antenna;
259 rx_status->qual = ath9k_compute_qual(hw, rx_stats);
260 rx_status->flag |= RX_FLAG_TSFT;
261
262 return 0;
263}
264EXPORT_SYMBOL(ath9k_cmn_rx_skb_preprocess);
265
266void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
267 struct sk_buff *skb,
268 struct ath_rx_status *rx_stats,
269 struct ieee80211_rx_status *rxs,
270 bool decrypt_error)
271{
272 struct ath_hw *ah = common->ah;
273 struct ieee80211_hdr *hdr;
274 int hdrlen, padsize;
275 u8 keyix;
276 __le16 fc;
277
278 /* see if any padding is done by the hw and remove it */
279 hdr = (struct ieee80211_hdr *) skb->data;
280 hdrlen = ieee80211_get_hdrlen_from_skb(skb);
281 fc = hdr->frame_control;
282
283 /* The MAC header is padded to have 32-bit boundary if the
284 * packet payload is non-zero. The general calculation for
285 * padsize would take into account odd header lengths:
286 * padsize = (4 - hdrlen % 4) % 4; However, since only
287 * even-length headers are used, padding can only be 0 or 2
288 * bytes and we can optimize this a bit. In addition, we must
289 * not try to remove padding from short control frames that do
290 * not have payload. */
291 padsize = hdrlen & 3;
292 if (padsize && hdrlen >= 24) {
293 memmove(skb->data + padsize, skb->data, hdrlen);
294 skb_pull(skb, padsize);
295 }
296
297 keyix = rx_stats->rs_keyix;
298
299 if (!(keyix == ATH9K_RXKEYIX_INVALID) && !decrypt_error) {
300 rxs->flag |= RX_FLAG_DECRYPTED;
301 } else if (ieee80211_has_protected(fc)
302 && !decrypt_error && skb->len >= hdrlen + 4) {
303 keyix = skb->data[hdrlen + 3] >> 6;
304
305 if (test_bit(keyix, common->keymap))
306 rxs->flag |= RX_FLAG_DECRYPTED;
307 }
308 if (ah->sw_mgmt_crypto &&
309 (rxs->flag & RX_FLAG_DECRYPTED) &&
310 ieee80211_is_mgmt(fc))
311 /* Use software decrypt for management frames. */
312 rxs->flag &= ~RX_FLAG_DECRYPTED;
313}
314EXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess);
315
316static int __init ath9k_cmn_init(void)
317{
318 return 0;
319}
320module_init(ath9k_cmn_init);
321
322static void __exit ath9k_cmn_exit(void)
323{
324 return;
325}
326module_exit(ath9k_cmn_exit);