blob: 3cec2f16c65744c120d974ba0e0a7cdb7db480be [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
197static inline u16 ar9170_get_tid(struct sk_buff *skb)
198{
199 struct ar9170_tx_control *txc = (void *) skb->data;
200 struct ieee80211_hdr *hdr = (void *) txc->frame_data;
201
202 return (ieee80211_get_qos_ctl(hdr))[0] & IEEE80211_QOS_CTL_TID_MASK;
203}
204
205#define GET_NEXT_SEQ(seq) ((seq + 1) & 0x0fff)
206#define GET_NEXT_SEQ_FROM_SKB(skb) (GET_NEXT_SEQ(ar9170_get_seq(skb)))
207
208#if (defined AR9170_QUEUE_DEBUG) || (defined AR9170_TXAGG_DEBUG)
Christian Lampartere9348cd2009-03-21 23:05:13 +0100209static void ar9170_print_txheader(struct ar9170 *ar, struct sk_buff *skb)
210{
211 struct ar9170_tx_control *txc = (void *) skb->data;
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200212 struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
213 struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data;
214 struct ieee80211_hdr *hdr = (void *) txc->frame_data;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100215
Christian Lamparteracbadf02009-07-11 17:24:14 +0200216 printk(KERN_DEBUG "%s: => FRAME [skb:%p, q:%d, DA:[%pM] flags:%x s:%d "
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200217 "mac_ctrl:%04x, phy_ctrl:%08x, timeout:[%d ms]]\n",
Christian Lampartere9348cd2009-03-21 23:05:13 +0100218 wiphy_name(ar->hw->wiphy), skb, skb_get_queue_mapping(skb),
Christian Lamparteracbadf02009-07-11 17:24:14 +0200219 ieee80211_get_DA(hdr), arinfo->flags, ar9170_get_seq_h(hdr),
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200220 le16_to_cpu(txc->mac_control), le32_to_cpu(txc->phy_control),
221 jiffies_to_msecs(arinfo->timeout - jiffies));
Christian Lampartere9348cd2009-03-21 23:05:13 +0100222}
223
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200224static void __ar9170_dump_txqueue(struct ar9170 *ar,
225 struct sk_buff_head *queue)
Christian Lampartere9348cd2009-03-21 23:05:13 +0100226{
227 struct sk_buff *skb;
228 int i = 0;
229
230 printk(KERN_DEBUG "---[ cut here ]---\n");
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200231 printk(KERN_DEBUG "%s: %d entries in queue.\n",
Christian Lampartere9348cd2009-03-21 23:05:13 +0100232 wiphy_name(ar->hw->wiphy), skb_queue_len(queue));
233
234 skb_queue_walk(queue, skb) {
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200235 printk(KERN_DEBUG "index:%d => \n", i++);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100236 ar9170_print_txheader(ar, skb);
237 }
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200238 if (i != skb_queue_len(queue))
239 printk(KERN_DEBUG "WARNING: queue frame counter "
240 "mismatch %d != %d\n", skb_queue_len(queue), i);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100241 printk(KERN_DEBUG "---[ end ]---\n");
242}
Christian Lamparteracbadf02009-07-11 17:24:14 +0200243#endif /* AR9170_QUEUE_DEBUG || AR9170_TXAGG_DEBUG */
Christian Lampartere9348cd2009-03-21 23:05:13 +0100244
Christian Lamparteracbadf02009-07-11 17:24:14 +0200245#ifdef AR9170_QUEUE_DEBUG
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200246static void ar9170_dump_txqueue(struct ar9170 *ar,
247 struct sk_buff_head *queue)
Christian Lampartere9348cd2009-03-21 23:05:13 +0100248{
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200249 unsigned long flags;
250
251 spin_lock_irqsave(&queue->lock, flags);
252 __ar9170_dump_txqueue(ar, queue);
253 spin_unlock_irqrestore(&queue->lock, flags);
254}
Christian Lamparteracbadf02009-07-11 17:24:14 +0200255#endif /* AR9170_QUEUE_DEBUG */
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200256
Christian Lamparteracbadf02009-07-11 17:24:14 +0200257#ifdef AR9170_QUEUE_STOP_DEBUG
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200258static void __ar9170_dump_txstats(struct ar9170 *ar)
259{
260 int i;
261
262 printk(KERN_DEBUG "%s: QoS queue stats\n",
263 wiphy_name(ar->hw->wiphy));
264
265 for (i = 0; i < __AR9170_NUM_TXQ; i++)
Christian Lamparteracbadf02009-07-11 17:24:14 +0200266 printk(KERN_DEBUG "%s: queue:%d limit:%d len:%d waitack:%d "
267 " stopped:%d\n", wiphy_name(ar->hw->wiphy), i,
268 ar->tx_stats[i].limit, ar->tx_stats[i].len,
269 skb_queue_len(&ar->tx_status[i]),
270 ieee80211_queue_stopped(ar->hw, i));
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200271}
Christian Lamparteracbadf02009-07-11 17:24:14 +0200272#endif /* AR9170_QUEUE_STOP_DEBUG */
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200273
Christian Lamparteracbadf02009-07-11 17:24:14 +0200274#ifdef AR9170_TXAGG_DEBUG
275static void ar9170_dump_tx_status_ampdu(struct ar9170 *ar)
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200276{
Christian Lampartere9348cd2009-03-21 23:05:13 +0100277 unsigned long flags;
278
Christian Lamparteracbadf02009-07-11 17:24:14 +0200279 spin_lock_irqsave(&ar->tx_status_ampdu.lock, flags);
280 printk(KERN_DEBUG "%s: A-MPDU tx_status queue => \n",
281 wiphy_name(ar->hw->wiphy));
282 __ar9170_dump_txqueue(ar, &ar->tx_status_ampdu);
283 spin_unlock_irqrestore(&ar->tx_status_ampdu.lock, flags);
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200284}
Christian Lamparteracbadf02009-07-11 17:24:14 +0200285
286#endif /* AR9170_TXAGG_DEBUG */
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200287
288/* caller must guarantee exclusive access for _bin_ queue. */
289static void ar9170_recycle_expired(struct ar9170 *ar,
290 struct sk_buff_head *queue,
291 struct sk_buff_head *bin)
292{
293 struct sk_buff *skb, *old = NULL;
294 unsigned long flags;
295
296 spin_lock_irqsave(&queue->lock, flags);
297 while ((skb = skb_peek(queue))) {
298 struct ieee80211_tx_info *txinfo;
299 struct ar9170_tx_info *arinfo;
300
301 txinfo = IEEE80211_SKB_CB(skb);
302 arinfo = (void *) txinfo->rate_driver_data;
303
304 if (time_is_before_jiffies(arinfo->timeout)) {
305#ifdef AR9170_QUEUE_DEBUG
306 printk(KERN_DEBUG "%s: [%ld > %ld] frame expired => "
307 "recycle \n", wiphy_name(ar->hw->wiphy),
308 jiffies, arinfo->timeout);
309 ar9170_print_txheader(ar, skb);
310#endif /* AR9170_QUEUE_DEBUG */
311 __skb_unlink(skb, queue);
312 __skb_queue_tail(bin, skb);
313 } else {
314 break;
315 }
316
317 if (unlikely(old == skb)) {
318 /* bail out - queue is shot. */
319
320 WARN_ON(1);
321 break;
322 }
323 old = skb;
324 }
325 spin_unlock_irqrestore(&queue->lock, flags);
326}
327
328static void ar9170_tx_status(struct ar9170 *ar, struct sk_buff *skb,
329 u16 tx_status)
330{
331 struct ieee80211_tx_info *txinfo;
332 unsigned int retries = 0;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100333
334 txinfo = IEEE80211_SKB_CB(skb);
335 ieee80211_tx_info_clear_status(txinfo);
336
337 switch (tx_status) {
338 case AR9170_TX_STATUS_RETRY:
339 retries = 2;
340 case AR9170_TX_STATUS_COMPLETE:
341 txinfo->flags |= IEEE80211_TX_STAT_ACK;
342 break;
343
344 case AR9170_TX_STATUS_FAILED:
345 retries = ar->hw->conf.long_frame_max_tx_count;
346 break;
347
348 default:
349 printk(KERN_ERR "%s: invalid tx_status response (%x).\n",
350 wiphy_name(ar->hw->wiphy), tx_status);
351 break;
352 }
353
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200354 txinfo->status.rates[0].count = retries + 1;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100355 skb_pull(skb, sizeof(struct ar9170_tx_control));
356 ieee80211_tx_status_irqsafe(ar->hw, skb);
357}
Christian Lampartere9348cd2009-03-21 23:05:13 +0100358
Christian Lamparteracbadf02009-07-11 17:24:14 +0200359static void ar9170_tx_fake_ampdu_status(struct ar9170 *ar)
360{
361 struct sk_buff_head success;
362 struct sk_buff *skb;
363 unsigned int i;
364 unsigned long queue_bitmap = 0;
365
366 skb_queue_head_init(&success);
367
368 while (skb_queue_len(&ar->tx_status_ampdu) > AR9170_NUM_TX_STATUS)
369 __skb_queue_tail(&success, skb_dequeue(&ar->tx_status_ampdu));
370
371 ar9170_recycle_expired(ar, &ar->tx_status_ampdu, &success);
372
373#ifdef AR9170_TXAGG_DEBUG
374 printk(KERN_DEBUG "%s: collected %d A-MPDU frames.\n",
375 wiphy_name(ar->hw->wiphy), skb_queue_len(&success));
376 __ar9170_dump_txqueue(ar, &success);
377#endif /* AR9170_TXAGG_DEBUG */
378
379 while ((skb = __skb_dequeue(&success))) {
380 struct ieee80211_tx_info *txinfo;
381
382 queue_bitmap |= BIT(skb_get_queue_mapping(skb));
383
384 txinfo = IEEE80211_SKB_CB(skb);
385 ieee80211_tx_info_clear_status(txinfo);
386
387 txinfo->flags |= IEEE80211_TX_STAT_ACK;
388 txinfo->status.rates[0].count = 1;
389
390 skb_pull(skb, sizeof(struct ar9170_tx_control));
391 ieee80211_tx_status_irqsafe(ar->hw, skb);
392 }
393
394 for_each_bit(i, &queue_bitmap, BITS_PER_BYTE) {
395#ifdef AR9170_QUEUE_STOP_DEBUG
396 printk(KERN_DEBUG "%s: wake queue %d\n",
397 wiphy_name(ar->hw->wiphy), i);
398 __ar9170_dump_txstats(ar);
399#endif /* AR9170_QUEUE_STOP_DEBUG */
400 ieee80211_wake_queue(ar->hw, i);
401 }
402
403 if (queue_bitmap)
404 ar9170_tx(ar);
405}
406
407static void ar9170_tx_ampdu_callback(struct ar9170 *ar, struct sk_buff *skb)
408{
409 struct ieee80211_tx_info *txinfo = IEEE80211_SKB_CB(skb);
410 struct ar9170_tx_info *arinfo = (void *) txinfo->rate_driver_data;
411
412 arinfo->timeout = jiffies +
413 msecs_to_jiffies(AR9170_BA_TIMEOUT);
414
415 skb_queue_tail(&ar->tx_status_ampdu, skb);
416 ar9170_tx_fake_ampdu_status(ar);
Christian Lamparteracbadf02009-07-11 17:24:14 +0200417
Christian Lamparter02bdf5b2009-10-17 21:56:43 +0200418 if (atomic_dec_and_test(&ar->tx_ampdu_pending) &&
419 !list_empty(&ar->tx_ampdu_list))
Christian Lamparteracbadf02009-07-11 17:24:14 +0200420 ar9170_tx_ampdu(ar);
421}
422
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200423void ar9170_tx_callback(struct ar9170 *ar, struct sk_buff *skb)
Christian Lampartere9348cd2009-03-21 23:05:13 +0100424{
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200425 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
426 struct ar9170_tx_info *arinfo = (void *) info->rate_driver_data;
427 unsigned int queue = skb_get_queue_mapping(skb);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100428 unsigned long flags;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100429
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200430 spin_lock_irqsave(&ar->tx_stats_lock, flags);
431 ar->tx_stats[queue].len--;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100432
Christian Lamparter53a76b52009-11-29 00:52:51 +0100433 if (ar->tx_stats[queue].len < AR9170_NUM_TX_LIMIT_SOFT) {
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200434#ifdef AR9170_QUEUE_STOP_DEBUG
435 printk(KERN_DEBUG "%s: wake queue %d\n",
436 wiphy_name(ar->hw->wiphy), queue);
437 __ar9170_dump_txstats(ar);
438#endif /* AR9170_QUEUE_STOP_DEBUG */
439 ieee80211_wake_queue(ar->hw, queue);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100440 }
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200441 spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
442
443 if (arinfo->flags & AR9170_TX_FLAG_BLOCK_ACK) {
Christian Lamparteracbadf02009-07-11 17:24:14 +0200444 ar9170_tx_ampdu_callback(ar, skb);
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200445 } else if (arinfo->flags & AR9170_TX_FLAG_WAIT_FOR_ACK) {
446 arinfo->timeout = jiffies +
447 msecs_to_jiffies(AR9170_TX_TIMEOUT);
448
449 skb_queue_tail(&ar->tx_status[queue], skb);
450 } else if (arinfo->flags & AR9170_TX_FLAG_NO_ACK) {
451 ar9170_tx_status(ar, skb, AR9170_TX_STATUS_FAILED);
452 } else {
453#ifdef AR9170_QUEUE_DEBUG
454 printk(KERN_DEBUG "%s: unsupported frame flags!\n",
455 wiphy_name(ar->hw->wiphy));
456 ar9170_print_txheader(ar, skb);
457#endif /* AR9170_QUEUE_DEBUG */
458 dev_kfree_skb_any(skb);
459 }
460
461 if (!ar->tx_stats[queue].len &&
462 !skb_queue_empty(&ar->tx_pending[queue])) {
463 ar9170_tx(ar);
464 }
Christian Lampartere9348cd2009-03-21 23:05:13 +0100465}
466
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200467static struct sk_buff *ar9170_get_queued_skb(struct ar9170 *ar,
468 const u8 *mac,
469 struct sk_buff_head *queue,
470 const u32 rate)
Christian Lampartere9348cd2009-03-21 23:05:13 +0100471{
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200472 unsigned long flags;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100473 struct sk_buff *skb;
474
475 /*
476 * Unfortunately, the firmware does not tell to which (queued) frame
477 * this transmission status report belongs to.
478 *
479 * So we have to make risky guesses - with the scarce information
480 * the firmware provided (-> destination MAC, and phy_control) -
481 * and hope that we picked the right one...
482 */
Christian Lampartere9348cd2009-03-21 23:05:13 +0100483
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200484 spin_lock_irqsave(&queue->lock, flags);
485 skb_queue_walk(queue, skb) {
486 struct ar9170_tx_control *txc = (void *) skb->data;
487 struct ieee80211_hdr *hdr = (void *) txc->frame_data;
488 u32 r;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100489
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200490 if (mac && compare_ether_addr(ieee80211_get_DA(hdr), mac)) {
491#ifdef AR9170_QUEUE_DEBUG
492 printk(KERN_DEBUG "%s: skip frame => DA %pM != %pM\n",
493 wiphy_name(ar->hw->wiphy), mac,
494 ieee80211_get_DA(hdr));
495 ar9170_print_txheader(ar, skb);
496#endif /* AR9170_QUEUE_DEBUG */
497 continue;
498 }
499
500 r = (le32_to_cpu(txc->phy_control) & AR9170_TX_PHY_MCS_MASK) >>
501 AR9170_TX_PHY_MCS_SHIFT;
502
503 if ((rate != AR9170_TX_INVALID_RATE) && (r != rate)) {
504#ifdef AR9170_QUEUE_DEBUG
505 printk(KERN_DEBUG "%s: skip frame => rate %d != %d\n",
506 wiphy_name(ar->hw->wiphy), rate, r);
507 ar9170_print_txheader(ar, skb);
508#endif /* AR9170_QUEUE_DEBUG */
509 continue;
510 }
511
512 __skb_unlink(skb, queue);
513 spin_unlock_irqrestore(&queue->lock, flags);
514 return skb;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100515 }
Christian Lampartere9348cd2009-03-21 23:05:13 +0100516
517#ifdef AR9170_QUEUE_DEBUG
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200518 printk(KERN_ERR "%s: ESS:[%pM] does not have any "
519 "outstanding frames in queue.\n",
520 wiphy_name(ar->hw->wiphy), mac);
521 __ar9170_dump_txqueue(ar, queue);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100522#endif /* AR9170_QUEUE_DEBUG */
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200523 spin_unlock_irqrestore(&queue->lock, flags);
524
525 return NULL;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100526}
527
Christian Lamparteracbadf02009-07-11 17:24:14 +0200528static void ar9170_handle_block_ack(struct ar9170 *ar, u16 count, u16 r)
529{
530 struct sk_buff *skb;
531 struct ieee80211_tx_info *txinfo;
532
533 while (count) {
534 skb = ar9170_get_queued_skb(ar, NULL, &ar->tx_status_ampdu, r);
535 if (!skb)
536 break;
537
538 txinfo = IEEE80211_SKB_CB(skb);
539 ieee80211_tx_info_clear_status(txinfo);
540
541 /* FIXME: maybe more ? */
542 txinfo->status.rates[0].count = 1;
543
544 skb_pull(skb, sizeof(struct ar9170_tx_control));
545 ieee80211_tx_status_irqsafe(ar->hw, skb);
546 count--;
547 }
548
549#ifdef AR9170_TXAGG_DEBUG
550 if (count) {
551 printk(KERN_DEBUG "%s: got %d more failed mpdus, but no more "
552 "suitable frames left in tx_status queue.\n",
553 wiphy_name(ar->hw->wiphy), count);
554
555 ar9170_dump_tx_status_ampdu(ar);
556 }
557#endif /* AR9170_TXAGG_DEBUG */
558}
559
Christian Lampartere9348cd2009-03-21 23:05:13 +0100560/*
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200561 * This worker tries to keeps an maintain tx_status queues.
562 * So we can guarantee that incoming tx_status reports are
563 * actually for a pending frame.
Christian Lampartere9348cd2009-03-21 23:05:13 +0100564 */
565
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200566static void ar9170_tx_janitor(struct work_struct *work)
Christian Lampartere9348cd2009-03-21 23:05:13 +0100567{
568 struct ar9170 *ar = container_of(work, struct ar9170,
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200569 tx_janitor.work);
570 struct sk_buff_head waste;
571 unsigned int i;
572 bool resched = false;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100573
Christian Lamparter4a48e2a2009-03-23 12:15:43 +0100574 if (unlikely(!IS_STARTED(ar)))
575 return ;
576
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200577 skb_queue_head_init(&waste);
578
579 for (i = 0; i < __AR9170_NUM_TXQ; i++) {
Christian Lampartere9348cd2009-03-21 23:05:13 +0100580#ifdef AR9170_QUEUE_DEBUG
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200581 printk(KERN_DEBUG "%s: garbage collector scans queue:%d\n",
582 wiphy_name(ar->hw->wiphy), i);
583 ar9170_dump_txqueue(ar, &ar->tx_pending[i]);
584 ar9170_dump_txqueue(ar, &ar->tx_status[i]);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100585#endif /* AR9170_QUEUE_DEBUG */
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200586
587 ar9170_recycle_expired(ar, &ar->tx_status[i], &waste);
588 ar9170_recycle_expired(ar, &ar->tx_pending[i], &waste);
589 skb_queue_purge(&waste);
590
591 if (!skb_queue_empty(&ar->tx_status[i]) ||
592 !skb_queue_empty(&ar->tx_pending[i]))
593 resched = true;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100594 }
595
Christian Lamparteracbadf02009-07-11 17:24:14 +0200596 ar9170_tx_fake_ampdu_status(ar);
597
Luis R. Rodriguez42935ec2009-07-29 20:08:07 -0400598 if (!resched)
599 return;
600
601 ieee80211_queue_delayed_work(ar->hw,
602 &ar->tx_janitor,
603 msecs_to_jiffies(AR9170_JANITOR_DELAY));
Christian Lampartere9348cd2009-03-21 23:05:13 +0100604}
605
Christian Lamparter66d00812009-05-28 17:04:27 +0200606void ar9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len)
Christian Lampartere9348cd2009-03-21 23:05:13 +0100607{
608 struct ar9170_cmd_response *cmd = (void *) buf;
609
610 if ((cmd->type & 0xc0) != 0xc0) {
611 ar->callback_cmd(ar, len, buf);
612 return;
613 }
614
615 /* hardware event handlers */
616 switch (cmd->type) {
617 case 0xc1: {
618 /*
619 * TX status notification:
620 * bytes: 0c c1 XX YY M1 M2 M3 M4 M5 M6 R4 R3 R2 R1 S2 S1
621 *
622 * XX always 81
623 * YY always 00
624 * M1-M6 is the MAC address
625 * R1-R4 is the transmit rate
626 * S1-S2 is the transmit status
627 */
628
629 struct sk_buff *skb;
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200630 u32 phy = le32_to_cpu(cmd->tx_status.rate);
631 u32 q = (phy & AR9170_TX_PHY_QOS_MASK) >>
632 AR9170_TX_PHY_QOS_SHIFT;
633#ifdef AR9170_QUEUE_DEBUG
634 printk(KERN_DEBUG "%s: recv tx_status for %pM, p:%08x, q:%d\n",
635 wiphy_name(ar->hw->wiphy), cmd->tx_status.dst, phy, q);
636#endif /* AR9170_QUEUE_DEBUG */
Christian Lampartere9348cd2009-03-21 23:05:13 +0100637
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200638 skb = ar9170_get_queued_skb(ar, cmd->tx_status.dst,
639 &ar->tx_status[q],
640 AR9170_TX_INVALID_RATE);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100641 if (unlikely(!skb))
642 return ;
643
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200644 ar9170_tx_status(ar, skb, le16_to_cpu(cmd->tx_status.status));
Christian Lampartere9348cd2009-03-21 23:05:13 +0100645 break;
646 }
647
648 case 0xc0:
649 /*
650 * pre-TBTT event
651 */
652 if (ar->vif && ar->vif->type == NL80211_IFTYPE_AP)
Luis R. Rodriguez42935ec2009-07-29 20:08:07 -0400653 ieee80211_queue_work(ar->hw, &ar->beacon_work);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100654 break;
655
656 case 0xc2:
657 /*
658 * (IBSS) beacon send notification
659 * bytes: 04 c2 XX YY B4 B3 B2 B1
660 *
661 * XX always 80
662 * YY always 00
663 * B1-B4 "should" be the number of send out beacons.
664 */
665 break;
666
667 case 0xc3:
668 /* End of Atim Window */
669 break;
670
671 case 0xc4:
Christian Lamparteracbadf02009-07-11 17:24:14 +0200672 /* BlockACK bitmap */
673 break;
674
Christian Lampartere9348cd2009-03-21 23:05:13 +0100675 case 0xc5:
676 /* BlockACK events */
Christian Lamparteracbadf02009-07-11 17:24:14 +0200677 ar9170_handle_block_ack(ar,
678 le16_to_cpu(cmd->ba_fail_cnt.failed),
679 le16_to_cpu(cmd->ba_fail_cnt.rate));
680 ar9170_tx_fake_ampdu_status(ar);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100681 break;
682
683 case 0xc6:
684 /* Watchdog Interrupt */
685 break;
686
687 case 0xc9:
688 /* retransmission issue / SIFS/EIFS collision ?! */
689 break;
690
Johannes Berg2543a0c2009-06-05 11:47:43 +0200691 /* firmware debug */
692 case 0xca:
693 printk(KERN_DEBUG "ar9170 FW: %.*s\n", len - 4, (char *)buf + 4);
694 break;
695 case 0xcb:
696 len -= 4;
697
698 switch (len) {
699 case 1:
700 printk(KERN_DEBUG "ar9170 FW: u8: %#.2x\n",
701 *((char *)buf + 4));
702 break;
703 case 2:
704 printk(KERN_DEBUG "ar9170 FW: u8: %#.4x\n",
705 le16_to_cpup((__le16 *)((char *)buf + 4)));
706 break;
707 case 4:
708 printk(KERN_DEBUG "ar9170 FW: u8: %#.8x\n",
709 le32_to_cpup((__le32 *)((char *)buf + 4)));
710 break;
711 case 8:
712 printk(KERN_DEBUG "ar9170 FW: u8: %#.16lx\n",
713 (unsigned long)le64_to_cpup(
714 (__le64 *)((char *)buf + 4)));
715 break;
716 }
717 break;
718 case 0xcc:
719 print_hex_dump_bytes("ar9170 FW:", DUMP_PREFIX_NONE,
720 (char *)buf + 4, len - 4);
721 break;
722
Christian Lampartere9348cd2009-03-21 23:05:13 +0100723 default:
724 printk(KERN_INFO "received unhandled event %x\n", cmd->type);
725 print_hex_dump_bytes("dump:", DUMP_PREFIX_NONE, buf, len);
726 break;
727 }
728}
729
Christian Lampartercca847992009-04-19 01:28:12 +0200730static void ar9170_rx_reset_rx_mpdu(struct ar9170 *ar)
Christian Lampartere9348cd2009-03-21 23:05:13 +0100731{
Christian Lampartercca847992009-04-19 01:28:12 +0200732 memset(&ar->rx_mpdu.plcp, 0, sizeof(struct ar9170_rx_head));
733 ar->rx_mpdu.has_plcp = false;
734}
Christian Lampartere9348cd2009-03-21 23:05:13 +0100735
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +0200736int ar9170_nag_limiter(struct ar9170 *ar)
Christian Lampartercca847992009-04-19 01:28:12 +0200737{
738 bool print_message;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100739
Christian Lampartercca847992009-04-19 01:28:12 +0200740 /*
741 * we expect all sorts of errors in promiscuous mode.
742 * don't bother with it, it's OK!
743 */
744 if (ar->sniffer_enabled)
745 return false;
746
747 /*
748 * only go for frequent errors! The hardware tends to
749 * do some stupid thing once in a while under load, in
750 * noisy environments or just for fun!
751 */
752 if (time_before(jiffies, ar->bad_hw_nagger) && net_ratelimit())
753 print_message = true;
754 else
755 print_message = false;
756
757 /* reset threshold for "once in a while" */
758 ar->bad_hw_nagger = jiffies + HZ / 4;
759 return print_message;
760}
761
762static int ar9170_rx_mac_status(struct ar9170 *ar,
763 struct ar9170_rx_head *head,
764 struct ar9170_rx_macstatus *mac,
765 struct ieee80211_rx_status *status)
766{
767 u8 error, decrypt;
768
Christian Lampartere9348cd2009-03-21 23:05:13 +0100769 BUILD_BUG_ON(sizeof(struct ar9170_rx_head) != 12);
Christian Lampartercca847992009-04-19 01:28:12 +0200770 BUILD_BUG_ON(sizeof(struct ar9170_rx_macstatus) != 4);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100771
Christian Lampartercca847992009-04-19 01:28:12 +0200772 error = mac->error;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100773 if (error & AR9170_RX_ERROR_MMIC) {
Christian Lampartercca847992009-04-19 01:28:12 +0200774 status->flag |= RX_FLAG_MMIC_ERROR;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100775 error &= ~AR9170_RX_ERROR_MMIC;
776 }
777
778 if (error & AR9170_RX_ERROR_PLCP) {
Christian Lampartercca847992009-04-19 01:28:12 +0200779 status->flag |= RX_FLAG_FAILED_PLCP_CRC;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100780 error &= ~AR9170_RX_ERROR_PLCP;
Christian Lampartercca847992009-04-19 01:28:12 +0200781
782 if (!(ar->filter_state & FIF_PLCPFAIL))
783 return -EINVAL;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100784 }
785
786 if (error & AR9170_RX_ERROR_FCS) {
Christian Lampartercca847992009-04-19 01:28:12 +0200787 status->flag |= RX_FLAG_FAILED_FCS_CRC;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100788 error &= ~AR9170_RX_ERROR_FCS;
Christian Lampartercca847992009-04-19 01:28:12 +0200789
790 if (!(ar->filter_state & FIF_FCSFAIL))
791 return -EINVAL;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100792 }
793
Christian Lampartercca847992009-04-19 01:28:12 +0200794 decrypt = ar9170_get_decrypt_type(mac);
Christian Lampartere9348cd2009-03-21 23:05:13 +0100795 if (!(decrypt & AR9170_RX_ENC_SOFTWARE) &&
796 decrypt != AR9170_ENC_ALG_NONE)
Christian Lampartercca847992009-04-19 01:28:12 +0200797 status->flag |= RX_FLAG_DECRYPTED;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100798
799 /* ignore wrong RA errors */
800 error &= ~AR9170_RX_ERROR_WRONG_RA;
801
802 if (error & AR9170_RX_ERROR_DECRYPT) {
803 error &= ~AR9170_RX_ERROR_DECRYPT;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100804 /*
805 * Rx decryption is done in place,
806 * the original data is lost anyway.
807 */
Christian Lampartercca847992009-04-19 01:28:12 +0200808
809 return -EINVAL;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100810 }
811
812 /* drop any other error frames */
Christian Lampartercca847992009-04-19 01:28:12 +0200813 if (unlikely(error)) {
814 /* TODO: update netdevice's RX dropped/errors statistics */
815
816 if (ar9170_nag_limiter(ar))
817 printk(KERN_DEBUG "%s: received frame with "
818 "suspicious error code (%#x).\n",
819 wiphy_name(ar->hw->wiphy), error);
820
821 return -EINVAL;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100822 }
823
Christian Lampartercca847992009-04-19 01:28:12 +0200824 status->band = ar->channel->band;
825 status->freq = ar->channel->center_freq;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100826
Christian Lampartercca847992009-04-19 01:28:12 +0200827 switch (mac->status & AR9170_RX_STATUS_MODULATION_MASK) {
828 case AR9170_RX_STATUS_MODULATION_CCK:
829 if (mac->status & AR9170_RX_STATUS_SHORT_PREAMBLE)
830 status->flag |= RX_FLAG_SHORTPRE;
831 switch (head->plcp[0]) {
832 case 0x0a:
833 status->rate_idx = 0;
834 break;
835 case 0x14:
836 status->rate_idx = 1;
837 break;
838 case 0x37:
839 status->rate_idx = 2;
840 break;
841 case 0x6e:
842 status->rate_idx = 3;
843 break;
844 default:
845 if (ar9170_nag_limiter(ar))
846 printk(KERN_ERR "%s: invalid plcp cck rate "
847 "(%x).\n", wiphy_name(ar->hw->wiphy),
848 head->plcp[0]);
849 return -EINVAL;
850 }
851 break;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100852
Christian Lamparter7d57b732009-11-14 00:57:58 +0100853 case AR9170_RX_STATUS_MODULATION_DUPOFDM:
Christian Lampartercca847992009-04-19 01:28:12 +0200854 case AR9170_RX_STATUS_MODULATION_OFDM:
855 switch (head->plcp[0] & 0xf) {
856 case 0xb:
857 status->rate_idx = 0;
858 break;
859 case 0xf:
860 status->rate_idx = 1;
861 break;
862 case 0xa:
863 status->rate_idx = 2;
864 break;
865 case 0xe:
866 status->rate_idx = 3;
867 break;
868 case 0x9:
869 status->rate_idx = 4;
870 break;
871 case 0xd:
872 status->rate_idx = 5;
873 break;
874 case 0x8:
875 status->rate_idx = 6;
876 break;
877 case 0xc:
878 status->rate_idx = 7;
879 break;
880 default:
881 if (ar9170_nag_limiter(ar))
882 printk(KERN_ERR "%s: invalid plcp ofdm rate "
883 "(%x).\n", wiphy_name(ar->hw->wiphy),
884 head->plcp[0]);
885 return -EINVAL;
886 }
887 if (status->band == IEEE80211_BAND_2GHZ)
888 status->rate_idx += 4;
889 break;
Christian Lampartere9348cd2009-03-21 23:05:13 +0100890
Christian Lampartercca847992009-04-19 01:28:12 +0200891 case AR9170_RX_STATUS_MODULATION_HT:
892 if (head->plcp[3] & 0x80)
893 status->flag |= RX_FLAG_40MHZ;
894 if (head->plcp[6] & 0x80)
895 status->flag |= RX_FLAG_SHORT_GI;
896
897 status->rate_idx = clamp(0, 75, head->plcp[6] & 0x7f);
898 status->flag |= RX_FLAG_HT;
899 break;
900
Christian Lamparter7d57b732009-11-14 00:57:58 +0100901 default:
Christian Lampartercca847992009-04-19 01:28:12 +0200902 if (ar9170_nag_limiter(ar))
903 printk(KERN_ERR "%s: invalid modulation\n",
904 wiphy_name(ar->hw->wiphy));
905 return -EINVAL;
906 }
907
908 return 0;
909}
910
911static void ar9170_rx_phy_status(struct ar9170 *ar,
912 struct ar9170_rx_phystatus *phy,
913 struct ieee80211_rx_status *status)
914{
915 int i;
916
917 BUILD_BUG_ON(sizeof(struct ar9170_rx_phystatus) != 20);
918
919 for (i = 0; i < 3; i++)
920 if (phy->rssi[i] != 0x80)
921 status->antenna |= BIT(i);
922
923 /* post-process RSSI */
924 for (i = 0; i < 7; i++)
925 if (phy->rssi[i] & 0x80)
926 phy->rssi[i] = ((phy->rssi[i] & 0x7f) + 1) & 0x7f;
927
928 /* TODO: we could do something with phy_errors */
929 status->signal = ar->noise[0] + phy->rssi_combined;
930 status->noise = ar->noise[0];
931}
932
933static struct sk_buff *ar9170_rx_copy_data(u8 *buf, int len)
934{
935 struct sk_buff *skb;
936 int reserved = 0;
937 struct ieee80211_hdr *hdr = (void *) buf;
938
939 if (ieee80211_is_data_qos(hdr->frame_control)) {
940 u8 *qc = ieee80211_get_qos_ctl(hdr);
941 reserved += NET_IP_ALIGN;
942
943 if (*qc & IEEE80211_QOS_CONTROL_A_MSDU_PRESENT)
944 reserved += NET_IP_ALIGN;
945 }
946
947 if (ieee80211_has_a4(hdr->frame_control))
948 reserved += NET_IP_ALIGN;
949
950 reserved = 32 + (reserved & NET_IP_ALIGN);
951
952 skb = dev_alloc_skb(len + reserved);
953 if (likely(skb)) {
954 skb_reserve(skb, reserved);
955 memcpy(skb_put(skb, len), buf, len);
956 }
957
958 return skb;
959}
960
961/*
962 * If the frame alignment is right (or the kernel has
963 * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there
964 * is only a single MPDU in the USB frame, then we could
965 * submit to mac80211 the SKB directly. However, since
966 * there may be multiple packets in one SKB in stream
967 * mode, and we need to observe the proper ordering,
968 * this is non-trivial.
969 */
970
971static void ar9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
972{
973 struct ar9170_rx_head *head;
974 struct ar9170_rx_macstatus *mac;
975 struct ar9170_rx_phystatus *phy = NULL;
976 struct ieee80211_rx_status status;
977 struct sk_buff *skb;
978 int mpdu_len;
979
980 if (unlikely(!IS_STARTED(ar) || len < (sizeof(*mac))))
981 return ;
982
983 /* Received MPDU */
984 mpdu_len = len - sizeof(*mac);
985
986 mac = (void *)(buf + mpdu_len);
987 if (unlikely(mac->error & AR9170_RX_ERROR_FATAL)) {
988 /* this frame is too damaged and can't be used - drop it */
989
990 return ;
991 }
992
993 switch (mac->status & AR9170_RX_STATUS_MPDU_MASK) {
994 case AR9170_RX_STATUS_MPDU_FIRST:
995 /* first mpdu packet has the plcp header */
996 if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) {
997 head = (void *) buf;
998 memcpy(&ar->rx_mpdu.plcp, (void *) buf,
999 sizeof(struct ar9170_rx_head));
1000
1001 mpdu_len -= sizeof(struct ar9170_rx_head);
1002 buf += sizeof(struct ar9170_rx_head);
1003 ar->rx_mpdu.has_plcp = true;
1004 } else {
1005 if (ar9170_nag_limiter(ar))
1006 printk(KERN_ERR "%s: plcp info is clipped.\n",
1007 wiphy_name(ar->hw->wiphy));
1008 return ;
1009 }
1010 break;
1011
1012 case AR9170_RX_STATUS_MPDU_LAST:
1013 /* last mpdu has a extra tail with phy status information */
1014
1015 if (likely(mpdu_len >= sizeof(struct ar9170_rx_phystatus))) {
1016 mpdu_len -= sizeof(struct ar9170_rx_phystatus);
1017 phy = (void *)(buf + mpdu_len);
1018 } else {
1019 if (ar9170_nag_limiter(ar))
1020 printk(KERN_ERR "%s: frame tail is clipped.\n",
1021 wiphy_name(ar->hw->wiphy));
1022 return ;
1023 }
1024
1025 case AR9170_RX_STATUS_MPDU_MIDDLE:
1026 /* middle mpdus are just data */
1027 if (unlikely(!ar->rx_mpdu.has_plcp)) {
1028 if (!ar9170_nag_limiter(ar))
1029 return ;
1030
1031 printk(KERN_ERR "%s: rx stream did not start "
1032 "with a first_mpdu frame tag.\n",
1033 wiphy_name(ar->hw->wiphy));
1034
1035 return ;
1036 }
1037
1038 head = &ar->rx_mpdu.plcp;
1039 break;
1040
1041 case AR9170_RX_STATUS_MPDU_SINGLE:
1042 /* single mpdu - has plcp (head) and phy status (tail) */
1043 head = (void *) buf;
1044
1045 mpdu_len -= sizeof(struct ar9170_rx_head);
1046 mpdu_len -= sizeof(struct ar9170_rx_phystatus);
1047
1048 buf += sizeof(struct ar9170_rx_head);
1049 phy = (void *)(buf + mpdu_len);
1050 break;
1051
1052 default:
1053 BUG_ON(1);
1054 break;
1055 }
1056
1057 if (unlikely(mpdu_len < FCS_LEN))
1058 return ;
1059
1060 memset(&status, 0, sizeof(status));
1061 if (unlikely(ar9170_rx_mac_status(ar, head, mac, &status)))
1062 return ;
1063
1064 if (phy)
1065 ar9170_rx_phy_status(ar, phy, &status);
1066
1067 skb = ar9170_rx_copy_data(buf, mpdu_len);
Johannes Bergf1d58c22009-06-17 13:13:00 +02001068 if (likely(skb)) {
1069 memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status));
1070 ieee80211_rx_irqsafe(ar->hw, skb);
1071 }
Christian Lampartere9348cd2009-03-21 23:05:13 +01001072}
1073
Christian Lampartere9348cd2009-03-21 23:05:13 +01001074void ar9170_rx(struct ar9170 *ar, struct sk_buff *skb)
1075{
Christian Lampartercca847992009-04-19 01:28:12 +02001076 unsigned int i, tlen, resplen, wlen = 0, clen = 0;
Christian Lampartere9348cd2009-03-21 23:05:13 +01001077 u8 *tbuf, *respbuf;
1078
1079 tbuf = skb->data;
1080 tlen = skb->len;
1081
1082 while (tlen >= 4) {
Christian Lampartercca847992009-04-19 01:28:12 +02001083 clen = tbuf[1] << 8 | tbuf[0];
1084 wlen = ALIGN(clen, 4);
Christian Lampartere9348cd2009-03-21 23:05:13 +01001085
Christian Lampartercca847992009-04-19 01:28:12 +02001086 /* check if this is stream has a valid tag.*/
Christian Lampartere9348cd2009-03-21 23:05:13 +01001087 if (tbuf[2] != 0 || tbuf[3] != 0x4e) {
Christian Lampartercca847992009-04-19 01:28:12 +02001088 /*
1089 * TODO: handle the highly unlikely event that the
1090 * corrupted stream has the TAG at the right position.
1091 */
1092
1093 /* check if the frame can be repaired. */
1094 if (!ar->rx_failover_missing) {
1095 /* this is no "short read". */
1096 if (ar9170_nag_limiter(ar)) {
1097 printk(KERN_ERR "%s: missing tag!\n",
1098 wiphy_name(ar->hw->wiphy));
1099 goto err_telluser;
1100 } else
1101 goto err_silent;
1102 }
1103
1104 if (ar->rx_failover_missing > tlen) {
1105 if (ar9170_nag_limiter(ar)) {
1106 printk(KERN_ERR "%s: possible multi "
1107 "stream corruption!\n",
1108 wiphy_name(ar->hw->wiphy));
1109 goto err_telluser;
1110 } else
1111 goto err_silent;
1112 }
1113
1114 memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen);
1115 ar->rx_failover_missing -= tlen;
1116
1117 if (ar->rx_failover_missing <= 0) {
1118 /*
1119 * nested ar9170_rx call!
1120 * termination is guranteed, even when the
1121 * combined frame also have a element with
1122 * a bad tag.
1123 */
1124
1125 ar->rx_failover_missing = 0;
1126 ar9170_rx(ar, ar->rx_failover);
1127
1128 skb_reset_tail_pointer(ar->rx_failover);
1129 skb_trim(ar->rx_failover, 0);
1130 }
1131
Christian Lampartere9348cd2009-03-21 23:05:13 +01001132 return ;
1133 }
Christian Lampartercca847992009-04-19 01:28:12 +02001134
1135 /* check if stream is clipped */
Christian Lampartere9348cd2009-03-21 23:05:13 +01001136 if (wlen > tlen - 4) {
Christian Lampartercca847992009-04-19 01:28:12 +02001137 if (ar->rx_failover_missing) {
1138 /* TODO: handle double stream corruption. */
1139 if (ar9170_nag_limiter(ar)) {
1140 printk(KERN_ERR "%s: double rx stream "
1141 "corruption!\n",
1142 wiphy_name(ar->hw->wiphy));
1143 goto err_telluser;
1144 } else
1145 goto err_silent;
1146 }
1147
1148 /*
1149 * save incomplete data set.
1150 * the firmware will resend the missing bits when
1151 * the rx - descriptor comes round again.
1152 */
1153
1154 memcpy(skb_put(ar->rx_failover, tlen), tbuf, tlen);
1155 ar->rx_failover_missing = clen - tlen;
Christian Lampartere9348cd2009-03-21 23:05:13 +01001156 return ;
1157 }
1158 resplen = clen;
1159 respbuf = tbuf + 4;
1160 tbuf += wlen + 4;
1161 tlen -= wlen + 4;
1162
1163 i = 0;
1164
1165 /* weird thing, but this is the same in the original driver */
1166 while (resplen > 2 && i < 12 &&
1167 respbuf[0] == 0xff && respbuf[1] == 0xff) {
1168 i += 2;
1169 resplen -= 2;
1170 respbuf += 2;
1171 }
1172
1173 if (resplen < 4)
1174 continue;
1175
1176 /* found the 6 * 0xffff marker? */
1177 if (i == 12)
1178 ar9170_handle_command_response(ar, respbuf, resplen);
1179 else
Christian Lampartercca847992009-04-19 01:28:12 +02001180 ar9170_handle_mpdu(ar, respbuf, clen);
Christian Lampartere9348cd2009-03-21 23:05:13 +01001181 }
1182
Christian Lampartercca847992009-04-19 01:28:12 +02001183 if (tlen) {
1184 if (net_ratelimit())
1185 printk(KERN_ERR "%s: %d bytes of unprocessed "
1186 "data left in rx stream!\n",
1187 wiphy_name(ar->hw->wiphy), tlen);
1188
1189 goto err_telluser;
1190 }
1191
1192 return ;
1193
1194err_telluser:
1195 printk(KERN_ERR "%s: damaged RX stream data [want:%d, "
1196 "data:%d, rx:%d, pending:%d ]\n",
1197 wiphy_name(ar->hw->wiphy), clen, wlen, tlen,
1198 ar->rx_failover_missing);
1199
1200 if (ar->rx_failover_missing)
1201 print_hex_dump_bytes("rxbuf:", DUMP_PREFIX_OFFSET,
1202 ar->rx_failover->data,
1203 ar->rx_failover->len);
1204
1205 print_hex_dump_bytes("stream:", DUMP_PREFIX_OFFSET,
1206 skb->data, skb->len);
1207
1208 printk(KERN_ERR "%s: please check your hardware and cables, if "
1209 "you see this message frequently.\n",
1210 wiphy_name(ar->hw->wiphy));
1211
1212err_silent:
1213 if (ar->rx_failover_missing) {
1214 skb_reset_tail_pointer(ar->rx_failover);
1215 skb_trim(ar->rx_failover, 0);
1216 ar->rx_failover_missing = 0;
1217 }
Christian Lampartere9348cd2009-03-21 23:05:13 +01001218}
Christian Lampartere9348cd2009-03-21 23:05:13 +01001219
1220#define AR9170_FILL_QUEUE(queue, ai_fs, cwmin, cwmax, _txop) \
1221do { \
1222 queue.aifs = ai_fs; \
1223 queue.cw_min = cwmin; \
1224 queue.cw_max = cwmax; \
1225 queue.txop = _txop; \
1226} while (0)
1227
1228static int ar9170_op_start(struct ieee80211_hw *hw)
1229{
1230 struct ar9170 *ar = hw->priv;
1231 int err, i;
1232
1233 mutex_lock(&ar->mutex);
1234
1235 /* reinitialize queues statistics */
1236 memset(&ar->tx_stats, 0, sizeof(ar->tx_stats));
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001237 for (i = 0; i < __AR9170_NUM_TXQ; i++)
1238 ar->tx_stats[i].limit = AR9170_TXQ_DEPTH;
Christian Lampartere9348cd2009-03-21 23:05:13 +01001239
1240 /* reset QoS defaults */
1241 AR9170_FILL_QUEUE(ar->edcf[0], 3, 15, 1023, 0); /* BEST EFFORT*/
1242 AR9170_FILL_QUEUE(ar->edcf[1], 7, 15, 1023, 0); /* BACKGROUND */
1243 AR9170_FILL_QUEUE(ar->edcf[2], 2, 7, 15, 94); /* VIDEO */
1244 AR9170_FILL_QUEUE(ar->edcf[3], 2, 3, 7, 47); /* VOICE */
1245 AR9170_FILL_QUEUE(ar->edcf[4], 2, 3, 7, 0); /* SPECIAL */
1246
Christian Lamparteracbadf02009-07-11 17:24:14 +02001247 /* set sane AMPDU defaults */
1248 ar->global_ampdu_density = 6;
1249 ar->global_ampdu_factor = 3;
1250
Christian Lamparter02bdf5b2009-10-17 21:56:43 +02001251 atomic_set(&ar->tx_ampdu_pending, 0);
Christian Lampartercca847992009-04-19 01:28:12 +02001252 ar->bad_hw_nagger = jiffies;
1253
Christian Lampartere9348cd2009-03-21 23:05:13 +01001254 err = ar->open(ar);
1255 if (err)
1256 goto out;
1257
1258 err = ar9170_init_mac(ar);
1259 if (err)
1260 goto out;
1261
1262 err = ar9170_set_qos(ar);
1263 if (err)
1264 goto out;
1265
1266 err = ar9170_init_phy(ar, IEEE80211_BAND_2GHZ);
1267 if (err)
1268 goto out;
1269
1270 err = ar9170_init_rf(ar);
1271 if (err)
1272 goto out;
1273
1274 /* start DMA */
1275 err = ar9170_write_reg(ar, 0x1c3d30, 0x100);
1276 if (err)
1277 goto out;
1278
1279 ar->state = AR9170_STARTED;
1280
1281out:
1282 mutex_unlock(&ar->mutex);
1283 return err;
1284}
1285
1286static void ar9170_op_stop(struct ieee80211_hw *hw)
1287{
1288 struct ar9170 *ar = hw->priv;
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001289 unsigned int i;
Christian Lampartere9348cd2009-03-21 23:05:13 +01001290
1291 if (IS_STARTED(ar))
1292 ar->state = AR9170_IDLE;
1293
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001294 cancel_delayed_work_sync(&ar->tx_janitor);
Alexander Beregalovff8365c2009-07-24 11:55:44 +04001295#ifdef CONFIG_AR9170_LEDS
Christian Lamparteracbadf02009-07-11 17:24:14 +02001296 cancel_delayed_work_sync(&ar->led_work);
Alexander Beregalovff8365c2009-07-24 11:55:44 +04001297#endif
Christian Lampartere9348cd2009-03-21 23:05:13 +01001298 cancel_work_sync(&ar->beacon_work);
Luis R. Rodrigueze351cfb2009-07-27 12:51:37 -07001299
Christian Lamparterb55d6bc2009-05-23 20:31:21 +02001300 mutex_lock(&ar->mutex);
Christian Lampartere9348cd2009-03-21 23:05:13 +01001301
1302 if (IS_ACCEPTING_CMD(ar)) {
1303 ar9170_set_leds_state(ar, 0);
1304
1305 /* stop DMA */
1306 ar9170_write_reg(ar, 0x1c3d30, 0);
1307 ar->stop(ar);
1308 }
1309
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001310 for (i = 0; i < __AR9170_NUM_TXQ; i++) {
1311 skb_queue_purge(&ar->tx_pending[i]);
1312 skb_queue_purge(&ar->tx_status[i]);
1313 }
Christian Lamparteracbadf02009-07-11 17:24:14 +02001314 skb_queue_purge(&ar->tx_status_ampdu);
1315
Christian Lampartere9348cd2009-03-21 23:05:13 +01001316 mutex_unlock(&ar->mutex);
1317}
1318
Christian Lamparteracbadf02009-07-11 17:24:14 +02001319static void ar9170_tx_indicate_immba(struct ar9170 *ar, struct sk_buff *skb)
1320{
1321 struct ar9170_tx_control *txc = (void *) skb->data;
1322
1323 txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_IMM_AMPDU);
1324}
1325
1326static void ar9170_tx_copy_phy(struct ar9170 *ar, struct sk_buff *dst,
1327 struct sk_buff *src)
1328{
1329 struct ar9170_tx_control *dst_txc, *src_txc;
1330 struct ieee80211_tx_info *dst_info, *src_info;
1331 struct ar9170_tx_info *dst_arinfo, *src_arinfo;
1332
1333 src_txc = (void *) src->data;
1334 src_info = IEEE80211_SKB_CB(src);
1335 src_arinfo = (void *) src_info->rate_driver_data;
1336
1337 dst_txc = (void *) dst->data;
1338 dst_info = IEEE80211_SKB_CB(dst);
1339 dst_arinfo = (void *) dst_info->rate_driver_data;
1340
1341 dst_txc->phy_control = src_txc->phy_control;
1342
1343 /* same MCS for the whole aggregate */
1344 memcpy(dst_info->driver_rates, src_info->driver_rates,
1345 sizeof(dst_info->driver_rates));
1346}
1347
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001348static int ar9170_tx_prepare(struct ar9170 *ar, struct sk_buff *skb)
Christian Lampartere9348cd2009-03-21 23:05:13 +01001349{
Christian Lampartere9348cd2009-03-21 23:05:13 +01001350 struct ieee80211_hdr *hdr;
1351 struct ar9170_tx_control *txc;
1352 struct ieee80211_tx_info *info;
Christian Lampartere9348cd2009-03-21 23:05:13 +01001353 struct ieee80211_tx_rate *txrate;
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001354 struct ar9170_tx_info *arinfo;
Christian Lampartere9348cd2009-03-21 23:05:13 +01001355 unsigned int queue = skb_get_queue_mapping(skb);
Christian Lampartere9348cd2009-03-21 23:05:13 +01001356 u16 keytype = 0;
1357 u16 len, icv = 0;
Christian Lampartere9348cd2009-03-21 23:05:13 +01001358
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001359 BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data));
Christian Lampartere9348cd2009-03-21 23:05:13 +01001360
1361 hdr = (void *)skb->data;
1362 info = IEEE80211_SKB_CB(skb);
1363 len = skb->len;
1364
Christian Lampartere9348cd2009-03-21 23:05:13 +01001365 txc = (void *)skb_push(skb, sizeof(*txc));
1366
Christian Lampartere9348cd2009-03-21 23:05:13 +01001367 if (info->control.hw_key) {
1368 icv = info->control.hw_key->icv_len;
1369
1370 switch (info->control.hw_key->alg) {
1371 case ALG_WEP:
1372 keytype = AR9170_TX_MAC_ENCR_RC4;
1373 break;
1374 case ALG_TKIP:
1375 keytype = AR9170_TX_MAC_ENCR_RC4;
1376 break;
1377 case ALG_CCMP:
1378 keytype = AR9170_TX_MAC_ENCR_AES;
1379 break;
1380 default:
1381 WARN_ON(1);
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001382 goto err_out;
Christian Lampartere9348cd2009-03-21 23:05:13 +01001383 }
1384 }
1385
1386 /* Length */
1387 txc->length = cpu_to_le16(len + icv + 4);
1388
1389 txc->mac_control = cpu_to_le16(AR9170_TX_MAC_HW_DURATION |
1390 AR9170_TX_MAC_BACKOFF);
1391 txc->mac_control |= cpu_to_le16(ar9170_qos_hwmap[queue] <<
1392 AR9170_TX_MAC_QOS_SHIFT);
1393 txc->mac_control |= cpu_to_le16(keytype);
1394 txc->phy_control = cpu_to_le32(0);
1395
1396 if (info->flags & IEEE80211_TX_CTL_NO_ACK)
1397 txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_NO_ACK);
1398
Christian Lampartere9348cd2009-03-21 23:05:13 +01001399 txrate = &info->control.rates[0];
Christian Lampartere9348cd2009-03-21 23:05:13 +01001400 if (txrate->flags & IEEE80211_TX_RC_USE_CTS_PROTECT)
1401 txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_CTS);
1402 else if (txrate->flags & IEEE80211_TX_RC_USE_RTS_CTS)
1403 txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_PROT_RTS);
1404
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001405 arinfo = (void *)info->rate_driver_data;
1406 arinfo->timeout = jiffies + msecs_to_jiffies(AR9170_QUEUE_TIMEOUT);
1407
1408 if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) &&
1409 (is_valid_ether_addr(ieee80211_get_DA(hdr)))) {
1410 if (info->flags & IEEE80211_TX_CTL_AMPDU) {
1411 if (unlikely(!info->control.sta))
1412 goto err_out;
1413
1414 txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_AGGR);
1415 arinfo->flags = AR9170_TX_FLAG_BLOCK_ACK;
Christian Lamparteracbadf02009-07-11 17:24:14 +02001416
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001417 goto out;
1418 }
1419
1420 txc->mac_control |= cpu_to_le16(AR9170_TX_MAC_RATE_PROBE);
1421 /*
1422 * WARNING:
1423 * Putting the QoS queue bits into an unexplored territory is
1424 * certainly not elegant.
1425 *
1426 * In my defense: This idea provides a reasonable way to
1427 * smuggle valuable information to the tx_status callback.
1428 * Also, the idea behind this bit-abuse came straight from
1429 * the original driver code.
1430 */
1431
1432 txc->phy_control |=
1433 cpu_to_le32(queue << AR9170_TX_PHY_QOS_SHIFT);
1434 arinfo->flags = AR9170_TX_FLAG_WAIT_FOR_ACK;
1435 } else {
1436 arinfo->flags = AR9170_TX_FLAG_NO_ACK;
1437 }
1438
1439out:
1440 return 0;
1441
1442err_out:
1443 skb_pull(skb, sizeof(*txc));
1444 return -EINVAL;
1445}
1446
1447static void ar9170_tx_prepare_phy(struct ar9170 *ar, struct sk_buff *skb)
1448{
1449 struct ar9170_tx_control *txc;
1450 struct ieee80211_tx_info *info;
1451 struct ieee80211_rate *rate = NULL;
1452 struct ieee80211_tx_rate *txrate;
1453 u32 power, chains;
1454
1455 txc = (void *) skb->data;
1456 info = IEEE80211_SKB_CB(skb);
1457 txrate = &info->control.rates[0];
1458
Christian Lampartere9348cd2009-03-21 23:05:13 +01001459 if (txrate->flags & IEEE80211_TX_RC_GREEN_FIELD)
1460 txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_GREENFIELD);
1461
1462 if (txrate->flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
1463 txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_PREAMBLE);
1464
1465 if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
1466 txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ);
1467 /* this works because 40 MHz is 2 and dup is 3 */
1468 if (txrate->flags & IEEE80211_TX_RC_DUP_DATA)
1469 txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_BW_40MHZ_DUP);
1470
1471 if (txrate->flags & IEEE80211_TX_RC_SHORT_GI)
1472 txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_SHORT_GI);
1473
1474 if (txrate->flags & IEEE80211_TX_RC_MCS) {
1475 u32 r = txrate->idx;
1476 u8 *txpower;
1477
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001478 /* heavy clip control */
1479 txc->phy_control |= cpu_to_le32((r & 0x7) << 7);
1480
Christian Lampartere9348cd2009-03-21 23:05:13 +01001481 r <<= AR9170_TX_PHY_MCS_SHIFT;
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001482 BUG_ON(r & ~AR9170_TX_PHY_MCS_MASK);
1483
Christian Lampartere9348cd2009-03-21 23:05:13 +01001484 txc->phy_control |= cpu_to_le32(r & AR9170_TX_PHY_MCS_MASK);
1485 txc->phy_control |= cpu_to_le32(AR9170_TX_PHY_MOD_HT);
1486
1487 if (txrate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) {
1488 if (info->band == IEEE80211_BAND_5GHZ)
1489 txpower = ar->power_5G_ht40;
1490 else
1491 txpower = ar->power_2G_ht40;
1492 } else {
1493 if (info->band == IEEE80211_BAND_5GHZ)
1494 txpower = ar->power_5G_ht20;
1495 else
1496 txpower = ar->power_2G_ht20;
1497 }
1498
1499 power = txpower[(txrate->idx) & 7];
1500 } else {
1501 u8 *txpower;
1502 u32 mod;
1503 u32 phyrate;
1504 u8 idx = txrate->idx;
1505
1506 if (info->band != IEEE80211_BAND_2GHZ) {
1507 idx += 4;
1508 txpower = ar->power_5G_leg;
1509 mod = AR9170_TX_PHY_MOD_OFDM;
1510 } else {
1511 if (idx < 4) {
1512 txpower = ar->power_2G_cck;
1513 mod = AR9170_TX_PHY_MOD_CCK;
1514 } else {
1515 mod = AR9170_TX_PHY_MOD_OFDM;
1516 txpower = ar->power_2G_ofdm;
1517 }
1518 }
1519
1520 rate = &__ar9170_ratetable[idx];
1521
1522 phyrate = rate->hw_value & 0xF;
1523 power = txpower[(rate->hw_value & 0x30) >> 4];
1524 phyrate <<= AR9170_TX_PHY_MCS_SHIFT;
1525
1526 txc->phy_control |= cpu_to_le32(mod);
1527 txc->phy_control |= cpu_to_le32(phyrate);
1528 }
1529
1530 power <<= AR9170_TX_PHY_TX_PWR_SHIFT;
1531 power &= AR9170_TX_PHY_TX_PWR_MASK;
1532 txc->phy_control |= cpu_to_le32(power);
1533
1534 /* set TX chains */
1535 if (ar->eeprom.tx_mask == 1) {
1536 chains = AR9170_TX_PHY_TXCHAIN_1;
1537 } else {
1538 chains = AR9170_TX_PHY_TXCHAIN_2;
1539
1540 /* >= 36M legacy OFDM - use only one chain */
1541 if (rate && rate->bitrate >= 360)
1542 chains = AR9170_TX_PHY_TXCHAIN_1;
1543 }
1544 txc->phy_control |= cpu_to_le32(chains << AR9170_TX_PHY_TXCHAIN_SHIFT);
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001545}
Christian Lampartere9348cd2009-03-21 23:05:13 +01001546
Christian Lamparteracbadf02009-07-11 17:24:14 +02001547static bool ar9170_tx_ampdu(struct ar9170 *ar)
1548{
1549 struct sk_buff_head agg;
1550 struct ar9170_sta_tid *tid_info = NULL, *tmp;
1551 struct sk_buff *skb, *first = NULL;
1552 unsigned long flags, f2;
1553 unsigned int i = 0;
1554 u16 seq, queue, tmpssn;
1555 bool run = false;
1556
1557 skb_queue_head_init(&agg);
1558
1559 spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
1560 if (list_empty(&ar->tx_ampdu_list)) {
1561#ifdef AR9170_TXAGG_DEBUG
1562 printk(KERN_DEBUG "%s: aggregation list is empty.\n",
1563 wiphy_name(ar->hw->wiphy));
1564#endif /* AR9170_TXAGG_DEBUG */
1565 goto out_unlock;
1566 }
1567
1568 list_for_each_entry_safe(tid_info, tmp, &ar->tx_ampdu_list, list) {
1569 if (tid_info->state != AR9170_TID_STATE_COMPLETE) {
1570#ifdef AR9170_TXAGG_DEBUG
1571 printk(KERN_DEBUG "%s: dangling aggregation entry!\n",
1572 wiphy_name(ar->hw->wiphy));
1573#endif /* AR9170_TXAGG_DEBUG */
1574 continue;
1575 }
1576
1577 if (++i > 64) {
1578#ifdef AR9170_TXAGG_DEBUG
1579 printk(KERN_DEBUG "%s: enough frames aggregated.\n",
1580 wiphy_name(ar->hw->wiphy));
1581#endif /* AR9170_TXAGG_DEBUG */
1582 break;
1583 }
1584
1585 queue = TID_TO_WME_AC(tid_info->tid);
1586
1587 if (skb_queue_len(&ar->tx_pending[queue]) >=
1588 AR9170_NUM_TX_AGG_MAX) {
1589#ifdef AR9170_TXAGG_DEBUG
1590 printk(KERN_DEBUG "%s: queue %d full.\n",
1591 wiphy_name(ar->hw->wiphy), queue);
1592#endif /* AR9170_TXAGG_DEBUG */
1593 continue;
1594 }
1595
1596 list_del_init(&tid_info->list);
1597
1598 spin_lock_irqsave(&tid_info->queue.lock, f2);
1599 tmpssn = seq = tid_info->ssn;
1600 first = skb_peek(&tid_info->queue);
1601
1602 if (likely(first))
1603 tmpssn = ar9170_get_seq(first);
1604
1605 if (unlikely(tmpssn != seq)) {
1606#ifdef AR9170_TXAGG_DEBUG
1607 printk(KERN_DEBUG "%s: ssn mismatch [%d != %d]\n.",
1608 wiphy_name(ar->hw->wiphy), seq, tmpssn);
1609#endif /* AR9170_TXAGG_DEBUG */
1610 tid_info->ssn = tmpssn;
1611 }
1612
1613#ifdef AR9170_TXAGG_DEBUG
1614 printk(KERN_DEBUG "%s: generate A-MPDU for tid:%d ssn:%d with "
1615 "%d queued frames.\n", wiphy_name(ar->hw->wiphy),
1616 tid_info->tid, tid_info->ssn,
1617 skb_queue_len(&tid_info->queue));
1618 __ar9170_dump_txqueue(ar, &tid_info->queue);
1619#endif /* AR9170_TXAGG_DEBUG */
1620
1621 while ((skb = skb_peek(&tid_info->queue))) {
1622 if (unlikely(ar9170_get_seq(skb) != seq))
1623 break;
1624
1625 __skb_unlink(skb, &tid_info->queue);
1626 tid_info->ssn = seq = GET_NEXT_SEQ(seq);
1627
1628 if (unlikely(skb_get_queue_mapping(skb) != queue)) {
1629#ifdef AR9170_TXAGG_DEBUG
1630 printk(KERN_DEBUG "%s: tid:%d(q:%d) queue:%d "
1631 "!match.\n", wiphy_name(ar->hw->wiphy),
1632 tid_info->tid,
1633 TID_TO_WME_AC(tid_info->tid),
1634 skb_get_queue_mapping(skb));
1635#endif /* AR9170_TXAGG_DEBUG */
1636 dev_kfree_skb_any(skb);
1637 continue;
1638 }
1639
1640 if (unlikely(first == skb)) {
1641 ar9170_tx_prepare_phy(ar, skb);
1642 __skb_queue_tail(&agg, skb);
1643 first = skb;
1644 } else {
1645 ar9170_tx_copy_phy(ar, skb, first);
1646 __skb_queue_tail(&agg, skb);
1647 }
1648
1649 if (unlikely(skb_queue_len(&agg) ==
1650 AR9170_NUM_TX_AGG_MAX))
1651 break;
1652 }
1653
1654 if (skb_queue_empty(&tid_info->queue))
1655 tid_info->active = false;
1656 else
1657 list_add_tail(&tid_info->list,
1658 &ar->tx_ampdu_list);
1659
1660 spin_unlock_irqrestore(&tid_info->queue.lock, f2);
1661
1662 if (unlikely(skb_queue_empty(&agg))) {
1663#ifdef AR9170_TXAGG_DEBUG
1664 printk(KERN_DEBUG "%s: queued empty list!\n",
1665 wiphy_name(ar->hw->wiphy));
1666#endif /* AR9170_TXAGG_DEBUG */
1667 continue;
1668 }
1669
1670 /*
1671 * tell the FW/HW that this is the last frame,
1672 * that way it will wait for the immediate block ack.
1673 */
1674 if (likely(skb_peek_tail(&agg)))
1675 ar9170_tx_indicate_immba(ar, skb_peek_tail(&agg));
1676
1677#ifdef AR9170_TXAGG_DEBUG
1678 printk(KERN_DEBUG "%s: generated A-MPDU looks like this:\n",
1679 wiphy_name(ar->hw->wiphy));
1680 __ar9170_dump_txqueue(ar, &agg);
1681#endif /* AR9170_TXAGG_DEBUG */
1682
1683 spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
1684
1685 spin_lock_irqsave(&ar->tx_pending[queue].lock, flags);
1686 skb_queue_splice_tail_init(&agg, &ar->tx_pending[queue]);
1687 spin_unlock_irqrestore(&ar->tx_pending[queue].lock, flags);
1688 run = true;
1689
1690 spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
1691 }
1692
1693out_unlock:
1694 spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
1695 __skb_queue_purge(&agg);
1696
1697 return run;
1698}
1699
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001700static void ar9170_tx(struct ar9170 *ar)
1701{
1702 struct sk_buff *skb;
1703 unsigned long flags;
1704 struct ieee80211_tx_info *info;
1705 struct ar9170_tx_info *arinfo;
1706 unsigned int i, frames, frames_failed, remaining_space;
1707 int err;
1708 bool schedule_garbagecollector = false;
Christian Lampartere9348cd2009-03-21 23:05:13 +01001709
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001710 BUILD_BUG_ON(sizeof(*arinfo) > sizeof(info->rate_driver_data));
Christian Lampartere9348cd2009-03-21 23:05:13 +01001711
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001712 if (unlikely(!IS_STARTED(ar)))
1713 return ;
Christian Lampartere9348cd2009-03-21 23:05:13 +01001714
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001715 remaining_space = AR9170_TX_MAX_PENDING;
1716
1717 for (i = 0; i < __AR9170_NUM_TXQ; i++) {
1718 spin_lock_irqsave(&ar->tx_stats_lock, flags);
Christian Lamparter53a76b52009-11-29 00:52:51 +01001719 frames = min(ar->tx_stats[i].limit - ar->tx_stats[i].len,
1720 skb_queue_len(&ar->tx_pending[i]));
1721
1722 if (remaining_space < frames) {
1723#ifdef AR9170_QUEUE_DEBUG
1724 printk(KERN_DEBUG "%s: tx quota reached queue:%d, "
1725 "remaining slots:%d, needed:%d\n",
1726 wiphy_name(ar->hw->wiphy), i, remaining_space,
1727 frames);
1728#endif /* AR9170_QUEUE_DEBUG */
1729 frames = remaining_space;
1730 }
1731
1732 ar->tx_stats[i].len += frames;
1733 ar->tx_stats[i].count += frames;
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001734 if (ar->tx_stats[i].len >= ar->tx_stats[i].limit) {
1735#ifdef AR9170_QUEUE_DEBUG
1736 printk(KERN_DEBUG "%s: queue %d full\n",
1737 wiphy_name(ar->hw->wiphy), i);
1738
Christian Lamparteracbadf02009-07-11 17:24:14 +02001739 printk(KERN_DEBUG "%s: stuck frames: ===> \n",
1740 wiphy_name(ar->hw->wiphy));
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001741 ar9170_dump_txqueue(ar, &ar->tx_pending[i]);
1742 ar9170_dump_txqueue(ar, &ar->tx_status[i]);
1743#endif /* AR9170_QUEUE_DEBUG */
Christian Lamparteracbadf02009-07-11 17:24:14 +02001744
1745#ifdef AR9170_QUEUE_STOP_DEBUG
1746 printk(KERN_DEBUG "%s: stop queue %d\n",
1747 wiphy_name(ar->hw->wiphy), i);
1748 __ar9170_dump_txstats(ar);
1749#endif /* AR9170_QUEUE_STOP_DEBUG */
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001750 ieee80211_stop_queue(ar->hw, i);
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001751 }
1752
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001753 spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
1754
1755 if (!frames)
1756 continue;
1757
1758 frames_failed = 0;
1759 while (frames) {
1760 skb = skb_dequeue(&ar->tx_pending[i]);
1761 if (unlikely(!skb)) {
1762 frames_failed += frames;
1763 frames = 0;
1764 break;
1765 }
1766
1767 info = IEEE80211_SKB_CB(skb);
1768 arinfo = (void *) info->rate_driver_data;
1769
1770 /* TODO: cancel stuck frames */
1771 arinfo->timeout = jiffies +
1772 msecs_to_jiffies(AR9170_TX_TIMEOUT);
1773
Christian Lamparteracbadf02009-07-11 17:24:14 +02001774 if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK)
Christian Lamparter02bdf5b2009-10-17 21:56:43 +02001775 atomic_inc(&ar->tx_ampdu_pending);
Christian Lamparteracbadf02009-07-11 17:24:14 +02001776
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001777#ifdef AR9170_QUEUE_DEBUG
1778 printk(KERN_DEBUG "%s: send frame q:%d =>\n",
1779 wiphy_name(ar->hw->wiphy), i);
1780 ar9170_print_txheader(ar, skb);
1781#endif /* AR9170_QUEUE_DEBUG */
1782
1783 err = ar->tx(ar, skb);
1784 if (unlikely(err)) {
Christian Lamparteracbadf02009-07-11 17:24:14 +02001785 if (arinfo->flags == AR9170_TX_FLAG_BLOCK_ACK)
Christian Lamparter02bdf5b2009-10-17 21:56:43 +02001786 atomic_dec(&ar->tx_ampdu_pending);
Christian Lamparteracbadf02009-07-11 17:24:14 +02001787
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001788 frames_failed++;
1789 dev_kfree_skb_any(skb);
1790 } else {
1791 remaining_space--;
1792 schedule_garbagecollector = true;
1793 }
1794
1795 frames--;
1796 }
1797
1798#ifdef AR9170_QUEUE_DEBUG
1799 printk(KERN_DEBUG "%s: ar9170_tx report for queue %d\n",
1800 wiphy_name(ar->hw->wiphy), i);
1801
1802 printk(KERN_DEBUG "%s: unprocessed pending frames left:\n",
1803 wiphy_name(ar->hw->wiphy));
1804 ar9170_dump_txqueue(ar, &ar->tx_pending[i]);
1805#endif /* AR9170_QUEUE_DEBUG */
1806
1807 if (unlikely(frames_failed)) {
1808#ifdef AR9170_QUEUE_DEBUG
Christian Lamparteracbadf02009-07-11 17:24:14 +02001809 printk(KERN_DEBUG "%s: frames failed %d =>\n",
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001810 wiphy_name(ar->hw->wiphy), frames_failed);
1811#endif /* AR9170_QUEUE_DEBUG */
1812
1813 spin_lock_irqsave(&ar->tx_stats_lock, flags);
1814 ar->tx_stats[i].len -= frames_failed;
1815 ar->tx_stats[i].count -= frames_failed;
Christian Lamparteracbadf02009-07-11 17:24:14 +02001816#ifdef AR9170_QUEUE_STOP_DEBUG
1817 printk(KERN_DEBUG "%s: wake queue %d\n",
1818 wiphy_name(ar->hw->wiphy), i);
1819 __ar9170_dump_txstats(ar);
1820#endif /* AR9170_QUEUE_STOP_DEBUG */
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001821 ieee80211_wake_queue(ar->hw, i);
1822 spin_unlock_irqrestore(&ar->tx_stats_lock, flags);
Christian Lampartere9348cd2009-03-21 23:05:13 +01001823 }
1824 }
1825
Luis R. Rodriguez42935ec2009-07-29 20:08:07 -04001826 if (!schedule_garbagecollector)
1827 return;
1828
1829 ieee80211_queue_delayed_work(ar->hw,
1830 &ar->tx_janitor,
1831 msecs_to_jiffies(AR9170_JANITOR_DELAY));
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001832}
1833
Christian Lamparteracbadf02009-07-11 17:24:14 +02001834static bool ar9170_tx_ampdu_queue(struct ar9170 *ar, struct sk_buff *skb)
1835{
1836 struct ieee80211_tx_info *txinfo;
1837 struct ar9170_sta_info *sta_info;
1838 struct ar9170_sta_tid *agg;
1839 struct sk_buff *iter;
1840 unsigned long flags, f2;
1841 unsigned int max;
1842 u16 tid, seq, qseq;
1843 bool run = false, queue = false;
1844
1845 tid = ar9170_get_tid(skb);
1846 seq = ar9170_get_seq(skb);
1847 txinfo = IEEE80211_SKB_CB(skb);
1848 sta_info = (void *) txinfo->control.sta->drv_priv;
1849 agg = &sta_info->agg[tid];
1850 max = sta_info->ampdu_max_len;
1851
1852 spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
1853
1854 if (unlikely(agg->state != AR9170_TID_STATE_COMPLETE)) {
1855#ifdef AR9170_TXAGG_DEBUG
1856 printk(KERN_DEBUG "%s: BlockACK session not fully initialized "
1857 "for ESS:%pM tid:%d state:%d.\n",
1858 wiphy_name(ar->hw->wiphy), agg->addr, agg->tid,
1859 agg->state);
1860#endif /* AR9170_TXAGG_DEBUG */
1861 goto err_unlock;
1862 }
1863
1864 if (!agg->active) {
1865 agg->active = true;
1866 agg->ssn = seq;
1867 queue = true;
1868 }
1869
1870 /* check if seq is within the BA window */
1871 if (unlikely(!BAW_WITHIN(agg->ssn, max, seq))) {
1872#ifdef AR9170_TXAGG_DEBUG
1873 printk(KERN_DEBUG "%s: frame with tid:%d seq:%d does not "
1874 "fit into BA window (%d - %d)\n",
1875 wiphy_name(ar->hw->wiphy), tid, seq, agg->ssn,
1876 (agg->ssn + max) & 0xfff);
1877#endif /* AR9170_TXAGG_DEBUG */
1878 goto err_unlock;
1879 }
1880
1881 spin_lock_irqsave(&agg->queue.lock, f2);
1882
1883 skb_queue_reverse_walk(&agg->queue, iter) {
1884 qseq = ar9170_get_seq(iter);
1885
1886 if (GET_NEXT_SEQ(qseq) == seq) {
1887 __skb_queue_after(&agg->queue, iter, skb);
1888 goto queued;
1889 }
1890 }
1891
1892 __skb_queue_head(&agg->queue, skb);
1893
1894queued:
1895 spin_unlock_irqrestore(&agg->queue.lock, f2);
1896
1897#ifdef AR9170_TXAGG_DEBUG
1898 printk(KERN_DEBUG "%s: new aggregate %p queued.\n",
1899 wiphy_name(ar->hw->wiphy), skb);
1900 __ar9170_dump_txqueue(ar, &agg->queue);
1901#endif /* AR9170_TXAGG_DEBUG */
1902
1903 if (skb_queue_len(&agg->queue) >= AR9170_NUM_TX_AGG_MAX)
1904 run = true;
1905
1906 if (queue)
1907 list_add_tail(&agg->list, &ar->tx_ampdu_list);
1908
1909 spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
1910 return run;
1911
1912err_unlock:
1913 spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
1914 dev_kfree_skb_irq(skb);
1915 return false;
1916}
1917
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001918int ar9170_op_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
1919{
1920 struct ar9170 *ar = hw->priv;
1921 struct ieee80211_tx_info *info;
1922
1923 if (unlikely(!IS_STARTED(ar)))
1924 goto err_free;
1925
1926 if (unlikely(ar9170_tx_prepare(ar, skb)))
1927 goto err_free;
1928
1929 info = IEEE80211_SKB_CB(skb);
1930 if (info->flags & IEEE80211_TX_CTL_AMPDU) {
Christian Lamparteracbadf02009-07-11 17:24:14 +02001931 bool run = ar9170_tx_ampdu_queue(ar, skb);
1932
Christian Lamparter02bdf5b2009-10-17 21:56:43 +02001933 if (run || !atomic_read(&ar->tx_ampdu_pending))
Christian Lamparteracbadf02009-07-11 17:24:14 +02001934 ar9170_tx_ampdu(ar);
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001935 } else {
1936 unsigned int queue = skb_get_queue_mapping(skb);
1937
1938 ar9170_tx_prepare_phy(ar, skb);
1939 skb_queue_tail(&ar->tx_pending[queue], skb);
Christian Lampartere9348cd2009-03-21 23:05:13 +01001940 }
1941
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001942 ar9170_tx(ar);
Christian Lampartere9348cd2009-03-21 23:05:13 +01001943 return NETDEV_TX_OK;
1944
Christian Lampartere9348cd2009-03-21 23:05:13 +01001945err_free:
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02001946 dev_kfree_skb_any(skb);
Christian Lampartere9348cd2009-03-21 23:05:13 +01001947 return NETDEV_TX_OK;
1948}
1949
1950static int ar9170_op_add_interface(struct ieee80211_hw *hw,
1951 struct ieee80211_if_init_conf *conf)
1952{
1953 struct ar9170 *ar = hw->priv;
Luis R. Rodriguez8c727e72009-09-10 10:10:54 -07001954 struct ath_common *common = &ar->common;
Christian Lampartere9348cd2009-03-21 23:05:13 +01001955 int err = 0;
1956
1957 mutex_lock(&ar->mutex);
1958
1959 if (ar->vif) {
1960 err = -EBUSY;
1961 goto unlock;
1962 }
1963
1964 ar->vif = conf->vif;
Luis R. Rodriguez8c727e72009-09-10 10:10:54 -07001965 memcpy(common->macaddr, conf->mac_addr, ETH_ALEN);
Christian Lampartere9348cd2009-03-21 23:05:13 +01001966
1967 if (modparam_nohwcrypt || (ar->vif->type != NL80211_IFTYPE_STATION)) {
1968 ar->rx_software_decryption = true;
1969 ar->disable_offload = true;
1970 }
1971
1972 ar->cur_filter = 0;
Christian Lampartereeef4182009-08-19 12:43:47 +02001973 err = ar9170_update_frame_filter(ar, AR9170_MAC_REG_FTF_DEFAULTS);
Christian Lampartere9348cd2009-03-21 23:05:13 +01001974 if (err)
1975 goto unlock;
1976
1977 err = ar9170_set_operating_mode(ar);
1978
1979unlock:
1980 mutex_unlock(&ar->mutex);
1981 return err;
1982}
1983
1984static void ar9170_op_remove_interface(struct ieee80211_hw *hw,
1985 struct ieee80211_if_init_conf *conf)
1986{
1987 struct ar9170 *ar = hw->priv;
1988
1989 mutex_lock(&ar->mutex);
1990 ar->vif = NULL;
Christian Lampartereeef4182009-08-19 12:43:47 +02001991 ar9170_update_frame_filter(ar, 0);
Christian Lampartere9348cd2009-03-21 23:05:13 +01001992 ar9170_set_beacon_timers(ar);
1993 dev_kfree_skb(ar->beacon);
1994 ar->beacon = NULL;
1995 ar->sniffer_enabled = false;
1996 ar->rx_software_decryption = false;
1997 ar9170_set_operating_mode(ar);
1998 mutex_unlock(&ar->mutex);
1999}
2000
2001static int ar9170_op_config(struct ieee80211_hw *hw, u32 changed)
2002{
2003 struct ar9170 *ar = hw->priv;
2004 int err = 0;
2005
2006 mutex_lock(&ar->mutex);
2007
Christian Lampartere9348cd2009-03-21 23:05:13 +01002008 if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
2009 /* TODO */
2010 err = 0;
2011 }
2012
2013 if (changed & IEEE80211_CONF_CHANGE_PS) {
2014 /* TODO */
2015 err = 0;
2016 }
2017
2018 if (changed & IEEE80211_CONF_CHANGE_POWER) {
2019 /* TODO */
2020 err = 0;
2021 }
2022
2023 if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) {
2024 /*
2025 * is it long_frame_max_tx_count or short_frame_max_tx_count?
2026 */
2027
2028 err = ar9170_set_hwretry_limit(ar,
2029 ar->hw->conf.long_frame_max_tx_count);
2030 if (err)
2031 goto out;
2032 }
2033
Christian Lampartere9348cd2009-03-21 23:05:13 +01002034 if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
Christian Lamparter29ceff52009-06-01 21:42:01 +02002035
2036 /* adjust slot time for 5 GHz */
2037 err = ar9170_set_slot_time(ar);
2038 if (err)
2039 goto out;
2040
2041 err = ar9170_set_dyn_sifs_ack(ar);
2042 if (err)
2043 goto out;
2044
Christian Lampartere9348cd2009-03-21 23:05:13 +01002045 err = ar9170_set_channel(ar, hw->conf.channel,
Johannes Berg9e52b06232009-04-20 18:27:04 +02002046 AR9170_RFI_NONE,
2047 nl80211_to_ar9170(hw->conf.channel_type));
Christian Lampartere9348cd2009-03-21 23:05:13 +01002048 if (err)
2049 goto out;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002050 }
2051
2052out:
2053 mutex_unlock(&ar->mutex);
2054 return err;
2055}
2056
Johannes Berg3ac64be2009-08-17 16:16:53 +02002057static u64 ar9170_op_prepare_multicast(struct ieee80211_hw *hw, int mc_count,
2058 struct dev_addr_list *mclist)
2059{
2060 u64 mchash;
2061 int i;
2062
2063 /* always get broadcast frames */
2064 mchash = 1ULL << (0xff >> 2);
2065
2066 for (i = 0; i < mc_count; i++) {
2067 if (WARN_ON(!mclist))
2068 break;
2069 mchash |= 1ULL << (mclist->dmi_addr[5] >> 2);
2070 mclist = mclist->next;
2071 }
2072
2073 return mchash;
2074}
2075
Christian Lampartere9348cd2009-03-21 23:05:13 +01002076static void ar9170_op_configure_filter(struct ieee80211_hw *hw,
2077 unsigned int changed_flags,
2078 unsigned int *new_flags,
Johannes Berg3ac64be2009-08-17 16:16:53 +02002079 u64 multicast)
Christian Lampartere9348cd2009-03-21 23:05:13 +01002080{
2081 struct ar9170 *ar = hw->priv;
2082
Christian Lampartereeef4182009-08-19 12:43:47 +02002083 if (unlikely(!IS_ACCEPTING_CMD(ar)))
2084 return ;
2085
2086 mutex_lock(&ar->mutex);
2087
Christian Lampartere9348cd2009-03-21 23:05:13 +01002088 /* mask supported flags */
2089 *new_flags &= FIF_ALLMULTI | FIF_CONTROL | FIF_BCN_PRBRESP_PROMISC |
Christian Lampartercca847992009-04-19 01:28:12 +02002090 FIF_PROMISC_IN_BSS | FIF_FCSFAIL | FIF_PLCPFAIL;
2091 ar->filter_state = *new_flags;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002092 /*
2093 * We can support more by setting the sniffer bit and
2094 * then checking the error flags, later.
2095 */
2096
Johannes Berg3ac64be2009-08-17 16:16:53 +02002097 if (changed_flags & FIF_ALLMULTI && *new_flags & FIF_ALLMULTI)
Christian Lampartereeef4182009-08-19 12:43:47 +02002098 multicast = ~0ULL;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002099
Christian Lampartereeef4182009-08-19 12:43:47 +02002100 if (multicast != ar->cur_mc_hash)
2101 ar9170_update_multicast(ar, multicast);
Christian Lampartere9348cd2009-03-21 23:05:13 +01002102
2103 if (changed_flags & FIF_CONTROL) {
2104 u32 filter = AR9170_MAC_REG_FTF_PSPOLL |
2105 AR9170_MAC_REG_FTF_RTS |
2106 AR9170_MAC_REG_FTF_CTS |
2107 AR9170_MAC_REG_FTF_ACK |
2108 AR9170_MAC_REG_FTF_CFE |
2109 AR9170_MAC_REG_FTF_CFE_ACK;
2110
2111 if (*new_flags & FIF_CONTROL)
Christian Lampartereeef4182009-08-19 12:43:47 +02002112 filter |= ar->cur_filter;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002113 else
Christian Lampartereeef4182009-08-19 12:43:47 +02002114 filter &= (~ar->cur_filter);
Christian Lampartere9348cd2009-03-21 23:05:13 +01002115
Christian Lampartereeef4182009-08-19 12:43:47 +02002116 ar9170_update_frame_filter(ar, filter);
Christian Lampartere9348cd2009-03-21 23:05:13 +01002117 }
2118
2119 if (changed_flags & FIF_PROMISC_IN_BSS) {
2120 ar->sniffer_enabled = ((*new_flags) & FIF_PROMISC_IN_BSS) != 0;
Christian Lampartereeef4182009-08-19 12:43:47 +02002121 ar9170_set_operating_mode(ar);
Christian Lampartere9348cd2009-03-21 23:05:13 +01002122 }
2123
Christian Lampartereeef4182009-08-19 12:43:47 +02002124 mutex_unlock(&ar->mutex);
Christian Lampartere9348cd2009-03-21 23:05:13 +01002125}
2126
Christian Lampartereeef4182009-08-19 12:43:47 +02002127
Christian Lampartere9348cd2009-03-21 23:05:13 +01002128static void ar9170_op_bss_info_changed(struct ieee80211_hw *hw,
2129 struct ieee80211_vif *vif,
2130 struct ieee80211_bss_conf *bss_conf,
2131 u32 changed)
2132{
2133 struct ar9170 *ar = hw->priv;
Luis R. Rodriguez8c727e72009-09-10 10:10:54 -07002134 struct ath_common *common = &ar->common;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002135 int err = 0;
2136
2137 mutex_lock(&ar->mutex);
2138
Johannes Berg2d0ddec2009-04-23 16:13:26 +02002139 if (changed & BSS_CHANGED_BSSID) {
Luis R. Rodriguez8c727e72009-09-10 10:10:54 -07002140 memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
Johannes Berg2d0ddec2009-04-23 16:13:26 +02002141 err = ar9170_set_operating_mode(ar);
Christian Lamparter29ceff52009-06-01 21:42:01 +02002142 if (err)
2143 goto out;
Johannes Berg2d0ddec2009-04-23 16:13:26 +02002144 }
2145
Joerg Albertea39d1a2009-08-21 23:25:07 +02002146 if (changed & BSS_CHANGED_BEACON_ENABLED)
2147 ar->enable_beacon = bss_conf->enable_beacon;
2148
2149 if (changed & BSS_CHANGED_BEACON) {
Johannes Berg2d0ddec2009-04-23 16:13:26 +02002150 err = ar9170_update_beacon(ar);
Christian Lamparter29ceff52009-06-01 21:42:01 +02002151 if (err)
2152 goto out;
Joerg Albertea39d1a2009-08-21 23:25:07 +02002153 }
Johannes Berg2d0ddec2009-04-23 16:13:26 +02002154
Joerg Albertea39d1a2009-08-21 23:25:07 +02002155 if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON |
2156 BSS_CHANGED_BEACON_INT)) {
Christian Lamparter29ceff52009-06-01 21:42:01 +02002157 err = ar9170_set_beacon_timers(ar);
2158 if (err)
2159 goto out;
2160 }
Christian Lampartere9348cd2009-03-21 23:05:13 +01002161
2162 if (changed & BSS_CHANGED_ASSOC) {
Christian Lampartere9348cd2009-03-21 23:05:13 +01002163#ifndef CONFIG_AR9170_LEDS
2164 /* enable assoc LED. */
2165 err = ar9170_set_leds_state(ar, bss_conf->assoc ? 2 : 0);
2166#endif /* CONFIG_AR9170_LEDS */
2167 }
2168
2169 if (changed & BSS_CHANGED_HT) {
2170 /* TODO */
2171 err = 0;
2172 }
2173
2174 if (changed & BSS_CHANGED_ERP_SLOT) {
Christian Lamparter29ceff52009-06-01 21:42:01 +02002175 err = ar9170_set_slot_time(ar);
2176 if (err)
2177 goto out;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002178 }
2179
2180 if (changed & BSS_CHANGED_BASIC_RATES) {
Christian Lamparter29ceff52009-06-01 21:42:01 +02002181 err = ar9170_set_basic_rates(ar);
2182 if (err)
2183 goto out;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002184 }
2185
Christian Lamparter29ceff52009-06-01 21:42:01 +02002186out:
Christian Lampartere9348cd2009-03-21 23:05:13 +01002187 mutex_unlock(&ar->mutex);
2188}
2189
2190static u64 ar9170_op_get_tsf(struct ieee80211_hw *hw)
2191{
2192 struct ar9170 *ar = hw->priv;
2193 int err;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002194 u64 tsf;
Joerg Albert181af382009-09-15 23:27:53 +02002195#define NR 3
2196 static const u32 addr[NR] = { AR9170_MAC_REG_TSF_H,
2197 AR9170_MAC_REG_TSF_L,
2198 AR9170_MAC_REG_TSF_H };
2199 u32 val[NR];
2200 int loops = 0;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002201
2202 mutex_lock(&ar->mutex);
Joerg Albert181af382009-09-15 23:27:53 +02002203
2204 while (loops++ < 10) {
2205 err = ar9170_read_mreg(ar, NR, addr, val);
2206 if (err || val[0] == val[2])
2207 break;
2208 }
2209
Christian Lampartere9348cd2009-03-21 23:05:13 +01002210 mutex_unlock(&ar->mutex);
2211
2212 if (WARN_ON(err))
2213 return 0;
Joerg Albert181af382009-09-15 23:27:53 +02002214 tsf = val[0];
2215 tsf = (tsf << 32) | val[1];
Christian Lampartere9348cd2009-03-21 23:05:13 +01002216 return tsf;
Joerg Albert181af382009-09-15 23:27:53 +02002217#undef NR
Christian Lampartere9348cd2009-03-21 23:05:13 +01002218}
2219
2220static int ar9170_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
2221 struct ieee80211_vif *vif, struct ieee80211_sta *sta,
2222 struct ieee80211_key_conf *key)
2223{
2224 struct ar9170 *ar = hw->priv;
2225 int err = 0, i;
2226 u8 ktype;
2227
2228 if ((!ar->vif) || (ar->disable_offload))
2229 return -EOPNOTSUPP;
2230
2231 switch (key->alg) {
2232 case ALG_WEP:
Zhu Yie31a16d2009-05-21 21:47:03 +08002233 if (key->keylen == WLAN_KEY_LEN_WEP40)
Christian Lampartere9348cd2009-03-21 23:05:13 +01002234 ktype = AR9170_ENC_ALG_WEP64;
2235 else
2236 ktype = AR9170_ENC_ALG_WEP128;
2237 break;
2238 case ALG_TKIP:
2239 ktype = AR9170_ENC_ALG_TKIP;
2240 break;
2241 case ALG_CCMP:
2242 ktype = AR9170_ENC_ALG_AESCCMP;
2243 break;
2244 default:
2245 return -EOPNOTSUPP;
2246 }
2247
2248 mutex_lock(&ar->mutex);
2249 if (cmd == SET_KEY) {
2250 if (unlikely(!IS_STARTED(ar))) {
2251 err = -EOPNOTSUPP;
2252 goto out;
2253 }
2254
2255 /* group keys need all-zeroes address */
2256 if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
2257 sta = NULL;
2258
2259 if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) {
2260 for (i = 0; i < 64; i++)
2261 if (!(ar->usedkeys & BIT(i)))
2262 break;
2263 if (i == 64) {
2264 ar->rx_software_decryption = true;
2265 ar9170_set_operating_mode(ar);
2266 err = -ENOSPC;
2267 goto out;
2268 }
2269 } else {
2270 i = 64 + key->keyidx;
2271 }
2272
2273 key->hw_key_idx = i;
2274
2275 err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL, ktype, 0,
2276 key->key, min_t(u8, 16, key->keylen));
2277 if (err)
2278 goto out;
2279
2280 if (key->alg == ALG_TKIP) {
2281 err = ar9170_upload_key(ar, i, sta ? sta->addr : NULL,
2282 ktype, 1, key->key + 16, 16);
2283 if (err)
2284 goto out;
2285
2286 /*
2287 * hardware is not capable generating the MMIC
2288 * for fragmented frames!
2289 */
2290 key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
2291 }
2292
2293 if (i < 64)
2294 ar->usedkeys |= BIT(i);
2295
2296 key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
2297 } else {
2298 if (unlikely(!IS_STARTED(ar))) {
2299 /* The device is gone... together with the key ;-) */
2300 err = 0;
2301 goto out;
2302 }
2303
2304 err = ar9170_disable_key(ar, key->hw_key_idx);
2305 if (err)
2306 goto out;
2307
2308 if (key->hw_key_idx < 64) {
2309 ar->usedkeys &= ~BIT(key->hw_key_idx);
2310 } else {
2311 err = ar9170_upload_key(ar, key->hw_key_idx, NULL,
2312 AR9170_ENC_ALG_NONE, 0,
2313 NULL, 0);
2314 if (err)
2315 goto out;
2316
2317 if (key->alg == ALG_TKIP) {
2318 err = ar9170_upload_key(ar, key->hw_key_idx,
2319 NULL,
2320 AR9170_ENC_ALG_NONE, 1,
2321 NULL, 0);
2322 if (err)
2323 goto out;
2324 }
2325
2326 }
2327 }
2328
2329 ar9170_regwrite_begin(ar);
2330 ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_L, ar->usedkeys);
2331 ar9170_regwrite(AR9170_MAC_REG_ROLL_CALL_TBL_H, ar->usedkeys >> 32);
2332 ar9170_regwrite_finish();
2333 err = ar9170_regwrite_result();
2334
2335out:
2336 mutex_unlock(&ar->mutex);
2337
2338 return err;
2339}
2340
2341static void ar9170_sta_notify(struct ieee80211_hw *hw,
2342 struct ieee80211_vif *vif,
2343 enum sta_notify_cmd cmd,
2344 struct ieee80211_sta *sta)
2345{
Christian Lamparteracbadf02009-07-11 17:24:14 +02002346 struct ar9170 *ar = hw->priv;
2347 struct ar9170_sta_info *sta_info = (void *) sta->drv_priv;
2348 unsigned int i;
2349
2350 switch (cmd) {
2351 case STA_NOTIFY_ADD:
2352 memset(sta_info, 0, sizeof(*sta_info));
2353
2354 if (!sta->ht_cap.ht_supported)
2355 break;
2356
2357 if (sta->ht_cap.ampdu_density > ar->global_ampdu_density)
2358 ar->global_ampdu_density = sta->ht_cap.ampdu_density;
2359
2360 if (sta->ht_cap.ampdu_factor < ar->global_ampdu_factor)
2361 ar->global_ampdu_factor = sta->ht_cap.ampdu_factor;
2362
2363 for (i = 0; i < AR9170_NUM_TID; i++) {
2364 sta_info->agg[i].state = AR9170_TID_STATE_SHUTDOWN;
2365 sta_info->agg[i].active = false;
2366 sta_info->agg[i].ssn = 0;
Christian Lamparteracbadf02009-07-11 17:24:14 +02002367 sta_info->agg[i].tid = i;
2368 INIT_LIST_HEAD(&sta_info->agg[i].list);
2369 skb_queue_head_init(&sta_info->agg[i].queue);
2370 }
2371
2372 sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor);
2373 break;
2374
2375 case STA_NOTIFY_REMOVE:
2376 if (!sta->ht_cap.ht_supported)
2377 break;
2378
2379 for (i = 0; i < AR9170_NUM_TID; i++) {
2380 sta_info->agg[i].state = AR9170_TID_STATE_INVALID;
2381 skb_queue_purge(&sta_info->agg[i].queue);
2382 }
2383
2384 break;
2385
2386 default:
2387 break;
2388 }
Christian Lampartere9348cd2009-03-21 23:05:13 +01002389}
2390
2391static int ar9170_get_stats(struct ieee80211_hw *hw,
2392 struct ieee80211_low_level_stats *stats)
2393{
2394 struct ar9170 *ar = hw->priv;
2395 u32 val;
2396 int err;
2397
2398 mutex_lock(&ar->mutex);
2399 err = ar9170_read_reg(ar, AR9170_MAC_REG_TX_RETRY, &val);
2400 ar->stats.dot11ACKFailureCount += val;
2401
2402 memcpy(stats, &ar->stats, sizeof(*stats));
2403 mutex_unlock(&ar->mutex);
2404
2405 return 0;
2406}
2407
2408static int ar9170_get_tx_stats(struct ieee80211_hw *hw,
2409 struct ieee80211_tx_queue_stats *tx_stats)
2410{
2411 struct ar9170 *ar = hw->priv;
2412
2413 spin_lock_bh(&ar->tx_stats_lock);
2414 memcpy(tx_stats, ar->tx_stats, sizeof(tx_stats[0]) * hw->queues);
2415 spin_unlock_bh(&ar->tx_stats_lock);
2416
2417 return 0;
2418}
2419
2420static int ar9170_conf_tx(struct ieee80211_hw *hw, u16 queue,
2421 const struct ieee80211_tx_queue_params *param)
2422{
2423 struct ar9170 *ar = hw->priv;
2424 int ret;
2425
2426 mutex_lock(&ar->mutex);
Dan Carpentere9d126c2009-08-09 14:24:09 +02002427 if (queue < __AR9170_NUM_TXQ) {
Christian Lampartere9348cd2009-03-21 23:05:13 +01002428 memcpy(&ar->edcf[ar9170_qos_hwmap[queue]],
2429 param, sizeof(*param));
2430
2431 ret = ar9170_set_qos(ar);
Dan Carpentere9d126c2009-08-09 14:24:09 +02002432 } else {
Christian Lampartere9348cd2009-03-21 23:05:13 +01002433 ret = -EINVAL;
Dan Carpentere9d126c2009-08-09 14:24:09 +02002434 }
Christian Lampartere9348cd2009-03-21 23:05:13 +01002435
2436 mutex_unlock(&ar->mutex);
2437 return ret;
2438}
2439
Johannes Berg9e52b06232009-04-20 18:27:04 +02002440static int ar9170_ampdu_action(struct ieee80211_hw *hw,
Johannes Bergc951ad32009-11-16 12:00:38 +01002441 struct ieee80211_vif *vif,
Johannes Berg9e52b06232009-04-20 18:27:04 +02002442 enum ieee80211_ampdu_mlme_action action,
2443 struct ieee80211_sta *sta, u16 tid, u16 *ssn)
2444{
Christian Lamparteracbadf02009-07-11 17:24:14 +02002445 struct ar9170 *ar = hw->priv;
2446 struct ar9170_sta_info *sta_info = (void *) sta->drv_priv;
2447 struct ar9170_sta_tid *tid_info = &sta_info->agg[tid];
2448 unsigned long flags;
2449
2450 if (!modparam_ht)
2451 return -EOPNOTSUPP;
2452
Johannes Berg9e52b06232009-04-20 18:27:04 +02002453 switch (action) {
Christian Lamparteracbadf02009-07-11 17:24:14 +02002454 case IEEE80211_AMPDU_TX_START:
2455 spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
2456 if (tid_info->state != AR9170_TID_STATE_SHUTDOWN ||
2457 !list_empty(&tid_info->list)) {
2458 spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
2459#ifdef AR9170_TXAGG_DEBUG
2460 printk(KERN_INFO "%s: A-MPDU [ESS:[%pM] tid:[%d]] "
2461 "is in a very bad state!\n",
2462 wiphy_name(hw->wiphy), sta->addr, tid);
2463#endif /* AR9170_TXAGG_DEBUG */
2464 return -EBUSY;
2465 }
2466
2467 *ssn = tid_info->ssn;
2468 tid_info->state = AR9170_TID_STATE_PROGRESS;
2469 tid_info->active = false;
2470 spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
Johannes Bergc951ad32009-11-16 12:00:38 +01002471 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
Christian Lamparteracbadf02009-07-11 17:24:14 +02002472 break;
2473
2474 case IEEE80211_AMPDU_TX_STOP:
2475 spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
2476 tid_info->state = AR9170_TID_STATE_SHUTDOWN;
2477 list_del_init(&tid_info->list);
2478 tid_info->active = false;
2479 skb_queue_purge(&tid_info->queue);
2480 spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
Johannes Bergc951ad32009-11-16 12:00:38 +01002481 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
Christian Lamparteracbadf02009-07-11 17:24:14 +02002482 break;
2483
2484 case IEEE80211_AMPDU_TX_OPERATIONAL:
2485#ifdef AR9170_TXAGG_DEBUG
2486 printk(KERN_INFO "%s: A-MPDU for %pM [tid:%d] Operational.\n",
2487 wiphy_name(hw->wiphy), sta->addr, tid);
2488#endif /* AR9170_TXAGG_DEBUG */
2489 spin_lock_irqsave(&ar->tx_ampdu_list_lock, flags);
2490 sta_info->agg[tid].state = AR9170_TID_STATE_COMPLETE;
2491 spin_unlock_irqrestore(&ar->tx_ampdu_list_lock, flags);
2492 break;
2493
Johannes Berg9e52b06232009-04-20 18:27:04 +02002494 case IEEE80211_AMPDU_RX_START:
2495 case IEEE80211_AMPDU_RX_STOP:
Christian Lamparteracbadf02009-07-11 17:24:14 +02002496 /* Handled by firmware */
2497 break;
2498
Johannes Berg9e52b06232009-04-20 18:27:04 +02002499 default:
2500 return -EOPNOTSUPP;
2501 }
Christian Lamparteracbadf02009-07-11 17:24:14 +02002502
2503 return 0;
Johannes Berg9e52b06232009-04-20 18:27:04 +02002504}
2505
Christian Lampartere9348cd2009-03-21 23:05:13 +01002506static const struct ieee80211_ops ar9170_ops = {
2507 .start = ar9170_op_start,
2508 .stop = ar9170_op_stop,
2509 .tx = ar9170_op_tx,
2510 .add_interface = ar9170_op_add_interface,
2511 .remove_interface = ar9170_op_remove_interface,
2512 .config = ar9170_op_config,
Johannes Berg3ac64be2009-08-17 16:16:53 +02002513 .prepare_multicast = ar9170_op_prepare_multicast,
Christian Lampartere9348cd2009-03-21 23:05:13 +01002514 .configure_filter = ar9170_op_configure_filter,
2515 .conf_tx = ar9170_conf_tx,
2516 .bss_info_changed = ar9170_op_bss_info_changed,
2517 .get_tsf = ar9170_op_get_tsf,
2518 .set_key = ar9170_set_key,
2519 .sta_notify = ar9170_sta_notify,
2520 .get_stats = ar9170_get_stats,
2521 .get_tx_stats = ar9170_get_tx_stats,
Johannes Berg9e52b06232009-04-20 18:27:04 +02002522 .ampdu_action = ar9170_ampdu_action,
Christian Lampartere9348cd2009-03-21 23:05:13 +01002523};
2524
2525void *ar9170_alloc(size_t priv_size)
2526{
2527 struct ieee80211_hw *hw;
2528 struct ar9170 *ar;
Christian Lampartercca847992009-04-19 01:28:12 +02002529 struct sk_buff *skb;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002530 int i;
2531
Christian Lampartercca847992009-04-19 01:28:12 +02002532 /*
2533 * this buffer is used for rx stream reconstruction.
2534 * Under heavy load this device (or the transport layer?)
2535 * tends to split the streams into seperate rx descriptors.
2536 */
2537
2538 skb = __dev_alloc_skb(AR9170_MAX_RX_BUFFER_SIZE, GFP_KERNEL);
2539 if (!skb)
2540 goto err_nomem;
2541
Christian Lampartere9348cd2009-03-21 23:05:13 +01002542 hw = ieee80211_alloc_hw(priv_size, &ar9170_ops);
2543 if (!hw)
Christian Lampartercca847992009-04-19 01:28:12 +02002544 goto err_nomem;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002545
2546 ar = hw->priv;
2547 ar->hw = hw;
Christian Lampartercca847992009-04-19 01:28:12 +02002548 ar->rx_failover = skb;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002549
2550 mutex_init(&ar->mutex);
2551 spin_lock_init(&ar->cmdlock);
2552 spin_lock_init(&ar->tx_stats_lock);
Christian Lamparteracbadf02009-07-11 17:24:14 +02002553 spin_lock_init(&ar->tx_ampdu_list_lock);
2554 skb_queue_head_init(&ar->tx_status_ampdu);
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02002555 for (i = 0; i < __AR9170_NUM_TXQ; i++) {
2556 skb_queue_head_init(&ar->tx_status[i]);
2557 skb_queue_head_init(&ar->tx_pending[i]);
2558 }
Christian Lampartercca847992009-04-19 01:28:12 +02002559 ar9170_rx_reset_rx_mpdu(ar);
Christian Lampartere9348cd2009-03-21 23:05:13 +01002560 INIT_WORK(&ar->beacon_work, ar9170_new_beacon);
Christian Lamparter9b9c5aa2009-06-06 05:07:23 +02002561 INIT_DELAYED_WORK(&ar->tx_janitor, ar9170_tx_janitor);
Christian Lamparteracbadf02009-07-11 17:24:14 +02002562 INIT_LIST_HEAD(&ar->tx_ampdu_list);
Christian Lampartere9348cd2009-03-21 23:05:13 +01002563
2564 /* all hw supports 2.4 GHz, so set channel to 1 by default */
2565 ar->channel = &ar9170_2ghz_chantable[0];
2566
2567 /* first part of wiphy init */
2568 ar->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
2569 BIT(NL80211_IFTYPE_WDS) |
2570 BIT(NL80211_IFTYPE_ADHOC);
2571 ar->hw->flags |= IEEE80211_HW_RX_INCLUDES_FCS |
2572 IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING |
2573 IEEE80211_HW_SIGNAL_DBM |
2574 IEEE80211_HW_NOISE_DBM;
2575
Christian Lamparteracbadf02009-07-11 17:24:14 +02002576 if (modparam_ht) {
2577 ar->hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
2578 } else {
2579 ar9170_band_2GHz.ht_cap.ht_supported = false;
2580 ar9170_band_5GHz.ht_cap.ht_supported = false;
2581 }
2582
Christian Lamparter4a48e2a2009-03-23 12:15:43 +01002583 ar->hw->queues = __AR9170_NUM_TXQ;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002584 ar->hw->extra_tx_headroom = 8;
2585 ar->hw->sta_data_size = sizeof(struct ar9170_sta_info);
2586
2587 ar->hw->max_rates = 1;
2588 ar->hw->max_rate_tries = 3;
2589
2590 for (i = 0; i < ARRAY_SIZE(ar->noise); i++)
2591 ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */
2592
2593 return ar;
Christian Lampartercca847992009-04-19 01:28:12 +02002594
2595err_nomem:
2596 kfree_skb(skb);
2597 return ERR_PTR(-ENOMEM);
Christian Lampartere9348cd2009-03-21 23:05:13 +01002598}
Christian Lampartere9348cd2009-03-21 23:05:13 +01002599
2600static int ar9170_read_eeprom(struct ar9170 *ar)
2601{
2602#define RW 8 /* number of words to read at once */
2603#define RB (sizeof(u32) * RW)
Luis R. Rodriguez608b88c2009-08-17 18:07:23 -07002604 struct ath_regulatory *regulatory = &ar->common.regulatory;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002605 u8 *eeprom = (void *)&ar->eeprom;
2606 u8 *addr = ar->eeprom.mac_address;
2607 __le32 offsets[RW];
Christian Lamparteracbadf02009-07-11 17:24:14 +02002608 unsigned int rx_streams, tx_streams, tx_params = 0;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002609 int i, j, err, bands = 0;
2610
2611 BUILD_BUG_ON(sizeof(ar->eeprom) & 3);
2612
2613 BUILD_BUG_ON(RB > AR9170_MAX_CMD_LEN - 4);
2614#ifndef __CHECKER__
2615 /* don't want to handle trailing remains */
2616 BUILD_BUG_ON(sizeof(ar->eeprom) % RB);
2617#endif
2618
2619 for (i = 0; i < sizeof(ar->eeprom)/RB; i++) {
2620 for (j = 0; j < RW; j++)
2621 offsets[j] = cpu_to_le32(AR9170_EEPROM_START +
2622 RB * i + 4 * j);
2623
2624 err = ar->exec_cmd(ar, AR9170_CMD_RREG,
2625 RB, (u8 *) &offsets,
2626 RB, eeprom + RB * i);
2627 if (err)
2628 return err;
2629 }
2630
2631#undef RW
2632#undef RB
2633
2634 if (ar->eeprom.length == cpu_to_le16(0xFFFF))
2635 return -ENODATA;
2636
2637 if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) {
2638 ar->hw->wiphy->bands[IEEE80211_BAND_2GHZ] = &ar9170_band_2GHz;
2639 bands++;
2640 }
2641 if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) {
2642 ar->hw->wiphy->bands[IEEE80211_BAND_5GHZ] = &ar9170_band_5GHz;
2643 bands++;
2644 }
Christian Lamparteracbadf02009-07-11 17:24:14 +02002645
2646 rx_streams = hweight8(ar->eeprom.rx_mask);
2647 tx_streams = hweight8(ar->eeprom.tx_mask);
2648
2649 if (rx_streams != tx_streams)
2650 tx_params = IEEE80211_HT_MCS_TX_RX_DIFF;
2651
2652 if (tx_streams >= 1 && tx_streams <= IEEE80211_HT_MCS_TX_MAX_STREAMS)
2653 tx_params = (tx_streams - 1) <<
2654 IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
2655
2656 ar9170_band_2GHz.ht_cap.mcs.tx_params |= tx_params;
2657 ar9170_band_5GHz.ht_cap.mcs.tx_params |= tx_params;
2658
Christian Lampartere9348cd2009-03-21 23:05:13 +01002659 /*
2660 * I measured this, a bandswitch takes roughly
2661 * 135 ms and a frequency switch about 80.
2662 *
2663 * FIXME: measure these values again once EEPROM settings
2664 * are used, that will influence them!
2665 */
2666 if (bands == 2)
2667 ar->hw->channel_change_time = 135 * 1000;
2668 else
2669 ar->hw->channel_change_time = 80 * 1000;
2670
Luis R. Rodriguez608b88c2009-08-17 18:07:23 -07002671 regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]);
2672 regulatory->current_rd_ext = le16_to_cpu(ar->eeprom.reg_domain[1]);
Christian Lamparter1878f772009-03-30 22:30:32 -04002673
Christian Lampartere9348cd2009-03-21 23:05:13 +01002674 /* second part of wiphy init */
2675 SET_IEEE80211_PERM_ADDR(ar->hw, addr);
2676
2677 return bands ? 0 : -EINVAL;
2678}
2679
Christian Lamparter1878f772009-03-30 22:30:32 -04002680static int ar9170_reg_notifier(struct wiphy *wiphy,
2681 struct regulatory_request *request)
2682{
2683 struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
2684 struct ar9170 *ar = hw->priv;
2685
Luis R. Rodriguez608b88c2009-08-17 18:07:23 -07002686 return ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory);
Christian Lamparter1878f772009-03-30 22:30:32 -04002687}
2688
Christian Lampartere9348cd2009-03-21 23:05:13 +01002689int ar9170_register(struct ar9170 *ar, struct device *pdev)
2690{
Luis R. Rodriguez608b88c2009-08-17 18:07:23 -07002691 struct ath_regulatory *regulatory = &ar->common.regulatory;
Christian Lampartere9348cd2009-03-21 23:05:13 +01002692 int err;
2693
2694 /* try to read EEPROM, init MAC addr */
2695 err = ar9170_read_eeprom(ar);
2696 if (err)
2697 goto err_out;
2698
Luis R. Rodriguez608b88c2009-08-17 18:07:23 -07002699 err = ath_regd_init(regulatory, ar->hw->wiphy,
Christian Lamparter1878f772009-03-30 22:30:32 -04002700 ar9170_reg_notifier);
Luis R. Rodriguez85efc862009-04-13 21:41:46 -04002701 if (err)
2702 goto err_out;
Christian Lamparter1878f772009-03-30 22:30:32 -04002703
Christian Lampartere9348cd2009-03-21 23:05:13 +01002704 err = ieee80211_register_hw(ar->hw);
2705 if (err)
2706 goto err_out;
2707
Luis R. Rodriguez608b88c2009-08-17 18:07:23 -07002708 if (!ath_is_world_regd(regulatory))
2709 regulatory_hint(ar->hw->wiphy, regulatory->alpha2);
Christian Lamparter1878f772009-03-30 22:30:32 -04002710
Christian Lampartere9348cd2009-03-21 23:05:13 +01002711 err = ar9170_init_leds(ar);
2712 if (err)
2713 goto err_unreg;
2714
2715#ifdef CONFIG_AR9170_LEDS
2716 err = ar9170_register_leds(ar);
2717 if (err)
2718 goto err_unreg;
2719#endif /* CONFIG_AR9170_LEDS */
2720
2721 dev_info(pdev, "Atheros AR9170 is registered as '%s'\n",
2722 wiphy_name(ar->hw->wiphy));
2723
2724 return err;
2725
2726err_unreg:
2727 ieee80211_unregister_hw(ar->hw);
2728
2729err_out:
2730 return err;
2731}
Christian Lampartere9348cd2009-03-21 23:05:13 +01002732
2733void ar9170_unregister(struct ar9170 *ar)
2734{
2735#ifdef CONFIG_AR9170_LEDS
2736 ar9170_unregister_leds(ar);
2737#endif /* CONFIG_AR9170_LEDS */
2738
Christian Lampartercca847992009-04-19 01:28:12 +02002739 kfree_skb(ar->rx_failover);
Christian Lampartere9348cd2009-03-21 23:05:13 +01002740 ieee80211_unregister_hw(ar->hw);
2741 mutex_destroy(&ar->mutex);
2742}