blob: 8a964f1303676f110478623b4f62d6b5db676f66 [file] [log] [blame]
Christian Lampartere9348cd2009-03-21 23:05:13 +01001/*
2 * Atheros AR9170 driver
3 *
4 * mac80211 interaction code
5 *
6 * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
7 * Copyright 2009, Christian Lamparter <chunkeey@web.de>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; see the file COPYING. If not, see
21 * http://www.gnu.org/licenses/.
22 *
23 * This file incorporates work covered by the following copyright and
24 * permission notice:
25 * Copyright (c) 2007-2008 Atheros Communications, Inc.
26 *
27 * Permission to use, copy, modify, and/or distribute this software for any
28 * purpose with or without fee is hereby granted, provided that the above
29 * copyright notice and this permission notice appear in all copies.
30 *
31 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
32 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
33 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
34 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
35 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
36 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
37 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
38 */
39
Christian Lampartere9348cd2009-03-21 23:05:13 +010040#include <linux/init.h>
41#include <linux/module.h>
42#include <linux/etherdevice.h>
43#include <net/mac80211.h>
44#include "ar9170.h"
45#include "hw.h"
46#include "cmd.h"
47
48static int modparam_nohwcrypt;
49module_param_named(nohwcrypt, modparam_nohwcrypt, bool, S_IRUGO);
50MODULE_PARM_DESC(nohwcrypt, "Disable hardware encryption.");
Christian Lampartere9348cd2009-03-21 23:05:13 +010051
Christian Lamparteracbadf02009-07-11 17:24:14 +020052static int modparam_ht;
53module_param_named(ht, modparam_ht, bool, S_IRUGO);
54MODULE_PARM_DESC(ht, "enable MPDU aggregation.");
55
Christian Lampartere9348cd2009-03-21 23:05:13 +010056#define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \
57 .bitrate = (_bitrate), \
58 .flags = (_flags), \
59 .hw_value = (_hw_rate) | (_txpidx) << 4, \
60}
61
62static struct ieee80211_rate __ar9170_ratetable[] = {
63 RATE(10, 0, 0, 0),
64 RATE(20, 1, 1, IEEE80211_RATE_SHORT_PREAMBLE),
65 RATE(55, 2, 2, IEEE80211_RATE_SHORT_PREAMBLE),
66 RATE(110, 3, 3, IEEE80211_RATE_SHORT_PREAMBLE),
67 RATE(60, 0xb, 0, 0),
68 RATE(90, 0xf, 0, 0),
69 RATE(120, 0xa, 0, 0),
70 RATE(180, 0xe, 0, 0),
71 RATE(240, 0x9, 0, 0),
72 RATE(360, 0xd, 1, 0),
73 RATE(480, 0x8, 2, 0),
74 RATE(540, 0xc, 3, 0),
75};
76#undef RATE
77
78#define ar9170_g_ratetable (__ar9170_ratetable + 0)
79#define ar9170_g_ratetable_size 12
80#define ar9170_a_ratetable (__ar9170_ratetable + 4)
81#define ar9170_a_ratetable_size 8
82
83/*
84 * NB: The hw_value is used as an index into the ar9170_phy_freq_params
85 * array in phy.c so that we don't have to do frequency lookups!
86 */
87#define CHAN(_freq, _idx) { \
88 .center_freq = (_freq), \
89 .hw_value = (_idx), \
90 .max_power = 18, /* XXX */ \
91}
92
93static struct ieee80211_channel ar9170_2ghz_chantable[] = {
94 CHAN(2412, 0),
95 CHAN(2417, 1),
96 CHAN(2422, 2),
97 CHAN(2427, 3),
98 CHAN(2432, 4),
99 CHAN(2437, 5),
100 CHAN(2442, 6),
101 CHAN(2447, 7),
102 CHAN(2452, 8),
103 CHAN(2457, 9),
104 CHAN(2462, 10),
105 CHAN(2467, 11),
106 CHAN(2472, 12),
107 CHAN(2484, 13),
108};
109
110static struct ieee80211_channel ar9170_5ghz_chantable[] = {
111 CHAN(4920, 14),
112 CHAN(4940, 15),
113 CHAN(4960, 16),
114 CHAN(4980, 17),
115 CHAN(5040, 18),
116 CHAN(5060, 19),
117 CHAN(5080, 20),
118 CHAN(5180, 21),
119 CHAN(5200, 22),
120 CHAN(5220, 23),
121 CHAN(5240, 24),
122 CHAN(5260, 25),
123 CHAN(5280, 26),
124 CHAN(5300, 27),
125 CHAN(5320, 28),
126 CHAN(5500, 29),
127 CHAN(5520, 30),
128 CHAN(5540, 31),
129 CHAN(5560, 32),
130 CHAN(5580, 33),
131 CHAN(5600, 34),
132 CHAN(5620, 35),
133 CHAN(5640, 36),
134 CHAN(5660, 37),
135 CHAN(5680, 38),
136 CHAN(5700, 39),
137 CHAN(5745, 40),
138 CHAN(5765, 41),
139 CHAN(5785, 42),
140 CHAN(5805, 43),
141 CHAN(5825, 44),
142 CHAN(5170, 45),
143 CHAN(5190, 46),
144 CHAN(5210, 47),
145 CHAN(5230, 48),
146};
147#undef CHAN
148
Johannes Berg9e52b06232009-04-20 18:27:04 +0200149#define AR9170_HT_CAP \
150{ \
151 .ht_supported = true, \
152 .cap = IEEE80211_HT_CAP_MAX_AMSDU | \
Johannes Berg9e52b06232009-04-20 18:27:04 +0200153 IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \
154 IEEE80211_HT_CAP_SGI_40 | \
Christian Lamparteracbadf02009-07-11 17:24:14 +0200155 IEEE80211_HT_CAP_GRN_FLD | \
Johannes Berg9e52b06232009-04-20 18:27:04 +0200156 IEEE80211_HT_CAP_DSSSCCK40 | \
157 IEEE80211_HT_CAP_SM_PS, \
Christian Lamparter083c4682009-04-24 21:35:57 +0200158 .ampdu_factor = 3, \
159 .ampdu_density = 6, \
Johannes Berg9e52b06232009-04-20 18:27:04 +0200160 .mcs = { \
Christian Lamparteracbadf02009-07-11 17:24:14 +0200161 .rx_mask = { 0xff, 0xff, 0, 0, 0x1, 0, 0, 0, 0, 0, }, \
162 .rx_highest = cpu_to_le16(300), \
163 .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \
Johannes Berg9e52b06232009-04-20 18:27:04 +0200164 }, \
165}
166
Christian Lampartere9348cd2009-03-21 23:05:13 +0100167static struct ieee80211_supported_band ar9170_band_2GHz = {
168 .channels = ar9170_2ghz_chantable,
169 .n_channels = ARRAY_SIZE(ar9170_2ghz_chantable),
170 .bitrates = ar9170_g_ratetable,
171 .n_bitrates = ar9170_g_ratetable_size,
Johannes Berg9e52b06232009-04-20 18:27:04 +0200172 .ht_cap = AR9170_HT_CAP,
173};
174
175static struct ieee80211_supported_band ar9170_band_5GHz = {
176 .channels = ar9170_5ghz_chantable,
177 .n_channels = ARRAY_SIZE(ar9170_5ghz_chantable),
178 .bitrates = ar9170_a_ratetable,
179 .n_bitrates = ar9170_a_ratetable_size,
180 .ht_cap = AR9170_HT_CAP,
Christian Lampartere9348cd2009-03-21 23:05:13 +0100181};
182
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200183static void ar9170_tx(struct ar9170 *ar);
Christian Lamparteracbadf02009-07-11 17:24:14 +0200184static bool ar9170_tx_ampdu(struct ar9170 *ar);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100185
Christian Lamparteracbadf02009-07-11 17:24:14 +0200186static inline u16 ar9170_get_seq_h(struct ieee80211_hdr *hdr)
187{
188 return le16_to_cpu(hdr->seq_ctrl) >> 4;
189}
190
191static inline u16 ar9170_get_seq(struct sk_buff *skb)
192{
193 struct ar9170_tx_control *txc = (void *) skb->data;
194 return ar9170_get_seq_h((void *) txc->frame_data);
195}
196
Christian Lamparter07bc5452009-11-29 00:59:48 +0100197static inline u16 ar9170_get_tid_h(struct ieee80211_hdr *hdr)
198{
199 return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK;
200}
201
Christian Lamparteracbadf02009-07-11 17:24:14 +0200202static inline u16 ar9170_get_tid(struct sk_buff *skb)
203{
204 struct ar9170_tx_control *txc = (void *) skb->data;
Christian Lamparter07bc5452009-11-29 00:59:48 +0100205 return ar9170_get_tid_h((struct ieee80211_hdr *) txc->frame_data);
Christian Lamparteracbadf02009-07-11 17:24:14 +0200206}
207
208#define GET_NEXT_SEQ(seq) ((seq + 1) & 0x0fff)
209#define GET_NEXT_SEQ_FROM_SKB(skb) (GET_NEXT_SEQ(ar9170_get_seq(skb)))
210
211#if (defined AR9170_QUEUE_DEBUG) || (defined AR9170_TXAGG_DEBUG)
Christian Lampartere9348cd2009-03-21 23:05:13 +0100212static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb)
213{
214 struct ar9170_tx_control *txc = (void *) skb->data;
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200215 struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
216 struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data;
217 struct ieee80211_hdr *hdr = (void *) txc->frame_data;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100218
Christian Lamparter15b098b2009-11-29 00:56:55 +0100219 printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] s:%d "
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200220 "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n",
Christian Lampartere9348cd2009-03-21 23:05:13 +0100221 wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb),
Christian Lamparter15b098b2009-11-29 00:56:55 +0100222 ieee80211_get_DA(hdr), ar9170_get_seq_h(hdr),
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200223 le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control),
224 jiffies_to_msecs(arinfo->timeout - jiffies));
Christian Lampartere9348cd2009-03-21 23:05:13 +0100225}
226
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200227static void __ar9170_dump_txqueue(struct ar9170 *ar,
228 struct sk_buff_head *queue)
Christian Lampartere9348cd2009-03-21 23:05:13 +0100229{
230 struct sk_buff *skb;
231 int i = 0;
232
233 printk(KERN_DEBUG "---[ cut here ]---\n");
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200234 printk(KERN_DEBUG "%s: %d entries in queue.\n",
Christian Lampartere9348cd2009-03-21 23:05:13 +0100235 wiphy_name(ar->hw->wiphy), skb_queue_len(queue));
236
237 skb_queue_walk(queue, skb) {
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200238 printk(KERN_DEBUG "index:%d => \n", i++);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100239 ar9170_print_txheader(ar, skb);
240 }
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200241 if (i != skb_queue_len(queue))
242 printk(KERN_DEBUG "WARNING: queue frame counter "
243 "mismatch %d != %d\n", skb_queue_len(queue), i);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100244 printk(KERN_DEBUG "---[ end ]---\n");
245}
Christian Lamparteracbadf02009-07-11 17:24:14 +0200246#endif /* AR9170_QUEUE_DEBUG || AR9170_TXAGG_DEBUG */
Christian Lampartere9348cd2009-03-21 23:05:13 +0100247
Christian Lamparteracbadf02009-07-11 17:24:14 +0200248#ifdef AR9170_QUEUE_DEBUG
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200249static void ar9170_dump_txqueue(struct ar9170 *ar,
250 struct sk_buff_head *queue)
Christian Lampartere9348cd2009-03-21 23:05:13 +0100251{
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200252 unsigned long flags;
253
254 spin_lock_irqsave(&queue->lock, flags);
255 __ar9170_dump_txqueue(ar, queue);
256 spin_unlock_irqrestore(&queue->lock, flags);
257}
Christian Lamparteracbadf02009-07-11 17:24:14 +0200258#endif /* AR9170_QUEUE_DEBUG */
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200259
Christian Lamparteracbadf02009-07-11 17:24:14 +0200260#ifdef AR9170_QUEUE_STOP_DEBUG
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200261static void __ar9170_dump_txstats(struct ar9170 *ar)
262{
263 int i;
264
265 printk(KERN_DEBUG "%s: QoS queue stats\n",
266 wiphy_name(ar->hw->wiphy));
267
268 for (i = 0; i < __AR9170_NUM_TXQ; i++)
Christian Lamparteracbadf02009-07-11 17:24:14 +0200269 printk(KERN_DEBUG "%s: queue:%d limit:%d len:%d waitack:%d "
270 " stopped:%d\n", wiphy_name(ar->hw->wiphy), i,
271 ar->tx_stats[i].limit, ar->tx_stats[i].len,
272 skb_queue_len(&ar->tx_status[i]),
273 ieee80211_queue_stopped(ar->hw, i));
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200274}
Christian Lamparteracbadf02009-07-11 17:24:14 +0200275#endif /* AR9170_QUEUE_STOP_DEBUG */
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200276
Christian Lamparteracbadf02009-07-11 17:24:14 +0200277#ifdef AR9170_TXAGG_DEBUG
278static void ar9170_dump_tx_status_ampdu(struct ar9170 *ar)
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200279{
Christian Lampartere9348cd2009-03-21 23:05:13 +0100280 unsigned long flags;
281
Christian Lamparteracbadf02009-07-11 17:24:14 +0200282 spin_lock_irqsave(&ar->tx_status_ampdu.lock, flags);
283 printk(KERN_DEBUG "%s: A-MPDU tx_status queue => \n",
284 wiphy_name(ar->hw->wiphy));
285 __ar9170_dump_txqueue(ar, &ar->tx_status_ampdu);
286 spin_unlock_irqrestore(&ar->tx_status_ampdu.lock, flags);
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200287}
Christian Lamparteracbadf02009-07-11 17:24:14 +0200288
289#endif /* AR9170_TXAGG_DEBUG */
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200290
291/* caller must guarantee exclusive access for _bin_ queue. */
292static void ar9170_recycle_expired(struct ar9170 *ar,
293 struct sk_buff_head *queue,
294 struct sk_buff_head *bin)
295{
296 struct sk_buff *skb, *old = NULL;
297 unsigned long flags;
298
299 spin_lock_irqsave(&queue->lock, flags);
300 while ((skb = skb_peek(queue))) {
301 struct ieee80211_tx_info *txinfo;
302 struct ar9170_tx_info *arinfo;
303
304 txinfo = IEEE80211_SKB_CB(skb);
305 arinfo = (void *) txinfo->rate_driver_data;
306
307 if (time_is_before_jiffies(arinfo->timeout)) {
308#ifdef AR9170_QUEUE_DEBUG
309 printk(KERN_DEBUG "%s: [%ld > %ld] frame expired => "
310 "recycle \n", wiphy_name(ar->hw->wiphy),
311 jiffies, arinfo->timeout);
312 ar9170_print_txheader(ar, skb);
313#endif /* AR9170_QUEUE_DEBUG */
314 __skb_unlink(skb, queue);
315 __skb_queue_tail(bin, skb);
316 } else {
317 break;
318 }
319
320 if (unlikely(old == skb)) {
321 /* bail out - queue is shot. */
322
323 WARN_ON(1);
324 break;
325 }
326 old = skb;
327 }
328 spin_unlock_irqrestore(&queue->lock, flags);
329}
330
331static void ar9170_tx_status(struct ar9170 *ar, struct sk_buff *skb,
332 u16 tx_status)
333{
334 struct ieee80211_tx_info *txinfo;
335 unsigned int retries = 0;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100336
337 txinfo = IEEE80211_SKB_CB(skb);
338 ieee80211_tx_info_clear_status(txinfo);
339
340 switch (tx_status) {
341 case AR9170_TX_STATUS_RETRY:
342 retries = 2;
343 case AR9170_TX_STATUS_COMPLETE:
344 txinfo->flags |= IEEE80211_TX_STAT_ACK;
345 break;
346
347 case AR9170_TX_STATUS_FAILED:
348 retries = ar->hw->conf.long_frame_max_tx_count;
349 break;
350
351 default:
352 printk(KERN_ERR "%s: invalid tx_status response (%x).\n",
353 wiphy_name(ar->hw->wiphy), tx_status);
354 break;
355 }
356
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200357 txinfo->status.rates[0].count = retries + 1;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100358 skb_pull(skb, sizeof(struct ar9170_tx_control));
359 ieee80211_tx_status_irqsafe(ar->hw, skb);
360}
Christian Lampartere9348cd2009-03-21 23:05:13 +0100361
Christian Lamparteracbadf02009-07-11 17:24:14 +0200362static void ar9170_tx_fake_ampdu_status(struct ar9170 *ar)
363{
364 struct sk_buff_head success;
365 struct sk_buff *skb;
366 unsigned int i;
367 unsigned long queue_bitmap = 0;
368
369 skb_queue_head_init(&success);
370
371 while (skb_queue_len(&ar->tx_status_ampdu) > AR9170_NUM_TX_STATUS)
372 __skb_queue_tail(&success, skb_dequeue(&ar->tx_status_ampdu));
373
374 ar9170_recycle_expired(ar, &ar->tx_status_ampdu, &success);
375
376#ifdef AR9170_TXAGG_DEBUG
377 printk(KERN_DEBUG "%s: collected %d A-MPDU frames.\n",
378 wiphy_name(ar->hw->wiphy), skb_queue_len(&success));
379 __ar9170_dump_txqueue(ar, &success);
380#endif /* AR9170_TXAGG_DEBUG */
381
382 while ((skb = __skb_dequeue(&success))) {
383 struct ieee80211_tx_info *txinfo;
384
385 queue_bitmap |= BIT(skb_get_queue_mapping(skb));
386
387 txinfo = IEEE80211_SKB_CB(skb);
388 ieee80211_tx_info_clear_status(txinfo);
389
390 txinfo->flags |= IEEE80211_TX_STAT_ACK;
391 txinfo->status.rates[0].count = 1;
392
393 skb_pull(skb, sizeof(struct ar9170_tx_control));
394 ieee80211_tx_status_irqsafe(ar->hw, skb);
395 }
396
397 for_each_bit(i, &queue_bitmap, BITS_PER_BYTE) {
398#ifdef AR9170_QUEUE_STOP_DEBUG
399 printk(KERN_DEBUG "%s: wake queue %d\n",
400 wiphy_name(ar->hw->wiphy), i);
401 __ar9170_dump_txstats(ar);
402#endif /* AR9170_QUEUE_STOP_DEBUG */
403 ieee80211_wake_queue(ar->hw, i);
404 }
405
406 if (queue_bitmap)
407 ar9170_tx(ar);
408}
409
410static void ar9170_tx_ampdu_callback(struct ar9170 *ar, struct sk_buff *skb)
411{
412 struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
413 struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data;
414
415 arinfo->timeout = jiffies +
416 msecs_to_jiffies(AR9170_BA_TIMEOUT);
417
418 skb_queue_tail(&ar->tx_status_ampdu, skb);
419 ar9170_tx_fake_ampdu_status(ar);
Christian Lamparteracbadf02009-07-11 17:24:14 +0200420
Christian Lamparter02bdf5b2009-10-17 21:56:43 +0200421 if (atomic_dec_and_test(&ar->tx_ampdu_pending) &&
422 !list_empty(&ar->tx_ampdu_list))
Christian Lamparteracbadf02009-07-11 17:24:14 +0200423 ar9170_tx_ampdu(ar);
424}
425
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200426void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb)
Christian Lampartere9348cd2009-03-21 23:05:13 +0100427{
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200428 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
429 struct ar9170_tx_info *arinfo = (void *) info->rate_driver_data;
430 unsigned int queue = skb_get_queue_mapping(skb);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100431 unsigned long flags;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100432
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200433 spin_lock_irqsave(&ar->tx_stats_lock, flags);
434 ar->tx_stats[queue].len--;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100435
Christian Lamparter53a76b52009-11-29 00:52:51 +0100436 if (ar->tx_stats[queue].len < AR9170_NUM_TX_LIMIT_SOFT) {
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200437#ifdef AR9170_QUEUE_STOP_DEBUG
438 printk(KERN_DEBUG "%s: wake queue %d\n",
439 wiphy_name(ar->hw->wiphy), queue);
440 __ar9170_dump_txstats(ar);
441#endif /* AR9170_QUEUE_STOP_DEBUG */
442 ieee80211_wake_queue(ar->hw, queue);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100443 }
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200444 spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
445
Christian Lamparter15b098b2009-11-29 00:56:55 +0100446 if (info->flags & IEEE80211_TX_CTL_NO_ACK) {
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200447 ar9170_tx_status(ar, skb, AR9170_TX_STATUS_FAILED);
448 } else {
Christian Lamparter15b098b2009-11-29 00:56:55 +0100449 if (info->flags & IEEE80211_TX_CTL_AMPDU) {
450 ar9170_tx_ampdu_callback(ar, skb);
451 } else {
452 arinfo->timeout = jiffies +
453 msecs_to_jiffies(AR9170_TX_TIMEOUT);
454
455 skb_queue_tail(&ar->tx_status[queue], skb);
456 }
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200457 }
458
459 if (!ar->tx_stats[queue].len &&
460 !skb_queue_empty(&ar->tx_pending[queue])) {
461 ar9170_tx(ar);
462 }
Christian Lampartere9348cd2009-03-21 23:05:13 +0100463}
464
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200465static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar,
466 const u8 *mac,
467 struct sk_buff_head *queue,
468 const u32 rate)
Christian Lampartere9348cd2009-03-21 23:05:13 +0100469{
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200470 unsigned long flags;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100471 struct sk_buff *skb;
472
473 /*
474 * Unfortunately, the firmware does not tell to which (queued) frame
475 * this transmission status report belongs to.
476 *
477 * So we have to make risky guesses - with the scarce information
478 * the firmware provided (-> destination MAC, and phy_control) -
479 * and hope that we picked the right one...
480 */
Christian Lampartere9348cd2009-03-21 23:05:13 +0100481
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200482 spin_lock_irqsave(&queue->lock, flags);
483 skb_queue_walk(queue, skb) {
484 struct ar9170_tx_control *txc = (void *) skb->data;
485 struct ieee80211_hdr *hdr = (void *) txc->frame_data;
486 u32 r;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100487
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200488 if (mac && compare_ether_addr(ieee80211_get_DA(hdr), mac)) {
489#ifdef AR9170_QUEUE_DEBUG
490 printk(KERN_DEBUG "%s: skip frame => DA %pM != %pM\n",
491 wiphy_name(ar->hw->wiphy), mac,
492 ieee80211_get_DA(hdr));
493 ar9170_print_txheader(ar, skb);
494#endif /* AR9170_QUEUE_DEBUG */
495 continue;
496 }
497
498 r = (le32_to_cpu(txc->phy_control) & AR9170_TX_PHY_MCS_MASK) >>
499 AR9170_TX_PHY_MCS_SHIFT;
500
501 if ((rate != AR9170_TX_INVALID_RATE) && (r != rate)) {
502#ifdef AR9170_QUEUE_DEBUG
503 printk(KERN_DEBUG "%s: skip frame => rate %d != %d\n",
504 wiphy_name(ar->hw->wiphy), rate, r);
505 ar9170_print_txheader(ar, skb);
506#endif /* AR9170_QUEUE_DEBUG */
507 continue;
508 }
509
510 __skb_unlink(skb, queue);
511 spin_unlock_irqrestore(&queue->lock, flags);
512 return skb;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100513 }
Christian Lampartere9348cd2009-03-21 23:05:13 +0100514
515#ifdef AR9170_QUEUE_DEBUG
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200516 printk(KERN_ERR "%s: ESS:[%pM] does not have any "
517 "outstanding frames in queue.\n",
518 wiphy_name(ar->hw->wiphy), mac);
519 __ar9170_dump_txqueue(ar, queue);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100520#endif /* AR9170_QUEUE_DEBUG */
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200521 spin_unlock_irqrestore(&queue->lock, flags);
522
523 return NULL;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100524}
525
Christian Lamparteracbadf02009-07-11 17:24:14 +0200526static void ar9170_handle_block_ack(struct ar9170 *ar, u16 count, u16 r)
527{
528 struct sk_buff *skb;
529 struct ieee80211_tx_info *txinfo;
530
531 while (count) {
532 skb = ar9170_get_queued_skb(ar, NULL, &ar->tx_status_ampdu, r);
533 if (!skb)
534 break;
535
536 txinfo = IEEE80211_SKB_CB(skb);
537 ieee80211_tx_info_clear_status(txinfo);
538
539 /* FIXME: maybe more ? */
540 txinfo->status.rates[0].count = 1;
541
542 skb_pull(skb, sizeof(struct ar9170_tx_control));
543 ieee80211_tx_status_irqsafe(ar->hw, skb);
544 count--;
545 }
546
547#ifdef AR9170_TXAGG_DEBUG
548 if (count) {
549 printk(KERN_DEBUG "%s: got %d more failed mpdus, but no more "
550 "suitable frames left in tx_status queue.\n",
551 wiphy_name(ar->hw->wiphy), count);
552
553 ar9170_dump_tx_status_ampdu(ar);
554 }
555#endif /* AR9170_TXAGG_DEBUG */
556}
557
Christian Lampartere9348cd2009-03-21 23:05:13 +0100558/*
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200559 * This worker tries to keeps an maintain tx_status queues.
560 * So we can guarantee that incoming tx_status reports are
561 * actually for a pending frame.
Christian Lampartere9348cd2009-03-21 23:05:13 +0100562 */
563
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200564static void ar9170_tx_janitor(struct work_struct *work)
Christian Lampartere9348cd2009-03-21 23:05:13 +0100565{
566 struct ar9170 *ar = container_of(work, struct ar9170,
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200567 tx_janitor.work);
568 struct sk_buff_head waste;
569 unsigned int i;
570 bool resched = false;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100571
Christian Lamparter4a48e2a2009-03-23 12:15:43 +0100572 if (unlikely(!IS_STARTED(ar)))
573 return ;
574
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200575 skb_queue_head_init(&waste);
576
577 for (i = 0; i < __AR9170_NUM_TXQ; i++) {
Christian Lampartere9348cd2009-03-21 23:05:13 +0100578#ifdef AR9170_QUEUE_DEBUG
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200579 printk(KERN_DEBUG "%s: garbage collector scans queue:%d\n",
580 wiphy_name(ar->hw->wiphy), i);
581 ar9170_dump_txqueue(ar, &ar->tx_pending[i]);
582 ar9170_dump_txqueue(ar, &ar->tx_status[i]);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100583#endif /* AR9170_QUEUE_DEBUG */
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200584
585 ar9170_recycle_expired(ar, &ar->tx_status[i], &waste);
586 ar9170_recycle_expired(ar, &ar->tx_pending[i], &waste);
587 skb_queue_purge(&waste);
588
589 if (!skb_queue_empty(&ar->tx_status[i]) ||
590 !skb_queue_empty(&ar->tx_pending[i]))
591 resched = true;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100592 }
593
Christian Lamparteracbadf02009-07-11 17:24:14 +0200594 ar9170_tx_fake_ampdu_status(ar);
595
Luis R. Rodriguez42935ec2009-07-29 20:08:07 -0400596 if (!resched)
597 return;
598
599 ieee80211_queue_delayed_work(ar->hw,
600 &ar->tx_janitor,
601 msecs_to_jiffies(AR9170_JANITOR_DELAY));
Christian Lampartere9348cd2009-03-21 23:05:13 +0100602}
603
Christian Lamparter66d00812009-05-28 17:04:27 +0200604void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
Christian Lampartere9348cd2009-03-21 23:05:13 +0100605{
606 struct ar9170_cmd_response *cmd = (void *) buf;
607
608 if ((cmd->type & 0xc0) != 0xc0) {
609 ar->callback_cmd(ar, len, buf);
610 return;
611 }
612
613 /* hardware event handlers */
614 switch (cmd->type) {
615 case 0xc1: {
616 /*
617 * TX status notification:
618 * bytes: 0c c1 XX YY M1 M2 M3 M4 M5 M6 R4 R3 R2 R1 S2 S1
619 *
620 * XX always 81
621 * YY always 00
622 * M1-M6 is the MAC address
623 * R1-R4 is the transmit rate
624 * S1-S2 is the transmit status
625 */
626
627 struct sk_buff *skb;
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200628 u32 phy = le32_to_cpu(cmd->tx_status.rate);
629 u32 q = (phy & AR9170_TX_PHY_QOS_MASK) >>
630 AR9170_TX_PHY_QOS_SHIFT;
631#ifdef AR9170_QUEUE_DEBUG
632 printk(KERN_DEBUG "%s: recv tx_status for %pM, p:%08x, q:%d\n",
633 wiphy_name(ar->hw->wiphy), cmd->tx_status.dst, phy, q);
634#endif /* AR9170_QUEUE_DEBUG */
Christian Lampartere9348cd2009-03-21 23:05:13 +0100635
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200636 skb = ar9170_get_queued_skb(ar, cmd->tx_status.dst,
637 &ar->tx_status[q],
638 AR9170_TX_INVALID_RATE);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100639 if (unlikely(!skb))
640 return ;
641
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200642 ar9170_tx_status(ar, skb, le16_to_cpu(cmd->tx_status.status));
Christian Lampartere9348cd2009-03-21 23:05:13 +0100643 break;
644 }
645
646 case 0xc0:
647 /*
648 * pre-TBTT event
649 */
650 if (ar->vif && ar->vif->type == NL80211_IFTYPE_AP)
Luis R. Rodriguez42935ec2009-07-29 20:08:07 -0400651 ieee80211_queue_work(ar->hw, &ar->beacon_work);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100652 break;
653
654 case 0xc2:
655 /*
656 * (IBSS) beacon send notification
657 * bytes: 04 c2 XX YY B4 B3 B2 B1
658 *
659 * XX always 80
660 * YY always 00
661 * B1-B4 "should" be the number of send out beacons.
662 */
663 break;
664
665 case 0xc3:
666 /* End of Atim Window */
667 break;
668
669 case 0xc4:
Christian Lamparteracbadf02009-07-11 17:24:14 +0200670 /* BlockACK bitmap */
671 break;
672
Christian Lampartere9348cd2009-03-21 23:05:13 +0100673 case 0xc5:
674 /* BlockACK events */
Christian Lamparteracbadf02009-07-11 17:24:14 +0200675 ar9170_handle_block_ack(ar,
676 le16_to_cpu(cmd->ba_fail_cnt.failed),
677 le16_to_cpu(cmd->ba_fail_cnt.rate));
678 ar9170_tx_fake_ampdu_status(ar);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100679 break;
680
681 case 0xc6:
682 /* Watchdog Interrupt */
683 break;
684
685 case 0xc9:
686 /* retransmission issue / SIFS/EIFS collision ?! */
687 break;
688
Johannes Berg2543a0c2009-06-05 11:47:43 +0200689 /* firmware debug */
690 case 0xca:
691 printk(KERN_DEBUG "ar9170 FW: %.*s\n", len - 4, (char *)buf + 4);
692 break;
693 case 0xcb:
694 len -= 4;
695
696 switch (len) {
697 case 1:
698 printk(KERN_DEBUG "ar9170 FW: u8: %#.2x\n",
699 *((char *)buf + 4));
700 break;
701 case 2:
702 printk(KERN_DEBUG "ar9170 FW: u8: %#.4x\n",
703 le16_to_cpup((__le16 *)((char *)buf + 4)));
704 break;
705 case 4:
706 printk(KERN_DEBUG "ar9170 FW: u8: %#.8x\n",
707 le32_to_cpup((__le32 *)((char *)buf + 4)));
708 break;
709 case 8:
710 printk(KERN_DEBUG "ar9170 FW: u8: %#.16lx\n",
711 (unsigned long)le64_to_cpup(
712 (__le64 *)((char *)buf + 4)));
713 break;
714 }
715 break;
716 case 0xcc:
717 print_hex_dump_bytes("ar9170 FW:", DUMP_PREFIX_NONE,
718 (char *)buf + 4, len - 4);
719 break;
720
Christian Lampartere9348cd2009-03-21 23:05:13 +0100721 default:
722 printk(KERN_INFO "received unhandled event %x\n", cmd->type);
723 print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len);
724 break;
725 }
726}
727
Christian Lampartercca847992009-04-19 01:28:12 +0200728static void ar9170_rx_reset_rx_mpdu(struct ar9170 *ar)
Christian Lampartere9348cd2009-03-21 23:05:13 +0100729{
Christian Lampartercca847992009-04-19 01:28:12 +0200730 memset(&ar->rx_mpdu.plcp, 0, sizeof(struct ar9170_rx_head));
731 ar->rx_mpdu.has_plcp = false;
732}
Christian Lampartere9348cd2009-03-21 23:05:13 +0100733
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200734int ar9170_nag_limiter(struct ar9170 *ar)
Christian Lampartercca847992009-04-19 01:28:12 +0200735{
736 bool print_message;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100737
Christian Lampartercca847992009-04-19 01:28:12 +0200738 /*
739 * we expect all sorts of errors in promiscuous mode.
740 * don't bother with it, it's OK!
741 */
742 if (ar->sniffer_enabled)
743 return false;
744
745 /*
746 * only go for frequent errors! The hardware tends to
747 * do some stupid thing once in a while under load, in
748 * noisy environments or just for fun!
749 */
750 if (time_before(jiffies, ar->bad_hw_nagger) && net_ratelimit())
751 print_message = true;
752 else
753 print_message = false;
754
755 /* reset threshold for "once in a while" */
756 ar->bad_hw_nagger = jiffies + HZ / 4;
757 return print_message;
758}
759
760static int ar9170_rx_mac_status(struct ar9170 *ar,
761 struct ar9170_rx_head *head,
762 struct ar9170_rx_macstatus *mac,
763 struct ieee80211_rx_status *status)
764{
765 u8 error, decrypt;
766
Christian Lampartere9348cd2009-03-21 23:05:13 +0100767 BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != 12);
Christian Lampartercca847992009-04-19 01:28:12 +0200768 BUILD_BUG_ON(sizeof(struct ar9170_rx_macstatus) != 4);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100769
Christian Lampartercca847992009-04-19 01:28:12 +0200770 error = mac->error;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100771 if (error & AR9170_RX_ERROR_MMIC) {
Christian Lampartercca847992009-04-19 01:28:12 +0200772 status->flag |= RX_FLAG_MMIC_ERROR;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100773 error &= ~AR9170_RX_ERROR_MMIC;
774 }
775
776 if (error & AR9170_RX_ERROR_PLCP) {
Christian Lampartercca847992009-04-19 01:28:12 +0200777 status->flag |= RX_FLAG_FAILED_PLCP_CRC;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100778 error &= ~AR9170_RX_ERROR_PLCP;
Christian Lampartercca847992009-04-19 01:28:12 +0200779
780 if (!(ar->filter_state & FIF_PLCPFAIL))
781 return -EINVAL;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100782 }
783
784 if (error & AR9170_RX_ERROR_FCS) {
Christian Lampartercca847992009-04-19 01:28:12 +0200785 status->flag |= RX_FLAG_FAILED_FCS_CRC;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100786 error &= ~AR9170_RX_ERROR_FCS;
Christian Lampartercca847992009-04-19 01:28:12 +0200787
788 if (!(ar->filter_state & FIF_FCSFAIL))
789 return -EINVAL;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100790 }
791
Christian Lampartercca847992009-04-19 01:28:12 +0200792 decrypt = ar9170_get_decrypt_type(mac);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100793 if (!(decrypt & AR9170_RX_ENC_SOFTWARE) &&
794 decrypt != AR9170_ENC_ALG_NONE)
Christian Lampartercca847992009-04-19 01:28:12 +0200795 status->flag |= RX_FLAG_DECRYPTED;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100796
797 /* ignore wrong RA errors */
798 error &= ~AR9170_RX_ERROR_WRONG_RA;
799
800 if (error & AR9170_RX_ERROR_DECRYPT) {
801 error &= ~AR9170_RX_ERROR_DECRYPT;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100802 /*
803 * Rx decryption is done in place,
804 * the original data is lost anyway.
805 */
Christian Lampartercca847992009-04-19 01:28:12 +0200806
807 return -EINVAL;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100808 }
809
810 /* drop any other error frames */
Christian Lampartercca847992009-04-19 01:28:12 +0200811 if (unlikely(error)) {
812 /* TODO: update netdevice's RX dropped/errors statistics */
813
814 if (ar9170_nag_limiter(ar))
815 printk(KERN_DEBUG "%s: received frame with "
816 "suspicious error code (%#x).\n",
817 wiphy_name(ar->hw->wiphy), error);
818
819 return -EINVAL;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100820 }
821
Christian Lampartercca847992009-04-19 01:28:12 +0200822 status->band = ar->channel->band;
823 status->freq = ar->channel->center_freq;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100824
Christian Lampartercca847992009-04-19 01:28:12 +0200825 switch (mac->status & AR9170_RX_STATUS_MODULATION_MASK) {
826 case AR9170_RX_STATUS_MODULATION_CCK:
827 if (mac->status & AR9170_RX_STATUS_SHORT_PREAMBLE)
828 status->flag |= RX_FLAG_SHORTPRE;
829 switch (head->plcp[0]) {
830 case 0x0a:
831 status->rate_idx = 0;
832 break;
833 case 0x14:
834 status->rate_idx = 1;
835 break;
836 case 0x37:
837 status->rate_idx = 2;
838 break;
839 case 0x6e:
840 status->rate_idx = 3;
841 break;
842 default:
843 if (ar9170_nag_limiter(ar))
844 printk(KERN_ERR "%s: invalid plcp cck rate "
845 "(%x).\n", wiphy_name(ar->hw->wiphy),
846 head->plcp[0]);
847 return -EINVAL;
848 }
849 break;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100850
Christian Lamparter7d57b732009-11-14 00:57:58 +0100851 case AR9170_RX_STATUS_MODULATION_DUPOFDM:
Christian Lampartercca847992009-04-19 01:28:12 +0200852 case AR9170_RX_STATUS_MODULATION_OFDM:
853 switch (head->plcp[0] & 0xf) {
854 case 0xb:
855 status->rate_idx = 0;
856 break;
857 case 0xf:
858 status->rate_idx = 1;
859 break;
860 case 0xa:
861 status->rate_idx = 2;
862 break;
863 case 0xe:
864 status->rate_idx = 3;
865 break;
866 case 0x9:
867 status->rate_idx = 4;
868 break;
869 case 0xd:
870 status->rate_idx = 5;
871 break;
872 case 0x8:
873 status->rate_idx = 6;
874 break;
875 case 0xc:
876 status->rate_idx = 7;
877 break;
878 default:
879 if (ar9170_nag_limiter(ar))
880 printk(KERN_ERR "%s: invalid plcp ofdm rate "
881 "(%x).\n", wiphy_name(ar->hw->wiphy),
882 head->plcp[0]);
883 return -EINVAL;
884 }
885 if (status->band == IEEE80211_BAND_2GHZ)
886 status->rate_idx += 4;
887 break;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100888
Christian Lampartercca847992009-04-19 01:28:12 +0200889 case AR9170_RX_STATUS_MODULATION_HT:
890 if (head->plcp[3] & 0x80)
891 status->flag |= RX_FLAG_40MHZ;
892 if (head->plcp[6] & 0x80)
893 status->flag |= RX_FLAG_SHORT_GI;
894
895 status->rate_idx = clamp(0, 75, head->plcp[6] & 0x7f);
896 status->flag |= RX_FLAG_HT;
897 break;
898
Christian Lamparter7d57b732009-11-14 00:57:58 +0100899 default:
Christian Lampartercca847992009-04-19 01:28:12 +0200900 if (ar9170_nag_limiter(ar))
901 printk(KERN_ERR "%s: invalid modulation\n",
902 wiphy_name(ar->hw->wiphy));
903 return -EINVAL;
904 }
905
906 return 0;
907}
908
909static void ar9170_rx_phy_status(struct ar9170 *ar,
910 struct ar9170_rx_phystatus *phy,
911 struct ieee80211_rx_status *status)
912{
913 int i;
914
915 BUILD_BUG_ON(sizeof(struct ar9170_rx_phystatus) != 20);
916
917 for (i = 0; i < 3; i++)
918 if (phy->rssi[i] != 0x80)
919 status->antenna |= BIT(i);
920
921 /* post-process RSSI */
922 for (i = 0; i < 7; i++)
923 if (phy->rssi[i] & 0x80)
924 phy->rssi[i] = ((phy->rssi[i] & 0x7f) + 1) & 0x7f;
925
926 /* TODO: we could do something with phy_errors */
927 status->signal = ar->noise[0] + phy->rssi_combined;
928 status->noise = ar->noise[0];
929}
930
931static struct sk_buff *ar9170_rx_copy_data(u8 *buf, int len)
932{
933 struct sk_buff *skb;
934 int reserved = 0;
935 struct ieee80211_hdr *hdr = (void *) buf;
936
937 if (ieee80211_is_data_qos(hdr->frame_control)) {
938 u8 *qc = ieee80211_get_qos_ctl(hdr);
939 reserved += NET_IP_ALIGN;
940
941 if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
942 reserved += NET_IP_ALIGN;
943 }
944
945 if (ieee80211_has_a4(hdr->frame_control))
946 reserved += NET_IP_ALIGN;
947
948 reserved = 32 + (reserved & NET_IP_ALIGN);
949
950 skb = dev_alloc_skb(len + reserved);
951 if (likely(skb)) {
952 skb_reserve(skb, reserved);
953 memcpy(skb_put(skb, len), buf, len);
954 }
955
956 return skb;
957}
958
959/*
960 * If the frame alignment is right (or the kernel has
961 * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there
962 * is only a single MPDU in the USB frame, then we could
963 * submit to mac80211 the SKB directly. However, since
964 * there may be multiple packets in one SKB in stream
965 * mode, and we need to observe the proper ordering,
966 * this is non-trivial.
967 */
968
969static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
970{
971 struct ar9170_rx_head *head;
972 struct ar9170_rx_macstatus *mac;
973 struct ar9170_rx_phystatus *phy = NULL;
974 struct ieee80211_rx_status status;
975 struct sk_buff *skb;
976 int mpdu_len;
977
978 if (unlikely(!IS_STARTED(ar) || len < (sizeof(*mac))))
979 return ;
980
981 /* Received MPDU */
982 mpdu_len = len - sizeof(*mac);
983
984 mac = (void *)(buf + mpdu_len);
985 if (unlikely(mac->error & AR9170_RX_ERROR_FATAL)) {
986 /* this frame is too damaged and can't be used - drop it */
987
988 return ;
989 }
990
991 switch (mac->status & AR9170_RX_STATUS_MPDU_MASK) {
992 case AR9170_RX_STATUS_MPDU_FIRST:
993 /* first mpdu packet has the plcp header */
994 if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) {
995 head = (void *) buf;
996 memcpy(&ar->rx_mpdu.plcp, (void *) buf,
997 sizeof(struct ar9170_rx_head));
998
999 mpdu_len -= sizeof(struct ar9170_rx_head);
1000 buf += sizeof(struct ar9170_rx_head);
1001 ar->rx_mpdu.has_plcp = true;
1002 } else {
1003 if (ar9170_nag_limiter(ar))
1004 printk(KERN_ERR "%s: plcp info is clipped.\n",
1005 wiphy_name(ar->hw->wiphy));
1006 return ;
1007 }
1008 break;
1009
1010 case AR9170_RX_STATUS_MPDU_LAST:
1011 /* last mpdu has a extra tail with phy status information */
1012
1013 if (likely(mpdu_len >= sizeof(struct ar9170_rx_phystatus))) {
1014 mpdu_len -= sizeof(struct ar9170_rx_phystatus);
1015 phy = (void *)(buf + mpdu_len);
1016 } else {
1017 if (ar9170_nag_limiter(ar))
1018 printk(KERN_ERR "%s: frame tail is clipped.\n",
1019 wiphy_name(ar->hw->wiphy));
1020 return ;
1021 }
1022
1023 case AR9170_RX_STATUS_MPDU_MIDDLE:
1024 /* middle mpdus are just data */
1025 if (unlikely(!ar->rx_mpdu.has_plcp)) {
1026 if (!ar9170_nag_limiter(ar))
1027 return ;
1028
1029 printk(KERN_ERR "%s: rx stream did not start "
1030 "with a first_mpdu frame tag.\n",
1031 wiphy_name(ar->hw->wiphy));
1032
1033 return ;
1034 }
1035
1036 head = &ar->rx_mpdu.plcp;
1037 break;
1038
1039 case AR9170_RX_STATUS_MPDU_SINGLE:
1040 /* single mpdu - has plcp (head) and phy status (tail) */
1041 head = (void *) buf;
1042
1043 mpdu_len -= sizeof(struct ar9170_rx_head);
1044 mpdu_len -= sizeof(struct ar9170_rx_phystatus);
1045
1046 buf += sizeof(struct ar9170_rx_head);
1047 phy = (void *)(buf + mpdu_len);
1048 break;
1049
1050 default:
1051 BUG_ON(1);
1052 break;
1053 }
1054
1055 if (unlikely(mpdu_len < FCS_LEN))
1056 return ;
1057
1058 memset(&status, 0, sizeof(status));
1059 if (unlikely(ar9170_rx_mac_status(ar, head, mac, &status)))
1060 return ;
1061
1062 if (phy)
1063 ar9170_rx_phy_status(ar, phy, &status);
1064
1065 skb = ar9170_rx_copy_data(buf, mpdu_len);
Johannes Bergf1d58c22009-06-17 13:13:00 +02001066 if (likely(skb)) {
1067 memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
1068 ieee80211_rx_irqsafe(ar->hw, skb);
1069 }
Christian Lampartere9348cd2009-03-21 23:05:13 +01001070}
1071
Christian Lampartere9348cd2009-03-21 23:05:13 +01001072void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb)
1073{
Christian Lampartercca847992009-04-19 01:28:12 +02001074 unsigned int i, tlen, resplen, wlen = 0, clen = 0;
Christian Lampartere9348cd2009-03-21 23:05:13 +01001075 u8 *tbuf, *respbuf;
1076
1077 tbuf = skb->data;
1078 tlen = skb->len;
1079
1080 while (tlen >= 4) {
Christian Lampartercca847992009-04-19 01:28:12 +02001081 clen = tbuf[1] << 8 | tbuf[0];
1082 wlen = ALIGN(clen, 4);
Christian Lampartere9348cd2009-03-21 23:05:13 +01001083
Christian Lampartercca847992009-04-19 01:28:12 +02001084 /* check if this is stream has a valid tag.*/
Christian Lampartere9348cd2009-03-21 23:05:13 +01001085 if (tbuf[2] != 0 || tbuf[3] != 0x4e) {
Christian Lampartercca847992009-04-19 01:28:12 +02001086 /*
1087 * TODO: handle the highly unlikely event that the
1088 * corrupted stream has the TAG at the right position.
1089 */
1090
1091 /* check if the frame can be repaired. */
1092 if (!ar->rx_failover_missing) {
1093 /* this is no "short read". */
1094 if (ar9170_nag_limiter(ar)) {
1095 printk(KERN_ERR "%s: missing tag!\n",
1096 wiphy_name(ar->hw->wiphy));
1097 goto err_telluser;
1098 } else
1099 goto err_silent;
1100 }
1101
1102 if (ar->rx_failover_missing > tlen) {
1103 if (ar9170_nag_limiter(ar)) {
1104 printk(KERN_ERR "%s: possible multi "
1105 "stream corruption!\n",
1106 wiphy_name(ar->hw->wiphy));
1107 goto err_telluser;
1108 } else
1109 goto err_silent;
1110 }
1111
1112 memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen);
1113 ar->rx_failover_missing -= tlen;
1114
1115 if (ar->rx_failover_missing <= 0) {
1116 /*
1117 * nested ar9170_rx call!
1118 * termination is guranteed, even when the
1119 * combined frame also have a element with
1120 * a bad tag.
1121 */
1122
1123 ar->rx_failover_missing = 0;
1124 ar9170_rx(ar, ar->rx_failover);
1125
1126 skb_reset_tail_pointer(ar->rx_failover);
1127 skb_trim(ar->rx_failover, 0);
1128 }
1129
Christian Lampartere9348cd2009-03-21 23:05:13 +01001130 return ;
1131 }
Christian Lampartercca847992009-04-19 01:28:12 +02001132
1133 /* check if stream is clipped */
Christian Lampartere9348cd2009-03-21 23:05:13 +01001134 if (wlen > tlen - 4) {
Christian Lampartercca847992009-04-19 01:28:12 +02001135 if (ar->rx_failover_missing) {
1136 /* TODO: handle double stream corruption. */
1137 if (ar9170_nag_limiter(ar)) {
1138 printk(KERN_ERR "%s: double rx stream "
1139 "corruption!\n",
1140 wiphy_name(ar->hw->wiphy));
1141 goto err_telluser;
1142 } else
1143 goto err_silent;
1144 }
1145
1146 /*
1147 * save incomplete data set.
1148 * the firmware will resend the missing bits when
1149 * the rx - descriptor comes round again.
1150 */
1151
1152 memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen);
1153 ar->rx_failover_missing = clen - tlen;
Christian Lampartere9348cd2009-03-21 23:05:13 +01001154 return ;
1155 }
1156 resplen = clen;
1157 respbuf = tbuf + 4;
1158 tbuf += wlen + 4;
1159 tlen -= wlen + 4;
1160
1161 i = 0;
1162
1163 /* weird thing, but this is the same in the original driver */
1164 while (resplen > 2 && i < 12 &&
1165 respbuf[0] == 0xff && respbuf[1] == 0xff) {
1166 i += 2;
1167 resplen -= 2;
1168 respbuf += 2;
1169 }
1170
1171 if (resplen < 4)
1172 continue;
1173
1174 /* found the 6 * 0xffff marker? */
1175 if (i == 12)
1176 ar9170_handle_command_response(ar, respbuf, resplen);
1177 else
Christian Lampartercca847992009-04-19 01:28:12 +02001178 ar9170_handle_mpdu(ar, respbuf, clen);
Christian Lampartere9348cd2009-03-21 23:05:13 +01001179 }
1180
Christian Lampartercca847992009-04-19 01:28:12 +02001181 if (tlen) {
1182 if (net_ratelimit())
1183 printk(KERN_ERR "%s: %d bytes of unprocessed "
1184 "data left in rx stream!\n",
1185 wiphy_name(ar->hw->wiphy), tlen);
1186
1187 goto err_telluser;
1188 }
1189
1190 return ;
1191
1192err_telluser:
1193 printk(KERN_ERR "%s: damaged RX stream data [want:%d, "
1194 "data:%d, rx:%d, pending:%d ]\n",
1195 wiphy_name(ar->hw->wiphy), clen, wlen, tlen,
1196 ar->rx_failover_missing);
1197
1198 if (ar->rx_failover_missing)
1199 print_hex_dump_bytes("rxbuf:", DUMP_PREFIX_OFFSET,
1200 ar->rx_failover->data,
1201 ar->rx_failover->len);
1202
1203 print_hex_dump_bytes("stream:", DUMP_PREFIX_OFFSET,
1204 skb->data, skb->len);
1205
1206 printk(KERN_ERR "%s: please check your hardware and cables, if "
1207 "you see this message frequently.\n",
1208 wiphy_name(ar->hw->wiphy));
1209
1210err_silent:
1211 if (ar->rx_failover_missing) {
1212 skb_reset_tail_pointer(ar->rx_failover);
1213 skb_trim(ar->rx_failover, 0);
1214 ar->rx_failover_missing = 0;
1215 }
Christian Lampartere9348cd2009-03-21 23:05:13 +01001216}
Christian Lampartere9348cd2009-03-21 23:05:13 +01001217
1218#define AR9170_FILL_QUEUE(queue, ai_fs, cwmin, cwmax, _txop) \
1219do { \
1220 queue.aifs = ai_fs; \
1221 queue.cw_min = cwmin; \
1222 queue.cw_max = cwmax; \
1223 queue.txop = _txop; \
1224} while (0)
1225
1226static int ar9170_op_start(struct ieee80211_hw *hw)
1227{
1228 struct ar9170 *ar = hw->priv;
1229 int err, i;
1230
1231 mutex_lock(&ar->mutex);
1232
1233 /* reinitialize queues statistics */
1234 memset(&ar->tx_stats, 0, sizeof(ar->tx_stats));
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001235 for (i = 0; i < __AR9170_NUM_TXQ; i++)
1236 ar->tx_stats[i].limit = AR9170_TXQ_DEPTH;
Christian Lampartere9348cd2009-03-21 23:05:13 +01001237
1238 /* reset QoS defaults */
1239 AR9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023, 0); /* BEST EFFORT*/
1240 AR9170_FILL_QUEUE(ar->edcf[1], 7, 15, 1023, 0); /* BACKGROUND */
1241 AR9170_FILL_QUEUE(ar->edcf[2], 2, 7, 15, 94); /* VIDEO */
1242 AR9170_FILL_QUEUE(ar->edcf[3], 2, 3, 7, 47); /* VOICE */
1243 AR9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */
1244
Christian Lamparteracbadf02009-07-11 17:24:14 +02001245 /* set sane AMPDU defaults */
1246 ar->global_ampdu_density = 6;
1247 ar->global_ampdu_factor = 3;
1248
Christian Lamparter02bdf5b2009-10-17 21:56:43 +02001249 atomic_set(&ar->tx_ampdu_pending, 0);
Christian Lampartercca847992009-04-19 01:28:12 +02001250 ar->bad_hw_nagger = jiffies;
1251
Christian Lampartere9348cd2009-03-21 23:05:13 +01001252 err = ar->open(ar);
1253 if (err)
1254 goto out;
1255
1256 err = ar9170_init_mac(ar);
1257 if (err)
1258 goto out;
1259
1260 err = ar9170_set_qos(ar);
1261 if (err)
1262 goto out;
1263
1264 err = ar9170_init_phy(ar, IEEE80211_BAND_2GHZ);
1265 if (err)
1266 goto out;
1267
1268 err = ar9170_init_rf(ar);
1269 if (err)
1270 goto out;
1271
1272 /* start DMA */
1273 err = ar9170_write_reg(ar, 0x1c3d30, 0x100);
1274 if (err)
1275 goto out;
1276
1277 ar->state = AR9170_STARTED;
1278
1279out:
1280 mutex_unlock(&ar->mutex);
1281 return err;
1282}
1283
1284static void ar9170_op_stop(struct ieee80211_hw *hw)
1285{
1286 struct ar9170 *ar = hw->priv;
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001287 unsigned int i;
Christian Lampartere9348cd2009-03-21 23:05:13 +01001288
1289 if (IS_STARTED(ar))
1290 ar->state = AR9170_IDLE;
1291
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001292 cancel_delayed_work_sync(&ar->tx_janitor);
Alexander Beregalovff8365c2009-07-24 11:55:44 +04001293#ifdef CONFIG_AR9170_LEDS
Christian Lamparteracbadf02009-07-11 17:24:14 +02001294 cancel_delayed_work_sync(&ar->led_work);
Alexander Beregalovff8365c2009-07-24 11:55:44 +04001295#endif
Christian Lampartere9348cd2009-03-21 23:05:13 +01001296 cancel_work_sync(&ar->beacon_work);
Luis R. Rodrigueze351cfb2009-07-27 12:51:37 -07001297
Christian Lamparterb55d6bc2009-05-23 20:31:21 +02001298 mutex_lock(&ar->mutex);
Christian Lampartere9348cd2009-03-21 23:05:13 +01001299
1300 if (IS_ACCEPTING_CMD(ar)) {
1301 ar9170_set_leds_state(ar, 0);
1302
1303 /* stop DMA */
1304 ar9170_write_reg(ar, 0x1c3d30, 0);
1305 ar->stop(ar);
1306 }
1307
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001308 for (i = 0; i < __AR9170_NUM_TXQ; i++) {
1309 skb_queue_purge(&ar->tx_pending[i]);
1310 skb_queue_purge(&ar->tx_status[i]);
1311 }
Christian Lamparteracbadf02009-07-11 17:24:14 +02001312 skb_queue_purge(&ar->tx_status_ampdu);
1313
Christian Lampartere9348cd2009-03-21 23:05:13 +01001314 mutex_unlock(&ar->mutex);
1315}
1316
Christian Lamparteracbadf02009-07-11 17:24:14 +02001317static void ar9170_tx_indicate_immba(struct ar9170 *ar, struct sk_buff *skb)
1318{
1319 struct ar9170_tx_control *txc = (void *) skb->data;
1320
1321 txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_IMM_AMPDU);
1322}
1323
1324static void ar9170_tx_copy_phy(struct ar9170 *ar, struct sk_buff *dst,
1325 struct sk_buff *src)
1326{
1327 struct ar9170_tx_control *dst_txc, *src_txc;
1328 struct ieee80211_tx_info *dst_info, *src_info;
1329 struct ar9170_tx_info *dst_arinfo, *src_arinfo;
1330
1331 src_txc = (void *) src->data;
1332 src_info = IEEE80211_SKB_CB(src);
1333 src_arinfo = (void *) src_info->rate_driver_data;
1334
1335 dst_txc = (void *) dst->data;
1336 dst_info = IEEE80211_SKB_CB(dst);
1337 dst_arinfo = (void *) dst_info->rate_driver_data;
1338
1339 dst_txc->phy_control = src_txc->phy_control;
1340
1341 /* same MCS for the whole aggregate */
1342 memcpy(dst_info->driver_rates, src_info->driver_rates,
1343 sizeof(dst_info->driver_rates));
1344}
1345
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001346static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
Christian Lampartere9348cd2009-03-21 23:05:13 +01001347{
Christian Lampartere9348cd2009-03-21 23:05:13 +01001348 struct ieee80211_hdr *hdr;
1349 struct ar9170_tx_control *txc;
1350 struct ieee80211_tx_info *info;
Christian Lampartere9348cd2009-03-21 23:05:13 +01001351 struct ieee80211_tx_rate *txrate;
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001352 struct ar9170_tx_info *arinfo;
Christian Lampartere9348cd2009-03-21 23:05:13 +01001353 unsigned int queue = skb_get_queue_mapping(skb);
Christian Lampartere9348cd2009-03-21 23:05:13 +01001354 u16 keytype = 0;
1355 u16 len, icv = 0;
Christian Lampartere9348cd2009-03-21 23:05:13 +01001356
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001357 BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data));
Christian Lampartere9348cd2009-03-21 23:05:13 +01001358
1359 hdr = (void *)skb->data;
1360 info = IEEE80211_SKB_CB(skb);
1361 len = skb->len;
1362
Christian Lampartere9348cd2009-03-21 23:05:13 +01001363 txc = (void *)skb_push(skb, sizeof(*txc));
1364
Christian Lampartere9348cd2009-03-21 23:05:13 +01001365 if (info->control.hw_key) {
1366 icv = info->control.hw_key->icv_len;
1367
1368 switch (info->control.hw_key->alg) {
1369 case ALG_WEP:
1370 keytype = AR9170_TX_MAC_ENCR_RC4;
1371 break;
1372 case ALG_TKIP:
1373 keytype = AR9170_TX_MAC_ENCR_RC4;
1374 break;
1375 case ALG_CCMP:
1376 keytype = AR9170_TX_MAC_ENCR_AES;
1377 break;
1378 default:
1379 WARN_ON(1);
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001380 goto err_out;
Christian Lampartere9348cd2009-03-21 23:05:13 +01001381 }
1382 }
1383
1384 /* Length */
1385 txc->length = cpu_to_le16(len + icv + 4);
1386
1387 txc->mac_control = cpu_to_le16(AR9170_TX_MAC_HW_DURATION |
1388 AR9170_TX_MAC_BACKOFF);
1389 txc->mac_control |= cpu_to_le16(ar9170_qos_hwmap[queue] <<
1390 AR9170_TX_MAC_QOS_SHIFT);
1391 txc->mac_control |= cpu_to_le16(keytype);
1392 txc->phy_control = cpu_to_le32(0);
1393
1394 if (info->flags & IEEE80211_TX_CTL_NO_ACK)
1395 txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_NO_ACK);
1396
Christian Lampartere9348cd2009-03-21 23:05:13 +01001397 txrate = &info->control.rates[0];
Christian Lampartere9348cd2009-03-21 23:05:13 +01001398 if (txrate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
1399 txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS);
1400 else if (txrate->flags & IEEE80211_TX_RC_USE_RTS_CTS)
1401 txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS);
1402
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001403 arinfo = (void *)info->rate_driver_data;
1404 arinfo->timeout = jiffies + msecs_to_jiffies(AR9170_QUEUE_TIMEOUT);
1405
1406 if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
1407 (is_valid_ether_addr(ieee80211_get_DA(hdr)))) {
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001408 /*
1409 * WARNING:
1410 * Putting the QoS queue bits into an unexplored territory is
1411 * certainly not elegant.
1412 *
1413 * In my defense: This idea provides a reasonable way to
1414 * smuggle valuable information to the tx_status callback.
1415 * Also, the idea behind this bit-abuse came straight from
1416 * the original driver code.
1417 */
1418
1419 txc->phy_control |=
1420 cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT);
Christian Lamparter15b098b2009-11-29 00:56:55 +01001421
1422 if (info->flags & IEEE80211_TX_CTL_AMPDU) {
1423 if (unlikely(!info->control.sta))
1424 goto err_out;
1425
1426 txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR);
1427 } else {
1428 txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE);
1429 }
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001430 }
1431
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001432 return 0;
1433
1434err_out:
1435 skb_pull(skb, sizeof(*txc));
1436 return -EINVAL;
1437}
1438
1439static void ar9170_tx_prepare_phy(struct ar9170 *ar, struct sk_buff *skb)
1440{
1441 struct ar9170_tx_control *txc;
1442 struct ieee80211_tx_info *info;
1443 struct ieee80211_rate *rate = NULL;
1444 struct ieee80211_tx_rate *txrate;
1445 u32 power, chains;
1446
1447 txc = (void *) skb->data;
1448 info = IEEE80211_SKB_CB(skb);
1449 txrate = &info->control.rates[0];
1450
Christian Lampartere9348cd2009-03-21 23:05:13 +01001451 if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD)
1452 txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD);
1453
1454 if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
1455 txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE);
1456
1457 if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
1458 txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ);
1459 /* this works because 40 MHz is 2 and dup is 3 */
1460 if (txrate->flags & IEEE80211_TX_RC_DUP_DATA)
1461 txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ_DUP);
1462
1463 if (txrate->flags & IEEE80211_TX_RC_SHORT_GI)
1464 txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI);
1465
1466 if (txrate->flags & IEEE80211_TX_RC_MCS) {
1467 u32 r = txrate->idx;
1468 u8 *txpower;
1469
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001470 /* heavy clip control */
1471 txc->phy_control |= cpu_to_le32((r & 0x7) << 7);
1472
Christian Lampartere9348cd2009-03-21 23:05:13 +01001473 r <<= AR9170_TX_PHY_MCS_SHIFT;
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001474 BUG_ON(r & ~AR9170_TX_PHY_MCS_MASK);
1475
Christian Lampartere9348cd2009-03-21 23:05:13 +01001476 txc->phy_control |= cpu_to_le32(r & AR9170_TX_PHY_MCS_MASK);
1477 txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_MOD_HT);
1478
1479 if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
1480 if (info->band == IEEE80211_BAND_5GHZ)
1481 txpower = ar->power_5G_ht40;
1482 else
1483 txpower = ar->power_2G_ht40;
1484 } else {
1485 if (info->band == IEEE80211_BAND_5GHZ)
1486 txpower = ar->power_5G_ht20;
1487 else
1488 txpower = ar->power_2G_ht20;
1489 }
1490
1491 power = txpower[(txrate->idx) & 7];
1492 } else {
1493 u8 *txpower;
1494 u32 mod;
1495 u32 phyrate;
1496 u8 idx = txrate->idx;
1497
1498 if (info->band != IEEE80211_BAND_2GHZ) {
1499 idx += 4;
1500 txpower = ar->power_5G_leg;
1501 mod = AR9170_TX_PHY_MOD_OFDM;
1502 } else {
1503 if (idx < 4) {
1504 txpower = ar->power_2G_cck;
1505 mod = AR9170_TX_PHY_MOD_CCK;
1506 } else {
1507 mod = AR9170_TX_PHY_MOD_OFDM;
1508 txpower = ar->power_2G_ofdm;
1509 }
1510 }
1511
1512 rate = &__ar9170_ratetable[idx];
1513
1514 phyrate = rate->hw_value & 0xF;
1515 power = txpower[(rate->hw_value & 0x30) >> 4];
1516 phyrate <<= AR9170_TX_PHY_MCS_SHIFT;
1517
1518 txc->phy_control |= cpu_to_le32(mod);
1519 txc->phy_control |= cpu_to_le32(phyrate);
1520 }
1521
1522 power <<= AR9170_TX_PHY_TX_PWR_SHIFT;
1523 power &= AR9170_TX_PHY_TX_PWR_MASK;
1524 txc->phy_control |= cpu_to_le32(power);
1525
1526 /* set TX chains */
1527 if (ar->eeprom.tx_mask == 1) {
1528 chains = AR9170_TX_PHY_TXCHAIN_1;
1529 } else {
1530 chains = AR9170_TX_PHY_TXCHAIN_2;
1531
1532 /* >= 36M legacy OFDM - use only one chain */
1533 if (rate && rate->bitrate >= 360)
1534 chains = AR9170_TX_PHY_TXCHAIN_1;
1535 }
1536 txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT);
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001537}
Christian Lampartere9348cd2009-03-21 23:05:13 +01001538
Christian Lamparteracbadf02009-07-11 17:24:14 +02001539static bool ar9170_tx_ampdu(struct ar9170 *ar)
1540{
1541 struct sk_buff_head agg;
1542 struct ar9170_sta_tid *tid_info = NULL, *tmp;
1543 struct sk_buff *skb, *first = NULL;
1544 unsigned long flags, f2;
1545 unsigned int i = 0;
1546 u16 seq, queue, tmpssn;
1547 bool run = false;
1548
1549 skb_queue_head_init(&agg);
1550
1551 spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
1552 if (list_empty(&ar->tx_ampdu_list)) {
1553#ifdef AR9170_TXAGG_DEBUG
1554 printk(KERN_DEBUG "%s: aggregation list is empty.\n",
1555 wiphy_name(ar->hw->wiphy));
1556#endif /* AR9170_TXAGG_DEBUG */
1557 goto out_unlock;
1558 }
1559
1560 list_for_each_entry_safe(tid_info, tmp, &ar->tx_ampdu_list, list) {
1561 if (tid_info->state != AR9170_TID_STATE_COMPLETE) {
1562#ifdef AR9170_TXAGG_DEBUG
1563 printk(KERN_DEBUG "%s: dangling aggregation entry!\n",
1564 wiphy_name(ar->hw->wiphy));
1565#endif /* AR9170_TXAGG_DEBUG */
1566 continue;
1567 }
1568
1569 if (++i > 64) {
1570#ifdef AR9170_TXAGG_DEBUG
1571 printk(KERN_DEBUG "%s: enough frames aggregated.\n",
1572 wiphy_name(ar->hw->wiphy));
1573#endif /* AR9170_TXAGG_DEBUG */
1574 break;
1575 }
1576
1577 queue = TID_TO_WME_AC(tid_info->tid);
1578
1579 if (skb_queue_len(&ar->tx_pending[queue]) >=
1580 AR9170_NUM_TX_AGG_MAX) {
1581#ifdef AR9170_TXAGG_DEBUG
1582 printk(KERN_DEBUG "%s: queue %d full.\n",
1583 wiphy_name(ar->hw->wiphy), queue);
1584#endif /* AR9170_TXAGG_DEBUG */
1585 continue;
1586 }
1587
1588 list_del_init(&tid_info->list);
1589
1590 spin_lock_irqsave(&tid_info->queue.lock, f2);
1591 tmpssn = seq = tid_info->ssn;
1592 first = skb_peek(&tid_info->queue);
1593
1594 if (likely(first))
1595 tmpssn = ar9170_get_seq(first);
1596
1597 if (unlikely(tmpssn != seq)) {
1598#ifdef AR9170_TXAGG_DEBUG
1599 printk(KERN_DEBUG "%s: ssn mismatch [%d != %d]\n.",
1600 wiphy_name(ar->hw->wiphy), seq, tmpssn);
1601#endif /* AR9170_TXAGG_DEBUG */
1602 tid_info->ssn = tmpssn;
1603 }
1604
1605#ifdef AR9170_TXAGG_DEBUG
1606 printk(KERN_DEBUG "%s: generate A-MPDU for tid:%d ssn:%d with "
1607 "%d queued frames.\n", wiphy_name(ar->hw->wiphy),
1608 tid_info->tid, tid_info->ssn,
1609 skb_queue_len(&tid_info->queue));
1610 __ar9170_dump_txqueue(ar, &tid_info->queue);
1611#endif /* AR9170_TXAGG_DEBUG */
1612
1613 while ((skb = skb_peek(&tid_info->queue))) {
1614 if (unlikely(ar9170_get_seq(skb) != seq))
1615 break;
1616
1617 __skb_unlink(skb, &tid_info->queue);
1618 tid_info->ssn = seq = GET_NEXT_SEQ(seq);
1619
1620 if (unlikely(skb_get_queue_mapping(skb) != queue)) {
1621#ifdef AR9170_TXAGG_DEBUG
1622 printk(KERN_DEBUG "%s: tid:%d(q:%d) queue:%d "
1623 "!match.\n", wiphy_name(ar->hw->wiphy),
1624 tid_info->tid,
1625 TID_TO_WME_AC(tid_info->tid),
1626 skb_get_queue_mapping(skb));
1627#endif /* AR9170_TXAGG_DEBUG */
1628 dev_kfree_skb_any(skb);
1629 continue;
1630 }
1631
1632 if (unlikely(first == skb)) {
1633 ar9170_tx_prepare_phy(ar, skb);
1634 __skb_queue_tail(&agg, skb);
1635 first = skb;
1636 } else {
1637 ar9170_tx_copy_phy(ar, skb, first);
1638 __skb_queue_tail(&agg, skb);
1639 }
1640
1641 if (unlikely(skb_queue_len(&agg) ==
1642 AR9170_NUM_TX_AGG_MAX))
1643 break;
1644 }
1645
1646 if (skb_queue_empty(&tid_info->queue))
1647 tid_info->active = false;
1648 else
1649 list_add_tail(&tid_info->list,
1650 &ar->tx_ampdu_list);
1651
1652 spin_unlock_irqrestore(&tid_info->queue.lock, f2);
1653
1654 if (unlikely(skb_queue_empty(&agg))) {
1655#ifdef AR9170_TXAGG_DEBUG
1656 printk(KERN_DEBUG "%s: queued empty list!\n",
1657 wiphy_name(ar->hw->wiphy));
1658#endif /* AR9170_TXAGG_DEBUG */
1659 continue;
1660 }
1661
1662 /*
1663 * tell the FW/HW that this is the last frame,
1664 * that way it will wait for the immediate block ack.
1665 */
Christian Lamparter07bc5452009-11-29 00:59:48 +01001666 ar9170_tx_indicate_immba(ar, skb_peek_tail(&agg));
Christian Lamparteracbadf02009-07-11 17:24:14 +02001667
1668#ifdef AR9170_TXAGG_DEBUG
1669 printk(KERN_DEBUG "%s: generated A-MPDU looks like this:\n",
1670 wiphy_name(ar->hw->wiphy));
1671 __ar9170_dump_txqueue(ar, &agg);
1672#endif /* AR9170_TXAGG_DEBUG */
1673
1674 spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
1675
1676 spin_lock_irqsave(&ar->tx_pending[queue].lock, flags);
1677 skb_queue_splice_tail_init(&agg, &ar->tx_pending[queue]);
1678 spin_unlock_irqrestore(&ar->tx_pending[queue].lock, flags);
1679 run = true;
1680
1681 spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
1682 }
1683
1684out_unlock:
1685 spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
1686 __skb_queue_purge(&agg);
1687
1688 return run;
1689}
1690
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001691static void ar9170_tx(struct ar9170 *ar)
1692{
1693 struct sk_buff *skb;
1694 unsigned long flags;
1695 struct ieee80211_tx_info *info;
1696 struct ar9170_tx_info *arinfo;
1697 unsigned int i, frames, frames_failed, remaining_space;
1698 int err;
1699 bool schedule_garbagecollector = false;
Christian Lampartere9348cd2009-03-21 23:05:13 +01001700
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001701 BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data));
Christian Lampartere9348cd2009-03-21 23:05:13 +01001702
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001703 if (unlikely(!IS_STARTED(ar)))
1704 return ;
Christian Lampartere9348cd2009-03-21 23:05:13 +01001705
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001706 remaining_space = AR9170_TX_MAX_PENDING;
1707
1708 for (i = 0; i < __AR9170_NUM_TXQ; i++) {
1709 spin_lock_irqsave(&ar->tx_stats_lock, flags);
Christian Lamparter53a76b52009-11-29 00:52:51 +01001710 frames = min(ar->tx_stats[i].limit - ar->tx_stats[i].len,
1711 skb_queue_len(&ar->tx_pending[i]));
1712
1713 if (remaining_space < frames) {
1714#ifdef AR9170_QUEUE_DEBUG
1715 printk(KERN_DEBUG "%s: tx quota reached queue:%d, "
1716 "remaining slots:%d, needed:%d\n",
1717 wiphy_name(ar->hw->wiphy), i, remaining_space,
1718 frames);
1719#endif /* AR9170_QUEUE_DEBUG */
1720 frames = remaining_space;
1721 }
1722
1723 ar->tx_stats[i].len += frames;
1724 ar->tx_stats[i].count += frames;
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001725 if (ar->tx_stats[i].len >= ar->tx_stats[i].limit) {
1726#ifdef AR9170_QUEUE_DEBUG
1727 printk(KERN_DEBUG "%s: queue %d full\n",
1728 wiphy_name(ar->hw->wiphy), i);
1729
Christian Lamparteracbadf02009-07-11 17:24:14 +02001730 printk(KERN_DEBUG "%s: stuck frames: ===> \n",
1731 wiphy_name(ar->hw->wiphy));
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001732 ar9170_dump_txqueue(ar, &ar->tx_pending[i]);
1733 ar9170_dump_txqueue(ar, &ar->tx_status[i]);
1734#endif /* AR9170_QUEUE_DEBUG */
Christian Lamparteracbadf02009-07-11 17:24:14 +02001735
1736#ifdef AR9170_QUEUE_STOP_DEBUG
1737 printk(KERN_DEBUG "%s: stop queue %d\n",
1738 wiphy_name(ar->hw->wiphy), i);
1739 __ar9170_dump_txstats(ar);
1740#endif /* AR9170_QUEUE_STOP_DEBUG */
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001741 ieee80211_stop_queue(ar->hw, i);
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001742 }
1743
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001744 spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
1745
1746 if (!frames)
1747 continue;
1748
1749 frames_failed = 0;
1750 while (frames) {
1751 skb = skb_dequeue(&ar->tx_pending[i]);
1752 if (unlikely(!skb)) {
1753 frames_failed += frames;
1754 frames = 0;
1755 break;
1756 }
1757
1758 info = IEEE80211_SKB_CB(skb);
1759 arinfo = (void *) info->rate_driver_data;
1760
1761 /* TODO: cancel stuck frames */
1762 arinfo->timeout = jiffies +
1763 msecs_to_jiffies(AR9170_TX_TIMEOUT);
1764
Christian Lamparter15b098b2009-11-29 00:56:55 +01001765 if (info->flags & IEEE80211_TX_CTL_AMPDU)
Christian Lamparter02bdf5b2009-10-17 21:56:43 +02001766 atomic_inc(&ar->tx_ampdu_pending);
Christian Lamparteracbadf02009-07-11 17:24:14 +02001767
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001768#ifdef AR9170_QUEUE_DEBUG
1769 printk(KERN_DEBUG "%s: send frame q:%d =>\n",
1770 wiphy_name(ar->hw->wiphy), i);
1771 ar9170_print_txheader(ar, skb);
1772#endif /* AR9170_QUEUE_DEBUG */
1773
1774 err = ar->tx(ar, skb);
1775 if (unlikely(err)) {
Christian Lamparter15b098b2009-11-29 00:56:55 +01001776 if (info->flags & IEEE80211_TX_CTL_AMPDU)
Christian Lamparter02bdf5b2009-10-17 21:56:43 +02001777 atomic_dec(&ar->tx_ampdu_pending);
Christian Lamparteracbadf02009-07-11 17:24:14 +02001778
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001779 frames_failed++;
1780 dev_kfree_skb_any(skb);
1781 } else {
1782 remaining_space--;
1783 schedule_garbagecollector = true;
1784 }
1785
1786 frames--;
1787 }
1788
1789#ifdef AR9170_QUEUE_DEBUG
1790 printk(KERN_DEBUG "%s: ar9170_tx report for queue %d\n",
1791 wiphy_name(ar->hw->wiphy), i);
1792
1793 printk(KERN_DEBUG "%s: unprocessed pending frames left:\n",
1794 wiphy_name(ar->hw->wiphy));
1795 ar9170_dump_txqueue(ar, &ar->tx_pending[i]);
1796#endif /* AR9170_QUEUE_DEBUG */
1797
1798 if (unlikely(frames_failed)) {
1799#ifdef AR9170_QUEUE_DEBUG
Christian Lamparteracbadf02009-07-11 17:24:14 +02001800 printk(KERN_DEBUG "%s: frames failed %d =>\n",
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001801 wiphy_name(ar->hw->wiphy), frames_failed);
1802#endif /* AR9170_QUEUE_DEBUG */
1803
1804 spin_lock_irqsave(&ar->tx_stats_lock, flags);
1805 ar->tx_stats[i].len -= frames_failed;
1806 ar->tx_stats[i].count -= frames_failed;
Christian Lamparteracbadf02009-07-11 17:24:14 +02001807#ifdef AR9170_QUEUE_STOP_DEBUG
1808 printk(KERN_DEBUG "%s: wake queue %d\n",
1809 wiphy_name(ar->hw->wiphy), i);
1810 __ar9170_dump_txstats(ar);
1811#endif /* AR9170_QUEUE_STOP_DEBUG */
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001812 ieee80211_wake_queue(ar->hw, i);
1813 spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
Christian Lampartere9348cd2009-03-21 23:05:13 +01001814 }
1815 }
1816
Luis R. Rodriguez42935ec2009-07-29 20:08:07 -04001817 if (!schedule_garbagecollector)
1818 return;
1819
1820 ieee80211_queue_delayed_work(ar->hw,
1821 &ar->tx_janitor,
1822 msecs_to_jiffies(AR9170_JANITOR_DELAY));
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001823}
1824
Christian Lamparteracbadf02009-07-11 17:24:14 +02001825static bool ar9170_tx_ampdu_queue(struct ar9170 *ar, struct sk_buff *skb)
1826{
1827 struct ieee80211_tx_info *txinfo;
1828 struct ar9170_sta_info *sta_info;
1829 struct ar9170_sta_tid *agg;
1830 struct sk_buff *iter;
1831 unsigned long flags, f2;
1832 unsigned int max;
1833 u16 tid, seq, qseq;
1834 bool run = false, queue = false;
1835
1836 tid = ar9170_get_tid(skb);
1837 seq = ar9170_get_seq(skb);
1838 txinfo = IEEE80211_SKB_CB(skb);
1839 sta_info = (void *) txinfo->control.sta->drv_priv;
1840 agg = &sta_info->agg[tid];
1841 max = sta_info->ampdu_max_len;
1842
1843 spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
1844
1845 if (unlikely(agg->state != AR9170_TID_STATE_COMPLETE)) {
1846#ifdef AR9170_TXAGG_DEBUG
1847 printk(KERN_DEBUG "%s: BlockACK session not fully initialized "
1848 "for ESS:%pM tid:%d state:%d.\n",
1849 wiphy_name(ar->hw->wiphy), agg->addr, agg->tid,
1850 agg->state);
1851#endif /* AR9170_TXAGG_DEBUG */
1852 goto err_unlock;
1853 }
1854
1855 if (!agg->active) {
1856 agg->active = true;
1857 agg->ssn = seq;
1858 queue = true;
1859 }
1860
1861 /* check if seq is within the BA window */
1862 if (unlikely(!BAW_WITHIN(agg->ssn, max, seq))) {
1863#ifdef AR9170_TXAGG_DEBUG
1864 printk(KERN_DEBUG "%s: frame with tid:%d seq:%d does not "
1865 "fit into BA window (%d - %d)\n",
1866 wiphy_name(ar->hw->wiphy), tid, seq, agg->ssn,
1867 (agg->ssn + max) & 0xfff);
1868#endif /* AR9170_TXAGG_DEBUG */
1869 goto err_unlock;
1870 }
1871
1872 spin_lock_irqsave(&agg->queue.lock, f2);
1873
1874 skb_queue_reverse_walk(&agg->queue, iter) {
1875 qseq = ar9170_get_seq(iter);
1876
1877 if (GET_NEXT_SEQ(qseq) == seq) {
1878 __skb_queue_after(&agg->queue, iter, skb);
1879 goto queued;
1880 }
1881 }
1882
1883 __skb_queue_head(&agg->queue, skb);
1884
1885queued:
1886 spin_unlock_irqrestore(&agg->queue.lock, f2);
1887
1888#ifdef AR9170_TXAGG_DEBUG
1889 printk(KERN_DEBUG "%s: new aggregate %p queued.\n",
1890 wiphy_name(ar->hw->wiphy), skb);
1891 __ar9170_dump_txqueue(ar, &agg->queue);
1892#endif /* AR9170_TXAGG_DEBUG */
1893
1894 if (skb_queue_len(&agg->queue) >= AR9170_NUM_TX_AGG_MAX)
1895 run = true;
1896
1897 if (queue)
1898 list_add_tail(&agg->list, &ar->tx_ampdu_list);
1899
1900 spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
1901 return run;
1902
1903err_unlock:
1904 spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
1905 dev_kfree_skb_irq(skb);
1906 return false;
1907}
1908
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001909int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
1910{
1911 struct ar9170 *ar = hw->priv;
1912 struct ieee80211_tx_info *info;
1913
1914 if (unlikely(!IS_STARTED(ar)))
1915 goto err_free;
1916
1917 if (unlikely(ar9170_tx_prepare(ar, skb)))
1918 goto err_free;
1919
1920 info = IEEE80211_SKB_CB(skb);
1921 if (info->flags & IEEE80211_TX_CTL_AMPDU) {
Christian Lamparteracbadf02009-07-11 17:24:14 +02001922 bool run = ar9170_tx_ampdu_queue(ar, skb);
1923
Christian Lamparter02bdf5b2009-10-17 21:56:43 +02001924 if (run || !atomic_read(&ar->tx_ampdu_pending))
Christian Lamparteracbadf02009-07-11 17:24:14 +02001925 ar9170_tx_ampdu(ar);
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001926 } else {
1927 unsigned int queue = skb_get_queue_mapping(skb);
1928
1929 ar9170_tx_prepare_phy(ar, skb);
1930 skb_queue_tail(&ar->tx_pending[queue], skb);
Christian Lampartere9348cd2009-03-21 23:05:13 +01001931 }
1932
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001933 ar9170_tx(ar);
Christian Lampartere9348cd2009-03-21 23:05:13 +01001934 return NETDEV_TX_OK;
1935
Christian Lampartere9348cd2009-03-21 23:05:13 +01001936err_free:
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001937 dev_kfree_skb_any(skb);
Christian Lampartere9348cd2009-03-21 23:05:13 +01001938 return NETDEV_TX_OK;
1939}
1940
1941static int ar9170_op_add_interface(struct ieee80211_hw *hw,
Johannes Berg1ed32e42009-12-23 13:15:45 +01001942 struct ieee80211_vif *vif)
Christian Lampartere9348cd2009-03-21 23:05:13 +01001943{
1944 struct ar9170 *ar = hw->priv;
Luis R. Rodriguez8c727e72009-09-10 10:10:54 -07001945 struct ath_common *common = &ar->common;
Christian Lampartere9348cd2009-03-21 23:05:13 +01001946 int err = 0;
1947
1948 mutex_lock(&ar->mutex);
1949
1950 if (ar->vif) {
1951 err = -EBUSY;
1952 goto unlock;
1953 }
1954
Johannes Berg1ed32e42009-12-23 13:15:45 +01001955 ar->vif = vif;
1956 memcpy(common->macaddr, vif->addr, ETH_ALEN);
Christian Lampartere9348cd2009-03-21 23:05:13 +01001957
1958 if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) {
1959 ar->rx_software_decryption = true;
1960 ar->disable_offload = true;
1961 }
1962
1963 ar->cur_filter = 0;
Christian Lampartereeef4182009-08-19 12:43:47 +02001964 err = ar9170_update_frame_filter(ar, AR9170_MAC_REG_FTF_DEFAULTS);
Christian Lampartere9348cd2009-03-21 23:05:13 +01001965 if (err)
1966 goto unlock;
1967
1968 err = ar9170_set_operating_mode(ar);
1969
1970unlock:
1971 mutex_unlock(&ar->mutex);
1972 return err;
1973}
1974
1975static void ar9170_op_remove_interface(struct ieee80211_hw *hw,
Johannes Berg1ed32e42009-12-23 13:15:45 +01001976 struct ieee80211_vif *vif)
Christian Lampartere9348cd2009-03-21 23:05:13 +01001977{
1978 struct ar9170 *ar = hw->priv;
1979
1980 mutex_lock(&ar->mutex);
1981 ar->vif = NULL;
Christian Lampartereeef4182009-08-19 12:43:47 +02001982 ar9170_update_frame_filter(ar, 0);
Christian Lampartere9348cd2009-03-21 23:05:13 +01001983 ar9170_set_beacon_timers(ar);
1984 dev_kfree_skb(ar->beacon);
1985 ar->beacon = NULL;
1986 ar->sniffer_enabled = false;
1987 ar->rx_software_decryption = false;
1988 ar9170_set_operating_mode(ar);
1989 mutex_unlock(&ar->mutex);
1990}
1991
1992static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed)
1993{
1994 struct ar9170 *ar = hw->priv;
1995 int err = 0;
1996
1997 mutex_lock(&ar->mutex);
1998
Christian Lampartere9348cd2009-03-21 23:05:13 +01001999 if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
2000 /* TODO */
2001 err = 0;
2002 }
2003
2004 if (changed & IEEE80211_CONF_CHANGE_PS) {
2005 /* TODO */
2006 err = 0;
2007 }
2008
2009 if (changed & IEEE80211_CONF_CHANGE_POWER) {
2010 /* TODO */
2011 err = 0;
2012 }
2013
2014 if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
2015 /*
2016 * is it long_frame_max_tx_count or short_frame_max_tx_count?
2017 */
2018
2019 err = ar9170_set_hwretry_limit(ar,
2020 ar->hw->conf.long_frame_max_tx_count);
2021 if (err)
2022 goto out;
2023 }
2024
Christian Lampartere9348cd2009-03-21 23:05:13 +01002025 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
Christian Lamparter29ceff52009-06-01 21:42:01 +02002026
2027 /* adjust slot time for 5 GHz */
2028 err = ar9170_set_slot_time(ar);
2029 if (err)
2030 goto out;
2031
2032 err = ar9170_set_dyn_sifs_ack(ar);
2033 if (err)
2034 goto out;
2035
Christian Lampartere9348cd2009-03-21 23:05:13 +01002036 err = ar9170_set_channel(ar, hw->conf.channel,
Johannes Berg9e52b06232009-04-20 18:27:04 +02002037 AR9170_RFI_NONE,
2038 nl80211_to_ar9170(hw->conf.channel_type));
Christian Lampartere9348cd2009-03-21 23:05:13 +01002039 if (err)
2040 goto out;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002041 }
2042
2043out:
2044 mutex_unlock(&ar->mutex);
2045 return err;
2046}
2047
Johannes Berg3ac64be2009-08-17 16:16:53 +02002048static u64 ar9170_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
2049 struct dev_addr_list *mclist)
2050{
2051 u64 mchash;
2052 int i;
2053
2054 /* always get broadcast frames */
2055 mchash = 1ULL << (0xff >> 2);
2056
2057 for (i = 0; i < mc_count; i++) {
2058 if (WARN_ON(!mclist))
2059 break;
2060 mchash |= 1ULL << (mclist->dmi_addr[5] >> 2);
2061 mclist = mclist->next;
2062 }
2063
2064 return mchash;
2065}
2066
Christian Lampartere9348cd2009-03-21 23:05:13 +01002067static void ar9170_op_configure_filter(struct ieee80211_hw *hw,
2068 unsigned int changed_flags,
2069 unsigned int *new_flags,
Johannes Berg3ac64be2009-08-17 16:16:53 +02002070 u64 multicast)
Christian Lampartere9348cd2009-03-21 23:05:13 +01002071{
2072 struct ar9170 *ar = hw->priv;
2073
Christian Lampartereeef4182009-08-19 12:43:47 +02002074 if (unlikely(!IS_ACCEPTING_CMD(ar)))
2075 return ;
2076
2077 mutex_lock(&ar->mutex);
2078
Christian Lampartere9348cd2009-03-21 23:05:13 +01002079 /* mask supported flags */
2080 *new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC |
Christian Lampartercca847992009-04-19 01:28:12 +02002081 FIF_PROMISC_IN_BSS | FIF_FCSFAIL | FIF_PLCPFAIL;
2082 ar->filter_state = *new_flags;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002083 /*
2084 * We can support more by setting the sniffer bit and
2085 * then checking the error flags, later.
2086 */
2087
Johannes Berg3ac64be2009-08-17 16:16:53 +02002088 if (changed_flags & FIF_ALLMULTI && *new_flags & FIF_ALLMULTI)
Christian Lampartereeef4182009-08-19 12:43:47 +02002089 multicast = ~0ULL;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002090
Christian Lampartereeef4182009-08-19 12:43:47 +02002091 if (multicast != ar->cur_mc_hash)
2092 ar9170_update_multicast(ar, multicast);
Christian Lampartere9348cd2009-03-21 23:05:13 +01002093
2094 if (changed_flags & FIF_CONTROL) {
2095 u32 filter = AR9170_MAC_REG_FTF_PSPOLL |
2096 AR9170_MAC_REG_FTF_RTS |
2097 AR9170_MAC_REG_FTF_CTS |
2098 AR9170_MAC_REG_FTF_ACK |
2099 AR9170_MAC_REG_FTF_CFE |
2100 AR9170_MAC_REG_FTF_CFE_ACK;
2101
2102 if (*new_flags & FIF_CONTROL)
Christian Lampartereeef4182009-08-19 12:43:47 +02002103 filter |= ar->cur_filter;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002104 else
Christian Lampartereeef4182009-08-19 12:43:47 +02002105 filter &= (~ar->cur_filter);
Christian Lampartere9348cd2009-03-21 23:05:13 +01002106
Christian Lampartereeef4182009-08-19 12:43:47 +02002107 ar9170_update_frame_filter(ar, filter);
Christian Lampartere9348cd2009-03-21 23:05:13 +01002108 }
2109
2110 if (changed_flags & FIF_PROMISC_IN_BSS) {
2111 ar->sniffer_enabled = ((*new_flags) & FIF_PROMISC_IN_BSS) != 0;
Christian Lampartereeef4182009-08-19 12:43:47 +02002112 ar9170_set_operating_mode(ar);
Christian Lampartere9348cd2009-03-21 23:05:13 +01002113 }
2114
Christian Lampartereeef4182009-08-19 12:43:47 +02002115 mutex_unlock(&ar->mutex);
Christian Lampartere9348cd2009-03-21 23:05:13 +01002116}
2117
Christian Lampartereeef4182009-08-19 12:43:47 +02002118
Christian Lampartere9348cd2009-03-21 23:05:13 +01002119static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw,
2120 struct ieee80211_vif *vif,
2121 struct ieee80211_bss_conf *bss_conf,
2122 u32 changed)
2123{
2124 struct ar9170 *ar = hw->priv;
Luis R. Rodriguez8c727e72009-09-10 10:10:54 -07002125 struct ath_common *common = &ar->common;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002126 int err = 0;
2127
2128 mutex_lock(&ar->mutex);
2129
Johannes Berg2d0ddec2009-04-23 16:13:26 +02002130 if (changed & BSS_CHANGED_BSSID) {
Luis R. Rodriguez8c727e72009-09-10 10:10:54 -07002131 memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
Johannes Berg2d0ddec2009-04-23 16:13:26 +02002132 err = ar9170_set_operating_mode(ar);
Christian Lamparter29ceff52009-06-01 21:42:01 +02002133 if (err)
2134 goto out;
Johannes Berg2d0ddec2009-04-23 16:13:26 +02002135 }
2136
Joerg Albertea39d1a2009-08-21 23:25:07 +02002137 if (changed & BSS_CHANGED_BEACON_ENABLED)
2138 ar->enable_beacon = bss_conf->enable_beacon;
2139
2140 if (changed & BSS_CHANGED_BEACON) {
Johannes Berg2d0ddec2009-04-23 16:13:26 +02002141 err = ar9170_update_beacon(ar);
Christian Lamparter29ceff52009-06-01 21:42:01 +02002142 if (err)
2143 goto out;
Joerg Albertea39d1a2009-08-21 23:25:07 +02002144 }
Johannes Berg2d0ddec2009-04-23 16:13:26 +02002145
Joerg Albertea39d1a2009-08-21 23:25:07 +02002146 if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON |
2147 BSS_CHANGED_BEACON_INT)) {
Christian Lamparter29ceff52009-06-01 21:42:01 +02002148 err = ar9170_set_beacon_timers(ar);
2149 if (err)
2150 goto out;
2151 }
Christian Lampartere9348cd2009-03-21 23:05:13 +01002152
2153 if (changed & BSS_CHANGED_ASSOC) {
Christian Lampartere9348cd2009-03-21 23:05:13 +01002154#ifndef CONFIG_AR9170_LEDS
2155 /* enable assoc LED. */
2156 err = ar9170_set_leds_state(ar, bss_conf->assoc ? 2 : 0);
2157#endif /* CONFIG_AR9170_LEDS */
2158 }
2159
2160 if (changed & BSS_CHANGED_HT) {
2161 /* TODO */
2162 err = 0;
2163 }
2164
2165 if (changed & BSS_CHANGED_ERP_SLOT) {
Christian Lamparter29ceff52009-06-01 21:42:01 +02002166 err = ar9170_set_slot_time(ar);
2167 if (err)
2168 goto out;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002169 }
2170
2171 if (changed & BSS_CHANGED_BASIC_RATES) {
Christian Lamparter29ceff52009-06-01 21:42:01 +02002172 err = ar9170_set_basic_rates(ar);
2173 if (err)
2174 goto out;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002175 }
2176
Christian Lamparter29ceff52009-06-01 21:42:01 +02002177out:
Christian Lampartere9348cd2009-03-21 23:05:13 +01002178 mutex_unlock(&ar->mutex);
2179}
2180
2181static u64 ar9170_op_get_tsf(struct ieee80211_hw *hw)
2182{
2183 struct ar9170 *ar = hw->priv;
2184 int err;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002185 u64 tsf;
Joerg Albert181af382009-09-15 23:27:53 +02002186#define NR 3
2187 static const u32 addr[NR] = { AR9170_MAC_REG_TSF_H,
2188 AR9170_MAC_REG_TSF_L,
2189 AR9170_MAC_REG_TSF_H };
2190 u32 val[NR];
2191 int loops = 0;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002192
2193 mutex_lock(&ar->mutex);
Joerg Albert181af382009-09-15 23:27:53 +02002194
2195 while (loops++ < 10) {
2196 err = ar9170_read_mreg(ar, NR, addr, val);
2197 if (err || val[0] == val[2])
2198 break;
2199 }
2200
Christian Lampartere9348cd2009-03-21 23:05:13 +01002201 mutex_unlock(&ar->mutex);
2202
2203 if (WARN_ON(err))
2204 return 0;
Joerg Albert181af382009-09-15 23:27:53 +02002205 tsf = val[0];
2206 tsf = (tsf << 32) | val[1];
Christian Lampartere9348cd2009-03-21 23:05:13 +01002207 return tsf;
Joerg Albert181af382009-09-15 23:27:53 +02002208#undef NR
Christian Lampartere9348cd2009-03-21 23:05:13 +01002209}
2210
2211static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
2212 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
2213 struct ieee80211_key_conf *key)
2214{
2215 struct ar9170 *ar = hw->priv;
2216 int err = 0, i;
2217 u8 ktype;
2218
2219 if ((!ar->vif) || (ar->disable_offload))
2220 return -EOPNOTSUPP;
2221
2222 switch (key->alg) {
2223 case ALG_WEP:
Zhu Yie31a16d2009-05-21 21:47:03 +08002224 if (key->keylen == WLAN_KEY_LEN_WEP40)
Christian Lampartere9348cd2009-03-21 23:05:13 +01002225 ktype = AR9170_ENC_ALG_WEP64;
2226 else
2227 ktype = AR9170_ENC_ALG_WEP128;
2228 break;
2229 case ALG_TKIP:
2230 ktype = AR9170_ENC_ALG_TKIP;
2231 break;
2232 case ALG_CCMP:
2233 ktype = AR9170_ENC_ALG_AESCCMP;
2234 break;
2235 default:
2236 return -EOPNOTSUPP;
2237 }
2238
2239 mutex_lock(&ar->mutex);
2240 if (cmd == SET_KEY) {
2241 if (unlikely(!IS_STARTED(ar))) {
2242 err = -EOPNOTSUPP;
2243 goto out;
2244 }
2245
2246 /* group keys need all-zeroes address */
2247 if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
2248 sta = NULL;
2249
2250 if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
2251 for (i = 0; i < 64; i++)
2252 if (!(ar->usedkeys & BIT(i)))
2253 break;
2254 if (i == 64) {
2255 ar->rx_software_decryption = true;
2256 ar9170_set_operating_mode(ar);
2257 err = -ENOSPC;
2258 goto out;
2259 }
2260 } else {
2261 i = 64 + key->keyidx;
2262 }
2263
2264 key->hw_key_idx = i;
2265
2266 err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, ktype, 0,
2267 key->key, min_t(u8, 16, key->keylen));
2268 if (err)
2269 goto out;
2270
2271 if (key->alg == ALG_TKIP) {
2272 err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL,
2273 ktype, 1, key->key + 16, 16);
2274 if (err)
2275 goto out;
2276
2277 /*
2278 * hardware is not capable generating the MMIC
2279 * for fragmented frames!
2280 */
2281 key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
2282 }
2283
2284 if (i < 64)
2285 ar->usedkeys |= BIT(i);
2286
2287 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
2288 } else {
2289 if (unlikely(!IS_STARTED(ar))) {
2290 /* The device is gone... together with the key ;-) */
2291 err = 0;
2292 goto out;
2293 }
2294
2295 err = ar9170_disable_key(ar, key->hw_key_idx);
2296 if (err)
2297 goto out;
2298
2299 if (key->hw_key_idx < 64) {
2300 ar->usedkeys &= ~BIT(key->hw_key_idx);
2301 } else {
2302 err = ar9170_upload_key(ar, key->hw_key_idx, NULL,
2303 AR9170_ENC_ALG_NONE, 0,
2304 NULL, 0);
2305 if (err)
2306 goto out;
2307
2308 if (key->alg == ALG_TKIP) {
2309 err = ar9170_upload_key(ar, key->hw_key_idx,
2310 NULL,
2311 AR9170_ENC_ALG_NONE, 1,
2312 NULL, 0);
2313 if (err)
2314 goto out;
2315 }
2316
2317 }
2318 }
2319
2320 ar9170_regwrite_begin(ar);
2321 ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_L, ar->usedkeys);
2322 ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_H, ar->usedkeys >> 32);
2323 ar9170_regwrite_finish();
2324 err = ar9170_regwrite_result();
2325
2326out:
2327 mutex_unlock(&ar->mutex);
2328
2329 return err;
2330}
2331
Johannes Berg3e60f862010-02-19 19:06:53 +01002332static int ar9170_sta_add(struct ieee80211_hw *hw,
2333 struct ieee80211_vif *vif,
2334 struct ieee80211_sta *sta)
Christian Lampartere9348cd2009-03-21 23:05:13 +01002335{
Christian Lamparteracbadf02009-07-11 17:24:14 +02002336 struct ar9170 *ar = hw->priv;
2337 struct ar9170_sta_info *sta_info = (void *) sta->drv_priv;
2338 unsigned int i;
2339
Johannes Berg3e60f862010-02-19 19:06:53 +01002340 memset(sta_info, 0, sizeof(*sta_info));
Christian Lamparteracbadf02009-07-11 17:24:14 +02002341
Johannes Berg3e60f862010-02-19 19:06:53 +01002342 if (!sta->ht_cap.ht_supported)
2343 return 0;
Christian Lamparteracbadf02009-07-11 17:24:14 +02002344
Johannes Berg3e60f862010-02-19 19:06:53 +01002345 if (sta->ht_cap.ampdu_density > ar->global_ampdu_density)
2346 ar->global_ampdu_density = sta->ht_cap.ampdu_density;
Christian Lamparteracbadf02009-07-11 17:24:14 +02002347
Johannes Berg3e60f862010-02-19 19:06:53 +01002348 if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor)
2349 ar->global_ampdu_factor = sta->ht_cap.ampdu_factor;
Christian Lamparteracbadf02009-07-11 17:24:14 +02002350
Johannes Berg3e60f862010-02-19 19:06:53 +01002351 for (i = 0; i < AR9170_NUM_TID; i++) {
2352 sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN;
2353 sta_info->agg[i].active = false;
2354 sta_info->agg[i].ssn = 0;
2355 sta_info->agg[i].tid = i;
2356 INIT_LIST_HEAD(&sta_info->agg[i].list);
2357 skb_queue_head_init(&sta_info->agg[i].queue);
Christian Lamparteracbadf02009-07-11 17:24:14 +02002358 }
Johannes Berg3e60f862010-02-19 19:06:53 +01002359
2360 sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor);
2361
2362 return 0;
2363}
2364
2365static int ar9170_sta_remove(struct ieee80211_hw *hw,
2366 struct ieee80211_vif *vif,
2367 struct ieee80211_sta *sta)
2368{
2369 struct ar9170_sta_info *sta_info = (void *) sta->drv_priv;
2370 unsigned int i;
2371
2372 if (!sta->ht_cap.ht_supported)
2373 return 0;
2374
2375 for (i = 0; i < AR9170_NUM_TID; i++) {
2376 sta_info->agg[i].state = AR9170_TID_STATE_INVALID;
2377 skb_queue_purge(&sta_info->agg[i].queue);
2378 }
2379
2380 return 0;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002381}
2382
2383static int ar9170_get_stats(struct ieee80211_hw *hw,
2384 struct ieee80211_low_level_stats *stats)
2385{
2386 struct ar9170 *ar = hw->priv;
2387 u32 val;
2388 int err;
2389
2390 mutex_lock(&ar->mutex);
2391 err = ar9170_read_reg(ar, AR9170_MAC_REG_TX_RETRY, &val);
2392 ar->stats.dot11ACKFailureCount += val;
2393
2394 memcpy(stats, &ar->stats, sizeof(*stats));
2395 mutex_unlock(&ar->mutex);
2396
2397 return 0;
2398}
2399
Christian Lampartere9348cd2009-03-21 23:05:13 +01002400static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue,
2401 const struct ieee80211_tx_queue_params *param)
2402{
2403 struct ar9170 *ar = hw->priv;
2404 int ret;
2405
2406 mutex_lock(&ar->mutex);
Dan Carpentere9d126c2009-08-09 14:24:09 +02002407 if (queue < __AR9170_NUM_TXQ) {
Christian Lampartere9348cd2009-03-21 23:05:13 +01002408 memcpy(&ar->edcf[ar9170_qos_hwmap[queue]],
2409 param, sizeof(*param));
2410
2411 ret = ar9170_set_qos(ar);
Dan Carpentere9d126c2009-08-09 14:24:09 +02002412 } else {
Christian Lampartere9348cd2009-03-21 23:05:13 +01002413 ret = -EINVAL;
Dan Carpentere9d126c2009-08-09 14:24:09 +02002414 }
Christian Lampartere9348cd2009-03-21 23:05:13 +01002415
2416 mutex_unlock(&ar->mutex);
2417 return ret;
2418}
2419
Johannes Berg9e52b06232009-04-20 18:27:04 +02002420static int ar9170_ampdu_action(struct ieee80211_hw *hw,
Johannes Bergc951ad32009-11-16 12:00:38 +01002421 struct ieee80211_vif *vif,
Johannes Berg9e52b06232009-04-20 18:27:04 +02002422 enum ieee80211_ampdu_mlme_action action,
2423 struct ieee80211_sta *sta, u16 tid, u16 *ssn)
2424{
Christian Lamparteracbadf02009-07-11 17:24:14 +02002425 struct ar9170 *ar = hw->priv;
2426 struct ar9170_sta_info *sta_info = (void *) sta->drv_priv;
2427 struct ar9170_sta_tid *tid_info = &sta_info->agg[tid];
2428 unsigned long flags;
2429
2430 if (!modparam_ht)
2431 return -EOPNOTSUPP;
2432
Johannes Berg9e52b06232009-04-20 18:27:04 +02002433 switch (action) {
Christian Lamparteracbadf02009-07-11 17:24:14 +02002434 case IEEE80211_AMPDU_TX_START:
2435 spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
2436 if (tid_info->state != AR9170_TID_STATE_SHUTDOWN ||
2437 !list_empty(&tid_info->list)) {
2438 spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
2439#ifdef AR9170_TXAGG_DEBUG
2440 printk(KERN_INFO "%s: A-MPDU [ESS:[%pM] tid:[%d]] "
2441 "is in a very bad state!\n",
2442 wiphy_name(hw->wiphy), sta->addr, tid);
2443#endif /* AR9170_TXAGG_DEBUG */
2444 return -EBUSY;
2445 }
2446
2447 *ssn = tid_info->ssn;
2448 tid_info->state = AR9170_TID_STATE_PROGRESS;
2449 tid_info->active = false;
2450 spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
Johannes Bergc951ad32009-11-16 12:00:38 +01002451 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
Christian Lamparteracbadf02009-07-11 17:24:14 +02002452 break;
2453
2454 case IEEE80211_AMPDU_TX_STOP:
2455 spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
2456 tid_info->state = AR9170_TID_STATE_SHUTDOWN;
2457 list_del_init(&tid_info->list);
2458 tid_info->active = false;
2459 skb_queue_purge(&tid_info->queue);
2460 spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
Johannes Bergc951ad32009-11-16 12:00:38 +01002461 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
Christian Lamparteracbadf02009-07-11 17:24:14 +02002462 break;
2463
2464 case IEEE80211_AMPDU_TX_OPERATIONAL:
2465#ifdef AR9170_TXAGG_DEBUG
2466 printk(KERN_INFO "%s: A-MPDU for %pM [tid:%d] Operational.\n",
2467 wiphy_name(hw->wiphy), sta->addr, tid);
2468#endif /* AR9170_TXAGG_DEBUG */
2469 spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
2470 sta_info->agg[tid].state = AR9170_TID_STATE_COMPLETE;
2471 spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
2472 break;
2473
Johannes Berg9e52b06232009-04-20 18:27:04 +02002474 case IEEE80211_AMPDU_RX_START:
2475 case IEEE80211_AMPDU_RX_STOP:
Christian Lamparteracbadf02009-07-11 17:24:14 +02002476 /* Handled by firmware */
2477 break;
2478
Johannes Berg9e52b06232009-04-20 18:27:04 +02002479 default:
2480 return -EOPNOTSUPP;
2481 }
Christian Lamparteracbadf02009-07-11 17:24:14 +02002482
2483 return 0;
Johannes Berg9e52b06232009-04-20 18:27:04 +02002484}
2485
Christian Lampartere9348cd2009-03-21 23:05:13 +01002486static const struct ieee80211_ops ar9170_ops = {
2487 .start = ar9170_op_start,
2488 .stop = ar9170_op_stop,
2489 .tx = ar9170_op_tx,
2490 .add_interface = ar9170_op_add_interface,
2491 .remove_interface = ar9170_op_remove_interface,
2492 .config = ar9170_op_config,
Johannes Berg3ac64be2009-08-17 16:16:53 +02002493 .prepare_multicast = ar9170_op_prepare_multicast,
Christian Lampartere9348cd2009-03-21 23:05:13 +01002494 .configure_filter = ar9170_op_configure_filter,
2495 .conf_tx = ar9170_conf_tx,
2496 .bss_info_changed = ar9170_op_bss_info_changed,
2497 .get_tsf = ar9170_op_get_tsf,
2498 .set_key = ar9170_set_key,
Johannes Berg3e60f862010-02-19 19:06:53 +01002499 .sta_add = ar9170_sta_add,
2500 .sta_remove = ar9170_sta_remove,
Christian Lampartere9348cd2009-03-21 23:05:13 +01002501 .get_stats = ar9170_get_stats,
Johannes Berg9e52b06232009-04-20 18:27:04 +02002502 .ampdu_action = ar9170_ampdu_action,
Christian Lampartere9348cd2009-03-21 23:05:13 +01002503};
2504
2505void *ar9170_alloc(size_t priv_size)
2506{
2507 struct ieee80211_hw *hw;
2508 struct ar9170 *ar;
Christian Lampartercca847992009-04-19 01:28:12 +02002509 struct sk_buff *skb;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002510 int i;
2511
Christian Lampartercca847992009-04-19 01:28:12 +02002512 /*
2513 * this buffer is used for rx stream reconstruction.
2514 * Under heavy load this device (or the transport layer?)
2515 * tends to split the streams into seperate rx descriptors.
2516 */
2517
2518 skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE, GFP_KERNEL);
2519 if (!skb)
2520 goto err_nomem;
2521
Christian Lampartere9348cd2009-03-21 23:05:13 +01002522 hw = ieee80211_alloc_hw(priv_size, &ar9170_ops);
2523 if (!hw)
Christian Lampartercca847992009-04-19 01:28:12 +02002524 goto err_nomem;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002525
2526 ar = hw->priv;
2527 ar->hw = hw;
Christian Lampartercca847992009-04-19 01:28:12 +02002528 ar->rx_failover = skb;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002529
2530 mutex_init(&ar->mutex);
2531 spin_lock_init(&ar->cmdlock);
2532 spin_lock_init(&ar->tx_stats_lock);
Christian Lamparteracbadf02009-07-11 17:24:14 +02002533 spin_lock_init(&ar->tx_ampdu_list_lock);
2534 skb_queue_head_init(&ar->tx_status_ampdu);
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02002535 for (i = 0; i < __AR9170_NUM_TXQ; i++) {
2536 skb_queue_head_init(&ar->tx_status[i]);
2537 skb_queue_head_init(&ar->tx_pending[i]);
2538 }
Christian Lampartercca847992009-04-19 01:28:12 +02002539 ar9170_rx_reset_rx_mpdu(ar);
Christian Lampartere9348cd2009-03-21 23:05:13 +01002540 INIT_WORK(&ar->beacon_work, ar9170_new_beacon);
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02002541 INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor);
Christian Lamparteracbadf02009-07-11 17:24:14 +02002542 INIT_LIST_HEAD(&ar->tx_ampdu_list);
Christian Lampartere9348cd2009-03-21 23:05:13 +01002543
2544 /* all hw supports 2.4 GHz, so set channel to 1 by default */
2545 ar->channel = &ar9170_2ghz_chantable[0];
2546
2547 /* first part of wiphy init */
2548 ar->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
2549 BIT(NL80211_IFTYPE_WDS) |
2550 BIT(NL80211_IFTYPE_ADHOC);
2551 ar->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS |
2552 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
2553 IEEE80211_HW_SIGNAL_DBM |
2554 IEEE80211_HW_NOISE_DBM;
2555
Christian Lamparteracbadf02009-07-11 17:24:14 +02002556 if (modparam_ht) {
2557 ar->hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
2558 } else {
2559 ar9170_band_2GHz.ht_cap.ht_supported = false;
2560 ar9170_band_5GHz.ht_cap.ht_supported = false;
2561 }
2562
Christian Lamparter4a48e2a2009-03-23 12:15:43 +01002563 ar->hw->queues = __AR9170_NUM_TXQ;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002564 ar->hw->extra_tx_headroom = 8;
2565 ar->hw->sta_data_size = sizeof(struct ar9170_sta_info);
2566
2567 ar->hw->max_rates = 1;
2568 ar->hw->max_rate_tries = 3;
2569
2570 for (i = 0; i < ARRAY_SIZE(ar->noise); i++)
2571 ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */
2572
2573 return ar;
Christian Lampartercca847992009-04-19 01:28:12 +02002574
2575err_nomem:
2576 kfree_skb(skb);
2577 return ERR_PTR(-ENOMEM);
Christian Lampartere9348cd2009-03-21 23:05:13 +01002578}
Christian Lampartere9348cd2009-03-21 23:05:13 +01002579
2580static int ar9170_read_eeprom(struct ar9170 *ar)
2581{
2582#define RW 8 /* number of words to read at once */
2583#define RB (sizeof(u32) * RW)
Luis R. Rodriguez608b88c2009-08-17 18:07:23 -07002584 struct ath_regulatory *regulatory = &ar->common.regulatory;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002585 u8 *eeprom = (void *)&ar->eeprom;
2586 u8 *addr = ar->eeprom.mac_address;
2587 __le32 offsets[RW];
Christian Lamparteracbadf02009-07-11 17:24:14 +02002588 unsigned int rx_streams, tx_streams, tx_params = 0;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002589 int i, j, err, bands = 0;
2590
2591 BUILD_BUG_ON(sizeof(ar->eeprom) & 3);
2592
2593 BUILD_BUG_ON(RB > AR9170_MAX_CMD_LEN - 4);
2594#ifndef __CHECKER__
2595 /* don't want to handle trailing remains */
2596 BUILD_BUG_ON(sizeof(ar->eeprom) % RB);
2597#endif
2598
2599 for (i = 0; i < sizeof(ar->eeprom)/RB; i++) {
2600 for (j = 0; j < RW; j++)
2601 offsets[j] = cpu_to_le32(AR9170_EEPROM_START +
2602 RB * i + 4 * j);
2603
2604 err = ar->exec_cmd(ar, AR9170_CMD_RREG,
2605 RB, (u8 *) &offsets,
2606 RB, eeprom + RB * i);
2607 if (err)
2608 return err;
2609 }
2610
2611#undef RW
2612#undef RB
2613
2614 if (ar->eeprom.length == cpu_to_le16(0xFFFF))
2615 return -ENODATA;
2616
2617 if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) {
2618 ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &ar9170_band_2GHz;
2619 bands++;
2620 }
2621 if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) {
2622 ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar9170_band_5GHz;
2623 bands++;
2624 }
Christian Lamparteracbadf02009-07-11 17:24:14 +02002625
2626 rx_streams = hweight8(ar->eeprom.rx_mask);
2627 tx_streams = hweight8(ar->eeprom.tx_mask);
2628
2629 if (rx_streams != tx_streams)
2630 tx_params = IEEE80211_HT_MCS_TX_RX_DIFF;
2631
2632 if (tx_streams >= 1 && tx_streams <= IEEE80211_HT_MCS_TX_MAX_STREAMS)
2633 tx_params = (tx_streams - 1) <<
2634 IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
2635
2636 ar9170_band_2GHz.ht_cap.mcs.tx_params |= tx_params;
2637 ar9170_band_5GHz.ht_cap.mcs.tx_params |= tx_params;
2638
Christian Lampartere9348cd2009-03-21 23:05:13 +01002639 /*
2640 * I measured this, a bandswitch takes roughly
2641 * 135 ms and a frequency switch about 80.
2642 *
2643 * FIXME: measure these values again once EEPROM settings
2644 * are used, that will influence them!
2645 */
2646 if (bands == 2)
2647 ar->hw->channel_change_time = 135 * 1000;
2648 else
2649 ar->hw->channel_change_time = 80 * 1000;
2650
Luis R. Rodriguez608b88c2009-08-17 18:07:23 -07002651 regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]);
2652 regulatory->current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]);
Christian Lamparter1878f772009-03-30 22:30:32 -04002653
Christian Lampartere9348cd2009-03-21 23:05:13 +01002654 /* second part of wiphy init */
2655 SET_IEEE80211_PERM_ADDR(ar->hw, addr);
2656
2657 return bands ? 0 : -EINVAL;
2658}
2659
Christian Lamparter1878f772009-03-30 22:30:32 -04002660static int ar9170_reg_notifier(struct wiphy *wiphy,
2661 struct regulatory_request *request)
2662{
2663 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
2664 struct ar9170 *ar = hw->priv;
2665
Luis R. Rodriguez608b88c2009-08-17 18:07:23 -07002666 return ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory);
Christian Lamparter1878f772009-03-30 22:30:32 -04002667}
2668
Christian Lampartere9348cd2009-03-21 23:05:13 +01002669int ar9170_register(struct ar9170 *ar, struct device *pdev)
2670{
Luis R. Rodriguez608b88c2009-08-17 18:07:23 -07002671 struct ath_regulatory *regulatory = &ar->common.regulatory;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002672 int err;
2673
2674 /* try to read EEPROM, init MAC addr */
2675 err = ar9170_read_eeprom(ar);
2676 if (err)
2677 goto err_out;
2678
Luis R. Rodriguez608b88c2009-08-17 18:07:23 -07002679 err = ath_regd_init(regulatory, ar->hw->wiphy,
Christian Lamparter1878f772009-03-30 22:30:32 -04002680 ar9170_reg_notifier);
Luis R. Rodriguez85efc862009-04-13 21:41:46 -04002681 if (err)
2682 goto err_out;
Christian Lamparter1878f772009-03-30 22:30:32 -04002683
Christian Lampartere9348cd2009-03-21 23:05:13 +01002684 err = ieee80211_register_hw(ar->hw);
2685 if (err)
2686 goto err_out;
2687
Luis R. Rodriguez608b88c2009-08-17 18:07:23 -07002688 if (!ath_is_world_regd(regulatory))
2689 regulatory_hint(ar->hw->wiphy, regulatory->alpha2);
Christian Lamparter1878f772009-03-30 22:30:32 -04002690
Christian Lampartere9348cd2009-03-21 23:05:13 +01002691 err = ar9170_init_leds(ar);
2692 if (err)
2693 goto err_unreg;
2694
2695#ifdef CONFIG_AR9170_LEDS
2696 err = ar9170_register_leds(ar);
2697 if (err)
2698 goto err_unreg;
2699#endif /* CONFIG_AR9170_LEDS */
2700
2701 dev_info(pdev, "Atheros AR9170 is registered as '%s'\n",
2702 wiphy_name(ar->hw->wiphy));
2703
2704 return err;
2705
2706err_unreg:
2707 ieee80211_unregister_hw(ar->hw);
2708
2709err_out:
2710 return err;
2711}
Christian Lampartere9348cd2009-03-21 23:05:13 +01002712
2713void ar9170_unregister(struct ar9170 *ar)
2714{
2715#ifdef CONFIG_AR9170_LEDS
2716 ar9170_unregister_leds(ar);
2717#endif /* CONFIG_AR9170_LEDS */
2718
Christian Lampartercca847992009-04-19 01:28:12 +02002719 kfree_skb(ar->rx_failover);
Christian Lampartere9348cd2009-03-21 23:05:13 +01002720 ieee80211_unregister_hw(ar->hw);
2721 mutex_destroy(&ar->mutex);
2722}