1c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/* 2c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Copyright (c) 2004-2008 Reyk Floeter <reyk@openbsd.org> 3c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Copyright (c) 2006-2008 Nick Kossifidis <mickflemm@gmail.com> 4c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Copyright (c) 2007-2008 Matthew W. S. Bell <mentor@madwifi.org> 5c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Copyright (c) 2007-2008 Luis Rodriguez <mcgrof@winlab.rutgers.edu> 6c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Copyright (c) 2007-2008 Pavel Roskin <proski@gnu.org> 7c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Copyright (c) 2007-2008 Jiri Slaby <jirislaby@gmail.com> 8c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 9c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Permission to use, copy, modify, and distribute this software for any 10c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * purpose with or without fee is hereby granted, provided that the above 11c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * copyright notice and this permission notice appear in all copies. 12c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 13c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 14c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 15c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 16c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 17c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 18c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 19c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 20c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 21c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 22c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 23c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/*********************************\ 24c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis* Protocol Control Unit Functions * 25c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis\*********************************/ 26c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 27bcd8f54a84ce99ade91c250a9bc850a9fd3389c1Luis R. Rodriguez#include <asm/unaligned.h> 28bcd8f54a84ce99ade91c250a9bc850a9fd3389c1Luis R. Rodriguez 29c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis#include "ath5k.h" 30c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis#include "reg.h" 31c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis#include "debug.h" 32c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 33c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis/** 34c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * DOC: Protocol Control Unit (PCU) functions 35c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * 36c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * Protocol control unit is responsible to maintain various protocol 37c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * properties before a frame is send and after a frame is received to/from 38c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * baseband. To be more specific, PCU handles: 39c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * 40c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * - Buffering of RX and TX frames (after QCU/DCUs) 41c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * 42c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * - Encrypting and decrypting (using the built-in engine) 43c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * 44c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * - Generating ACKs, RTS/CTS frames 45c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * 46c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * - Maintaining TSF 47c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * 48c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * - FCS 49c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * 50c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * - Updating beacon data (with TSF etc) 51c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * 52c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * - Generating virtual CCA 53c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * 54c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * - RX/Multicast filtering 55c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * 56c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * - BSSID filtering 57c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * 58c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * - Various statistics 59c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * 60c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * -Different operating modes: AP, STA, IBSS 61c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * 62c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * Note: Most of these functions can be tweaked/bypassed so you can do 63c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * them on sw above for debugging or research. For more infos check out PCU 64c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * registers on reg.h. 65c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis */ 66c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis 67c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis/** 68c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * DOC: ACK rates 69c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * 706a2a0e738225fc9ec063f84b79f0adf5c0ed176cPavel Roskin * AR5212+ can use higher rates for ack transmission 7161cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis * based on current tx rate instead of the base rate. 7261cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis * It does this to better utilize channel usage. 73c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * There is a mapping between G rates (that cover both 7461cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis * CCK and OFDM) and ack rates that we use when setting 7561cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis * rate -> duration table. This mapping is hw-based so 7661cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis * don't change anything. 7761cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis * 7861cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis * To enable this functionality we must set 7961cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis * ah->ah_ack_bitrate_high to true else base rate is 8061cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis * used (1Mb for CCK, 6Mb for OFDM). 8161cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis */ 8261cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidisstatic const unsigned int ack_rates_high[] = 8361cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis/* Tx -> ACK */ 8461cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis/* 1Mb -> 1Mb */ { 0, 8561cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis/* 2MB -> 2Mb */ 1, 8661cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis/* 5.5Mb -> 2Mb */ 1, 8761cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis/* 11Mb -> 2Mb */ 1, 8861cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis/* 6Mb -> 6Mb */ 4, 8961cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis/* 9Mb -> 6Mb */ 4, 9061cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis/* 12Mb -> 12Mb */ 6, 9161cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis/* 18Mb -> 12Mb */ 6, 9261cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis/* 24Mb -> 24Mb */ 8, 9361cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis/* 36Mb -> 24Mb */ 8, 9461cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis/* 48Mb -> 24Mb */ 8, 9561cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis/* 54Mb -> 24Mb */ 8 }; 9661cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis 97c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/*******************\ 989320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis* Helper functions * 99c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis\*******************/ 100c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 101c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/** 102c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_get_frame_duration() - Get tx time of a frame 10361cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis * @ah: The &struct ath5k_hw 10461cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis * @len: Frame's length in bytes 10561cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis * @rate: The @struct ieee80211_rate 106c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * @shortpre: Indicate short preample 10761cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis * 10861cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis * Calculate tx duration of a frame given it's rate and length 10961cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis * It extends ieee80211_generic_frame_duration for non standard 11061cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis * bwmodes. 11161cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis */ 112c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisint 1134ee73f338a528f44fd90496adfbfd9c119401850Michal Kaziorath5k_hw_get_frame_duration(struct ath5k_hw *ah, enum ieee80211_band band, 114a27049e2c926bcf68360532a5ae66e408296ae85Felix Fietkau int len, struct ieee80211_rate *rate, bool shortpre) 11561cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis{ 11661cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis int sifs, preamble, plcp_bits, sym_time; 11761cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis int bitrate, bits, symbols, symbol_bits; 11861cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis int dur; 11961cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis 12061cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis /* Fallback */ 12161cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis if (!ah->ah_bwmode) { 122e0d687bd9df218ba3d97aac15919d30816d72dcbPavel Roskin __le16 raw_dur = ieee80211_generic_frame_duration(ah->hw, 1234ee73f338a528f44fd90496adfbfd9c119401850Michal Kazior NULL, band, len, rate); 124a27049e2c926bcf68360532a5ae66e408296ae85Felix Fietkau 125a27049e2c926bcf68360532a5ae66e408296ae85Felix Fietkau /* subtract difference between long and short preamble */ 126a27049e2c926bcf68360532a5ae66e408296ae85Felix Fietkau dur = le16_to_cpu(raw_dur); 127a27049e2c926bcf68360532a5ae66e408296ae85Felix Fietkau if (shortpre) 128a27049e2c926bcf68360532a5ae66e408296ae85Felix Fietkau dur -= 96; 129a27049e2c926bcf68360532a5ae66e408296ae85Felix Fietkau 130a27049e2c926bcf68360532a5ae66e408296ae85Felix Fietkau return dur; 13161cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis } 13261cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis 13361cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis bitrate = rate->bitrate; 13461cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis preamble = AR5K_INIT_OFDM_PREAMPLE_TIME; 13561cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis plcp_bits = AR5K_INIT_OFDM_PLCP_BITS; 13661cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis sym_time = AR5K_INIT_OFDM_SYMBOL_TIME; 13761cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis 13861cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis switch (ah->ah_bwmode) { 13961cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis case AR5K_BWMODE_40MHZ: 14061cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis sifs = AR5K_INIT_SIFS_TURBO; 14161cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis preamble = AR5K_INIT_OFDM_PREAMBLE_TIME_MIN; 14261cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis break; 14361cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis case AR5K_BWMODE_10MHZ: 14461cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis sifs = AR5K_INIT_SIFS_HALF_RATE; 14561cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis preamble *= 2; 14661cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis sym_time *= 2; 1476a09ae95ed248d6d946407bb1f955e5f2624663dSimon Wunderlich bitrate = DIV_ROUND_UP(bitrate, 2); 14861cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis break; 14961cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis case AR5K_BWMODE_5MHZ: 15061cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis sifs = AR5K_INIT_SIFS_QUARTER_RATE; 15161cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis preamble *= 4; 15261cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis sym_time *= 4; 1536a09ae95ed248d6d946407bb1f955e5f2624663dSimon Wunderlich bitrate = DIV_ROUND_UP(bitrate, 4); 15461cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis break; 15561cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis default: 15661cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis sifs = AR5K_INIT_SIFS_DEFAULT_BG; 15761cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis break; 15861cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis } 15961cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis 16061cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis bits = plcp_bits + (len << 3); 16161cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis /* Bit rate is in 100Kbits */ 16261cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis symbol_bits = bitrate * sym_time; 16361cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis symbols = DIV_ROUND_UP(bits * 10, symbol_bits); 16461cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis 16561cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis dur = sifs + preamble + (sym_time * symbols); 16661cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis 16761cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis return dur; 16861cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis} 16961cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis 17061cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis/** 171c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_get_default_slottime() - Get the default slot time for current mode 172c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @ah: The &struct ath5k_hw 173c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 174c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisunsigned int 175c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_get_default_slottime(struct ath5k_hw *ah) 176c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 1779320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis struct ieee80211_channel *channel = ah->ah_current_channel; 1783017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis unsigned int slot_time; 179c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 1803017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis switch (ah->ah_bwmode) { 1813017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis case AR5K_BWMODE_40MHZ: 1823017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis slot_time = AR5K_INIT_SLOT_TIME_TURBO; 1833017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis break; 1843017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis case AR5K_BWMODE_10MHZ: 1853017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis slot_time = AR5K_INIT_SLOT_TIME_HALF_RATE; 1863017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis break; 1873017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis case AR5K_BWMODE_5MHZ: 1883017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis slot_time = AR5K_INIT_SLOT_TIME_QUARTER_RATE; 1893017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis break; 1903017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis case AR5K_BWMODE_DEFAULT: 1913017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis default: 192b1ad1b6febb7772583c98d9a879fbbdb82a726a7Felix Fietkau slot_time = AR5K_INIT_SLOT_TIME_DEFAULT; 19332c254645f90a5a5486788c0deb30531fdb609c2Pavel Roskin if ((channel->hw_value == AR5K_MODE_11B) && !ah->ah_short_slot) 1943017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis slot_time = AR5K_INIT_SLOT_TIME_B; 1953017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis break; 1963017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis } 197c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 1983017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis return slot_time; 1999320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis} 200c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 2019320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis/** 202c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_get_default_sifs() - Get the default SIFS for current mode 2039320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * @ah: The &struct ath5k_hw 2049320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis */ 205c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisunsigned int 206c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_get_default_sifs(struct ath5k_hw *ah) 2079320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis{ 2089320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis struct ieee80211_channel *channel = ah->ah_current_channel; 2093017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis unsigned int sifs; 210c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 2113017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis switch (ah->ah_bwmode) { 2123017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis case AR5K_BWMODE_40MHZ: 2133017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis sifs = AR5K_INIT_SIFS_TURBO; 2143017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis break; 2153017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis case AR5K_BWMODE_10MHZ: 2163017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis sifs = AR5K_INIT_SIFS_HALF_RATE; 2173017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis break; 2183017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis case AR5K_BWMODE_5MHZ: 2193017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis sifs = AR5K_INIT_SIFS_QUARTER_RATE; 2203017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis break; 2213017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis case AR5K_BWMODE_DEFAULT: 2223017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis sifs = AR5K_INIT_SIFS_DEFAULT_BG; 2233017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis default: 22432c254645f90a5a5486788c0deb30531fdb609c2Pavel Roskin if (channel->band == IEEE80211_BAND_5GHZ) 2253017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis sifs = AR5K_INIT_SIFS_DEFAULT_A; 2263017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis break; 2273017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis } 228c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 2293017fcab416d8d1ee48ca16aa9a3062f600dab8eNick Kossifidis return sifs; 230c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 231c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 232c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/** 233c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_update_mib_counters() - Update MIB counters (mac layer statistics) 234c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @ah: The &struct ath5k_hw 235c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 236495391d715a310a7cbf622850e372d40ac86ef6eBruno Randolf * Reads MIB counters from PCU and updates sw statistics. Is called after a 237495391d715a310a7cbf622850e372d40ac86ef6eBruno Randolf * MIB interrupt, because one of these counters might have reached their maximum 238495391d715a310a7cbf622850e372d40ac86ef6eBruno Randolf * and triggered the MIB interrupt, to let us read and clear the counter. 239495391d715a310a7cbf622850e372d40ac86ef6eBruno Randolf * 240c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * NOTE: Is called in interrupt context! 241c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 242c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisvoid 243c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_update_mib_counters(struct ath5k_hw *ah) 244c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 245e0d687bd9df218ba3d97aac15919d30816d72dcbPavel Roskin struct ath5k_statistics *stats = &ah->stats; 246c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 247c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* Read-And-Clear */ 248495391d715a310a7cbf622850e372d40ac86ef6eBruno Randolf stats->ack_fail += ath5k_hw_reg_read(ah, AR5K_ACK_FAIL); 249495391d715a310a7cbf622850e372d40ac86ef6eBruno Randolf stats->rts_fail += ath5k_hw_reg_read(ah, AR5K_RTS_FAIL); 250495391d715a310a7cbf622850e372d40ac86ef6eBruno Randolf stats->rts_ok += ath5k_hw_reg_read(ah, AR5K_RTS_OK); 251495391d715a310a7cbf622850e372d40ac86ef6eBruno Randolf stats->fcs_error += ath5k_hw_reg_read(ah, AR5K_FCS_FAIL); 252495391d715a310a7cbf622850e372d40ac86ef6eBruno Randolf stats->beacons += ath5k_hw_reg_read(ah, AR5K_BEACON_CNT); 253c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 254c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 255c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 256c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/******************\ 257c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis* ACK/CTS Timeouts * 258c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis\******************/ 259c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 2609320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis/** 261c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_write_rate_duration() - Fill rate code to duration table 262c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * @ah: The &struct ath5k_hw 2639320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * 2649320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * Write the rate code to duration table upon hw reset. This is a helper for 26561cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis * ath5k_hw_pcu_init(). It seems all this is doing is setting an ACK timeout on 2669320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * the hardware, based on current mode, for each rate. The rates which are 2679320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * capable of short preamble (802.11b rates 2Mbps, 5.5Mbps, and 11Mbps) have 2689320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * different rate code so we write their value twice (one for long preamble 2699320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * and one for short). 2709320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * 2719320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * Note: Band doesn't matter here, if we set the values for OFDM it works 2729320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * on both a and g modes. So all we have to do is set values for all g rates 27361cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis * that include all OFDM and CCK rates. 27461cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis * 2759320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis */ 276c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisstatic inline void 277c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_write_rate_duration(struct ath5k_hw *ah) 2789320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis{ 2799320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis struct ieee80211_rate *rate; 2809320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis unsigned int i; 28161cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis /* 802.11g covers both OFDM and CCK */ 28261cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis u8 band = IEEE80211_BAND_2GHZ; 2839320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 2849320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis /* Write rate duration table */ 285e0d687bd9df218ba3d97aac15919d30816d72dcbPavel Roskin for (i = 0; i < ah->sbands[band].n_bitrates; i++) { 2869320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis u32 reg; 2879320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis u16 tx_time; 2889320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 28961cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis if (ah->ah_ack_bitrate_high) 290e0d687bd9df218ba3d97aac15919d30816d72dcbPavel Roskin rate = &ah->sbands[band].bitrates[ack_rates_high[i]]; 29161cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis /* CCK -> 1Mb */ 29261cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis else if (i < 4) 293e0d687bd9df218ba3d97aac15919d30816d72dcbPavel Roskin rate = &ah->sbands[band].bitrates[0]; 29461cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis /* OFDM -> 6Mb */ 29561cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis else 296e0d687bd9df218ba3d97aac15919d30816d72dcbPavel Roskin rate = &ah->sbands[band].bitrates[4]; 2979320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 2989320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis /* Set ACK timeout */ 2999320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis reg = AR5K_RATE_DUR(rate->hw_value); 3009320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 3019320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis /* An ACK frame consists of 10 bytes. If you add the FCS, 3029320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * which ieee80211_generic_frame_duration() adds, 3039320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * its 14 bytes. Note we use the control rate and not the 3049320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * actual rate for this rate. See mac80211 tx.c 3059320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * ieee80211_duration() for a brief description of 3069320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * what rate we should choose to TX ACKs. */ 3074ee73f338a528f44fd90496adfbfd9c119401850Michal Kazior tx_time = ath5k_hw_get_frame_duration(ah, band, 10, 3084ee73f338a528f44fd90496adfbfd9c119401850Michal Kazior rate, false); 30961cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis 3109320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis ath5k_hw_reg_write(ah, tx_time, reg); 3119320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 3129320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis if (!(rate->flags & IEEE80211_RATE_SHORT_PREAMBLE)) 3139320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis continue; 3149320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 3154ee73f338a528f44fd90496adfbfd9c119401850Michal Kazior tx_time = ath5k_hw_get_frame_duration(ah, band, 10, rate, true); 3169320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis ath5k_hw_reg_write(ah, tx_time, 3179320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis reg + (AR5K_SET_SHORT_PREAMBLE << 2)); 3189320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis } 3199320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis} 3209320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 321c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/** 322c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_set_ack_timeout() - Set ACK timeout on PCU 323c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @ah: The &struct ath5k_hw 324c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @timeout: Timeout in usec 325c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 326c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisstatic int 327c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_set_ack_timeout(struct ath5k_hw *ah, unsigned int timeout) 328c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 3293578e6ebb305e6bf7519f6e86741772892f4d51aLukáš Turek if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_ACK)) 3303578e6ebb305e6bf7519f6e86741772892f4d51aLukáš Turek <= timeout) 331c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return -EINVAL; 332c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 333c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_ACK, 3343578e6ebb305e6bf7519f6e86741772892f4d51aLukáš Turek ath5k_hw_htoclock(ah, timeout)); 335c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 336c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return 0; 337c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 338c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 339c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/** 340c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_set_cts_timeout() - Set CTS timeout on PCU 341c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @ah: The &struct ath5k_hw 342c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @timeout: Timeout in usec 343c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 344c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisstatic int 345c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_set_cts_timeout(struct ath5k_hw *ah, unsigned int timeout) 346c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 3473578e6ebb305e6bf7519f6e86741772892f4d51aLukáš Turek if (ath5k_hw_clocktoh(ah, AR5K_REG_MS(0xffffffff, AR5K_TIME_OUT_CTS)) 3483578e6ebb305e6bf7519f6e86741772892f4d51aLukáš Turek <= timeout) 349c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return -EINVAL; 350c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 351c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis AR5K_REG_WRITE_BITS(ah, AR5K_TIME_OUT, AR5K_TIME_OUT_CTS, 3523578e6ebb305e6bf7519f6e86741772892f4d51aLukáš Turek ath5k_hw_htoclock(ah, timeout)); 353c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 354c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return 0; 355c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 356c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 3576e08d228b6d8e93d7b25b3573c6da7da179c2ae1Lukáš Turek 3589320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis/*******************\ 3599320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis* RX filter Control * 3609320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis\*******************/ 3616e08d228b6d8e93d7b25b3573c6da7da179c2ae1Lukáš Turek 3626e08d228b6d8e93d7b25b3573c6da7da179c2ae1Lukáš Turek/** 363c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_set_lladdr() - Set station id 364c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @ah: The &struct ath5k_hw 365c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * @mac: The card's mac address (array of octets) 366c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 367c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Set station id on hw using the provided mac address 368c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 369c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisint 370c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_set_lladdr(struct ath5k_hw *ah, const u8 *mac) 371c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 372954fecea5d1df4d1dc7bf9a822a2fad308e8588eLuis R. Rodriguez struct ath_common *common = ath5k_hw_common(ah); 373c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis u32 low_id, high_id; 374f6bac3ea5990653765700b2c3778b08782abebe5Bob Copeland u32 pcu_reg; 375c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 376c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* Set new station ID */ 377954fecea5d1df4d1dc7bf9a822a2fad308e8588eLuis R. Rodriguez memcpy(common->macaddr, mac, ETH_ALEN); 378c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 379f6bac3ea5990653765700b2c3778b08782abebe5Bob Copeland pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; 380f6bac3ea5990653765700b2c3778b08782abebe5Bob Copeland 381bcd8f54a84ce99ade91c250a9bc850a9fd3389c1Luis R. Rodriguez low_id = get_unaligned_le32(mac); 382bcd8f54a84ce99ade91c250a9bc850a9fd3389c1Luis R. Rodriguez high_id = get_unaligned_le16(mac + 4); 383c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 384c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); 385f6bac3ea5990653765700b2c3778b08782abebe5Bob Copeland ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); 386c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 387c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return 0; 388c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 389c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 390c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/** 391c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_set_bssid() - Set current BSSID on hw 392c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @ah: The &struct ath5k_hw 393c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 394418de6d955fa1da0cb4332661a31d21f57e954abNick Kossifidis * Sets the current BSSID and BSSID mask we have from the 395418de6d955fa1da0cb4332661a31d21f57e954abNick Kossifidis * common struct into the hardware 396c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 397c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisvoid 398c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_set_bssid(struct ath5k_hw *ah) 399c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 400954fecea5d1df4d1dc7bf9a822a2fad308e8588eLuis R. Rodriguez struct ath_common *common = ath5k_hw_common(ah); 401c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis u16 tim_offset = 0; 402c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 403c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* 404418de6d955fa1da0cb4332661a31d21f57e954abNick Kossifidis * Set BSSID mask on 5212 405c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 406a72d57a862f700edf85da81aae3cd8f923e989a1Luis R. Rodriguez if (ah->ah_version == AR5K_AR5212) 407a72d57a862f700edf85da81aae3cd8f923e989a1Luis R. Rodriguez ath_hw_setbssidmask(common); 408c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 409c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* 410418de6d955fa1da0cb4332661a31d21f57e954abNick Kossifidis * Set BSSID 411c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 412abba06869e2546484fa142528737d1a0622add54Luis R. Rodriguez ath5k_hw_reg_write(ah, 413abba06869e2546484fa142528737d1a0622add54Luis R. Rodriguez get_unaligned_le32(common->curbssid), 414a3f86bff1c056f47c2df4c58bfcf7bdda8eaf9d0Luis R. Rodriguez AR5K_BSS_ID0); 415abba06869e2546484fa142528737d1a0622add54Luis R. Rodriguez ath5k_hw_reg_write(ah, 416abba06869e2546484fa142528737d1a0622add54Luis R. Rodriguez get_unaligned_le16(common->curbssid + 4) | 417abba06869e2546484fa142528737d1a0622add54Luis R. Rodriguez ((common->curaid & 0x3fff) << AR5K_BSS_ID1_AID_S), 418a3f86bff1c056f47c2df4c58bfcf7bdda8eaf9d0Luis R. Rodriguez AR5K_BSS_ID1); 419c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 420be5d6b75e0fb3f7e23ea5325109ef4195f2b282aLuis R. Rodriguez if (common->curaid == 0) { 421c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_disable_pspoll(ah); 422c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return; 423c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } 424c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 425c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis AR5K_REG_WRITE_BITS(ah, AR5K_BEACON, AR5K_BEACON_TIM, 426abba06869e2546484fa142528737d1a0622add54Luis R. Rodriguez tim_offset ? tim_offset + 4 : 0); 427c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 428c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_enable_pspoll(ah, NULL, 0); 429c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 430c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 431c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis/** 432c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_set_bssid_mask() - Filter out bssids we listen 433c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * @ah: The &struct ath5k_hw 434c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * @mask: The BSSID mask to set (array of octets) 435c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * 436c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * BSSID masking is a method used by AR5212 and newer hardware to inform PCU 437c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * which bits of the interface's MAC address should be looked at when trying 438c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * to decide which packets to ACK. In station mode and AP mode with a single 439c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * BSS every bit matters since we lock to only one BSS. In AP mode with 440c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * multiple BSSes (virtual interfaces) not every bit matters because hw must 441c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * accept frames for all BSSes and so we tweak some bits of our mac address 442c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * in order to have multiple BSSes. 443c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * 444c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * For more information check out ../hw.c of the common ath module. 445c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis */ 446c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisvoid 447c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_set_bssid_mask(struct ath5k_hw *ah, const u8 *mask) 448c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 449954fecea5d1df4d1dc7bf9a822a2fad308e8588eLuis R. Rodriguez struct ath_common *common = ath5k_hw_common(ah); 450c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 451f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis /* Cache bssid mask so that we can restore it 452f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis * on reset */ 453954fecea5d1df4d1dc7bf9a822a2fad308e8588eLuis R. Rodriguez memcpy(common->bssidmask, mask, ETH_ALEN); 45413b81559200b8e54473e5b140323cbb5f2bb21c0Luis R. Rodriguez if (ah->ah_version == AR5K_AR5212) 45513b81559200b8e54473e5b140323cbb5f2bb21c0Luis R. Rodriguez ath_hw_setbssidmask(common); 456c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 457c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 458c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis/** 459c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_set_mcast_filter() - Set multicast filter 460c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * @ah: The &struct ath5k_hw 461c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * @filter0: Lower 32bits of muticast filter 462c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * @filter1: Higher 16bits of multicast filter 463c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 464c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisvoid 465c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_set_mcast_filter(struct ath5k_hw *ah, u32 filter0, u32 filter1) 466c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 467c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_write(ah, filter0, AR5K_MCAST_FILTER0); 468c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_write(ah, filter1, AR5K_MCAST_FILTER1); 469c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 470c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 471c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/** 472c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_get_rx_filter() - Get current rx filter 473c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @ah: The &struct ath5k_hw 474c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 475c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Returns the RX filter by reading rx filter and 476c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * phy error filter registers. RX filter is used 477c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * to set the allowed frame types that PCU will accept 478c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * and pass to the driver. For a list of frame types 479c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * check out reg.h. 480c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 481c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisu32 482c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_get_rx_filter(struct ath5k_hw *ah) 483c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 484c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis u32 data, filter = 0; 485c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 486c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis filter = ath5k_hw_reg_read(ah, AR5K_RX_FILTER); 487c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 488c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /*Radar detection for 5212*/ 489c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (ah->ah_version == AR5K_AR5212) { 490c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis data = ath5k_hw_reg_read(ah, AR5K_PHY_ERR_FIL); 491c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 492c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (data & AR5K_PHY_ERR_FIL_RADAR) 493c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis filter |= AR5K_RX_FILTER_RADARERR; 494c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (data & (AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK)) 495c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis filter |= AR5K_RX_FILTER_PHYERR; 496c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } 497c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 498c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis return filter; 499c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 500c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 501c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/** 502c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_set_rx_filter() - Set rx filter 503c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @ah: The &struct ath5k_hw 504c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @filter: RX filter mask (see reg.h) 505c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 506c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Sets RX filter register and also handles PHY error filter 507c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * register on 5212 and newer chips so that we have proper PHY 508c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * error reporting. 509c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 510c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisvoid 511c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_set_rx_filter(struct ath5k_hw *ah, u32 filter) 512c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 513c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis u32 data = 0; 514c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 515c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* Set PHY error filter register on 5212*/ 516c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (ah->ah_version == AR5K_AR5212) { 517c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (filter & AR5K_RX_FILTER_RADARERR) 518c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis data |= AR5K_PHY_ERR_FIL_RADAR; 519c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (filter & AR5K_RX_FILTER_PHYERR) 520c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis data |= AR5K_PHY_ERR_FIL_OFDM | AR5K_PHY_ERR_FIL_CCK; 521c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } 522c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 523c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* 52425985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * The AR5210 uses promiscuous mode to detect radar activity 525c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 526c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (ah->ah_version == AR5K_AR5210 && 527c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis (filter & AR5K_RX_FILTER_RADARERR)) { 528c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis filter &= ~AR5K_RX_FILTER_RADARERR; 529c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis filter |= AR5K_RX_FILTER_PROM; 530c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } 531c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 532f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis /*Zero length DMA (phy error reporting) */ 533c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (data) 534c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis AR5K_REG_ENABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA); 535c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis else 536c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis AR5K_REG_DISABLE_BITS(ah, AR5K_RXCFG, AR5K_RXCFG_ZLFDMA); 537c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 538c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /*Write RX Filter register*/ 539c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_write(ah, filter & 0xff, AR5K_RX_FILTER); 540c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 541c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /*Write PHY error filter register on 5212*/ 542c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (ah->ah_version == AR5K_AR5212) 543c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_write(ah, data, AR5K_PHY_ERR_FIL); 544c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 545c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 546c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 547c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 548c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/****************\ 549c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis* Beacon control * 550c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis\****************/ 551c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 5521c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault#define ATH5K_MAX_TSF_READ 10 5531c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault 554c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/** 555c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_get_tsf64() - Get the full 64bit TSF 556c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @ah: The &struct ath5k_hw 557c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 558c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Returns the current TSF 559c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 560c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisu64 561c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_get_tsf64(struct ath5k_hw *ah) 562c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 5631c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault u32 tsf_lower, tsf_upper1, tsf_upper2; 5641c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault int i; 56528df897a42aa41d6318be5b9872c4bb5c8d8d7e3Bruno Randolf unsigned long flags; 56628df897a42aa41d6318be5b9872c4bb5c8d8d7e3Bruno Randolf 56728df897a42aa41d6318be5b9872c4bb5c8d8d7e3Bruno Randolf /* This code is time critical - we don't want to be interrupted here */ 56828df897a42aa41d6318be5b9872c4bb5c8d8d7e3Bruno Randolf local_irq_save(flags); 5691c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault 5701c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault /* 5711c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault * While reading TSF upper and then lower part, the clock is still 5721c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault * counting (or jumping in case of IBSS merge) so we might get 5731c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault * inconsistent values. To avoid this, we read the upper part again 5741c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault * and check it has not been changed. We make the hypothesis that a 5751c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault * maximum of 3 changes can happens in a row (we use 10 as a safe 5761c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault * value). 5771c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault * 5781c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault * Impact on performance is pretty small, since in most cases, only 5791c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault * 3 register reads are needed. 5801c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault */ 5811c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault 5821c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault tsf_upper1 = ath5k_hw_reg_read(ah, AR5K_TSF_U32); 5831c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault for (i = 0; i < ATH5K_MAX_TSF_READ; i++) { 5841c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault tsf_lower = ath5k_hw_reg_read(ah, AR5K_TSF_L32); 5851c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault tsf_upper2 = ath5k_hw_reg_read(ah, AR5K_TSF_U32); 5861c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault if (tsf_upper2 == tsf_upper1) 5871c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault break; 5881c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault tsf_upper1 = tsf_upper2; 5891c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault } 5901c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault 59128df897a42aa41d6318be5b9872c4bb5c8d8d7e3Bruno Randolf local_irq_restore(flags); 59228df897a42aa41d6318be5b9872c4bb5c8d8d7e3Bruno Randolf 593e4bbf2f541501dcde47ce687ffc6d238bd2f7813Pavel Roskin WARN_ON(i == ATH5K_MAX_TSF_READ); 5941c0fc65e6de4e941ff483df445e721d6edb1f84bBenoit Papillault 595fdd55d14b7d3a721e60fdc8be12ec0beb9cda8c6Pavel Roskin return ((u64)tsf_upper1 << 32) | tsf_lower; 596c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 597c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 598c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis#undef ATH5K_MAX_TSF_READ 599c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis 600c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis/** 601c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_set_tsf64() - Set a new 64bit TSF 6028cab7581dba90b0519e25784e08feb5dedde737fAlina Friedrichsen * @ah: The &struct ath5k_hw 6038cab7581dba90b0519e25784e08feb5dedde737fAlina Friedrichsen * @tsf64: The new 64bit TSF 6048cab7581dba90b0519e25784e08feb5dedde737fAlina Friedrichsen * 6058cab7581dba90b0519e25784e08feb5dedde737fAlina Friedrichsen * Sets the new TSF 6068cab7581dba90b0519e25784e08feb5dedde737fAlina Friedrichsen */ 607c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisvoid 608c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_set_tsf64(struct ath5k_hw *ah, u64 tsf64) 6098cab7581dba90b0519e25784e08feb5dedde737fAlina Friedrichsen{ 6108cab7581dba90b0519e25784e08feb5dedde737fAlina Friedrichsen ath5k_hw_reg_write(ah, tsf64 & 0xffffffff, AR5K_TSF_L32); 6110ad65bd7e1b38dd2c86da5f07dbfa35fe1f03099Alina Friedrichsen ath5k_hw_reg_write(ah, (tsf64 >> 32) & 0xffffffff, AR5K_TSF_U32); 6128cab7581dba90b0519e25784e08feb5dedde737fAlina Friedrichsen} 6138cab7581dba90b0519e25784e08feb5dedde737fAlina Friedrichsen 6148cab7581dba90b0519e25784e08feb5dedde737fAlina Friedrichsen/** 615c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_reset_tsf() - Force a TSF reset 616c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * @ah: The &struct ath5k_hw 617c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * 618c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Forces a TSF reset on PCU 619c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 620c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisvoid 621c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_reset_tsf(struct ath5k_hw *ah) 622c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 62314be9947ef9843102b67d315c7483de112b5b2d7Bob Copeland u32 val; 62414be9947ef9843102b67d315c7483de112b5b2d7Bob Copeland 62514be9947ef9843102b67d315c7483de112b5b2d7Bob Copeland val = ath5k_hw_reg_read(ah, AR5K_BEACON) | AR5K_BEACON_RESET_TSF; 62614be9947ef9843102b67d315c7483de112b5b2d7Bob Copeland 62714be9947ef9843102b67d315c7483de112b5b2d7Bob Copeland /* 62814be9947ef9843102b67d315c7483de112b5b2d7Bob Copeland * Each write to the RESET_TSF bit toggles a hardware internal 62914be9947ef9843102b67d315c7483de112b5b2d7Bob Copeland * signal to reset TSF, but if left high it will cause a TSF reset 63014be9947ef9843102b67d315c7483de112b5b2d7Bob Copeland * on the next chip reset as well. Thus we always write the value 63114be9947ef9843102b67d315c7483de112b5b2d7Bob Copeland * twice to clear the signal. 63214be9947ef9843102b67d315c7483de112b5b2d7Bob Copeland */ 63314be9947ef9843102b67d315c7483de112b5b2d7Bob Copeland ath5k_hw_reg_write(ah, val, AR5K_BEACON); 63414be9947ef9843102b67d315c7483de112b5b2d7Bob Copeland ath5k_hw_reg_write(ah, val, AR5K_BEACON); 635c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 636c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 637c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis/** 638c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_init_beacon_timers() - Initialize beacon timers 639c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * @ah: The &struct ath5k_hw 640c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * @next_beacon: Next TBTT 641c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * @interval: Current beacon interval 642c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * 643c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * This function is used to initialize beacon timers based on current 644c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * operation mode and settings. 645c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 646c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisvoid 647c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_init_beacon_timers(struct ath5k_hw *ah, u32 next_beacon, u32 interval) 648c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis{ 649c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis u32 timer1, timer2, timer3; 650c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 651c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* 652c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Set the additional timers by mode 653c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 654e0d687bd9df218ba3d97aac15919d30816d72dcbPavel Roskin switch (ah->opmode) { 655f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis case NL80211_IFTYPE_MONITOR: 65605c914fe330fa8e1cc67870dc0d3809dfd96c107Johannes Berg case NL80211_IFTYPE_STATION: 657f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis /* In STA mode timer1 is used as next wakeup 658f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis * timer and timer2 as next CFP duration start 659f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis * timer. Both in 1/8TUs. */ 660f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis /* TODO: PCF handling */ 661c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis if (ah->ah_version == AR5K_AR5210) { 662c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis timer1 = 0xffffffff; 663c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis timer2 = 0xffffffff; 664c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } else { 665c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis timer1 = 0x0000ffff; 666c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis timer2 = 0x0007ffff; 667c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } 668f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis /* Mark associated AP as PCF incapable for now */ 669f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PCF); 670c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis break; 671f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis case NL80211_IFTYPE_ADHOC: 672f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis AR5K_REG_ENABLE_BITS(ah, AR5K_TXCFG, AR5K_TXCFG_ADHOC_BCN_ATIM); 673c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis default: 674f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis /* On non-STA modes timer1 is used as next DMA 675f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis * beacon alert (DBA) timer and timer2 as next 676f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis * software beacon alert. Both in 1/8TUs. */ 677c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis timer1 = (next_beacon - AR5K_TUNE_DMA_BEACON_RESP) << 3; 678c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis timer2 = (next_beacon - AR5K_TUNE_SW_BEACON_RESP) << 3; 679f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis break; 680c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis } 681c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 682f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis /* Timer3 marks the end of our ATIM window 683f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis * a zero length window is not allowed because 684f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis * we 'll get no beacons */ 6854a79f2c517cce31c3b25aab0ec5078368b22c363Bruno Randolf timer3 = next_beacon + 1; 686c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 687c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis /* 688c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis * Set the beacon register and enable all timers. 689c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis */ 69035edf8aae8f903b154d658b9a7eed0d5c1a4a814Nick Kossifidis /* When in AP or Mesh Point mode zero timer0 to start TSF */ 691e0d687bd9df218ba3d97aac15919d30816d72dcbPavel Roskin if (ah->opmode == NL80211_IFTYPE_AP || 692e0d687bd9df218ba3d97aac15919d30816d72dcbPavel Roskin ah->opmode == NL80211_IFTYPE_MESH_POINT) 693f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis ath5k_hw_reg_write(ah, 0, AR5K_TIMER0); 694428cbd4ff4d0f2423f49e499f499f04a636cb152Nick Kossifidis 695428cbd4ff4d0f2423f49e499f499f04a636cb152Nick Kossifidis ath5k_hw_reg_write(ah, next_beacon, AR5K_TIMER0); 696c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_write(ah, timer1, AR5K_TIMER1); 697c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_write(ah, timer2, AR5K_TIMER2); 698c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_write(ah, timer3, AR5K_TIMER3); 699c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 700f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis /* Force a TSF reset if requested and enable beacons */ 701f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis if (interval & AR5K_BEACON_RESET_TSF) 702f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis ath5k_hw_reset_tsf(ah); 703f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis 704c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis ath5k_hw_reg_write(ah, interval & (AR5K_BEACON_PERIOD | 705f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis AR5K_BEACON_ENABLE), 706f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis AR5K_BEACON); 707f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis 708f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis /* Flush any pending BMISS interrupts on ISR by 709f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis * performing a clear-on-write operation on PISR 710f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis * register for the BMISS bit (writing a bit on 7116a2a0e738225fc9ec063f84b79f0adf5c0ed176cPavel Roskin * ISR toggles a reset for that bit and leaves 7126a2a0e738225fc9ec063f84b79f0adf5c0ed176cPavel Roskin * the remaining bits intact) */ 713f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis if (ah->ah_version == AR5K_AR5210) 714f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_ISR); 715f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis else 716f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis ath5k_hw_reg_write(ah, AR5K_ISR_BMISS, AR5K_PISR); 717f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis 7186a2a0e738225fc9ec063f84b79f0adf5c0ed176cPavel Roskin /* TODO: Set enhanced sleep registers on AR5212 719f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis * based on vif->bss_conf params, until then 720f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis * disable power save reporting.*/ 721f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, AR5K_STA_ID1_PWR_SV); 722f07a6c495e88ae0143e3c20b1ed666314197277fNick Kossifidis 723c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis} 724c6e387a214f4b2c4bd48020409e366c133385d98Nick Kossifidis 7256e08d228b6d8e93d7b25b3573c6da7da179c2ae1Lukáš Turek/** 726c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_check_timer_win() - Check if timer B is timer A + window 7277f896126017830b29cf501d246ee32b81e359acdBruno Randolf * @a: timer a (before b) 7287f896126017830b29cf501d246ee32b81e359acdBruno Randolf * @b: timer b (after a) 7297f896126017830b29cf501d246ee32b81e359acdBruno Randolf * @window: difference between a and b 7307f896126017830b29cf501d246ee32b81e359acdBruno Randolf * @intval: timers are increased by this interval 7317f896126017830b29cf501d246ee32b81e359acdBruno Randolf * 7327f896126017830b29cf501d246ee32b81e359acdBruno Randolf * This helper function checks if timer B is timer A + window and covers 7337f896126017830b29cf501d246ee32b81e359acdBruno Randolf * cases where timer A or B might have already been updated or wrapped 7347f896126017830b29cf501d246ee32b81e359acdBruno Randolf * around (Timers are 16 bit). 7357f896126017830b29cf501d246ee32b81e359acdBruno Randolf * 7367f896126017830b29cf501d246ee32b81e359acdBruno Randolf * Returns true if O.K. 7377f896126017830b29cf501d246ee32b81e359acdBruno Randolf */ 7387f896126017830b29cf501d246ee32b81e359acdBruno Randolfstatic inline bool 7397f896126017830b29cf501d246ee32b81e359acdBruno Randolfath5k_check_timer_win(int a, int b, int window, int intval) 7407f896126017830b29cf501d246ee32b81e359acdBruno Randolf{ 7417f896126017830b29cf501d246ee32b81e359acdBruno Randolf /* 7427f896126017830b29cf501d246ee32b81e359acdBruno Randolf * 1.) usually B should be A + window 7437f896126017830b29cf501d246ee32b81e359acdBruno Randolf * 2.) A already updated, B not updated yet 7447f896126017830b29cf501d246ee32b81e359acdBruno Randolf * 3.) A already updated and has wrapped around 7457f896126017830b29cf501d246ee32b81e359acdBruno Randolf * 4.) B has wrapped around 7467f896126017830b29cf501d246ee32b81e359acdBruno Randolf */ 7477f896126017830b29cf501d246ee32b81e359acdBruno Randolf if ((b - a == window) || /* 1.) */ 7487f896126017830b29cf501d246ee32b81e359acdBruno Randolf (a - b == intval - window) || /* 2.) */ 7497f896126017830b29cf501d246ee32b81e359acdBruno Randolf ((a | 0x10000) - b == intval - window) || /* 3.) */ 7507f896126017830b29cf501d246ee32b81e359acdBruno Randolf ((b | 0x10000) - a == window)) /* 4.) */ 7517f896126017830b29cf501d246ee32b81e359acdBruno Randolf return true; /* O.K. */ 7527f896126017830b29cf501d246ee32b81e359acdBruno Randolf return false; 7537f896126017830b29cf501d246ee32b81e359acdBruno Randolf} 7547f896126017830b29cf501d246ee32b81e359acdBruno Randolf 7557f896126017830b29cf501d246ee32b81e359acdBruno Randolf/** 756c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_check_beacon_timers() - Check if the beacon timers are correct 7577f896126017830b29cf501d246ee32b81e359acdBruno Randolf * @ah: The &struct ath5k_hw 7587f896126017830b29cf501d246ee32b81e359acdBruno Randolf * @intval: beacon interval 7597f896126017830b29cf501d246ee32b81e359acdBruno Randolf * 760c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * This is a workaround for IBSS mode 7617f896126017830b29cf501d246ee32b81e359acdBruno Randolf * 7627f896126017830b29cf501d246ee32b81e359acdBruno Randolf * The need for this function arises from the fact that we have 4 separate 7637f896126017830b29cf501d246ee32b81e359acdBruno Randolf * HW timer registers (TIMER0 - TIMER3), which are closely related to the 7647f896126017830b29cf501d246ee32b81e359acdBruno Randolf * next beacon target time (NBTT), and that the HW updates these timers 76525985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * separately based on the current TSF value. The hardware increments each 76625985edcedea6396277003854657b5f3cb31a628Lucas De Marchi * timer by the beacon interval, when the local TSF converted to TU is equal 7677f896126017830b29cf501d246ee32b81e359acdBruno Randolf * to the value stored in the timer. 7687f896126017830b29cf501d246ee32b81e359acdBruno Randolf * 7697f896126017830b29cf501d246ee32b81e359acdBruno Randolf * The reception of a beacon with the same BSSID can update the local HW TSF 7707f896126017830b29cf501d246ee32b81e359acdBruno Randolf * at any time - this is something we can't avoid. If the TSF jumps to a 7717f896126017830b29cf501d246ee32b81e359acdBruno Randolf * time which is later than the time stored in a timer, this timer will not 7727f896126017830b29cf501d246ee32b81e359acdBruno Randolf * be updated until the TSF in TU wraps around at 16 bit (the size of the 7737f896126017830b29cf501d246ee32b81e359acdBruno Randolf * timers) and reaches the time which is stored in the timer. 7747f896126017830b29cf501d246ee32b81e359acdBruno Randolf * 7757f896126017830b29cf501d246ee32b81e359acdBruno Randolf * The problem is that these timers are closely related to TIMER0 (NBTT) and 7767f896126017830b29cf501d246ee32b81e359acdBruno Randolf * that they define a time "window". When the TSF jumps between two timers 7777f896126017830b29cf501d246ee32b81e359acdBruno Randolf * (e.g. ATIM and NBTT), the one in the past will be left behind (not 7787f896126017830b29cf501d246ee32b81e359acdBruno Randolf * updated), while the one in the future will be updated every beacon 7797f896126017830b29cf501d246ee32b81e359acdBruno Randolf * interval. This causes the window to get larger, until the TSF wraps 7807f896126017830b29cf501d246ee32b81e359acdBruno Randolf * around as described above and the timer which was left behind gets 7817f896126017830b29cf501d246ee32b81e359acdBruno Randolf * updated again. But - because the beacon interval is usually not an exact 7827f896126017830b29cf501d246ee32b81e359acdBruno Randolf * divisor of the size of the timers (16 bit), an unwanted "window" between 7837f896126017830b29cf501d246ee32b81e359acdBruno Randolf * these timers has developed! 7847f896126017830b29cf501d246ee32b81e359acdBruno Randolf * 7857f896126017830b29cf501d246ee32b81e359acdBruno Randolf * This is especially important with the ATIM window, because during 7867f896126017830b29cf501d246ee32b81e359acdBruno Randolf * the ATIM window only ATIM frames and no data frames are allowed to be 7877f896126017830b29cf501d246ee32b81e359acdBruno Randolf * sent, which creates transmission pauses after each beacon. This symptom 7887f896126017830b29cf501d246ee32b81e359acdBruno Randolf * has been described as "ramping ping" because ping times increase linearly 7897f896126017830b29cf501d246ee32b81e359acdBruno Randolf * for some time and then drop down again. A wrong window on the DMA beacon 7907f896126017830b29cf501d246ee32b81e359acdBruno Randolf * timer has the same effect, so we check for these two conditions. 7917f896126017830b29cf501d246ee32b81e359acdBruno Randolf * 7927f896126017830b29cf501d246ee32b81e359acdBruno Randolf * Returns true if O.K. 7937f896126017830b29cf501d246ee32b81e359acdBruno Randolf */ 7947f896126017830b29cf501d246ee32b81e359acdBruno Randolfbool 7957f896126017830b29cf501d246ee32b81e359acdBruno Randolfath5k_hw_check_beacon_timers(struct ath5k_hw *ah, int intval) 7967f896126017830b29cf501d246ee32b81e359acdBruno Randolf{ 7977f896126017830b29cf501d246ee32b81e359acdBruno Randolf unsigned int nbtt, atim, dma; 7987f896126017830b29cf501d246ee32b81e359acdBruno Randolf 7997f896126017830b29cf501d246ee32b81e359acdBruno Randolf nbtt = ath5k_hw_reg_read(ah, AR5K_TIMER0); 8007f896126017830b29cf501d246ee32b81e359acdBruno Randolf atim = ath5k_hw_reg_read(ah, AR5K_TIMER3); 8017f896126017830b29cf501d246ee32b81e359acdBruno Randolf dma = ath5k_hw_reg_read(ah, AR5K_TIMER1) >> 3; 8027f896126017830b29cf501d246ee32b81e359acdBruno Randolf 8037f896126017830b29cf501d246ee32b81e359acdBruno Randolf /* NOTE: SWBA is different. Having a wrong window there does not 8046a2a0e738225fc9ec063f84b79f0adf5c0ed176cPavel Roskin * stop us from sending data and this condition is caught by 8057f896126017830b29cf501d246ee32b81e359acdBruno Randolf * other means (SWBA interrupt) */ 8067f896126017830b29cf501d246ee32b81e359acdBruno Randolf 8077f896126017830b29cf501d246ee32b81e359acdBruno Randolf if (ath5k_check_timer_win(nbtt, atim, 1, intval) && 8087f896126017830b29cf501d246ee32b81e359acdBruno Randolf ath5k_check_timer_win(dma, nbtt, AR5K_TUNE_DMA_BEACON_RESP, 8097f896126017830b29cf501d246ee32b81e359acdBruno Randolf intval)) 8107f896126017830b29cf501d246ee32b81e359acdBruno Randolf return true; /* O.K. */ 8117f896126017830b29cf501d246ee32b81e359acdBruno Randolf return false; 8127f896126017830b29cf501d246ee32b81e359acdBruno Randolf} 8137f896126017830b29cf501d246ee32b81e359acdBruno Randolf 8147f896126017830b29cf501d246ee32b81e359acdBruno Randolf/** 815c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_set_coverage_class() - Set IEEE 802.11 coverage class 8166e08d228b6d8e93d7b25b3573c6da7da179c2ae1Lukáš Turek * @ah: The &struct ath5k_hw 8176e08d228b6d8e93d7b25b3573c6da7da179c2ae1Lukáš Turek * @coverage_class: IEEE 802.11 coverage class number 8186e08d228b6d8e93d7b25b3573c6da7da179c2ae1Lukáš Turek * 819eeb8832b3181d6ca8593051b68c466e5d2653bb3Nick Kossifidis * Sets IFS intervals and ACK/CTS timeouts for given coverage class. 8206e08d228b6d8e93d7b25b3573c6da7da179c2ae1Lukáš Turek */ 821c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisvoid 822c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_set_coverage_class(struct ath5k_hw *ah, u8 coverage_class) 8236e08d228b6d8e93d7b25b3573c6da7da179c2ae1Lukáš Turek{ 8246e08d228b6d8e93d7b25b3573c6da7da179c2ae1Lukáš Turek /* As defined by IEEE 802.11-2007 17.3.8.6 */ 8256e08d228b6d8e93d7b25b3573c6da7da179c2ae1Lukáš Turek int slot_time = ath5k_hw_get_default_slottime(ah) + 3 * coverage_class; 8266e08d228b6d8e93d7b25b3573c6da7da179c2ae1Lukáš Turek int ack_timeout = ath5k_hw_get_default_sifs(ah) + slot_time; 8276e08d228b6d8e93d7b25b3573c6da7da179c2ae1Lukáš Turek int cts_timeout = ack_timeout; 8286e08d228b6d8e93d7b25b3573c6da7da179c2ae1Lukáš Turek 829eeb8832b3181d6ca8593051b68c466e5d2653bb3Nick Kossifidis ath5k_hw_set_ifs_intervals(ah, slot_time); 8306e08d228b6d8e93d7b25b3573c6da7da179c2ae1Lukáš Turek ath5k_hw_set_ack_timeout(ah, ack_timeout); 8316e08d228b6d8e93d7b25b3573c6da7da179c2ae1Lukáš Turek ath5k_hw_set_cts_timeout(ah, cts_timeout); 8326e08d228b6d8e93d7b25b3573c6da7da179c2ae1Lukáš Turek 8336e08d228b6d8e93d7b25b3573c6da7da179c2ae1Lukáš Turek ah->ah_coverage_class = coverage_class; 8346e08d228b6d8e93d7b25b3573c6da7da179c2ae1Lukáš Turek} 8359320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 8369320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis/***************************\ 8379320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis* Init/Start/Stop functions * 8389320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis\***************************/ 8399320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 8409320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis/** 841c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_start_rx_pcu() - Start RX engine 8429320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * @ah: The &struct ath5k_hw 8439320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * 8449320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * Starts RX engine on PCU so that hw can process RXed frames 8459320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * (ACK etc). 8469320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * 8479320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * NOTE: RX DMA should be already enabled using ath5k_hw_start_rx_dma 8489320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis */ 849c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisvoid 850c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_start_rx_pcu(struct ath5k_hw *ah) 8519320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis{ 8529320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis AR5K_REG_DISABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); 8539320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis} 8549320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 8559320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis/** 856c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * at5k_hw_stop_rx_pcu() - Stop RX engine 8579320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * @ah: The &struct ath5k_hw 8589320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * 8599320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * Stops RX engine on PCU 8609320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis */ 861c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisvoid 862c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_stop_rx_pcu(struct ath5k_hw *ah) 8639320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis{ 8649320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis AR5K_REG_ENABLE_BITS(ah, AR5K_DIAG_SW, AR5K_DIAG_SW_DIS_RX); 8659320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis} 8669320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 8679320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis/** 868c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_set_opmode() - Set PCU operating mode 8699320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * @ah: The &struct ath5k_hw 870c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * @op_mode: One of enum nl80211_iftype 8719320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * 8729320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * Configure PCU for the various operating modes (AP/STA etc) 8739320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis */ 874c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisint 875c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_set_opmode(struct ath5k_hw *ah, enum nl80211_iftype op_mode) 8769320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis{ 8779320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis struct ath_common *common = ath5k_hw_common(ah); 8789320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis u32 pcu_reg, beacon_reg, low_id, high_id; 8799320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 880e0d687bd9df218ba3d97aac15919d30816d72dcbPavel Roskin ATH5K_DBG(ah, ATH5K_DEBUG_MODE, "mode %d\n", op_mode); 8819320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 8829320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis /* Preserve rest settings */ 8839320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis pcu_reg = ath5k_hw_reg_read(ah, AR5K_STA_ID1) & 0xffff0000; 8849320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis pcu_reg &= ~(AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_AP 8859320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis | AR5K_STA_ID1_KEYSRCH_MODE 8869320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis | (ah->ah_version == AR5K_AR5210 ? 8879320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis (AR5K_STA_ID1_PWR_SV | AR5K_STA_ID1_NO_PSPOLL) : 0)); 8889320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 8899320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis beacon_reg = 0; 8909320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 8919320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis switch (op_mode) { 8929320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis case NL80211_IFTYPE_ADHOC: 8939320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis pcu_reg |= AR5K_STA_ID1_ADHOC | AR5K_STA_ID1_KEYSRCH_MODE; 8949320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis beacon_reg |= AR5K_BCR_ADHOC; 8959320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis if (ah->ah_version == AR5K_AR5210) 8969320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; 8979320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis else 8989320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis AR5K_REG_ENABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); 8999320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis break; 9009320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 9019320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis case NL80211_IFTYPE_AP: 9029320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis case NL80211_IFTYPE_MESH_POINT: 9039320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis pcu_reg |= AR5K_STA_ID1_AP | AR5K_STA_ID1_KEYSRCH_MODE; 9049320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis beacon_reg |= AR5K_BCR_AP; 9059320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis if (ah->ah_version == AR5K_AR5210) 9069320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis pcu_reg |= AR5K_STA_ID1_NO_PSPOLL; 9079320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis else 9089320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis AR5K_REG_DISABLE_BITS(ah, AR5K_CFG, AR5K_CFG_IBSS); 9099320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis break; 9109320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 9119320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis case NL80211_IFTYPE_STATION: 9129320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE 9139320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis | (ah->ah_version == AR5K_AR5210 ? 9149320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis AR5K_STA_ID1_PWR_SV : 0); 9159320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis case NL80211_IFTYPE_MONITOR: 9169320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis pcu_reg |= AR5K_STA_ID1_KEYSRCH_MODE 9179320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis | (ah->ah_version == AR5K_AR5210 ? 9189320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis AR5K_STA_ID1_NO_PSPOLL : 0); 9199320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis break; 9209320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 9219320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis default: 9229320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis return -EINVAL; 9239320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis } 9249320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 9259320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis /* 9269320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * Set PCU registers 9279320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis */ 9289320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis low_id = get_unaligned_le32(common->macaddr); 9299320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis high_id = get_unaligned_le16(common->macaddr + 4); 9309320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis ath5k_hw_reg_write(ah, low_id, AR5K_STA_ID0); 9319320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis ath5k_hw_reg_write(ah, pcu_reg | high_id, AR5K_STA_ID1); 9329320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 9339320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis /* 9349320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * Set Beacon Control Register on 5210 9359320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis */ 9369320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis if (ah->ah_version == AR5K_AR5210) 9379320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis ath5k_hw_reg_write(ah, beacon_reg, AR5K_BCR); 9389320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 9399320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis return 0; 9409320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis} 9419320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 942c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis/** 943c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * ath5k_hw_pcu_init() - Initialize PCU 944c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * @ah: The &struct ath5k_hw 945c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * @op_mode: One of enum nl80211_iftype 946c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * @mode: One of enum ath5k_driver_mode 947c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * 948c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * This function is used to initialize PCU by setting current 949c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis * operation mode and various other settings. 950c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidis */ 951c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisvoid 952c47faa364cfb249d5d7670fb7293a6f9acd8aa9eNick Kossifidisath5k_hw_pcu_init(struct ath5k_hw *ah, enum nl80211_iftype op_mode) 9539320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis{ 9549320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis /* Set bssid and bssid mask */ 9559320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis ath5k_hw_set_bssid(ah); 9569320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 9579320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis /* Set PCU config */ 9589320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis ath5k_hw_set_opmode(ah, op_mode); 9599320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 9609320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis /* Write rate duration table only on AR5212 and if 9619320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * virtual interface has already been brought up 9629320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * XXX: rethink this after new mode changes to 9639320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * mac80211 are integrated */ 9649320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis if (ah->ah_version == AR5K_AR5212 && 965e0d687bd9df218ba3d97aac15919d30816d72dcbPavel Roskin ah->nvifs) 96661cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis ath5k_hw_write_rate_duration(ah); 9679320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 9689320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis /* Set RSSI/BRSSI thresholds 9699320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * 9709320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * Note: If we decide to set this value 9716a2a0e738225fc9ec063f84b79f0adf5c0ed176cPavel Roskin * dynamically, have in mind that when AR5K_RSSI_THR 9729320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * register is read it might return 0x40 if we haven't 9739320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * wrote anything to it plus BMISS RSSI threshold is zeroed. 9749320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * So doing a save/restore procedure here isn't the right 9759320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis * choice. Instead store it on ath5k_hw */ 9769320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis ath5k_hw_reg_write(ah, (AR5K_TUNE_RSSI_THRES | 9779320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis AR5K_TUNE_BMISS_THRES << 9789320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis AR5K_RSSI_THR_BMISS_S), 9799320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis AR5K_RSSI_THR); 9809320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 9819320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis /* MIC QoS support */ 9829320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis if (ah->ah_mac_srev >= AR5K_SREV_AR2413) { 9839320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis ath5k_hw_reg_write(ah, 0x000100aa, AR5K_MIC_QOS_CTL); 9849320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis ath5k_hw_reg_write(ah, 0x00003210, AR5K_MIC_QOS_SEL); 9859320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis } 9869320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 9879320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis /* QoS NOACK Policy */ 9889320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis if (ah->ah_version == AR5K_AR5212) { 9899320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis ath5k_hw_reg_write(ah, 9909320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis AR5K_REG_SM(2, AR5K_QOS_NOACK_2BIT_VALUES) | 9919320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis AR5K_REG_SM(5, AR5K_QOS_NOACK_BIT_OFFSET) | 9929320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis AR5K_REG_SM(0, AR5K_QOS_NOACK_BYTE_OFFSET), 9939320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis AR5K_QOS_NOACK); 9949320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis } 9959320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 9969320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis /* Restore slot time and ACK timeouts */ 9979320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis if (ah->ah_coverage_class > 0) 9989320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis ath5k_hw_set_coverage_class(ah, ah->ah_coverage_class); 9999320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis 100061cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis /* Set ACK bitrate mode (see ack_rates_high) */ 100161cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis if (ah->ah_version == AR5K_AR5212) { 100261cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis u32 val = AR5K_STA_ID1_BASE_RATE_11B | AR5K_STA_ID1_ACKCTS_6MB; 100361cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis if (ah->ah_ack_bitrate_high) 100461cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis AR5K_REG_DISABLE_BITS(ah, AR5K_STA_ID1, val); 100561cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis else 100661cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis AR5K_REG_ENABLE_BITS(ah, AR5K_STA_ID1, val); 100761cde037234c4b8e6497a23f5f236c64cbf9d41dNick Kossifidis } 10089320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis return; 10099320b5c4a7260d9593102f378201d17e3f030739Nick Kossifidis} 1010