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