1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Atheros CARL9170 driver
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * mac80211 interaction code
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Copyright 2008, Johannes Berg <johannes@sipsolutions.net>
7*4882a593Smuzhiyun * Copyright 2009, 2010, Christian Lamparter <chunkeey@googlemail.com>
8*4882a593Smuzhiyun *
9*4882a593Smuzhiyun * This program is free software; you can redistribute it and/or modify
10*4882a593Smuzhiyun * it under the terms of the GNU General Public License as published by
11*4882a593Smuzhiyun * the Free Software Foundation; either version 2 of the License, or
12*4882a593Smuzhiyun * (at your option) any later version.
13*4882a593Smuzhiyun *
14*4882a593Smuzhiyun * This program is distributed in the hope that it will be useful,
15*4882a593Smuzhiyun * but WITHOUT ANY WARRANTY; without even the implied warranty of
16*4882a593Smuzhiyun * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17*4882a593Smuzhiyun * GNU General Public License for more details.
18*4882a593Smuzhiyun *
19*4882a593Smuzhiyun * You should have received a copy of the GNU General Public License
20*4882a593Smuzhiyun * along with this program; see the file COPYING. If not, see
21*4882a593Smuzhiyun * http://www.gnu.org/licenses/.
22*4882a593Smuzhiyun *
23*4882a593Smuzhiyun * This file incorporates work covered by the following copyright and
24*4882a593Smuzhiyun * permission notice:
25*4882a593Smuzhiyun * Copyright (c) 2007-2008 Atheros Communications, Inc.
26*4882a593Smuzhiyun *
27*4882a593Smuzhiyun * Permission to use, copy, modify, and/or distribute this software for any
28*4882a593Smuzhiyun * purpose with or without fee is hereby granted, provided that the above
29*4882a593Smuzhiyun * copyright notice and this permission notice appear in all copies.
30*4882a593Smuzhiyun *
31*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
32*4882a593Smuzhiyun * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
33*4882a593Smuzhiyun * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
34*4882a593Smuzhiyun * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
35*4882a593Smuzhiyun * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
36*4882a593Smuzhiyun * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
37*4882a593Smuzhiyun * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
38*4882a593Smuzhiyun */
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun #include <linux/slab.h>
41*4882a593Smuzhiyun #include <linux/module.h>
42*4882a593Smuzhiyun #include <linux/etherdevice.h>
43*4882a593Smuzhiyun #include <linux/random.h>
44*4882a593Smuzhiyun #include <net/mac80211.h>
45*4882a593Smuzhiyun #include <net/cfg80211.h>
46*4882a593Smuzhiyun #include "hw.h"
47*4882a593Smuzhiyun #include "carl9170.h"
48*4882a593Smuzhiyun #include "cmd.h"
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun static bool modparam_nohwcrypt;
51*4882a593Smuzhiyun module_param_named(nohwcrypt, modparam_nohwcrypt, bool, 0444);
52*4882a593Smuzhiyun MODULE_PARM_DESC(nohwcrypt, "Disable hardware crypto offload.");
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun int modparam_noht;
55*4882a593Smuzhiyun module_param_named(noht, modparam_noht, int, 0444);
56*4882a593Smuzhiyun MODULE_PARM_DESC(noht, "Disable MPDU aggregation.");
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun #define RATE(_bitrate, _hw_rate, _txpidx, _flags) { \
59*4882a593Smuzhiyun .bitrate = (_bitrate), \
60*4882a593Smuzhiyun .flags = (_flags), \
61*4882a593Smuzhiyun .hw_value = (_hw_rate) | (_txpidx) << 4, \
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun struct ieee80211_rate __carl9170_ratetable[] = {
65*4882a593Smuzhiyun RATE(10, 0, 0, 0),
66*4882a593Smuzhiyun RATE(20, 1, 1, IEEE80211_RATE_SHORT_PREAMBLE),
67*4882a593Smuzhiyun RATE(55, 2, 2, IEEE80211_RATE_SHORT_PREAMBLE),
68*4882a593Smuzhiyun RATE(110, 3, 3, IEEE80211_RATE_SHORT_PREAMBLE),
69*4882a593Smuzhiyun RATE(60, 0xb, 0, 0),
70*4882a593Smuzhiyun RATE(90, 0xf, 0, 0),
71*4882a593Smuzhiyun RATE(120, 0xa, 0, 0),
72*4882a593Smuzhiyun RATE(180, 0xe, 0, 0),
73*4882a593Smuzhiyun RATE(240, 0x9, 0, 0),
74*4882a593Smuzhiyun RATE(360, 0xd, 1, 0),
75*4882a593Smuzhiyun RATE(480, 0x8, 2, 0),
76*4882a593Smuzhiyun RATE(540, 0xc, 3, 0),
77*4882a593Smuzhiyun };
78*4882a593Smuzhiyun #undef RATE
79*4882a593Smuzhiyun
80*4882a593Smuzhiyun #define carl9170_g_ratetable (__carl9170_ratetable + 0)
81*4882a593Smuzhiyun #define carl9170_g_ratetable_size 12
82*4882a593Smuzhiyun #define carl9170_a_ratetable (__carl9170_ratetable + 4)
83*4882a593Smuzhiyun #define carl9170_a_ratetable_size 8
84*4882a593Smuzhiyun
85*4882a593Smuzhiyun /*
86*4882a593Smuzhiyun * NB: The hw_value is used as an index into the carl9170_phy_freq_params
87*4882a593Smuzhiyun * array in phy.c so that we don't have to do frequency lookups!
88*4882a593Smuzhiyun */
89*4882a593Smuzhiyun #define CHAN(_freq, _idx) { \
90*4882a593Smuzhiyun .center_freq = (_freq), \
91*4882a593Smuzhiyun .hw_value = (_idx), \
92*4882a593Smuzhiyun .max_power = 18, /* XXX */ \
93*4882a593Smuzhiyun }
94*4882a593Smuzhiyun
95*4882a593Smuzhiyun static struct ieee80211_channel carl9170_2ghz_chantable[] = {
96*4882a593Smuzhiyun CHAN(2412, 0),
97*4882a593Smuzhiyun CHAN(2417, 1),
98*4882a593Smuzhiyun CHAN(2422, 2),
99*4882a593Smuzhiyun CHAN(2427, 3),
100*4882a593Smuzhiyun CHAN(2432, 4),
101*4882a593Smuzhiyun CHAN(2437, 5),
102*4882a593Smuzhiyun CHAN(2442, 6),
103*4882a593Smuzhiyun CHAN(2447, 7),
104*4882a593Smuzhiyun CHAN(2452, 8),
105*4882a593Smuzhiyun CHAN(2457, 9),
106*4882a593Smuzhiyun CHAN(2462, 10),
107*4882a593Smuzhiyun CHAN(2467, 11),
108*4882a593Smuzhiyun CHAN(2472, 12),
109*4882a593Smuzhiyun CHAN(2484, 13),
110*4882a593Smuzhiyun };
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun static struct ieee80211_channel carl9170_5ghz_chantable[] = {
113*4882a593Smuzhiyun CHAN(4920, 14),
114*4882a593Smuzhiyun CHAN(4940, 15),
115*4882a593Smuzhiyun CHAN(4960, 16),
116*4882a593Smuzhiyun CHAN(4980, 17),
117*4882a593Smuzhiyun CHAN(5040, 18),
118*4882a593Smuzhiyun CHAN(5060, 19),
119*4882a593Smuzhiyun CHAN(5080, 20),
120*4882a593Smuzhiyun CHAN(5180, 21),
121*4882a593Smuzhiyun CHAN(5200, 22),
122*4882a593Smuzhiyun CHAN(5220, 23),
123*4882a593Smuzhiyun CHAN(5240, 24),
124*4882a593Smuzhiyun CHAN(5260, 25),
125*4882a593Smuzhiyun CHAN(5280, 26),
126*4882a593Smuzhiyun CHAN(5300, 27),
127*4882a593Smuzhiyun CHAN(5320, 28),
128*4882a593Smuzhiyun CHAN(5500, 29),
129*4882a593Smuzhiyun CHAN(5520, 30),
130*4882a593Smuzhiyun CHAN(5540, 31),
131*4882a593Smuzhiyun CHAN(5560, 32),
132*4882a593Smuzhiyun CHAN(5580, 33),
133*4882a593Smuzhiyun CHAN(5600, 34),
134*4882a593Smuzhiyun CHAN(5620, 35),
135*4882a593Smuzhiyun CHAN(5640, 36),
136*4882a593Smuzhiyun CHAN(5660, 37),
137*4882a593Smuzhiyun CHAN(5680, 38),
138*4882a593Smuzhiyun CHAN(5700, 39),
139*4882a593Smuzhiyun CHAN(5745, 40),
140*4882a593Smuzhiyun CHAN(5765, 41),
141*4882a593Smuzhiyun CHAN(5785, 42),
142*4882a593Smuzhiyun CHAN(5805, 43),
143*4882a593Smuzhiyun CHAN(5825, 44),
144*4882a593Smuzhiyun CHAN(5170, 45),
145*4882a593Smuzhiyun CHAN(5190, 46),
146*4882a593Smuzhiyun CHAN(5210, 47),
147*4882a593Smuzhiyun CHAN(5230, 48),
148*4882a593Smuzhiyun };
149*4882a593Smuzhiyun #undef CHAN
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun #define CARL9170_HT_CAP \
152*4882a593Smuzhiyun { \
153*4882a593Smuzhiyun .ht_supported = true, \
154*4882a593Smuzhiyun .cap = IEEE80211_HT_CAP_MAX_AMSDU | \
155*4882a593Smuzhiyun IEEE80211_HT_CAP_SUP_WIDTH_20_40 | \
156*4882a593Smuzhiyun IEEE80211_HT_CAP_SGI_40 | \
157*4882a593Smuzhiyun IEEE80211_HT_CAP_DSSSCCK40 | \
158*4882a593Smuzhiyun IEEE80211_HT_CAP_SM_PS, \
159*4882a593Smuzhiyun .ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, \
160*4882a593Smuzhiyun .ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, \
161*4882a593Smuzhiyun .mcs = { \
162*4882a593Smuzhiyun .rx_mask = { 0xff, 0xff, 0, 0, 0x1, 0, 0, 0, 0, 0, }, \
163*4882a593Smuzhiyun .rx_highest = cpu_to_le16(300), \
164*4882a593Smuzhiyun .tx_params = IEEE80211_HT_MCS_TX_DEFINED, \
165*4882a593Smuzhiyun }, \
166*4882a593Smuzhiyun }
167*4882a593Smuzhiyun
168*4882a593Smuzhiyun static struct ieee80211_supported_band carl9170_band_2GHz = {
169*4882a593Smuzhiyun .channels = carl9170_2ghz_chantable,
170*4882a593Smuzhiyun .n_channels = ARRAY_SIZE(carl9170_2ghz_chantable),
171*4882a593Smuzhiyun .bitrates = carl9170_g_ratetable,
172*4882a593Smuzhiyun .n_bitrates = carl9170_g_ratetable_size,
173*4882a593Smuzhiyun .ht_cap = CARL9170_HT_CAP,
174*4882a593Smuzhiyun };
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun static struct ieee80211_supported_band carl9170_band_5GHz = {
177*4882a593Smuzhiyun .channels = carl9170_5ghz_chantable,
178*4882a593Smuzhiyun .n_channels = ARRAY_SIZE(carl9170_5ghz_chantable),
179*4882a593Smuzhiyun .bitrates = carl9170_a_ratetable,
180*4882a593Smuzhiyun .n_bitrates = carl9170_a_ratetable_size,
181*4882a593Smuzhiyun .ht_cap = CARL9170_HT_CAP,
182*4882a593Smuzhiyun };
183*4882a593Smuzhiyun
carl9170_ampdu_gc(struct ar9170 * ar)184*4882a593Smuzhiyun static void carl9170_ampdu_gc(struct ar9170 *ar)
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun struct carl9170_sta_tid *tid_info;
187*4882a593Smuzhiyun LIST_HEAD(tid_gc);
188*4882a593Smuzhiyun
189*4882a593Smuzhiyun rcu_read_lock();
190*4882a593Smuzhiyun list_for_each_entry_rcu(tid_info, &ar->tx_ampdu_list, list) {
191*4882a593Smuzhiyun spin_lock_bh(&ar->tx_ampdu_list_lock);
192*4882a593Smuzhiyun if (tid_info->state == CARL9170_TID_STATE_SHUTDOWN) {
193*4882a593Smuzhiyun tid_info->state = CARL9170_TID_STATE_KILLED;
194*4882a593Smuzhiyun list_del_rcu(&tid_info->list);
195*4882a593Smuzhiyun ar->tx_ampdu_list_len--;
196*4882a593Smuzhiyun list_add_tail(&tid_info->tmp_list, &tid_gc);
197*4882a593Smuzhiyun }
198*4882a593Smuzhiyun spin_unlock_bh(&ar->tx_ampdu_list_lock);
199*4882a593Smuzhiyun
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun rcu_assign_pointer(ar->tx_ampdu_iter, tid_info);
202*4882a593Smuzhiyun rcu_read_unlock();
203*4882a593Smuzhiyun
204*4882a593Smuzhiyun synchronize_rcu();
205*4882a593Smuzhiyun
206*4882a593Smuzhiyun while (!list_empty(&tid_gc)) {
207*4882a593Smuzhiyun struct sk_buff *skb;
208*4882a593Smuzhiyun tid_info = list_first_entry(&tid_gc, struct carl9170_sta_tid,
209*4882a593Smuzhiyun tmp_list);
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun while ((skb = __skb_dequeue(&tid_info->queue)))
212*4882a593Smuzhiyun carl9170_tx_status(ar, skb, false);
213*4882a593Smuzhiyun
214*4882a593Smuzhiyun list_del_init(&tid_info->tmp_list);
215*4882a593Smuzhiyun kfree(tid_info);
216*4882a593Smuzhiyun }
217*4882a593Smuzhiyun }
218*4882a593Smuzhiyun
carl9170_flush(struct ar9170 * ar,bool drop_queued)219*4882a593Smuzhiyun static void carl9170_flush(struct ar9170 *ar, bool drop_queued)
220*4882a593Smuzhiyun {
221*4882a593Smuzhiyun if (drop_queued) {
222*4882a593Smuzhiyun int i;
223*4882a593Smuzhiyun
224*4882a593Smuzhiyun /*
225*4882a593Smuzhiyun * We can only drop frames which have not been uploaded
226*4882a593Smuzhiyun * to the device yet.
227*4882a593Smuzhiyun */
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun for (i = 0; i < ar->hw->queues; i++) {
230*4882a593Smuzhiyun struct sk_buff *skb;
231*4882a593Smuzhiyun
232*4882a593Smuzhiyun while ((skb = skb_dequeue(&ar->tx_pending[i]))) {
233*4882a593Smuzhiyun struct ieee80211_tx_info *info;
234*4882a593Smuzhiyun
235*4882a593Smuzhiyun info = IEEE80211_SKB_CB(skb);
236*4882a593Smuzhiyun if (info->flags & IEEE80211_TX_CTL_AMPDU)
237*4882a593Smuzhiyun atomic_dec(&ar->tx_ampdu_upload);
238*4882a593Smuzhiyun
239*4882a593Smuzhiyun carl9170_tx_status(ar, skb, false);
240*4882a593Smuzhiyun }
241*4882a593Smuzhiyun }
242*4882a593Smuzhiyun }
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun /* Wait for all other outstanding frames to timeout. */
245*4882a593Smuzhiyun if (atomic_read(&ar->tx_total_queued))
246*4882a593Smuzhiyun WARN_ON(wait_for_completion_timeout(&ar->tx_flush, HZ) == 0);
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun
carl9170_flush_ba(struct ar9170 * ar)249*4882a593Smuzhiyun static void carl9170_flush_ba(struct ar9170 *ar)
250*4882a593Smuzhiyun {
251*4882a593Smuzhiyun struct sk_buff_head free;
252*4882a593Smuzhiyun struct carl9170_sta_tid *tid_info;
253*4882a593Smuzhiyun struct sk_buff *skb;
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun __skb_queue_head_init(&free);
256*4882a593Smuzhiyun
257*4882a593Smuzhiyun rcu_read_lock();
258*4882a593Smuzhiyun spin_lock_bh(&ar->tx_ampdu_list_lock);
259*4882a593Smuzhiyun list_for_each_entry_rcu(tid_info, &ar->tx_ampdu_list, list) {
260*4882a593Smuzhiyun if (tid_info->state > CARL9170_TID_STATE_SUSPEND) {
261*4882a593Smuzhiyun tid_info->state = CARL9170_TID_STATE_SUSPEND;
262*4882a593Smuzhiyun
263*4882a593Smuzhiyun spin_lock(&tid_info->lock);
264*4882a593Smuzhiyun while ((skb = __skb_dequeue(&tid_info->queue)))
265*4882a593Smuzhiyun __skb_queue_tail(&free, skb);
266*4882a593Smuzhiyun spin_unlock(&tid_info->lock);
267*4882a593Smuzhiyun }
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun spin_unlock_bh(&ar->tx_ampdu_list_lock);
270*4882a593Smuzhiyun rcu_read_unlock();
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun while ((skb = __skb_dequeue(&free)))
273*4882a593Smuzhiyun carl9170_tx_status(ar, skb, false);
274*4882a593Smuzhiyun }
275*4882a593Smuzhiyun
carl9170_zap_queues(struct ar9170 * ar)276*4882a593Smuzhiyun static void carl9170_zap_queues(struct ar9170 *ar)
277*4882a593Smuzhiyun {
278*4882a593Smuzhiyun struct carl9170_vif_info *cvif;
279*4882a593Smuzhiyun unsigned int i;
280*4882a593Smuzhiyun
281*4882a593Smuzhiyun carl9170_ampdu_gc(ar);
282*4882a593Smuzhiyun
283*4882a593Smuzhiyun carl9170_flush_ba(ar);
284*4882a593Smuzhiyun carl9170_flush(ar, true);
285*4882a593Smuzhiyun
286*4882a593Smuzhiyun for (i = 0; i < ar->hw->queues; i++) {
287*4882a593Smuzhiyun spin_lock_bh(&ar->tx_status[i].lock);
288*4882a593Smuzhiyun while (!skb_queue_empty(&ar->tx_status[i])) {
289*4882a593Smuzhiyun struct sk_buff *skb;
290*4882a593Smuzhiyun
291*4882a593Smuzhiyun skb = skb_peek(&ar->tx_status[i]);
292*4882a593Smuzhiyun carl9170_tx_get_skb(skb);
293*4882a593Smuzhiyun spin_unlock_bh(&ar->tx_status[i].lock);
294*4882a593Smuzhiyun carl9170_tx_drop(ar, skb);
295*4882a593Smuzhiyun spin_lock_bh(&ar->tx_status[i].lock);
296*4882a593Smuzhiyun carl9170_tx_put_skb(skb);
297*4882a593Smuzhiyun }
298*4882a593Smuzhiyun spin_unlock_bh(&ar->tx_status[i].lock);
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun BUILD_BUG_ON(CARL9170_NUM_TX_LIMIT_SOFT < 1);
302*4882a593Smuzhiyun BUILD_BUG_ON(CARL9170_NUM_TX_LIMIT_HARD < CARL9170_NUM_TX_LIMIT_SOFT);
303*4882a593Smuzhiyun BUILD_BUG_ON(CARL9170_NUM_TX_LIMIT_HARD >= CARL9170_BAW_BITS);
304*4882a593Smuzhiyun
305*4882a593Smuzhiyun /* reinitialize queues statistics */
306*4882a593Smuzhiyun memset(&ar->tx_stats, 0, sizeof(ar->tx_stats));
307*4882a593Smuzhiyun for (i = 0; i < ar->hw->queues; i++)
308*4882a593Smuzhiyun ar->tx_stats[i].limit = CARL9170_NUM_TX_LIMIT_HARD;
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun for (i = 0; i < DIV_ROUND_UP(ar->fw.mem_blocks, BITS_PER_LONG); i++)
311*4882a593Smuzhiyun ar->mem_bitmap[i] = 0;
312*4882a593Smuzhiyun
313*4882a593Smuzhiyun rcu_read_lock();
314*4882a593Smuzhiyun list_for_each_entry_rcu(cvif, &ar->vif_list, list) {
315*4882a593Smuzhiyun spin_lock_bh(&ar->beacon_lock);
316*4882a593Smuzhiyun dev_kfree_skb_any(cvif->beacon);
317*4882a593Smuzhiyun cvif->beacon = NULL;
318*4882a593Smuzhiyun spin_unlock_bh(&ar->beacon_lock);
319*4882a593Smuzhiyun }
320*4882a593Smuzhiyun rcu_read_unlock();
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun atomic_set(&ar->tx_ampdu_upload, 0);
323*4882a593Smuzhiyun atomic_set(&ar->tx_ampdu_scheduler, 0);
324*4882a593Smuzhiyun atomic_set(&ar->tx_total_pending, 0);
325*4882a593Smuzhiyun atomic_set(&ar->tx_total_queued, 0);
326*4882a593Smuzhiyun atomic_set(&ar->mem_free_blocks, ar->fw.mem_blocks);
327*4882a593Smuzhiyun }
328*4882a593Smuzhiyun
329*4882a593Smuzhiyun #define CARL9170_FILL_QUEUE(queue, ai_fs, cwmin, cwmax, _txop) \
330*4882a593Smuzhiyun do { \
331*4882a593Smuzhiyun queue.aifs = ai_fs; \
332*4882a593Smuzhiyun queue.cw_min = cwmin; \
333*4882a593Smuzhiyun queue.cw_max = cwmax; \
334*4882a593Smuzhiyun queue.txop = _txop; \
335*4882a593Smuzhiyun } while (0)
336*4882a593Smuzhiyun
carl9170_op_start(struct ieee80211_hw * hw)337*4882a593Smuzhiyun static int carl9170_op_start(struct ieee80211_hw *hw)
338*4882a593Smuzhiyun {
339*4882a593Smuzhiyun struct ar9170 *ar = hw->priv;
340*4882a593Smuzhiyun int err, i;
341*4882a593Smuzhiyun
342*4882a593Smuzhiyun mutex_lock(&ar->mutex);
343*4882a593Smuzhiyun
344*4882a593Smuzhiyun carl9170_zap_queues(ar);
345*4882a593Smuzhiyun
346*4882a593Smuzhiyun /* reset QoS defaults */
347*4882a593Smuzhiyun CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_VO], 2, 3, 7, 47);
348*4882a593Smuzhiyun CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_VI], 2, 7, 15, 94);
349*4882a593Smuzhiyun CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_BE], 3, 15, 1023, 0);
350*4882a593Smuzhiyun CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_BK], 7, 15, 1023, 0);
351*4882a593Smuzhiyun CARL9170_FILL_QUEUE(ar->edcf[AR9170_TXQ_SPECIAL], 2, 3, 7, 0);
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun ar->current_factor = ar->current_density = -1;
354*4882a593Smuzhiyun /* "The first key is unique." */
355*4882a593Smuzhiyun ar->usedkeys = 1;
356*4882a593Smuzhiyun ar->filter_state = 0;
357*4882a593Smuzhiyun ar->ps.last_action = jiffies;
358*4882a593Smuzhiyun ar->ps.last_slept = jiffies;
359*4882a593Smuzhiyun ar->erp_mode = CARL9170_ERP_AUTO;
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun /* Set "disable hw crypto offload" whenever the module parameter
362*4882a593Smuzhiyun * nohwcrypt is true or if the firmware does not support it.
363*4882a593Smuzhiyun */
364*4882a593Smuzhiyun ar->disable_offload = modparam_nohwcrypt |
365*4882a593Smuzhiyun ar->fw.disable_offload_fw;
366*4882a593Smuzhiyun ar->rx_software_decryption = ar->disable_offload;
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun for (i = 0; i < ar->hw->queues; i++) {
369*4882a593Smuzhiyun ar->queue_stop_timeout[i] = jiffies;
370*4882a593Smuzhiyun ar->max_queue_stop_timeout[i] = 0;
371*4882a593Smuzhiyun }
372*4882a593Smuzhiyun
373*4882a593Smuzhiyun atomic_set(&ar->mem_allocs, 0);
374*4882a593Smuzhiyun
375*4882a593Smuzhiyun err = carl9170_usb_open(ar);
376*4882a593Smuzhiyun if (err)
377*4882a593Smuzhiyun goto out;
378*4882a593Smuzhiyun
379*4882a593Smuzhiyun err = carl9170_init_mac(ar);
380*4882a593Smuzhiyun if (err)
381*4882a593Smuzhiyun goto out;
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun err = carl9170_set_qos(ar);
384*4882a593Smuzhiyun if (err)
385*4882a593Smuzhiyun goto out;
386*4882a593Smuzhiyun
387*4882a593Smuzhiyun if (ar->fw.rx_filter) {
388*4882a593Smuzhiyun err = carl9170_rx_filter(ar, CARL9170_RX_FILTER_OTHER_RA |
389*4882a593Smuzhiyun CARL9170_RX_FILTER_CTL_OTHER | CARL9170_RX_FILTER_BAD);
390*4882a593Smuzhiyun if (err)
391*4882a593Smuzhiyun goto out;
392*4882a593Smuzhiyun }
393*4882a593Smuzhiyun
394*4882a593Smuzhiyun err = carl9170_write_reg(ar, AR9170_MAC_REG_DMA_TRIGGER,
395*4882a593Smuzhiyun AR9170_DMA_TRIGGER_RXQ);
396*4882a593Smuzhiyun if (err)
397*4882a593Smuzhiyun goto out;
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun /* Clear key-cache */
400*4882a593Smuzhiyun for (i = 0; i < AR9170_CAM_MAX_USER + 4; i++) {
401*4882a593Smuzhiyun err = carl9170_upload_key(ar, i, NULL, AR9170_ENC_ALG_NONE,
402*4882a593Smuzhiyun 0, NULL, 0);
403*4882a593Smuzhiyun if (err)
404*4882a593Smuzhiyun goto out;
405*4882a593Smuzhiyun
406*4882a593Smuzhiyun err = carl9170_upload_key(ar, i, NULL, AR9170_ENC_ALG_NONE,
407*4882a593Smuzhiyun 1, NULL, 0);
408*4882a593Smuzhiyun if (err)
409*4882a593Smuzhiyun goto out;
410*4882a593Smuzhiyun
411*4882a593Smuzhiyun if (i < AR9170_CAM_MAX_USER) {
412*4882a593Smuzhiyun err = carl9170_disable_key(ar, i);
413*4882a593Smuzhiyun if (err)
414*4882a593Smuzhiyun goto out;
415*4882a593Smuzhiyun }
416*4882a593Smuzhiyun }
417*4882a593Smuzhiyun
418*4882a593Smuzhiyun carl9170_set_state_when(ar, CARL9170_IDLE, CARL9170_STARTED);
419*4882a593Smuzhiyun
420*4882a593Smuzhiyun ieee80211_queue_delayed_work(ar->hw, &ar->stat_work,
421*4882a593Smuzhiyun round_jiffies(msecs_to_jiffies(CARL9170_STAT_WORK)));
422*4882a593Smuzhiyun
423*4882a593Smuzhiyun ieee80211_wake_queues(ar->hw);
424*4882a593Smuzhiyun err = 0;
425*4882a593Smuzhiyun
426*4882a593Smuzhiyun out:
427*4882a593Smuzhiyun mutex_unlock(&ar->mutex);
428*4882a593Smuzhiyun return err;
429*4882a593Smuzhiyun }
430*4882a593Smuzhiyun
carl9170_cancel_worker(struct ar9170 * ar)431*4882a593Smuzhiyun static void carl9170_cancel_worker(struct ar9170 *ar)
432*4882a593Smuzhiyun {
433*4882a593Smuzhiyun cancel_delayed_work_sync(&ar->stat_work);
434*4882a593Smuzhiyun cancel_delayed_work_sync(&ar->tx_janitor);
435*4882a593Smuzhiyun #ifdef CONFIG_CARL9170_LEDS
436*4882a593Smuzhiyun cancel_delayed_work_sync(&ar->led_work);
437*4882a593Smuzhiyun #endif /* CONFIG_CARL9170_LEDS */
438*4882a593Smuzhiyun cancel_work_sync(&ar->ps_work);
439*4882a593Smuzhiyun cancel_work_sync(&ar->ping_work);
440*4882a593Smuzhiyun cancel_work_sync(&ar->ampdu_work);
441*4882a593Smuzhiyun }
442*4882a593Smuzhiyun
carl9170_op_stop(struct ieee80211_hw * hw)443*4882a593Smuzhiyun static void carl9170_op_stop(struct ieee80211_hw *hw)
444*4882a593Smuzhiyun {
445*4882a593Smuzhiyun struct ar9170 *ar = hw->priv;
446*4882a593Smuzhiyun
447*4882a593Smuzhiyun carl9170_set_state_when(ar, CARL9170_STARTED, CARL9170_IDLE);
448*4882a593Smuzhiyun
449*4882a593Smuzhiyun ieee80211_stop_queues(ar->hw);
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun mutex_lock(&ar->mutex);
452*4882a593Smuzhiyun if (IS_ACCEPTING_CMD(ar)) {
453*4882a593Smuzhiyun RCU_INIT_POINTER(ar->beacon_iter, NULL);
454*4882a593Smuzhiyun
455*4882a593Smuzhiyun carl9170_led_set_state(ar, 0);
456*4882a593Smuzhiyun
457*4882a593Smuzhiyun /* stop DMA */
458*4882a593Smuzhiyun carl9170_write_reg(ar, AR9170_MAC_REG_DMA_TRIGGER, 0);
459*4882a593Smuzhiyun carl9170_usb_stop(ar);
460*4882a593Smuzhiyun }
461*4882a593Smuzhiyun
462*4882a593Smuzhiyun carl9170_zap_queues(ar);
463*4882a593Smuzhiyun mutex_unlock(&ar->mutex);
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun carl9170_cancel_worker(ar);
466*4882a593Smuzhiyun }
467*4882a593Smuzhiyun
carl9170_restart_work(struct work_struct * work)468*4882a593Smuzhiyun static void carl9170_restart_work(struct work_struct *work)
469*4882a593Smuzhiyun {
470*4882a593Smuzhiyun struct ar9170 *ar = container_of(work, struct ar9170,
471*4882a593Smuzhiyun restart_work);
472*4882a593Smuzhiyun int err = -EIO;
473*4882a593Smuzhiyun
474*4882a593Smuzhiyun ar->usedkeys = 0;
475*4882a593Smuzhiyun ar->filter_state = 0;
476*4882a593Smuzhiyun carl9170_cancel_worker(ar);
477*4882a593Smuzhiyun
478*4882a593Smuzhiyun mutex_lock(&ar->mutex);
479*4882a593Smuzhiyun if (!ar->force_usb_reset) {
480*4882a593Smuzhiyun err = carl9170_usb_restart(ar);
481*4882a593Smuzhiyun if (net_ratelimit()) {
482*4882a593Smuzhiyun if (err)
483*4882a593Smuzhiyun dev_err(&ar->udev->dev, "Failed to restart device (%d).\n", err);
484*4882a593Smuzhiyun else
485*4882a593Smuzhiyun dev_info(&ar->udev->dev, "device restarted successfully.\n");
486*4882a593Smuzhiyun }
487*4882a593Smuzhiyun }
488*4882a593Smuzhiyun carl9170_zap_queues(ar);
489*4882a593Smuzhiyun mutex_unlock(&ar->mutex);
490*4882a593Smuzhiyun
491*4882a593Smuzhiyun if (!err && !ar->force_usb_reset) {
492*4882a593Smuzhiyun ar->restart_counter++;
493*4882a593Smuzhiyun atomic_set(&ar->pending_restarts, 0);
494*4882a593Smuzhiyun
495*4882a593Smuzhiyun ieee80211_restart_hw(ar->hw);
496*4882a593Smuzhiyun } else {
497*4882a593Smuzhiyun /*
498*4882a593Smuzhiyun * The reset was unsuccessful and the device seems to
499*4882a593Smuzhiyun * be dead. But there's still one option: a low-level
500*4882a593Smuzhiyun * usb subsystem reset...
501*4882a593Smuzhiyun */
502*4882a593Smuzhiyun
503*4882a593Smuzhiyun carl9170_usb_reset(ar);
504*4882a593Smuzhiyun }
505*4882a593Smuzhiyun }
506*4882a593Smuzhiyun
carl9170_restart(struct ar9170 * ar,const enum carl9170_restart_reasons r)507*4882a593Smuzhiyun void carl9170_restart(struct ar9170 *ar, const enum carl9170_restart_reasons r)
508*4882a593Smuzhiyun {
509*4882a593Smuzhiyun carl9170_set_state_when(ar, CARL9170_STARTED, CARL9170_IDLE);
510*4882a593Smuzhiyun
511*4882a593Smuzhiyun /*
512*4882a593Smuzhiyun * Sometimes, an error can trigger several different reset events.
513*4882a593Smuzhiyun * By ignoring these *surplus* reset events, the device won't be
514*4882a593Smuzhiyun * killed again, right after it has recovered.
515*4882a593Smuzhiyun */
516*4882a593Smuzhiyun if (atomic_inc_return(&ar->pending_restarts) > 1) {
517*4882a593Smuzhiyun dev_dbg(&ar->udev->dev, "ignoring restart (%d)\n", r);
518*4882a593Smuzhiyun return;
519*4882a593Smuzhiyun }
520*4882a593Smuzhiyun
521*4882a593Smuzhiyun ieee80211_stop_queues(ar->hw);
522*4882a593Smuzhiyun
523*4882a593Smuzhiyun dev_err(&ar->udev->dev, "restart device (%d)\n", r);
524*4882a593Smuzhiyun
525*4882a593Smuzhiyun if (!WARN_ON(r == CARL9170_RR_NO_REASON) ||
526*4882a593Smuzhiyun !WARN_ON(r >= __CARL9170_RR_LAST))
527*4882a593Smuzhiyun ar->last_reason = r;
528*4882a593Smuzhiyun
529*4882a593Smuzhiyun if (!ar->registered)
530*4882a593Smuzhiyun return;
531*4882a593Smuzhiyun
532*4882a593Smuzhiyun if (!IS_ACCEPTING_CMD(ar) || ar->needs_full_reset)
533*4882a593Smuzhiyun ar->force_usb_reset = true;
534*4882a593Smuzhiyun
535*4882a593Smuzhiyun ieee80211_queue_work(ar->hw, &ar->restart_work);
536*4882a593Smuzhiyun
537*4882a593Smuzhiyun /*
538*4882a593Smuzhiyun * At this point, the device instance might have vanished/disabled.
539*4882a593Smuzhiyun * So, don't put any code which access the ar9170 struct
540*4882a593Smuzhiyun * without proper protection.
541*4882a593Smuzhiyun */
542*4882a593Smuzhiyun }
543*4882a593Smuzhiyun
carl9170_ping_work(struct work_struct * work)544*4882a593Smuzhiyun static void carl9170_ping_work(struct work_struct *work)
545*4882a593Smuzhiyun {
546*4882a593Smuzhiyun struct ar9170 *ar = container_of(work, struct ar9170, ping_work);
547*4882a593Smuzhiyun int err;
548*4882a593Smuzhiyun
549*4882a593Smuzhiyun if (!IS_STARTED(ar))
550*4882a593Smuzhiyun return;
551*4882a593Smuzhiyun
552*4882a593Smuzhiyun mutex_lock(&ar->mutex);
553*4882a593Smuzhiyun err = carl9170_echo_test(ar, 0xdeadbeef);
554*4882a593Smuzhiyun if (err)
555*4882a593Smuzhiyun carl9170_restart(ar, CARL9170_RR_UNRESPONSIVE_DEVICE);
556*4882a593Smuzhiyun mutex_unlock(&ar->mutex);
557*4882a593Smuzhiyun }
558*4882a593Smuzhiyun
carl9170_init_interface(struct ar9170 * ar,struct ieee80211_vif * vif)559*4882a593Smuzhiyun static int carl9170_init_interface(struct ar9170 *ar,
560*4882a593Smuzhiyun struct ieee80211_vif *vif)
561*4882a593Smuzhiyun {
562*4882a593Smuzhiyun struct ath_common *common = &ar->common;
563*4882a593Smuzhiyun int err;
564*4882a593Smuzhiyun
565*4882a593Smuzhiyun if (!vif) {
566*4882a593Smuzhiyun WARN_ON_ONCE(IS_STARTED(ar));
567*4882a593Smuzhiyun return 0;
568*4882a593Smuzhiyun }
569*4882a593Smuzhiyun
570*4882a593Smuzhiyun memcpy(common->macaddr, vif->addr, ETH_ALEN);
571*4882a593Smuzhiyun
572*4882a593Smuzhiyun /* We have to fall back to software crypto, whenever
573*4882a593Smuzhiyun * the user choose to participates in an IBSS. HW
574*4882a593Smuzhiyun * offload for IBSS RSN is not supported by this driver.
575*4882a593Smuzhiyun *
576*4882a593Smuzhiyun * NOTE: If the previous main interface has already
577*4882a593Smuzhiyun * disabled hw crypto offload, we have to keep this
578*4882a593Smuzhiyun * previous disable_offload setting as it was.
579*4882a593Smuzhiyun * Altough ideally, we should notify mac80211 and tell
580*4882a593Smuzhiyun * it to forget about any HW crypto offload for now.
581*4882a593Smuzhiyun */
582*4882a593Smuzhiyun ar->disable_offload |= ((vif->type != NL80211_IFTYPE_STATION) &&
583*4882a593Smuzhiyun (vif->type != NL80211_IFTYPE_AP));
584*4882a593Smuzhiyun
585*4882a593Smuzhiyun /* The driver used to have P2P GO+CLIENT support,
586*4882a593Smuzhiyun * but since this was dropped and we don't know if
587*4882a593Smuzhiyun * there are any gremlins lurking in the shadows,
588*4882a593Smuzhiyun * so best we keep HW offload disabled for P2P.
589*4882a593Smuzhiyun */
590*4882a593Smuzhiyun ar->disable_offload |= vif->p2p;
591*4882a593Smuzhiyun
592*4882a593Smuzhiyun ar->rx_software_decryption = ar->disable_offload;
593*4882a593Smuzhiyun
594*4882a593Smuzhiyun err = carl9170_set_operating_mode(ar);
595*4882a593Smuzhiyun return err;
596*4882a593Smuzhiyun }
597*4882a593Smuzhiyun
carl9170_op_add_interface(struct ieee80211_hw * hw,struct ieee80211_vif * vif)598*4882a593Smuzhiyun static int carl9170_op_add_interface(struct ieee80211_hw *hw,
599*4882a593Smuzhiyun struct ieee80211_vif *vif)
600*4882a593Smuzhiyun {
601*4882a593Smuzhiyun struct carl9170_vif_info *vif_priv = (void *) vif->drv_priv;
602*4882a593Smuzhiyun struct ieee80211_vif *main_vif, *old_main = NULL;
603*4882a593Smuzhiyun struct ar9170 *ar = hw->priv;
604*4882a593Smuzhiyun int vif_id = -1, err = 0;
605*4882a593Smuzhiyun
606*4882a593Smuzhiyun mutex_lock(&ar->mutex);
607*4882a593Smuzhiyun rcu_read_lock();
608*4882a593Smuzhiyun if (vif_priv->active) {
609*4882a593Smuzhiyun /*
610*4882a593Smuzhiyun * Skip the interface structure initialization,
611*4882a593Smuzhiyun * if the vif survived the _restart call.
612*4882a593Smuzhiyun */
613*4882a593Smuzhiyun vif_id = vif_priv->id;
614*4882a593Smuzhiyun vif_priv->enable_beacon = false;
615*4882a593Smuzhiyun
616*4882a593Smuzhiyun spin_lock_bh(&ar->beacon_lock);
617*4882a593Smuzhiyun dev_kfree_skb_any(vif_priv->beacon);
618*4882a593Smuzhiyun vif_priv->beacon = NULL;
619*4882a593Smuzhiyun spin_unlock_bh(&ar->beacon_lock);
620*4882a593Smuzhiyun
621*4882a593Smuzhiyun goto init;
622*4882a593Smuzhiyun }
623*4882a593Smuzhiyun
624*4882a593Smuzhiyun /* Because the AR9170 HW's MAC doesn't provide full support for
625*4882a593Smuzhiyun * multiple, independent interfaces [of different operation modes].
626*4882a593Smuzhiyun * We have to select ONE main interface [main mode of HW], but we
627*4882a593Smuzhiyun * can have multiple slaves [AKA: entry in the ACK-table].
628*4882a593Smuzhiyun *
629*4882a593Smuzhiyun * The first (from HEAD/TOP) interface in the ar->vif_list is
630*4882a593Smuzhiyun * always the main intf. All following intfs in this list
631*4882a593Smuzhiyun * are considered to be slave intfs.
632*4882a593Smuzhiyun */
633*4882a593Smuzhiyun main_vif = carl9170_get_main_vif(ar);
634*4882a593Smuzhiyun
635*4882a593Smuzhiyun if (main_vif) {
636*4882a593Smuzhiyun switch (main_vif->type) {
637*4882a593Smuzhiyun case NL80211_IFTYPE_STATION:
638*4882a593Smuzhiyun if (vif->type == NL80211_IFTYPE_STATION)
639*4882a593Smuzhiyun break;
640*4882a593Smuzhiyun
641*4882a593Smuzhiyun err = -EBUSY;
642*4882a593Smuzhiyun rcu_read_unlock();
643*4882a593Smuzhiyun
644*4882a593Smuzhiyun goto unlock;
645*4882a593Smuzhiyun
646*4882a593Smuzhiyun case NL80211_IFTYPE_MESH_POINT:
647*4882a593Smuzhiyun case NL80211_IFTYPE_AP:
648*4882a593Smuzhiyun if ((vif->type == NL80211_IFTYPE_STATION) ||
649*4882a593Smuzhiyun (vif->type == NL80211_IFTYPE_WDS) ||
650*4882a593Smuzhiyun (vif->type == NL80211_IFTYPE_AP) ||
651*4882a593Smuzhiyun (vif->type == NL80211_IFTYPE_MESH_POINT))
652*4882a593Smuzhiyun break;
653*4882a593Smuzhiyun
654*4882a593Smuzhiyun err = -EBUSY;
655*4882a593Smuzhiyun rcu_read_unlock();
656*4882a593Smuzhiyun goto unlock;
657*4882a593Smuzhiyun
658*4882a593Smuzhiyun default:
659*4882a593Smuzhiyun rcu_read_unlock();
660*4882a593Smuzhiyun goto unlock;
661*4882a593Smuzhiyun }
662*4882a593Smuzhiyun }
663*4882a593Smuzhiyun
664*4882a593Smuzhiyun vif_id = bitmap_find_free_region(&ar->vif_bitmap, ar->fw.vif_num, 0);
665*4882a593Smuzhiyun
666*4882a593Smuzhiyun if (vif_id < 0) {
667*4882a593Smuzhiyun rcu_read_unlock();
668*4882a593Smuzhiyun
669*4882a593Smuzhiyun err = -ENOSPC;
670*4882a593Smuzhiyun goto unlock;
671*4882a593Smuzhiyun }
672*4882a593Smuzhiyun
673*4882a593Smuzhiyun BUG_ON(ar->vif_priv[vif_id].id != vif_id);
674*4882a593Smuzhiyun
675*4882a593Smuzhiyun vif_priv->active = true;
676*4882a593Smuzhiyun vif_priv->id = vif_id;
677*4882a593Smuzhiyun vif_priv->enable_beacon = false;
678*4882a593Smuzhiyun ar->vifs++;
679*4882a593Smuzhiyun if (old_main) {
680*4882a593Smuzhiyun /* We end up in here, if the main interface is being replaced.
681*4882a593Smuzhiyun * Put the new main interface at the HEAD of the list and the
682*4882a593Smuzhiyun * previous inteface will automatically become second in line.
683*4882a593Smuzhiyun */
684*4882a593Smuzhiyun list_add_rcu(&vif_priv->list, &ar->vif_list);
685*4882a593Smuzhiyun } else {
686*4882a593Smuzhiyun /* Add new inteface. If the list is empty, it will become the
687*4882a593Smuzhiyun * main inteface, otherwise it will be slave.
688*4882a593Smuzhiyun */
689*4882a593Smuzhiyun list_add_tail_rcu(&vif_priv->list, &ar->vif_list);
690*4882a593Smuzhiyun }
691*4882a593Smuzhiyun rcu_assign_pointer(ar->vif_priv[vif_id].vif, vif);
692*4882a593Smuzhiyun
693*4882a593Smuzhiyun init:
694*4882a593Smuzhiyun main_vif = carl9170_get_main_vif(ar);
695*4882a593Smuzhiyun
696*4882a593Smuzhiyun if (main_vif == vif) {
697*4882a593Smuzhiyun rcu_assign_pointer(ar->beacon_iter, vif_priv);
698*4882a593Smuzhiyun rcu_read_unlock();
699*4882a593Smuzhiyun
700*4882a593Smuzhiyun if (old_main) {
701*4882a593Smuzhiyun struct carl9170_vif_info *old_main_priv =
702*4882a593Smuzhiyun (void *) old_main->drv_priv;
703*4882a593Smuzhiyun /* downgrade old main intf to slave intf.
704*4882a593Smuzhiyun * NOTE: We are no longer under rcu_read_lock.
705*4882a593Smuzhiyun * But we are still holding ar->mutex, so the
706*4882a593Smuzhiyun * vif data [id, addr] is safe.
707*4882a593Smuzhiyun */
708*4882a593Smuzhiyun err = carl9170_mod_virtual_mac(ar, old_main_priv->id,
709*4882a593Smuzhiyun old_main->addr);
710*4882a593Smuzhiyun if (err)
711*4882a593Smuzhiyun goto unlock;
712*4882a593Smuzhiyun }
713*4882a593Smuzhiyun
714*4882a593Smuzhiyun err = carl9170_init_interface(ar, vif);
715*4882a593Smuzhiyun if (err)
716*4882a593Smuzhiyun goto unlock;
717*4882a593Smuzhiyun } else {
718*4882a593Smuzhiyun rcu_read_unlock();
719*4882a593Smuzhiyun err = carl9170_mod_virtual_mac(ar, vif_id, vif->addr);
720*4882a593Smuzhiyun
721*4882a593Smuzhiyun if (err)
722*4882a593Smuzhiyun goto unlock;
723*4882a593Smuzhiyun }
724*4882a593Smuzhiyun
725*4882a593Smuzhiyun if (ar->fw.tx_seq_table) {
726*4882a593Smuzhiyun err = carl9170_write_reg(ar, ar->fw.tx_seq_table + vif_id * 4,
727*4882a593Smuzhiyun 0);
728*4882a593Smuzhiyun if (err)
729*4882a593Smuzhiyun goto unlock;
730*4882a593Smuzhiyun }
731*4882a593Smuzhiyun
732*4882a593Smuzhiyun unlock:
733*4882a593Smuzhiyun if (err && (vif_id >= 0)) {
734*4882a593Smuzhiyun vif_priv->active = false;
735*4882a593Smuzhiyun bitmap_release_region(&ar->vif_bitmap, vif_id, 0);
736*4882a593Smuzhiyun ar->vifs--;
737*4882a593Smuzhiyun RCU_INIT_POINTER(ar->vif_priv[vif_id].vif, NULL);
738*4882a593Smuzhiyun list_del_rcu(&vif_priv->list);
739*4882a593Smuzhiyun mutex_unlock(&ar->mutex);
740*4882a593Smuzhiyun synchronize_rcu();
741*4882a593Smuzhiyun } else {
742*4882a593Smuzhiyun if (ar->vifs > 1)
743*4882a593Smuzhiyun ar->ps.off_override |= PS_OFF_VIF;
744*4882a593Smuzhiyun
745*4882a593Smuzhiyun mutex_unlock(&ar->mutex);
746*4882a593Smuzhiyun }
747*4882a593Smuzhiyun
748*4882a593Smuzhiyun return err;
749*4882a593Smuzhiyun }
750*4882a593Smuzhiyun
carl9170_op_remove_interface(struct ieee80211_hw * hw,struct ieee80211_vif * vif)751*4882a593Smuzhiyun static void carl9170_op_remove_interface(struct ieee80211_hw *hw,
752*4882a593Smuzhiyun struct ieee80211_vif *vif)
753*4882a593Smuzhiyun {
754*4882a593Smuzhiyun struct carl9170_vif_info *vif_priv = (void *) vif->drv_priv;
755*4882a593Smuzhiyun struct ieee80211_vif *main_vif;
756*4882a593Smuzhiyun struct ar9170 *ar = hw->priv;
757*4882a593Smuzhiyun unsigned int id;
758*4882a593Smuzhiyun
759*4882a593Smuzhiyun mutex_lock(&ar->mutex);
760*4882a593Smuzhiyun
761*4882a593Smuzhiyun if (WARN_ON_ONCE(!vif_priv->active))
762*4882a593Smuzhiyun goto unlock;
763*4882a593Smuzhiyun
764*4882a593Smuzhiyun ar->vifs--;
765*4882a593Smuzhiyun
766*4882a593Smuzhiyun rcu_read_lock();
767*4882a593Smuzhiyun main_vif = carl9170_get_main_vif(ar);
768*4882a593Smuzhiyun
769*4882a593Smuzhiyun id = vif_priv->id;
770*4882a593Smuzhiyun
771*4882a593Smuzhiyun vif_priv->active = false;
772*4882a593Smuzhiyun WARN_ON(vif_priv->enable_beacon);
773*4882a593Smuzhiyun vif_priv->enable_beacon = false;
774*4882a593Smuzhiyun list_del_rcu(&vif_priv->list);
775*4882a593Smuzhiyun RCU_INIT_POINTER(ar->vif_priv[id].vif, NULL);
776*4882a593Smuzhiyun
777*4882a593Smuzhiyun if (vif == main_vif) {
778*4882a593Smuzhiyun rcu_read_unlock();
779*4882a593Smuzhiyun
780*4882a593Smuzhiyun if (ar->vifs) {
781*4882a593Smuzhiyun WARN_ON(carl9170_init_interface(ar,
782*4882a593Smuzhiyun carl9170_get_main_vif(ar)));
783*4882a593Smuzhiyun } else {
784*4882a593Smuzhiyun carl9170_set_operating_mode(ar);
785*4882a593Smuzhiyun }
786*4882a593Smuzhiyun } else {
787*4882a593Smuzhiyun rcu_read_unlock();
788*4882a593Smuzhiyun
789*4882a593Smuzhiyun WARN_ON(carl9170_mod_virtual_mac(ar, id, NULL));
790*4882a593Smuzhiyun }
791*4882a593Smuzhiyun
792*4882a593Smuzhiyun carl9170_update_beacon(ar, false);
793*4882a593Smuzhiyun carl9170_flush_cab(ar, id);
794*4882a593Smuzhiyun
795*4882a593Smuzhiyun spin_lock_bh(&ar->beacon_lock);
796*4882a593Smuzhiyun dev_kfree_skb_any(vif_priv->beacon);
797*4882a593Smuzhiyun vif_priv->beacon = NULL;
798*4882a593Smuzhiyun spin_unlock_bh(&ar->beacon_lock);
799*4882a593Smuzhiyun
800*4882a593Smuzhiyun bitmap_release_region(&ar->vif_bitmap, id, 0);
801*4882a593Smuzhiyun
802*4882a593Smuzhiyun carl9170_set_beacon_timers(ar);
803*4882a593Smuzhiyun
804*4882a593Smuzhiyun if (ar->vifs == 1)
805*4882a593Smuzhiyun ar->ps.off_override &= ~PS_OFF_VIF;
806*4882a593Smuzhiyun
807*4882a593Smuzhiyun unlock:
808*4882a593Smuzhiyun mutex_unlock(&ar->mutex);
809*4882a593Smuzhiyun
810*4882a593Smuzhiyun synchronize_rcu();
811*4882a593Smuzhiyun }
812*4882a593Smuzhiyun
carl9170_ps_check(struct ar9170 * ar)813*4882a593Smuzhiyun void carl9170_ps_check(struct ar9170 *ar)
814*4882a593Smuzhiyun {
815*4882a593Smuzhiyun ieee80211_queue_work(ar->hw, &ar->ps_work);
816*4882a593Smuzhiyun }
817*4882a593Smuzhiyun
818*4882a593Smuzhiyun /* caller must hold ar->mutex */
carl9170_ps_update(struct ar9170 * ar)819*4882a593Smuzhiyun static int carl9170_ps_update(struct ar9170 *ar)
820*4882a593Smuzhiyun {
821*4882a593Smuzhiyun bool ps = false;
822*4882a593Smuzhiyun int err = 0;
823*4882a593Smuzhiyun
824*4882a593Smuzhiyun if (!ar->ps.off_override)
825*4882a593Smuzhiyun ps = (ar->hw->conf.flags & IEEE80211_CONF_PS);
826*4882a593Smuzhiyun
827*4882a593Smuzhiyun if (ps != ar->ps.state) {
828*4882a593Smuzhiyun err = carl9170_powersave(ar, ps);
829*4882a593Smuzhiyun if (err)
830*4882a593Smuzhiyun return err;
831*4882a593Smuzhiyun
832*4882a593Smuzhiyun if (ar->ps.state && !ps) {
833*4882a593Smuzhiyun ar->ps.sleep_ms = jiffies_to_msecs(jiffies -
834*4882a593Smuzhiyun ar->ps.last_action);
835*4882a593Smuzhiyun }
836*4882a593Smuzhiyun
837*4882a593Smuzhiyun if (ps)
838*4882a593Smuzhiyun ar->ps.last_slept = jiffies;
839*4882a593Smuzhiyun
840*4882a593Smuzhiyun ar->ps.last_action = jiffies;
841*4882a593Smuzhiyun ar->ps.state = ps;
842*4882a593Smuzhiyun }
843*4882a593Smuzhiyun
844*4882a593Smuzhiyun return 0;
845*4882a593Smuzhiyun }
846*4882a593Smuzhiyun
carl9170_ps_work(struct work_struct * work)847*4882a593Smuzhiyun static void carl9170_ps_work(struct work_struct *work)
848*4882a593Smuzhiyun {
849*4882a593Smuzhiyun struct ar9170 *ar = container_of(work, struct ar9170,
850*4882a593Smuzhiyun ps_work);
851*4882a593Smuzhiyun mutex_lock(&ar->mutex);
852*4882a593Smuzhiyun if (IS_STARTED(ar))
853*4882a593Smuzhiyun WARN_ON_ONCE(carl9170_ps_update(ar) != 0);
854*4882a593Smuzhiyun mutex_unlock(&ar->mutex);
855*4882a593Smuzhiyun }
856*4882a593Smuzhiyun
carl9170_update_survey(struct ar9170 * ar,bool flush,bool noise)857*4882a593Smuzhiyun static int carl9170_update_survey(struct ar9170 *ar, bool flush, bool noise)
858*4882a593Smuzhiyun {
859*4882a593Smuzhiyun int err;
860*4882a593Smuzhiyun
861*4882a593Smuzhiyun if (noise) {
862*4882a593Smuzhiyun err = carl9170_get_noisefloor(ar);
863*4882a593Smuzhiyun if (err)
864*4882a593Smuzhiyun return err;
865*4882a593Smuzhiyun }
866*4882a593Smuzhiyun
867*4882a593Smuzhiyun if (ar->fw.hw_counters) {
868*4882a593Smuzhiyun err = carl9170_collect_tally(ar);
869*4882a593Smuzhiyun if (err)
870*4882a593Smuzhiyun return err;
871*4882a593Smuzhiyun }
872*4882a593Smuzhiyun
873*4882a593Smuzhiyun if (flush)
874*4882a593Smuzhiyun memset(&ar->tally, 0, sizeof(ar->tally));
875*4882a593Smuzhiyun
876*4882a593Smuzhiyun return 0;
877*4882a593Smuzhiyun }
878*4882a593Smuzhiyun
carl9170_stat_work(struct work_struct * work)879*4882a593Smuzhiyun static void carl9170_stat_work(struct work_struct *work)
880*4882a593Smuzhiyun {
881*4882a593Smuzhiyun struct ar9170 *ar = container_of(work, struct ar9170, stat_work.work);
882*4882a593Smuzhiyun int err;
883*4882a593Smuzhiyun
884*4882a593Smuzhiyun mutex_lock(&ar->mutex);
885*4882a593Smuzhiyun err = carl9170_update_survey(ar, false, true);
886*4882a593Smuzhiyun mutex_unlock(&ar->mutex);
887*4882a593Smuzhiyun
888*4882a593Smuzhiyun if (err)
889*4882a593Smuzhiyun return;
890*4882a593Smuzhiyun
891*4882a593Smuzhiyun ieee80211_queue_delayed_work(ar->hw, &ar->stat_work,
892*4882a593Smuzhiyun round_jiffies(msecs_to_jiffies(CARL9170_STAT_WORK)));
893*4882a593Smuzhiyun }
894*4882a593Smuzhiyun
carl9170_op_config(struct ieee80211_hw * hw,u32 changed)895*4882a593Smuzhiyun static int carl9170_op_config(struct ieee80211_hw *hw, u32 changed)
896*4882a593Smuzhiyun {
897*4882a593Smuzhiyun struct ar9170 *ar = hw->priv;
898*4882a593Smuzhiyun int err = 0;
899*4882a593Smuzhiyun
900*4882a593Smuzhiyun mutex_lock(&ar->mutex);
901*4882a593Smuzhiyun if (changed & IEEE80211_CONF_CHANGE_LISTEN_INTERVAL) {
902*4882a593Smuzhiyun /* TODO */
903*4882a593Smuzhiyun err = 0;
904*4882a593Smuzhiyun }
905*4882a593Smuzhiyun
906*4882a593Smuzhiyun if (changed & IEEE80211_CONF_CHANGE_PS) {
907*4882a593Smuzhiyun err = carl9170_ps_update(ar);
908*4882a593Smuzhiyun if (err)
909*4882a593Smuzhiyun goto out;
910*4882a593Smuzhiyun }
911*4882a593Smuzhiyun
912*4882a593Smuzhiyun if (changed & IEEE80211_CONF_CHANGE_SMPS) {
913*4882a593Smuzhiyun /* TODO */
914*4882a593Smuzhiyun err = 0;
915*4882a593Smuzhiyun }
916*4882a593Smuzhiyun
917*4882a593Smuzhiyun if (changed & IEEE80211_CONF_CHANGE_CHANNEL) {
918*4882a593Smuzhiyun enum nl80211_channel_type channel_type =
919*4882a593Smuzhiyun cfg80211_get_chandef_type(&hw->conf.chandef);
920*4882a593Smuzhiyun
921*4882a593Smuzhiyun /* adjust slot time for 5 GHz */
922*4882a593Smuzhiyun err = carl9170_set_slot_time(ar);
923*4882a593Smuzhiyun if (err)
924*4882a593Smuzhiyun goto out;
925*4882a593Smuzhiyun
926*4882a593Smuzhiyun err = carl9170_update_survey(ar, true, false);
927*4882a593Smuzhiyun if (err)
928*4882a593Smuzhiyun goto out;
929*4882a593Smuzhiyun
930*4882a593Smuzhiyun err = carl9170_set_channel(ar, hw->conf.chandef.chan,
931*4882a593Smuzhiyun channel_type);
932*4882a593Smuzhiyun if (err)
933*4882a593Smuzhiyun goto out;
934*4882a593Smuzhiyun
935*4882a593Smuzhiyun err = carl9170_update_survey(ar, false, true);
936*4882a593Smuzhiyun if (err)
937*4882a593Smuzhiyun goto out;
938*4882a593Smuzhiyun
939*4882a593Smuzhiyun err = carl9170_set_dyn_sifs_ack(ar);
940*4882a593Smuzhiyun if (err)
941*4882a593Smuzhiyun goto out;
942*4882a593Smuzhiyun
943*4882a593Smuzhiyun err = carl9170_set_rts_cts_rate(ar);
944*4882a593Smuzhiyun if (err)
945*4882a593Smuzhiyun goto out;
946*4882a593Smuzhiyun }
947*4882a593Smuzhiyun
948*4882a593Smuzhiyun if (changed & IEEE80211_CONF_CHANGE_POWER) {
949*4882a593Smuzhiyun err = carl9170_set_mac_tpc(ar, ar->hw->conf.chandef.chan);
950*4882a593Smuzhiyun if (err)
951*4882a593Smuzhiyun goto out;
952*4882a593Smuzhiyun }
953*4882a593Smuzhiyun
954*4882a593Smuzhiyun out:
955*4882a593Smuzhiyun mutex_unlock(&ar->mutex);
956*4882a593Smuzhiyun return err;
957*4882a593Smuzhiyun }
958*4882a593Smuzhiyun
carl9170_op_prepare_multicast(struct ieee80211_hw * hw,struct netdev_hw_addr_list * mc_list)959*4882a593Smuzhiyun static u64 carl9170_op_prepare_multicast(struct ieee80211_hw *hw,
960*4882a593Smuzhiyun struct netdev_hw_addr_list *mc_list)
961*4882a593Smuzhiyun {
962*4882a593Smuzhiyun struct netdev_hw_addr *ha;
963*4882a593Smuzhiyun u64 mchash;
964*4882a593Smuzhiyun
965*4882a593Smuzhiyun /* always get broadcast frames */
966*4882a593Smuzhiyun mchash = 1ULL << (0xff >> 2);
967*4882a593Smuzhiyun
968*4882a593Smuzhiyun netdev_hw_addr_list_for_each(ha, mc_list)
969*4882a593Smuzhiyun mchash |= 1ULL << (ha->addr[5] >> 2);
970*4882a593Smuzhiyun
971*4882a593Smuzhiyun return mchash;
972*4882a593Smuzhiyun }
973*4882a593Smuzhiyun
carl9170_op_configure_filter(struct ieee80211_hw * hw,unsigned int changed_flags,unsigned int * new_flags,u64 multicast)974*4882a593Smuzhiyun static void carl9170_op_configure_filter(struct ieee80211_hw *hw,
975*4882a593Smuzhiyun unsigned int changed_flags,
976*4882a593Smuzhiyun unsigned int *new_flags,
977*4882a593Smuzhiyun u64 multicast)
978*4882a593Smuzhiyun {
979*4882a593Smuzhiyun struct ar9170 *ar = hw->priv;
980*4882a593Smuzhiyun
981*4882a593Smuzhiyun /* mask supported flags */
982*4882a593Smuzhiyun *new_flags &= FIF_ALLMULTI | ar->rx_filter_caps;
983*4882a593Smuzhiyun
984*4882a593Smuzhiyun if (!IS_ACCEPTING_CMD(ar))
985*4882a593Smuzhiyun return;
986*4882a593Smuzhiyun
987*4882a593Smuzhiyun mutex_lock(&ar->mutex);
988*4882a593Smuzhiyun
989*4882a593Smuzhiyun ar->filter_state = *new_flags;
990*4882a593Smuzhiyun /*
991*4882a593Smuzhiyun * We can support more by setting the sniffer bit and
992*4882a593Smuzhiyun * then checking the error flags, later.
993*4882a593Smuzhiyun */
994*4882a593Smuzhiyun
995*4882a593Smuzhiyun if (*new_flags & FIF_ALLMULTI)
996*4882a593Smuzhiyun multicast = ~0ULL;
997*4882a593Smuzhiyun
998*4882a593Smuzhiyun if (multicast != ar->cur_mc_hash)
999*4882a593Smuzhiyun WARN_ON(carl9170_update_multicast(ar, multicast));
1000*4882a593Smuzhiyun
1001*4882a593Smuzhiyun if (changed_flags & FIF_OTHER_BSS) {
1002*4882a593Smuzhiyun ar->sniffer_enabled = !!(*new_flags & FIF_OTHER_BSS);
1003*4882a593Smuzhiyun
1004*4882a593Smuzhiyun WARN_ON(carl9170_set_operating_mode(ar));
1005*4882a593Smuzhiyun }
1006*4882a593Smuzhiyun
1007*4882a593Smuzhiyun if (ar->fw.rx_filter && changed_flags & ar->rx_filter_caps) {
1008*4882a593Smuzhiyun u32 rx_filter = 0;
1009*4882a593Smuzhiyun
1010*4882a593Smuzhiyun if (!ar->fw.ba_filter)
1011*4882a593Smuzhiyun rx_filter |= CARL9170_RX_FILTER_CTL_OTHER;
1012*4882a593Smuzhiyun
1013*4882a593Smuzhiyun if (!(*new_flags & (FIF_FCSFAIL | FIF_PLCPFAIL)))
1014*4882a593Smuzhiyun rx_filter |= CARL9170_RX_FILTER_BAD;
1015*4882a593Smuzhiyun
1016*4882a593Smuzhiyun if (!(*new_flags & FIF_CONTROL))
1017*4882a593Smuzhiyun rx_filter |= CARL9170_RX_FILTER_CTL_OTHER;
1018*4882a593Smuzhiyun
1019*4882a593Smuzhiyun if (!(*new_flags & FIF_PSPOLL))
1020*4882a593Smuzhiyun rx_filter |= CARL9170_RX_FILTER_CTL_PSPOLL;
1021*4882a593Smuzhiyun
1022*4882a593Smuzhiyun if (!(*new_flags & FIF_OTHER_BSS)) {
1023*4882a593Smuzhiyun rx_filter |= CARL9170_RX_FILTER_OTHER_RA;
1024*4882a593Smuzhiyun rx_filter |= CARL9170_RX_FILTER_DECRY_FAIL;
1025*4882a593Smuzhiyun }
1026*4882a593Smuzhiyun
1027*4882a593Smuzhiyun WARN_ON(carl9170_rx_filter(ar, rx_filter));
1028*4882a593Smuzhiyun }
1029*4882a593Smuzhiyun
1030*4882a593Smuzhiyun mutex_unlock(&ar->mutex);
1031*4882a593Smuzhiyun }
1032*4882a593Smuzhiyun
1033*4882a593Smuzhiyun
carl9170_op_bss_info_changed(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_bss_conf * bss_conf,u32 changed)1034*4882a593Smuzhiyun static void carl9170_op_bss_info_changed(struct ieee80211_hw *hw,
1035*4882a593Smuzhiyun struct ieee80211_vif *vif,
1036*4882a593Smuzhiyun struct ieee80211_bss_conf *bss_conf,
1037*4882a593Smuzhiyun u32 changed)
1038*4882a593Smuzhiyun {
1039*4882a593Smuzhiyun struct ar9170 *ar = hw->priv;
1040*4882a593Smuzhiyun struct ath_common *common = &ar->common;
1041*4882a593Smuzhiyun int err = 0;
1042*4882a593Smuzhiyun struct carl9170_vif_info *vif_priv;
1043*4882a593Smuzhiyun struct ieee80211_vif *main_vif;
1044*4882a593Smuzhiyun
1045*4882a593Smuzhiyun mutex_lock(&ar->mutex);
1046*4882a593Smuzhiyun vif_priv = (void *) vif->drv_priv;
1047*4882a593Smuzhiyun main_vif = carl9170_get_main_vif(ar);
1048*4882a593Smuzhiyun if (WARN_ON(!main_vif))
1049*4882a593Smuzhiyun goto out;
1050*4882a593Smuzhiyun
1051*4882a593Smuzhiyun if (changed & BSS_CHANGED_BEACON_ENABLED) {
1052*4882a593Smuzhiyun struct carl9170_vif_info *iter;
1053*4882a593Smuzhiyun int i = 0;
1054*4882a593Smuzhiyun
1055*4882a593Smuzhiyun vif_priv->enable_beacon = bss_conf->enable_beacon;
1056*4882a593Smuzhiyun rcu_read_lock();
1057*4882a593Smuzhiyun list_for_each_entry_rcu(iter, &ar->vif_list, list) {
1058*4882a593Smuzhiyun if (iter->active && iter->enable_beacon)
1059*4882a593Smuzhiyun i++;
1060*4882a593Smuzhiyun
1061*4882a593Smuzhiyun }
1062*4882a593Smuzhiyun rcu_read_unlock();
1063*4882a593Smuzhiyun
1064*4882a593Smuzhiyun ar->beacon_enabled = i;
1065*4882a593Smuzhiyun }
1066*4882a593Smuzhiyun
1067*4882a593Smuzhiyun if (changed & BSS_CHANGED_BEACON) {
1068*4882a593Smuzhiyun err = carl9170_update_beacon(ar, false);
1069*4882a593Smuzhiyun if (err)
1070*4882a593Smuzhiyun goto out;
1071*4882a593Smuzhiyun }
1072*4882a593Smuzhiyun
1073*4882a593Smuzhiyun if (changed & (BSS_CHANGED_BEACON_ENABLED | BSS_CHANGED_BEACON |
1074*4882a593Smuzhiyun BSS_CHANGED_BEACON_INT)) {
1075*4882a593Smuzhiyun
1076*4882a593Smuzhiyun if (main_vif != vif) {
1077*4882a593Smuzhiyun bss_conf->beacon_int = main_vif->bss_conf.beacon_int;
1078*4882a593Smuzhiyun bss_conf->dtim_period = main_vif->bss_conf.dtim_period;
1079*4882a593Smuzhiyun }
1080*4882a593Smuzhiyun
1081*4882a593Smuzhiyun /*
1082*4882a593Smuzhiyun * Therefore a hard limit for the broadcast traffic should
1083*4882a593Smuzhiyun * prevent false alarms.
1084*4882a593Smuzhiyun */
1085*4882a593Smuzhiyun if (vif->type != NL80211_IFTYPE_STATION &&
1086*4882a593Smuzhiyun (bss_conf->beacon_int * bss_conf->dtim_period >=
1087*4882a593Smuzhiyun (CARL9170_QUEUE_STUCK_TIMEOUT / 2))) {
1088*4882a593Smuzhiyun err = -EINVAL;
1089*4882a593Smuzhiyun goto out;
1090*4882a593Smuzhiyun }
1091*4882a593Smuzhiyun
1092*4882a593Smuzhiyun err = carl9170_set_beacon_timers(ar);
1093*4882a593Smuzhiyun if (err)
1094*4882a593Smuzhiyun goto out;
1095*4882a593Smuzhiyun }
1096*4882a593Smuzhiyun
1097*4882a593Smuzhiyun if (changed & BSS_CHANGED_HT) {
1098*4882a593Smuzhiyun /* TODO */
1099*4882a593Smuzhiyun err = 0;
1100*4882a593Smuzhiyun if (err)
1101*4882a593Smuzhiyun goto out;
1102*4882a593Smuzhiyun }
1103*4882a593Smuzhiyun
1104*4882a593Smuzhiyun if (main_vif != vif)
1105*4882a593Smuzhiyun goto out;
1106*4882a593Smuzhiyun
1107*4882a593Smuzhiyun /*
1108*4882a593Smuzhiyun * The following settings can only be changed by the
1109*4882a593Smuzhiyun * master interface.
1110*4882a593Smuzhiyun */
1111*4882a593Smuzhiyun
1112*4882a593Smuzhiyun if (changed & BSS_CHANGED_BSSID) {
1113*4882a593Smuzhiyun memcpy(common->curbssid, bss_conf->bssid, ETH_ALEN);
1114*4882a593Smuzhiyun err = carl9170_set_operating_mode(ar);
1115*4882a593Smuzhiyun if (err)
1116*4882a593Smuzhiyun goto out;
1117*4882a593Smuzhiyun }
1118*4882a593Smuzhiyun
1119*4882a593Smuzhiyun if (changed & BSS_CHANGED_ASSOC) {
1120*4882a593Smuzhiyun ar->common.curaid = bss_conf->aid;
1121*4882a593Smuzhiyun err = carl9170_set_beacon_timers(ar);
1122*4882a593Smuzhiyun if (err)
1123*4882a593Smuzhiyun goto out;
1124*4882a593Smuzhiyun }
1125*4882a593Smuzhiyun
1126*4882a593Smuzhiyun if (changed & BSS_CHANGED_ERP_SLOT) {
1127*4882a593Smuzhiyun err = carl9170_set_slot_time(ar);
1128*4882a593Smuzhiyun if (err)
1129*4882a593Smuzhiyun goto out;
1130*4882a593Smuzhiyun }
1131*4882a593Smuzhiyun
1132*4882a593Smuzhiyun if (changed & BSS_CHANGED_BASIC_RATES) {
1133*4882a593Smuzhiyun err = carl9170_set_mac_rates(ar);
1134*4882a593Smuzhiyun if (err)
1135*4882a593Smuzhiyun goto out;
1136*4882a593Smuzhiyun }
1137*4882a593Smuzhiyun
1138*4882a593Smuzhiyun out:
1139*4882a593Smuzhiyun WARN_ON_ONCE(err && IS_STARTED(ar));
1140*4882a593Smuzhiyun mutex_unlock(&ar->mutex);
1141*4882a593Smuzhiyun }
1142*4882a593Smuzhiyun
carl9170_op_get_tsf(struct ieee80211_hw * hw,struct ieee80211_vif * vif)1143*4882a593Smuzhiyun static u64 carl9170_op_get_tsf(struct ieee80211_hw *hw,
1144*4882a593Smuzhiyun struct ieee80211_vif *vif)
1145*4882a593Smuzhiyun {
1146*4882a593Smuzhiyun struct ar9170 *ar = hw->priv;
1147*4882a593Smuzhiyun struct carl9170_tsf_rsp tsf;
1148*4882a593Smuzhiyun int err;
1149*4882a593Smuzhiyun
1150*4882a593Smuzhiyun mutex_lock(&ar->mutex);
1151*4882a593Smuzhiyun err = carl9170_exec_cmd(ar, CARL9170_CMD_READ_TSF,
1152*4882a593Smuzhiyun 0, NULL, sizeof(tsf), &tsf);
1153*4882a593Smuzhiyun mutex_unlock(&ar->mutex);
1154*4882a593Smuzhiyun if (WARN_ON(err))
1155*4882a593Smuzhiyun return 0;
1156*4882a593Smuzhiyun
1157*4882a593Smuzhiyun return le64_to_cpu(tsf.tsf_64);
1158*4882a593Smuzhiyun }
1159*4882a593Smuzhiyun
carl9170_op_set_key(struct ieee80211_hw * hw,enum set_key_cmd cmd,struct ieee80211_vif * vif,struct ieee80211_sta * sta,struct ieee80211_key_conf * key)1160*4882a593Smuzhiyun static int carl9170_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
1161*4882a593Smuzhiyun struct ieee80211_vif *vif,
1162*4882a593Smuzhiyun struct ieee80211_sta *sta,
1163*4882a593Smuzhiyun struct ieee80211_key_conf *key)
1164*4882a593Smuzhiyun {
1165*4882a593Smuzhiyun struct ar9170 *ar = hw->priv;
1166*4882a593Smuzhiyun int err = 0, i;
1167*4882a593Smuzhiyun u8 ktype;
1168*4882a593Smuzhiyun
1169*4882a593Smuzhiyun if (ar->disable_offload || !vif)
1170*4882a593Smuzhiyun return -EOPNOTSUPP;
1171*4882a593Smuzhiyun
1172*4882a593Smuzhiyun /* Fall back to software encryption whenever the driver is connected
1173*4882a593Smuzhiyun * to more than one network.
1174*4882a593Smuzhiyun *
1175*4882a593Smuzhiyun * This is very unfortunate, because some machines cannot handle
1176*4882a593Smuzhiyun * the high througput speed in 802.11n networks.
1177*4882a593Smuzhiyun */
1178*4882a593Smuzhiyun
1179*4882a593Smuzhiyun if (!is_main_vif(ar, vif)) {
1180*4882a593Smuzhiyun mutex_lock(&ar->mutex);
1181*4882a593Smuzhiyun goto err_softw;
1182*4882a593Smuzhiyun }
1183*4882a593Smuzhiyun
1184*4882a593Smuzhiyun /*
1185*4882a593Smuzhiyun * While the hardware supports *catch-all* key, for offloading
1186*4882a593Smuzhiyun * group-key en-/de-cryption. The way of how the hardware
1187*4882a593Smuzhiyun * decides which keyId maps to which key, remains a mystery...
1188*4882a593Smuzhiyun */
1189*4882a593Smuzhiyun if ((vif->type != NL80211_IFTYPE_STATION &&
1190*4882a593Smuzhiyun vif->type != NL80211_IFTYPE_ADHOC) &&
1191*4882a593Smuzhiyun !(key->flags & IEEE80211_KEY_FLAG_PAIRWISE))
1192*4882a593Smuzhiyun return -EOPNOTSUPP;
1193*4882a593Smuzhiyun
1194*4882a593Smuzhiyun switch (key->cipher) {
1195*4882a593Smuzhiyun case WLAN_CIPHER_SUITE_WEP40:
1196*4882a593Smuzhiyun ktype = AR9170_ENC_ALG_WEP64;
1197*4882a593Smuzhiyun break;
1198*4882a593Smuzhiyun case WLAN_CIPHER_SUITE_WEP104:
1199*4882a593Smuzhiyun ktype = AR9170_ENC_ALG_WEP128;
1200*4882a593Smuzhiyun break;
1201*4882a593Smuzhiyun case WLAN_CIPHER_SUITE_TKIP:
1202*4882a593Smuzhiyun ktype = AR9170_ENC_ALG_TKIP;
1203*4882a593Smuzhiyun break;
1204*4882a593Smuzhiyun case WLAN_CIPHER_SUITE_CCMP:
1205*4882a593Smuzhiyun ktype = AR9170_ENC_ALG_AESCCMP;
1206*4882a593Smuzhiyun key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
1207*4882a593Smuzhiyun break;
1208*4882a593Smuzhiyun default:
1209*4882a593Smuzhiyun return -EOPNOTSUPP;
1210*4882a593Smuzhiyun }
1211*4882a593Smuzhiyun
1212*4882a593Smuzhiyun mutex_lock(&ar->mutex);
1213*4882a593Smuzhiyun if (cmd == SET_KEY) {
1214*4882a593Smuzhiyun if (!IS_STARTED(ar)) {
1215*4882a593Smuzhiyun err = -EOPNOTSUPP;
1216*4882a593Smuzhiyun goto out;
1217*4882a593Smuzhiyun }
1218*4882a593Smuzhiyun
1219*4882a593Smuzhiyun if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
1220*4882a593Smuzhiyun sta = NULL;
1221*4882a593Smuzhiyun
1222*4882a593Smuzhiyun i = 64 + key->keyidx;
1223*4882a593Smuzhiyun } else {
1224*4882a593Smuzhiyun for (i = 0; i < 64; i++)
1225*4882a593Smuzhiyun if (!(ar->usedkeys & BIT(i)))
1226*4882a593Smuzhiyun break;
1227*4882a593Smuzhiyun if (i == 64)
1228*4882a593Smuzhiyun goto err_softw;
1229*4882a593Smuzhiyun }
1230*4882a593Smuzhiyun
1231*4882a593Smuzhiyun key->hw_key_idx = i;
1232*4882a593Smuzhiyun
1233*4882a593Smuzhiyun err = carl9170_upload_key(ar, i, sta ? sta->addr : NULL,
1234*4882a593Smuzhiyun ktype, 0, key->key,
1235*4882a593Smuzhiyun min_t(u8, 16, key->keylen));
1236*4882a593Smuzhiyun if (err)
1237*4882a593Smuzhiyun goto out;
1238*4882a593Smuzhiyun
1239*4882a593Smuzhiyun if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
1240*4882a593Smuzhiyun err = carl9170_upload_key(ar, i, sta ? sta->addr :
1241*4882a593Smuzhiyun NULL, ktype, 1,
1242*4882a593Smuzhiyun key->key + 16, 16);
1243*4882a593Smuzhiyun if (err)
1244*4882a593Smuzhiyun goto out;
1245*4882a593Smuzhiyun
1246*4882a593Smuzhiyun /*
1247*4882a593Smuzhiyun * hardware is not capable generating MMIC
1248*4882a593Smuzhiyun * of fragmented frames!
1249*4882a593Smuzhiyun */
1250*4882a593Smuzhiyun key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC;
1251*4882a593Smuzhiyun }
1252*4882a593Smuzhiyun
1253*4882a593Smuzhiyun if (i < 64)
1254*4882a593Smuzhiyun ar->usedkeys |= BIT(i);
1255*4882a593Smuzhiyun
1256*4882a593Smuzhiyun key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV;
1257*4882a593Smuzhiyun } else {
1258*4882a593Smuzhiyun if (!IS_STARTED(ar)) {
1259*4882a593Smuzhiyun /* The device is gone... together with the key ;-) */
1260*4882a593Smuzhiyun err = 0;
1261*4882a593Smuzhiyun goto out;
1262*4882a593Smuzhiyun }
1263*4882a593Smuzhiyun
1264*4882a593Smuzhiyun if (key->hw_key_idx < 64) {
1265*4882a593Smuzhiyun ar->usedkeys &= ~BIT(key->hw_key_idx);
1266*4882a593Smuzhiyun } else {
1267*4882a593Smuzhiyun err = carl9170_upload_key(ar, key->hw_key_idx, NULL,
1268*4882a593Smuzhiyun AR9170_ENC_ALG_NONE, 0,
1269*4882a593Smuzhiyun NULL, 0);
1270*4882a593Smuzhiyun if (err)
1271*4882a593Smuzhiyun goto out;
1272*4882a593Smuzhiyun
1273*4882a593Smuzhiyun if (key->cipher == WLAN_CIPHER_SUITE_TKIP) {
1274*4882a593Smuzhiyun err = carl9170_upload_key(ar, key->hw_key_idx,
1275*4882a593Smuzhiyun NULL,
1276*4882a593Smuzhiyun AR9170_ENC_ALG_NONE,
1277*4882a593Smuzhiyun 1, NULL, 0);
1278*4882a593Smuzhiyun if (err)
1279*4882a593Smuzhiyun goto out;
1280*4882a593Smuzhiyun }
1281*4882a593Smuzhiyun
1282*4882a593Smuzhiyun }
1283*4882a593Smuzhiyun
1284*4882a593Smuzhiyun err = carl9170_disable_key(ar, key->hw_key_idx);
1285*4882a593Smuzhiyun if (err)
1286*4882a593Smuzhiyun goto out;
1287*4882a593Smuzhiyun }
1288*4882a593Smuzhiyun
1289*4882a593Smuzhiyun out:
1290*4882a593Smuzhiyun mutex_unlock(&ar->mutex);
1291*4882a593Smuzhiyun return err;
1292*4882a593Smuzhiyun
1293*4882a593Smuzhiyun err_softw:
1294*4882a593Smuzhiyun if (!ar->rx_software_decryption) {
1295*4882a593Smuzhiyun ar->rx_software_decryption = true;
1296*4882a593Smuzhiyun carl9170_set_operating_mode(ar);
1297*4882a593Smuzhiyun }
1298*4882a593Smuzhiyun mutex_unlock(&ar->mutex);
1299*4882a593Smuzhiyun return -ENOSPC;
1300*4882a593Smuzhiyun }
1301*4882a593Smuzhiyun
carl9170_op_sta_add(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta)1302*4882a593Smuzhiyun static int carl9170_op_sta_add(struct ieee80211_hw *hw,
1303*4882a593Smuzhiyun struct ieee80211_vif *vif,
1304*4882a593Smuzhiyun struct ieee80211_sta *sta)
1305*4882a593Smuzhiyun {
1306*4882a593Smuzhiyun struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
1307*4882a593Smuzhiyun unsigned int i;
1308*4882a593Smuzhiyun
1309*4882a593Smuzhiyun atomic_set(&sta_info->pending_frames, 0);
1310*4882a593Smuzhiyun
1311*4882a593Smuzhiyun if (sta->ht_cap.ht_supported) {
1312*4882a593Smuzhiyun if (sta->ht_cap.ampdu_density > 6) {
1313*4882a593Smuzhiyun /*
1314*4882a593Smuzhiyun * HW does support 16us AMPDU density.
1315*4882a593Smuzhiyun * No HT-Xmit for station.
1316*4882a593Smuzhiyun */
1317*4882a593Smuzhiyun
1318*4882a593Smuzhiyun return 0;
1319*4882a593Smuzhiyun }
1320*4882a593Smuzhiyun
1321*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(sta_info->agg); i++)
1322*4882a593Smuzhiyun RCU_INIT_POINTER(sta_info->agg[i], NULL);
1323*4882a593Smuzhiyun
1324*4882a593Smuzhiyun sta_info->ampdu_max_len = 1 << (3 + sta->ht_cap.ampdu_factor);
1325*4882a593Smuzhiyun sta_info->ht_sta = true;
1326*4882a593Smuzhiyun }
1327*4882a593Smuzhiyun
1328*4882a593Smuzhiyun return 0;
1329*4882a593Smuzhiyun }
1330*4882a593Smuzhiyun
carl9170_op_sta_remove(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_sta * sta)1331*4882a593Smuzhiyun static int carl9170_op_sta_remove(struct ieee80211_hw *hw,
1332*4882a593Smuzhiyun struct ieee80211_vif *vif,
1333*4882a593Smuzhiyun struct ieee80211_sta *sta)
1334*4882a593Smuzhiyun {
1335*4882a593Smuzhiyun struct ar9170 *ar = hw->priv;
1336*4882a593Smuzhiyun struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
1337*4882a593Smuzhiyun unsigned int i;
1338*4882a593Smuzhiyun bool cleanup = false;
1339*4882a593Smuzhiyun
1340*4882a593Smuzhiyun if (sta->ht_cap.ht_supported) {
1341*4882a593Smuzhiyun
1342*4882a593Smuzhiyun sta_info->ht_sta = false;
1343*4882a593Smuzhiyun
1344*4882a593Smuzhiyun rcu_read_lock();
1345*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(sta_info->agg); i++) {
1346*4882a593Smuzhiyun struct carl9170_sta_tid *tid_info;
1347*4882a593Smuzhiyun
1348*4882a593Smuzhiyun tid_info = rcu_dereference(sta_info->agg[i]);
1349*4882a593Smuzhiyun RCU_INIT_POINTER(sta_info->agg[i], NULL);
1350*4882a593Smuzhiyun
1351*4882a593Smuzhiyun if (!tid_info)
1352*4882a593Smuzhiyun continue;
1353*4882a593Smuzhiyun
1354*4882a593Smuzhiyun spin_lock_bh(&ar->tx_ampdu_list_lock);
1355*4882a593Smuzhiyun if (tid_info->state > CARL9170_TID_STATE_SHUTDOWN)
1356*4882a593Smuzhiyun tid_info->state = CARL9170_TID_STATE_SHUTDOWN;
1357*4882a593Smuzhiyun spin_unlock_bh(&ar->tx_ampdu_list_lock);
1358*4882a593Smuzhiyun cleanup = true;
1359*4882a593Smuzhiyun }
1360*4882a593Smuzhiyun rcu_read_unlock();
1361*4882a593Smuzhiyun
1362*4882a593Smuzhiyun if (cleanup)
1363*4882a593Smuzhiyun carl9170_ampdu_gc(ar);
1364*4882a593Smuzhiyun }
1365*4882a593Smuzhiyun
1366*4882a593Smuzhiyun return 0;
1367*4882a593Smuzhiyun }
1368*4882a593Smuzhiyun
carl9170_op_conf_tx(struct ieee80211_hw * hw,struct ieee80211_vif * vif,u16 queue,const struct ieee80211_tx_queue_params * param)1369*4882a593Smuzhiyun static int carl9170_op_conf_tx(struct ieee80211_hw *hw,
1370*4882a593Smuzhiyun struct ieee80211_vif *vif, u16 queue,
1371*4882a593Smuzhiyun const struct ieee80211_tx_queue_params *param)
1372*4882a593Smuzhiyun {
1373*4882a593Smuzhiyun struct ar9170 *ar = hw->priv;
1374*4882a593Smuzhiyun int ret;
1375*4882a593Smuzhiyun
1376*4882a593Smuzhiyun mutex_lock(&ar->mutex);
1377*4882a593Smuzhiyun memcpy(&ar->edcf[ar9170_qmap(queue)], param, sizeof(*param));
1378*4882a593Smuzhiyun ret = carl9170_set_qos(ar);
1379*4882a593Smuzhiyun mutex_unlock(&ar->mutex);
1380*4882a593Smuzhiyun return ret;
1381*4882a593Smuzhiyun }
1382*4882a593Smuzhiyun
carl9170_ampdu_work(struct work_struct * work)1383*4882a593Smuzhiyun static void carl9170_ampdu_work(struct work_struct *work)
1384*4882a593Smuzhiyun {
1385*4882a593Smuzhiyun struct ar9170 *ar = container_of(work, struct ar9170,
1386*4882a593Smuzhiyun ampdu_work);
1387*4882a593Smuzhiyun
1388*4882a593Smuzhiyun if (!IS_STARTED(ar))
1389*4882a593Smuzhiyun return;
1390*4882a593Smuzhiyun
1391*4882a593Smuzhiyun mutex_lock(&ar->mutex);
1392*4882a593Smuzhiyun carl9170_ampdu_gc(ar);
1393*4882a593Smuzhiyun mutex_unlock(&ar->mutex);
1394*4882a593Smuzhiyun }
1395*4882a593Smuzhiyun
carl9170_op_ampdu_action(struct ieee80211_hw * hw,struct ieee80211_vif * vif,struct ieee80211_ampdu_params * params)1396*4882a593Smuzhiyun static int carl9170_op_ampdu_action(struct ieee80211_hw *hw,
1397*4882a593Smuzhiyun struct ieee80211_vif *vif,
1398*4882a593Smuzhiyun struct ieee80211_ampdu_params *params)
1399*4882a593Smuzhiyun {
1400*4882a593Smuzhiyun struct ieee80211_sta *sta = params->sta;
1401*4882a593Smuzhiyun enum ieee80211_ampdu_mlme_action action = params->action;
1402*4882a593Smuzhiyun u16 tid = params->tid;
1403*4882a593Smuzhiyun u16 *ssn = ¶ms->ssn;
1404*4882a593Smuzhiyun struct ar9170 *ar = hw->priv;
1405*4882a593Smuzhiyun struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
1406*4882a593Smuzhiyun struct carl9170_sta_tid *tid_info;
1407*4882a593Smuzhiyun
1408*4882a593Smuzhiyun if (modparam_noht)
1409*4882a593Smuzhiyun return -EOPNOTSUPP;
1410*4882a593Smuzhiyun
1411*4882a593Smuzhiyun switch (action) {
1412*4882a593Smuzhiyun case IEEE80211_AMPDU_TX_START:
1413*4882a593Smuzhiyun if (!sta_info->ht_sta)
1414*4882a593Smuzhiyun return -EOPNOTSUPP;
1415*4882a593Smuzhiyun
1416*4882a593Smuzhiyun tid_info = kzalloc(sizeof(struct carl9170_sta_tid),
1417*4882a593Smuzhiyun GFP_ATOMIC);
1418*4882a593Smuzhiyun if (!tid_info)
1419*4882a593Smuzhiyun return -ENOMEM;
1420*4882a593Smuzhiyun
1421*4882a593Smuzhiyun tid_info->hsn = tid_info->bsn = tid_info->snx = (*ssn);
1422*4882a593Smuzhiyun tid_info->state = CARL9170_TID_STATE_PROGRESS;
1423*4882a593Smuzhiyun tid_info->tid = tid;
1424*4882a593Smuzhiyun tid_info->max = sta_info->ampdu_max_len;
1425*4882a593Smuzhiyun tid_info->sta = sta;
1426*4882a593Smuzhiyun tid_info->vif = vif;
1427*4882a593Smuzhiyun
1428*4882a593Smuzhiyun INIT_LIST_HEAD(&tid_info->list);
1429*4882a593Smuzhiyun INIT_LIST_HEAD(&tid_info->tmp_list);
1430*4882a593Smuzhiyun skb_queue_head_init(&tid_info->queue);
1431*4882a593Smuzhiyun spin_lock_init(&tid_info->lock);
1432*4882a593Smuzhiyun
1433*4882a593Smuzhiyun spin_lock_bh(&ar->tx_ampdu_list_lock);
1434*4882a593Smuzhiyun ar->tx_ampdu_list_len++;
1435*4882a593Smuzhiyun list_add_tail_rcu(&tid_info->list, &ar->tx_ampdu_list);
1436*4882a593Smuzhiyun rcu_assign_pointer(sta_info->agg[tid], tid_info);
1437*4882a593Smuzhiyun spin_unlock_bh(&ar->tx_ampdu_list_lock);
1438*4882a593Smuzhiyun
1439*4882a593Smuzhiyun return IEEE80211_AMPDU_TX_START_IMMEDIATE;
1440*4882a593Smuzhiyun
1441*4882a593Smuzhiyun case IEEE80211_AMPDU_TX_STOP_CONT:
1442*4882a593Smuzhiyun case IEEE80211_AMPDU_TX_STOP_FLUSH:
1443*4882a593Smuzhiyun case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
1444*4882a593Smuzhiyun rcu_read_lock();
1445*4882a593Smuzhiyun tid_info = rcu_dereference(sta_info->agg[tid]);
1446*4882a593Smuzhiyun if (tid_info) {
1447*4882a593Smuzhiyun spin_lock_bh(&ar->tx_ampdu_list_lock);
1448*4882a593Smuzhiyun if (tid_info->state > CARL9170_TID_STATE_SHUTDOWN)
1449*4882a593Smuzhiyun tid_info->state = CARL9170_TID_STATE_SHUTDOWN;
1450*4882a593Smuzhiyun spin_unlock_bh(&ar->tx_ampdu_list_lock);
1451*4882a593Smuzhiyun }
1452*4882a593Smuzhiyun
1453*4882a593Smuzhiyun RCU_INIT_POINTER(sta_info->agg[tid], NULL);
1454*4882a593Smuzhiyun rcu_read_unlock();
1455*4882a593Smuzhiyun
1456*4882a593Smuzhiyun ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
1457*4882a593Smuzhiyun ieee80211_queue_work(ar->hw, &ar->ampdu_work);
1458*4882a593Smuzhiyun break;
1459*4882a593Smuzhiyun
1460*4882a593Smuzhiyun case IEEE80211_AMPDU_TX_OPERATIONAL:
1461*4882a593Smuzhiyun rcu_read_lock();
1462*4882a593Smuzhiyun tid_info = rcu_dereference(sta_info->agg[tid]);
1463*4882a593Smuzhiyun
1464*4882a593Smuzhiyun sta_info->stats[tid].clear = true;
1465*4882a593Smuzhiyun sta_info->stats[tid].req = false;
1466*4882a593Smuzhiyun
1467*4882a593Smuzhiyun if (tid_info) {
1468*4882a593Smuzhiyun bitmap_zero(tid_info->bitmap, CARL9170_BAW_SIZE);
1469*4882a593Smuzhiyun tid_info->state = CARL9170_TID_STATE_IDLE;
1470*4882a593Smuzhiyun }
1471*4882a593Smuzhiyun rcu_read_unlock();
1472*4882a593Smuzhiyun
1473*4882a593Smuzhiyun if (WARN_ON_ONCE(!tid_info))
1474*4882a593Smuzhiyun return -EFAULT;
1475*4882a593Smuzhiyun
1476*4882a593Smuzhiyun break;
1477*4882a593Smuzhiyun
1478*4882a593Smuzhiyun case IEEE80211_AMPDU_RX_START:
1479*4882a593Smuzhiyun case IEEE80211_AMPDU_RX_STOP:
1480*4882a593Smuzhiyun /* Handled by hardware */
1481*4882a593Smuzhiyun break;
1482*4882a593Smuzhiyun
1483*4882a593Smuzhiyun default:
1484*4882a593Smuzhiyun return -EOPNOTSUPP;
1485*4882a593Smuzhiyun }
1486*4882a593Smuzhiyun
1487*4882a593Smuzhiyun return 0;
1488*4882a593Smuzhiyun }
1489*4882a593Smuzhiyun
1490*4882a593Smuzhiyun #ifdef CONFIG_CARL9170_WPC
carl9170_register_wps_button(struct ar9170 * ar)1491*4882a593Smuzhiyun static int carl9170_register_wps_button(struct ar9170 *ar)
1492*4882a593Smuzhiyun {
1493*4882a593Smuzhiyun struct input_dev *input;
1494*4882a593Smuzhiyun int err;
1495*4882a593Smuzhiyun
1496*4882a593Smuzhiyun if (!(ar->features & CARL9170_WPS_BUTTON))
1497*4882a593Smuzhiyun return 0;
1498*4882a593Smuzhiyun
1499*4882a593Smuzhiyun input = input_allocate_device();
1500*4882a593Smuzhiyun if (!input)
1501*4882a593Smuzhiyun return -ENOMEM;
1502*4882a593Smuzhiyun
1503*4882a593Smuzhiyun snprintf(ar->wps.name, sizeof(ar->wps.name), "%s WPS Button",
1504*4882a593Smuzhiyun wiphy_name(ar->hw->wiphy));
1505*4882a593Smuzhiyun
1506*4882a593Smuzhiyun snprintf(ar->wps.phys, sizeof(ar->wps.phys),
1507*4882a593Smuzhiyun "ieee80211/%s/input0", wiphy_name(ar->hw->wiphy));
1508*4882a593Smuzhiyun
1509*4882a593Smuzhiyun input->name = ar->wps.name;
1510*4882a593Smuzhiyun input->phys = ar->wps.phys;
1511*4882a593Smuzhiyun input->id.bustype = BUS_USB;
1512*4882a593Smuzhiyun input->dev.parent = &ar->hw->wiphy->dev;
1513*4882a593Smuzhiyun
1514*4882a593Smuzhiyun input_set_capability(input, EV_KEY, KEY_WPS_BUTTON);
1515*4882a593Smuzhiyun
1516*4882a593Smuzhiyun err = input_register_device(input);
1517*4882a593Smuzhiyun if (err) {
1518*4882a593Smuzhiyun input_free_device(input);
1519*4882a593Smuzhiyun return err;
1520*4882a593Smuzhiyun }
1521*4882a593Smuzhiyun
1522*4882a593Smuzhiyun ar->wps.pbc = input;
1523*4882a593Smuzhiyun return 0;
1524*4882a593Smuzhiyun }
1525*4882a593Smuzhiyun #endif /* CONFIG_CARL9170_WPC */
1526*4882a593Smuzhiyun
1527*4882a593Smuzhiyun #ifdef CONFIG_CARL9170_HWRNG
carl9170_rng_get(struct ar9170 * ar)1528*4882a593Smuzhiyun static int carl9170_rng_get(struct ar9170 *ar)
1529*4882a593Smuzhiyun {
1530*4882a593Smuzhiyun
1531*4882a593Smuzhiyun #define RW (CARL9170_MAX_CMD_PAYLOAD_LEN / sizeof(u32))
1532*4882a593Smuzhiyun #define RB (CARL9170_MAX_CMD_PAYLOAD_LEN)
1533*4882a593Smuzhiyun
1534*4882a593Smuzhiyun static const __le32 rng_load[RW] = {
1535*4882a593Smuzhiyun [0 ... (RW - 1)] = cpu_to_le32(AR9170_RAND_REG_NUM)};
1536*4882a593Smuzhiyun
1537*4882a593Smuzhiyun u32 buf[RW];
1538*4882a593Smuzhiyun
1539*4882a593Smuzhiyun unsigned int i, off = 0, transfer, count;
1540*4882a593Smuzhiyun int err;
1541*4882a593Smuzhiyun
1542*4882a593Smuzhiyun BUILD_BUG_ON(RB > CARL9170_MAX_CMD_PAYLOAD_LEN);
1543*4882a593Smuzhiyun
1544*4882a593Smuzhiyun if (!IS_ACCEPTING_CMD(ar) || !ar->rng.initialized)
1545*4882a593Smuzhiyun return -EAGAIN;
1546*4882a593Smuzhiyun
1547*4882a593Smuzhiyun count = ARRAY_SIZE(ar->rng.cache);
1548*4882a593Smuzhiyun while (count) {
1549*4882a593Smuzhiyun err = carl9170_exec_cmd(ar, CARL9170_CMD_RREG,
1550*4882a593Smuzhiyun RB, (u8 *) rng_load,
1551*4882a593Smuzhiyun RB, (u8 *) buf);
1552*4882a593Smuzhiyun if (err)
1553*4882a593Smuzhiyun return err;
1554*4882a593Smuzhiyun
1555*4882a593Smuzhiyun transfer = min_t(unsigned int, count, RW);
1556*4882a593Smuzhiyun for (i = 0; i < transfer; i++)
1557*4882a593Smuzhiyun ar->rng.cache[off + i] = buf[i];
1558*4882a593Smuzhiyun
1559*4882a593Smuzhiyun off += transfer;
1560*4882a593Smuzhiyun count -= transfer;
1561*4882a593Smuzhiyun }
1562*4882a593Smuzhiyun
1563*4882a593Smuzhiyun ar->rng.cache_idx = 0;
1564*4882a593Smuzhiyun
1565*4882a593Smuzhiyun #undef RW
1566*4882a593Smuzhiyun #undef RB
1567*4882a593Smuzhiyun return 0;
1568*4882a593Smuzhiyun }
1569*4882a593Smuzhiyun
carl9170_rng_read(struct hwrng * rng,u32 * data)1570*4882a593Smuzhiyun static int carl9170_rng_read(struct hwrng *rng, u32 *data)
1571*4882a593Smuzhiyun {
1572*4882a593Smuzhiyun struct ar9170 *ar = (struct ar9170 *)rng->priv;
1573*4882a593Smuzhiyun int ret = -EIO;
1574*4882a593Smuzhiyun
1575*4882a593Smuzhiyun mutex_lock(&ar->mutex);
1576*4882a593Smuzhiyun if (ar->rng.cache_idx >= ARRAY_SIZE(ar->rng.cache)) {
1577*4882a593Smuzhiyun ret = carl9170_rng_get(ar);
1578*4882a593Smuzhiyun if (ret) {
1579*4882a593Smuzhiyun mutex_unlock(&ar->mutex);
1580*4882a593Smuzhiyun return ret;
1581*4882a593Smuzhiyun }
1582*4882a593Smuzhiyun }
1583*4882a593Smuzhiyun
1584*4882a593Smuzhiyun *data = ar->rng.cache[ar->rng.cache_idx++];
1585*4882a593Smuzhiyun mutex_unlock(&ar->mutex);
1586*4882a593Smuzhiyun
1587*4882a593Smuzhiyun return sizeof(u16);
1588*4882a593Smuzhiyun }
1589*4882a593Smuzhiyun
carl9170_unregister_hwrng(struct ar9170 * ar)1590*4882a593Smuzhiyun static void carl9170_unregister_hwrng(struct ar9170 *ar)
1591*4882a593Smuzhiyun {
1592*4882a593Smuzhiyun if (ar->rng.initialized) {
1593*4882a593Smuzhiyun hwrng_unregister(&ar->rng.rng);
1594*4882a593Smuzhiyun ar->rng.initialized = false;
1595*4882a593Smuzhiyun }
1596*4882a593Smuzhiyun }
1597*4882a593Smuzhiyun
carl9170_register_hwrng(struct ar9170 * ar)1598*4882a593Smuzhiyun static int carl9170_register_hwrng(struct ar9170 *ar)
1599*4882a593Smuzhiyun {
1600*4882a593Smuzhiyun int err;
1601*4882a593Smuzhiyun
1602*4882a593Smuzhiyun snprintf(ar->rng.name, ARRAY_SIZE(ar->rng.name),
1603*4882a593Smuzhiyun "%s_%s", KBUILD_MODNAME, wiphy_name(ar->hw->wiphy));
1604*4882a593Smuzhiyun ar->rng.rng.name = ar->rng.name;
1605*4882a593Smuzhiyun ar->rng.rng.data_read = carl9170_rng_read;
1606*4882a593Smuzhiyun ar->rng.rng.priv = (unsigned long)ar;
1607*4882a593Smuzhiyun
1608*4882a593Smuzhiyun if (WARN_ON(ar->rng.initialized))
1609*4882a593Smuzhiyun return -EALREADY;
1610*4882a593Smuzhiyun
1611*4882a593Smuzhiyun err = hwrng_register(&ar->rng.rng);
1612*4882a593Smuzhiyun if (err) {
1613*4882a593Smuzhiyun dev_err(&ar->udev->dev, "Failed to register the random "
1614*4882a593Smuzhiyun "number generator (%d)\n", err);
1615*4882a593Smuzhiyun return err;
1616*4882a593Smuzhiyun }
1617*4882a593Smuzhiyun
1618*4882a593Smuzhiyun ar->rng.initialized = true;
1619*4882a593Smuzhiyun
1620*4882a593Smuzhiyun err = carl9170_rng_get(ar);
1621*4882a593Smuzhiyun if (err) {
1622*4882a593Smuzhiyun carl9170_unregister_hwrng(ar);
1623*4882a593Smuzhiyun return err;
1624*4882a593Smuzhiyun }
1625*4882a593Smuzhiyun
1626*4882a593Smuzhiyun return 0;
1627*4882a593Smuzhiyun }
1628*4882a593Smuzhiyun #endif /* CONFIG_CARL9170_HWRNG */
1629*4882a593Smuzhiyun
carl9170_op_get_survey(struct ieee80211_hw * hw,int idx,struct survey_info * survey)1630*4882a593Smuzhiyun static int carl9170_op_get_survey(struct ieee80211_hw *hw, int idx,
1631*4882a593Smuzhiyun struct survey_info *survey)
1632*4882a593Smuzhiyun {
1633*4882a593Smuzhiyun struct ar9170 *ar = hw->priv;
1634*4882a593Smuzhiyun struct ieee80211_channel *chan;
1635*4882a593Smuzhiyun struct ieee80211_supported_band *band;
1636*4882a593Smuzhiyun int err, b, i;
1637*4882a593Smuzhiyun
1638*4882a593Smuzhiyun chan = ar->channel;
1639*4882a593Smuzhiyun if (!chan)
1640*4882a593Smuzhiyun return -ENODEV;
1641*4882a593Smuzhiyun
1642*4882a593Smuzhiyun if (idx == chan->hw_value) {
1643*4882a593Smuzhiyun mutex_lock(&ar->mutex);
1644*4882a593Smuzhiyun err = carl9170_update_survey(ar, false, true);
1645*4882a593Smuzhiyun mutex_unlock(&ar->mutex);
1646*4882a593Smuzhiyun if (err)
1647*4882a593Smuzhiyun return err;
1648*4882a593Smuzhiyun }
1649*4882a593Smuzhiyun
1650*4882a593Smuzhiyun for (b = 0; b < NUM_NL80211_BANDS; b++) {
1651*4882a593Smuzhiyun band = ar->hw->wiphy->bands[b];
1652*4882a593Smuzhiyun
1653*4882a593Smuzhiyun if (!band)
1654*4882a593Smuzhiyun continue;
1655*4882a593Smuzhiyun
1656*4882a593Smuzhiyun for (i = 0; i < band->n_channels; i++) {
1657*4882a593Smuzhiyun if (band->channels[i].hw_value == idx) {
1658*4882a593Smuzhiyun chan = &band->channels[i];
1659*4882a593Smuzhiyun goto found;
1660*4882a593Smuzhiyun }
1661*4882a593Smuzhiyun }
1662*4882a593Smuzhiyun }
1663*4882a593Smuzhiyun return -ENOENT;
1664*4882a593Smuzhiyun
1665*4882a593Smuzhiyun found:
1666*4882a593Smuzhiyun memcpy(survey, &ar->survey[idx], sizeof(*survey));
1667*4882a593Smuzhiyun
1668*4882a593Smuzhiyun survey->channel = chan;
1669*4882a593Smuzhiyun survey->filled = SURVEY_INFO_NOISE_DBM;
1670*4882a593Smuzhiyun
1671*4882a593Smuzhiyun if (ar->channel == chan)
1672*4882a593Smuzhiyun survey->filled |= SURVEY_INFO_IN_USE;
1673*4882a593Smuzhiyun
1674*4882a593Smuzhiyun if (ar->fw.hw_counters) {
1675*4882a593Smuzhiyun survey->filled |= SURVEY_INFO_TIME |
1676*4882a593Smuzhiyun SURVEY_INFO_TIME_BUSY |
1677*4882a593Smuzhiyun SURVEY_INFO_TIME_TX;
1678*4882a593Smuzhiyun }
1679*4882a593Smuzhiyun
1680*4882a593Smuzhiyun return 0;
1681*4882a593Smuzhiyun }
1682*4882a593Smuzhiyun
carl9170_op_flush(struct ieee80211_hw * hw,struct ieee80211_vif * vif,u32 queues,bool drop)1683*4882a593Smuzhiyun static void carl9170_op_flush(struct ieee80211_hw *hw,
1684*4882a593Smuzhiyun struct ieee80211_vif *vif,
1685*4882a593Smuzhiyun u32 queues, bool drop)
1686*4882a593Smuzhiyun {
1687*4882a593Smuzhiyun struct ar9170 *ar = hw->priv;
1688*4882a593Smuzhiyun unsigned int vid;
1689*4882a593Smuzhiyun
1690*4882a593Smuzhiyun mutex_lock(&ar->mutex);
1691*4882a593Smuzhiyun for_each_set_bit(vid, &ar->vif_bitmap, ar->fw.vif_num)
1692*4882a593Smuzhiyun carl9170_flush_cab(ar, vid);
1693*4882a593Smuzhiyun
1694*4882a593Smuzhiyun carl9170_flush(ar, drop);
1695*4882a593Smuzhiyun mutex_unlock(&ar->mutex);
1696*4882a593Smuzhiyun }
1697*4882a593Smuzhiyun
carl9170_op_get_stats(struct ieee80211_hw * hw,struct ieee80211_low_level_stats * stats)1698*4882a593Smuzhiyun static int carl9170_op_get_stats(struct ieee80211_hw *hw,
1699*4882a593Smuzhiyun struct ieee80211_low_level_stats *stats)
1700*4882a593Smuzhiyun {
1701*4882a593Smuzhiyun struct ar9170 *ar = hw->priv;
1702*4882a593Smuzhiyun
1703*4882a593Smuzhiyun memset(stats, 0, sizeof(*stats));
1704*4882a593Smuzhiyun stats->dot11ACKFailureCount = ar->tx_ack_failures;
1705*4882a593Smuzhiyun stats->dot11FCSErrorCount = ar->tx_fcs_errors;
1706*4882a593Smuzhiyun return 0;
1707*4882a593Smuzhiyun }
1708*4882a593Smuzhiyun
carl9170_op_sta_notify(struct ieee80211_hw * hw,struct ieee80211_vif * vif,enum sta_notify_cmd cmd,struct ieee80211_sta * sta)1709*4882a593Smuzhiyun static void carl9170_op_sta_notify(struct ieee80211_hw *hw,
1710*4882a593Smuzhiyun struct ieee80211_vif *vif,
1711*4882a593Smuzhiyun enum sta_notify_cmd cmd,
1712*4882a593Smuzhiyun struct ieee80211_sta *sta)
1713*4882a593Smuzhiyun {
1714*4882a593Smuzhiyun struct carl9170_sta_info *sta_info = (void *) sta->drv_priv;
1715*4882a593Smuzhiyun
1716*4882a593Smuzhiyun switch (cmd) {
1717*4882a593Smuzhiyun case STA_NOTIFY_SLEEP:
1718*4882a593Smuzhiyun sta_info->sleeping = true;
1719*4882a593Smuzhiyun if (atomic_read(&sta_info->pending_frames))
1720*4882a593Smuzhiyun ieee80211_sta_block_awake(hw, sta, true);
1721*4882a593Smuzhiyun break;
1722*4882a593Smuzhiyun
1723*4882a593Smuzhiyun case STA_NOTIFY_AWAKE:
1724*4882a593Smuzhiyun sta_info->sleeping = false;
1725*4882a593Smuzhiyun break;
1726*4882a593Smuzhiyun }
1727*4882a593Smuzhiyun }
1728*4882a593Smuzhiyun
carl9170_tx_frames_pending(struct ieee80211_hw * hw)1729*4882a593Smuzhiyun static bool carl9170_tx_frames_pending(struct ieee80211_hw *hw)
1730*4882a593Smuzhiyun {
1731*4882a593Smuzhiyun struct ar9170 *ar = hw->priv;
1732*4882a593Smuzhiyun
1733*4882a593Smuzhiyun return !!atomic_read(&ar->tx_total_queued);
1734*4882a593Smuzhiyun }
1735*4882a593Smuzhiyun
1736*4882a593Smuzhiyun static const struct ieee80211_ops carl9170_ops = {
1737*4882a593Smuzhiyun .start = carl9170_op_start,
1738*4882a593Smuzhiyun .stop = carl9170_op_stop,
1739*4882a593Smuzhiyun .tx = carl9170_op_tx,
1740*4882a593Smuzhiyun .flush = carl9170_op_flush,
1741*4882a593Smuzhiyun .add_interface = carl9170_op_add_interface,
1742*4882a593Smuzhiyun .remove_interface = carl9170_op_remove_interface,
1743*4882a593Smuzhiyun .config = carl9170_op_config,
1744*4882a593Smuzhiyun .prepare_multicast = carl9170_op_prepare_multicast,
1745*4882a593Smuzhiyun .configure_filter = carl9170_op_configure_filter,
1746*4882a593Smuzhiyun .conf_tx = carl9170_op_conf_tx,
1747*4882a593Smuzhiyun .bss_info_changed = carl9170_op_bss_info_changed,
1748*4882a593Smuzhiyun .get_tsf = carl9170_op_get_tsf,
1749*4882a593Smuzhiyun .set_key = carl9170_op_set_key,
1750*4882a593Smuzhiyun .sta_add = carl9170_op_sta_add,
1751*4882a593Smuzhiyun .sta_remove = carl9170_op_sta_remove,
1752*4882a593Smuzhiyun .sta_notify = carl9170_op_sta_notify,
1753*4882a593Smuzhiyun .get_survey = carl9170_op_get_survey,
1754*4882a593Smuzhiyun .get_stats = carl9170_op_get_stats,
1755*4882a593Smuzhiyun .ampdu_action = carl9170_op_ampdu_action,
1756*4882a593Smuzhiyun .tx_frames_pending = carl9170_tx_frames_pending,
1757*4882a593Smuzhiyun };
1758*4882a593Smuzhiyun
carl9170_alloc(size_t priv_size)1759*4882a593Smuzhiyun void *carl9170_alloc(size_t priv_size)
1760*4882a593Smuzhiyun {
1761*4882a593Smuzhiyun struct ieee80211_hw *hw;
1762*4882a593Smuzhiyun struct ar9170 *ar;
1763*4882a593Smuzhiyun struct sk_buff *skb;
1764*4882a593Smuzhiyun int i;
1765*4882a593Smuzhiyun
1766*4882a593Smuzhiyun /*
1767*4882a593Smuzhiyun * this buffer is used for rx stream reconstruction.
1768*4882a593Smuzhiyun * Under heavy load this device (or the transport layer?)
1769*4882a593Smuzhiyun * tends to split the streams into separate rx descriptors.
1770*4882a593Smuzhiyun */
1771*4882a593Smuzhiyun
1772*4882a593Smuzhiyun skb = __dev_alloc_skb(AR9170_RX_STREAM_MAX_SIZE, GFP_KERNEL);
1773*4882a593Smuzhiyun if (!skb)
1774*4882a593Smuzhiyun goto err_nomem;
1775*4882a593Smuzhiyun
1776*4882a593Smuzhiyun hw = ieee80211_alloc_hw(priv_size, &carl9170_ops);
1777*4882a593Smuzhiyun if (!hw)
1778*4882a593Smuzhiyun goto err_nomem;
1779*4882a593Smuzhiyun
1780*4882a593Smuzhiyun ar = hw->priv;
1781*4882a593Smuzhiyun ar->hw = hw;
1782*4882a593Smuzhiyun ar->rx_failover = skb;
1783*4882a593Smuzhiyun
1784*4882a593Smuzhiyun memset(&ar->rx_plcp, 0, sizeof(struct ar9170_rx_head));
1785*4882a593Smuzhiyun ar->rx_has_plcp = false;
1786*4882a593Smuzhiyun
1787*4882a593Smuzhiyun /*
1788*4882a593Smuzhiyun * Here's a hidden pitfall!
1789*4882a593Smuzhiyun *
1790*4882a593Smuzhiyun * All 4 AC queues work perfectly well under _legacy_ operation.
1791*4882a593Smuzhiyun * However as soon as aggregation is enabled, the traffic flow
1792*4882a593Smuzhiyun * gets very bumpy. Therefore we have to _switch_ to a
1793*4882a593Smuzhiyun * software AC with a single HW queue.
1794*4882a593Smuzhiyun */
1795*4882a593Smuzhiyun hw->queues = __AR9170_NUM_TXQ;
1796*4882a593Smuzhiyun
1797*4882a593Smuzhiyun mutex_init(&ar->mutex);
1798*4882a593Smuzhiyun spin_lock_init(&ar->beacon_lock);
1799*4882a593Smuzhiyun spin_lock_init(&ar->cmd_lock);
1800*4882a593Smuzhiyun spin_lock_init(&ar->tx_stats_lock);
1801*4882a593Smuzhiyun spin_lock_init(&ar->tx_ampdu_list_lock);
1802*4882a593Smuzhiyun spin_lock_init(&ar->mem_lock);
1803*4882a593Smuzhiyun spin_lock_init(&ar->state_lock);
1804*4882a593Smuzhiyun atomic_set(&ar->pending_restarts, 0);
1805*4882a593Smuzhiyun ar->vifs = 0;
1806*4882a593Smuzhiyun for (i = 0; i < ar->hw->queues; i++) {
1807*4882a593Smuzhiyun skb_queue_head_init(&ar->tx_status[i]);
1808*4882a593Smuzhiyun skb_queue_head_init(&ar->tx_pending[i]);
1809*4882a593Smuzhiyun
1810*4882a593Smuzhiyun INIT_LIST_HEAD(&ar->bar_list[i]);
1811*4882a593Smuzhiyun spin_lock_init(&ar->bar_list_lock[i]);
1812*4882a593Smuzhiyun }
1813*4882a593Smuzhiyun INIT_WORK(&ar->ps_work, carl9170_ps_work);
1814*4882a593Smuzhiyun INIT_WORK(&ar->ping_work, carl9170_ping_work);
1815*4882a593Smuzhiyun INIT_WORK(&ar->restart_work, carl9170_restart_work);
1816*4882a593Smuzhiyun INIT_WORK(&ar->ampdu_work, carl9170_ampdu_work);
1817*4882a593Smuzhiyun INIT_DELAYED_WORK(&ar->stat_work, carl9170_stat_work);
1818*4882a593Smuzhiyun INIT_DELAYED_WORK(&ar->tx_janitor, carl9170_tx_janitor);
1819*4882a593Smuzhiyun INIT_LIST_HEAD(&ar->tx_ampdu_list);
1820*4882a593Smuzhiyun rcu_assign_pointer(ar->tx_ampdu_iter,
1821*4882a593Smuzhiyun (struct carl9170_sta_tid *) &ar->tx_ampdu_list);
1822*4882a593Smuzhiyun
1823*4882a593Smuzhiyun bitmap_zero(&ar->vif_bitmap, ar->fw.vif_num);
1824*4882a593Smuzhiyun INIT_LIST_HEAD(&ar->vif_list);
1825*4882a593Smuzhiyun init_completion(&ar->tx_flush);
1826*4882a593Smuzhiyun
1827*4882a593Smuzhiyun /* firmware decides which modes we support */
1828*4882a593Smuzhiyun hw->wiphy->interface_modes = 0;
1829*4882a593Smuzhiyun
1830*4882a593Smuzhiyun ieee80211_hw_set(hw, RX_INCLUDES_FCS);
1831*4882a593Smuzhiyun ieee80211_hw_set(hw, MFP_CAPABLE);
1832*4882a593Smuzhiyun ieee80211_hw_set(hw, REPORTS_TX_ACK_STATUS);
1833*4882a593Smuzhiyun ieee80211_hw_set(hw, SUPPORTS_PS);
1834*4882a593Smuzhiyun ieee80211_hw_set(hw, PS_NULLFUNC_STACK);
1835*4882a593Smuzhiyun ieee80211_hw_set(hw, NEED_DTIM_BEFORE_ASSOC);
1836*4882a593Smuzhiyun ieee80211_hw_set(hw, SUPPORTS_RC_TABLE);
1837*4882a593Smuzhiyun ieee80211_hw_set(hw, SIGNAL_DBM);
1838*4882a593Smuzhiyun ieee80211_hw_set(hw, SUPPORTS_HT_CCK_RATES);
1839*4882a593Smuzhiyun
1840*4882a593Smuzhiyun if (!modparam_noht) {
1841*4882a593Smuzhiyun /*
1842*4882a593Smuzhiyun * see the comment above, why we allow the user
1843*4882a593Smuzhiyun * to disable HT by a module parameter.
1844*4882a593Smuzhiyun */
1845*4882a593Smuzhiyun ieee80211_hw_set(hw, AMPDU_AGGREGATION);
1846*4882a593Smuzhiyun }
1847*4882a593Smuzhiyun
1848*4882a593Smuzhiyun hw->extra_tx_headroom = sizeof(struct _carl9170_tx_superframe);
1849*4882a593Smuzhiyun hw->sta_data_size = sizeof(struct carl9170_sta_info);
1850*4882a593Smuzhiyun hw->vif_data_size = sizeof(struct carl9170_vif_info);
1851*4882a593Smuzhiyun
1852*4882a593Smuzhiyun hw->max_rates = CARL9170_TX_MAX_RATES;
1853*4882a593Smuzhiyun hw->max_rate_tries = CARL9170_TX_USER_RATE_TRIES;
1854*4882a593Smuzhiyun
1855*4882a593Smuzhiyun for (i = 0; i < ARRAY_SIZE(ar->noise); i++)
1856*4882a593Smuzhiyun ar->noise[i] = -95; /* ATH_DEFAULT_NOISE_FLOOR */
1857*4882a593Smuzhiyun
1858*4882a593Smuzhiyun wiphy_ext_feature_set(hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST);
1859*4882a593Smuzhiyun
1860*4882a593Smuzhiyun return ar;
1861*4882a593Smuzhiyun
1862*4882a593Smuzhiyun err_nomem:
1863*4882a593Smuzhiyun kfree_skb(skb);
1864*4882a593Smuzhiyun return ERR_PTR(-ENOMEM);
1865*4882a593Smuzhiyun }
1866*4882a593Smuzhiyun
carl9170_read_eeprom(struct ar9170 * ar)1867*4882a593Smuzhiyun static int carl9170_read_eeprom(struct ar9170 *ar)
1868*4882a593Smuzhiyun {
1869*4882a593Smuzhiyun #define RW 8 /* number of words to read at once */
1870*4882a593Smuzhiyun #define RB (sizeof(u32) * RW)
1871*4882a593Smuzhiyun u8 *eeprom = (void *)&ar->eeprom;
1872*4882a593Smuzhiyun __le32 offsets[RW];
1873*4882a593Smuzhiyun int i, j, err;
1874*4882a593Smuzhiyun
1875*4882a593Smuzhiyun BUILD_BUG_ON(sizeof(ar->eeprom) & 3);
1876*4882a593Smuzhiyun
1877*4882a593Smuzhiyun BUILD_BUG_ON(RB > CARL9170_MAX_CMD_LEN - 4);
1878*4882a593Smuzhiyun #ifndef __CHECKER__
1879*4882a593Smuzhiyun /* don't want to handle trailing remains */
1880*4882a593Smuzhiyun BUILD_BUG_ON(sizeof(ar->eeprom) % RB);
1881*4882a593Smuzhiyun #endif
1882*4882a593Smuzhiyun
1883*4882a593Smuzhiyun for (i = 0; i < sizeof(ar->eeprom) / RB; i++) {
1884*4882a593Smuzhiyun for (j = 0; j < RW; j++)
1885*4882a593Smuzhiyun offsets[j] = cpu_to_le32(AR9170_EEPROM_START +
1886*4882a593Smuzhiyun RB * i + 4 * j);
1887*4882a593Smuzhiyun
1888*4882a593Smuzhiyun err = carl9170_exec_cmd(ar, CARL9170_CMD_RREG,
1889*4882a593Smuzhiyun RB, (u8 *) &offsets,
1890*4882a593Smuzhiyun RB, eeprom + RB * i);
1891*4882a593Smuzhiyun if (err)
1892*4882a593Smuzhiyun return err;
1893*4882a593Smuzhiyun }
1894*4882a593Smuzhiyun
1895*4882a593Smuzhiyun #undef RW
1896*4882a593Smuzhiyun #undef RB
1897*4882a593Smuzhiyun return 0;
1898*4882a593Smuzhiyun }
1899*4882a593Smuzhiyun
carl9170_parse_eeprom(struct ar9170 * ar)1900*4882a593Smuzhiyun static int carl9170_parse_eeprom(struct ar9170 *ar)
1901*4882a593Smuzhiyun {
1902*4882a593Smuzhiyun struct ath_regulatory *regulatory = &ar->common.regulatory;
1903*4882a593Smuzhiyun unsigned int rx_streams, tx_streams, tx_params = 0;
1904*4882a593Smuzhiyun int bands = 0;
1905*4882a593Smuzhiyun int chans = 0;
1906*4882a593Smuzhiyun
1907*4882a593Smuzhiyun if (ar->eeprom.length == cpu_to_le16(0xffff))
1908*4882a593Smuzhiyun return -ENODATA;
1909*4882a593Smuzhiyun
1910*4882a593Smuzhiyun rx_streams = hweight8(ar->eeprom.rx_mask);
1911*4882a593Smuzhiyun tx_streams = hweight8(ar->eeprom.tx_mask);
1912*4882a593Smuzhiyun
1913*4882a593Smuzhiyun if (rx_streams != tx_streams) {
1914*4882a593Smuzhiyun tx_params = IEEE80211_HT_MCS_TX_RX_DIFF;
1915*4882a593Smuzhiyun
1916*4882a593Smuzhiyun WARN_ON(!(tx_streams >= 1 && tx_streams <=
1917*4882a593Smuzhiyun IEEE80211_HT_MCS_TX_MAX_STREAMS));
1918*4882a593Smuzhiyun
1919*4882a593Smuzhiyun tx_params |= (tx_streams - 1) <<
1920*4882a593Smuzhiyun IEEE80211_HT_MCS_TX_MAX_STREAMS_SHIFT;
1921*4882a593Smuzhiyun
1922*4882a593Smuzhiyun carl9170_band_2GHz.ht_cap.mcs.tx_params |= tx_params;
1923*4882a593Smuzhiyun carl9170_band_5GHz.ht_cap.mcs.tx_params |= tx_params;
1924*4882a593Smuzhiyun }
1925*4882a593Smuzhiyun
1926*4882a593Smuzhiyun if (ar->eeprom.operating_flags & AR9170_OPFLAG_2GHZ) {
1927*4882a593Smuzhiyun ar->hw->wiphy->bands[NL80211_BAND_2GHZ] =
1928*4882a593Smuzhiyun &carl9170_band_2GHz;
1929*4882a593Smuzhiyun chans += carl9170_band_2GHz.n_channels;
1930*4882a593Smuzhiyun bands++;
1931*4882a593Smuzhiyun }
1932*4882a593Smuzhiyun if (ar->eeprom.operating_flags & AR9170_OPFLAG_5GHZ) {
1933*4882a593Smuzhiyun ar->hw->wiphy->bands[NL80211_BAND_5GHZ] =
1934*4882a593Smuzhiyun &carl9170_band_5GHz;
1935*4882a593Smuzhiyun chans += carl9170_band_5GHz.n_channels;
1936*4882a593Smuzhiyun bands++;
1937*4882a593Smuzhiyun }
1938*4882a593Smuzhiyun
1939*4882a593Smuzhiyun if (!bands)
1940*4882a593Smuzhiyun return -EINVAL;
1941*4882a593Smuzhiyun
1942*4882a593Smuzhiyun ar->survey = kcalloc(chans, sizeof(struct survey_info), GFP_KERNEL);
1943*4882a593Smuzhiyun if (!ar->survey)
1944*4882a593Smuzhiyun return -ENOMEM;
1945*4882a593Smuzhiyun ar->num_channels = chans;
1946*4882a593Smuzhiyun
1947*4882a593Smuzhiyun regulatory->current_rd = le16_to_cpu(ar->eeprom.reg_domain[0]);
1948*4882a593Smuzhiyun
1949*4882a593Smuzhiyun /* second part of wiphy init */
1950*4882a593Smuzhiyun SET_IEEE80211_PERM_ADDR(ar->hw, ar->eeprom.mac_address);
1951*4882a593Smuzhiyun
1952*4882a593Smuzhiyun return 0;
1953*4882a593Smuzhiyun }
1954*4882a593Smuzhiyun
carl9170_reg_notifier(struct wiphy * wiphy,struct regulatory_request * request)1955*4882a593Smuzhiyun static void carl9170_reg_notifier(struct wiphy *wiphy,
1956*4882a593Smuzhiyun struct regulatory_request *request)
1957*4882a593Smuzhiyun {
1958*4882a593Smuzhiyun struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
1959*4882a593Smuzhiyun struct ar9170 *ar = hw->priv;
1960*4882a593Smuzhiyun
1961*4882a593Smuzhiyun ath_reg_notifier_apply(wiphy, request, &ar->common.regulatory);
1962*4882a593Smuzhiyun }
1963*4882a593Smuzhiyun
carl9170_register(struct ar9170 * ar)1964*4882a593Smuzhiyun int carl9170_register(struct ar9170 *ar)
1965*4882a593Smuzhiyun {
1966*4882a593Smuzhiyun struct ath_regulatory *regulatory = &ar->common.regulatory;
1967*4882a593Smuzhiyun int err = 0, i;
1968*4882a593Smuzhiyun
1969*4882a593Smuzhiyun if (WARN_ON(ar->mem_bitmap))
1970*4882a593Smuzhiyun return -EINVAL;
1971*4882a593Smuzhiyun
1972*4882a593Smuzhiyun ar->mem_bitmap = kcalloc(roundup(ar->fw.mem_blocks, BITS_PER_LONG),
1973*4882a593Smuzhiyun sizeof(unsigned long),
1974*4882a593Smuzhiyun GFP_KERNEL);
1975*4882a593Smuzhiyun
1976*4882a593Smuzhiyun if (!ar->mem_bitmap)
1977*4882a593Smuzhiyun return -ENOMEM;
1978*4882a593Smuzhiyun
1979*4882a593Smuzhiyun /* try to read EEPROM, init MAC addr */
1980*4882a593Smuzhiyun err = carl9170_read_eeprom(ar);
1981*4882a593Smuzhiyun if (err)
1982*4882a593Smuzhiyun return err;
1983*4882a593Smuzhiyun
1984*4882a593Smuzhiyun err = carl9170_parse_eeprom(ar);
1985*4882a593Smuzhiyun if (err)
1986*4882a593Smuzhiyun return err;
1987*4882a593Smuzhiyun
1988*4882a593Smuzhiyun err = ath_regd_init(regulatory, ar->hw->wiphy,
1989*4882a593Smuzhiyun carl9170_reg_notifier);
1990*4882a593Smuzhiyun if (err)
1991*4882a593Smuzhiyun return err;
1992*4882a593Smuzhiyun
1993*4882a593Smuzhiyun if (modparam_noht) {
1994*4882a593Smuzhiyun carl9170_band_2GHz.ht_cap.ht_supported = false;
1995*4882a593Smuzhiyun carl9170_band_5GHz.ht_cap.ht_supported = false;
1996*4882a593Smuzhiyun }
1997*4882a593Smuzhiyun
1998*4882a593Smuzhiyun for (i = 0; i < ar->fw.vif_num; i++) {
1999*4882a593Smuzhiyun ar->vif_priv[i].id = i;
2000*4882a593Smuzhiyun ar->vif_priv[i].vif = NULL;
2001*4882a593Smuzhiyun }
2002*4882a593Smuzhiyun
2003*4882a593Smuzhiyun err = ieee80211_register_hw(ar->hw);
2004*4882a593Smuzhiyun if (err)
2005*4882a593Smuzhiyun return err;
2006*4882a593Smuzhiyun
2007*4882a593Smuzhiyun /* mac80211 interface is now registered */
2008*4882a593Smuzhiyun ar->registered = true;
2009*4882a593Smuzhiyun
2010*4882a593Smuzhiyun if (!ath_is_world_regd(regulatory))
2011*4882a593Smuzhiyun regulatory_hint(ar->hw->wiphy, regulatory->alpha2);
2012*4882a593Smuzhiyun
2013*4882a593Smuzhiyun #ifdef CONFIG_CARL9170_DEBUGFS
2014*4882a593Smuzhiyun carl9170_debugfs_register(ar);
2015*4882a593Smuzhiyun #endif /* CONFIG_CARL9170_DEBUGFS */
2016*4882a593Smuzhiyun
2017*4882a593Smuzhiyun err = carl9170_led_init(ar);
2018*4882a593Smuzhiyun if (err)
2019*4882a593Smuzhiyun goto err_unreg;
2020*4882a593Smuzhiyun
2021*4882a593Smuzhiyun #ifdef CONFIG_CARL9170_LEDS
2022*4882a593Smuzhiyun err = carl9170_led_register(ar);
2023*4882a593Smuzhiyun if (err)
2024*4882a593Smuzhiyun goto err_unreg;
2025*4882a593Smuzhiyun #endif /* CONFIG_CARL9170_LEDS */
2026*4882a593Smuzhiyun
2027*4882a593Smuzhiyun #ifdef CONFIG_CARL9170_WPC
2028*4882a593Smuzhiyun err = carl9170_register_wps_button(ar);
2029*4882a593Smuzhiyun if (err)
2030*4882a593Smuzhiyun goto err_unreg;
2031*4882a593Smuzhiyun #endif /* CONFIG_CARL9170_WPC */
2032*4882a593Smuzhiyun
2033*4882a593Smuzhiyun #ifdef CONFIG_CARL9170_HWRNG
2034*4882a593Smuzhiyun err = carl9170_register_hwrng(ar);
2035*4882a593Smuzhiyun if (err)
2036*4882a593Smuzhiyun goto err_unreg;
2037*4882a593Smuzhiyun #endif /* CONFIG_CARL9170_HWRNG */
2038*4882a593Smuzhiyun
2039*4882a593Smuzhiyun dev_info(&ar->udev->dev, "Atheros AR9170 is registered as '%s'\n",
2040*4882a593Smuzhiyun wiphy_name(ar->hw->wiphy));
2041*4882a593Smuzhiyun
2042*4882a593Smuzhiyun return 0;
2043*4882a593Smuzhiyun
2044*4882a593Smuzhiyun err_unreg:
2045*4882a593Smuzhiyun carl9170_unregister(ar);
2046*4882a593Smuzhiyun return err;
2047*4882a593Smuzhiyun }
2048*4882a593Smuzhiyun
carl9170_unregister(struct ar9170 * ar)2049*4882a593Smuzhiyun void carl9170_unregister(struct ar9170 *ar)
2050*4882a593Smuzhiyun {
2051*4882a593Smuzhiyun if (!ar->registered)
2052*4882a593Smuzhiyun return;
2053*4882a593Smuzhiyun
2054*4882a593Smuzhiyun ar->registered = false;
2055*4882a593Smuzhiyun
2056*4882a593Smuzhiyun #ifdef CONFIG_CARL9170_LEDS
2057*4882a593Smuzhiyun carl9170_led_unregister(ar);
2058*4882a593Smuzhiyun #endif /* CONFIG_CARL9170_LEDS */
2059*4882a593Smuzhiyun
2060*4882a593Smuzhiyun #ifdef CONFIG_CARL9170_DEBUGFS
2061*4882a593Smuzhiyun carl9170_debugfs_unregister(ar);
2062*4882a593Smuzhiyun #endif /* CONFIG_CARL9170_DEBUGFS */
2063*4882a593Smuzhiyun
2064*4882a593Smuzhiyun #ifdef CONFIG_CARL9170_WPC
2065*4882a593Smuzhiyun if (ar->wps.pbc) {
2066*4882a593Smuzhiyun input_unregister_device(ar->wps.pbc);
2067*4882a593Smuzhiyun ar->wps.pbc = NULL;
2068*4882a593Smuzhiyun }
2069*4882a593Smuzhiyun #endif /* CONFIG_CARL9170_WPC */
2070*4882a593Smuzhiyun
2071*4882a593Smuzhiyun #ifdef CONFIG_CARL9170_HWRNG
2072*4882a593Smuzhiyun carl9170_unregister_hwrng(ar);
2073*4882a593Smuzhiyun #endif /* CONFIG_CARL9170_HWRNG */
2074*4882a593Smuzhiyun
2075*4882a593Smuzhiyun carl9170_cancel_worker(ar);
2076*4882a593Smuzhiyun cancel_work_sync(&ar->restart_work);
2077*4882a593Smuzhiyun
2078*4882a593Smuzhiyun ieee80211_unregister_hw(ar->hw);
2079*4882a593Smuzhiyun }
2080*4882a593Smuzhiyun
carl9170_free(struct ar9170 * ar)2081*4882a593Smuzhiyun void carl9170_free(struct ar9170 *ar)
2082*4882a593Smuzhiyun {
2083*4882a593Smuzhiyun WARN_ON(ar->registered);
2084*4882a593Smuzhiyun WARN_ON(IS_INITIALIZED(ar));
2085*4882a593Smuzhiyun
2086*4882a593Smuzhiyun kfree_skb(ar->rx_failover);
2087*4882a593Smuzhiyun ar->rx_failover = NULL;
2088*4882a593Smuzhiyun
2089*4882a593Smuzhiyun kfree(ar->mem_bitmap);
2090*4882a593Smuzhiyun ar->mem_bitmap = NULL;
2091*4882a593Smuzhiyun
2092*4882a593Smuzhiyun kfree(ar->survey);
2093*4882a593Smuzhiyun ar->survey = NULL;
2094*4882a593Smuzhiyun
2095*4882a593Smuzhiyun mutex_destroy(&ar->mutex);
2096*4882a593Smuzhiyun
2097*4882a593Smuzhiyun ieee80211_free_hw(ar->hw);
2098*4882a593Smuzhiyun }
2099