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